Change font size
It is currently Mon Nov 19, 2018 11:02 am

Forum rules


{L_IMAGE}



Post a new topicPost a reply Page 1 of 1   [ 9 posts ]
Author Message
 Post subject: Building a "touch screen" prim
PostPosted: Mon Apr 20, 2009 5:05 pm 
Site Admin
User avatar

Joined: Wed Jul 16, 2008 7:22 pm
Posts: 186
In response to a conversation in #osgrid, here are a couple of scripts which demonstrate how to build a touch screen interface on a prim surface.

The first script is used to define the "button" areas. It'll spit out a line of code that can then be used in another script to actually respond to presses on the buttons. First, texture a face of your prim with your control panel image:

{L_IMAGE}

Then drop in this script:

{L_CODE}:
// TouchST Map List Builder - v1.0
// Author: Warin Cascabel
//
// Drop the script into a prim, give it a command to start recording, then click pairs of points on the prim to define areas
// (e.g. the edges of buttons on a texture mapped on the face). Give it another command to stop recording, and it will spit
// out a line of code which can be used to detect which button was pressed (see TouchST Map List Example script for how to
// do that).

integer CommChannel = 10; // Accepts commands on channel 10. Change that if you prefer a different channel, but please,
                          // not channel 0. Nobody wants to hear you talking to inanimate objects. Seriously.


// Internal variables; do not modify.
//
integer begun = 0;
integer point1 = 0;
vector FirstPoint;
list PointList = [];

// Usage() provides some simple help text.
//
Usage()
{
    llOwnerSay( "Type \"/" + (string) CommChannel + " start\" to begin, \"/" + (string) CommChannel + " end\" when done." );
}

default
{
    state_entry()
    {
        llListen( CommChannel, "", llGetOwner(), "" );  // Listen for chat from our owner, on the above-defined channel.
        Usage();
    }
   
    touch_start( integer foo )
    {
        if (llDetectedKey( 0 ) != llGetOwner()) return; // Only respond to touches from our owner.
        if (!begun) {                                   // If we haven't begun recording yet,
            Usage();                                    //    tell our owner how to use us
            return;                                     //    and quit
        }
        if (point1)                                     // If we already have the starting point in memory
        {
            vector SecondPoint = llDetectedTouchST( 0 );//    get the position of the second point
            float f;
            if (FirstPoint.x > SecondPoint.x)           //    Make sure the first x coordinate is less than the second
            {                                           //    If not, swap them.
                f = FirstPoint.x;
                FirstPoint.x = SecondPoint.x;
                SecondPoint.x = f;
            }
            if (FirstPoint.y > SecondPoint.y)           //    Make sure the first y coordinate is less than the second
            {                                           //    If not, swap them.
                f = FirstPoint.y;
                FirstPoint.y = SecondPoint.y;
                SecondPoint.y = f;
            }
            PointList += [ FirstPoint, SecondPoint ];   //    Add these points to our list
            point1 = 0;                                 //    Clear out the point1 flag
            llOwnerSay( "Click the next starting point, or type \"/" + (string) CommChannel + " end\" to finish." );
        }
        else                                            // This is the first point of the pair
        {
            FirstPoint = llDetectedTouchST( 0 );        // Get its coordinate
            point1 = 1;                                 // Set the point1 flag
            llOwnerSay( "Click the ending point, type \"/" + (string) CommChannel + " undo\" to undo the starting point, or type \"/" + (string) CommChannel + " end\" to abort this square and finish." );
        }
    }
   
    listen( integer channel, string who, key id, string message )
    {
        if (id != llGetOwner()) return;                 // Ignore any chat apart from our owners
        message = llToLower( message );                 // Convert the message to all lowercase
        if (message == "start")                         // start recording
        {
            begun = 1;                                  // set the begun flag
            PointList = [];                             // clear out the point list
            llOwnerSay( "Click the first starting point." );  // provide some help text
        }
        else if (message == "end")                      // stop recording
        {
            llOwnerSay( "\nlist ButtonCoords = [ " + llList2CSV( PointList ) + " ];" ); // Set our output string
            begun = 0;                                  // clear the begun flag
        }
        else if (message == "undo")                     // undo the starting point
        {
            point1 = 0;                                 // clear the point1 flag
            llOwnerSay( "Box canceled." );              // Provide feedback
        }
    }
}


