456 lines
13 KiB
Plaintext
456 lines
13 KiB
Plaintext
// based loosely on icon-mono.lsl
|
|
|
|
//--------------------------------------------------------------------------
|
|
// BEGIN config
|
|
|
|
// use flags
|
|
//#define USE_BOLTS
|
|
#define USE_VERBOSE
|
|
|
|
// metadata
|
|
#define PANEL_VERSION "0.1"
|
|
#define PANEL_DEVICE_NAME "connectors"
|
|
|
|
// gauge
|
|
#define GAUGE_CUT_START 0
|
|
#define GAUGE_CUT_END 1
|
|
#define GAUGE_SRC "power"
|
|
#define GAUGE_MIN 0
|
|
#define GAUGE_MAX 1
|
|
#define GAUGE_DANGER 0.2
|
|
|
|
// lights
|
|
#define MAX_GLOW 0.3
|
|
#define FULLBRIGHT_ON_GLOW
|
|
#define OFF_DAMP_FACTOR 0.4
|
|
|
|
// END config
|
|
//--------------------------------------------------------------------------
|
|
// BEGIN macros
|
|
|
|
#define color_parse(_argv) <(float)gets(_argv, 1), (float)gets(argv, 2), (float)gets(argv, 3)>
|
|
#define add_device(_id, _ch) tell(_id, _ch, "add " + PANEL_DEVICE_NAME)
|
|
#define try_add_port(_id, _ch, _port, _link) if (_link != LINK_THIS) tell(_id, _ch, "port " + _port + " " + (string)llGetLinkKey(_link))
|
|
|
|
#define GAUGE_SRC_Q GAUGE_SRC + "-q"
|
|
|
|
// END macros
|
|
//--------------------------------------------------------------------------
|
|
// BEGIN includes
|
|
|
|
#include <utils.lsl>
|
|
#include <objects.lsl>
|
|
|
|
// END includes
|
|
//--------------------------------------------------------------------------
|
|
// BEGIN globals
|
|
|
|
integer LN_GAUGE = LINK_THIS;
|
|
integer LN_POWER_BUTTON = LINK_THIS;
|
|
integer LN_PLUG_POWER = LINK_THIS;
|
|
integer LN_PLUG_DATA1 = LINK_THIS;
|
|
integer LN_PLUG_DATA2 = LINK_THIS;
|
|
integer LN_PLUG_AUDIO1 = LINK_THIS;
|
|
integer LN_PLUG_AUDIO2 = LINK_THIS;
|
|
|
|
integer L_CAPS = 0;
|
|
integer L_LIGHTS = 0;
|
|
|
|
#define C_CAPS 411
|
|
integer C_LIGHTS = 0;
|
|
|
|
integer power_on = 1;
|
|
integer broken = 0;
|
|
integer charging = 0;
|
|
float gap = 0;
|
|
|
|
vector color = <1, 1, 1>;
|
|
vector color2 = <1, 1, 1>;
|
|
vector color3 = <1, 1, 1>;
|
|
vector color4 = <1, 1, 1>;
|
|
|
|
float gauge_value = GAUGE_MIN;
|
|
|
|
key avatar = NULL_KEY;
|
|
key controller = NULL_KEY;
|
|
|
|
// END globals
|
|
//--------------------------------------------------------------------------
|
|
// BEGIN functions
|
|
|
|
integer get_prim_count() {
|
|
if (llGetAttached()) {
|
|
return llGetNumberOfPrims();
|
|
}
|
|
|
|
return llGetObjectPrimCount(llGetKey());
|
|
} // get_prim_count()
|
|
|
|
populate_link_nums() {
|
|
integer i = get_prim_count();
|
|
string link_name;
|
|
for (; i > 0; i--) {
|
|
link_name = llGetLinkName(i);
|
|
switch (link_name) {
|
|
case "gauge":
|
|
LN_GAUGE = i;
|
|
break;
|
|
case "powerbutton":
|
|
LN_POWER_BUTTON = i;
|
|
break;
|
|
case "port-power":
|
|
LN_PLUG_POWER = i;
|
|
break;
|
|
case "port-data-1":
|
|
LN_PLUG_DATA1 = i;
|
|
break;
|
|
case "port-data-2":
|
|
LN_PLUG_DATA2 = i;
|
|
break;
|
|
case "port-audio-in":
|
|
LN_PLUG_AUDIO1 = i;
|
|
break;
|
|
case "port-audio-out":
|
|
LN_PLUG_AUDIO2 = i;
|
|
break;
|
|
default:
|
|
break;
|
|
} // switch (link_name)
|
|
} // for (...)
|
|
} // populate_link_nums()
|
|
|
|
init() {
|
|
avatar = llGetOwner();
|
|
|
|
populate_link_nums();
|
|
|
|
C_LIGHTS = 105 - (integer)("0x" + substr(avatar, 29, 35));
|
|
llListenRemove(L_LIGHTS);
|
|
L_LIGHTS = llListen(C_LIGHTS, "", NULL_KEY, "");
|
|
|
|
llListenRemove(L_CAPS);
|
|
L_CAPS = llListen(C_CAPS, "", NULL_KEY, "");
|
|
|
|
power_on = 1;
|
|
|
|
add_device(avatar, C_LIGHTS);
|
|
} // init()
|
|
|
|
set_tint(integer link, integer side, vector tint) {
|
|
llSetLinkColor(link, tint, side);
|
|
|
|
llSetLinkGLTFOverrides(link, side, [
|
|
OVERRIDE_GLTF_BASE_COLOR_FACTOR, llsRGB2Linear(tint),
|
|
OVERRIDE_GLTF_EMISSIVE_FACTOR, llsRGB2Linear(tint)
|
|
]);
|
|
} // set_tint(link, side, tint)
|
|
|
|
set_alpha(integer link, integer side, float alpha) {
|
|
llSetLinkAlpha(link, alpha, side);
|
|
|
|
integer alpha_mode = PRIM_GLTF_ALPHA_MODE_BLEND;
|
|
if (alpha == 1 || alpha == 0) {
|
|
alpha_mode = PRIM_GLTF_ALPHA_MODE_MASK;
|
|
}
|
|
|
|
llSetLinkGLTFOverrides(link, side, [
|
|
OVERRIDE_GLTF_BASE_ALPHA_MODE, alpha_mode,
|
|
OVERRIDE_GLTF_BASE_ALPHA_MASK, 0.5,
|
|
OVERRIDE_GLTF_BASE_ALPHA, alpha
|
|
]);
|
|
} // set_alpha(link, side, alpha)
|
|
|
|
set_glow(integer link, integer side, float glow) {
|
|
#ifdef FULLBRIGHT_ON_GLOW
|
|
integer fullbright = 0;
|
|
if (glow > 0) {
|
|
fullbright = 1;
|
|
}
|
|
#endif
|
|
|
|
setp(link, [
|
|
PRIM_GLOW, side, glow
|
|
#ifdef FULLBRIGHT_ON_GLOW
|
|
,
|
|
PRIM_FULLBRIGHT, side, fullbright
|
|
#endif
|
|
]);
|
|
} // set_glow(link, side, glow)
|
|
|
|
// level clamped to [0, 1]
|
|
update_colors(float level) {
|
|
if (level < 0) {
|
|
level = 0;
|
|
} else if (level > 1) {
|
|
level = 1;
|
|
}
|
|
|
|
if (!power_on) {
|
|
set_tint(LN_POWER_BUTTON, ALL_SIDES, color * OFF_DAMP_FACTOR);
|
|
set_glow(LN_POWER_BUTTON, ALL_SIDES, 0);
|
|
|
|
set_tint(LN_GAUGE, ALL_SIDES, color * OFF_DAMP_FACTOR);
|
|
set_glow(LN_GAUGE, ALL_SIDES, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
set_tint(LN_POWER_BUTTON, ALL_SIDES, color * level);
|
|
set_glow(LN_POWER_BUTTON, ALL_SIDES, MAX_GLOW * level);
|
|
|
|
if (charging) {
|
|
set_tint(LN_GAUGE, ALL_SIDES, color2 * level);
|
|
} else if (gauge_value < GAUGE_DANGER) {
|
|
set_tint(LN_GAUGE, ALL_SIDES, color3 * level);
|
|
} else {
|
|
set_tint(LN_GAUGE, ALL_SIDES, color * level);
|
|
}
|
|
|
|
set_glow(LN_GAUGE, ALL_SIDES, MAX_GLOW * level);
|
|
} // update_colors(level)
|
|
|
|
update_gauge() {
|
|
if (LN_GAUGE == LINK_THIS) {
|
|
return;
|
|
}
|
|
|
|
float interval = GAUGE_CUT_END - GAUGE_CUT_START;
|
|
float gauge_pct = gauge_value / (GAUGE_MAX - GAUGE_MIN);
|
|
float gauge_extent = gauge_pct * interval;
|
|
float gauge_end = interval * gauge_extent;
|
|
|
|
// clamp 100% just in case of rounding errors
|
|
if (gauge_end > 1.0) {
|
|
gauge_end = 1.0;
|
|
}
|
|
|
|
// minimum slice step
|
|
if (gauge_end < 0.05) {
|
|
gauge_end = 0.05;
|
|
}
|
|
|
|
// NEED MANUAL EDITING FOR DIFFERENT SHAPES >~>
|
|
setp(LN_GAUGE, [
|
|
PRIM_TYPE,
|
|
PRIM_TYPE_TUBE,
|
|
PRIM_HOLE_DEFAULT, // hole_shape
|
|
<GAUGE_CUT_START, gauge_end, 0>, // cut
|
|
0.0, // hollow
|
|
<0, 0, 0>, // twist
|
|
<1.0, 0.1, 0>, // hole_size
|
|
<0, 0, 0>, // top_shear
|
|
<0, 1, 0>, // advanced_cut
|
|
<0, 0, 0>, // taper
|
|
1, // revolutions
|
|
0, // radius_offset
|
|
0 // skew
|
|
]);
|
|
|
|
} // update_gauge()
|
|
|
|
update_port(string port_type, key src_id, integer connected) {
|
|
integer port_link = 0;
|
|
|
|
switch (port_type) {
|
|
case "power":
|
|
port_link = LN_PLUG_POWER;
|
|
break;
|
|
case "audio-in":
|
|
port_link = LN_PLUG_AUDIO1;
|
|
break;
|
|
case "audio-out":
|
|
port_link = LN_PLUG_AUDIO2;
|
|
break;
|
|
case "data-1":
|
|
port_link = LN_PLUG_DATA1;
|
|
break;
|
|
case "data-2":
|
|
port_link = LN_PLUG_DATA2;
|
|
break;
|
|
default:
|
|
#ifdef USE_VERBOSE
|
|
echo("Unknown port: " + port_type);
|
|
#endif
|
|
break;
|
|
} // switch (port_type)
|
|
|
|
if (connected) {
|
|
tell(src_id, C_LIGHTS, "port-real " + port_type + " " + (string)llGetLinkKey(port_link));
|
|
}
|
|
|
|
set_alpha(port_link, ALL_SIDES, (float)connected);
|
|
} // update_port(port_type, src_id, connected)
|
|
|
|
// END functions
|
|
//--------------------------------------------------------------------------
|
|
// BEGIN main
|
|
|
|
default {
|
|
state_entry() {
|
|
init();
|
|
} // state_entry()
|
|
|
|
on_rez(integer n) {
|
|
init();
|
|
} // on_rez(...)
|
|
|
|
touch_end(integer n) {
|
|
while (n--) {
|
|
key user = llDetectedKey(n);
|
|
integer touched_link = llDetectedLinkNumber(n);
|
|
|
|
if (touched_link == LN_POWER_BUTTON) {
|
|
if(power_on) {
|
|
tell(controller, C_LIGHTS, "command " + (string)user + " " + (string)user + " power off");
|
|
llTriggerSound("88af7a41-10e7-06ad-799e-313cbbe0ffad", 1);
|
|
} else {
|
|
tell(controller, C_LIGHTS, "command " + (string)user + " " + (string)user + " power on");
|
|
llTriggerSound("dccca2d0-b50c-e069-a1f9-c3336249421d", 1);
|
|
}
|
|
}
|
|
}
|
|
} // touch_end(...)
|
|
|
|
listen(integer cc, string src, key id, string msg) {
|
|
if (cc == C_CAPS) {
|
|
if (substr(msg, 0, 4) == "info ") {
|
|
integer rc = (integer)delstring(msg, 0, 4);
|
|
tell(id, rc, "hwc " + jsobject([
|
|
"vendor", "Cat Conspiracy",
|
|
"version", PANEL_VERSION,
|
|
"purpose", "info",
|
|
"channel", jsobject(["caps", C_CAPS, "lights", C_LIGHTS]),
|
|
"private", 0,
|
|
"busy", 0,
|
|
"usable", power_on,
|
|
"health", 1.0,
|
|
"info", "http://localhost:8080/"
|
|
]));
|
|
} // if (cmd == "info")
|
|
} // if (cc == C_CAPS)
|
|
else if (cc == C_LIGHTS) {
|
|
list argv = split(msg, " ");
|
|
string cmd = gets(argv, 0);
|
|
|
|
switch (cmd) {
|
|
case "off":
|
|
power_on = 0;
|
|
gap = 0;
|
|
update_colors(1);
|
|
break;
|
|
case "on":
|
|
power_on = 1;
|
|
if (broken) {
|
|
gap = 0.05;
|
|
} else {
|
|
gap = 0;
|
|
}
|
|
update_colors(1);
|
|
break;
|
|
#ifdef USE_BOLTS
|
|
case "bolts":
|
|
if (gets(argv, 1) == "on") {
|
|
echo("@detach=n");
|
|
} else if (gets(argv, 1) == "off") {
|
|
echo("@detach=y");
|
|
}
|
|
break;
|
|
#endif
|
|
case "broken":
|
|
gap = 0.05;
|
|
broken = 1;
|
|
break;
|
|
case "fixed":
|
|
broken = 0;
|
|
update_colors(1);
|
|
break;
|
|
case "color":
|
|
color = color_parse(argv);
|
|
update_colors(1);
|
|
break;
|
|
case "color-2":
|
|
color2 = color_parse(argv);
|
|
update_colors(1);
|
|
break;
|
|
case "color-3":
|
|
color3 = color_parse(argv);
|
|
update_colors(1);
|
|
break;
|
|
case "color-4":
|
|
color4 = color_parse(argv);
|
|
update_colors(1);
|
|
break;
|
|
case "name":
|
|
llSetObjectName(concat(delrange(argv, 0, 0), " ") + " (" + PANEL_DEVICE_NAME + ")");
|
|
break;
|
|
case "probe":
|
|
add_device(id, C_LIGHTS);
|
|
break;
|
|
case "add-confirm":
|
|
controller = id;
|
|
|
|
// Queries
|
|
tell(id, C_LIGHTS, "color-q");
|
|
tell(id, C_LIGHTS, "power-q");
|
|
tell(id, C_LIGHTS, GAUGE_SRC_Q);
|
|
|
|
// Ports
|
|
/*try_add_port(id, C_LIGHTS, "power", LN_PLUG_POWER);
|
|
try_add_port(id, C_LIGHTS, "audio-in", LN_PLUG_AUDIO1);
|
|
try_add_port(id, C_LIGHTS, "audio-out", LN_PLUG_AUDIO2);
|
|
try_add_port(id, C_LIGHTS, "data-1", LN_PLUG_DATA1);
|
|
try_add_port(id, C_LIGHTS, "data-2", LN_PLUG_DATA2);*/
|
|
tell(id, C_LIGHTS, "port power " + (string)llGetKey());
|
|
tell(id, C_LIGHTS, "port audio-in " + (string)llGetKey());
|
|
tell(id, C_LIGHTS, "port audio-out " + (string)llGetKey());
|
|
tell(id, C_LIGHTS, "port data-1 " + (string)llGetKey());
|
|
tell(id, C_LIGHTS, "port data-2 " + (string)llGetKey());
|
|
|
|
break;
|
|
case GAUGE_SRC:
|
|
gauge_value = (float)gets(argv, 1);
|
|
update_gauge();
|
|
update_colors(1);
|
|
break;
|
|
case "charge":
|
|
if (gets(argv, 1) == "start") {
|
|
charging = 1;
|
|
} else if (gets(argv, 1) == "stop") {
|
|
charging = 0;
|
|
}
|
|
update_colors(1);
|
|
break;
|
|
case "port-connect":
|
|
update_port(gets(argv, 1), id, 1);
|
|
break;
|
|
case "port-disconnect":
|
|
update_port(gets(argv, 1), id, 0);
|
|
break;
|
|
default:
|
|
#ifdef USE_VERBOSE
|
|
echo("Unhandled light bus (" + src + "): " + msg);
|
|
#endif
|
|
break;
|
|
} // switch (cmd)
|
|
|
|
llSetTimerEvent(gap);
|
|
} // if (cc == C_LIGHTS)
|
|
} // listen(...)
|
|
|
|
timer() {
|
|
if (!broken) {
|
|
return;
|
|
}
|
|
|
|
float t = 1;
|
|
if (llFrand(1.0) < 0.1) {
|
|
t = llFrand(0.2);
|
|
}
|
|
|
|
update_colors(t);
|
|
} // timer()
|
|
} // state default
|
|
|
|
// END main
|
|
//--------------------------------------------------------------------------
|