Showing posts with label Linden Script Language. Show all posts
Showing posts with label Linden Script Language. Show all posts

Thursday, 9 June 2011

Second Life - My Last blog

Introduction

My last blog was about sending emails and receiving Notecards. In this week's blog I will try to describe how prims can be configured to receive and forward Notecards and receive emails.

Creating a post box system

A Post Box is an object that enables users to drop/post Notecards. In addition, the Post Box system must enable the Owner to collect, read and manage posted Notecards. To achieve this requirements, I created an object that enables Second Life residents to drag and drop Notecards to it and display the collected Notecards when touched by the owner. The following image shows the object:
The first thing that need to be done is to allow users to drag and drop Notecards into my Post Box. To allow drag and drop, I added the following syntax in the state_entry() event:
llAllowInventoryDrop(TRUE);
When this is enabled, dropped objects are added to the Post Box inventory.
To add some animation to my Post Box, I added the following script that is triggered when an object is dropped on the Post Box.
This simple animation will make the Post Box jump three times in the same location when an Notecard is dropped.
Line 12 checks two actions; If an object was dropped on the prim, or if the inventory list has changed. When one of these conditions is met, the script in lines 14 to 27 is executed.
In line 15, the Post Box location is stored in a vector using llGetPos(). The movement is stored in line 16 in a variable (move). Line 17 stores the loop pointer.
Using a for loop, lines 22 and 23 will move the object vertically 3 times. When the animation is complete, using llOwnerSay(string message), a notification is sent to the owner.
To test my script, I dropped two Notecards in my Post Box and checked my Post Box Contents. The Notecards where there...
The next step is to send the received Notecards to their owner. To achieve this, I added the folowing script in the touch_start() event; this event is triggered whenever an avatar touches my Post Box.
In line 24, the Owner UUID is stored in a key variable (OwnerKey). In line 38 the llDetectedKey(0) is used to get the UUID key of the avatar touching the prim; this is compared with the Owner UUID stored in OwnerKey.
If the Owner is touching the prim, using a for loop and llGiveInventory(key avatar ID, string Object name), all Notecards are forwarded to the owner. Within the loop, the following functions are used: 
  • llGetInventoryNumber(INVENTORY_NOTECARD) – This function is used to get the total number of Notecards in the inventory.
  • llGetInventoryName(INVENTORY_NOTECARD, integer index) – This function is used to get the name of a specific Notecards, at index.
When I touch the Post Box, the Second Live viewer will launch the following dialog for each Notecard:

Receiving emails

In my last blog, I described how to create an object that can send emails using the llEmail(string email address, string subject, string message). The next step is to enable a prim to receive emails.
First I created a simple prim and using llEmail() function, I sent an email to my inbox to determine the prim email address (<primid>@lsl.secondlife.com).
In the state_entry() event I added the following:
llSetTimerEvent(5,0);
This function will trigger the timer event every 5 seconds. In the timer event, I added the following code:
timer(){
llGetNextEmail(“”,””);
}
The llGetNextEmail(string address, string subject) function, will retrieve the first queued email message from address mail box with subject as the email subject. In this case, since the parameters are omitted, the function will return all emails.
The email() event is triggered when a new email is received. To display the message contents I added the following in the email() event:
Within the email() event, one can access the following parameters:
  • time – the email message time
  • address – the email message sender email
  • subject – the email subject
  • message – the email body
  • num_left – number of emails left in the mail box
In lines 17 to 19, using the llSay() function, the message, subject and address are being displayed. The following is an example:

Conclusion

Using emails and LSL, one can further enhance a prim to receive instructions via email. This means that a prim can be configured to receive instructions by emails, parse the contents and action accordingly. Sounds cool...
One can also enhance the Post Box system to convert Notecards to emails and forward them to the object owner.
Many technologies exist within second life, and hopefully I will try to experience them in the near future. For now, this is my last blog on Second Life cause I need to move on with other topics and technologies.
Good luck with Second Life....

Tuesday, 7 June 2011

Second Life - Emails,web pages and Notecard givers

Introduction

Linden Scripting, enables residents to make use of existing web technologies. And amongst others, residents can create objects that communicate with the Internet, display web pages and send emails. In addition, residents can embed information in Notecards and share these with other residents.
Using some examples, in this blog I will describe how to send an email, launch a web page and give a Notecard to an avatar using Linden Scripting.

Emails and Web pages

