Tape helper script

HI

I’m trying to make the written text in a text shape object display the value from a tape helper object, ie the distance value from the tape helper?

I cant seem to link the two parameters and haven’t found a solution on the internet yet. Does anyone have any ideas?

Many thanks,

Mark

It’s not very difficult to link a tape’s length to a text object’s text.

If you run this in an empty scene it should create a linked tape and text object.

(
	theTape = tape pos:[0,0,0] target:(targetObject pos:[0,100,0])
	theText = text size:10 pos:[25,0,0]
	theText.text = (distance theTape theTape.target) as string

	when transform theTape changes id:#tape2text handleAt:#redrawViews do
	(
		theText.text = (distance theTape theTape.target) as string
	)
)

/*
Type this into the MAXScript listener to break the link
deleteAllChangeHandlers id:#tape2text
*/

How exactly did you want it to work?

Cool solution Dan! I gave it a stab & had the same principle but I’ve never been able to get my head around callbacks, they make my brain hurt :frowning:

Thanks, too many callbacks can slow your scene down as well but in this case I think it’s the only solution.

Thanks Dan, only simple if you know how!!

Works a treat, just the job.

On a slightly connected note! I wouldn’t mind a similar thing but having a text object display the rotation of a camera/object in Z, ie 275 degrees/or just the rotation value from the Z as I cant work out how to get max to display rotations in degrees.

Many thanks,

Try the DegToRad and RadToDeg functions - max works in radians internally.

Here’s an edited version for camera rotation.

(
	theCam = VRayPhysicalCamera pos:[0,0,0] targeted:false
	camr = eulerangles 90 0 0
	rotate theCam camr
	theText = text size:10 pos:[25,0,0]
	theText.text = ((quatToEuler2 (theCam.transform.rotationPart)).z) as string

	when transform theCam changes id:#cam2text handleAt:#redrawViews do
	(
		theText.text = ((quatToEuler2 (theCam.transform.rotationPart)).z) as string
	)
)

/*
Type this into the MAXScript listener to break the link
deleteAllChangeHandlers id:#cam2text
*/

How are you using these, are you writing your own script?

Thanks Dan, no, they are both just for info when we’re setting up cameras, distance to target, camera bearing etc for the architect mainly!

Just tried the script, works great. Is there a way that the script could be applied to a camera already made, with any name?

I wish I knew scripting!!

Thanks again,
Mark

Thanks Jo, I wonder if this script could be made to do the conversion of RadToDeg as part of its internal process?

I dont suppose max can be made to display in degrees in its spinners! Would be nice.

Sorry Mark i haven’t got time to do this properly. I’ve modified the script so that if you run the script then click on a camera it adds a text object to that camera. You can then repeat this for any number of cameras now.

(
	fn camFil cam =
	(
		superClassOf cam == camera
	)

	theCam = pickObject filter:camFil
	theCamHand = GetHandleByAnim theCam
	theText = text name:(theCam.name+" Angle") size:10 pos:(theCam.pos+[25,0,0])
	theText.parent = theCam
	theTextHand = GetHandleByAnim theText
	theText.text = formattedPrint ((quatToEuler2 (theCam.transform.rotationPart)).z) format:"0.3g"

	when transform (GetAnimByHandle theCamHand) changes id:#cam2text do
	(
		if IsValidNode (GetAnimByHandle theTextHand) then
		(
			(GetAnimByHandle theTextHand).text = formattedPrint ((quatToEuler2 ((GetAnimByHandle theCamHand).transform.rotationPart)).z) format:"0.3g"
			rotate (GetAnimByHandle theTextHand) (inverse (GetAnimByHandle theTextHand).rotation)
		)
	)
)

/*
Type this into the MAXScript listener to break the link
deleteAllChangeHandlers id:#cam2text
*/

This really isn’t a very good solution though.

I wrote one as well that I love. It’s quick and not fancy at all, because I wrote it on set for a shoot and didn’t have much time. Just click the script, and then draw a line (just like a normal) spline. It will put the measurements in between each segment of the line. No callbacks, no frills. Redraw your line if you mess up.

