You are not logged in.

Dear visitor, welcome to krpano.com Forum. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

1

Monday, March 15th 2010, 5:11pm

How does dereferencing work in Krpano?

Could someone please explain? I think I'm losing my mind here.

2

Monday, March 15th 2010, 6:34pm

Consider this:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 <onstart="test-dereferencing(2,'spot-three')" />

	<testarray>
		<point name="one" />
		<point name="two" />
		<point name="three" />
		<spot name="spot-one" x="1" />
		<spot name="spot-two" x="2" />
		<spot name="spot-three" x="3" />
	</testarray>
	
	<action name="test-dereferencing">
	set(i,"2"); 
	set(%3,"2");
	set(tmpname,'spot-three');
	
	trace(" ");
	trace('i is ',i, ' testarry.point[i] is ', testarray.point[i].name);
	trace('i is ',i, ' testarry.point[i] is ', testarray.point[get(i)].name);
	trace('i is ',i, ' testarry.point[i] is ', get(testarray.point[get(i)].name));
	trace('i is ',i, ' testarry.point[i] is ', get(testarray.point[i].name));
 
 	trace(" ");
	trace('arg1 is ',%1, ' testarry.point[arg1] is ', testarray.point[%1].name);
	trace('arg1 is ',%1, ' testarry.point[arg1] is ', testarray.point[get(%1)].name);
	trace('arg1 is ',%1, ' testarry.point[arg1] is ', get(testarray.point[get(%1)].name));
	trace('arg1 is ',%1, ' testarry.point[arg1] is ', get(testarray.point[%1].name));
	
	trace(" ");
	trace('arg3 is ',%3, ' testarry.point[arg3] is ', testarray.point[%3].name); 	
	trace('arg3 is ',%3, ' testarry.point[arg3] is ', testarray.point[get(%3)].name);
	trace('arg3 is ',%3, ' testarry.point[arg3] is ', get(testarray.point[get(%3)].name));
	trace('arg3 is ',%3, ' testarry.point[arg3] is ', get(testarray.point[%3].name));

	trace(" ");
	trace('arg2 is ',%2, ' testarry.spot[arg2] is ', testarray.spot[%2].x);
	trace('arg2 is ',%2, ' testarry.spot[arg2] is ', testarray.spot[get(%2)].x);
	trace('arg2 is ',%2, ' testarry.spot[arg2] is ', get(testarray.spot[get(%2)].x));
	trace('arg2 is ',%2, ' testarry.spot[arg2] is ', get(testarray.spot[%2].x));
	
	trace(" ");
	trace('tmpname is ',tmpname, ' testarry.spot[tmpname] is ', testarray.spot[tmpname].x);
	trace('tmpname is ',tmpname, ' testarry.spot[tmpname] is ', testarray.spot[get(tmpname)].x);
	trace('tmpname is ',tmpname, ' testarry.spot[tmpname] is ', get(testarray.spot[get(tmpname)].x));
	trace('tmpname is ',tmpname, ' testarry.spot[tmpname] is ', get(testarray.spot[tmpname].x));
	
	trace(" ");
	trace('dereference-this(get(tmpname))');
	dereference-this(get(tmpname));
	
	trace(" ");
	txtadd(newname,'spot-',testarray.point[%1].name);
	trace(newname);
	txtadd(newname,'spot-',get(testarray.point[%1].name));
	trace(newname);
	trace('newname is ',newname, ' testarry.spot[newname] is ', testarray.spot[newname].x);
	trace('newname is ',newname, ' testarry.spot[newname] is ', testarray.spot[get(newname)].x);
	trace('newname is ',newname, ' testarry.spot[newname] is ', get(testarray.spot[get(newname)].x));
	trace('newname is ',newname, ' testarry.spot[newname] is ', get(testarray.spot[newname].x));
	
	trace(" ");
	dereference-this(get(newname));
	</action>
	
	<action name="dereference-this">
		trace('arg1 is ',%1, ' testarry.spot[%1] is ', testarray.spot[%1].x);
		trace('arg1 is ',%1, ' testarry.spot[%1] is ', testarray.spot[get(%1)].x);
		trace('arg1 is ',%1, ' testarry.spot[%1] is ', get(testarray.spot[get(%1)].x));
		trace('arg1 is ',%1, ' testarry.spot[%1] is ', get(testarray.spot[%1].x));
	</action>


