My friend bucky Barkley just told me yesterday about an incredibly cool feature, that the ever-amazing Qarl Linden has been silently developing: getting the coordinates of the exact spot where you touch on a prim.

Why is this so cool? Well, it allows you to do very complex interfaces with just a handful of prims (or one single prim), and naturally enough, you can imagine how important this is to be able to do browsable HTML-on-a-prim.

In the mean time, I’ll leave you with one simple application as a demonstration: changing the colour of a prim by simply dragging with the mouse over a prim’s surface:

YouTube Preview Image

People like Timeless Prototype and Strife Onizuka have been all enthusiastic about this, since Qarl announced in March that he would be implementing this. Shortly thereafter, a Wiki page for comments has been set up by Qarl. The discussion there seemed not to gather much attention, so Qarl turned to the Public JIRA instead.

So, silently but inexorably, this project advanced without many announcements — until, at last, a few days ago, it was launched on the Preview Grid for anyone to explore. It’s rock-solid and works incredibly well — the kind of thing we actually have been expecting from “Magic Qarl”, Wizard of SL Features!

To do a simple test I had to figure out something within my reach to demonstrate how it works, and that is also visually appealing. My first thought was to get back to my old LSL-based web browser and add proper support for clicking on hyperlinks and moving the scrollbars, but that is not the work of a couple of hours. The second idea was to create a whiteboard, that dynamically updates a texture (streamed via HTML-on-a-prim) with dots as you move the cursor over a prim. This would be quite useful, and it’s not too hard to do. Alas, I would need a parcel on the Preview Grid to be able to set the Media URL to allow HTML-on-a-prim, and I can’t do that on the public sandbox, so I have to wait until this feature is rolled out on the Agni (main) Grid — very likely, it’ll be there once Mono is rolled out, which is scheduled for “any time real soon now” (watch the Linden Lab Official Blog for announcements in the next few days!).

So I thought about my old scripting classes, where I usually give the students learning LSL something to do that is visually appealing to encourage them. One of the items that they almost always start to do is a colour changing script (usually tied in to clicking on buttons to change another prim’s colour). This is a variant of the same old story — since you have three parameters for a colour (red, green, blue), showing all possible colours is best done by using a cube — an interface issue on all “colour picker” widgets on the 2D world of our desktops, since invariably you have to map a 3D vector space onto a 2D interface. Not so in SL! A colour cube for picking all possible colours is a natural interface inside a 3D virtual world, of course, and thanks to Qarl’s magic LSL functions, which retrieve things like the face you’ve touched, the coordinates on top of the face, and even the normal and binormal vectors of the avatar-prim interaction (think what people will now be able to do with particles and the physics engine!), this becomes immensely easy to do in plain old LSL.

Here goes the scripts I’ve used. You should read something about how to map colours on top of a cube to understand how those textures were generated. I recommend the introduction to colours by Dan Short; from his site (looking at the HTML source :) ) you can also easily retrieve the textures used in the video above and upload them to Second Life®.

So, log in to the Preview Grid, and create a simple cube, and link it to another object. The cube will be the root prim and will detect touch events, sending the appropriate colour to the second object, which will just set it to the colour selected. Thanks to the touch event, you can repeatedly send these messages, and thus smoothly change the other prim’s colour, resulting in a nice effect as it gradually changes to the colour you’ve chosen.

Smoothly? Oh yes! :) Remember, this is all being compiled to Mono on the Preview Grid — so you get blindingly fast responsiveness :)

Anyway, on the Colour Cube (the prim that will serve as a 3D colour changing button), place the script below. Notice that you might have to tweak the ranges depending on the textures you’ve placed and the way they’re rotated (this was actually what took me the most time!). As said, I’ve used Dan Short’s textures, and they’re clearly labeled as “top”, “bottom”, “left”, “right”, “front”, and “back”, so it’s easy to apply them on a cube just rezzed in front of you (assuming you didn’t rotate it!). If you design your own textures for the Colour Cube, you’ll very likely need to adjust the ranges for each face (I used paper and a pencil to finally figure out half of the faces, since the trial-and-error method was taking too long for my taste!)

// Gwyn's Color Cube
// See http://www.danshort.com/colorcube/

vector range;  // these are globals to save some precious CPU cycles
vector colour;
integer face;

default
{
    state_entry()
    {
        colour = <1.0, 1.0, 1.0>;
        llSetText((string)colour, colour, 1.0);
        llMessageLinked(LINK_ALL_CHILDREN, 0, (string)colour, NULL_KEY);
    }

    touch(integer total_number)
    {
        // Face will say which pairs of colour to change
        face = llDetectedTouchFace(0);

        // this is the X, Y position on the face just touched
        range = llDetectedTouchST(0);

        if (face == 0) // red (primary) is fixed
        {
            colour = <1.0, 1.0-range.y, 1.0-range.x>;
        }
        else if (face == 1) // green (primary) is fixed
        {
            colour = <range.y, 1.0, 1.0-range.x>;
        }
        else if (face == 2) // blue is always absent
        {
            colour = <range.y, 1.0-range.x, 0.0>;
        }
        else if (face == 3) // green is always absent
        {
            colour = <range.y, 0.0, range.x>;
        }
        else if (face == 4) // blue (primary) is fixed
        {
            colour = <range.y, range.x, 1.0>;
        }
        else if (face == 5) // red is always absent
        {
            colour = <0.0, range.y, 1.0-range.x>;
        }
        llSetText((string)colour, colour, 1.0);
        llMessageLinked(LINK_ALL_CHILDREN, 0, (string)colour, NULL_KEY);

    }
}

The prim that changes colour (in my case, a sphere) just replies to linked messages and changes the colour of all faces:

integer r;
integer g;
integer b;
vector colour;

default
{
    link_message(integer sender_num, integer num, string str, key id)
    {
        colour = (vector) str;
        llSetColor(colour, ALL_SIDES);
        r = (integer)(colour.x * 255);
        g = (integer)(colour.y * 255);
        b = (integer)(colour.z * 255);

        llSetText((string) r + "," + (string) g + "," + (string) b, colour, 1.0);
    }
}

If you’re concerned about performance, you could do it the other way round: leave the main prim just to send the range coordinates, and do the math on the sphere’s script. I’ve added some hovertext to display the colours in float (on the Colour Cube) and in decimal (on the sphere), just as a visual feedback to be sure I was doing this correctly. You can obviously remove them, as well as the float-to-decimal conversion — hovertext is laggy, although, again, compiling it on Mono you won’t see any issues.

Many, many thanks to Qarl Linden and his amazing talent to develop the kind of features that will have huge impact on how future Second Life devices will work! Now you can have a one-prim-HUD and simplify dramatically your interface with just a single click :) I’m eager to try this out on the main grid… very, very soon!