You are currently browsing the monthly archive for April 2008.

Temp-on-rez is a prim setting which will keep a prim ‘alive’ for a fixed amount of time, after which it will be removed. It is a very handy feature with a number of legitimate uses, the most common of which I suppose are bullets and vendor displays (which temporarily rez examples of the items for sale).

Unfortunately it is sometimes used as a way of circumventing Second Life’s prim limits. There are gadgets you can get which will essentially keep temp-on-rez items permanently alive (basically they re-rez the items every time the temp-on-rez reaches its time-out).

If you’ve been tempted by these gadgets, or if you’re actually thinking of trying to create one, please, please don’t.

The prim limits are there for a reason. The more prims there are in a sim, the heavier the load on the Second Life servers. Using the temp-on-rez to bypass the limits simply increases the load, and makes the Second Life experience even worse than it already is, not only for other users but for you (the temp-on-rez abuser!) yourself.

Second Life is struggling enough as it is. Don’t make it worse.

Thank you.

A Little History

Second Life has long had a system for displaying video on a prim. This is the parcel-media system, whereby you can supply a URL for a video feed, and the video will be displayed on an assigned texture (if you have never seen this before, the set-up for it is on the last tab of the About Land dialog). Its main restriction has been (and still is) that only one video can be displayed on each parcel of land. You can have any number of prims displaying the video, but they will all display the same video.

It has always been possible to display output from a web-site to the parcel media stream, although it was never easy. If you are interested, it involves creating a CGI script on a web-site to generate an image. By then pointing the parcel-media URL at this script, the image will be displayed on any prim which uses the parcel-media texture.

I experimented with this myself a little while ago, and got a system up and running which would display text which was ‘chatted’ by an avatar. I had ideas about creating some sort of live broadcast system. Unfortunately, the Quicktime vulnerability then appeared, and for some time anyone with any sense kept parcel-media switched off. I stopped experimenting at that point, and didn’t go back to it even after the vulnerability was fixed.

Recent Changes

The more recent versions of Second Life include the ability to directly display a web-page via the parcel-media. Point the parcel-media URL at a web-page, and the page will be displayed on the parcel-media texture.

This brings us a step closer to the long-promised HTML-on-a-prim, but we aren’t quite there yet. For a start, this system only applies to parcel-media, and hence suffers from the same restrictions that parcel-media suffers from. There are also some quirks in the way in which the web-pages are displayed.

The main problem that I have found is that the pages seem to rendered at a fixed size (it looks to be something like a 1024 x 1024 area). If the webpage is too large to fit this, scroll-bars will appear. Of course, because the page is essentially just displayed as an image, these scroll-bars are inactive in Second Life. It also means that you have to display the page on a fairly sizeable prim in order for a normal web-page to be readable. It would have been nice to have the ability to display only part of the web-page, with it sizing to fit the prim.

Implementing a Broadcaster

So much for the background. Now, how can we make use of this? Obviously, we can just display a web-page, but there other things that can be done, such as creating genuinely active text. That’s what I want to demonstrate in this post. It is going to be rather simplistic and limited, but it should be quite easy to extend the basic idea into something more sophisticated and useful.

To make particular example work, you will need a website that handles PHP, and that you can upload files to. You will also need to own or rent a parcel of land that you can change the parcel-media on (obviously!).

Let’s start with the PHP script (if you are more familiar with other web-page scripting languages, it should not be difficult to adapt this script):

<html>
<head></head>
<style>body { font-size: 64pt; font-family: Verdana, sans-serif }</style>
<body>
<?php

