Notifications
Clear all

[Closed] MS noobquestion: passing a variable

hi all,
[i]
from time to time i do some little maxscript with the help of the max-ms help and reading/googling into this forum and also into scriptspot. with some basic knowledge of js and php i have been able to make little scripts for some easy automated processes. its mostly try and error but at the end it always has been a great time saver.

right now a have done another little script and want to make it usable for other people without typing e.g. basic vars and object names into to script itself. it took some time to manage my first rollout but i have problems with passing the vars over to my functions.

can somebody help me on understanding how to do that? i know i should buy myself some good book and spend time on intense learning but i have to admit i only touch ms when it seems to be very important and the other time i try improving modelling and render skills.
[/i]
anyway here is a cropped version of my problem. what do i have to do that the function
knows the object i selected earlier? Thanks in advance and sorry for bad english.


 
 clearselection() 
 rollout varTest "varTest" width:240 height:80(
 
 	fn doIt = (
 		newObj = instance testObj
 		newObj.pos = [0,0,0]
 	)
 	
 	pickbutton chooseObj "pick object" width:200 
 	on chooseObj picked testObj do( 
 		if testObj != undefined do(
 			chooseObj.text = testObj.name
 			)
 	)
 	
 	button exeBtn "do it" width:200
 	on exeBtn pressed do (
 		doIt()
 	)
 	
 	
 )
 createdialog varTest
 
 
5 Replies

I always pass in the obj to the function. That avoids any and all scope issues. Most of my functions are in a global scope. So the variable can be passed to them even if it’s created in a local function and doesn’t have to be defined as a global variable itself. Even large scripts tend to only have 3 or 4 global variables max and use structs wherever possible.

fn doIt Obj = (
newObj = instance Obj
newObj.pos = [0,0,0]
)

Hi Horst,
MaxScript Reference is your best teacher. I slightly changed your code and pointed out the relative information in the Reference.


-- clearselection() 
-- remove this or it will deselect anything before running the script

rollout varTest "varTest" width:120 height:30
(
    -- use a regular button that triggers the action 
    button btInstance "Instance this!" width:110 align:#center

    -- create a function and after its name, list the parameters you want to pass
    -- to it. You will access the same variables inside the function body.
    -- See MaxScript Reference "Creating Functions" and sub paragraphs
    fn doIt objToInst instName instPosition =
    (
         newObj = instance objToInst
         newObj.name = instName
         newObj.pos = instPosition
     )

    on btInstance pressed do
    (
        -- the 'selection' ObjectSet stores references to the current selection
        -- See MaxScript Reference "ObjectSet Values"
        
        -- the .count is a property of ObjectSets and Arrays and stores
		-- the number of elements in the set
        -- See MaxScript Reference "Array Values"
        local selCount = selection.count

        -- test the number of currently selectled objects
        -- See MaxScript Reference "Controlling Program Flow in Scripts"
        if (selCount == 1) then
        (
        -- call the function 'doIt' and pass some values
        -- selection[1] means the first element in the current selection set
        -- See MaxScript Reference "Function Parameters"
            doIt selection[1] "My New Instance" [10, 20, 30]
        )
        else if (selCount == 0) then
        (
            messageBox "Please pick an object" title:"Error"
        )
        else
        (
            messageBox "Too many objects selected" title:"Error"
        )
    )
)
-- create a dialog just a litter fancier, but not required :)
createDialog varTest style:#(#style_toolwindow, #style_border, #style_sysmenu)

  • Enrico

The principle you have to remember is: You cannot access a variable if it has not been already declared. If your function looks for ‘testObj’, it won’t find it anywhere, so a NEW local variable will be created automatically inside the function. That variable will be of course ‘undefined’ and this will cause an error.

The other problem is that the vartiable testObj passed to the event handler has a very short life expectancy – it is created as local to the even handler and destroyed right after the handler stops running. So testObj does not exist outside of the handler.

Even if testObj was defined inside the chooseObj event handler, the function would not “see” the variable because it comes up later in the code.

To fix this, all you have to do is pre-declare testObj as local in the beginning of the rollout BEFORE both the function and the even handlers, then make sure you assign the argument of the handler to that variable to preserve it beyond the life of the handler’s scope.

This will initialize an empty undefined variable, then when the even handler picks an object, it will “see” that variable and will write into it instead of creating a new one implicitly. Then when the doIt function is called, it will also “see” the existing variable and use it instead of creating its own.

I also added some code to disable the second button and only enable it when you pick a valid object.

