Hi!
You are almost there
The Graph::IRoot::CreateNode() method can be used to create a scene graph node at runtime. Here, the className parameter represents the actual name of the class you want to create an instance from. This name must be equal to the element tag you would specify in an XML scene graph description; in your case you would create a plane geometry node from the Graph::PlaneGeometry class by stating
root->CreateNode("PlaneGeometry");
As a convenience, you might also pass the node's desired ID with the following call (optional):
root->CreateNode("PlaneGeometry", "myPlaneGeom1");
Both methods return a Graph::INode* object, which represents the base interface of all scene graph nodes. In order to access the specific functionality of the node you created, you need to cast that base interface to the actual interface. With that interface in hand, you can directly access its methods, and also the methods of any of the available other base interfaces for this class:
Graph::IPlaneGeometry* geom = dynamic_cast<Graph::IPlaneGeometry*>(root->CreateNode("PlaneGeometry", "myPlaneGeom1"));
geom->SetFrameSize(42.0, 21.0);
geom->GetTransformInterface()->SetPositionX(27.0);
geom->GetNodeInterface()->SetVisible(false);
geom->GetNodeInterface()->SetId("myPlaneGeom1"); // redundant, because we already passed an ID at root->CreateNode().
Now we have a newly created node with some parameters set. We must place this node somewhere in the scene graph and initialize it, which is done using the base Graph::INode interface. If we want to add it to the graph's root node, we might write:
root->InitGraph(geom->GetNodeInterface(), root->GetRootNode());
In practice, you will most likely need to put the node at some other place in the graph, for example
root->InitGraph(geom->GetNodeInterface(), root->FindNode("/myNamespace1/blah"));
will add the node as a child of the existing node found at "/myNamespace1/blah", and initialize it.
If you do not only want to create a single node but a more complex sub-graph, you do not need to explicitly perform root->InitGraph() on every single node in that sub-graph. You might do something like this:
Graph::INode* subGraph = root->CreateNode("FixedParameters", "testParams"));
Graph::IFixedParameters* params = dynamic_cast<Graph::IFixedParameters*>(subGraph);
params->SetColor(IEnums::LIGHTING_COMPONENT_DIFFUSE, Color(1.0f, 0.5f, 0.0f, 1.0f));
Graph::IMaterialState* matState = dynamic_cast<Graph::IMaterialState*>(root->CreateNode("MaterialState", "testMatState"));
matState->GetMaterialNodeTarget()->SetNumberOfNodes(1);
matState->GetMaterialNodeTarget()->SetNodeId("/common_materials/mat_white", 0);
subGraph->AddChild(matState->GetNodeInterface());
Graph::ICubeGeometry* cube = dynamic_cast<Graph::ICubeGeometry*>(root->CreateNode("CubeGeometry", "testCube"));
cube->GetTransformInterface()->SetPosition(Real(3.0), Real(1.5), Real(0.1));
cube->SetScaleFactor(Real(0.25));
subGraph->AddChild(cube->GetNodeInterface());
root->InitGraph(subGraph, root->FindNode("/myNamespace1/blah"));
However, as soon as you manually create (a) node(s) at runtime, you are also responsible for correct destruction! Every root->InitGraph() call must have a corresponding root->DeInitGraph() call along with root->DestroyGraph(). Here's a more detailed example:
App::MyLogic::MyLogic(Logic::IFactory* factory)
: BaseProcessor(factory)
, mSubGraph(0)
{
}
Bool App::MyLogic::CreateMyGraph(Graph::IRoot* root)
{
if (mSubGraph == 0)
{
mSubGraph = root->CreateNode("FixedParameters", "testParams"));
Graph::IFixedParameters* params = dynamic_cast<Graph::IFixedParameters*>(mSubGraph);
params->SetColor(IEnums::LIGHTING_COMPONENT_DIFFUSE, Color(1.0f, 0.5f, 0.0f, 1.0f));
Graph::IMaterialState* matState = dynamic_cast<Graph::IMaterialState*>(root->CreateNode("MaterialState", "testMatState"));
matState->GetMaterialNodeTarget()->SetNumberOfNodes(1);
matState->GetMaterialNodeTarget()->SetNodeId("/common_materials/mat_white", 0);
mSubGraph->AddChild(matState->GetNodeInterface());
Graph::ICubeGeometry* cube = dynamic_cast<Graph::ICubeGeometry*>(root->CreateNode("CubeGeometry", "testCube"));
cube->GetTransformInterface()->SetPosition(Real(3.0), Real(1.5), Real(0.1));
cube->SetScaleFactor(Real(0.25));
mSubGraph->AddChild(cube->GetNodeInterface());
root->InitGraph(mSubGraph, root->FindNode("/myNamespace1/blah"));
}
return true;
}
Bool App::MyLogic::DestroyMyGraph(Graph::IRoot* root)
{
if (mSubGraph != 0)
{
root->DeInitGraph(mSubGraph);
root->DestroyGraph(mSubGraph);
mSubGraph = 0;
}
}
Bool App::MyLogic::OnDeInit(const Logic::IState* state)
{
return DestroyMyGraph(state->GetGraphRoot());
}
void App::MyLogic::OnProcessTick(const Logic::IState* state)
{
if (state->GetDeviceHandler()->WasTouchReleased())
{
if (mSubGraph == 0)
{
CreateMyGraph(state->GetGraphRoot());
}
else
{
DestroyMyGraph(state->GetGraphRoot());
}
}
}
If you want to use the newly created node with a Logic::PlaneGeometryNode observable, you would write something like that:
Graph::IPlaneGeometry* geom = dynamic_cast<Graph::IPlaneGeometry*>(root->CreateNode("PlaneGeometry", "myPlaneGeom1"));
root->InitGraph(geom->GetNodeInterface(), root->FindNode("/myNamespace1/blah"));
AddGraphNode(mPgn.GetReference(geom->GetNodeInterface())); // define in header file: Logic::PlaneGeometryNode mPgn;
...
again followed by the following code on destruction:
...
Graph::INode* geom = mPgn.GetNodeInterface();
RemoveGraphNode(mPgn);
root->DeInitGraph(geom);
root->DestroyGraph(geom);
Hope that helps!
dizzy