Builders' Tabs

Written by Kitsune

Abbreviation: BTs (eg. "This house uses BTs"), pronounced: b(ee) t(ee)s.

Builders' Tabs were invented and sold by me (TimelessPrototype). However, since they have proved to be the builder's right hand tool for precision building with ease - especially for unusually-shaped buildings - I thought I should share the script for all to enjoy. I DO NOT support this script so please don't ask me about it. Please use the http://lslwiki.net/lslwiki/css/outside.gif); padding-right: 9px; font-family: Verdana, sans-serif; font-size: 13px; line-height: 16px; background-position: 100% 50%; background-repeat: no-repeat no-repeat; ">SL forums and ask for help there. Thank you. However, the intellectual property is still mine. You may not sell Builders' Tabs unless they are part of your pre-fabricated product (eg. housing modules with touch assembly using Builders' Tabs). If you are making a raging profit, please show your financial appreciation by donating to TimelessPrototype in SL.

Please follow these instructions carefully to make the Builder's Tab.

1. Create two prims. One prim serves as a Tab, and the other serves as the root prim.
2. Link the two prims. You could have any number of prims in this link set with one or more Tab prims.
3. In the root prim, drop in the following script and rename the script to "mover".

 

 

// By Timeless Prototype
// 2005-01-17

vector   targetPos = ZERO_VECTOR;
rotation targetRot = ZERO_ROTATION;
integer  timeOut;
integer  pendingMove = 0;
integer  pendingLockDelete = 0;
integer  lockTimeOut;

init()
{
    if (! (llGetPermissions() & PERMISSION_CHANGE_LINKS))
    {
        llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
    }
}

default
{
    state_entry()
    {
        init();
    }

 

 

 


4. In the non-root prim (the Tab prim), drop in the following script and rename the script to "tab".

 

 

// Tip: zero rot the Tab prim then link to east side of root prim.
// You can link it anywhere to the root prim, but when you first use it,
// this is a good demonstrational position.

integer  lh;
vector   targetJointPos = <0,0,0>;
rotation targetJointRot = ZERO_ROTATION;
integer  nodeActive = 0;
integer  pendingTabDelete = 0;

init()
{
    if (llGetObjectName() != "Tab")
    {
        llSetObjectName("Tab");
    }
}

restoreColor()
{
    llSetColor(<0,0,1>, 0); // +ve Z axis (face)
    llSetColor(<0,1,0>, 1); // -ve Y axis (face)
    llSetColor(<1,0,0>, 2); // +ve X axis (face)
    llSetColor(<0,1,0>, 3); // +ve Y axis (face)
    llSetColor(<1,0,0>, 4); // -ve X axis (face)
    llSetColor(<0,0,1>, 5); // -ve Z axis (face)
    llSetPrimitiveParams([ PRIM_MATERIAL, PRIM_MATERIAL_WOOD ] );
}

show()
{
    string plus = "28aa0989-55ef-0abe-332d-5fb243bdc76c";
    string minus = "1f69b45a-6975-6353-87b8-d856f491430b";
    llSetTexture(plus, ALL_SIDES);
    llSetTexture(minus, 1);
    llSetTexture(minus, 4);
    llSetTexture(minus, 5);
}

hide()
{
    llSetTexture("f54a0c32-3cd1-d49a-5b4f-7b792bebc204", ALL_SIDES);
    llSetPrimitiveParams([ PRIM_MATERIAL, PRIM_MATERIAL_WOOD ] );
}

default
{
    state_entry()
    {
        init();
        lh = llListen(23, "", "", "");
        restoreColor();
        show();
    }
    
    on_rez(integer start_num)
    {
        llResetScript();
    }
    
    changed(integer change)
    {
        if (change & CHANGED_LINK)
        {
            if (pendingTabDelete == 1)
            {
                if (llGetLinkNumber() < 2)
                {
                    llDie();
                }
                else
                {
                    llSetTimerEvent(0.0);
                    llSetTimerEvent(1.0);
                }
            }
        }
    }

    timer()
    {
        llSetTimerEvent(0.0);
        llMessageLinked(LINK_SET, llGetLinkNumber(), "final_lock_all", NULL_KEY);
    }
    
    touch_start(integer total_number)
    {
        if (targetJointPos == <0,0,0> && llDetectedKey(0) == llGetOwner())
        {
            if (nodeActive == 0)
            {
                // TESTED, LEAVE THIS ALONE!
                llTriggerSound("268bed48-92c0-5ff3-7d39-cbec55dc69a1", 1.0);
                llShout(23, "joint|" + (string)(llGetRootPosition() + (llGetLocalPos() * llGetRootRotation())) + "|" + (string)(llGetLocalRot() * llGetRootRotation()));
                llSetColor(<1,0,1>, ALL_SIDES);
                llSetPrimitiveParams([ PRIM_MATERIAL, PRIM_MATERIAL_LIGHT ] );
                nodeActive = 1;
                // END OF TESTED
            }
            else 
            {
                llTriggerSound("268bed48-92c0-5ff3-7d39-cbec55dc69a1", 1.0);
                llShout(23, "cancel_join");
                restoreColor();
                nodeActive = 0;
            }
        }
        else if (llDetectedKey(0) == llGetOwner())
        {
            llTriggerSound("268bed48-92c0-5ff3-7d39-cbec55dc69a1", 1.0);
            llShout(23, "cancel_join");
            // Begin move to last known location
            
            rotation targetRootRot =  (ZERO_ROTATION / (<0.0, 0.0, 1.0, 0.0> * llGetLocalRot())) * targetJointRot;
            
            vector targetRootPos = targetJointPos - (llGetLocalPos() * targetRootRot);
            
            llMessageLinked(LINK_SET, 1, "move_to|" + (string)targetRootPos + "|" + (string)targetRootRot, NULL_KEY);
            restoreColor();
            nodeActive = 0;
            targetJointPos = <0,0,0>;
            targetJointRot = ZERO_ROTATION;
        }
    }
    
    listen(integer channel, string name, key id, string message)
    {
        if (llGetOwner() == llGetOwnerKey(id) || llGetOwner() == id)
        {
            list words   = llParseStringKeepNulls(llToLower(message), ["|"], []);
            string word0 = llList2String(words, 0);
            string word1 = llList2String(words, 1);
            string word2 = llList2String(words, 2);
            
            if (word0 == "joint")
            {
                targetJointPos = (vector)word1;
                targetJointRot = (rotation)word2;
                restoreColor();
                nodeActive = 0;
            }
            else if (word0 == "cancel_join")
            {
                targetJointPos = <0,0,0>;
                targetJointRot = ZERO_ROTATION;
                restoreColor();
                nodeActive = 0;
            }
            else if (word0 == "show")
            {
                show();
            }
            else if (word0 == "hide")
            {
                hide();
            }
            else if (word0 == "final_lock_all")
            {
                llSleep(llFrand(1.0));
                pendingTabDelete = 1;
                llSetTimerEvent(1.0);
            }
        }
    }
    
    moving_start()
    {
        if (nodeActive == 1)
        {
            llShout(23, "cancel_join");
            restoreColor();
            nodeActive = 0;
        }
    }
}

 

 

 

5. Take a copy of this Builder's Tab into your inventory. This will become your Base Tab that gets used to make modules that can be touch assembled.

Test your new Builders' Tabs:

1. Rez two of these Builders' Tabs
2. Touch the Tab on each and watch them magically align the tabs on themselves.

The following is derived from the help notecard that came with the Builders' Tabs Kit:

BUILDER'S TAB KIT version 2.1
bringing 'Touch to Assemble' to your buildings


by Timeless Prototype


NOTE: ADVANCED BUILDING SKILLS REQUIRED FOR PRECISION PLACEMENT OF BUILDER TABS!!!


What is it?


Ever needed to join up building parts over and over again? Builder's Tabs introduce an easy way to Touch to Assemble your buildings.

The Builder's Tab is a prim that you link one or more of to your building modules. A building module is typically a component of a building, perhaps a wall, an entire room or a roof for example. You place the 'mover' script into the building module's root prim. When you touch the first Tab that is where the other module must move to. Touch the Tab on the other module to begin the movement.

The target module stays in place and the second module will move and rotate as necessary so that the touched prims (Tabs) overlap exactly.

You WILL REQUIRE precise building skills if you want the modules to join up precisely by correctly placing the Tabs.


What Commands Are There?


Say:
'/23 hide' - to hide the Tabs from view.
'/23 show' - to show the Tabs again.
'/23 final_lock_all' - de-links the tabs and deletes the tab prims and the mover scripts. Only the current Owner can issue this command.


How do I get started?


1. Rez the Builder's Tab.
2. De-link the Tab from the example root prim.
3. Position the tab on your building module.
4. Link the Tab (or more than one Tab if you like) to your building module. The building module should be Shift selected LAST so that the Tabs are NEVER the root prim.
5. Copy the 'mover' script from the example Builder's Tab's root prim's contents into your inventory.
6. Copy the 'mover' script from your inventory into the root prim of your building module.
7. Your building module is now ready for touch assembly. Take a copy of your work. You can add as many Tabs to a single module as you like.
8. Test it.

Tips:


The Tabs when touched will move to overlap eachother exactly. They will also rotate 180 degrees around the local Z axis. So with this in mind, always keep the RED face with the PLUS sign facing outwards.