// Get the text to display.
$contents = stripslashes($_GET&#91;"contents"&#93;);

// Only works with PHP compiled as an Apache module.
$headers = apache_request_headers();
$ownerKey = $headers&#91;"X-SecondLife-Owner-Key"&#93;;

// Output the text.
echo("<p>".$contents."</p>\n");

?>
</body>
</html>

This script expects to be passed a ‘comments’ parameter containing the text to be displayed. For example, assuming you have saved the script as broadcast.php, the following would be used to call the script:

broadcast.php?contents=This%20is%20a%20test.

This would display a web-page with the line “This is a test.”.

A couple of other points: the code above includes a line to read the owner key, but doesn’t make any use of it. In a real situation you would probably want to use this as the basis for some kind of security (remember that anyone with a browser can call this script!). There are also a number of other headers which are available — see the LSL Wiki for more information about them.

Also note that I have set the font-size to a rather large 64 points! This is so that the line of text will show up at a reasonable size on our display.

Now for the Second Life side.

For this example we will set up a script that will listen on a specified channel, and will use our web-script to display anything which is chatted on that channel. We will also set up a timer that will automatically clear the text and replace it with a default after 30 seconds.

In this example I am using a script on my own website — you should replace the URL with the appropriate path for your own site. You can make use of the script on my website if you want to just try things out, but it will display my own logo, and is not guaranteed to stay on the website for long, as it is only a test.

string text;
string baseUrl = "http://ejournal.cyberias.net/broadcast.php?contents=";
integer anyoneCanUse = TRUE;
key avatar;
integer handle;
integer onChannel = 1234;

init()
{
  text = llEscapeURL("Chat some text on channel /" + (string)onChannel);
  string url = baseUrl + text;
  llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_URL, url, PARCEL_MEDIA_COMMAND_PLAY, PARCEL_MEDIA_COMMAND_LOOP]);
}

send()
{
  string url = baseUrl + text;
  llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_URL, url]);
}

default
{
  state_entry()
  {
    llSetTimerEvent(30.0);
    handle = llListen(onChannel, "", avatar, "");
  }

  listen(integer channel, string name, key id, string message)
  {
    if (channel == onChannel)
    {
      llSetTimerEvent(0.0);
      text = llEscapeURL(message);
      send();
      llSetTimerEvent(30.0);
    }
  }

  timer()
  {
    text = llEscapeURL("Chat some text on channel /" + (string)onChannel);
    send();
  }

  state_exit()
  {
    llListenRemove(handle);
    llSetTimerEvent(0.0);
  }
}

Create a prim, and apply your parcel-media texture to one face. Create a script in the prim, and replace the default contents with the above code.

Anyone who stands near the prim and chats on the specified channel will have the chat displayed on the prim (provided, of course, that they have video switched on).

Here is my own test broadcaster in action:

Text on a Prim!

Where’s the point in having a blog if you can’t use for some occasional self-advertisement? Actually, some people’s blogs are solely for this purpose, so I think I can be excused (and I’ve marked this as entry 1 because I intend to more in future — you have been warned!)

Arcane Designs StoreI have recently completed my first significant gadget for Second Life, a functioning reproduction of a Victorian Magic Lantern. To show it off, and to make a place for selling both it and other things I might create, I’ve built a small store, Arcane Designs, next to Morgridge Mansion.

As a matter of fact, I’ve already got a second item on sale, which is my Psychic Card Table, a Second Life version of a card trick which I have seen elsewhere on the Internet. It has been on display in the Mansion for some time, as a sort of conversation-piece, but I’ve decided I might as well put it on sale.

Both items are also available from SL Exchange. You want to see them here first? All right, you’ve twisted my arm.

Magic LanternPsychic Card Table

Links

Morgridge Mansion
If you have Second Life installed you can use this link to teleport to Morgridge Mansion. It will actually drop you at the hub. Walk north-west to get to the Mansion itself — it isn’t very far.

SL Exchange Page

As with all my script posts, I am assuming here that you already know the basics of how to create and edit prims and scripts.

I’ve already covered the rotation option for animating textures, in my post about creating a simple rippling water texture. In this post, however, I want to look at the other animation options, and give some examples. The only one I’m not going to cover is the scaling option, which works in a similar way to the rotation option, but which I have never found a real use for.

Let’s start with what most people think of in terms of texture animations, which is where the animation displays a series of ‘frames’. As a simple example, here is an alternative way of creating a rippling water effect, this time using an animation. To see this in action, rez a cube, and create a new script for it. Replace the contents of the script with the following:

default
{
 state_entry()
 {
  llSetTexture("349b2fec-0f7e-bd5f-5bcc-7090d27ae0fb", ALL_SIDES);
  llSetTextureAnim(ANIM_ON | LOOP, ALL_SIDES, 3, 3, 1, 9, 12.0);
 }
}

As with all the examples in this post, I am taking the textures from the asset server using their UUID, so they should be available to anyone. Of course, you don’t have to do it this way – you can apply animated textures to the prim in the normal way if you want (in which case you can remove the llSetTexture call in the above example).

