ares-scripties/hardware/indicators.lsl

398 lines
12 KiB
Plaintext

// init flow -> init() -> populate_link_nums() -> dataserver -> finalize_init()
//--------------------------------------------------------------------------
// BEGIN config
// use flags
//#define USE_BOLTS
//#define USE_VERBOSE
#define DEVICE_VERSION "0.1"
#define DEVICE_NAME "indicators"
// lights
#define MAX_GLOW 0.3
#define FULLBRIGHT_ON_GLOW
#define OFF_DAMP_FACTOR 0.4
#define MASKED_TINT_FACTOR 0.5
#define INDICATOR_LINK_NAME "icon"
#define TOUCHABLE_LINK_NAME "glass"
#define TEXTURE_TILES 8
// 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 " + DEVICE_NAME)
// END macros
//--------------------------------------------------------------------------
// BEGIN includes
#include <utils.lsl>
#include <objects.lsl>
// END includes
//--------------------------------------------------------------------------
// BEGIN globals
key config_query = NULL_KEY;
integer config_cur_line = 0;
string config_nc_name = "config";
key config_nc_key = NULL_KEY;
list system_names = [];
list system_flags = [];
list system_texcoords = [];
list ind_links = [];
list touch_links = [];
integer L_CAPS = 0;
integer L_LIGHTS = 0;
#define C_CAPS 411
integer C_LIGHTS = 0;
integer power_on = 1;
integer broken = 0;
float gap = 0;
vector color = <1, 1, 1>;
vector color2 = <1, 1, 1>;
vector color3 = <1, 1, 1>;
vector color4 = <1, 1, 1>;
integer sys_state = 0xFFFFFFFF;
integer masked_state = 0;
integer forbidden_state = 0;
key avatar = NULL_KEY;
key controller = NULL_KEY;
// END globals
//--------------------------------------------------------------------------
// BEGIN functions
set_tint(integer link, integer side, vector tint, vector repeats, vector offsets, float glow) {
#ifdef FULLBRIGHT_ON_GLOW
integer fullbright = 0;
if (glow > 0) {
fullbright = 1;
}
#endif
setp(link, [
PRIM_COLOR, side, tint, 1,
PRIM_GLOW, side, glow,
#ifdef FULLBRIGHT_ON_GLOW
PRIM_FULLBRIGHT, side, fullbright,
#endif
PRIM_GLTF_BASE_COLOR, side, "", repeats, offsets, 0, llsRGB2Linear(tint), 1, PRIM_GLTF_ALPHA_MODE_OPAQUE, 0.5, 0,
PRIM_GLTF_NORMAL, side, "", repeats, offsets, 0,
PRIM_GLTF_METALLIC_ROUGHNESS, side, "", repeats, offsets, 0, 1, 1,
PRIM_GLTF_EMISSIVE, side, "", repeats, offsets, 0, llsRGB2Linear(tint)
]);
}
update_colors(float level) {
if (level < 0) {
level = 0;
}
if (level > 1) {
level = 1;
}
integer sysi = count(system_names);
float tex_scale = 1.0 / TEXTURE_TILES;
vector repeats = <tex_scale, tex_scale, 0>;
while (sysi--) {
integer l = geti(ind_links, sysi);
string name = gets(system_names, sysi);
integer flag = geti(system_flags, sysi);
vector texcoord = getv(system_texcoords, sysi);
#ifdef USE_VERBOSE
echo("Updating sysi " + (string)sysi + ": link " + (string)l + ", system " + name + ", flag " + (string)flag + ", with offset " + (string)texcoord);
#endif
if (!l || !strlen(name) || !flag || texcoord == ZERO_VECTOR) {
#ifdef USE_VERBOSE
echo("Invalid, skipping " + (string)sysi + "...");
#endif
jump sysicontinue;
}
if (power_on) {
if (forbidden_state & flag) {
// System forbidden
set_tint(l, ALL_SIDES, color * OFF_DAMP_FACTOR, repeats, texcoord * tex_scale, 0);
} else if (masked_state & flag) {
// System requirements unmet
set_tint(l, ALL_SIDES, color3 * level * MASKED_TINT_FACTOR, repeats, texcoord * tex_scale, level * MAX_GLOW);
} else if (sys_state & flag) {
// System enabled
set_tint(l, ALL_SIDES, color * level, repeats, texcoord * tex_scale, level * MAX_GLOW);
} else {
// System disabled explicitly
set_tint(l, ALL_SIDES, color3 * level, repeats, texcoord * tex_scale, level * MAX_GLOW);
}
} else {
set_tint(l, ALL_SIDES, color * OFF_DAMP_FACTOR, repeats, texcoord * tex_scale, 0);
}
@sysicontinue;
}
}
integer get_prim_count() {
if (llGetAttached()) {
return llGetNumberOfPrims();
}
return llGetObjectPrimCount(llGetKey());
} // get_prim_count()
populate_link_nums() {
ind_links = [];
touch_links = [];
integer i = get_prim_count();
string link_name;
for (; i > 0; i--) {
link_name = llGetLinkName(i);
if (strpos(link_name, INDICATOR_LINK_NAME) != -1) {
ind_links += i;
}
if (strpos(link_name, TOUCHABLE_LINK_NAME) != -1) {
touch_links += i;
}
} // for (...)
#ifdef USE_VERBOSE
echo("Found " + (string)count(ind_links) + " icons, with " + (string)count(touch_links) + " touchable links");
#endif
} // populate_link_nums()
init() {
avatar = llGetOwner();
controller = NULL_KEY;
populate_link_nums();
power_on = 1;
key nc = llGetInventoryKey(config_nc_name);
if (nc == config_nc_key && nc != NULL_KEY) {
// No config change.
finalize_init();
return;
}
system_names = [];
system_flags = [];
system_texcoords = [];
config_nc_key = nc;
config_cur_line = 0;
if (config_nc_key == NULL_KEY) {
echo("No config found, cannot start");
return;
}
config_query = llGetNotecardLine(config_nc_name, config_cur_line);
}
finalize_init() {
#ifdef USE_VERBOSE
echo("Found " + (string)count(system_names) + " configured systems to track, finalizing");
#endif
update_colors(1);
// Called from dataserver once config is read.
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, "");
add_device(avatar, C_LIGHTS);
}
// END functions
//--------------------------------------------------------------------------
// BEGIN main
default {
state_entry() {
init();
} // state_entry()
on_rez(integer n) {
init();
} // on_rez(...)
changed(integer chg) {
if (chg & CHANGED_INVENTORY) {
init();
}
if (chg & CHANGED_OWNER) {
init();
}
if (chg & CHANGED_LINK) {
init();
}
}
dataserver(key qid, string data) {
if (qid == config_query) {
if (data == EOF) {
echo("Config reloaded.");
finalize_init();
} else {
// line
if (substr(data, 0, 0) == "#") {
#ifdef USE_VERBOSE
echo("Skipping comment in config: " + data);
#endif
jump confignextline;
}
list cl = split(data, " ");
if (count(cl) != 4) {
echo("Invalid line in config: " + data);
jump confignextline;
}
system_names += gets(cl, 0);
system_flags += geti(cl, 1);
system_texcoords += <geti(cl, 2), geti(cl, 3), 1>;
#ifdef USE_VERBOSE
echo("Registered system " + concat(cl, " "));
#endif
@confignextline;
config_query = llGetNotecardLine(config_nc_name, ++config_cur_line);
}
}
}
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", DEVICE_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":
gap = 0;
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), " ") + " (" + DEVICE_NAME + ")");
case "probe":
add_device(id, C_LIGHTS);
break;
case "add-confirm":
controller = id;
tell(id, C_LIGHTS, "color-q");
tell(id, C_LIGHTS, "command " + (string)avatar + " " + (string)avatar + " subsys query");
break;
case "subsys":
#ifdef USE_VERBOSE
echo("Received " + msg);
#endif
sys_state = geti(argv, 1);
masked_state = geti(argv, 2);
forbidden_state = geti(argv, 3);
update_colors(1);
break;
case "power":
break;
case "rate":
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
//--------------------------------------------------------------------------