Type: /10 start to begin recording. Click the opposite corners of each button (e.g. top left corner, then bottom right corner). Once you're finished, type /10 end to stop recording. It will spit out a line of code like this:

{L_CODE}:
list ButtonCoords = [ <0.040404,0.572013,0.000000>, <0.445333,0.714434,0.000000>, <0.040740,0.324040,0.000000>, <0.445979,0.468508,0.000000>, <0.040887,0.079658,0.000000>, <0.446032,0.222644,0.000000>, <0.548612,0.572047,0.000000>, <0.952732,0.714478,0.000000>, <0.548699,0.324969,0.000000>, <0.953914,0.468322,0.000000>, <0.549857,0.079893,0.000000>, <0.953868,0.223173,0.000000> ];


Delete the script out of the prim, then drop this script in:

{L_CODE}:
// TouchST Map List Example - v1.0
// Author: Warin Cascabel
//
// Simple example of using "buttons" on a prim's texture.

// Replace the following ButtonCoords list with one generated by the TouchST Map List Builder script.  It consists of pairs of coordinates
// defining the minimum and maximum point coordinates for each button.
list ButtonCoords = [ <0.040404,0.572013,0.000000>, <0.445333,0.714434,0.000000>, <0.040740,0.324040,0.000000>, <0.445979,0.468508,0.000000>,
                      <0.040887,0.079658,0.000000>, <0.446032,0.222644,0.000000>, <0.548612,0.572047,0.000000>, <0.952732,0.714478,0.000000>,
                      <0.548699,0.324969,0.000000>, <0.953914,0.468322,0.000000>, <0.549857,0.079893,0.000000>, <0.953868,0.223173,0.000000> ];

// The FindButton() function takes a vector, and sees if it falls within any of the pairs of coordinates in
// the ButtonCoords list. If so, it returns the zero-based index (0 for the first pair, 1 for the second pair,
// etc.), or -1 if the coordinate did not fall within any of the pairs in the list.
//
integer FindButton( vector v )
{
    integer j = llGetListLength( ButtonCoords );        // How many buttons?
    integer i;
    for (i = 0; i < j; i += 2)                          // Scan through the list
    {
        vector s = llList2Vector( ButtonCoords, i );    // Get the starting point of the rectangle
        vector e = llList2Vector( ButtonCoords, i+1 );  // Get the ending point of the rectangle
                                                        // If the provided point falls within the rectangle, return
                                                        // the number of the pair
        if ((v.x >= s.x) && (v.x <= e.x) && (v.y >= s.y) && (v.y <= e.y)) return (i >> 1);
    }
    return -1;                                          // If we reached here, the point fell outside all the rectangles
}                                                       // so return -1 to indicate "not found".

default
{
    touch_start( integer foo )
    {
        while (foo--)                                           // For each person who touched us:
        {
            key k = llDetectedKey( foo );                       // Get the UUID of the person who clicked us
            integer face = llDetectedTouchFace( foo );          // Get the face where they clicked. We could use this information
                                                                //   to ignore the touch if it wasn't on the correct face, or
                                                                //   check a different list depending on which face was clicked
                                                                //   but for this example script we don't actually do anything
                                                                //   with the information.
                                                               
            integer i = FindButton( llDetectedTouchST( foo ));  // Get the coordinate where they clicked; see if it's a button
            if (i != -1)                                        // If so, tell them what button they clicked (but of course we
            {                                                   // could do so much more with this information).
                llInstantMessage( k, "You clicked button number " + (string) i );
            }
            else                                                // If they did not click on a button...
            {
                llInstantMessage( k, "Good work. You missed all the buttons." ); // ...print a message saying so.
            }
        }
    }
}


