Notifications
Clear all

[Closed] Multiple instances of the same rollout definition

I’ve written quite a big piece of code to control a characters animation.
What I’d like to be able to do is have multiple rollout floaters open … one per character on screen.

Creating an array of rollout floaters is pretty easy…
However…try as I might I can’t find a way to have multiple instances of the same rollout definition… except loading the whole thing in as a text file at runtime an using ‘execute’ … which seems like overkill…

heres a small piece of test code.

The question is. How do i get the rollout to appear in the second rollout floater?


 
 floaterCount = 0
 struct test
 (
 	txt = "a",
 	myFloater,
 	roll,
 	RollName,
 	fn CreateMyRollout = 
 	(
 		roll = rollout RollName "test rollout"
 		(
 			label lblA ""
 			Label lblB ""
 		)
 		floaterName = "test floater " + ((floaterCount+=1) as string)
 		myFloater = NewRolloutFloater floaterName 200 200
 		
 		AddRollout RollName  myFloater
 		myFloater.pos += floaterCount * [100,100]
 		RollName.lblA.text = txt
 		Roll.lblb.text = "txt"
 	),
 	a = CreateMyRollout()
 )
 
 if TestArray != Undefined do
 (
 	if TestArray.count > 0 do for T in TestArray do CloseRolloutFloater T.MyFloater
 )
 
 TestArray = #(test(),test())
 
 

Does anyone out there know nice way to fix this problem or a way round it to get similar results? …bobo , pen ?

6 Replies
 PEN

We had a long discussion about this some time ago. There is no way that I have found to have instances of a rollout open at the same time. You can re-eval it making a new instance and display it. Instead of doing it in a string place the rollout in a function and call the function. That should get you a new copy of the rollout. I’m working it this way for PEN Attribute Holder 3 for various reasons as well as wanting to be able to float several at once. Not sure if it is going to work the way that I want yet as I have not tried it.

1 Reply
(@carlosa)
Joined: 11 months ago

Posts: 0

yeah i thought something like this would work as well.

but this dosn’t seem to work all that well. it seems to be that garbage collection dosn’t clean up after itself well enough for the “createdialog” function to build a new rollout.
here my test code


  struct myAwsomeCharTool
  (
  	ro, --this holds the rollout varible
  	char, --char is a dynamic value for to be hidden in an invisible text field of the rollout
  	fn ui = --this function creates a rollout
  	(
  		rollout ro01 ("charUI \"" + char + "\"")
  		(
  			button whatChar "whatChar"
  			editText charNm "" visible:false text:char --this is how the tool know what char to work on
  			on whatChar pressed do
  			(
  				messagebox charNm.text	 
  			)
  		)
  		ro01
  	),
  	fn run = --this functions creates the rollout and exposes to the hole struct
  	(
  		ro = ui()
  		createdialog ro
  	)
  )
  
  charList =  #("peter","phil","ana")
  uiList = #()
  for i = 1 to charList.count do
  (
	chT = myAwsomeCharTool() --create a new object
  	chT.char = charList[i] --setThe char tag for that rollout
  	chT.run() --create the dialog
  	append uiList chT --add the stuct to an array so in case we need to acess rollout out info later
  )
  
  

this code should open 3 different rollouts but it only opens one.
i think it’s becuse the varible name “ro01” is locked in memory until the script is done executing. so is not getting reassainged and when “createdialog” is ren for the second time and third time it sees the rollout as already open, and return ok.

this actualy seems like a bug if you ask me.

the funy part is that if i evaluate the hole script agein and the stuct is re evaluted, a new rollout is open, but still no intances. kind of crapy

I had a simular issue and Paul is right, the only way to do it is to create them dynamically. You may want to checkout the RolloutCreator functions.

Basically, you need to a new <rollout_name> for each rollout so that you can get a reference to them an make then, essentially unquie.

The problem is:

rollout ro01 ("charUI \"" + char + "\"")

creates a SINGLE instance of the rollout, regardless of what the caption might be. You need to change it’s name (ro01)…it is global reference.

Take a look at the RolloutCreator functions, this is what they were design to do.

If you can’t make that work, you will need to “evaluate” a string representation of your rollout using the execute function

