Notifications
Clear all

[Closed] Newbie Questions – Where do I look?

Very interesting. Also, useful.

Does that mean that if you want to access a variable control within a rollout from outside the maxscript you have to “stack” additional locators?

By which I mean something like

myscript.myfloaterrollout.myrollout.myvariable.control

Or are they simply inaccessible?

2 Replies
(@rustyknight)
Joined: 11 months ago

Posts: 0

Ahhh, no, but yes…

You don’t need to specifiy the script, but you do need to make sure it’s within it’s current context…ie you’ve included the parent script so that the current script knows about it somehow…this is the tricky part

(@bobo)
Joined: 11 months ago

Posts: 0

The only thing you cannot access is a MacroScript’s body. Thus, you have to define the rollout as a global variable, then you can access anything inside incl. functions, controls and their event handlers from other scripts or the Listener.

MacroScript someMacro category:"Some Category"
 (
 global Somerollout
 rollout Somerollout "Somerollout" 
 (
button someButton "Press me!"
on someButton pressed do print "Pressed!"
 )
 createDialog Somerollout
 )

--press the icon to open the rollout, then type

Somerollout.somebutton.pressed()

Within a MacroScript, you can also declare all local variables used within the code in the BEGINNING of the Macro definition – this will make them visible to any code inside the Macro’s body.

MacroScript someMacro category:"Some Category"
 (
 local SomeVariable
 local anotherVariable
 rollout Somerollout "Somerollout" 
 (
 fn someFunction =
 (
 SomeVariable = 10
 anotherVariable = "Some String"
 )
 
 button someButton "Press Me"
 on someButton pressed do
 (
 someFunction()
 print SomeVariable 
 print anotherVariable 
 )
 )
 createDialog Somerollout
 )

Thanks Bobo! As always, lots of useful information!!

Shane

Thanks Bobo! As always, lots of useful information!!

Shane

Thanks again. Very useful.

I was pretty busy today, but I’ll post my completed little tool tomorrow.

Huzzah!

I have another question however. Today I was messing around with rigging and how I could optimize my rigging through using maxscript (even simple macro’s are amazingly efficient).

I was wondering if it were possible to wire a value from an object (like… Xrotation) to a spinner or control in a scripted rollout. I know that you could simply script the -effect- of the spinner, but I imagine it would be cleaner if you could use pre-existing systems.

Are there any functions that can do anything like this or is this a pipe-dream?

Hello again.

I’ve finished my locking mechanism. You can gaze upon it’s code here:


