#include "dadrag.h" /*************************************** * CDADrag ***************************************/ STDMETHODIMP_(ULONG) CDADrag::AddRef() { return InterlockedIncrement(&_cRefs); } STDMETHODIMP_(ULONG) CDADrag::Release() { ULONG refCount = InterlockedDecrement(&_cRefs); if (!refCount) { delete this; return refCount; } return _cRefs; } STDMETHODIMP CDADrag::Cleanup() { _pickEv->Release(); _releaseEv->Release(); _draggableGeo->Release(); _draggablePt->Release(); _releaseHdlr->Release(); _e->Release(); return S_OK; } STDMETHODIMP CDADrag::QueryInterface(REFIID riid, void **ppv) { if (!ppv) return E_POINTER; *ppv = NULL; if (riid == IID_IUnknown) { *ppv = (void *)(IUnknown *)this; } else if (riid == IID_IDABvrHook) { *ppv = (void *)(IDAUntilNotifier *)this; } if (*ppv) { ((IUnknown *)*ppv)->AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP CDADrag::initNotify(IDAGeometryPtr geo, CDARelease *releaseHdlr, IDAPoint3Ptr pt, IDAStaticsPtr e) { _e = e; IDAPickableResultPtr pgeo = geo->Pickable(); _pickEv = _e->AndEvent(e->LeftButtonDown, pgeo->PickEvent); // construct a handler for release events, // upon pick events it passes the puck back to this object. _releaseHdlr = releaseHdlr; _releaseHdlr->AddRef(); _releaseHdlr->initNotify(_pickEv, this, e); _draggablePt = (IDAPoint3Ptr)_e->UntilNotify(pt, _pickEv, this)->RunOnce(); _releaseEv = _e->LeftButtonUp->Snapshot(_draggablePt); _draggableGeo = pgeo->Geometry->Transform(_e->Translate3Point(_draggablePt)); return S_OK; } STDMETHODIMP CDADrag::raw_Notify(IDABehavior* eventData, IDABehavior* curRunningBvr, IDAView* curView, IDABehavior** ppBvr) { IDAPoint3Ptr currPt = (IDAPoint3Ptr)curRunningBvr; // pull apart the pair that comes from andEvent and from the // pick event pair, ultimately to get at the local mouse IDAPairPtr andEventPair = (IDAPairPtr)eventData; IDAPairPtr pickPair = (IDAPairPtr)(andEventPair->Second); IDAVector3Ptr localMouse = (IDAVector3Ptr)(pickPair->Second); IDAPoint3Ptr draggingPt = currPt->Transform(_e->Translate3Vector(localMouse)); IDAPoint3Ptr finalPt = (IDAPoint3Ptr)_e->UntilNotify(draggingPt, _releaseEv, _releaseHdlr); *ppBvr = (IDABehavior*)finalPt; finalPt->AddRef(); return S_OK; } /*************************************** * CDARelease ***************************************/ STDMETHODIMP_(ULONG) CDARelease::AddRef() { return InterlockedIncrement(&_cRefs); } STDMETHODIMP_(ULONG) CDARelease::Release() { ULONG refCount = InterlockedDecrement(&_cRefs); if (!refCount) { delete this; return refCount; } return _cRefs; } STDMETHODIMP CDARelease::Cleanup() { _pickEv->Release(); _e->Release(); _grabHdlr->Release(); return S_OK; } STDMETHODIMP CDARelease::QueryInterface(REFIID riid, void **ppv) { if (!ppv) return E_POINTER; *ppv = NULL; if (riid == IID_IUnknown) { *ppv = (void *)(IUnknown *)this; } else if (riid == IID_IDABvrHook) { *ppv = (void *)(IDAUntilNotifier *)this; } if (*ppv) { ((IUnknown *)*ppv)->AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP CDARelease::initNotify(IDAEventPtr pickEv, CDADrag* grabHdlr, IDAStaticsPtr e) { _e = e; _pickEv = pickEv; _grabHdlr = grabHdlr; _grabHdlr->AddRef(); return S_OK; } STDMETHODIMP CDARelease::raw_Notify(IDABehavior* eventData, IDABehavior* curRunningBvr, IDAView* curView, IDABehavior** ppBvr) { // Releasing. Freeze the image where it is, and go // back to waiting for a pick event. IDAPoint3Ptr snappedPt = (IDAPoint3Ptr)eventData; IDAPoint3Ptr releasePt = (IDAPoint3Ptr)_e->UntilNotify(snappedPt, _pickEv, _grabHdlr); *ppBvr = (IDABehavior*)releasePt; releasePt->AddRef(); //Increment ref for return return S_OK; }