Enjoy,
Colin


macroScript measureHelper category:"ColinScripts" tooltip:"Measure Helper" Icon:#("Helpers",5) (
(
    global theDist, groupNode, getRotateAngles

    fn setColor o = o.wirecolor = green

    fn getRotateAngles = (
        -- Orient the text correctly
        case viewport.getType() of (
            #view_bottom: (eulerAngles 180 0 0)
            #view_right: (eulerAngles 90 0 90)
            #view_left: (eulerAngles 90 0 -90)
            #view_front: (eulerAngles 90 0 0)
            #view_back: (eulerAngles 90 0 180)
            default: (eulerAngles 0 0 0)
        )
    )

    tool placeText prompt:"Select Placement for Text" numPoints:1 (
        local b
        on mousePoint clickno do (
            if clickno == 1 then b = text pos:worldPoint text:(theDist as string) size:5 else #stop
            b.wirecolor = green

            -- Orient the text correctly
            rotate b getRotateAngles()

            attachNodesToGroup b groupNode
        )
    )

    local measureLine = startObjectCreation line returnNewNodes:true newNodeCallback:setColor

    measureLine = measureLine[1]

    if measureLine != undefined and (numKnots measureLine) >= 2 then (
        -- Measure the distance between knots
        local pt, prevpt

        groupNode = group measureLine name:(uniqueName "Measure Group")
        1
        for k = 1 to (numKnots measureLine) do (
            pt = (getKnotPoint measureLine 1 k)

            -- Create Dummies at the knots
            d = dummy pos:pt name:(measureLine.name+"_knot_"+k as string) scale:[.2,.2,.2]
            attachNodesToGroup d groupNode

            if k > 1 then (
                theDist = distance prevpt pt

                local midpt = point3 ((prevpt.x + pt.x)/2) ((prevpt.y + pt.y)/2) ((prevpt.z + pt.z)/2)

                local distanceText = text pos:midpt text:(theDist as string) size:5
                distanceText.wirecolor = green
                rotate distanceText (getRotateAngles())

                attachNodesToGroup distanceText groupNode

                --messageBox ("Click for Text Placement: " + (k-1) as string + " of " + (((numKnots measureLine)-1) as string))
                --starttool placeText

                --format "distance between % and %: %\n" prevpt pt (distance prevpt pt)
            )

            prevpt = pt
        )
    ) else
        messageBox "Problem with created Measuring Spline, undefined or less than 2 knots."

)
)

Hey thanks for posting this Colin! Just been trying it and works really well. I will have to make the text larger as we work in mm but I can definitely see myself using it. Surprising that there isn’t something like this in Max already really.

@m_hinks Did the last script do want you wanted it to?

Dan

It saves me tons of time when I have to do print screens of measurements (which isn’t often), but man it’s amazing for that.

Hi Colin, yes its very useful, I can see that coming in handy.

Dan, thanks again. It is perfect for the job, except for one thing which I just found out! I have made a template file with a couple of these tapes so I can merge into files where I need it. But the script seems to be getting lost when I merge to a new scene? I’m not sure if there is any way to add the script to the new scene, or whether the method of linking the text to the length can be done on the object?

Thanks again, its very useful!
Mark

No, the when construct that I used won’t survive merging into a different scene or even saving and reopening the scene.
Here’s a different way of linking the text tape which should at least survive the scene being saved and reloaded. Not tested merging though.

(
	theTape = tape pos:[0,0,0] target:(targetObject pos:[0,100,0])
	theText = text size:10 pos:[25,0,0] wirecolor:yellow

	textCtrl = float_script()
	textCtrl.addNode "theText" theText
	textCtrl.addNode "theTape" theTape
	textCtrl.addNode "theTarg" theTape.target

	textCtrl.SetExpression "theText.text = (distance theTape theTarg) as string\n theText.pos = theTape.center\n0"
	theText.kerning.controller = textCtrl
)

Just tested merging and it does work.