Replace the ButtonCoords list with the data that was provided by the TouchST Map List Builder script (copy the text out of your chat history window, then paste it into the script in place of the existing ButtonCoords list).

Save the script, and now it will tell you which button you're clicking on.

Obviously, that's just a simple example script - for a more real-world example, let's make the above texture work as a real one-prim plaza teleport system:

{L_CODE}:
// One-prim Plaza Teleport System
// Author: Warin Cascabel
//
// NOTE: This script requires osTeleportAgent() to be enabled in OpenSim.ini. If you do not want to enable
// that function, comment out the osTeleportAgent() line, and uncomment the llMapDestination() line.
//
list ButtonCoords = [ <0.040404,0.572013,0.000000>, <0.445333,0.714434,0.000000>, <0.040740,0.324040,0.000000>, <0.445979,0.468508,0.000000>,
                               <0.040887,0.079658,0.000000>, <0.446032,0.222644,0.000000>, <0.548612,0.572047,0.000000>, <0.952732,0.714478,0.000000>,
                               <0.548699,0.324969,0.000000>, <0.953914,0.468322,0.000000>, <0.549857,0.079893,0.000000>, <0.953868,0.223173,0.000000> ];
list RegionNames = [ "Bade Plaza", "Lbsa Plaza", "SeaPrior Plaza", "Teravus Plaza", "Wright Plaza", "Zaius Plaza" ];
list LandingSpots = [ <92.0,115.0,41.0>, <127.0,128.0,22.0>, <69.0,202.0,21.0>, <113.0,126.0,35.0>, <128.0,126.0,22.0>, <127.0,127.0,22.0> ];
list LookAts = [ <1.0,0.0,0.0>, <1.0,0.0,0.0>, <1.0,0.0,0.0>, <1.0,0.0,0.0>, <1.0,0.0,0.0>, <1.0,0.0,0.0> ];

integer FindTouchedRegion( vector v )
{
    integer j = llGetListLength( ButtonCoords );
    integer i;
    for (i = 0; i < j; i += 2)
    {
        vector llc = llList2Vector( ButtonCoords, i );
        vector urc = llList2Vector( ButtonCoords, i+1 );
        if ((v.x >= llc.x) && (v.x <= urc.x) && (v.y >= llc.y) && (v.y <= urc.y))
            return i >> 1;
    }
    return -1;
}


default
{
    state_entry()
    {
        llOwnerSay( "Online" );
    }
   
    touch_start(integer num_detected)
    {
        while (num_detected--)
        {
            if (llDetectedTouchFace( num_detected ) == 4) // only detect touches on the front face
            {
                vector v = llDetectedTouchST( num_detected );  // Get the point where the user touched
                integer WhichButton = FindTouchedRegion( llDetectedTouchST( num_detected )); // which button was it?
                if (WhichButton > -1)
                {
                    string DestinationName = llList2String( RegionNames, WhichButton ); // Get the region name
                    vector DestinationPos = llList2Vector( LandingSpots, WhichButton ); // Get the landing spot
                    vector DestinationLook = llList2Vector( LookAts, WhichButton );     // Get the lookat vector
                    key AgentToTeleport = llDetectedKey( num_detected );
//                    llMapDestination( DestinationName, DestinationPos, DestinationLook );  // use this if osTeleportAgent() is not enabled
                    osTeleportAgent( AgentToTeleport, DestinationName, DestinationPos, DestinationLook );
                }
            }
        }
    }
}


Top
 Profile  
 
 Post subject: Re: Building a "touch screen" prim
PostPosted: Mon Apr 20, 2009 7:55 pm 

