Some guidance/help needed


My little script to make measuring a little quicker and easier which can be found on Scriptspot
and needs a little help from the gurus here.

  1. If you click on un-go to remove the tape and reset the ui it works fine but it doesn’t clear the information from max’s memory so if you immediately click “Go” again it will re-make the tape in the same location even if the two objects being measured are deleted.
    –How do I go about resetting this?

  2. If you need to finesse the position the tape in the viewport what do I need to do to capture the changes in my edittext of the Tape Measure ui?

Download the .mcr script



Add this at the end of the but_dtape handler

pPoz = qPoz = rTape = pbt_picktT.object = pbt_picktS.object = undefined

You’re not doing a good cleanup in the eventhandler and also the btn go handler is very error prone, it probably crashes when you haven’t picked 2 points, but press the button.

Read up on the following functions : getNodeByName / isValidNode / createDialog (instead of rolloutfloater, if your only using one rollout) and definitely take a look at your error catching, loads of try catches usually means you’re not quite sure how to deal with exceptions. For example:

on but_sTape pressed do
					if rTape != undefined do
					select rTape
					but_sTape.text =

Should also just work like

on but_sTape pressed do
  if isValidNode rTape do
	select rTape
	but_sTape.text =

See no try catch needed at all, because I know when I have a valid node the rest of the code block works.

Hope this helps,


Tomorow I will release a script that use tape to measure distance and some other things(need time to capture some videos of how the script work). In the code you will find the ansewr of question 2. Just a hint - check maxscript referense for “when construct”. I think that there is better solution then mine, but… the people wtih more expirience in mxs may be will help you and me. :slight_smile:


Thanks Johan just the kind of thing I needed

Look forward to it miauu
I’m not quite at this level yet but looking into all these sugestions


why do we need the tape helper in this tool?


Well really because I wanted to cover anything I couldn’t think of, I originally just gave the result but mainly because I’m a noob at scripting I can’t work out how to update the result in real time as you manually move the tape to finesse the position of it. But the tape can.

Feel free to make some suggestions, I follow much of what you offer to the community and admire your knowledge and commonsense advice.


let’s think… do we really need the tape?
– to measure distance between two nodes we are using distance method
– to draw line between two nodes we can use vewport draw methods
– the type dosn’t really solve the problem of real-time update

where is the point to use it?

if you don’t mind i can show my way of doing these things…


yes please god yes


I was just looking at Viewport Draw method and tried the first example

unregisterRedrawViewsCallback GW_displayObjectNames
fn GW_displayObjectNames =
  gw.setTransform (matrix3 1)
  for o in objects where not o.isHiddenInVpt do
    gw.text o.pos (o as string) color:yellow
  gw.enlargeUpdateRect #whole  
registerRedrawViewsCallback GW_displayObjectNames

There is something wrong, now there is $Particle_View:Particle View […]
permanently in my viewport lol I’m off to restart max


It seems Bobo has tackled something like this before here

I guess my difference is, ideally that I’d like to pick the objects I’d like to measure and have it snap to their locations and possibly their faces/vertices so you can get a more accurate measurement.

DIMaster on cgtalk


Just so you know, DIMaster 2 lets you snap to vertices and even sicks to them.
It is a special mode that reads the data from the Snap system and uses an Attachment Constraint on a Helper to stick to the snapped vertex. If you change the size of the object you are measuring, the DIMline would change size with it dynamically.


Yes playing with it now. Trying to understand some of the code but completly lost :shrug:
It would still be nice to have an interface to pick the objects to measure but I imagine that would get complicated trying to pick a point on the objects to align/snap to.


Here a video that show what my toll can do. The main idea was to create a script that allow user to select edges with desired length(a requested script in one bulgarian forum). I create that script a few months ago, but now I decide to extend the capabilitis of the script. So, now the script can measure the length of selected edges, can measure distance between verts, middle points of edges, objects. Editable Mesh, Editable Poly and Edit Poly objects are supported. :slight_smile:


Awesome job, I like it very much! :applause:


Удоволствието е изцяло мое. :slight_smile:


