// RcUpdate3DLoader.cpp : Implementation of CRcUpdate3DLoader
// This command is created by Rn3DLoader node object to update itself.
// The purpose is to get some CPU time to access the Dependency Graph.
//
// RcUpdate3DLoader could be used by more than just one node, therefore
// we need to specify which node should be updated. The identification
// is stored in CON_CMD_3DLOADERUPDCMD_NODE_ID connector.

#include "stdafx.h"
#include "RcUpdate3DLoader.h"
#include "Rn3DLoader.h"


// CRcUpdate3DLoader

// OnGetValue - method is called when a connector's value is required. Due to fact this
// command will not be put into Dependency Graph (as activity node), we don't need to
// react on it. Similarly it is with OnSetValue, OnDefaultValue and OnInvalidate that
// treats the connectors' events of this command
STDMETHODIMP CRcUpdate3DLoader::OnGetValue(CONID conID, IRsDataCache* pDataCache, VARIANT* pVtData, RtBool* pHandled)
{
	return S_OK;
}

// Called when a connector value was set
STDMETHODIMP CRcUpdate3DLoader::OnSetValue(CONID con_id, IRsDataCache* pDataCache, VARIANT* pvtData, RtBool* pHandled)
{
	return S_OK;
}

// Called to initialize a connector's value
STDMETHODIMP CRcUpdate3DLoader::OnDefaultValue(CONID con_id, VARIANT* pVtData, RtBool* pHandled)
{
	return S_OK;
}

// Called when a connector was invalidated
STDMETHODIMP CRcUpdate3DLoader::OnInvalidate(CONID con_id, RtBool* pHandled)
{
	return S_OK;
}

// Called when this command was created
STDMETHODIMP CRcUpdate3DLoader::OnInitialize(void)
{
	return S_OK;
}

// When the command is created, add commands attributes. In this case there it is only
// one attribute that identify which one 3DLoader objects should be updated
STDMETHODIMP CRcUpdate3DLoader::OnLoadDefault(void)
{
    RtConDesc sNodeId = {&CON_CMD_3DLOADERUPDCMD_NODE_ID, L"NodeId", L"3DLoader node ID", VT_BSTR, NULL, CONFLG_IN};

    CComQIPtr<IRsBaseNode> spBase = m_spUnkAgg;
    if (spBase == NULL)       // This fail can occurs when the node is already destroyed and you
        return E_UNEXPECTED;  // are trying to access it. Usually it is during system shutdown.

    spBase->AddNewConnector(&sNodeId, NULL);

    return S_OK;
}

// Called when this command is to be destroyed
STDMETHODIMP CRcUpdate3DLoader::OnDestroy(void)
{
	return S_OK;
}

HRESULT CRcUpdate3DLoader::FinalConstruct()
{
	// kernel package
	CComPtr<IRpKernel> spKernelPck;
	HRESULT hRes = CRp3DLoader::GetKernelPackage(&spKernelPck);
	
	// create base node
	if (SUCCEEDED(hRes))
		hRes = spKernelPck->CreateBaseNode(GetControllingUnknown(), &m_spUnkAgg);

	return hRes;
}

// Called to execute this command. We read the command's parameter, find the
// 3DLoader node object in Dependency Graph and then call its update
// method
STDMETHODIMP CRcUpdate3DLoader::Execute(void)
{
    // Read the command's attribute (parameter)
    CComQIPtr<IRsBaseNode> spBase = m_spUnkAgg;
    if (spBase == NULL)       // This fail can occurs when the node is already destroyed and you
        return E_UNEXPECTED;  // are trying to access it. Usually it is during system shutdown.

    // We are expecting a string Id of the node
    CComVariant vNodeId;
    spBase->GetValue(CON_CMD_3DLOADERUPDCMD_NODE_ID, &vNodeId);
    if (FAILED(vNodeId.ChangeType(VT_BSTR)))
        return S_FALSE;

    // Try to find the node in graph
    CComPtr<IRpKernel> spKernelPckg;
    CRp3DLoader::GetKernelPackage(&spKernelPckg);
    if (spKernelPckg == NULL)
        return E_UNEXPECTED;

    CComQIPtr<IRnKernel> spKernel;
    spKernelPckg->GetKernelNode(&spKernel);
    CComQIPtr<IRnEncapsulator> spKernelEnc = spKernel;
    if (spKernelEnc == NULL)
        return S_FALSE;

    CComPtr<IRsNode> sp3DLoaderNode;
    spKernelEnc->FindNodeByName(vNodeId.bstrVal, &sp3DLoaderNode);
    CComQIPtr<IRn3DLoader> sp3DLoader = sp3DLoaderNode;
    if (sp3DLoader == NULL)
        return S_FALSE;     // This may happen if you e.g. delete the node and this command was already sent

    // If the node was found, execute its update routine
	return sp3DLoader->Update();
}

// We don't know make undo for this command
STDMETHODIMP CRcUpdate3DLoader::Undo(void)
{
    return E_NOTIMPL;
}

// Redo hasn't sense too
STDMETHODIMP CRcUpdate3DLoader::Redo(void)
{
	return E_NOTIMPL;
}

// We tell the system we haven't undo/redo actions for this command
STDMETHODIMP CRcUpdate3DLoader::HasUndo(RtBool* isUndoable)
{
	// Command hasn't undo.
	*isUndoable = false;

	return S_OK;
}