The aim of this task is to create an object that can send an email and launch an Internet web page. To achieve this, using some prims, I created a chair that when touched a web page is launched in the client Internet browser. In addition,when an avatar sits on the chair, an email is send to my Gmail mailbox.
To start with, I created the chair and ensured that avatars can sit correctly without using scripting.
In Linden Scripting, the llLoadURL() function is used to launch a web page in an external Internet browser. This function is used as follows:
llLoadURL(key avatar, string message, string url);
To instruct the chair to launch a web page when touched, I used the following script:
The llDetectedKey(0) function in line 12, returns the UUID key of the avatar and stores the value in a variable. Line 13, launches a Wikipedia page and displays the message “About chairs”.
When the chair is touched, the Second Live Viewer will launch the following dialog:
In Linden Scripting to send an email, the llEmail() function is used as follows:
llEmail(string email address, string subject, string message);
Sending an email is not difficult, the tricky part in this task is how to send an email when an avatar sits on the chair.
The solution is simple. Avatars and prims are all objects of the same kind, when an avatar sits on a target prim, the avatar is linked to the target prim. So to make it simpler, if I count the number of prims when the chair is empty, the result will be 4 (the chair is made up of 4 objects). If I count the number of prims when someone is sitting on my chair, the result will be 5 (4 objects plus the avatar).
To send the email, I used the changed() event handler. Amongst others, this event is triggered when the number of prims changes. The event handler change parameter is a bit-field, and contains information on what type of change has been performed. Amongst others this bit-field can indicate when:
  • An object is added, removed from your inventory
  • An object change color
  • The number of linked objects change
For a full list, refer to changed event.
The email address of the recipient is stored in a variable in line 18. The if statement in line 21 checks if the bit-field is CHANGED_LINK. In line 23, llGetNumberOfPrims() is used to get the total number of prims.
If the total number of prims is 5, then an avatar has sit on the chair; script lines 27 and 28 are executed.
In line 27, the last linked object name within the group (the avatar) is stored in a variable using the llGetLinkName(integer index); this will be used in the email body. The email is send in line 28, and the email is as follows:
Note, the email header contains information on the Region, and the region Local-Position. This enables the recipient to identify from which area the object is sending the email.

Notecards and Givers

In Second Life, Notecards are inventory items that contain plain text or embedded items. A typical example when such notes are used is when land owners wish to provide visitors with further information related to their land.
The aim of this task is to create a Notecard giver.
To create a new Notecard and embed the Notecard to an object:
1. From My Inventory, right click the Notecards folder and select New Notecard. A new Notecard is added in the Notecards folder.
2. Provide a name for the new Notecard and fill in the description and the contents. For example, my Notecard looks something like the following:
3. Create an object and add a new script. For this task, I added a simple bench where an avatar can sit.
4. Open the object building tool bar and select the Content tab. Drag and drop the Notecard into the contents folder. Your building tool bar should look as follows:
In this example, the Notecard is given when an avatar touches the bench. To achieve this, I added the following code to the default state:
The llGetInventoryName() is used to retrieve the Notecard name. Every inventory object has an index, having the first object with an index of 0. Line 9 is retrieving the name of the first Notecard from the inventory. Line 10, gets the avatar key, this will be used as our Notecard recipient.
In line 13, using llGiveInventory(key avatar, string object name), the Notecard is given to the detected avatar.
When the bench is clicked/touched, the following dialog will notify the avatar that a Notecard is being offered and enables the user to Keep/Decline or Block the Notecard.
When accepting a Notecard, the Notecard is added to your Notecard folder in the MyInventory section.

Conclusion

While researching for the right functions to use, I bumped into some forums that stated that in Second Life, sending emails are usually used as sensors. This means that object owners use email technologies to be notified when their objects have been touched or changed (similar to an alarm).
On the other hand, Notecards and external web pages are usually used to provide more information to a visitor/residents.
Happy Teleporting...

Thursday, 2 June 2011

Second Life - The Linden Scripting

Introduction

While teleporting yourself from one land to another in second life, for sure you met people dressed with strange clothing and visited interesting places with strange buildings.
An interesting fact is that all buildings, all clothes and all strange objects that you encounter while travelling, are build by residents.
As a resident, Second Life enables you to build your own objects and store such objects in your inventory. To achieve this, the Second Life viewer provides the required tools to build your own objects, from simple static blocks to complex dynamic machines.
Static objects can be easily created; drag and drop, customize properties and that’s all you need to know. Dynamic objects are a bit more tricky because movement and logic can only be achieved by using scripting; Linden Scripting Language (LSL). Luckily for us, Second Live provides a script editor that enables you to create, debug and test your scripts.
This blog is all about scripting. I will try to explain some code blocks that I created while getting acquainted with the Linden Scripting language.
All scripting mentioned in this blog were created and tested on Fermi Sandbox; a land that enables residents to build their own objects for free.

