How To ... Develop a Scene Browser using TreeView ActiveX Control - Part One

How To > Use ActiveX Controls > Develop a Scene Browser - Part One

This tutorial demonstrates how to create a Scene Browser showing the object hierarchy in a TreeView ActiveX Control.

NOTE:

ActiveX Controls have been deprecated by Microsoft in the latest versions of the Windows operating system in favor of the DotNet framework and its controls.

While MAXScript still supports ActiveX controls, these have to be installed and registered on the system to be accessible to MAXScript.

As a replacement of ActiveX controls, MAXScript supports DotNet controls in 3ds Max 9 and higher.

Please see the topic Converting ActiveX TreeView Control to DotNet TreeView Control

Related topics:

ActiveX Controls in MAXScript Rollouts

TreeView ActiveX Control

NATURAL LANGUAGE

Create a simple macroScript.

Define a rollout which will be used to create a floating dialog.

The only UI controls in the rollout will be a TreeView ActiveX Control and a spinner to control the Indentation

Create a function to recursively traverse all children and add children nodes to the TreeView.

Create a function to define the layout and appearance of the TreeView.

Create a function to fill in the nodes into the TreeView by calling the recursive function.

The two functions will be called by the on open event handler whenever the dialog is created (and thus the rollout is opened).

SCRIPT:

macroScript SceneTreeView category:"HowTo"
(
rollout treeview_rollout "TreeView Scene Browser"
(
fn initTreeView tv =
(
tv.Indentation = 28*15
tv.LineStyle = #tvwRootLines
)
fn addChildren tv theNode theChildren =
(
for c in theChildren do
(
newNode = tv.Nodes.add theNode.index 4 "" c.name 0
addChildren tv newNode c.children
)
)
fn fillInTreeView tv =
(
theRoot = tv.Nodes.add()
theRoot.text ="WORLD ROOT"
rootNodes =for o in objects where o.parent == undefined collect o
addChildren tv theRoot rootNodes
)
activeXControl tv "MSComctlLib.TreeCtrl" width:190 height:290 align:#center
spinner spn_indent "Indentation" range:[0,100,28] type:#integer fieldwidth:40
 
on tv nodeClick theNode do try(select (getNodeByName theNode.text))catch()
on spn_indent changed val do tv.indentation = val*15
on treeview_rollout open do
(
initTreeView tv
fillInTreeView tv
)
)
try(destroyDialog treeview_rollout)catch()
createDialog treeview_rollout 200 320
)

RESULT:

Step-By-Step

macroScript SceneTreeView category:"HowTo" (

We start by defining a simple MacroScript with the name SceneTreeView which will appear in the category "HowTo". Simple (old-style) macroScripts do not have on execute do or on isEnabled event handlers. The code inside the MacroScript definition is executed immediately when the ActionItem (button, menu item or keyboard shortcut) representing the MacroScript is activated.

rollout treeview_rollout "TreeView Scene Browser" (

This is the rollout to be created when the MacroScript is executed. It will display the title "TreeView Scene Browser". The variable treeview_rollout will be local to the macroScript and will be used later on to create a dialog out of the rollout definition.

fn initTreeView tv = (

This is the function which will perform the initialization of the TreeView ActiveX control we will create. The control itself will be passed as argument to the function.

tv.Indentation = 28*15

The .indentation property expects a value in Twips and defines the amount of twips to indent children relatively to their parent. Since a pixel is roughly 15 twips, this line tells the hierarchy to use 28 pixels indentation.

tv.LineStyle = #tvwRootLines

TheLineStyle propery controls the appearance of the lines connecting the nodes in the hierarchy. We want the root to have its own plus/minus box and be connected to the scene nodes.

) fn addChildren tv theNode theChildren = (

This function will be called recursively to create children of the node passed as argument using theChildren argument containing an array of 3ds Max scene nodes. The argument tv will contain the TreeView to add to.

for c in theChildren do (

For each 3ds Max scene node in theChildren array...

newNode = tv.Nodes.add theNode.index 4 "" c.name 0

...we add a new child to the supplied node. We pass a couple of parameters to the add() method - the index of the parent, the relationship flag (4), the key (empty string), the text of the new child (the name of the scene node), and the index of the image to be displayed as icon (0 for no image)

addChildren tv newNode c.children

Once the child is created, the function calls itself recursively, passing the newly created node and the array of children of the current scene object as parameter. This way, the complete scene hierarchy will be recreated by the TreeView!

)

The c loop ends here.

)

The recursive function ends here.

fn fillInTreeView tv = (

This function will define the content of the TreeView.

theRoot = tv.Nodes.add()

We add a single new node to represent the Root.

theRoot.text = "WORLD ROOT"

We set its label to "WORLD ROOT"

rootNodes = for o in objects where o.parent == undefined collect o

Then we collect all objects in the scene that have no parent. These are the top-level nodes that will be the "children of the world".

addChildren tv theRoot rootNodes

Finally, we call the recursive function, passing the TreeView, the Root node and the array of top-level scene objects as arguments.

) 

activeXControl tv "MSComctlLib.TreeCtrl" width:190 height:290 align:#center

Now we can create a TreeView ActiveX control in the rollout.

spinner spn_indent "Indentation" range:[0,100,28] type:#integer fieldwidth:40

This spinner will allow us to test interactively the .indentation property of the TreeView. Simply changing the spinner's value will dynamically update the indentation of the complete hierarchy!

on tv nodeClick theNode do try(select (getNodeByName theNode.text))catch()

If the user clicked a node, we will try to convert its name back to a 3ds Max scene node and select it in the scene. This demonstrates the usage of TreeView event handlers...

on spn_indent changed val do tv.indentation = val*15

If the user changed the spinner, we want the .indentation to be set to the respective amount of Twips.

on treeview_rollout open do (

When the rollout is opening (this is when the CreateDialog function is called)...

initTreeView tv fillInTreeView tv

...the initialization function and the data collecting function will be called to define the style and populate the TreeView control with the names of the 3ds Max scene objects.

)

The rollout open event ends here.

) try(destroyDialog treeview_rollout)catch()

Before creating a new dialog, we want to make sure any previously opened dialog with the same name is closed...

createDialog treeview_rollout 200 320

Finally, we create a new Dialog using the rollout definition.

)

What's Next?

This is a very basic version of the script. To see how it can be further improved and customized, see Part Two of the tutorial - How To ... Develop a Scene Browser using TreeView ActiveX Control - Part Two

See Also