Notifications
Clear all

[Closed] how to access variables from a rollout declared within another?

I have a rollout open in a dialog and I want another rollout to pop up in a second dialog in case of an error. The idea is to allow the user to correct the cause of the error on the fly.
Here is the (trimmed) code:

 
(
global rltVoronoiCells
global rltCorrect
try destroydialog rltVoronoiCells catch()
try destroydialog rltCorrect catch()
 
rollout rltVoronoiCells "Voronoi Cells" width:259 height:368
(
...
on btnCCfromFile pressed do
(
	...
	for i = 1 to theLines.count do
	(
	 oneLine = theLines[i] as stringStream
	 try for j = 1 to 3 do (readValue oneLine) + 0
	 catch
	 (
		rollout rltCorrect "" width:243 height:95
		(
		 label lblCorrect "Missing or invalid coordinate(s) at line" pos:[15,10] width:180 height:20
		 label lblLineNb "" pos:[193,10] width:34 height:20
		 editText edtCorrect "" pos:[10,30] width:219 height:16
		 button btnCorrect "Correct" pos:[60,60] width:50 height:25
		 button btnDontCorrect "Abort" pos:[134,60] width:50 height:25
		 on rltCorrect open do
		 (
 
			--lblLineNb.text = i as string
			edtCorrect.text = oneLine
 
		 )-- end on rltCorrect open
		)-- end rollout rltCorrect
		createDialog rltCorrect 243 95
	 )-- end catch
	)-- end for
)-- end on btnCCfromFile pressed
createDialog rltVoronoiCells 259 368 pos:[980,600]
)-- end script 

I’m creating the popup rollout within an event handler of the first. It works but I’m not sure it’s the right way to do it.

My problem is that when when I try to read the counter value (i in the line commented out) , I get a compile error saying No outer local variable references permitted here.
While the oneLine variable, which is also an outer local variable, is read fine in the next line.

I’ve read again and again the reference about scope of variables but can’t figure what I’m doing wrong.
Can anyone help me with this?[size=1]
[/size]

10 Replies

Can’t inline define rollouts like that… basically when maxscript evaluates your code, it notices the rollout definition, tries to parse it, and sees it’s referencing an ‘i’ which is in your runtime code… which it can’t access when it’s trying to parse it before that code is ever run.

Instead, create your rollout dynamically… either using the rolloutCreator struct, or manually.

E.g.


 	 catch
 	 (
 		rltCorrect_str = "
 rollout rltCorrect \"\" width:243 height:95
 (
 	label lblCorrect \"Missing or invalid coordinate(s) at line\" pos:[15,10] width:180 height:20
 	label lblLineNb \"" + i as string + "\" pos:[193,10] width:34 height:20
 	editText edtCorrect \"" + oneLine as string + "\" pos:[10,30] width:219 height:16
 	button btnCorrect \"Correct\" pos:[60,60] width:50 height:25
 	button btnDontCorrect \"Abort\" pos:[134,60] width:50 height:25
)-- end rollout rltCorrect"
 		rltCorrect = execute rltCorrect_str
 		createDialog rltCorrect 243 95
 	 )-- end catch
 

Thanks again, Richard. I’m not sure I understand everything but I’ll try tomorrow.

As an alternative, and before spending another day on something stupid, would it be correct to create the rollouts one after the other (not nested as in the previous code) and to declare the two variables I need as global to the script?

That, too, should work – as long as you adjust those UI control strings in the ‘on open’ event, and don’t hardcode them into the UI code itself. I suggest using a struct to store such variables, and making just the struct global – saves on global variable clutter

As you can see from my other post, I have several options now.
Thank you for your time, Richard. You’ve been very helpful.

I’m still trying to understand a little more on how the scope of variables works.

I have these two almost identical scripts:

 
(
local theIndex
local popupRlt
rollout mainRlt "Main Rollout" width:150 height:100
(
  button theButton "Press Me" pos:[25,25] width:100 height:50
  on theButton pressed do
	for theIndex=1 to 10 do
	  if theIndex==7 do
		createDialog popupRlt 100 50 600 400
)
rollout popupRlt "Popup Rollout" width:100 height:50
(
  editText theText "" pos:[10,17] width:80 height:16
  on popupRlt open do
	theText.text=theIndex as string
)
createDialog mainRlt 150 100 400 400
)

 
(
local theIndex
local popupRlt
rollout mainRlt "Main Rollout" width:150 height:100
(
  button theButton "Press Me" pos:[25,25] width:100 height:50
  on theButton pressed do
	for i=1 to 10 do
	  if i==7 do
	  (
		theIndex=i
		createDialog popupRlt 100 50 600 400
	  )
)
rollout popupRlt "Popup Rollout" width:100 height:50
(
  editText theText "" pos:[10,17] width:80 height:16
  on popupRlt open do
	theText.text=theIndex as string
)
createDialog mainRlt 150 100 400 400
)

While the second script has “7” displayed as expected, I get “undefined” with the first.
Shouldn’t the variable in the first script be visible to the second rollout, as it is declared at the script’s level?
Is it something to protect a variable used as a counter in a for loop?

The scope is fine, but when you say…

for theIndex=1 to 10 do

You are creating a new local variable for theIndex that exists only for the loop.

e.g.


(
theIndex = 5
print theIndex
for theIndex = 1 to 3 do ( print theIndex )
print theIndex
OK
)

The rollout ‘lives’ in the scope of your script, not in the scope of the loop That’s why the 2nd one does work… this would work as well ( ignore my additional parantheses, they’re just for my own sanity ):



(
local theIndex
local popupRlt
rollout mainRlt "Main Rollout" width:150 height:100
(
	button theButton "Press Me" pos:[25,25] width:100 height:50
	on theButton pressed do (
		for i=1 to 10 do (
			theIndex = i
			if theIndex==7 do (
				createDialog popupRlt 100 50 600 400
			)
		)
	)
)
rollout popupRlt "Popup Rollout" width:100 height:50
(
  editText theText "" pos:[10,17] width:80 height:16
  on popupRlt open do
	theText.text=theIndex as string
)
createDialog mainRlt 150 100 400 400
)

I’ve finally found it: “The for loop index variable’s scope is always the extent of the for loop, even if another variable of the same name already exists.”

The script is almost finished and everything is working like a charm, thanks to you!
Have a beer on me. :))

I spoke too fast.

Under certain circumstances, while parsing an array, I need to recheck the same value.

I tried something like this:

for i=1 to 5 do
(
 print("before messageBox, i="+i as string)
 if queryBox "Redo?" beep:false do i-=1
 print("after messageBox,  i="+i as string)
)

which doesn’t work.
It looks like the counter in a for loop is protected against any change.

As I already have many tests and variables in that part of the script (which starts looking like spaghetti code), I’m trying to avoid using yet another test, like a while loop inside the for loop.
Is there any other way?

well, you don’t need a while loop inside the for loop, per se… I do think you’d have to replace the for loop with a while loop, though:


i = 1
while (i <= 5) do (
	print ("before messageBox, i=" + i as string)
	if (queryBox "Redo?" beep:false) do ( i -= 1 )
	print ("after messageBox,  i=" + i as string)
	i += 1
)

although there’s other constructs (besides a do … while loop), but this is the easiest

Page 1 / 2