Linden Scripting Language

The Linden Scripting Language (LSL) is used within Second Life to give behavior and animate avatars and primitives (prims).
The LSL is based on State Machines. Machines are objects that can change their state according to some Input. To better understand state machines, let’s assume that we have a light bulb. Unless the light bulb is not damaged or broken, the bulb can be in two different states; on or off. And an input to change the bulb state can be a switch.
Similar to other programming languages, LSL is made up of the following components:
  • Functions – These blocks of code, return results and modify objects based on parameters. Functions can be called and executed from other functions or Events to perform mathematical calculations and modify objects. In Second life a number of pre-defined functions are already built and for a full list of functions, refer to LSL Functions.
  • Events – These can be used as listeners. When an event is associated with an object, the event will stay idle until an event occur. When an event occurs, the code within the event is executed. For example, an event can be used to display a message when an avatar touches a specific prim. For a full list of pre-defined events, refer to LSL Events.
  • Types – LSL is strongly typed, variables have to be declared with their variable type. In LSL various types are supported, and amongst others you can create Integers, Floats and Strings. Similar to other programming languages, in LSL, type casting is supported. For example, you can change a String to an Integer and vice versa. For more information on Types refer to LSL Types.
  • Operators – These are used to perform mathematical functions and comparison. Amongst others, LSL supports, addition, subtraction, multiplication and many more. For a full list of supported operators, refer to LSL Operators.
  • Constants – Constant values can be used to refer to objects and object properties. Unlike variables, such values cannot be changed. For a full list of constants, refer to LSL Constants.
  • Libraries – LSL contains a list of pre-defined scripts that can be copied and used for free. Second Life residents can contribute to this list by creating their scripts and uploading them into the LSL library. For more information, refer to LSL Library
  • Flow Control – Similar to other languages, LSL supports, looping, function calling and conditional comparisons. Using loops and conditions you can iterate in a list of objects or call a function a number of times. For more information, refer to LSL Flow Control.

Create a basic script

The best way to describe how to create a basic script is by showing an example. Let us assume that we want to create a block that displays a message when is touched by an avatar.
1.    I teleported my avatar to Fermi Sandbox. This land enables you to build and test your prims for free.
2.    Right click an empty space and select Build. This will launch the Build toolbar.
3.    Select the Cube icon and the Create (Magic wand).
4.    Click an empty space to add the new block.
5.    In the Build toolbar, click Content and New Script. This will create a new script file containing the default syntax.
6.    Double click the new script file to launch the Script editor. The content should be similar to the following:
7.    Close the Build toolbar and test your prim.
When the prim is in the default state, the state_entry event will display some text using the llSay(<Channel>,<Text to display>).The event touch_start is executed when the prim is touched by an avatar.

Display messages

The following functions can be used by a prim to display a message:

Function
Description
Example
llSay(<Channel>,<Text to display>)
Text can be heard by everyone within 20 meters and can be 1023 bytes in length. To prevent recursion, a prim cannot llSay text to itself.
llSay(0,"Hello, Avatar!");

llOwnerSay(<Text to display>)
Test can be heard only by the prim owner. Messages longer that 1023 bytes are truncated.  The message will disappear after 45 seconds when the owner leaves the prim region.
llOwnerSay("Hello Owner!" );
llInstantMessage(<Key>,<Text>);
Message is send via chat to a specific avatar. The Key is used to identify the recipient of the message (Avatar UUID).
llInstantMessage(llDetectedKey(0),"You have been registered!");
NOTE: llDetectedKey(0) is used to get the avatar UUID.
llShout(<Channel>,<Text>);

Text can be heard by everyone within 100 meters and can be 1023 bytes in length. To prevent recursion, a prim cannot llShout text to itself.
llShout(0,"Hello All" );
llWhisper(<Channel>,<Text> );

Text can be heard by everyone within 10 meters and can be 1023 bytes in length. To prevent recursion, a prim cannot llWhisper text to itself.
llWhisper(0,"whispering" );


Chat with a prim