The texture in this example is 128 x 128, and has the frames laid out in a 3 x 3 grid (the texture was created using the Gimp drawing package). It is actually rather smaller than is necessary, and hence not very high quality. A 256 x 256 version of the texture would be better quality, and would still load reasonably quickly.

Let’s look at each of the parameters of the llSetTextureAnim function.

The first parameter is a set of flags which are combined together using an OR (the ‘|’ symbol). In my example, only two options are included: ANIM_ON, which switches the animation on (no surprise there!) and the LOOP option, which tells the animation to return to the beginning and start again once it has reached the last frame. The alternative to LOOP is PING-PONG, which still keeps the animation running continuously, but when it reaches the last frame it then plays the frames in reverse until it gets back to the first frame, and so on.

If you don’t specify one or other of LOOP or PING-PONG the animation will play through just once and then stop (it will redisplay the first frame, though). We’ll see a possible use for this later.

The other possible flags for this parameter are SCALE, ROTATE, REVERSE, and SMOOTH. As I said above, I won’t be going in to SCALE and ROTATE in this post. REVERSE simply plays the animation backwards. I’ll come back to the SMOOTH option later.

The next two parameters tell the function how the frames are laid out in the texture. In my example, they are laid out in a 3 x 3 grid, so we set both values to 3. A common alternative would be to have the frames laid out horizontally in a long strip. If this sample texture had been done that way we would have had a strip 9 frames long, so these parameters would be 1, 9.

The next two parameters tell the function which frames to display, from the first frame to the last frame. You can use this if you only want to display part of the animation (possibly you might want to display different parts at different times). In this case we want to use all the frames.

The last parameter is the speed of the animation — the higher the number, the faster the animation. It is approximately (very approximately!) in frames per second, and values between 5 and 15 are usually appropriate, though of course this depends on your animation.

Now, what about that SMOOTH option? Well, this works in a rather different way. Instead of displaying individual frame, the SMOOTH option basically scrolls the entire texture sideways. Because of this, it is possible to use this to scroll a texture which isn’t animated (in other words, a texture which isn’t actually a series of frames).

As an example, let’s create a slowly drifting starfield. Rez a cube, and size it so that it is about 4 m wide and 2 m tall. Create a new script in it, and replace the script contents with the following:

default
{
 state_entry()
 {
  llSetTexture("43019701-cf5c-d484-3b35-3fb59fe895b4", ALL_SIDES);
  llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, 1, 2, 1, 1, 0.02);
 }
}

Notice that although the texture is not animated, we have specified a Y frame count of 2. This might seem rather odd, and needs some explanation. As soon as you apply llSetTextureAnim, the script will override whatever X and Y repeat values that you have specified, and instead will size the texture to match the X and Y frame count that you have specified, stretching it as necessary.

In order to make the texture fill the X direction without stretching, the Y frame-count has been specified as 2, making the script treat the texture as a two-frame animation. Because the start and end frames are both 1, it only displays one frame, which in this case works out as the top half of the texture, with the result that the texture is scaled correctly for us. This is not really an efficient way of doing things! Really, an animated texture needs to have the same X:Y ratio as the prim face that you are going to use it on.

Next, something more useful. Let’s see how to use texture animation with Second Life’s waterfall textures, and create a simple waterfall.

Start by rezzing a cube, and size it so that it is 2 m wide, 4 m tall, and 0.2 m deep. On the Texture tab, set the rotation to 90.0. This is because animations which use SMOOTH, as we are going to do, always slide along the X axis, so we need to rotate the texture to make our water flow vertically.

Create a new script in it, and replace the script contents with the following:

default
{
 state_entry()
 {
  llSetTexture("af8c86bd-c377-c331-7476-58abeb7af8fc", ALL_SIDES);
  llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, 1, 2, 1, 1, 0.5);
 }
}

By itself, this should look reasonably effective. We can make it better, though. Take a copy of this prim, shifting it so that it is a little bit in front of the original prim. Edit the script in this copy, and replace it with the following:

default
{
 state_entry()
 {
  llSetTexture("49649c94-f720-6d0f-2246-49cc1835284f", ALL_SIDES);
  llSetTextureAnim(ANIM_ON | LOOP | SMOOTH, ALL_SIDES, 1, 2, 1, 1, 0.25);
 }
}

