PDA

View Full Version : how to access variables from a rollout declared within another?


Caprier
12-05-2008, 10:58 PM
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?

ZeBoxx2
12-05-2008, 11:07 PM
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

Caprier
12-06-2008, 12:31 AM
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?

ZeBoxx2
12-06-2008, 12:51 AM
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 :)

Caprier
12-06-2008, 08:02 AM
As you can see from my other post, I have several options now.
Thank you for your time, Richard. You've been very helpful.

Caprier
12-06-2008, 04:58 PM
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?

ZeBoxx2
12-06-2008, 06:03 PM
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
)

Caprier
12-06-2008, 06:41 PM
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. :))

Caprier
12-07-2008, 10:43 AM
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?

ZeBoxx2
12-07-2008, 12:26 PM
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

Caprier
12-07-2008, 02:07 PM
So the idea is to implement my own for loop while keeping the counter accessible. That makes sense. Thanks again, Richard.

On a side note, I can't believe how hard it is to test values out of a string. I thought that would be one of the easiest parts and I've already spent two days on it...

CGTalk Moderation
12-07-2008, 02:07 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.