Table of Contents

ChangeLog

31 December 2022

  • Code rewrite.

Shortnote

This is a color changer that, when dropped in an object with linked primitives, will allow the owner to change the color of each individually linked primitive.

Code

color_changer.lsl
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2022 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
integer wasMenuIndex = 0;
list wasDialogMenu(list input, list actions, string direction) {
    integer cut = 11-wasListCountExclude(actions, [""]);
    if(direction == ">" &&  (wasMenuIndex+1)*cut+wasMenuIndex+1 < llGetListLength(input)) {
        ++wasMenuIndex;
        jump slice;
    }
    if(direction == "<" && wasMenuIndex-1 >= 0) {
        --wasMenuIndex;
        jump slice;
    }
@slice;
    integer multiple = wasMenuIndex*cut;
    input = llList2List(input, multiple+wasMenuIndex, multiple+cut+wasMenuIndex);
    input = wasListMerge(input, actions, "");
    return input;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
integer wasListCountExclude(list input, list exclude) {
    if(llGetListLength(input) == 0) return 0;
    if(llListFindList(exclude, (list)llList2String(input, 0)) == -1) 
        return 1 + wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
    return wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
list wasListMerge(list l, list m, string merge) {
    if(llGetListLength(l) == 0 && llGetListLength(m) == 0) return [];
    string a = llList2String(m, 0);
    if(a != merge) return [ a ] + wasListMerge(l, llDeleteSubList(m, 0, 0), merge);
    return [ llList2String(l, 0) ] + wasListMerge(llDeleteSubList(l, 0, 0), llDeleteSubList(m, 0, 0), merge);
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2022 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
vector wasVectorClamp(vector v, float min, float max) {
    return
        <
            llListStatistics(
                LIST_STAT_MAX,
                [
                    llListStatistics(
                        LIST_STAT_MIN,
                        [
                            v.x,
                            max
                        ]
                    ),
                    min
                ]
            ),
            llListStatistics(
                LIST_STAT_MAX,
                [
                    llListStatistics(
                        LIST_STAT_MIN,
                        [
                            v.y,
                            max
                        ]
                    ),
                    min
                ]
            ),
            llListStatistics(
                LIST_STAT_MAX,
                [
                    llListStatistics(
                        LIST_STAT_MIN,
                        [
                            v.z,
                            max
                        ]
                    ),
                    min
                ]
            )
        >;
}
 
key owner;
integer link;
list links;
integer channel;
float value = .5;
 
default {
    state_entry() {
        owner = llGetOwner();
        channel = (integer)("0x8" + llGetSubString(llGetKey(), 0, 6));
 
        links = [];
        integer i = llGetNumberOfPrims();
        do { 
            links += (string)i; 
        } while(--i > 0);
 
        if(llGetListLength(links) == 1) {
            links = [ 0 ];
        }
        link = llList2Integer(links, 0);
 
        state wait;
    }
 
    changed(integer change) {
        if(change & CHANGED_LINK) {
            llResetScript();
        }
    }
 
    attach(key id) {
        llResetScript();
    }
 
    on_rez(integer param) { 
        llResetScript(); 
    }
}
 
state wait {
    touch_start(integer num) {
        if(llDetectedKey(0) != owner) {
            return;
        }
 
        state choose;
    }
 
    changed(integer change) {
        if(change & CHANGED_LINK) {
            llResetScript();
        }
    }
 
    attach(key id) {
        llResetScript();
    }
 
    on_rez(integer param) { 
        llResetScript(); 
    }
}
 
state choose_trampoline {
    state_entry() {
        state choose;
    }
}
 
state choose {
    touch_start(integer num) {
        state choose_trampoline;
    }
 
    state_entry() {
        vector color = llList2Vector(
            llGetLinkPrimitiveParams(
                link, 
                [
                    PRIM_COLOR, 
                    ALL_SIDES
                ]
            ),
            0
        );
 
        llListen(channel, "", owner, "");
 
        llDialog(
            owner, 
            "Colorize © 2022, Wizardry and Steamworks\n-----------------------------------------\nLink: " + (string)link + "               \nColor: " + (string)color + "             \n-----------------------------------------\nLinks: select a primitive to color       \nColor: color the selected primitive      \n",
            [
                "Links",
                "Color",
                "⏏ Exit"
 
            ], 
            channel
        );
    }
 
    listen(integer channel, string name, key owner, string message) {
        if(message == "⏏ Exit") {
            state wait;
        }
        if(message == "Links") {
            state selection;
        }
        if(message == "Color") {
            state colorize;
        }
    }
 
    changed(integer change) {
        if(change & CHANGED_LINK) {
            llResetScript();
        }
    }
 
    attach(key id) {
        llResetScript();
    }
 
    on_rez(integer param) { 
        llResetScript(); 
    }
}
 
state selection {
    state_entry() {
        llListen(channel, "", owner, "");
 
        vector color = llList2Vector(
            llGetLinkPrimitiveParams(
                link, 
                [
                    PRIM_COLOR, 
                    ALL_SIDES
                ]
            ),
            0
        );
 
        llDialog(
            owner, 
            "Colorize © 2022, Wizardry and Steamworks\n-----------------------------------------\nLink: " + (string)link + "               \nColor: " + (string)color + "             \n",
            wasDialogMenu(
                links, 
                [
                    "⏏ Exit", 
                    "⟻ Back", 
                    "Next ⟼"
                ], 
                ""
            ), 
            channel
        );
    }
 
    listen(integer channel, string name, key owner, string message) {
        if(message == "⏏ Exit") {
            state choose;
        }
 
        vector color = llList2Vector(
            llGetLinkPrimitiveParams(
                link, 
                [
                    PRIM_COLOR, 
                    ALL_SIDES
                ]
            ),
            0
        );
 
        if(message == "⟻ Back") {
            llDialog(
                owner, 
                "Colorize © 2022, Wizardry and Steamworks\n-----------------------------------------\nLink: " + (string)link + "               \nColor: " + (string)color + "             \n",
                wasDialogMenu(
                    links, 
                    [
                        "⏏ Exit", 
                        "⟻ Back", 
                        "Next ⟼"
                    ], 
                    "<"
                ), 
                channel
            );
 
            return;
        }
 
        if(message == "Next ⟼") {
            llDialog(
                owner, 
                "Colorize © 2022, Wizardry and Steamworks\n-----------------------------------------\nLink: " + (string)link + "               \nColor: " + (string)color + "             \n", 
                wasDialogMenu(
                    links, 
                    [
                        "⏏ Exit", 
                        "⟻ Back", 
                        "Next ⟼"
                    ], 
                    ">"
                ), 
                channel
            );
 
            return;
        }
 
        link = (integer)message;
 
        color = llList2Vector(
            llGetLinkPrimitiveParams(
                link, 
                [
                    PRIM_COLOR, 
                    ALL_SIDES
                ]
            ),
            0
        );
 
        llDialog(
            owner, 
            "Colorize © 2022, Wizardry and Steamworks\n-----------------------------------------\nLink: " + (string)link + "               \nColor: " + (string)color + "             \n",
            wasDialogMenu(
                links, 
                [
                    "⏏ Exit", 
                    "⟻ Back", 
                    "Next ⟼"
                ], 
                ""
            ), 
            channel
        );
    }
 
    changed(integer change) {
        if(change & CHANGED_LINK) {
            llResetScript();
        }
    }
 
    attach(key id) {
        llResetScript();
    }
 
    on_rez(integer param) { 
        llResetScript(); 
    }
}
 
state colorize {
    state_entry() {
        llListen(channel, "", owner, "");
 
        list l = llGetLinkPrimitiveParams(
            link, 
            [
                PRIM_COLOR, 
                ALL_SIDES
            ]
        );
 
        vector color = llList2Vector(l, 0);
 
        llDialog(
            owner, 
            "Colorize © 2022, Wizardry and Steamworks\n-----------------------------------------\nLink: " + (string)link + "               \nModify: " + (string)value + "            \nColor: " + (string)color + "             \n",
            [
                "R ▼", 
                "G ▼", 
                "B ▼", 
                "R ▲", 
                "G ▲", 
                "B ▲",
                "⏏ Exit",
                "↑",
                "↓"
            ], 
            channel
        );
    }
 
    listen(integer channel, string name, key owner, string message) {
        if(message == "⏏ Exit") {
            state choose;
        }
 
        list l = llGetLinkPrimitiveParams(
            link, 
            [
                PRIM_COLOR, 
                ALL_SIDES
            ]
        );
 
        vector color = llList2Vector(l, 0);
        float alpha = llList2Float(l, 1);
 
        if(message == "↑") {
            value += .05;
            jump menu;
        }
 
        if(message == "↓") {
            value -= .05;
            jump menu;
        }
 
        integer i = llListFindList(
            [
                "R ▼", 
                "G ▼", 
                "B ▼", 
                "R ▲", 
                "G ▲", 
                "B ▲"
            ], 
            [ 
                message 
            ]
        );
        if(i != -1) {
            list l = llParseString2List(
                llList2String(
                    [
                        "R ▼", 
                        "G ▼", 
                        "B ▼", 
                        "R ▲", 
                        "G ▲", 
                        "B ▲"
                    ], 
                    i
                ),
                [" "],
                []
            );
 
            color +=
                // sign
                (float)(
                    llList2String(
                        [ "-", "+" ], 
                        "▲" == llList2String(l, 1)
                    ) + "1"
                ) *
                // value
                llList2Vector(
                    [ 
                        llList2Vector(
                            [
                                llList2Vector(
                                    [ 
                                        ZERO_VECTOR,
                                        <0, 0, value>
                                    ], 
                                    llList2String(l, 0) == "B"
                                ),
                                <0, value, 0>
                            ], 
                            llList2String(l, 0) == "G"
                        ),
                        <value, 0, 0>
                    ], 
                    llList2String(l, 0) == "R"
                );
 
            jump menu;
        }
 
@menu;
 
        color = wasVectorClamp(
            color, 
            0, 
            1
        );
 
        llSetLinkPrimitiveParamsFast(
            link, 
            [
                PRIM_COLOR, 
                ALL_SIDES, 
                color, 
                alpha
            ]
        );
 
        llDialog(
            owner, 
            "Colorize © 2022, Wizardry and Steamworks\n-----------------------------------------\nLink: " + (string)link + "               \nModify: " + (string)value + "            \nColor: " + (string)color + "             \n",
            [
                "R ▼", 
                "G ▼", 
                "B ▼", 
                "R ▲", 
                "G ▲", 
                "B ▲",
                "⏏ Exit",
                "↑",
                "↓"
            ], 
            channel
        );
    }
 
    changed(integer change) {
        if(change & CHANGED_LINK) {
            llResetScript();
        }
    }
 
    attach(key id) {
        llResetScript();
    }
 
    on_rez(integer param) { 
        llResetScript(); 
    }
}