An object can be instructed to listen to “chat messages” generated by another object. The following example shows a prim that will echo your message and display your name when you speak.
When the default state is initialized the code in line 6 will call the listen event. When the listen event is triggered, the messages are displayed using the llInstantMessage function.
The function llListen triggers the listen event and is constructed as follows:
llListen(<Channel>, <Object Name>,<Object UUID>,<Text Spoken>);
The above code will produce the following output when I say “Hello Prim”:

Moving an object

Using vectors you can instruct an object to move to a specific position in LSL. A vector is a data type made up of three float values. You can specify the X, Y and Z coordinates in a vector to represent a specific position in SL. A vector can be created by using the following syntax:
vector vec=<<X Value>, <Y Value>, <Z Value>>;
The following example shows a prim that when touched, the prim moves in 4 random positions. Once ready, the prim will return to its initial position.
To start with, I created a function that generates a random vector(random move) using the llFrand function as follows:
This function will create a vector with 2 random numbers. Since the block will not move vertically on the Z axis, only the X and Y axis are altered.
The next step is to create a global variable to store the prim initial position:
//Prim initial position
vector initialPosition;
The default state syntax is as follows:
When the prim is in the default state, the prim will whisper a welcome message to the avatar (line 17). When the prim is touched, the touch_start event stores the current prim position and change the prim state to move.
The move state syntax is as follows:
When the prim enters the move state, a loop that will iterate for 4 times is started. The loop will display a message in line 36.
In Line 37 the random vector from getRandomVector() function is added to the prim current position and the result is set as the prim current position. The algorithm is as follows:
Current Position = Current Position + Distance to move
Using the llSleep(<Time in Seconds>) at line 38, the event is halted for 1 second. In line 39 the repeat counter is incremented.
When the loop is finished, the event will display a message, will move the prim to its initial position and will change the prim to the default state.
One thing to note is, if you sit on this block and click on it, the avatar will move with the block.

Changing color

The llSetPrimitiveParams(<parameters and values>) function enables you to change any prim property. In the following example, I linked a ball shaped prim on s stand to simulate a “stand light”. By default the ball shaped prim is colored in black and transparent. When touched, the ball shaped prim is colored yellow with a bright effect. The following code will do the trick:
In the default state, the PRIM_COLOR parameter is used to set the color to <0,0,0> (RGB color code for black), while the PRIM_FULLBRIGHT parameter is used to remove the bright effect.
When the prim is touched, the state will change to on, the PRIM_COLOR is set to <1,1,0>(RGB Color code for yellow) and the PRIM_FULLBRIGHT parameter is set to true. The prim will return to default state if touched for the second time.

Using messages

Typically to build something in Second Life you’ll have to build and link various prims to form a single unit. When multiple prims are grouped, you can move the group and save the group in your inventory as a single unit.
A group of linked prims is made up of only one parent/root prim (the last prim selected when linking) and a number of children (child prims).
Message passing in LSL, enables you to send messages and instructions between prims through scripting. To explain this, let us assume that we have an object made up of multiple prims, and we want that all prims change color when the object is touched. This can only be achieved through message passing. When the parent prim is touched, the parent prim sends a message using llMessageLinked() to all child prims. All children must have the event link_message(), this is triggered when the script receives a link message sent by llMessageLinked().
The following script is added to the parent script and is used to send a message to all child prims:
When the default state is entered, line 6 will get the number of prims using llGetNumberOfPrims() and will store the value into a local variable. Using llMessageLinked(), the script sends the color vector to use <0,0,1> (blue) as a parameter to all child prims.
In line 17, the prim will change to StateOne when touched.
When the parent script is in StateOne, using llMessageLinked(), the script sends the color vector to use <0,1,0> (red) as a parameter to all child prims.
In line 44, the prim will change back to the default state when touched.
All child prims should implement the following code:
When a child prim receives a message, the link_message() event is triggered and the code in line 4 is executed.
In line 4, using llSetPrimitiveParams() function, the prim color is changed according to the variable str. The following screenshots show the prims changing colors using the code described in this section.

Conclusion

Objects, scripting and imagination, made Second Life as it is. Residents can create their own objects and customize their appearance using Second Life building tools.
Using LSL, you can add logic, animate and interact with building blocks (prims). LSL syntax is very similar to the commonly used web programming languages; the only difference is that is based on state machines.
While I tried to script my own objects, I learned how much effort was done to build places I’ve visited in the last few days. Creating a block with some basic scripting is one thing, creating a whole city is a lot of time, patience and persistence.
Happy scripting…

Resources