Shane

I’ve used a filein technique once… Here’s the test code from when I dev’d it…

It copies the contents of the script from one file to the other, appending a number to any variable that is “rollout_” and then filein that new file and delete’s it…

The rollout definition line needs to be the first thing it finds in the script, it assumes it is on it’s own line… hence filterstring[2], it now has the rollout base name. and loops checking for instances of it

If it finds a rollout one that exists but is not open, it sets the rollout def to undefined, before continuing and defining it…

It works well but you have to take care to only have one “rollout_” string per line… You can see I defined the title to a var because this one does not find the second one per line while stepping down the code.


   (
   -- Allows multiple unique instances of the same rollout via fileIn
   -- This verison only finds the first "rollout_" per line.
   
   local FSin = Openfile "D:\	emp\\TestRollout.ms" mode:"r"
   local FSOut = Openfile "D:\	emp\\TestRolloutVersion.ms" mode:"w"
   local tnRollName = ""
   local tnLine
   
   do(
   tnLine = readLine FSin
   if ( matchpattern tnLine pattern:"*rollout_*" ) then
   	(
   	if ( tnRollName == "" ) then
   		(
   		local RollExists = false
   		local RollCount = 0
   		tnRollName = (filterString tnLine " ")[2] 
   			do(
   			RollCount += 1
   			RollExists = execute ( "( Classof " + tnRollName + ( RollCount as string ) + " == RolloutClass )" )
   			if ( RollExists ) then  
   				(
   				local Rollopen = execute ( tnRollName + ( RollCount as string ) + ".open" )
   				if ( not Rollopen ) then 
   					(	
   					execute ( tnRollName + ( RollCount as string ) + "=undefined" )
   					RollExists = false
   					)
   				)
   	
   			)while( RollExists )
   		)
   
   	local ReplacePos = ( findString tnLine "rollout_" )
   	tnLine = replace tnLine ReplacePos 8 ("rollout_"+ ( RollCount as string ))
   	)
     format "%
" tnLine to:FSout
    )
   while( not eof FSin )
   
   close FSin
   close FSOut
   
   filein "D:\	emp\\TestRolloutVersion.ms"
   
   deleteFile "D:\	emp\\TestRolloutVersion.ms"
   )
   

Here’s the Code found in TestRollout.ms


   rollout TestRollout_ ""
   (
   button CloseMe "Close TestRollout_ "
   
   on TestRollout_ open do
   	(
   	local TRname = "TestRollout_ "
   	TestRollout_.Title = TRname
   	)
on CloseMe pressed do ( destroyDialog TestRollout_ )
   )
   
   CreateDialog TestRollout_
   

Hope this is helpful

Thanks for your help guys… I guess I was hoping that I’d missed something, and that the impossible was in fact possible…

You guys have probably thought of this already…but…

  It would be nice Autodesk could give us a extra version of the rollout function which returns a unique instance. So rather than..
   
   [b][b]rollout[/b][/b] &lt;var_name&gt;  &lt;description_string&gt;
  [ [b][b]rolledUp[/b][/b]:&lt;boolean&gt; ] [  [b][b]silentErrors[/b][/b]:&lt;boolean&gt;  ]
  [b][b]([/b][/b] &lt;rollout_body&gt; [b][b])
   
   [/b][/b]We have something that works in the same way as max structures.. ie you create a rollout definition then create instances from that definition

   [b][b]RolloutDef[/b][/b] &lt;Rollout_definition_name&gt; &lt;description_string&gt;
  [b][b]([/b][/b] &lt;rollout_body&gt; [b][b])

[/b][/b]
<rollout_instance> = <Rollout_definition_name>( [ rolledUp:<boolean> ][silentErrors:<boolean> ] )

  Could you clarify. Is that the kind of method I'm using in my sample code?
  Rollout creator is useful, although in the end its just a nice max script wrapper for the execute function. ...lol.. It seems I always end up writing my own version of rollout creator when I need to dynamic create rollouts..
  I guessed as much, I even tried various methods pass the Rollout function a variable containing the new name ... didn't work though ...sigh.

Absolutely. It probably the only way to do it… short of rewriting the whole interface in C# or python…arrrg