PDA

View Full Version : Traverse hierarchy



nickdigital
02-09-2013, 09:30 PM
Does anyone have an example of traversing a parent-child hierarchy? I understand the .next code but how does one deal with a hierarchy that has multiple child branches? You'd have to go back to the parent and then traverse down the next child branch.

Is there an equivalent of select parent and child, same as in Scene Editor.

RebelHill
02-10-2013, 05:01 AM
there's SelectParent() and SelectChild()... but you'll probs find most useful for this sorta thing... visitnodes()

nickdigital
02-10-2013, 06:17 PM
Thanks RH!

nickdigital
02-12-2013, 07:25 PM
Ok so how would one use visitnodes so that you can perform an action on everything in the hierarchy but only once. I'm iterating through but how would I check if an action has been previously run on a parent that has multiple child branches?

sami
02-12-2013, 07:43 PM
not sure what you are asking, but you could create an array of flags that mimics the node hierarchy of the thing you are traversing.

What you are asking I think, is you kind of want a logical object (an OOP object not a LW object) that also has a "dirty" flag per node. This would encapsulate your tree and add "properties" per node. So I think you need to create a "class" object that stores your tree structure and have one property for the real scene object and a second property for the dirtyflag. Then traverse your object - check the dirty flag and perform operations on the property containing the actual scene item.

let me know if this doesn't make sense or if I got what you wanted wrong.

RebelHill
02-13-2013, 09:44 AM
visitnodes should visit each item in the hierarchy only once... so it shouldnt repeat on a parent item to multiple child branches... nuless ofc ur visitnodes-ing multiple times on the same items for different child trees somehow or other.

Else, u can use a linked array (key:element) that records each items name with a true/false, yes/no /whatever/whichever flag thats referenced in the function fed to visitnodes to decide if the contents of that function should be run on the given item.

nickdigital
02-13-2013, 10:37 AM
Thanks for the responses. I found that since the parent will already be selected I can get that info from that selection and then deal with the children through visitnodes. The solution came to me during my drive home. A lot can be said for disconnecting from the computer and letting your mind explore things on their own.

nickdigital
02-20-2013, 12:03 AM
How can I pass the child that comes out of visitnodes into a function (myUDF) when that function (myUDF) is also expecting incoming parameters?

Or...

Can I return the child to a variable?

I have the below but that's not working.



{
...
c = visitnodes(myselect[i],"hierarchy_iterate");
info (c);
...
...
...
}
hierarchy_iterate: parent, child
{
return (child);
}

Basically I have a UDF where I want to pass the child to it but my UDF has a lot of other parameters that are defined elsewhere. visitnodes() only accepts two parameters.

RebelHill
02-20-2013, 04:29 AM
selection = Scene().firstselect(); //binds whatever item u have selected
visitnodes(selection,"vnFunc"); //runs over the hierarchy of selection executing vnFunc

vnFunc: parent,child
{
myUDF(child); //calls the udf for each child item
}

myUDF:item
{
doStuffTo(item);
}

nickdigital
02-20-2013, 05:59 AM
But myUDF has more than just item being fed to it. For example it has info from ctlitems bring fed into it.

RebelHill
02-20-2013, 07:13 AM
in which case ull want to instead use visitnodes to get the hierarchy, and another function to process it... such...

selectedHierarchy = visitnodes(selection,"vnFunc");

vnFunc: parent,child
{
AddToSelection(child);
}

myUDF: item,var1,varEtc
{
stuff;
}

foreach(selectedHierarchy,item)
{
myUDF(item,var1,varEtc);
}

nickdigital
02-20-2013, 11:23 AM
Ok I'm not sure if I'm making progress or just getting more lost, ;D.

I'm getting this error, "stack empty, no value to assign to variable generic::selectedHierarchy". If I don't do child.name for the AddToSelected part that line of code doesn't work.

I also notice that this actually selects items when the script is done running. Will this work if my hierarchy has items of mixed types (mesh, lights, camera, bones)?

The firstframe variable is defined further up in my code. I'm just passing it so I can test that when I run my UDF on my child that I'm getting the proper data passed through.



myselect = Scene().getSelect();
for (i=1;i<=myselect.size();i++){
selectedHierarchy = visitnodes(myselect[i],"hierarchy_iterate");
foreach(selectedHierarchy,myselect[i]){
test(selectedHierarcny,firstframe);
}


// UDFs
hierarchy_iterate: parent, child
{
info (child.name);
AddToSelection(child.name);
}

test:child,firstframe{
info (child.name);
info (firstframe);
}

RebelHill
02-20-2013, 11:39 AM
foreach(selectedHierarchy,myselect[i]){
test(selectedHierarcny,firstframe)

there's ur problem (I think)... first line.

ur iterating from an array (myselect[i]) into the foreach...

foreach takes an array (someSelection), and creates an identifier for each of the items (someItem) to pass to the function inside it...

foreach(someSelection,someItem);
{
myUDF(someItem,otherVar,etcVar);
}

myUDF: inputItemVar,otherVar,etcVar
{stuff}

............

In a way (though not exactly)... foreach(selection,item) is the same as for(i=1;i<=selection.size;i++)... just as the [i] in "for" is an "auto" variable relating to each element of the array... item (or whatever name u use) in foreach is an auto var... doesnt need declaring, and shouldnt refer to any specific "object".

nickdigital
02-20-2013, 01:15 PM
Ok so for the "foreach" line I replaced "myselect" with "item" but I'm still getting the same error.


myselect = Scene().getSelect();
for (i=1;i<=myselect.size();i++){
selectedHierarchy = visitnodes(myselect[i],"hierarchy_iterate");
foreach(selectedHierarchy,item){
test(selectedHierarcny,firstframe);
}


// UDFs
hierarchy_iterate: parent, child
{
info (child.name);
AddToSelection(child.name);
}

test:child,firstframe{
info (child.name);
info (firstframe);
}

nickdigital
02-20-2013, 01:34 PM
What if I restructure my UDF so the paramaters are global declarations? Then I can just pass the child item like your previous example.

vnFunc: parent,child
{
myUDF(child); //calls the udf for each child item
}

myUDF:item
{
doStuffTo(item);
}

nickdigital
02-20-2013, 02:51 PM
What if I restructure my UDF so the paramaters are global declarations? Then I can just pass the child item like your previous example.


So far this seems to be working so so far so good.

RebelHill
02-20-2013, 03:55 PM
U can... if the vars ur wanting to pass in dont need to change throughout the life of the script its just as easy to make them global, then u can call them from within the func itself without the pass in.