Joined: Sat Mar 14, 2009 8:03 pm
Posts: 16
Thankyou Warin! This is a very handy couple of scripts. It also cleared up a couple of questions I had when i was experimenting with the functions. =)


Top
 Profile  
 
 Post subject: Re: Building a "touch screen" prim
PostPosted: Tue Apr 21, 2009 8:56 am 
OSG Elite
User avatar

Joined: Fri Oct 17, 2008 11:30 am
Posts: 300
Location: Yorkshire, England
Nice scripts. Worth mentioning (correct me if I'm wrong here), but a script using osTeleportAgent() needs to be owned by the region's master avatar in order to work. If it's not, it simply does nothing for that function no matter how hard you click it.

_________________
John
UK resident; OSGrid & Second Life: "Barrington John"; code monkey in RL
OSGrid region server: P4/3.6GHz/2GB, Ubuntu Karmic/Mono 2.6/MySQL 14.14v5.1.37, home ADSL (~8.5Mbps/0.85Mbps), 8-14 regions, 2 users


Top
 Profile  
 
 Post subject: Re: Building a "touch screen" prim
PostPosted: Sun Apr 26, 2009 9:19 pm 
Site Admin
User avatar

Joined: Wed Jul 16, 2008 7:22 pm
Posts: 186
It seems the object containing the script must be owned by the same person who owns the parcel that the object is on. (Furthermore, the avatar being teleported has to be on land owned by the same person.)

Interestingly, the region's master avatar does *not* have blanket permission to use the function anywhere in the region; if a parcel has been sold to someone else, and the master avatar rezzes an osTeleportAgent()-using object in that parcel, the function will silently fail.


Top
 Profile  
 
 Post subject: Re: Building a "touch screen" prim
PostPosted: Sun Apr 26, 2009 10:23 pm 

Joined: Sat Mar 14, 2009 8:03 pm
Posts: 16
Thank you again for this handy script. I am loving the single prim huds =) This script makes it very quick and simple.


Top
 Profile  
 
 Post subject: Re: Building a "touch screen" prim
PostPosted: Mon Apr 27, 2009 11:41 am 
Site Admin
User avatar

Joined: Sun Feb 22, 2009 1:39 pm
Posts: 402
Location: Wisconsin, USA
Works fine for me on a parcel I "own", but am not the master avatar of.


Top
 Profile  
 
 Post subject: Re: Building a "touch screen" prim
PostPosted: Fri Jan 08, 2010 8:44 am 

Joined: Fri Dec 25, 2009 12:15 pm
Posts: 41
I came across this teleport system inworld one night and Ive played with it, and fiddled with the cords. Its awesome, ty Warin. :mrgreen:


Top
 Profile  
 
 Post subject: Re: Building a "touch screen" prim
PostPosted: Sat Sep 21, 2013 2:46 am 
Furious Typer
User avatar

Joined: Sat May 26, 2012 8:56 pm
Posts: 280
I have tried this script a few times but it seems to only map the first 15 "buttons" of my 30 button matrix.


Top
 Profile  
 
 Post subject: Re: Building a "touch screen" prim
PostPosted: Tue Sep 24, 2013 8:20 pm 
Furious Typer
User avatar

Joined: Fri Mar 26, 2010 12:11 pm
Posts: 147
Location: Belgium / Brussels
Another way, probably more easy ...
{L_CODE}:
//  0   10  20
//  1   11  21
//  2   12  22
integer cols = 3;
integer rows = 3;
integer keypad(vector loc) {return 10 * llFloor(loc.x * cols) + (rows - llFloor(loc.y * rows) - 1);}

Enjoy! :)

_________________
Webmaster @ digitalconcepts.free.fr & digigrids.free.fr


Top
 Profile  
 
Display posts from previous:  Sort by  
Post a new topicPost a reply Page 1 of 1   [ 9 posts ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
610nm Style by Daniel St. Jules of Gamexe.net