Notifications
Clear all

[Closed] MAX_Script_Help – > Rotating Objects With a Slider

OK,

I know what you are thinking… “Why?..” Its a lighting programming thing.

Here is where I am stuck, I have a small script that can change the rotation information of an object on a slider,

Here is the code:

try(destroyDialog test)catch()

rollout test “Test” width:188 height:65
(

slider sld30 "Position " pos:[13,8] width:165 height:44 range:[-10,10,0] ticks:20

on sld30 changed val do
(
 macros.run "Tools" "Rotate"
 rotate $ (angleaxis 8 [0,0,0]) 
)

)
Createdialog Test

Problem here is I would like it to start from a zero position in the middle of the slider, and rotate in one direction if the slider is moved to the right, or a positive rotation if it is moved to the left. (or vise versa, does not matter) Ultimately it would be awesome if it wasn’t on a slider at all but on a wheel, like the attached image.

That is way down the road though, if at all possible.

Thanks in advance!

8 Replies

You have a fantastic post by DenisT about rotating with sliders here:
http://forums.cgsociety.org/showthread.php?f=98&t=1383632

For a ‘wheel’ instead of a ‘slider’, perhaps you can use Angle UI. Here’s an example of use:


	rollout test "Angle Test"
	(
		fn formattedvalue wheel =
		(
			angValue = if wheel > 180 then (formattedPrint (wheel-360) format:" 1.2f") else (formattedPrint (wheel) format:" 1.2f")
			return ("Angle: " + angValue + "º")
		)
			
		label		angText 	"" align:#left
		Angle 	ang 		"" diameter:80 align:#center range:[0,360,0] startdegrees:270 dir:#cw color:blue
		spinner 	spn 		"" fieldwidth:60 align:#center range:[0,360,0]
			
		on test open do
		(
			angText.text = formattedvalue ang.degrees
		)

		on ang changed val do
		(
			angText.text = formattedvalue ang.degrees
			spn.value = val
		)

		on spn changed val do
		(
			ang.degrees= val
			angText.text = formattedvalue ang.degrees
		)

	)

	createdialog test 200 130

Hey Aaandres

I like this solution a lot, it does represent a negative angle vs a positive one, this is to control a yoked fixture so it makes sense. Where 0 represents a 90 degree position. I am still stuck on getting the rotation to end at 0 and begin to rotate in the opposite direction.

Example: If I rotate the blue wheel to the left so that it becomes a negative number on the wheel, the rotate tool will spin the object to the left. If I rotate the blue wheel to the right so that the number becomes a positive number the rotate tool will spin the object to the right.

Here is how I edited the code to rotate the objects based on the wheel.

rollout test “Angle Test”
(
fn formattedvalue wheel =
(
angValue = if wheel > 180 then (formattedPrint (wheel-360) format:” 1.2f”) else (formattedPrint (wheel) format:” 1.2f”)
return (“Angle: ” + angValue + “º”)
)

	label		angText 	"" align:#left
	Angle 	ang 		"" diameter:80 align:#center range:[0,360,0] startdegrees:270 dir:#cw color:blue
	spinner 	spn 		"" fieldwidth:60 align:#center range:[0,360,0]
		
	on test open do
	(
		angText.text = formattedvalue ang.degrees
	)

	on ang changed val do
	(
		angText.text = formattedvalue ang.degrees
		spn.value = val
	    macros.run "Tools" "Rotate"
		rotate $ (angleaxis 2 [0,0,0]) 
	)

	on spn changed val do
	(
		ang.degrees= val
		angText.text = formattedvalue ang.degrees
		macros.run "Tools" "Rotate"
		rotate $ (angleaxis 2 [0,0,0]) 
	)

)

createdialog test 200 130

please put you code between “code tags”. it’s easy to do in the edit message window -> just select a code and press toolbar button #

thanks

Will do, my bad.

Here’s an example for local Z axis rotation.
You should read DenisT functions in the above link to make global and local rotation functions. In fact, rotations in 3dsMax are something impossible for me.


	rollout test "Angle Test"
	(
		fn angleValue wheel =
		(
			if wheel > 180 then (wheel-360) else wheel
		)
		
		fn formattedvalue wheel =
		(
			angValueText = formattedPrint wheel format:" 1.2f"
			return ("Angle: " + angValueText + "º")
		)
		
		local originTM = Matrix3 1
		fn rotateLocalZ rot_z node: = 
		(
			if node == unsupplied do node = selection[1]
			if isvalidnode node do
			(
				tm = copy originTM
				refPos = originTM.position
				tm.position = [0,0,0]
				prerotateZ tm rot_z
				tm.position += refPos
				node.transform = tm
			)
		)		
			
		label		angText 	"" align:#left
		Angle 	ang 		"" diameter:80 align:#center range:[0,360,0] startdegrees:270 dir:#cw color:blue
		spinner 	spn 		"" fieldwidth:60 align:#center range:[0,360,0]  scale:0.5
			
		on test open do
		(
			wheel = angleValue ang.degrees
			angText.text = formattedvalue wheel
			
			node = selection[1]
			if isvalidnode node do originTM = copy node.transform
		)

		on ang changed val do
		(
			wheel = angleValue ang.degrees
			angText.text = formattedvalue wheel
			spn.value = val
			
			rotateLocalZ wheel
		)

		on spn changed val do
		(
			ang.degrees= val
			wheel = angleValue ang.degrees
			angText.text = formattedvalue ang.degrees
			
			rotateLocalZ wheel
		)

	)

	createdialog test 200 130


i see that i didn’t show how to make it undoable…
well. here is another ‘master class’


try (destroydialog RotateWhatSelected) catch()
rollout RotateWhatSelected "Rotate What Selected" width:300
(
	radiobuttons axis_rb labels:#("X   ", "Y  ", "Z  ") align:#center
	slider rotate_sl width:284 range:[-180, 180, 0] scale:0.1 type:#float
	
	local working_val = 0 
	local axis 
	fn getAxis = case axis_rb.state of 
	(
		1: x_axis
		2: y_axis
		3: z_axis
	)
		
	on rotate_sl changed val do
	(
		in coordsys local 
		(
			for node in selection as array do 
			(
				rotate node (angleaxis (val - working_val) axis)
			)
		)
		working_val = val
 	)
	on rotate_sl rightclick do
	(
		theHold.Cancel()
		redrawviews()
		rotate_sl.value = 0
		working_val = 0
		theHold.Begin()
	)
	on rotate_sl buttondown do
	(
		axis = getAxis()
		
		theHold.Begin()
		working_val = 0
	)
	on rotate_sl buttonup do
	(
		if theHold.Holding() do theHold.Accept "RotateWhatSelected"
		working_val = 0
		rotate_sl.value = 0
	)
)
createdialog RotateWhatSelected

(ps. i’m sure someone can do it better to give me a master class)

Homework for an enthusiast:

modify the code above to make it ‘animatably’ correct

(as you ca see the code can animate, but animates whole rotattion (not x,y,z), which makes key-to-key interpolation not by component).

expecting that all nodes have Euler_XYZ controller is not excepted!

Hey denisT

This is impressive, It works just as expected. I dont need the Z axis so I have eliminated that from the script and renamed X to be “Pan” and Y to be “Tilt” as how you would operate a yoked lighting instrument. I am learning a lot from the help that I am getting through this thread.

Thank you for solving this problem for me!

I have a few others that are simply just too far out there for me to even attempt if you are interested. There are some actions I would like to automate but they dont show any feedback in the listener window. I will post these on separate threads.