Result:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
INFO: i is 2 testarry.point[i] is testarray.point[i].name
INFO: i is 2 testarry.point[i] is testarray.point[get(i)].name
INFO: i is 2 testarry.point[i] is 2
INFO: i is 2 testarry.point[i] is 2
INFO:  
INFO: arg1 is 2 testarry.point[arg1] is three
INFO: arg1 is 2 testarry.point[arg1] is testarray.point[get(2)].name
INFO: arg1 is 2 testarry.point[arg1] is 2
INFO: arg1 is 2 testarry.point[arg1] is three
INFO:  
INFO: arg3 is 2 testarry.point[arg3] is testarray.point[null].name
INFO: arg3 is 2 testarry.point[arg3] is testarray.point[get(null)].name
INFO: arg3 is 2 testarry.point[arg3] is 2
INFO: arg3 is 2 testarry.point[arg3] is 2
INFO:  
INFO: arg2 is spot-three testarry.spot[arg2] is 3
INFO: arg2 is spot-three testarry.spot[arg2] is testarray.spot[get(spot-three)].x
INFO: arg2 is spot-three testarry.spot[arg2] is 2
INFO: arg2 is spot-three testarry.spot[arg2] is 3
INFO:  
INFO: tmpname is spot-three testarry.spot[tmpname] is testarray.spot[tmpname].x
INFO: tmpname is spot-three testarry.spot[tmpname] is testarray.spot[get(tmpname)].x
INFO: tmpname is spot-three testarry.spot[tmpname] is 2
INFO: tmpname is spot-three testarry.spot[tmpname] is 2
INFO:  
INFO: dereference-this(get(tmpname))
INFO: arg1 is spot-three testarry.spot[spot-three] is 3
INFO: arg1 is spot-three testarry.spot[spot-three] is testarray.spot[get(spot-three)].x
INFO: arg1 is spot-three testarry.spot[spot-three] is 2
INFO: arg1 is spot-three testarry.spot[spot-three] is 3
INFO:  
INFO: spot-testarray.point[2].name
INFO: spot-three
INFO: newname is spot-three testarry.spot[newname] is testarray.spot[newname].x
INFO: newname is spot-three testarry.spot[newname] is testarray.spot[get(newname)].x
INFO: newname is spot-three testarry.spot[newname] is 2
INFO: newname is spot-three testarry.spot[newname] is 2
INFO:  
INFO: arg1 is spot-three testarry.spot[spot-three] is 3
INFO: arg1 is spot-three testarry.spot[spot-three] is testarray.spot[get(spot-three)].x
INFO: arg1 is spot-three testarry.spot[spot-three] is 2
INFO: arg1 is spot-three testarry.spot[spot-three] is 3


Please shed some light on this?

michel

Professional

Posts: 1,153

Location: ANDORRA

Occupation: TV

  • Send private message

3

Tuesday, March 16th 2010, 1:26am

Hi hitodenashi,

I have played a little with your request....
I have noticed 2 things:
It seems that setting a parameter of an action in this way:

Source code

1
set(%3,"2");

it is not possible.... I think parameters must be set inside the calling of the action...
in fact the code above is equal to:

Source code

1
set(null,"2");

Try this:

Source code

1
trace('%3 ',%3);

The result is:

Source code

1
INFO: null 2

That's why:

Source code

1
2
trace('i is ',i, ' testarry.point[i] is ', get(testarray.point[get(i)].name));
trace('i is ',i, ' testarry.point[i] is ', get(testarray.point[i].name));

Returns:

Source code

