Notifications
Clear all

[Closed] Local Offset Transforms

Alright, just when I thought I was getting the hang of this…I get hung up on something that seems so simple and end up wanting to throw my computer out the window :banghead:

I am basically trying to script the same exact behavior as when you spin the Z Offset:Local spinner in the move transform type-in dialog.

A bonus would be the same behavior as the Look At: Dolly spinner in the same dialog since I am also performing these transoforms moves on target cameras.

Basically I have this…
on sp03 changed val do (in coordsys #local Cam01.pos.z = val)
which is acting very weird because the local position gets set to 0 each time the spinner increments.

I’m not getting anywhere with the support docs other than even more confused and worried about when I get to the rotation part 😮

6 Replies

which is acting very weird because the local position gets set to 0 each time the spinner increments.

This makes sense because an object’s position relative to itself (local) is always [0,0,0]. The transform type-in displays the offset between its current position and prior position when you first pressed your mouse down, hence why it doesn’t reset to [0,0,0] until you release the mouse during a spinner drag. In a maxscript rollout, however, where you are changing the object’s position each time the value changes, the local position is being updated during each change and so your changes are incremental, rather than relative to a starting point.

If you want to recreate the behavior of the transform type-in in a spinner in your own rollout, you’ll need to capture the initial mouse down event on the spinner (and cache the initial position at that point), then during subsequent value changes while dragging the mouse, set the object’s position to the cached value + the spinner value (doing the proper coordinate conversion). Then on mouse release, set the spinner back to zero. You can do this with buttondown/buttonup events.

Here’s a sample script showing you how to do that. Select an object, run the script, then adjust the spinner and watch the object move along the z-axis in local space the same way it does when using the transform type-in:


try(destroydialog zMover)catch()

rollout zMover "zMover"	
(
	local startPos = [0,0,0]
	local dragging = false
	
	spinner zVal range:[-100000,100000,0]
	
	on zVal entered do
	(
		if not dragging then
		(
			in coordsys local $.pos.z = zVal.value
			zVal.value = 0
		)
	)
		
	on zVal buttonDown do
	(
		dragging = true; startPos = $.position
	)
	
	on zVal buttonUp do
	(
		dragging = false; zVal.value = 0
	)
	
	on zVal changed val do
	(
		if dragging then
		(			
			localPos = (startPos * (inverse $.transform)) + [0,0,zVal.value] --convert startPos to local space and add our spinner value to the z-Axis
			$.pos = localPos * $.transform --convert the resulting position back to world space and assign it to the object
		)
	)
	
)

createdialog zMover


There are several different ways of doing it. A simple one could be as follow:

(
 	try (destroydialog ::RO_TEST)catch()
 	rollout RO_TEST "" width:142 height:32
 	(
 		spinner spn_offset "Offset Z:" pos:[8,8] fieldwidth:72 range:[-1E9,1E9,0]
 		
 		local camPos, camDir
 		
 		on spn_offset changed val do
 		(
 			if camPos == undefined do
 			(
 				camPos = $.pos
 				camDir = $.dir
 			)
 			$.pos = camPos + (camDir*val)
 		)
 		
 		on spn_offset entered do
 		(
 			spn_offset.value = 0
 			camPos = undefined
 		)
 		
 	)
 	createdialog RO_TEST
 )

Bonus:

(
 	try (destroydialog ::RO_TEST)catch()
 	rollout RO_TEST "" width:142 height:64
 	(
 		spinner spn_offset "Offset Z:" pos:[ 8, 8] fieldwidth:72 range:[-1E9,1E9,0]
 		spinner spn_dolly  "Dolly:"	pos:[25,32] fieldwidth:72 range:[0,1E9,0]
 		
 		local camPos, camDir, camDolly
 		
 		fn UpdateCameraPos val dolly:false =
 		(
 			if camPos == undefined do
 			(
 				camPos = $.pos
 				camDir = $.dir
 				camDolly = $.targetDistance
 			)
 			
 			if dolly do val -= camDolly
 			
 			$.pos = camPos + (camDir*val)
 			spn_dolly.value = $.targetdistance
 		)
 		
 		on spn_offset entered do
 		(
 			spn_offset.value = 0
 			camPos = undefined
 		)
 		
 		on spn_offset changed val do UpdateCameraPos val
 		
 		on spn_dolly entered do camPos = undefined
 			
 		on spn_dolly changed val do UpdateCameraPos val dolly:true
 	)
 	createdialog RO_TEST
 )

You can also do it storing the initial camera transform and modifying it later.

Note that none of the above codes handle undo and updates when camera is selected or modified. To handle them it would require a little more of work.

Hey guys,
Thank you both so much for responding. I’m busy on admin stuff this morning but hope to get back on this after lunch today.

I did get the following sort of working last night but it feels a little hacky so I’m eager to compare it to what you guys posted here when I can wrap my head around it. Thanks again and I’ll follow up later today.

on sp03 changed val do (Cam01.objectoffsetpos = [0,0,val])	
on sp03 entered do (ResetPivot Cam01; Sp03.value=0)

let me show my variant which solves some issues (multi-selection, undo/redo):

try(destroydialog MovinZ) catch()
rollout MovinZ "Move In Z" width:200 height:50
(
	spinner move_sp "Move Value: " type:#worldunits range:[-1e9,1e9,0] fieldwidth:68 align:#center offset:[0,15]
	
	local moving_value = 0
	on move_sp buttondown do 
	(
		moving_value = 0
	)
	on move_sp changed val do
	(
		if not thehold.holding() do thehold.Begin()
		in coordsys local move selection [0,0, val - moving_value] 
		moving_value = val
	)
	on move_sp entered arg can do 
	(
		if thehold.holding() do
		(
			if can then thehold.Cancel() 
			else thehold.Accept "MovinZ"
		)
		move_sp.value = moving_value = 0
	)
)
createdialog MovinZ
1 Reply
(@polytools3d)
Joined: 11 months ago

Posts: 0

In the Max Transform Type-In tool:

You can’t change the dolly value of more than 1 camera at the time.

If you reach the 0.0 targetDistance, the camera keeps moving in opposite direction.

Wow guys, I just ran all of these and this is amazing – thank you! I was suprised how little showed up when googling the subject line of this thread so I think this is going to help a lot of people over time. It is also cool to see several different ways of solving the same exact problem. Rather than just copy pasting them, I’m going to go through each carefully and then write my own so I really understand it but I can’t thank you all enough.