#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::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, 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 = new CDARelease();
_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::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;
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();
return S_OK;
}