1
2
INFO: i is 2 testarry.point[i] is 2
INFO: i is 2 testarry.point[i] is 2

The two trace returns null, so 2....

Also, it seems that using get() like this:

Source code

1
testarray.point[get(i)].name

it is not resolved as expected... the same is true when a variable is used as part of a variable like:

Source code

1
testarray.point[i].name

and then:

Source code

1
2
get(testarray.point[get(i)].name)
get(testarray.point[i].name)

returns null....

Sorry about my rudimentary explanation... I hope this can help in a way...

SAlut.

4

Tuesday, March 16th 2010, 4:55am

Thank you!
I'm grateful for any advice. The documentation is...a tad lacking, and most of the good stuff is somewhere deep in the forums, often under misleading titles *huh*

I've been just throwing stuff at krpano and trying to make sense of the results.

What is bugging me most is that I can't find a way to use variable names in other variables. Like this:

Source code

1
2
3
txtadd(newname,'spot-',get(testarray.point[%1].name));
trace(newname);
trace('newname is ',newname, ' testarry.spot[newname] is ', testarray.spot[newname].x);


That doesn't work :/

But if I pass it through an action call, like this:

Source code

1
2
3
4
5
dereference-this(get(newname));

<action name="dereference-this">
trace('arg1 is ',%1, ' testarry.spot[%1] is ', testarray.spot[%1].x);
</action>


It's magically working.

Seems as though % sigil variables are not treated the same as regular ones?
I also learned that using 'set(x,"0")' makes a global variable x. Any way to make it local variables?
Also what's the deal with the $ sigil variables?


That leads me to this:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<mappoints>
<stuff name="one" />
<stuff name="two" />
</mappoints>

<plugin name="loc-one" />
<plugin name="loc-two" />

	<action name="scale-stuff">
		foreach(mappoints.stuff,i,	
			scale2(get(i));
		);
		</action>
		
		<action name="scale2">
			txtadd(tmpname,'loc-',get(mappoints.stuff[%1].name));
			do-scale-stuff(get(tmpname));
			</action>
		
		<action name="do-scale-stuff">
			switch(plugin[%1].destscale,1,0.3);
			tween(plugin[%1].scale,$destscale);			
		</action>


It works, but it makes no sense? Maybe I'm approaching it from the wrong angle?

Why not something like this:

Source code

1
2
3
4
5
6
7
   <action name="scale-stuff">
		foreach(mappoints.stuff,i,
txtadd(tmpname,'loc-',get(mappoints.stuff[i].name));	
 			switch(plugin[tmpname].destscale,1,0.3);
			tween(plugin[tmpname].scale,$destscale);   
		);
		</action>


I hope Klaus can lend a hand here.

This post has been edited 1 times, last edit by "hitodenashi" (Mar 16th 2010, 6:17am)


5

Tuesday, March 16th 2010, 6:00am

Wow Michel!!!!!!

There's not a week that goes by where I don't learn something from one of your posts, but this one takes the cake. I was looking at the results from hitodenashi's test function and I couldn't figure out why the "2" kept showing up. I did notice that he set(%3,2), but hadn't figured out that this assigns a value to null (which is of course is a very bad thing). Bravo for reasoning this out!

hitodenashi,

There are a couple of ways to accomplish what you're trying to do. The easiest method to use a variable as an index is to pass the dereferenced value through an action argument. This is essentially the method you used in lines 24,27,36,39,66, and 69 of your test-dereferencing example.

Here's a simplified example:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<krpano version="1.0.8" onstart="test-dereferencing()" >

	<testarray>
		<point name="one" />
		<point name="two" />
		<point name="three" />
		<spot name="spot-one" x="1" />
		<spot name="spot-two" x="2" />
		<spot name="spot-three" x="3" />
	</testarray>
	
	<action name="trace_testarray_point">
		trace("testarray point %1 =",testarray.point[%1].name);
	</action>
	<action name="test-dereferencing">
		set(i,0);
		trace_testarray_point(get(i));
		inc(i);
		trace_testarray_point(get(i));
		inc(i);
		trace_testarray_point(get(i));
	</action>