here is my tool-snippet that demonstrates how to use callbacks and when constructs for real-time UI update:

  global Distance_Catcher
  global Distance_Catcher_Settings = if Distance_Catcher_Settings == undefined then
  	[100,100], 	-- dialog pos
  	undefined, 	-- dialog size
  	1,			-- units
  	#(),		-- locked nodes
  	undefined,	-- locked distance
  	undefined	-- last distance
  else Distance_Catcher_Settings
  try(destroydialog Distance_Catcher) catch()
  rollout Distance_Catcher_Rol "Distance Catcher" width:220
  	local dcs = Distance_Catcher_Settings
  	group "Nodes: "
  		edittext name01_et "" readonly:on width:170 across:2
  		checkbutton lock01_cb width:17 height:17 align:#right offset:[-4,0] tooltip:"Lock Node" checked:(isvalidnode dcs[4][1])
  		edittext name02_et "" readonly:on width:170  across:2
  		checkbutton lock02_cb width:17 height:17 align:#right offset:[-4,0] tooltip:"Lock Node" checked:(isvalidnode dcs[4][2])
  	group "Distance: "
  		label units_lb "Units:" across:2 offset:[-24,1]
  		radiobuttons units_rb labels:#("World", "System") default:dcs[3] columns:2 offset:[-42,0]
  		edittext dist_et "" readonly:on width:85 across:3
  		edittext lock_et "" readonly:on width:85 align:#right offset:[40,0] 
  		checkbutton lock_cb width:17 height:17 align:#right offset:[-4,0] tooltip:"Lock Distance" checked:(dcs[5] != undefined)
  	fn getCurrentNodes = 
  		nodes = getCurrentSelection()
  		node01 = dcs[4][1]
  		node02 = dcs[4][2]
  		if isvalidnode node01 do 
  			if node01 != nodes[1] or nodes[2] == undefined do nodes[2] = nodes[1]
  			nodes[1] = node01
  		if isvalidnode node02 do 
  			if not isvalidnode node01 and node02 == nodes[1] and nodes[2] != undefined do nodes[1] = nodes[2]
  			nodes[2] = node02
  	fn theDist d = if dcs[3] == 1 then units.formatvalue d else d as string
  	fn updateDistance nodes: names:on values:on = 
  		if nodes == unsupplied do nodes = getCurrentNodes()
  		if names do
  			name01_et.text = try(nodes[1].name) catch("")
  			name02_et.text = try(nodes[2].name) catch("")
  		if values do
  			dcs[6] = try(distance nodes[1] nodes[2]) catch(0)
  			dist_et.text = theDist dcs[6]
  			lock_et.text = theDist (if dcs[5] != undefined then dcs[5] else dcs[6])
  	fn updateHandlers = 
  		deleteAllChangeHandlers id:#distance_catcher
  		if (nodes = getCurrentNodes()).count > 0 do
  			when transform nodes change id:#distance_catcher handleAt:#redrawViews do updateDistance names:off
  			when name nodes change id:#distance_catcher do updateDistance values:off
  	on lock01_cb changed state do 
  		dcs[4][1] = if state then (getCurrentNodes())[1] else undefined
  	on lock02_cb changed state do 
  		dcs[4][2] = if state then (getCurrentNodes())[2] else undefined
  	on units_rb changed state do 
  		dcs[3] = state
  		updateDistance names:off
  	on lock_cb changed state do 
  		dcs[5] = if state then dcs[6] else undefined
  		updateDistance names:off
  	on Distance_Catcher_Rol close do 
  		deleteAllChangeHandlers id:#distance_catcher
  		callbacks.removescripts id:#distance_catcher
  		dcs[1] = getdialogpos Distance_Catcher_Rol
  	on Distance_Catcher_Rol open do 
  		deleteAllChangeHandlers id:#distance_catcher
  		callbacks.removescripts id:#distance_catcher
  		callbacks.addscript #selectionSetChanged "Distance_Catcher.updateHandlers()" id:#distance_catcher
  		callbacks.addscript #unitsChange "Distance_Catcher.updateDistance unitsonly:on" id:#distance_catcher
  Distance_Catcher = Distance_Catcher_Rol
  createdialog Distance_Catcher pos:Distance_Catcher_Settings[1]

the tools displays the distance between two selected (or/and locked) nodes. The node names, distance value, and distance value units updates in real-time using events system:
– names changed
– transforms changed
– selection changed
– units changed

the drawing lines between checked nodes was not my point. it’s easy to find a good sample about this matter.


My script is ready. You can find it here.


do you show spline’s length in you tool? or am i guessing wrong?


Yes. The tool shows spline length(also length for selected segment)


I don’t know whether to thank you all or give up lol

So thank you everyone, I’ll continue to work on my lowly little script by stealing from you all and trying to understand callbacks. I’ve been plowing through the help file and MAXScript Essentials.

Originally it was thrown together as an alternative to assigning a shortcut to the tape so yes a lot of try catch’s and bad, very bad code.

I’m humbled, jealous and have a headache!