« Quicklies For The Atheist In You | Main | Quicklies - SL Edition »

Typing Override Script and Laptop Keyboard Too (Secret Part 5)

I've enjoyed this series so much that I decided to extend it a bit. This is part number five in a four part series of blog howto entries. If you're finding this entry from a Google search or otherwise coming in fresh I suggest that you first pop over and read through the introductions.

For this entry I've put together yet another modified script to share with you. What it will do is to change the laptop's screen to an alternate picture. It's like a wall hanging that you put on your virtual home to display memories. Instead of rotating through the pictures or waiting for someone to click the frame this will change to a new (random) picture every time your keyboard appears.

In order for this to work cleanly without too many convoluted extra steps (involving linked messages or listens) the script which will change the prim's texture should be located in the prim that it will modify. That means that we'll have to juggle some files around since our root prim is currently the keyboard prim of the laptop and not the screen.

LaptopEditLinkedParts.jpg
Edit Linked Parts

First rez your keyboard and edit it. In the edit window turn on the "Edit linked parts" checkbox so that you can select only a single building block. Notice how the outline around the laptop's keyboard area is yellow while the rest of the object is outlined in blue? This tells us that the root prim of this object is the keyboard.

LaptopUnlinkScreen.jpg
Unlink the Screen

Click on the computer screen itself to change your selection from the entire laptop to just that one prim. Now choose "Unlink" from the "Tools" menu to separate it out.

LaptopNowScreenIsRootPrim.jpg
Make The Screen The Root Prim

Now you want to link it back together but with the laptop as the root prim. The trick to remember is that the LAST item selected in the link chain is the one that becomes the root prim. So first make sure you turn off the "Edit linked parts" checkbox so you're selecting entire objects. Now click to select the laptop computer sans screen - then hold the shift key and click to add the screen in to your selection. At this time you'll see two yellow highlighted prims because the keyboard is currently the root prim for the laptop object and the screen is the root prim for its object-of-one.

LaptopLinkBackTogether.jpg
Link Them Together

Go back to the "Tools" menu and link your objects back together. You'll be left with a single object consisting of 4 prims and with a yellow root prim outline around the screen.

LaptopDragContentsToInv.jpg
Copy Contents Out

Now we need to transfer the contents across from the old root prim to the new one. Unfortunately we cannot simply drag them from one prim to another within an object. We have to move or copy the contents to our own inventory first and THEN copy it to the new target prim. It's a painful extra step. So turn "Edit linked parts" back on and select the keyboard prim again. In your own inventory create yourself a nice new empty temporary folder to act as the middle man drag and drop spot. Select all of its contents (hint - click the top item, hold shift and then click the bottom item to select them all together) and drag them to your new temporary folder and drop them in place. A copy of each item will be made for you.

LaptopDeleteRootPrimContents.jpg
Delete Old Contents

With the items still highlighted in your object's contents go ahead and right click them and choose delete from the pie menu. We don't need them sitting in two separate prims of the object both running and sucking up resources for no good reason, right?

LaptopCopyContentsBackFromInvToNewRootPrim.jpg
Copy To New Root Prim

Now either select your new root prim, the screen, or turn "Edit linked parts" off since the object's contents ARE the root prim's contents. Drag the items out of your temporary folder in your inventory and drop them into the root prim's contents to make a copy.

LaptopCopyPicturesToContents.jpg
Insert Pictures

Our newly tweaked script will randomly select pictures from the new root prim's contents. You'll need to populate these pictures - drag some memories into your laptop.

We're going to completely replace the KeyboardOverride.lsl script with the version posted below.

Here's a quick rundown of the new bits of code that were required to achieve our goal:

In our declaration section we define a new global integer which we'll use to track how many texture items are in the prim's inventory. This saves us from making a lot of heavy duty inventory read calls during normal operation.

//Track the number of textures/pictures we have in the inventory of the prim this script resides in
integer num_pics;

In the initialization function we then populate this integer with the correct value:

//We've been reset so count how many pics are in inventory now.
num_pics = llGetInventoryNumber(INVENTORY_TEXTURE);

Later, in the section where we hide the keyboard and stop the typing animation override we have a new section of code. This bit selects one of the textures from the prim's contents at random and then sets one face of the root prim to be the newly selected random texture.