</krpano>


Here note that we dereference the variable i with the get() function, pass the value through the argument where it is substituted into the square brackets and used to index the point. Action arguments are simply substituted into the action code. It doesn't matter what the context of the code surrounding the argument is, it can even be in quotes, the argument is simply substituted in much the same manner as a macro substitution in C.

This is important because you can't dereference a variable between square brackets in the krpano scripting language. So

Source code

1
testarray.point[0]
works and

Source code

1
testarray.point[%1]
works if %1 is a valid address
but

Source code

1
testarray.point[i].name
won't work, nor will

Source code

1
testarray.point[get(i)].name
because the square brackets do not allow internal dereferencing.

I've posted before that variable dereferencing is one of the most confusing aspects of krpano's scripting language. I believe the confusing inconsistencies arise because of Klaus' need to keep the scripts as backward compatible as possible. Since the scripts support unquoted strings, there are a number of unconventional behaviors in the language.

I'm only aware of two places where krpano automatically dereferences variables:
1) the predicate of an if statement --so don't use get() in there
2) the arguments of the trace function.

You'll note that

Source code

1
trace(testarray.point[%1].name);
will produce the correct result for a valid address. That's because the trace function automatically dereferences the variable when it is a standalone argument. (that's why the i variable in lines 18-21 of your example were properly resolved in the 'i =',i, part of the trace statement).

One of the confusing things about automatic variable dereferencing (in if statements and trace statements), is that when the variable resolves to null, krpano converts it back to the original variable description. Thus, if foo is a null variable, trace(foo) prints "foo" rather than "null". This is Klaus' way of supporting unquoted strings. Unfortunately it can be confusing, for example if we provide an invalid address to your example array:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<krpano version="1.0.8" onstart="test-dereferencing()" >

	<testarray>
		<point name="one" />
		<point name="two" />
		<point name="three" />
		<spot name="spot-one" x="1" />
		<spot name="spot-two" x="2" />
		<spot name="spot-three" x="3" />
	</testarray>
	
	<action name="trace_testarray_point">
		trace("testarray point %1 =",testarray.point[%1].name);
	</action>
	<action name="test-dereferencing">
		set(i,0);
		trace_testarray_point(get(i));
		inc(i);
		trace_testarray_point(get(i));
		inc(i);
		trace_testarray_point(get(i));
		inc(i);
		trace_testarray_point(get(i));
	</action>
</krpano>

This code prints out

Quoted


INFO: testarray point 0 =one
INFO: testarray point 1 =two
INFO: testarray point 2 =three
INFO: testarray point 3 =testarray.point[3]


the value of testarray.point[3].name is actually null, but krpano substitutes the original string back in for the trace.

Note that the fact that variables are automatically dereferenced in the trace function, but are not automatically dereferenced in action arguments, can lead to very confusing debugging sessions. Note that in the following example the arguments are exactly the same for the trace statement and the trace_action statement, but the resulting traces are different!

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<krpano version="1.0.8" onstart="test-dereferencing()" >

	<action name="trace_action">
		trace("%1%2%3%4%5%6");
	</action>
	<action name="test-dereferencing">
		set(i,0);
		set(j,i);<!--note this sets j to the string "i"-->
		set(k,get(i));

		trace("i=",i," j=",j," k=",k);
		trace_action("i=",i," j=",j," k=",k);

		trace(" get(i)=",get(i)," get(j)=",get(j)," get(k)=",get(k));
		trace_action(" get(i)=",get(i)," get(j)=",get(j)," get(k)=",get(k));
	</action>
</krpano>


Here are the results:

Quoted


INFO: i=0 j=i k=0
INFO: i=i j=j k=k
INFO: get(i)=0 get(j)=0 get(k)=0
INFO: get(i)=0 get(j)=i get(k)=0


By now I'm sure you're head is about to explode so we'll stop here. I hope this was helpful.

