// RcCreateProcClip.cpp : Implementation of CRcCreateProcClip

#include "stdafx.h"
#include "RpAnimPluginPackage.h"
#include "RcCreateProcClip.h"
#include "RaClip.h"
#include "RsSelectionHelper.h"   //selections support


// CRcCreateProcClip

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

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

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

STDMETHODIMP CRcCreateProcClip::OnInvalidate(CONID con_id, RtBool* pHandled)
{
    return S_OK;
}

STDMETHODIMP CRcCreateProcClip::OnInitialize(void)
{
    return S_OK;
}

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

STDMETHODIMP CRcCreateProcClip::OnDestroy(void)
{
    return S_OK;
}

// create aggregated Space3dObject (Space3dObject agregates BaseNode)
HRESULT CRcCreateProcClip::FinalConstruct()
{
    CComPtr<IRpKernel> spKernelPackage;
    HRESULT hr = CRpAnimPlugin::GetKernelPackage(&spKernelPackage);
    if (FAILED(hr))
        return hr;
    
    return spKernelPackage->CreateBaseNode(GetControllingUnknown(), &m_spUnkAgg);
}


STDMETHODIMP CRcCreateProcClip::Execute(void)
{
    CComQIPtr<IRsBaseNode> spBase = m_spUnkAgg;   // Get the BaseNode interface
    ATLASSERT(spBase);

	HRESULT hRes;
	CComPtr<IRsNode>	spClipNode;
	if(FAILED(hRes = GetClipObject(&spClipNode)))
		return hRes;

	CComQIPtr<IRnAnimClip>	spAnimClip = spClipNode;
	if(spAnimClip)
	{
		// get owner of clip node
		CComPtr<IRsNode>	spOwnerNode;
		spClipNode->GetOwner(&spOwnerNode);
		CComQIPtr<IRnEncapsulator>	spOwnerSpace = spOwnerNode;
		
		// create procedural clip activity node, and add it to clip owner
		CComPtr<IRsNode>	spProcClip;
		if(FAILED(hRes = AddProceduralClip(spOwnerSpace, &spProcClip)))
			return hRes;

		// connect to original kf data
		CComQIPtr<IRsBaseNode>	spClipBase = spClipNode;
		CComQIPtr<IRsBaseNode>	spClipProcBase = spProcClip;

		if(spClipBase && spClipProcBase)
			hRes = spClipBase->ConnectToConnector(CON_ANIMDATA, spClipProcBase, CON_KFANIMDATA);
	}
	else
	{
		// if clip node is not specified, put proc clip activity node inside the selected encapsulator
		CComQIPtr<IRnEncapsulator>	spEncaps = spClipNode;

		if(spEncaps)
		{
			CComPtr<IRsNode>	spProcClip;
			AddProceduralClip(spEncaps, &spProcClip);
		}

	}
    
    return hRes;
}

STDMETHODIMP CRcCreateProcClip::Undo(void)
{
    return S_OK;
}

STDMETHODIMP CRcCreateProcClip::Redo(void)
{
    return S_OK;
}

STDMETHODIMP CRcCreateProcClip::HasUndo(RtBool* isUndoable)
{
    *isUndoable = static_cast<RtBool>(false);
    return S_OK;
}



HRESULT CRcCreateProcClip::GetClipObject(IRsNode** ppAnimClipNode)
{
	HRESULT hRes;
	CComQIPtr<IRsBaseNode> spBase = m_spUnkAgg; 

	CComVariant vData;
	spBase->GetValue(CON_ANIMCMD_CLIPNAME, &vData);
	
	CComBSTR bszObjectName;
	if(vData.vt == VT_BSTR)
		bszObjectName = V_BSTR(&vData);

    if (bszObjectName.Length() < 1)   
    {
		// Default selection:
		RsSelectionHelper::GetFirstSelectedNodeName<CRpAnimPlugin>(&bszObjectName);
	}
 
	// verify if selected object is clip node in the object contraint graph
	CComPtr<IRnKernel>    spKernel;
    if(FAILED(hRes = CRpAnimPlugin::GetKernelNode(&spKernel)))
		return hRes;
    CComQIPtr<IRnEncapsulator> spKernelRoot = spKernel;
	
	if(!bszObjectName)
		return E_INVALIDARG;

	CComPtr<IRsNode>	spNode;
    hRes = spKernelRoot->FindNodeByName(bszObjectName, &spNode);
    if (hRes != S_OK)
        return hRes;

	return spNode.CopyTo(ppAnimClipNode);
}

HRESULT CRcCreateProcClip::AddProceduralClip(IRnEncapsulator *pOwner, IRsNode** ppClipProc)
{
	HRESULT hRes;
	CComPtr<IRsNode>	spClipProc;
	if(FAILED(hRes = CRpAnimPlugin::CreateCmdObj(DEF_GUIDNAME_PTR(IRaClip), &spClipProc)))
		return hRes;

	if(FAILED(hRes = pOwner->AddSubObject(spClipProc)))
		return hRes;
	
	return spClipProc.CopyTo(ppClipProc);
}