macroScript BigLock category: "Testing"
(
	on isEnabled return
	(
		selection.count == 1
	)
	on execute do
	(
		function newkeyhole shifter =
		global keyhole = $
		global lockarray = getTransformLockFlags (keyhole)
		rollout lock_rol "Locks"
		(
			button lock "Lock All" width:77
			button unlock "Unlock All" width:77
	
			checkbutton posx "X" checked:lockarray[1] across:3 offset:[0,13]
			on posx changed state do
			(
				lockarray[1] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton posY "Y" checked:lockarray[2]offset:[0,13]
			on posY changed state do
			(
				lockarray[2] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton posZ "Z" checked:lockarray[3]offset:[0,13]
			on posZ changed state do
			(
				lockarray[3] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton rotX "X" checked:lockarray[4] across:3 offset:[0,20]
			on rotX changed state do
			(
				lockarray[4] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton rotY "Y" checked:lockarray[5] offset:[0,20]
			on rotY changed state do
			(
				lockarray[5] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton rotZ "Z" checked:lockarray[6] offset:[0,20]
			on rotZ changed state do
			(
				lockarray[6] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton scaleX "X" checked:lockarray[7] across: 3 offset:[0,20]
			on scaleX changed state do
			(
				lockarray[7] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton scaleY "Y" checked:lockarray[8] offset:[0,20]
			on scaleY changed state do
			(
				lockarray[8] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton scaleZ "Z" checked:lockarray[9] offset:[0,20]
			on scaleZ changed state do
			(
				lockarray[9] = state
				setTransFormLockFlags keyhole lockarray
			)
	
			groupBox posbox "Position" pos:[10,57] width: 87 height: 42
			groupBox rotbox "Rotation" pos:[10,103] width: 87 height: 42
			groupBox scalebox "Scale" pos:[10,149] width: 87 height: 42
			
			on lock pressed do
			(
				posx.checked=true
				posy.checked=true
				posz.checked=true
				rotx.checked=true
				roty.checked=true
				rotz.checked=true
				scalex.checked=true
				scaley.checked=true
				scalez.checked=true
				setTransformLockFlags keyhole #all
			)
			on unlock pressed do
			(
				posx.checked=false
				posy.checked=false
				posz.checked=false
				rotx.checked=false
				roty.checked=false
				rotz.checked=false
				scalex.checked=false
				scaley.checked=false
				scalez.checked=false
				setTransformLockFlags keyhole #none
			)
		)
		big_lock_float=newrolloutfloater "Big Lock" 120 230
		addrollout lock_rol big_lock_float
	)
)

It’s working now, which is good, but I don’t think it’s terribly elegant in execution. Is there a way to optimize this? Is it unnecessarily large?

I am also working on a wiring tool to increase the speed at which I can do simple wiring.

It’s… almost working. I decided that the best way for me to automate the input of a complex command would be to build a string that contained the code I wanted, and then to execute that code.

Unfortunately, the execute function seems to be… broken? It just doesn’t work. When I type in the code that my tool gives me, it works, but when I try to execute the script that contains EXACTLY the same code, it gives me this error:

>> MAXScript Wire Controller Exception: -- Unable to convert: undefined to type: Float <<
>> MAXScript Wire Controller Exception: -- Unable to convert: undefined to type: Float <<

I have no idea what it’s doing or why. Could someone tell me why executre (string) doesn’t work? Am I missing something? Any help would be deeply appreciated as this is kinda driving me nuts.

Here is what I have so far.

global mainrollout

rollout mainrollout "Wire Tool"
(
	--The "WireThem" function builds a string based on the state of the UI. It then
	--executes that string to wire the objects together.
	
	function wirethem = 
	(
		global connectstring

		global string_selection
		global string_select_plane	
	
		global string_target
		global string_target_plane
		
		global string_selfact = " \"" + mainrollout.selectfactor.text + "\""
		global string_tarfact = " \"" + mainrollout.targetfactor.text + "\""
		
		case mainrollout.selectplane.selection of
		(
			1: (string_select_plane = "[#X")
			2: (string_select_plane = "[#Y")
			3: (string_select_plane = "[#Z")
		)

		case mainrollout.selectparam.selection of
		(
			1: string_selection = " $.pos.controller" + string_select_plane + "_Position]"
			2: string_selection = " $.rotation.controller" + string_select_plane + "_Rotation]"
			3: string_selection = " $.transform.controller[#Scale]"
		)
		
		case mainrollout.targetplane.selection of
		(
			1: (string_target_plane = "[#X")
			2: (string_target_plane = "[#Y")
			3: (string_target_plane = "[#Z")
		)
		
		case mainrollout.targetparam.selection of
		(
			1: string_target = " $" + mainrollout.grabit.object.name + ".pos.controller" + string_target_plane + "_Position]"
			2: string_target = " $" + mainrollout.grabit.object.name + ".rotation.controller" + string_target_plane + "_Rotation]"
			3: string_target = " $" + mainrollout.grabit.object.name + ".transform.controller[#Scale]"
		)
		
		connectstring = "macros.run \"Parameter Wire\" \"paramWire\"
"
		
		case mainrollout.connectwire.state of
		(
			1: connectstring += "paramWire.connect" + string_target + string_selection + string_tarfact
			2: connectstring += "paramWire.connect" + string_selection + string_target + string_selfact
			3: connectstring += "paramWire.connect2way" + string_selection + string_target + string_selfact + string_tarfact
		)
		
		print connectstring
		
		execute connectstring
	)

	function selectiontextswitch = 
	(
		global plane
	
		case mainrollout.selectplane.selection of
		(
			1: plane = "X"
			2: plane = "Y"
			3: plane = "Z"
		)
		
		case mainrollout.selectparam.selection of
		(
			1: mainrollout.selectfactor.text = plane + "Position"
			2: mainrollout.selectfactor.text = plane + "Rotation"
			3: mainrollout.selectfactor.text = "Scale"
		)
	)

	function targettextswitch = 
	(
		global plane
	
		case mainrollout.targetplane.selection of
		(
			1: plane = "X"
			2: plane = "Y"
			3: plane = "Z"
		)
		
		case mainrollout.targetparam.selection of
		(
			1: mainrollout.targetfactor.text = plane + "Position"
			2: mainrollout.targetfactor.text = plane + "Rotation"
			3: mainrollout.targetfactor.text = "Scale"
		)
	)

	-- This area defines the UI
	listbox selectparam items: #("Position", "Rotation", "Scale") across: 2 height: 3 width: 80 offset: [3,15]
	listbox selectplane items: #("X", "Y", "Z") height: 3 width: 80 offset: [4,15]
	edittext selectfactor "Factor:" text: "XPosition"
	
	pickbutton grabit "Select A Target" tooltip: "Pick an object" offset: [0,8] width: 189 
	radiobuttons connectwire labels:#("Up", "Down", "Mix") columns: 3
	
	listbox targetparam items: #("Position", "Rotation", "Scale") across: 2 height: 3 width: 80 offset: [3,15]
	listbox targetplane items: #("X", "Y", "Z") height: 3 width: 80 offset: [4,15]
	edittext targetfactor "Factor:" text: "XPosition"
	
	groupbox groupselect "Selection" pos:[5,5] width: 189 height: 90
	groupbox grouptarget "Target" pos:[5,146] width: 189 height: 90
	
	button linkit "Link" width: 92 offset: [-5,0] across: 2
	button breakit "Break" width: 92 offset: [5,0]

	-- Calling functions and pressing buttons

	on selectparam selected useless do selectiontextswitch()
	on selectplane selected useless do selectiontextswitch()
	on targetparam selected useless do targettextswitch()
	on targetplane selected useless do targettextswitch()
	
	on grabit picked obj do
		if isValidNode obj do grabit.tooltip = "Current Selection: " + obj.name
	
	on linkit pressed do if grabit.object != undefined do wirethem()
	
)
createdialog mainrollout 200 267

Thank you in advance.

Hi Context!

Some nice work there my friend!

Personally, I wouldn’t place ALL the functions and rollouts within the execute event handler, but that’s just me. It might be better to put them within the body of the macroscript


  macroscript ... (
    -- Add functions that need to be accessed by both the macroscript and the roll outs...
    fn myBigFatFunction ... (
    )
  
    rollout ... (
  	-- Add functions relevent to the rollout only
    )
  
    on execute do (
  	big_lock_float=newrolloutfloater "Big Lock" 120 230
  	addrollout lock_rol big_lock_float
    )
  )
  

I would also make “big_lock_float” global so you can dispose of any existing rollouts that might still be hanging around when the macroscript is re-run…ie


  macroscript ... (
    global big_lock_float -- note that we don't apply a value to it!  This is important...
  
    on execute do (
  	if big_lock_float != undefined do closerolloutfloter big_lock_float
  
  	-- Reinitalise the rollout here and continue on...
    )
  )
  

But that’s just me…I like to try and stay clean!

I am also working on a wiring tool to increase the speed at which I can do simple wiring.

Please let me say, that this tool is really cool! You’ve really done a great job on it and you going to slap you’re self when you discover why it won’t work…

Firstly, lose

connectstring = "macros.run \"Parameter Wire\" \"paramWire\"
"

It is simply not doing what you want and you don’t need it for what you are trying to do…

I would also change the global variables listed in the “wirethem” function to local. I had some interesting issues while testing the code, with the connectstring gradually getting longer and longer because it was maintaining a context out side of the script. And as far as I can tell, they don’t need to be. They only have relevance within the context of the function…


  		global connectstring
  
  		global string_selection
  		global string_select_plane	
  	
  		global string_target
  		global string_target_plane
  		
  		global string_selfact = " \"" + mainrollout.selectfactor.text + "\""
  		global string_tarfact = " \"" + mainrollout.targetfactor.text + "\""
  

But now, onto the crust of the problem.

The real issue you are having is within the “expression” part of the paramwire interface…

Currently, your connect string is reading something like this:

paramWire.connect $Box01.pos.controller[#X_Position] $.pos.controller[#X_Position] "XPosition"

When you want it to read something like this:

paramWire.connect $Box01.pos.controller[#X_Position] $.pos.controller[#X_Position] "X_Position"

Can you spot the difference?

Look at the very last statement. Your code reads:
XPosition
When it should read:
X_Position

I know, it seems so small and insignificant, but there it is. Max does not know what “XPosition” is, because it is undefined, where as “X_Position” is the value of the controller, within the context of the expression editor.

So in the function “selectiontextswitch” you need to change the case statement to read


  		case mainrollout.selectparam.selection of
  		(
  			1: mainrollout.selectfactor.text = plane + "[b]_Position[/b]"
  			2: mainrollout.selectfactor.text = plane + "[b]_Rotation[/b]"
  			3: mainrollout.selectfactor.text = "Scale"
  		)
  

And, you need to change the controls “selectfactor” and “targetfactor” to


  edittext selectfactor "Factor:" text: "[b]X_Position[/b]"
  edittext targetfactor "Factor:" text: "[b]X_Position[/b]"
  

That should work. I’ve really knocked your code around during my testing, so I might have missed something, so if any one else sees something i’ve missed, please pipe in and let us know

And, I have to say context, you’ve done some really nice code! I like what you’ve done and I like the way you’ve done it! Very nice!

I would normally dis-encourage you from using the execute function where you can, as it is very slow in its opertation, but for you now, it should suffice.

Take a look at the paramWire interface in the docs for more info, but essentially, you’ve already been using it

Shane

Ha! Syntax is not my friend! Thank you very much for figuring that out. I would have smashed my brains out on that before realizing I was missing a single underscore.

The code I posted for my locking mechanism last time was an (inexplicalby) old version. I’m saving my scripts in two different locations (which is a bad move) so I accidentially posted an old and nonfunctional version. This one works! And it also does almost everything you suggested.

macroScript BigLock category: "Testing"
(
	global keyhole = $
	global lockarray = getTransformLockFlags (keyhole)
	global lock_rol
	global big_lock_float
	global rebuildlock

	function rebuildlock =
	(
		if $ != undefined do
		(
			keyhole = $
			lockarray = getTransformLockFlags (keyhole)
			lock_rol.posx.checked = lockarray[1]
			lock_rol.posy.checked = lockarray[2]
			lock_rol.posz.checked = lockarray[3]
			lock_rol.rotx.checked = lockarray[4]
			lock_rol.roty.checked = lockarray[5]
			lock_rol.rotz.checked = lockarray[6]
			lock_rol.scalex.checked = lockarray[7]
			lock_rol.scaley.checked = lockarray[8]
			lock_rol.scalez.checked = lockarray[9]
		)

		if big_lock_float.open != true do
		(
			callbacks.removescripts id:#biglocks
		)
	)
	
	callbacks.addScript #selectionSetChanged "rebuildlock()" id: #biglocks persistent: false
	
	on isEnabled return
	(
		selection.count == 1
	)
	on execute do
	(
		rollout lock_rol "Locks"
		(
			button lock "Lock All" width:77
			button unlock "Unlock All" width:77
	
			checkbutton posx "X" checked:lockarray[1] across:3 offset:[0,13]
			on posx changed state do
			(
				lockarray[1] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton posY "Y" checked:lockarray[2]offset:[0,13]
			on posY changed state do
			(
				lockarray[2] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton posZ "Z" checked:lockarray[3]offset:[0,13]
			on posZ changed state do
			(
				lockarray[3] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton rotX "X" checked:lockarray[4] across:3 offset:[0,20]
			on rotX changed state do
			(
				lockarray[4] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton rotY "Y" checked:lockarray[5] offset:[0,20]
			on rotY changed state do
			(
				lockarray[5] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton rotZ "Z" checked:lockarray[6] offset:[0,20]
			on rotZ changed state do
			(
				lockarray[6] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton scaleX "X" checked:lockarray[7] across: 3 offset:[0,20]
			on scaleX changed state do
			(
				lockarray[7] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton scaleY "Y" checked:lockarray[8] offset:[0,20]
			on scaleY changed state do
			(
				lockarray[8] = state
				setTransFormLockFlags keyhole lockarray
			)
			checkbutton scaleZ "Z" checked:lockarray[9] offset:[0,20]
			on scaleZ changed state do
			(
				lockarray[9] = state
				setTransFormLockFlags keyhole lockarray
			)
	
			groupBox posbox "Position" pos:[10,57] width: 87 height: 42
			groupBox rotbox "Rotation" pos:[10,103] width: 87 height: 42
			groupBox scalebox "Scale" pos:[10,149] width: 87 height: 42
			
			on lock pressed do
			(
				posx.checked=true
				posy.checked=true
				posz.checked=true
				rotx.checked=true
				roty.checked=true
				rotz.checked=true
				scalex.checked=true
				scaley.checked=true
				scalez.checked=true
				setTransformLockFlags keyhole #all
			)
			on unlock pressed do
			(
				posx.checked=false
				posy.checked=false
				posz.checked=false
				rotx.checked=false
				roty.checked=false
				rotz.checked=false
				scalex.checked=false
				scaley.checked=false
				scalez.checked=false
				setTransformLockFlags keyhole #none
			)
			
		)
		big_lock_float=newrolloutfloater "" 120 227
		addrollout lock_rol big_lock_float
	)
)

As for my wiring box. It works too! Hurrah!

I started having problems with collectstring getting bigger and bigger as well… so I just changed it’s initial definition to:

global connectstring = “”

Which works. Changing it to local caused a whole host of problems.

Here is the final code for my wiring doohicky. I think I might make icons for the “Up/Down/Mixed” section, but this is pretty much it.



global mainrollout

rollout mainrollout "Wire Tool"
(
	--The "WireThem" function builds a string based on the state of the UI. It then
	--executes that string to wire the objects together.
	
	function wirethem = 
	(
		global connectstring = ""

		global string_selection
		global string_select_plane	
	
		global string_target
		global string_target_plane
		
		global string_selfact = " \"" + mainrollout.selectfactor.text + "\""
		global string_tarfact = " \"" + mainrollout.targetfactor.text + "\""
		
		case mainrollout.selectplane.selection of
		(
			1: (string_select_plane = "[#X")
			2: (string_select_plane = "[#Y")
			3: (string_select_plane = "[#Z")
		)

		case mainrollout.selectparam.selection of
		(
			1: string_selection = " $.pos.controller" + string_select_plane + "_Position]"
			2: string_selection = " $.rotation.controller" + string_select_plane + "_Rotation]"
			3: string_selection = " $.transform.controller[#Scale]"
		)
		
		case mainrollout.targetplane.selection of
		(
			1: (string_target_plane = "[#X")
			2: (string_target_plane = "[#Y")
			3: (string_target_plane = "[#Z")
		)
		
		case mainrollout.targetparam.selection of
		(
			1: string_target = " $" + mainrollout.grabit.object.name + ".pos.controller" + string_target_plane + "_Position]"
			2: string_target = " $" + mainrollout.grabit.object.name + ".rotation.controller" + string_target_plane + "_Rotation]"
			3: string_target = " $" + mainrollout.grabit.object.name + ".transform.controller[#Scale]"
		)
						
		case mainrollout.connectwire.state of
		(
			1: connectstring += "paramWire.connect" + string_target + string_selection + string_tarfact
			2: connectstring += "paramWire.connect" + string_selection + string_target + string_selfact
			3: connectstring += "paramWire.connect2way" + string_selection + string_target + string_selfact + string_tarfact
		)
		
		-- print connectstring
		
		execute connectstring
	)
	
	
	--This function adds presets to the selectfactor box

	function selectiontextswitch = 
	(
		global plane
	
		case mainrollout.selectplane.selection of
		(
			1: plane = "X"
			2: plane = "Y"
			3: plane = "Z"
		)
		
		case mainrollout.selectparam.selection of
		(
			1: mainrollout.selectfactor.text = plane + "_Position"
			2: mainrollout.selectfactor.text = plane + "_Rotation"
			3: mainrollout.selectfactor.text = "Scale"
		)
	)

	--This function adds presets to the targetfactor box

	function targettextswitch = 
	(
		global plane
	
		case mainrollout.targetplane.selection of
		(
			1: plane = "X"
			2: plane = "Y"
			3: plane = "Z"
		)
		
		case mainrollout.targetparam.selection of
		(
			1: mainrollout.targetfactor.text = plane + "_Position"
			2: mainrollout.targetfactor.text = plane + "_Rotation"
			3: mainrollout.targetfactor.text = "Scale"
		)
	)

	function shatter = 
	(
		$.pos.controller.X_Position.controller = bezier_float ()
		$.pos.controller.Y_Position.controller = bezier_float ()
		$.pos.controller.Z_Position.controller = bezier_float ()
 
		$.rotation.controller.X_Rotation.controller = bezier_float ()
		$.rotation.controller.Y_Rotation.controller = bezier_float ()
		$.rotation.controller.Z_Rotation.controller = bezier_float ()
		
		$.scale.controller = bezier_scale ()

	)

	-- This area defines the UI
	listbox selectparam items: #("Position", "Rotation", "Scale") across: 2 height: 3 width: 80 offset: [3,15]
	listbox selectplane items: #("X", "Y", "Z") height: 3 width: 80 offset: [4,15]
	edittext selectfactor "Factor:" text: "X_Position"
	
	pickbutton grabit "Select A Target" tooltip: "Pick an object" offset: [0,8] width: 189 
	radiobuttons connectwire labels:#("Up", "Down", "Mix") columns: 3
	
	listbox targetparam items: #("Position", "Rotation", "Scale") across: 2 height: 3 width: 80 offset: [3,15]
	listbox targetplane items: #("X", "Y", "Z") height: 3 width: 80 offset: [4,15]
	edittext targetfactor "Factor:" text: "X_Position"
	
	groupbox groupselect "Selection" pos:[5,5] width: 189 height: 90
	groupbox grouptarget "Target" pos:[5,146] width: 189 height: 90
	
	button linkit "Link" width: 92 offset: [-5,0] across: 2
	button breakit "Break" width: 92 offset: [5,0]

	-- Calling functions and pressing buttons

	on selectparam selected useless do selectiontextswitch()
	on selectplane selected useless do selectiontextswitch()
	on targetparam selected useless do targettextswitch()
	on targetplane selected useless do targettextswitch()
	
	on grabit picked obj do
		if isValidNode obj do grabit.tooltip = "Current Selection: " + obj.name
	
	on linkit pressed do if grabit.object != undefined do wirethem()
	on breakit pressed do if $ != undefined do shatter()
	
)
createdialog mainrollout 200 267

It’s pretty much the same as last time, except I added the “Shatter” function, which strips wiring parameters from an object by resetting it’s Assigned Controllers.

This has been fun so far, except for the feeling of being stabbed in the brain. The utility of being able to make my own tools does exceed my frustration. Thanks again for the help.

I am still wondering if it was possible to wire an object parameter to a spinner created in a Maxscript. I am making an… odd rig, and I was hoping to create it’s own floating rollout. Is this possible?

Oh yes… what alternatives to useing the Execute (string) function would you suggest? The only one I can think of is long lists of nested case statements. I gather the execute function is memory inefficient? How would I avoid using that statement, without having to add hundreds of more lines of code?

Thanks in advance!

With global variables, you need to ask yourself, do I want to access this variable outside of this scope?? ie The macroscript…

A problem you might run into later on, is if you reuse variable names, which is something we all do from time to time. So if you have two global variables with the same name, you are actually using the singal variable, which will cause no end of head aches and unexpected problems that are next to near impossible to solve…especially if another script by someone else is using that variable

As for my wiring box. It works too! Hurrah! 

Alright!

I started having problems with collectstring getting bigger and bigger as well... so I just changed it's initial definition to:

global connectstring = ""

Which works. Changing it to local caused a whole host of problems. 

Really? Worked okay for me. That would suggest to me that the connectstring value is been accessed out side the function or you are not initialising it properly…

Perhaps you need to move into the local scope of the rollout instead of the within the function?  That way it is always avaliable within in the rollout, but the WHOLE max environment...

But if you look at this section here:


   	case mainrollout.connectwire.state of
   		(
   			1: connectstring += "paramWire.connect" + string_target + string_selection + string_tarfact
   			2: connectstring += "paramWire.connect" + string_selection + string_target + string_selfact
   			3: connectstring += "paramWire.connect2way" + string_selection + string_target + string_selfact + string_tarfact
   		)
   

This is the only section I recall you assigning a value to the connect string. The problem I see here is ” += ” assignment. Which is basically appending the right side value to the connctstring, which may be undefined, unless (and you have) initialised it.

You could write it:


   	case mainrollout.connectwire.state of
    		(
    			1: connectstring [b]=[/b] "paramWire.connect" + string_target + string_selection + string_tarfact
    			2: connectstring [b]=[/b] "paramWire.connect" + string_selection + string_target + string_selfact
    			3: connectstring [b]=[/b] "paramWire.connect2way" + string_selection + string_target + string_selfact + string_tarfact
    		)
    

And since this is the main section you construct the string anyway, that should work.

I’m sorry, I’m very picky about variable scope, both from a memory point of view, but also from making sure that my variables don’t accidently get changed some where else in my code…oh the horror stories I can tell…

I am still wondering if it was possible to wire an object parameter to a spinner created in a Maxscript. I am making an... odd rig, and I was hoping to create it's own floating rollout. Is this possible?

Off the top of my head, yes, I’m sure it is, but I can’t recall how to do it right now…I’m suppose to be getting ready for work :P…I’ll pull up some old code from my rigging script and see what I did.

Oh yes... what alternatives to useing the Execute (string) function would you suggest? The only one I can think of is long lists of nested case statements. I gather the execute function is memory inefficient? How would I avoid using that statement, without having to add hundreds of more lines of code?

Sometimes, there isn’t one and to be honset for what you’ve done it works. It just tends to be very expensive from an execution point of view…

Instead of assigning all the values to strings, you keep references of the each of the object elements…

I have to get to work, so I will cut up the code there and post how I might do it then…

Shane

Okay, here is the “non execute” method;


    fn getSubAnimValue iType iSubAnim = (
  	/*
  	  local lstSubAnims = #(#(#X_Position, #Y_Position, #Z_Position),
  									#(#X_Rotation, #Y_Rotation, #Z_Rotation),
  									#(#X_Scale, #Y_Scale, #Z_Scale))
  	*/
   
  	-- Select the sub anim parameter based on the type
  	-- and "plane"
  	case iType of (
  	  1: 
  		case iSubAnim of (
  		  1: return #X_Position
  		  2: return #Y_Position
  		  3: return #Z_Position
  		)
  	  2: 
  		case iSubAnim of (
  		  1: return #X_Rotation
  		  2: return #Y_Rotation
  		  3: return #Z_Rotation
  		)
  	  3: 
  		case iSubAnim of (
  		  1: return #X_Scale
  		  2: return #Y_Scale
  		  3: return #Z_Scale
  	  )
  	)
   		
  	return undefined
    )
   	
    fn getController oNode iType = (
  	-- Get the object controller
  	case iType of (
  	  1: return oNode.pos.controller
  	  2: return oNode.rotation.controller
  	  3: return oNode.transform.controller
  	)
    )
   	
    -- Get the sub anim value that can be used by the
    -- param wire interface...ie node.pos.controller[#X_Position]
    fn getWireParameter oNode iType iSubAnim = (
  	return (getController oNode iType)[(getSubAnimValue iType iSubAnim)]
    )
   	
    function wirethem = 
    (
  	-- Get the selection sub anim parameter
  	local selectAnim = getWireParameter $ mainrollout.selectparam.selection mainrollout.selectplane.selection
  	-- Get the target sub anim parameter
  	local targetAnim = getWireParameter mainrollout.grabit.object mainrollout.targetparam.selection mainrollout.targetplane.selection
   	    
  	-- Wire them together
  	case mainrollout.connectwire.state of
  	(
  	  1: paramWire.connect targetAnim selectAnim string_tarfact
  	  2: paramWire.connect selectAnim targetAnim string_selfact
  	  3: paramWire.connect2way selectAnim targetAnim string_selfact
  	)
    )
   

In fact, this is the long hand version, the short hand version would change the getSubAnimValue function to:


   fn getSubAnimValue iType iSubAnim = (
 	local lstSubAnims = #(#(#X_Position, #Y_Position, #Z_Position),
 								  #(#X_Rotation, #Y_Rotation, #Z_Rotation),
 								  #(#X_Scale, #Y_Scale, #Z_Scale))
 	return lstSubAnims[iType][iSubAnim]
   )
 

But I thought the case statement was slightly more readable…

Have fun
Shane

Variable Scope -> I get that. I had to go back and debug the lockscript because I was having scope problems all over the place. Local variables are happy.

I will be more careful with this in the future.

Non Execute Method -> I… have no idea what you’re doing here, but I will find out. I do not know what subAnim’s are, but I imagine that the documentation will tell me. Thanks again, for all your help.

Rig -> I was just thinking about this on the way home from a thanksgiving party. The easiest way I can think is just have the spinner in the code automatically update a spinner on an invisible object, and then wire the parameter you want to the spinner on the object. It’s indirect, but it would work.

If you can think up a better way, I am all ears.

Doubleplus thanks.

2 Replies
(@rustyknight)
Joined: 11 months ago

Posts: 0

That’s alright, neither do i ;)…lol

ed: Seriously though, I am simply accessing the information directly from the object.

“subanims”

are any animatable property that is visible as track in the Track View
You can basically access them via “named property access” methods…ie

$.pos.controller[#X_Position] – Get the subanim for the x position of the position controller.

This is the information you pass to the paramwire interface that does all the work for you.

(@rustyknight)
Joined: 11 months ago

Posts: 0

I’ve had an really quick look at this. Simply, I created an object, dropped an attribute holder modifier onto and created a custom attribute named “Param1” which is a float wrapped around a spinner…Then I typed this…


 paramWire.connect $.modifiers[#Attribute_Holder].Custom_Attributes[#Param1] $.pos.controller[#X_Position] "Param1"
 

And this gives control of the objects x-position over to the custom attribute. So yes, it can be done and it is all done on itself…

I’ll hunt through my old code, because I know I’ve scripted custom attributes before…

Shane

Page 2 / 3