steve

This post has been edited 1 times, last edit by "pinsane" (Mar 16th 2010, 7:01am)


6

Tuesday, March 16th 2010, 7:35am

Seems as though % variables are not treated the same as regular ones?


Yes, they are simple substitutions so they can go between square brackets.


It works, but it makes no sense? Maybe I'm approaching it from the wrong angle?


Actually, you're using the most readable approach. It works because you are evaluating the variable and then passing it through an argument where it is substituted into the square brackets. It's the most straightforward method.

Here's another solution more along the lines of your request, but unfortunately you still have to use hack-ey txtadd commands. Personally, I think your earlier approach is easier to understand!

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<krpano version="1.0.8" onstart="why_not_something_like_this()" >
	<mappoints>
		<stuff name="one" />
		<stuff name="two" />
	</mappoints>

	<plugin name="loc-one" />
	<plugin name="loc-two" />

	<action name="why_not_something_like_this">
		foreach(mappoints.stuff,i,
			txtadd(tmp,'txtadd(tmpname,"loc-",get(mappoints.stuff[',get(i),'].name));');
			eval_str(get(tmp));
			txtadd(tmp,'
				switch(plugin[',get(tmpname),'].destscale,1,0.3);
				tween(plugin[',get(tmpname),'].scale,$destscale);
			');
			eval_str(get(tmp));
		);
	</action>

	<!--	_eval_action
		private function to execute eval action -->
	<action name="_eval_action">
		trace("Error in eval: push/pop stack corrupted"); <!-- this line should never execute -->
	</action>
	<!--	eval_str(evalstr.str);
		accepts a single string of action[s] which are executing in a blocking manner-->
	<action name="eval_str"> <!--evalstr.str-->
		push(action[_eval_action].content);
		set(action[_eval_action].content,%1);
		_eval_action(%2,%3,%4,%5,%6,%7,%8,%9);
		pop(action[_eval_action]content);
	</action>
	<!--	_foreach_action
		private function to execute foreach loop body action -->
	<action name="_foreach_action">
		trace("Error in foreach loop: push/pop stack corrupted"); <!-- this line should never execute -->
	</action>
	<!--	foreach <objectid> <index.str> <body.str>
		foreach loop function which iterates the action across each of the objects-->
	<action name="foreach"> <!--objectid.str,index.str,body.str-->
		sub(%2,%1.count,1);
		push(action[_foreach_action].content);
		set(action[_foreach_action].content,"if(%2 GE 0,%3;dec(%2);_foreach_action(););");
		_foreach_action();
		pop(action[_foreach_action].content);
	</action>

</krpano>



Also what's the deal with the $ variables?


I believe they only work with the tween function.


I also learned that using 'set(x,"0")' makes a global variable x. Any way to make it local variables?


Not really. I'd really like to find a way to use scoped variables but haven't found an elegant solution. Krpano kinda supports local variables in that functions called from plugins inherit the plugin's attributes as variables. Perhaps Klaus could shine some light as to how we might exploit that from a general programming point of view (ie. when the actions are not called from a plugin event).

I too don't like cluttering up the global-variable space. I've been using the attributes of the action as pseudo local variables but it makes the code look uglier and you need to be very careful if you use recursion. Here's the above example recoded using attributes as fake local variables:

Source code

1
2
3
4
5
6
7
8
9
10
11
	<action name="scaler">
		foreach(mappoints.stuff,i,
			txtadd(action[scaler].tmp,'txtadd(action[scaler].tmpname,"loc-",get(mappoints.stuff[',get(i),'].name));');
			eval_str(get(action[scaler].tmp));
			txtadd(action[scaler].tmp,'
				switch(plugin[',get(action[scaler].tmpname),'].destscale,1,0.3);
				tween(plugin[',get(action[scaler].tmpname),'].scale,$destscale);
			');
			eval_str(get(action[scaler].tmp));
		);
	</action>

I'm almost embarrassed to post such ugly code *unsure*

Hope this was helpful

steve

7

Tuesday, March 16th 2010, 9:25am

Thanks Steve!
I was on the verge of just dropping krpano and doing something easier, like debugging obfuscated perl. *g*
This stuff should really go into the documentation or a wiki.

BTW, I propose a new attribute/pragma in the krpano node: scripting="sane" which drops all the nasty backward compatibility.

Quoted from "pinsane"


Quoted


Quoted from "hitodenashi"


It works, but it makes no sense? Maybe I'm approaching it from the wrong angle?

Actually, you're using the most readable approach. It works because you are evaluating the variable and then passing it through an argument where it is substituted into the square brackets. It's the most straightforward method.


Ah, I meant to say that it doesn't make sense to program that way....and then you go and say that it's the most straightforward way *pinch*
What's worse, seems you're right *wacko*

Some other observations (this was/is a long night!):

Having node names start with numbers is a bad idea:

Source code

1
2
3
<mapthings>
<floor name="2nd" />
</mapthings>



There is a problem here:

Source code

1
2
3
4
5
6
foreach(things,i,scale-things(get(i)));
is a no-go, but
foreach(things,i,scalethings(get(i)));
is ok.
foreach(things,i,do-scale-things(get(i)));
is ok.


WTF?
foreach(things,i,scale-things(get(i))) works but scale-things() gets passed a null?

Krpano is practicing some kind of bizarre psychological warfare on me *confused*

8

Tuesday, March 16th 2010, 3:17pm


I was on the verge of just dropping krpano and doing something easier, like debugging obfuscated perl. *g*

BTW, I propose a new attribute/pragma in the krpano node: scripting="sane" which drops all the nasty backward compatibility.

Thanks hitodenashi, I laughed out loud when reading this. I should know better than to read this board when eating breakfast. Anyone know how to get Count Chocula off a computer monitor?


Having node names start with numbers is a bad idea:


True dat. Krpano will try to interpret them as a number. Don't start variable names with a + or - either! ;-)


Source code

1
2
3
4
5
6
 foreach(things,i,scale-things(get(i)));
is a no-go, but
foreach(things,i,scalethings(get(i)));
is ok.
foreach(things,i,do-scale-things(get(i)));
is ok.



WTF?
foreach(things,i,scale-things(get(i))) works but scale-things() gets passed a null?


foreach(things,i,scale-things(get(i))); works for me. Can you post a complete example? scale-things() should pass a null to all %# arguments.

steve

9

Wednesday, March 17th 2010, 1:32am


Thanks hitodenashi, I laughed out loud when reading this. I should know better than to read this board when eating breakfast. Anyone know how to get Count Chocula off a computer monitor?


Glad I could help! Monitors need their cereals too, you know.


foreach(things,i,scale-things(get(i))); works for me. Can you post a complete example? scale-things() should pass a null to all %# arguments.


Um, my bad. Should have gone to bed 6 hours earlier, at least.
Turns out I already had one scale-things() action I forgot about, that's what happens when you need three subroutines instead of one :(
That, and the lack of sleep.

OTOH I was happy with this little thing:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
<action name="hide-this">
	if(%1 == null, derefthis(%0,get(name)),
		set(plugin[%1].enabled,false);
		tween(plugin[%1].alpha,0,0.3,null,set(plugin[%1].visible,false)); 
		tween(plugin[%1].textblur,20,0.3); 
		tween(plugin[%1].blur,20,0.3);
		);
</action>

<!-- derefthis(caller,original-caller) -->
<action name="derefthis">
	action(%1,%2);
</action>


Now I can have one action for all plugins :)

10

Wednesday, March 17th 2010, 4:01am


OTOH I was happy with this little thing:

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
<action name="hide-this">
	if(%1 == null, derefthis(%0,get(name)),
		set(plugin[%1].enabled,false);
		tween(plugin[%1].alpha,0,0.3,null,set(plugin[%1].visible,false)); 
		tween(plugin[%1].textblur,20,0.3); 
		tween(plugin[%1].blur,20,0.3);
		);
</action>

<!-- derefthis(caller,original-caller) -->
<action name="derefthis">
	action(%1,%2);
</action>


Now I can have one action for all plugins :)

