In the following example (a guard stack for a recursive and potentially re-entrant method), I’m looking to use Node User Variables to store a VariantVector. Node::vars_ is a protected member, so we have to use accessors (GetVar/SetVar)
Since Node::GetVar and its counterpart Node::GetVars both only provide const (read-only) access, this means that any non-trivial types such as vectors and maps need to be completely copied every time we want to perform read-write access to a node user variable.
BTNodeState BehaviorTree::Process(float timeStep, Urho3D::ScriptInstance* callerAgent)
{
if (isActive_)
{
this->callingAgent = callerAgent;
timeStep_=timeStep;
/// We assume that the scriptinstance's parent node has a "subtree stack" variable...
Variant v=callingAgent->GetNode()->GetVar("SubtreeStack_");
if(v.GetType()==VAR_NONE)
{
/// Agent does not yet have a Subtree Stack variable: add one now
VariantVector vv {this};
callingAgent->GetNode()->SetVar("SubtreeStack_", vv);
}else{
/// Obtain a pointer to the stack object within variant v
VariantVector* pv=v.GetVariantVectorPtr();
/// Check if this behaviortree exists in the execution guard stack
if(pv && pv->Contains(this))
{
URHO3D_LOGERROR("Behavior Subtree Recursion was prevented!");
return NS_ERROR;
}
/// Push this behaviortree onto the guard stack
pv->Push(this);
/// Write modified variant back to node variable
callingAgent->GetNode()->SetVar("SubtreeStack_",v);
}
/// Push sentinal nullptr onto list of active nodes
activeNodes_.Push(nullptr);
/// Execute behaviortree
while(Step(timeStep))
continue;
/// Pop this behaviortree from the guard stack
v=callingAgent->GetNode()->GetVar("SubtreeStack_"); /// Probably not necessary: local variant v should still be valid?
v.GetVariantVectorPtr()->Pop();
callingAgent->GetNode()->SetVar("SubtreeStack_",v);
}
return currentState_;
}
Take note of the last few lines, where we need to “pop” a value from the stack, then write the variant back to the node variable container…
Am I overlooking something?