macroScript SceneTreeView category:"DotNet"
(
--We create an ImageList object to hold all icons for the TreeView --in the local scope of the MacroScript. In he case of ActiveX, --the ImageList had to be a UI control inside the rollout. --It is possible to create a local DotNet object inside the rollout --and pass the ImageList as parameter to the functions, but it is --more convoluted. In this version, all functions "see" the --ImageList DotNet object in the higher scope:
ilTv = dotNetObject "System.Windows.Forms.ImageList"
ilTv.imageSize = dotNetObject "System.Drawing.Size" 16 15
rollout treeview_rollout "TreeView Scene Browser"
(
/* ActiveX Version:
fn getIconFromBitmap thePath number =
(
tempBmp = openBitmap thePath
iconBmp = bitmap 16 15
for v = 0 to 14 do
setPixels iconBmp [0,v] (getPixels tempBmp [(number-1)*16, v] 16)
iconBmp.filename = getDir #image +"/_temp.bmp"
save iconBmp
close iconBmp
close tempBmp
getDir #image +"/_temp.bmp"
)
*/ --When creating icons for DotNet, it is necessary to create --one bitmap for each icon, because the DotNet image list will --lock the file for the duration of the script execution. --The original script used a single file to write temporarily --all icon bitmaps. This version writes a separate bitmap with the --name passed as third argument. The function only creates bitmaps --if they do not exist yet to avoid bitmap access errors.
fn getIconFromBitmap thePath number iconFileName =
(
theFileName = getDir #image +"\\icon_"+ iconFileName +".bmp"
if not doesFileExist theFileName do
(
tempBmp = openBitmap thePath
iconBmp = bitmap 16 15
for v = 0 to 14 do
setPixels iconBmp [0,v] (getPixels tempBmp [(number-1)*16, v] 16)
iconBmp.filename = theFileName
save iconBmp
close iconBmp
close tempBmp
)
img = dotNetClass "System.Drawing.Image" --create an image
ilTv.images.add (img.fromFile theFileName) --add to the list
)
/* ActiveX Version:
fn initTreeView tv ilTv =
(
tv.Indentation = 28*15
tv.LineStyle = #tvwRootLines
tv.checkboxes = true
tv.sorted = true
ilTv.imagewidth = 16
ilTv.imageheight = 15
iconDir = (getDir #ui) + "\\icons"
ilTv.listImages.add 1 #root (loadPicture (getIconFromBitmap (iconDir + "\\Standard_16i.bmp") 2))
ilTv.listImages.add 2 #geomnode (loadPicture (getIconFromBitmap (iconDir + "\\Standard_16i.bmp") 1))
ilTv.listImages.add 3 #light (loadPicture (getIconFromBitmap (iconDir + "\\Lights_16i.bmp") 3))
ilTv.listImages.add 4 #camera (loadPicture (getIconFromBitmap (iconDir + "\\Cameras_16i.bmp") 2))
ilTv.listImages.add 5 #helper (loadPicture (getIconFromBitmap (iconDir + "\\Helpers_16i.bmp") 1))
tv.imageList = ilTv
)
*/
fn initTreeView tv =
(
tv.Indent= 28
tv.CheckBoxes = true --same as in ActiveX --This is the icons directory. --We could also use the new colorman.resolveIconFolder() method --to get the path to the actual system icons...
iconDir = (getDir #ui) + "\\icons\\"
--We call our function for each icon, this time also passing a --third argument with the icon name suffix.
getIconFromBitmap (iconDir + "Standard_16i.bmp") 2 "Sphere"
getIconFromBitmap (iconDir + "Standard_16i.bmp") 1 "Box"
getIconFromBitmap (iconDir + "Lights_16i.bmp") 3 "Light"
getIconFromBitmap (iconDir + "Cameras_16i.bmp") 2 "Camera"
getIconFromBitmap (iconDir + "Helpers_16i.bmp") 1 "Helper"
--At the end, we assign the ImageList to the TreeView.
tv.imageList = ilTv
)
/* ActiveX Version:
fn addChildren tv theNode theChildren =
(
for c in theChildren do
(
theIcon = case superclassof c of
(
GeometryClass: 2
Light: 3
Camera: 4
Helper: 5
Default:2
)
newNode = tv.Nodes.add theNode.index 4 "" c.name theIcon
theNode.sorted = true
newNode.checked = not c.isHidden
newNode.forecolor = color c.wirecolor.b c.wirecolor.g c.wirecolor.r
addChildren tv newNode c.children
)
)
*/
fn addChildren theNode theChildren =
(
for c in theChildren do
(
newNode = theNode.Nodes.add c.name
newNode.tag = dotNetMXSValue c
--By default, all nodes will use icon 0 (the first one) unless --specified otherwise via the .iconIndex and .selectedIconIndex --properties.We set both of them to the icon corresponding to --the superclass of the scene object:
newNode.imageIndex = newNode.selectedImageIndex = case superclassof c of
(
Default: 1
Light: 2
Camera: 3
Helper: 4
)
newNode.checked = not c.isHidden--same as in ActiveX --For the color, we create a DotNet color class from the --wirecolor of the object and assign to the .forecolor of --the TreeView node:
newNode.forecolor = (dotNetClass "System.Drawing.Color").fromARGB c.wirecolor.r c.wirecolor.g c.wirecolor.b
addChildren newNode c.children
)
)
--Since every node uses icon with index 0 unless specified otherwise --the Root Node will use the first icon by default.
fn fillInTreeView tv =
(
theRoot = tv.Nodes.add "WORLD ROOT"
rootNodes =for o in objects where o.parent == undefined collect o
addChildren theRoot rootNodes
)
dotNetControl tv "TreeView" width:290 height:490 align:#center
on tv Click arg do
(
hitNode = tv.GetNodeAt (dotNetObject "System.Drawing.Point" arg.x arg.y)
if hitNode != undefined do
try(select hitNode.tag.value)catch(max select none)
)
/*
on tv NodeCheck theNode do
(
theSceneNode = (getNodeByName theNode.text)
if theSceneNode != undefined do
theSceneNode.isHidden = not theNode.checked
)
*/ --NOTE that in the case of ActiveX controls, we were using the name --displayed by the TreeView node. In the case of DotNet, we are --using the actual MAXScript value pointing at the scene object. --The arg argument provides a .node property containing the node --that was checked. We use the .tag property to access the --DotNetMXSValue stored in the TreeView node and then the .value to --get the MAXScript value stored in it. Then we set the isHidden --property of the scene object to the inverse of the checked state --of the TreeView node:
on tv AfterCheck arg do
try (arg.node.tag.value.isHidden = not arg.node.checked)catch()
on treeview_rollout open do
(
initTreeView tv
fillInTreeView tv
)
)
try (destroyDialog treeview_rollout)catch()
createDialog treeview_rollout 300 500
)
|