(
 clearselection() 
 rollout varTest "varTest" width:240 height:80
 (
  local testObj
 	 fn doIt = (
 		 newObj = instance testObj
 		 newObj.pos = [0,0,0]
 	 )
 	 
 	 pickbutton chooseObj "pick object" width:200 
 	 button exeBtn "do it" width:200 enabled:false
 	
 	 on chooseObj picked obj do( 
 		 if obj != undefined do(
 			testObj = obj
 			exeBtn.enabled = true
 			 chooseObj.text = testObj.name
 			 )
 	 )	
 	 on exeBtn pressed do (
 		 doIt()
 	 )
  )
  createdialog varTest
 )

thatoneguy, SyncViewS and Bobo – many thanks for your replies and help.
sadly i can not read/understand your code and comments that easily so i have to work me through and this will take some time. but i will post feedback after i am finished.

besides you helped me with my problem i am very surprised and happy to see that there are still people out there willing to help and share knowledge without financial or other personal benefit. many thanks and a big karma point to all of you.

ok, here we go. thanks for your explanations. i learned a lot and finally got my litte script to work (although i believe the code is not good).

anyway, i needed to create some ropes (of single elements) that have to be very editable so i came along the spacing tool, but after changing the spline i have to delete the instanced objects and reuse the spacing tool again. in my case an absolute time killer so a tried to make the script.

this script is for free and anybody may use it and/or create changes.

attached you will find a mini tut and the script itself.

also here is the code:


  
  
  clearselection() 
  
  rollout ropeSim "obj2spl aligner" width:180 height:240
  (
  	
  	local origObj					-- the object that should be instanced
  	local targetSpline				-- the spline where the the instances are aligned to
  	local instanceCount				-- the amount of instances
  	local instanceArray = #()		-- array for new createt instance objects
  	
  	
  	-- selecting the object to clone/align:
  	pickbutton chooseObj "pick object" width:140 tooltip:"pick the object to be duplicated"
  	
  	-- selecting the spline to align on:
  	fn validSpline spl = classof spl == Line
  	pickbutton chooseSpl "pick spline" width:140 filter:validSpline tooltip:"pick the line/spline for alignment of objects"
  	
  	-- setting amount of duplicates/instances
  	spinner instCount "InstanceCount:"  pos:[60,80] width:80 height:16 range:[2,1000,0] type:#integer
  	
  	-- preview Button
  	button prevBtn "create" pos:[20,120]
  	
  	-- cancel Button
  	button redoBtn "reset" pos:[90,120]
  	
  	-- infobox
  	label lab10 ""
  	label lab11 "This script is for aligning" align:#left
  	label lab12 "object instances along a spline." align:#left
  	label lab13 "Beware to eventually change the" align:#left
  	label lab14 "object rotation to get desired result" align:#left
  	
  	
  	fn cloneAlign = (
  		for i = 0 to instanceCount do (
  			
  			percentState = 100.0/instanceCount * i
  			
  			-- oldObj = obj
  			-- spl = getnodebyname "Line02"
  			
  			new_copy = instance origObj 											--instance the object
  			new_copy.name = uniquename (origObj.name+"_Instance") 					--rename it
  			append instanceArray new_copy
  			-- print instanceArray
  			new_copy.pos.controller = path follow:true path:targetSpline constantVel:true percent:percentState allowUpsideDown:on
  			new_copy.transform = origObj.transform 									--copy the TMatrix to orient correctly
  		)
  		-- print instanceArray
  	)
  	
  	fn deleteInstances = (
  		for k = 1 to instanceArray.count do (
  			-- print instanceArray[k]
  			delete instanceArray[k]
  		)
  		-- empty array
  		instanceArray = #()
  		
  	)
  	
  	
  	
  	-- if object is picked:
  	on chooseObj picked obj do( 
  		--see if the user did not cancel the picking...
  		if obj != undefined do(
  			--if he did not, make the box's wireframe red:
  			obj.wirecolor = red
  			origObj = obj
  			--and display the name of the object on the button:
  			chooseObj.text = obj.name
  			)
  	)--end on
  	
  	
  	-- if spline is picked:
  	on chooseSpl picked spl do( 
  		--see if the user did not cancel the picking...
  		if spl != undefined do(
  			--if he did not, make the box's wireframe red:
  			spl.wirecolor = red
  			targetSpline = spl
  			--and display the name of the object on the button:
  			chooseSpl.text = spl.name
  			)
  	) --end on
  
  	-- if spinner is changed:
  	on instCount changed val do(
  		instanceCount = val
  		-- print val
  	) --end on
  
  	-- id preview button is pressed:
  	on prevBtn pressed do (
  		-- messagebox "do the action"
  		cloneAlign()
  	) --end on
  
  	-- if cancel button is pressed:
  	on redoBtn pressed do (
  		deleteInstances()
  	) -- end on
  	
  	on ropeSim close do(
  		-- max undo
  		-- deleteAllChangeHandlers id:#ropeSim_handler
  	) --end on
  
  	
  	
  
  )
  
  createdialog ropeSim
  

thank you.