This now gives us two waterfall animations, running at different speeds. The result is very effective.

Near the start of this post I mentioned that if you had neither LOOP nor PING-PONG in the animation flags the animation would run through just once. Here is an example of this. It is a ‘LOCKED’ sign which flashes once when somebody touches it.

Rez a new cube, and size it to be 1 m wide, 0.5 m tall, and 0.5 m deep. Create a new script in it, and replace the script contents with the following:

default
{
 state_entry()
 {
  llSetTexture("7392be5b-ce2f-eb64-6a45-a4544ec539a9", ALL_SIDES);
  llSetTextureAnim(ANIM_ON, ALL_SIDES, 1, 2, 1, 2, 5.0);
 }
 touch_start(integer total_number)
 {
  // Curiously, we have to switch the animation off first.
  llSetTextureAnim(0, ALL_SIDES, 1, 2, 1, 2, 0.0);
  // Now run the animation once.
  llSetTextureAnim(ANIM_ON, ALL_SIDES, 1, 2, 1, 2, 5.0);
 }
}

Finally, some useful (I hope!) notes:

Finding the prim face: You’ll notice that in the above scripts I have specified ALL_SIDES as the side to apply the texture and animation. A lot of the time you will want to put the texture and animation on one side only. The easiest way to find out the side number of a prim face is to use the Advanced (or Debug) menu.

To active or deactivate the menu, hold down CTRL+ALT+d on your keyboard. The Advanced menu should appear on the main Second Life menu.

Once this menu is showing, edit the prim you want to investigate. Click the ‘Select Texture’ option, and select the face you want to check. Then hold down CTRL+SHIFT+ALT+t on your keyboard. Details of the texture will appear in the bottom-left of your screen, including the face number.

Switching off animations: If you want to switch off the animation on a texture, simply pass zero as the flag. The other parameters are irrelevant:

llSetTextureAnim(0, ALL_SIDES, 1, 1, 1, 1, 0.0);

Texture Size: remember that a texture with multiple frames can easily be very large indeed, and Second Life still has to load the entire texture (no, it doesn’t load it frame by frame!). Creating an effective animation using a minimum number of frames is a skill in its own right.

The LSL Wiki has additional useful information: http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSetTextureAnim

Yes, I’m finally back. My computer is now healthy and happy again, though Second Life seems to be falling apart. No change there then. I managed to get on-line and stay on-line long enough to collect the pictures for this post, though.

Numbakulla Island has been around for some time, and I first came across it a couple of years ago (I think). I’ve been meaning to blog about it for a while, and have finally got round to it.

What is Numbakulla? Well, at first sight, it is a rather interesting and well-built island sim, and worth looking round just for its own sake. However, that is not its main purpose. In fact, Numbakulla is a Second Life version of a point-and-click adventure.

When you first teleport it, you end on the shore beside a shipwreck. The broken ship is half-sunk in the waters beside you, and books, suitcases, and scraps of paper have been tossed up on the shore or still float on the sea.

Shipwreck

You are greeted by a notecard, which gives you some explanation about the game and how to play it. Beside you is an open chest and a small stand with a  notebook on it. When you click on the notebook, you are given a notebook of your own, which is crucial to the game. You wear this notebook (nothing visible appears, but once you start interacting with things on the island you will get messages from it), and start your exploration.

Chest and notebook

A cave is in front of you, and is the obvious direction to go in, but even as you do so, you come across a scrap of paper on the ground. Click it, and you get your first clue (such as it is) to the game.

Letter

Then it is through the cave, and out onto the main island, with its curious, plant-like buildings.

Main island

It will take a little while before you come across your first real hint of the goal of the game and the explanation of the island’s subtitle The Pot-Healer Adventure. In the meantime it is a case of wandering round the island — there is plenty to see — and looking out for things which can be clicked on and interacted with. Such as this pump, which is near the cave exit.

Village pump

It predictably pours water, and your notebook tells you that you need something to collect the water in…but I won’t say more, and so that I won’t spoil the game for you, I’ll refrain from telling you much more about the island, except to say that there is a lot more than just the area which I have shown here.

More of the island

I’ll confess, too, that I haven’t really begun to solve the game myself, and I intend to go back soon and explore the island properly.

I hope I’ve tempted you to pay a visit yourself. Have fun.