I chose to do this as the keyboard was being hidden because it would give the texture a moment to be downloaded and rezzed prior to the keyboard being displayed again.


// Reset the laptop's computer screen to a new random picture!
integer invNum = randInt(num_pics);
string newInvName = llGetInventoryName(INVENTORY_TEXTURE, invNum);
llSetTexture(newInvName, 5); //Side 5 is, in this case, the side facing the typist. We use one particular side in order to avoid making a screen appear on the back side of the keyboard lid by accident.

When ready edit the KeyboardOveride.lsl script and replace its contents with the code below. Scroll to the bottom of this page to see some snapshots of the new keyboard in action.



/// @file KeyboardOverride.lsl
/// Max Case's Free Keyboard Script 1.0 04/18/2005
/// Modified and renamed to KeyboardOverride 1.2 08/15/2007
///
/// Put it in a keyboard prim, attach it to yourself (or not) and
/// watch as that prim magically appears whenever you type.
/// Feel free to reuse, etc, but please don't just resell this script.
/// That would be lame, since I am giving it to you for free.
/// Naturally, if you build something nice off of it, sell that.
///
/// Or make a nice texture you would like to sell with keyboard script,
/// that's ok. Just leave script open to all to see.
///
/// Feedback/Rates/Donations/Hate Mail always welcome. Don't be shy.
/// leave in the comments; they don't affect performance.
/// – Max
///
/// Code comments assume that the keyboard is saved into the contents
/// of a keyboard object of some sort -Dolmere
///
/// @author Max Case, 04/18/2005
/// @author Vershana Amarula, 05/26/2005
/// @author Dolmere Talamasca 08/13/2007
///
/// Change history
///
/// 05/26/2005-VA Tweaks, changed variable names, added comments
/// and constants
///
/// 08/13/2007-DT Renamed file, modified description, added more comments
///
/// 08/15/2007-DT Added laptop screen texture changing components.


///
/// Declaration section - define and initialize all needed variables
///

/// The name or UUID of the animation to play when your avatar is typing
// An animation named "speak-no-evil" made by Roenik Newell for me is supplied as an example AO override.
// Change it to the string name of an animation that you have copied into the prim where this script will reside.
string newTypingAnimation = "speak-no-evil";

/// Keeps track of who is holding the object.
key kOwner;

/// Keeps track of the last typing state detected.
integer iPrevState;

/// Opacity percentage that represents "completely transparent".
float TRANSPARENT = 0.0;

/// Time interval to wait between testing for typing activity.
float TYPING_CHECK_PERIOD = .2;

/// Value to represent the (initial) state of "not typing".
integer IS_NOT_TYPING = 0;

/// Value to represent the state of "not being held"
integer IS_NOT_HELD = -1;

// The key for the default typing animation that Linden Lab uses
key typingAnim = "c541c47f-e0c0-058b-ad1a-d6ae3a4584d9";
// The actual name of the typing animation is "type"
// For more details see http://secondlife.com/badgeo/wakka.php?wakka=ClientAssetKeys and http://secondlife.com/badgeo/wakka.php?wakka=animation

// Track whether or not we have animation permissions
integer gotPermission = FALSE;

//Track the number of textures/pictures we have in the inventory of the prim this script resides in
integer num_pics;

/// Perform all necessary operations to prepare script for use here.
initialize()
{
// During initialization, store the current owner to verify
// against later. If the owner changes, we'll reinitialize.
kOwner = llGetOwner();

// Make the entire object as transparent as our settings allow
llSetLinkAlpha(LINK_SET, TRANSPARENT, ALL_SIDES);

/// Set up a timer to periodically check for typing activity.
llSetTimerEvent(TYPING_CHECK_PERIOD);

// Assume that the owner is NOT typing at the time we're initialized.
iPrevState = IS_NOT_TYPING;

// Request permission to animate the owner of the prim where this script is executing
// This call will be resolved in the run_time_permissions() function below
llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);

//We've been reset so count how many pics are in inventory now.
num_pics = llGetInventoryNumber(INVENTORY_TEXTURE);
}

// Random integer function taken from lsl wiki
// http://lslwiki.net/lslwiki/wakka.php?wakka=llFrand
integer randInt(integer n)
{
return (integer)llFrand(n + 1);
}

