398 lines
12 KiB
Plaintext
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
|
|
//--------------------------------------------------------------------------
|