Difference between revisions of "LSL 101/Variables"
m (<lsl> tag to <source>) |
|||
(21 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:LSL 101]] | [[Category:LSL 101]] | ||
{{NavNextPrev|prev= | {{NavNextPrev|prev=The touch start Event|next=Strings and Simple Output}} | ||
{{LSL Wikibook Index}} | |||
==Data types - Variables == | |||
LSL accepts seven types of [[LSL_Variables |variable]] data: string, key, integer, float, vector, rotation, or list. We will discuss each type below. | |||
< | The value of the variable is limited by its type. There is more on this below, too. | ||
Constants are variables where the data doesn't change, they're defined by the system and you'll see them in CAPITAL letters throughout. The Boolean Constants TRUE and FALSE and there are many predefined constants in LSL. There is a list at [https://wiki.secondlife.com/wiki/Category:LSL_Constants LSL Constants] | |||
This page might seem too long, but the only other option was seven separate pages, so please bear with it, there's a lot of information, but every effort has been made to not be redundant or overly detailed. Each section head is a link to the official SL wiki page for that data type. | |||
===[[String|string]]=== | |||
A string is text data enclosed in " double quotes ". Any character or number, symbol or sign can be used as text data. | |||
Strings can be joined together by using a + plus sign (called the *+ [[Operator|operator]]*) | |||
If you need to use accents, new lines or other special characters and it's just not working out, read the notes on the [[String|string]] wiki page. | |||
See [[LSL 101/Strings and Simple Output | Strings and Simple Output]] and [[LSL_101/String_Concatenation | String Concatenation ]] which are part of the LSL 101 and contain more information and examples for this heavily used type of data. | |||
===[[Key|key]]=== | |||
Key data is the [[UUID|Universally Unique Identifier]] for every object, texture, sound, animation, and avatar inworld. Each has some combination of 36 dashes, numbers or letters. | |||
Objects that are taken to inventory and re-rezzed get a new key on-rez. This is why servers have to stay in the same place inworld to work with delivery systems. If the server is taken to inventory, it loses its UUID and its daughter prims can no longer find it, as the new UUID was selected by the system at random. | |||
Avatar keys as well as keys for imported sounds, animations & avatars remain constant, unless stored in a box and returned to inventory at which point they receive new keys. An item must remain active in your inventory for its key to be accessible inworld. | |||
But how to get a key? | |||
* someone gives it to you | |||
* use a function like [[LlGetKey|llGetKey]] and the one in the next example | |||
* in inventory on full permission items by right clicking and selecting "copy asset UUID." | |||
This script solves two problems: how to get the avatar keys of people who touch your stuff, and how to keep the prim from losing touch of the number of poky fingered friends of yours who just have to push the red button labeled "don't push this button". It will tell you the name & UUID key of each toucher in roughly the order of touching. | |||
<source lang="lsl2"> | |||
default | |||
{ | |||
touch_start(integer total_number) | |||
{ | |||
integer number = 0; // start at zero | |||
do | |||
llOwnerSay(llDetectedName( number ) + "'s key is: " + (string) llDetectedKey(number)); | |||
// tell my owner each toucher's name & key | |||
while(total_number > ++number); | |||
// while the total number from the touch_start event | |||
// is greater than the incremented number ( ++number ) | |||
} | |||
} | |||
</source> | |||
===[[Integer|integer]]=== | |||
Integers are numbers, but only a limited set of numbers. Integers in LSL are any numbers between −2,147,483,648 and +2,147,483,647, so long as they are 'whole' numbers (that is, they don't have a decimal point, like 1.5). | |||
Integers are declared and defined like this | |||
<source lang="lsl2"> | |||
integer myNumber = 42; | |||
</source> | |||
To a computer *TRUE* and *FALSE* are also integers. In fact, almost all constants are integers, the ones that are can be expressed in TRUE (value of 1) or FALSE = (value of 0). | |||
And because these are numbers we can use number [[LSL_Operators|Operators]] to manipulate them. | |||
LSL uses + for addition, - for subtraction, * for multiplication and / for division as long as the answer falls in between −2147483648 to 2147483647 the range of numbers available. | |||
LSL also uses > Greater than and < Less Than as well as == equals (note the double =, a single = means an assignment, not a comparison) and the infamous "oh that's what that means" != which is does not equal. LSL uses ++ for increment (count up) and -- for decrement (count down) | |||
In addition there are &, %, ^, |, || which have more specialized uses as shown on the [[LSL_Operators| LSL Wiki Operators Page]]. | |||
In string data, the + plus sign is also used to join two strings which is called "concatenation". | |||
More information is coming later in this tutorial at [[LSL 101/LSL in Focus:Integers#Signed Integers|Arithmatic Operators]]. | |||
There is a lot more information on [[LSL_101/Integers |Integers]] which is part of this tutorial but not absolutely necessary to read right now. | |||
===[[Float|float]]=== | |||
Floats are numbers with decimal points. This example declares and uses float data. | |||
<source lang="lsl2"> | |||
float min = 1.0; | |||
float max = 10.0; | |||
default | default | ||
{ | { | ||
state_entry() | |||
{ | |||
llOwnerSay("My minimum value is " + (string)min + "and my maximum value is " + (string)max); | |||
} | |||
} | |||
</source> | |||
Notice the *typecasting* of the float to a string by the phrases | |||
<source lang="lsl2"> | |||
(string)min | |||
(string)max | |||
</source> | |||
In LSL typecasting from integer (1) to (1.0) is what is called *implicit* - meaning the system will let you get away with it, and I'll show you an example in the next section. | |||
The following operators can be applied to floats: + - * / . You can not use % & | << >> ^ . | |||
===[[Vector|vector]]=== | |||
Vectors use three floats enclosed in < pointy brackets > and set off by commas to express XYZ or RGB data and use the same Operators as floats. | |||
Example snippet: | |||
<source lang="lsl2"> | |||
vector white = <1,1,1>; // but wait you said floats ?? | |||
vector black = <0,0,0>; // yes I did, keep reading | |||
vector grey = < 0.5, 0.5, 0.5 >; // oooh, it's an *implicit float* | |||
//you can use an integer or a float and the system will accept it. | |||
vector red = < 1.0, 0.0, 0.0 >; | |||
vector green = < 0.0, 1.0, 0.0 >; | |||
vector blue = < 0.0, 0.0, 1.0 >; | |||
vector yellow = < 1.0, 1.0, 0.0 >; | |||
vector cyan = < 0.0, 1.0, 1.0 >; | |||
vector magenta = < 1.0, 0.0, 1.0 >; | |||
</source> | |||
Vectors are often used for X,Y,Z data for [[LlGetPos | Position]], [[LlSetVelocity|Velocity]], and [[LSL Color|Color]] as in the example above, and they also hold data for things which only have two dimensions, the third one is given the value of zero. One example of this is in Particles, where each sprite can only have sizes in X & Y so the third value is always zero or FALSE. Another is texture repeats, which only have X,Y data and are always shown in vector format such as <1,1,0> or <0.3,0.3,FALSE> . | |||
If you need only part of a vector use this format | |||
<source lang="lsl2"> | |||
default | |||
{ | |||
touch_start(integer total_number) | |||
{ | |||
vector test=llGetScale(); | |||
llOwnerSay("My dimensions are: " + (string)test); | |||
llOwnerSay("My Z dimension is: " + (string)test.z); // Outputs only the Z size | |||
} | |||
} | |||
</source> | |||
===[[Rotation|rotation]]=== | |||
Rotation data is expressed in quaternions, which consists of 4 float elements: x, y, z, and s. It looks like <0.0,0.0,0.0,1.0>, but many scripts use vector data for XYZ (known as Euler representation) and some mathematical function to convert them to rotations. | |||
Scripts involving angles or rotations often make use of the following float constants:- | |||
PI_BY_TWO equals 90 degrees, expressed in radians | |||
TWO_PI equals 360 degrees, expressed in radians | |||
there is also a predefined rotation constant ZERO_ROTATION which effectively means 'no rotation' | |||
Rotation scripts work differently if they are in the child prim of an object or in the root prim. | |||
Perhaps the most common rotating script uses llTargetOmega to make prims spin, although that simple function uses vector data and not a quaternion. Here's an example: | |||
<source lang="lsl2"> | |||
default | |||
{ | |||
state_entry() | |||
{ | |||
// rotate one time per second around X axis. | |||
llTargetOmega(<1.0,0.0,0.0>, TWO_PI, 1.0); | |||
} | |||
} | |||
</source> | |||
That's super handy if you want perfect X Y or Z orientation, but to get an object to spin around a tilted center requires a bit of math. Don't worry, the system does most of it for you! | |||
Look at this script. | |||
< | <source lang="lsl2"> | ||
default | |||
{ | |||
state_entry() | |||
{ | |||
// rotate one time per second around local X axis | |||
// think globes ! | |||
llTargetOmega(<1.0, 0.0, 0.0>*llGetRot(), 0.1, 0.01); | |||
} | |||
} | |||
</source> | |||
Here the vector for XYZ of rotation is being multiplied by a function, llGetRot(), which *gets* the current rotation of the prim, giving it to you as a quaternion. (It's not a mathematical multiplication, '*' just happens to be the symbol used to combine rotations). | |||
< | You can also get only parts of the rotation and use that as shown in this snippet example | ||
<source lang="lsl2"> | |||
float x = 0.0; | |||
float y = 0.0; | |||
float z = 0.0; | |||
float s = 1.0; | |||
rotation rot_a = <0.0, 0.0, 0.0, 1.0>; //copies these values into the respective values of the rotation. | |||
rotation rot_b = <x,y,z,s>; //copies the values of the variable into the rot. | |||
rotation rot_c = rot_b; //copies the value of rot_b into rot_c | |||
// this snippet brought to you by the [http://lslwiki.net/lslwiki/wakka.php?wakka=rotation *other page* on rotations]. | |||
</source> | |||
There are ready made functions to help you with rotations including [[LlEuler2Rot|llEuler2Rot]] and [[LlRot2Euler|llRot2Euler]] | |||
If you're going to be brave enough to do rotations of objects other than these simple examples, please read the entire LSL Wiki page [[Rotation|rotation]] first. | |||
One of the most interesting, and very accessible uses for rotations in SL is for [ http://www.heatonresearch.com/stories/encogia-ferris-wheel.html |Ferris Wheels], the scripts on that page from Jeff Heaton are excellent demonstrations of LSL rotations. | |||
===[[LSL List|list]]=== | |||
A list is a data type which can contain nothing or several *elements* or items. For example, when I start making my grocery list, it's empty, then I write all the things I need, and later when I get them, I will scratch them off the list. My list might never get empty, but it could. | |||
Lists are set off from their world by [ square brackets ] and the items inside are separated by commas. | |||
Lists can contain all the other data types | |||
<source lang="lsl2"> | |||
default | |||
{ | |||
touch_start(integer total_number) | |||
{ | |||
string clear = "8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"; | |||
// we can define elements that go inside lists | |||
< | list a = ["abc", 123 , 3.1416, < 1.0, 1.0, 1.0 > , <0.0,0.0,0.0,1.0>,clear]; | ||
integer i; | |||
integer s = llGetListLength(a); // count it up | |||
do | |||
llOwnerSay(llList2String(a,i)); // list it out | |||
while(s>++i); // while the length of the list is greater than the number of items said | |||
} | |||
} | |||
</source> | |||
Lists are really important in [[LlSetTextureAnim|texture animations]] and [[LlParticleSystem|particle effects.]] | |||
==Conclusion== | |||
Thank you for staying all the way to the bottom of the data types, much more information is available in the links. | |||
'''Continue this tutorial with [[LSL 101/Strings and Simple Output|Strings and Simple Output]].''' |
Latest revision as of 12:49, 24 January 2015
← The touch start Event | ↑̲ LSL 101 ̲↑ | Strings and Simple Output → |
Data types - Variables
LSL accepts seven types of variable data: string, key, integer, float, vector, rotation, or list. We will discuss each type below.
The value of the variable is limited by its type. There is more on this below, too.
Constants are variables where the data doesn't change, they're defined by the system and you'll see them in CAPITAL letters throughout. The Boolean Constants TRUE and FALSE and there are many predefined constants in LSL. There is a list at LSL Constants
This page might seem too long, but the only other option was seven separate pages, so please bear with it, there's a lot of information, but every effort has been made to not be redundant or overly detailed. Each section head is a link to the official SL wiki page for that data type.
string
A string is text data enclosed in " double quotes ". Any character or number, symbol or sign can be used as text data.
Strings can be joined together by using a + plus sign (called the *+ operator*)
If you need to use accents, new lines or other special characters and it's just not working out, read the notes on the string wiki page.
See Strings and Simple Output and String Concatenation which are part of the LSL 101 and contain more information and examples for this heavily used type of data.
key
Key data is the Universally Unique Identifier for every object, texture, sound, animation, and avatar inworld. Each has some combination of 36 dashes, numbers or letters.
Objects that are taken to inventory and re-rezzed get a new key on-rez. This is why servers have to stay in the same place inworld to work with delivery systems. If the server is taken to inventory, it loses its UUID and its daughter prims can no longer find it, as the new UUID was selected by the system at random.
Avatar keys as well as keys for imported sounds, animations & avatars remain constant, unless stored in a box and returned to inventory at which point they receive new keys. An item must remain active in your inventory for its key to be accessible inworld.
But how to get a key?
- someone gives it to you
- use a function like llGetKey and the one in the next example
- in inventory on full permission items by right clicking and selecting "copy asset UUID."
This script solves two problems: how to get the avatar keys of people who touch your stuff, and how to keep the prim from losing touch of the number of poky fingered friends of yours who just have to push the red button labeled "don't push this button". It will tell you the name & UUID key of each toucher in roughly the order of touching.
default
{
touch_start(integer total_number)
{
integer number = 0; // start at zero
do
llOwnerSay(llDetectedName( number ) + "'s key is: " + (string) llDetectedKey(number));
// tell my owner each toucher's name & key
while(total_number > ++number);
// while the total number from the touch_start event
// is greater than the incremented number ( ++number )
}
}
integer
Integers are numbers, but only a limited set of numbers. Integers in LSL are any numbers between −2,147,483,648 and +2,147,483,647, so long as they are 'whole' numbers (that is, they don't have a decimal point, like 1.5).
Integers are declared and defined like this
integer myNumber = 42;
To a computer *TRUE* and *FALSE* are also integers. In fact, almost all constants are integers, the ones that are can be expressed in TRUE (value of 1) or FALSE = (value of 0).
And because these are numbers we can use number Operators to manipulate them.
LSL uses + for addition, - for subtraction, * for multiplication and / for division as long as the answer falls in between −2147483648 to 2147483647 the range of numbers available.
LSL also uses > Greater than and < Less Than as well as == equals (note the double =, a single = means an assignment, not a comparison) and the infamous "oh that's what that means" != which is does not equal. LSL uses ++ for increment (count up) and -- for decrement (count down)
In addition there are &, %, ^, |, || which have more specialized uses as shown on the LSL Wiki Operators Page.
In string data, the + plus sign is also used to join two strings which is called "concatenation".
More information is coming later in this tutorial at Arithmatic Operators.
There is a lot more information on Integers which is part of this tutorial but not absolutely necessary to read right now.
float
Floats are numbers with decimal points. This example declares and uses float data.
float min = 1.0;
float max = 10.0;
default
{
state_entry()
{
llOwnerSay("My minimum value is " + (string)min + "and my maximum value is " + (string)max);
}
}
Notice the *typecasting* of the float to a string by the phrases
(string)min
(string)max
In LSL typecasting from integer (1) to (1.0) is what is called *implicit* - meaning the system will let you get away with it, and I'll show you an example in the next section.
The following operators can be applied to floats: + - * / . You can not use % & | << >> ^ .
vector
Vectors use three floats enclosed in < pointy brackets > and set off by commas to express XYZ or RGB data and use the same Operators as floats.
Example snippet:
vector white = <1,1,1>; // but wait you said floats ??
vector black = <0,0,0>; // yes I did, keep reading
vector grey = < 0.5, 0.5, 0.5 >; // oooh, it's an *implicit float*
//you can use an integer or a float and the system will accept it.
vector red = < 1.0, 0.0, 0.0 >;
vector green = < 0.0, 1.0, 0.0 >;
vector blue = < 0.0, 0.0, 1.0 >;
vector yellow = < 1.0, 1.0, 0.0 >;
vector cyan = < 0.0, 1.0, 1.0 >;
vector magenta = < 1.0, 0.0, 1.0 >;
Vectors are often used for X,Y,Z data for Position, Velocity, and Color as in the example above, and they also hold data for things which only have two dimensions, the third one is given the value of zero. One example of this is in Particles, where each sprite can only have sizes in X & Y so the third value is always zero or FALSE. Another is texture repeats, which only have X,Y data and are always shown in vector format such as <1,1,0> or <0.3,0.3,FALSE> .
If you need only part of a vector use this format
default
{
touch_start(integer total_number)
{
vector test=llGetScale();
llOwnerSay("My dimensions are: " + (string)test);
llOwnerSay("My Z dimension is: " + (string)test.z); // Outputs only the Z size
}
}
rotation
Rotation data is expressed in quaternions, which consists of 4 float elements: x, y, z, and s. It looks like <0.0,0.0,0.0,1.0>, but many scripts use vector data for XYZ (known as Euler representation) and some mathematical function to convert them to rotations.
Scripts involving angles or rotations often make use of the following float constants:-
PI_BY_TWO equals 90 degrees, expressed in radians TWO_PI equals 360 degrees, expressed in radians
there is also a predefined rotation constant ZERO_ROTATION which effectively means 'no rotation'
Rotation scripts work differently if they are in the child prim of an object or in the root prim.
Perhaps the most common rotating script uses llTargetOmega to make prims spin, although that simple function uses vector data and not a quaternion. Here's an example:
default
{
state_entry()
{
// rotate one time per second around X axis.
llTargetOmega(<1.0,0.0,0.0>, TWO_PI, 1.0);
}
}
That's super handy if you want perfect X Y or Z orientation, but to get an object to spin around a tilted center requires a bit of math. Don't worry, the system does most of it for you!
Look at this script.
default
{
state_entry()
{
// rotate one time per second around local X axis
// think globes !
llTargetOmega(<1.0, 0.0, 0.0>*llGetRot(), 0.1, 0.01);
}
}
Here the vector for XYZ of rotation is being multiplied by a function, llGetRot(), which *gets* the current rotation of the prim, giving it to you as a quaternion. (It's not a mathematical multiplication, '*' just happens to be the symbol used to combine rotations).
You can also get only parts of the rotation and use that as shown in this snippet example
float x = 0.0;
float y = 0.0;
float z = 0.0;
float s = 1.0;
rotation rot_a = <0.0, 0.0, 0.0, 1.0>; //copies these values into the respective values of the rotation.
rotation rot_b = <x,y,z,s>; //copies the values of the variable into the rot.
rotation rot_c = rot_b; //copies the value of rot_b into rot_c
// this snippet brought to you by the [http://lslwiki.net/lslwiki/wakka.php?wakka=rotation *other page* on rotations].
There are ready made functions to help you with rotations including llEuler2Rot and llRot2Euler
If you're going to be brave enough to do rotations of objects other than these simple examples, please read the entire LSL Wiki page rotation first.
One of the most interesting, and very accessible uses for rotations in SL is for [ http://www.heatonresearch.com/stories/encogia-ferris-wheel.html |Ferris Wheels], the scripts on that page from Jeff Heaton are excellent demonstrations of LSL rotations.
list
A list is a data type which can contain nothing or several *elements* or items. For example, when I start making my grocery list, it's empty, then I write all the things I need, and later when I get them, I will scratch them off the list. My list might never get empty, but it could.
Lists are set off from their world by [ square brackets ] and the items inside are separated by commas.
Lists can contain all the other data types
default
{
touch_start(integer total_number)
{
string clear = "8dcd4a48-2d37-4909-9f78-f7a9eb4ef903";
// we can define elements that go inside lists
list a = ["abc", 123 , 3.1416, < 1.0, 1.0, 1.0 > , <0.0,0.0,0.0,1.0>,clear];
integer i;
integer s = llGetListLength(a); // count it up
do
llOwnerSay(llList2String(a,i)); // list it out
while(s>++i); // while the length of the list is greater than the number of items said
}
}
Lists are really important in texture animations and particle effects.
Conclusion
Thank you for staying all the way to the bottom of the data types, much more information is available in the links.
Continue this tutorial with Strings and Simple Output.