Notifications
Clear all

[Closed] Error: "No outer local variable references permitted here", when construct

I want to create a when construct to handle transform events on some splines, then I have something like this:


sr = splineShape() --spline shape with normal
addnewSpline sr
addknot sr 1 #corner #line p
addknot sr 1 #corner #line (p + normal*normalLength)
updateShape sr

ni = NormalInfo line:sr t:_t b:_b n:_n texel:[texel.x*widthRatio, texel.y*heightRatio]

handler = when transform sr changes handleAt:#redrawViews ni do
(
	local p0 = getKnotPoint sr 1 1
	local p1 = getKnotPoint sr 1 2
	local n = normalize p1-p0
	print "lol
"
)

And I get that error when I Evaluate All:


-- Compile error: No outer local variable references permitted here:  sr
--  In line: 											local p0 = getKnotPoint sr 1

Then, well, I really don’t know what to do, that doesn’t make any sense to me because that is the object that I want to handle events for. Why I can’t work with it in the change handler body??? I’m really confused

Thanks in advance.

5 Replies

Instead of sr try using the object parameter ni.

handler = when transform sr changes handleAt:#redrawViews [b]ni[/b] do
(
	local p0 = getKnotPoint [b]ni[/b] 1 1
	local p1 = getKnotPoint [b]ni[/b] 1 2
	local n = normalize p1-p0
	print "lol
"
)

The reason it works this way is because you can create a when construct for multiple objects at once (in which case you replace the sr parameter by an object array).
This will cause the callback to be executed multiple times for each of those objects, and the ni parameter will contain the object for which it’s currently being executed.

Martijn

Wow thanks. That is not exactly what my code should look like because I want for that ni to be available inside the change handling function. But the first line in my snippet shows that sr is stored into ni.line, so I can get it from ni inside that function. You made me realize that the first object parameter is the object which will be monitored to raise events and it is not automatically passed as a parameter for the function.

Thanks again…

Well actually I misunderstood the documentation. That last parameter is a variable where the object which is being monitored for events is assigned to…But I want that ni object inside that function, I need it there inside, I have to get some data from it. Now I can’t see a way to do that.

I obviously didn’t read your initial post properly so I missed the fact that you’re assigning a struct to variable ni and want to use that in your callback.

sr = splineShape() --spline shape with normal
...

[b]global[/b] ni = NormalInfo line:sr t:_t b:_b n:_n texel:[texel.x*widthRatio, texel.y*heightRatio]

handler = when transform sr changes handleAt:#redrawViews [b]obj[/b] do
(
	-- This only works if this callback is applied to just [u]one[/u]
	-- object and so [b]ni[/b] and [b]sr[/b] both point to the same object.
	-- if you need to use multiple objects/structs, you'll need to first find the struct
	-- that belongs to [b]obj[/b] (the actual object that is passed as an argument
	-- to this function).
	print ni
)

Hope this makes sense,
Martijn

Now I see that the only choice is to use global variables inside the change handler. But I have several splines like that and one unique ni thing for each. The solution I got working is to create a global array where I store the nis in the same ordering as the splines are created and I store a user property inside the spline with the index of its ni using setUserProp function, like this


sr = splineShape()

/* ... */

--create ni for this new splineShape
ni = NormalInfo line:sr t:_t b:_b n:_n texel:[x*widthRatio, normalMap.bitmap.height-1-y*heightRatio]
--store it in the next available position in the global array
normalInfoArray[normalInfoArray.count+1] = ni

setUserProp sr "i" (normalInfoArray.count+1)

ni.eventHandler = when transform sr changes handleAt:#redrawViews sr do
(
        --here I get the corresponding ni for this spline
	local ni = normalInfoArray[ getUserProp sr "i" ]
	
        /* ... */
)

I kinda don’t like this solution but I can’t think of any other one. Also I tried setting the ni object as an user property but that doesn’t work because user properties can only be strings or numbers.