/// All behaviors associated with the default state.
default
{
// Operations to perform when entering state "default"
state_entry()
{
// Checks to see if we have changed owner when the script starts
// and (re)initializes if so.
if(llGetOwner() != kOwner)
{
initialize();
}
}

attach(key id)
{
if(id)//tests if it is a valid key and not NULL_KEY
{
initialize();
}
}

// Operations to perform when "rezzing" (using) the object
on_rez(integer total_number)
{
// Checks for new owner when object is rezzed and (re)initializes
// if so.
if(llGetOwner() != kOwner)
{
initialize();
}
}

run_time_permissions(integer perm) {
if( perm == (PERMISSION_TRIGGER_ANIMATION) )
{
gotPermission = TRUE;
}
}

// Operations to perform when the time value set with llSetTimerEvent elapses
timer()
{
// Is someone holding me?
integer iAttached = llGetAttached();

if(iAttached == 0)
{
// Not attached, make myself visible so I can easily be found
// (if I haven't already)!
if(iPrevState != IS_NOT_HELD)
{
// Make the entire object visible
llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES);
iPrevState = IS_NOT_HELD;
}
return;
}

// Are we typing? Thanks to Strife for rewrite here, though I find
// this sort of condensed logic can be confusing for non-programmer
// type, But this is definitely more efficient. -max
integer iTypingState = llGetAgentInfo(kOwner) & AGENT_TYPING;

// Has status changed since last checked?
if (iPrevState != iTypingState)
{
iPrevState = iTypingState;
if (iTypingState == 0)
{
if (llListFindList(llGetAnimationList(kOwner), [newTypingAnimation]))
{
// Make the entire object to be as transparent as settings allow
llSetLinkAlpha(LINK_SET, TRANSPARENT, ALL_SIDES);
llStopAnimation(newTypingAnimation);

// Reset the laptop's computer screen to a new random picture!
integer invNum = randInt(num_pics);
string newInvName = llGetInventoryName(INVENTORY_TEXTURE, invNum);
llSetTexture(newInvName, 5); //Side 5 is, in this case, the side facing the typist. We use one particular side in order to avoid making a screen appear on the back side of the keyboard lid by accident.
}
} else
{
if (llListFindList(llGetAnimationList(kOwner), [newTypingAnimation]))
{
// Make the entire object visible
llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES);
llStartAnimation(newTypingAnimation);
}
}
}
}
}


Did you really make it this far?
Are you having any trouble putting your own together?
Perhaps you would like to see the finished product in action?
I've taken the libert of posting the final FireEyes Laptop Keyboard, scripted and texture changing, to SLExchange.com. Enjoy.

LaptopTesting1.jpg
Start Typing and Watch the Screen
LaptopTesting2.jpg
Keep Typing - Screen Changes
LaptopTesting3.jpg
Textures Are Randomly Selected

EXTRA BONUS POINTS / HOMEWORK

Now that you've seen a few different ways to modify the keyboard script I suggest the following exercises for LSL practice:

1) Convert the random selection of pictures to a sequential selection of pictures instead.

2) Convert the static selection of a single embedded animation to a random or sequential selection of any animations found in contents.

Report back on your success, will you? :)

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Recent Comments

Melynn said: The purple/pink guitar is in small pieces now, so it's a toad-ily mute point anyway. :) That's even more amusing.…

Crap Mariner said: You know, it would be amusing to have the equivalent of a Turing Test to see if people could figure out if a stream of chat is actually from me or if it's from …

Dolmere Talamasca said: One might note that the JIRA bug now has 650 votes for it. Keep 'em coming people, it's easy to login and add your vote if you think something like this is need…

Dolmere Talamasca said: Interesting way of looking at it, Vint. I would think more PA than PS but unpaid labor is still unpaid labor.…

Dolmere Talamasca said: Instead of the typing animation use "UISndTyping" and clear the field to accomplish the closest thing to what I'm looking for (As noted by Jacek at Crap Mariner said: *shrug* Got time to hit the tower on Monday with Cyl and SUPRISE SPECIAL GUEST? Not sure which song... um... Rainbow Connection would be cool basstasstically…