// RcMouseToolExample.cpp : Implementation of CRcMouseToolExample

#include "stdafx.h"
#include "RcMouseToolExample.h"
#include "RpExamplesPlugin.h"

STDMETHODIMP CRcMouseToolExample::OnGetValue(CONID conID, IRsDataCache* pDataCache, VARIANT* pVtData, RtBool* pHandled)
{
    return S_OK;
}

STDMETHODIMP CRcMouseToolExample::OnSetValue(CONID conID, IRsDataCache* pDataCache, VARIANT* pvtData, RtBool* pHandled)
{
	return S_OK;
}

STDMETHODIMP CRcMouseToolExample::OnDefaultValue(CONID conID, VARIANT* pVtData, RtBool* pHandled)
{
    return S_OK;
}

STDMETHODIMP CRcMouseToolExample::OnInvalidate(CONID conID, RtBool* pHandled)
{
    return S_OK;
}
STDMETHODIMP CRcMouseToolExample::OnInitialize(void)
{
    return S_OK;
}



STDMETHODIMP CRcMouseToolExample::OnLoadDefault(void)
{
    return S_OK;
}

STDMETHODIMP CRcMouseToolExample::OnDestroy(void)
{
    m_spCameraNode.Release();
    return S_OK;
}

HRESULT CRcMouseToolExample::FinalConstruct()
{
    CComPtr<IRpKernel> spKernelPackage;
	HRESULT hr = CRpExamplesPlugin::GetKernelPackage(&spKernelPackage);
    if (FAILED(hr))
        return hr;
    
    return spKernelPackage->CreateBaseNode(GetControllingUnknown(), &m_pUnkAgg);
}

STDMETHODIMP CRcMouseToolExample::Execute(void)
{
	//tool finished. Execute is called to prepare create undo/redo information for our tool command
	//this example does not implement undo redo so we do nothing here.
    return S_OK;
}

STDMETHODIMP CRcMouseToolExample::Undo(void)
{
	//command does not implement undo or redo	
    return S_OK;
}

STDMETHODIMP CRcMouseToolExample::Redo(void)
{
	//command does not implement undo or redo
    return S_OK;
}

STDMETHODIMP CRcMouseToolExample::HasUndo(RtBool* isUndoable)
{
    *isUndoable = false;
    return S_OK;
}

STDMETHODIMP CRcMouseToolExample::OnPress(RtMouseEvent* pEvent, IRsNode* pViewNode)
{
    m_spCameraNode.Release();
	
	// get active camera node
	CComPtr<IRpView3D> spView3DPck;
	CRpExamplesPlugin::FindPackage(DEF_GUIDNAME_PTR(CRpView3D), &spView3DPck);
	if (!spView3DPck) {
		return E_FAIL;
	};
	
	//create view helper
	CComPtr<IRsViewHelper> spViewHelper;
	spView3DPck->CreateViewHelper(&spViewHelper);

	//for view3d window get it's active camera node
    spViewHelper->GetActiveCamera(pViewNode, &m_spCameraNode);
	
	if (!m_spCameraNode)
        return E_FAIL;

    m_yStartPos = pEvent->yPos;
    
    
    //save old FOV value for FOV calculations
    m_spCameraNode->GetValue(CON_SPACE3D_CAMERA_FOV, &m_vOldFov);
    m_vOldFov.ChangeType(VT_R4);
   
    return S_OK;
}

STDMETHODIMP CRcMouseToolExample::OnDrag(RtMouseEvent* pEvent)
{
	//handle dragging

	if (!m_spCameraNode)
		return E_FAIL;

	RtLong delta = m_yStartPos - pEvent->yPos;
    RtFloat fFov = delta * -0.001f + m_vOldFov.fltVal;

    if (fFov < 1e-3f)
        fFov = 1e-3f;

    if (fFov > 3.1415f)
        fFov = 3.1415f;

    CComVariant varFov(fFov);
      
    m_spCameraNode->SetValue(CON_SPACE3D_CAMERA_FOV, varFov);
//		m_spCameraNode->SetValue(CON_VIEW3D_FOV, varFov); 
       
    return S_OK;
}

STDMETHODIMP CRcMouseToolExample::OnRelease(RtMouseEvent* pEvent)
{
   //do nothing on release as fov is already set.
	//we return S_OK to finish press-drag-release sequence
    return S_OK;
}



STDMETHODIMP CRcMouseToolExample::GetToolPriority(RtMouseEvent *pMouseEvent,IRsNode *pViewNode,RtUlong *pPriority)
{
	//we only request left/right clicks and mouse move events
	if (pMouseEvent->eventType == MET_LBUTTON_DOWN || 
		pMouseEvent->eventType == MET_RBUTTON_DOWN ||
		pMouseEvent->eventType == MET_MOVE) {
			*pPriority = 1;
			return S_OK;
	};

	//for other events, select next tool (clicks, wheel, etc)
	*pPriority = TOOLMNG_TOOLPRIORITY_INACTIVE;
	return S_OK;
}
STDMETHODIMP CRcMouseToolExample::OnToolRemove()
{
	//tool is removed from tool manager. If you don't want your tool to be removed, return S_FALSE
	return S_OK;
}
STDMETHODIMP CRcMouseToolExample::OnFocus()
{
	//notification by tool manager that focus has been regained
	return S_OK;
}
STDMETHODIMP CRcMouseToolExample::OnFocusLost()
{
	//notification by tool manager that focus has been lost (when new tool is activated etc)
	return S_OK;
}
STDMETHODIMP CRcMouseToolExample::IsToolLocked(RtBool *pbLocked)
{
	return E_NOTIMPL;
}
STDMETHODIMP CRcMouseToolExample::ProcessMouseEvent(RtMouseEvent *pEvent,IRsNode *pViewNode)
{
	//handle more complex mouse events processing here. 
	return S_OK;
}
