macroscript showNodeLabels category:"MB Tools" ( -- showNodeLabels v1.1 -- for 3ds max 9-2010 - (c) 2010 by M. Breidt (martin@breidt.net) -- -- This code is released under "Quote ware" license: -- If you use this tool in a production environment with a group of more than two people, -- or have used it in the past under such conditions, then you are obliged to tell -- me (martin@breidt.net) about it and allow me to list that project title and your -- company name as a reference on my website http://scripts.breidt.net -- -- Synopsis: -- This macroScript will display viewport labels for selected nodes, useful for quickly -- identifying unselected nodes by name -- -- Installation: -- Run the script, then install the macro 'showNodeLabels' from the category 'MB Tools' -- into a toolbar, a quad menu, a hotkey or the menu bar. -- The following description assumes a toolbar button: -- -- Usage: -- Select some objects and hit the button to turn on viewport labels for these nodes. -- Hit the button again to turn off viewport labels for the selected nodes -- Don't select any objects and hit the button to turn off ALL labels -- -- Known limitations: -- * Currently not persistent with save/load; you need to re-enable all labels after -- loading a new scene -- * Button will stay active when all labeled nodes are deleted; just press it twice. -- * Sometimes, viewport artifacts (trails) show up when moving nodes or the viewport; -- a simple refresh or short viewport pan will fix this. :-) -- * Node labels can overlap in the viewport; no fancy occlusion testing is done, sorry. -- * Viewports slow down noticeably with 200+ labels -- * Renaming an object will not immediately change the label, but on the next viewport update -- -- Changelist: -- v1.0 - * Initial release -- -- v1.1 - * labels are no longer drawn when node isn't visible -- * added custom offset 'labelDelta' to label text, and custom text color -- * holding Shift while running macro will select and print all labeled objects global showNodeLabelsList if showNodeLabelsList == undefined then showNodeLabelsList = #() fn drawNodeLabels = ( -- callback function for drawing labels for all nodes in showNodeLabelsList array -- USER CUSTOMIZABLE VARIABLES below --------------------- local labelDelta = [0,0,0] -- offset in screen coordinates for label. 3rd element should be zero -- Positive values move labels away from center of object. local textCol = (color 255 255 255) -- label text color -- END OF USER CUSTOMIZABLE SECTION -------------------- gw.setTransform (matrix3 1) for i = showNodeLabelsList.count to 1 by -1 do ( -- count backwards to allow deletion of list entries local obj = showNodeLabelsList[i] if (isValidNode obj) then ( if (not obj.isHiddenInVpt ) then ( -- check whether obj is actually visible; don't draw label otherwise -- local m = obj.transform -- local o = m.translation -- use bounding box for label positions local mx = obj.max local ct = obj.center -- transform 3D world coordinates to device coordinates wct = gw.wTransPoint ct -- center of node in device coordinates wmx = gw.wTransPoint mx -- upper right corner of node bounding box in device coordinates wmx += labelDelta -- add user offset -- draw black text at BB max (shadow effect) local d = [1,1,0] gw.wtext (wmx+d) obj.name color:black -- text shadow -- draw black line from center to text pos gw.wpolyline #(wct, wmx) false rgb:#(black,black) -- draw white text gw.wtext (wmx) obj.name color:textCol -- text ) ) else ( -- not a valid node, remove it from list deleteItem showNodeLabelsList i ) ) -- end: for obj gw.enlargeUpdateRect #whole gw.updateScreen() ) -- end: fn drawNodeLabels on isChecked do ( ((classOf showNodeLabelsList)==Array) and (showNodeLabelsList.count>0) -- we could check for valid objects here, but might be slow ) on execute do ( if (classOf showNodeLabelsList)==Array then ( if keyboard.shiftPressed then ( format "Selecting % labeled node(s):\n" showNodeLabelsList.count for i in showNodeLabelsList do format "\t%\n" i.name select showNodeLabelsList ) else ( if (selection.count==0) then ( -- nothing selected, clear list of nodes format "showNodeLabels: clearing all labels\n" showNodeLabelsList = #() ) else ( -- some objects selected, toggle them in/out selnodes = selection as array for o in selnodes do ( local i = findItem showNodeLabelsList o if i==0 then ( -- not yet in list, so put it there now format "showNodeLabels: Adding label for node %\n" o.name append showNodeLabelsList o ) else ( -- it is in list, so remove it format "showNodeLabels: Removing label for node %\n" o.name deleteItem showNodeLabelsList i ) ) -- end: for o ) -- end: else if showNodeLabelsList.count > 0 then ( format "showNodeLabels: draw callback registered\n" registerRedrawViewsCallback drawNodeLabels ) else ( format "showNodeLabels: draw callback removed\n" unregisterRedrawViewsCallback drawNodeLabels ) max views redraw ) ) -- end: if classOf ) -- end: on execute ) -- end: macroscript