Very nice! Nice use of %0 for a general purpose function!

steve

11

Wednesday, March 17th 2010, 11:31am

Hi,

I haven't read all yet, but here a summary about variables/parameters and the placeholders
and about how are they currently working:

  • when calling an action - the code of the action will be first parsed for the the %0 - %9 placeholders,
    and when found these will be replaced with the corresponding parameter,
    e.g. %1 is the first parameter, %2 the second one and so on,
    %0 is the name of the action itself

  • about the - get() - this is a special function, it will be only parsed when an action/function will be called,
    and it will be resolved before passing the parameters to the action,
    e.g.
    test(get(view.hlookat));
    will become first:
    test(0.000);
    and then the action 'test' will be called with this value, and there the value (here '0.000') will replace the %1 placeholders

  • using - get() - to the content of a variable is no necessary in some functions (e.g. in the add/sub/mul),
    because these functions are looking itself first if there is a variable with the given name, and if not they take the value,
    (the main reason for this behavior - these functions where implemented before get())

  • something about the array access via - []
    • the access to an array element is possible either it's 'name' or by a numeric index (0 - array.count),
      e.g. plugin[testname] or plugin[0]
    • using get inside [] is not possible!
    • since 1.0.8 beta 9 there is a way to use variables inside []
      variables can used by putting a '%' in front of their name,
      but only 'global' variables can be used there at the moment - e.g. set(plugin[%i].var, ...);
      variables with a path like "%plugin[name].var" can not be used inside []

      update for version 1.0.8.10:
      now it's also possible to use get inside the [] - e.g. set(plugin[get(var)].var, ...);

    • and it's not possible yet to use this %variable access for tween() function

  • 'local' variables
    when an action/code will be called from a plugin or hotspot event (e.g. onclick,...) the 'context' of the plugin/hotspot is used for variable access, that means the full path to the variable (e.g. plugin[name].var) is not needed in this case,


