210 lines
5.7 KiB
Plaintext
210 lines
5.7 KiB
Plaintext
/*
|
|
HS_DollyCam - Marker helper (separate script to save Controller memory)
|
|
- Receives link_message MC_CMD:
|
|
"SHOW|N" -> rez markers for first N presets found
|
|
"HIDE" -> cleanup markers
|
|
- Listens MARKER_CH for HELLO/CLICK
|
|
- On CLICK sends MC_EVT_CLICK with payload idx to Controller
|
|
*/
|
|
|
|
integer MC_CMD = 5100;
|
|
integer MC_EVT_CLICK = 5101;
|
|
|
|
string MARKER_OBJECT = "HS_CamMarker";
|
|
integer MARKER_CH = -880088;
|
|
|
|
key gOwner;
|
|
integer gShowToken = 0;
|
|
|
|
// [key objKey, integer idx, vector pos, rotation rot] repeating
|
|
list gMarkers;
|
|
|
|
string PRE_KEY(integer idx) { return "P" + (string)idx; }
|
|
|
|
vector gTmpPos;
|
|
vector gTmpFoc;
|
|
rotation gTmpRot;
|
|
|
|
say(string s) { llOwnerSay(s); }
|
|
|
|
integer isValidIdx(integer idx) { return (idx > 0); }
|
|
|
|
integer loadPreset(integer idx)
|
|
{
|
|
string data = llLinksetDataRead(PRE_KEY(idx));
|
|
if (data == "") return FALSE;
|
|
|
|
list p = llParseString2List(data, ["|"], []);
|
|
if (llGetListLength(p) < 10) return FALSE;
|
|
|
|
gTmpPos = <(float)llList2String(p,0),(float)llList2String(p,1),(float)llList2String(p,2)>;
|
|
gTmpFoc = <(float)llList2String(p,3),(float)llList2String(p,4),(float)llList2String(p,5)>;
|
|
gTmpRot = <(float)llList2String(p,6),(float)llList2String(p,7),(float)llList2String(p,8),(float)llList2String(p,9)>;
|
|
return TRUE;
|
|
}
|
|
|
|
rotation markerRotFromPosFocus(vector pos, vector focus)
|
|
{
|
|
vector fwd = llVecNorm(focus - pos);
|
|
vector up = <0,0,1>;
|
|
vector left = up % fwd;
|
|
if (llVecMag(left) < 0.0001) left = <1,0,0>;
|
|
else left = llVecNorm(left);
|
|
vector up2 = llVecNorm(fwd % left);
|
|
return llAxes2Rot(left, up2, fwd);
|
|
}
|
|
|
|
markersClearLocal()
|
|
{
|
|
gMarkers = [];
|
|
}
|
|
|
|
integer markersFind(key obj)
|
|
{
|
|
integer i;
|
|
for (i = 0; i < llGetListLength(gMarkers); i += 4) {
|
|
if (llList2Key(gMarkers, i) == obj) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
markersHide()
|
|
{
|
|
integer i;
|
|
for (i = 0; i < llGetListLength(gMarkers); i += 4) {
|
|
key obj = llList2Key(gMarkers, i);
|
|
if (obj != NULL_KEY)
|
|
llRegionSayTo(obj, MARKER_CH, "DIE|" + (string)gShowToken);
|
|
}
|
|
markersClearLocal();
|
|
say("Markers cleaned up.");
|
|
}
|
|
|
|
showCams(integer want)
|
|
{
|
|
if (llGetInventoryType(MARKER_OBJECT) != INVENTORY_OBJECT) {
|
|
say("Missing marker object in HUD contents: " + MARKER_OBJECT);
|
|
return;
|
|
}
|
|
|
|
markersHide();
|
|
gShowToken = (integer)llFrand(2147483647.0);
|
|
|
|
vector aPos = llList2Vector(llGetObjectDetails(gOwner, [OBJECT_POS]), 0);
|
|
vector rezPos = aPos + <0,0,1>;
|
|
|
|
integer found = 0;
|
|
integer idx;
|
|
for (idx = 1; idx <= 999 && found < want; ++idx) {
|
|
if (!loadPreset(idx)) jump cont;
|
|
vector pos = gTmpPos;
|
|
vector foc = gTmpFoc;
|
|
rotation mrot = markerRotFromPosFocus(pos, foc);
|
|
|
|
llRezObject(MARKER_OBJECT, rezPos, ZERO_VECTOR, ZERO_ROTATION, idx);
|
|
|
|
gMarkers += [NULL_KEY, idx, pos, mrot];
|
|
found++;
|
|
@cont;
|
|
}
|
|
|
|
say("Showing cams: " + (string)found + " (token " + (string)gShowToken + ")");
|
|
}
|
|
|
|
default
|
|
{
|
|
state_entry()
|
|
{
|
|
gOwner = llGetOwner();
|
|
llListen(MARKER_CH, "", "", "");
|
|
}
|
|
|
|
attach(key id)
|
|
{
|
|
if (id == NULL_KEY) {
|
|
markersHide();
|
|
} else {
|
|
gOwner = llGetOwner();
|
|
}
|
|
}
|
|
|
|
link_message(integer sender, integer num, string str, key id)
|
|
{
|
|
if (num != MC_CMD) return;
|
|
if (id != gOwner) return;
|
|
|
|
str = llStringTrim(str, STRING_TRIM);
|
|
if (str == "") return;
|
|
|
|
list p = llParseString2List(str, ["|"], []);
|
|
string cmd = llToUpper(llList2String(p, 0));
|
|
|
|
if (cmd == "HIDE") {
|
|
markersHide();
|
|
return;
|
|
}
|
|
if (cmd == "SHOW") {
|
|
integer want = 12;
|
|
if (llGetListLength(p) >= 2) want = (integer)llList2String(p, 1);
|
|
if (want < 1) want = 1;
|
|
if (want > 30) want = 30;
|
|
showCams(want);
|
|
return;
|
|
}
|
|
}
|
|
|
|
object_rez(key id)
|
|
{
|
|
integer i;
|
|
for (i = 0; i < llGetListLength(gMarkers); i += 4) {
|
|
if (llList2Key(gMarkers, i) == NULL_KEY) {
|
|
integer idx = llList2Integer(gMarkers, i+1);
|
|
vector pos = llList2Vector(gMarkers, i+2);
|
|
rotation rot = llList2Rot(gMarkers, i+3);
|
|
|
|
gMarkers = llListReplaceList(gMarkers, [id], i, i);
|
|
|
|
llRegionSayTo(id, MARKER_CH,
|
|
"SET|" + (string)gShowToken + "|" + (string)idx + "|" + (string)pos + "|" + (string)rot
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
listen(integer channel, string name, key id, string msg)
|
|
{
|
|
if (channel != MARKER_CH) return;
|
|
|
|
list p = llParseString2List(msg, ["|"], []);
|
|
if (llGetListLength(p) < 2) return;
|
|
|
|
string typ = llToUpper(llList2String(p,0));
|
|
integer tok = (integer)llList2String(p,1);
|
|
if (tok != gShowToken) return;
|
|
|
|
if (typ == "HELLO") {
|
|
integer at = markersFind(id);
|
|
if (at >= 0) {
|
|
integer idx = llList2Integer(gMarkers, at+1);
|
|
vector pos = llList2Vector(gMarkers, at+2);
|
|
rotation rot = llList2Rot(gMarkers, at+3);
|
|
|
|
llRegionSayTo(id, MARKER_CH,
|
|
"SET|" + (string)gShowToken + "|" + (string)idx + "|" + (string)pos + "|" + (string)rot
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (typ == "CLICK" && llGetListLength(p) >= 3) {
|
|
integer idx2 = (integer)llList2String(p,2);
|
|
if (!isValidIdx(idx2)) return;
|
|
|
|
// Inform Controller (it will stop playlist + move camera)
|
|
llMessageLinked(LINK_SET, MC_EVT_CLICK, (string)idx2, gOwner);
|
|
return;
|
|
}
|
|
}
|
|
}
|