Notifications
Clear all

[Closed] Need help optimizing speed in a treeView control

Hi all,

I am trying to mimick the Outliner from Maya.
So far, I have it working … (kind of…)

But i have an speed issue with a funtion that would return all the children of a given treeNode.

the idea beeing:

  • click on a TreeView Node
  • get all the Treeview children of that node
  • match the Scene objects
  • select them

How would you write such a function:
fn getTVChildren TV theNode = (…)

so far I have it working using 2 functions and a local array variable


  	local TVchildren -- 
  	
  	fn getTVFirstChildren tv theNode = -- get the direct children of a TV node
  		(
  		local Children=#()
  		if theNode.children>0 do
  			(
  			Children=for n in tv.nodes where (n.parent != undefined and n.parent.index==theNode.index) collect n
  			)
  		return Children
  		)
  	
  	-- recursive funtion to get all the children from an TV node array into the TVchildren array
  	-- Note: MUST clear the TVchildren array before the call !!!
  	fn walkChildren tv arrayChildren =
  	(
  		for i = 1 to arrayChildren.count do
  		(
  			append TVchildren arrayChildren[i]
  			walkChildren tv (getTVFirstChildren tv arrayChildren[i])
  		)
  	)
  

then I call the functions from a NodeClick handler:


  	-- Left click Handler
  	on tv nodeClick theNode do
  	(
  		sel=#() -- clear the selection
  		TVchildren = #()
  		TVCursel = theNode.index
  		if theNode.children>0 do
  			(
  			theChildren = getTVChildren tv theNode -- get direct children
  			walkChildren tv theChildren -- get all children from the direct children
  			-- Nodes = for o in objects collect o
  			-- .tag property stores the index of the object from the Nodes array
  			sel = for Node in TVchildren collect Nodes[Node.tag] 
  			)
  		append sel Nodes[theNode.tag] -- add the clicked Node itself
  		select sel -- Select the items
  	)
  
  

This works But is Very slow (testing with 2 biped objects) since all nodes are looped for each children…

Isn’t there a predefined function to get all the children (and the children’s children) from a Node ?

Thanks in advance for any input.

6 Replies

You may have already seen that there is a “how to develop a scene browser using Treeview Active X control” in the Maxscript help.

It also uses a function to recursively get children.

Hi,

The How-to example has a function to recursively ADD Scene Nodes to a tree: AddChildren

What I am looking for is a better way to implement a ‘GetTreeviewChildren’ function
I know how to get the all children from a SCENE node, but more complex is to get
all the children from a TREEVIEW node.
also I don’t have a ROOT node:

+ROOT
+item1
item2
+item3

and what i have (want) is this:
+item1
item2
+item3

or else, is there a way to hide the Root Node in a treeview ?

Try something like this

 
fn GetChildren node = 
(
   if ( node != undefined ) do
   (
	  if(node.children>0) then
	  (
		 --Now get children (if any)
		 local currentNode = node.Child
		for i=1 to node.children do
		(
		   --Recurse on the current child
		   GetChildren currentNode

		   --Move to the next child
		   currentNode = currentNode.next
	   ) 
	 )
	 else
	 (
		return node
	 )
  )
)

Have a look at this thread on the 3dbuzz forum where i have implemented something similar to what you are doing.
http://www.3dbuzz.com/vbforum/showthread.php?t=137957&page=2
Hope this helps
Mobeen

Hi,

Thanks for the tip mobeen, very usefull !

But, the ‘getchildren’ function does not return anything unless ‘node’ has no children
if ‘node” has 1 or more children it return ‘OK’

so I modified it slighly to add the current child to an external array:


fn GetTVchildren node = 
  	(
  	if(node.children>0) do
  		(
  		--Now get children (if any)
  		local currentNode = node.Child
  		for i=1 to node.children do
  			(
  			append TVchildren currentNode -- add the child to the array
  			GetTVchildren currentNode --Recurse on the current child
  			currentNode = currentNode.next --Move to the next child
  			) 
  		 )
  	)
  

Works a treat, and WAY faster than the previous code !!!
Thx again

But, is there a way to avoid using an external array, and have the function return an array of the children ?

Maybe this could help. It’s not related to TV nodes but shows how to gather node’s children without using an external array:

fn getNodeChildren node = (
	local children = #()

	if node.children.count > 0 do (
		for child in node.children do (
			append children child
			join children (getNodeChildren child)
		)
	)
	
	return children
)

Yeah i already have this function to get SCENE nodes
but for Treeview, the .children property returns the number of children, not the children themselves…

but using an external works great !
I was just thinking of a way to avoid external array.

Also, while i’m at it, i am trying to hack the fact the treeview does not allow multiple selection by changing the backcolor property…

I have implemented drag and drop functionality, and it works well, but when trying to implement the ‘shift-click’ handler (like selecting files in Windows explorer) , i have a problem retreiving the index of the nodes.

  1. store the index of a clicked note in a ‘clickedNode’ variable
  • when shift click another node, check for the ‘clickedNode’ variable and store the index in 2. ‘shiftClickedNode’ variable
  1. retreive all nodes from the ‘clickedNode’ to the ‘shiftClickedNode’

But the prob i am facing is that the indices of the nodes in the treeview are not linear:
node1 may not have index 1, node2 may not have index2 etc …

so for example:
click node4 – (index 15)
shift click node 10 ( index 3)
how can I get the indices of the nodes DISPLAYED beween those 2 ?
this seams very hard (for me)

Any ideas ??