best regards,
Klaus

12

Wednesday, March 17th 2010, 4:20pm

Thank you Klaus!!!!!! This new method of simple dereferencing will clean up alot of code in the future.

May I respectfully make an observation? While this new capability is much appreciated, I'm worried that using the % character to dereference a variable may introduce confusion. The use of the %varname looks too similar to argument substitution (eg. %1 %2 etc). Right now %varname only works for global variables in indices, but I'm sure people will expect not only "path" dereferencing to work (ie. %plugin[foo].url) but for the %varname to work in a manner equivalent to arguments (allowed anywhere in the action, used in quoted strings etc). Perhaps a better choice would be instead to allow get(varname) to work in the brackets. The initial release could be limited to globals but eventually this could be expanded to "path" variables. I think this is what most people would expect to be the solution rather than a special case usage of the % symbol.

If I could have my druthers, I'd rather the % symbol be used to extend the number of arguments for actions %1 - %9 then %a - %z.

Once again, thanks for the great new feature, and thanks for krpano!

submitted with respect,
steve

13

Friday, March 19th 2010, 12:51pm

Hi,

thanks for your suggestions!
yes, get() would be probably more logically
I will add it in one of the next releases (and maybe let the '%' access in array indices undocumented)

using "fullpath" variables will also come in one of the next releases,
but this will take more time,

using %a-%z is a good and simple idea for extending the number of parameters,
but I have already added (in the next release) the possibility for using %10-%99

best regards,
Klaus

14

Saturday, March 20th 2010, 11:12pm


yes, get() would be probably more logically
I will add it in one of the next releases

...

have already added (in the next release) the possibility for using %10-%99

Klaus, I was once the Director of Marketing for a couple of software companies, so I know how rarely one gets all of what they ask for. Thanks for adding these features and making such a great tool.

steve