ares-scripties/hardware/minimal_panel.lsl

462 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 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) {
tell(controller, C_LIGHTS, "auth " + PANEL_DEVICE_NAME + " " + (string)user);
}
}
} // 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
update_port("power", avatar, 0);
update_port("audio-in", avatar, 0);
update_port("audio-out", avatar, 0);
update_port("data-1", avatar, 0);
update_port("data-2", avatar, 0);
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;
case "accept":
key user = getk(argv, 1);
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);
}
break;
case "denyaccess":
tell(getk(argv, 1), 0, "Access denied.");
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
//--------------------------------------------------------------------------