- Add Makefile and release creation instructions. - Add a simple Python program to automate the OpenSim conversion based on markings in the code. - Add .gitignore entries for the generated files. - Add parentheses around assignments as required by OpenSim. This is done only to the core scripts. - OpenSim isn't compatible with SL when there are conditions of type key. Those are all converted. Conditions of other types, except integer, are expanded for clarity and optimization, as they generate the same or better code that way, and currently the optimizer can do a better job when they are expanded. - Floats in scientific notation need a dot. - llParseStringXXXX doesn't work the same in OpenSim as in SL, when the separator is an Unicode codepoint that doesn't represent a character. For that reason, the internal separator, which is U+FFFD ("Replacement Character") is changed automatically by the Python program to U+001F (Unit Separator control character). For further safety, function strReplace is altered to use osReplaceString instead of llParseStringKeepNulls/llDumpList2String. Furthermore, the ~ operator has the wrong precedence in OpenSim, but that was handled by a previous commit. Note that appearances of the ~ operator that were not preceded by a ! have only been replaced in the core scripts.
447 lines
14 KiB
Text
447 lines
14 KiB
Text
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright © the AVsitter Contributors (http://avsitter.github.io)
|
|
* AVsitter™ is a trademark. For trademark use policy see:
|
|
* https://avsitter.github.io/TRADEMARK.mediawiki
|
|
*
|
|
* Please consider supporting continued development of AVsitter and
|
|
* receive automatic updates and other benefits! All details and user
|
|
* instructions can be found at http://avsitter.github.io
|
|
*/
|
|
|
|
string product = "AVsitter™ sequence";
|
|
string version = "2.2";
|
|
string main_script = "[AV]sitA";
|
|
list SITTERS;
|
|
integer DEBUG;
|
|
string notecard_name = "[AV]sequence_settings";
|
|
integer notecard_line;
|
|
key notecard_query;
|
|
key notecard_key;
|
|
list SEQUENCE_DATA_NAMES;
|
|
list SEQUENCE_DATA_ACTIONS;
|
|
list SEQUENCE_DATA_DATAS;
|
|
string CURRENT_SEQUENCE_NAME;
|
|
list CURRENT_SEQUENCE_ACTIONS;
|
|
list CURRENT_SEQUENCE_DATAS;
|
|
integer SEQUENCE_LINKNUMBER = 90210;
|
|
integer SEQUENCE_POINTER = -1;
|
|
integer sequence_running;
|
|
key CONTROLLER;
|
|
key CONTROLLED;
|
|
integer menu_channel;
|
|
integer menu_handle;
|
|
integer playsounds = TRUE;
|
|
integer no_waits_yet;
|
|
integer verbose = 1;
|
|
|
|
Out(integer level, string out)
|
|
{
|
|
if (verbose >= level)
|
|
{
|
|
llOwnerSay(llGetScriptName() + "[" + version + "] " + out);
|
|
}
|
|
}
|
|
|
|
string strReplace(string str, string search, string replace)
|
|
{
|
|
return llDumpList2String(llParseStringKeepNulls(str, [search], []), replace);
|
|
}
|
|
|
|
DEBUGSay(integer level, string out)
|
|
{
|
|
if (DEBUG >= level)
|
|
{
|
|
llWhisper(0, out);
|
|
}
|
|
}
|
|
|
|
run_sequence()
|
|
{
|
|
while (SEQUENCE_POINTER >= 0)
|
|
{
|
|
string command = llList2String(CURRENT_SEQUENCE_ACTIONS, SEQUENCE_POINTER);
|
|
string data = llList2String(CURRENT_SEQUENCE_DATAS, SEQUENCE_POINTER);
|
|
list data_list = llParseStringKeepNulls(data, ["|"], []);
|
|
if (command == "PLAY")
|
|
{
|
|
DEBUGSay(2, "Playing pose " + data);
|
|
llMessageLinked(LINK_THIS, 90003, data, "");
|
|
llSleep(0.5);
|
|
}
|
|
else if (command == "SAY")
|
|
{
|
|
llSay(0, parse_text(data));
|
|
}
|
|
else if (command == "WHISPER")
|
|
{
|
|
llWhisper(0, parse_text(data));
|
|
}
|
|
else if (command == "SOUND")
|
|
{
|
|
if (playsounds)
|
|
{
|
|
string sound = llList2String(data_list, 0);
|
|
float volume = (float)llList2String(data_list, 1);
|
|
llPlaySound(sound, volume);
|
|
DEBUGSay(2, "Playing sound " + sound + " at volume " + (string)volume);
|
|
}
|
|
}
|
|
else if (command == "LOOP")
|
|
{
|
|
no_waits_yet = FALSE;
|
|
if (SEQUENCE_POINTER == llGetListLength(CURRENT_SEQUENCE_ACTIONS) - 1)
|
|
{
|
|
SEQUENCE_POINTER = -1;
|
|
DEBUGSay(2, "Looping back to start of sequence");
|
|
if (sequence_running)
|
|
{
|
|
llSetTimerEvent(0.1);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
else if (command == "WAIT")
|
|
{
|
|
if (sequence_running)
|
|
{
|
|
float time = (float)data;
|
|
DEBUGSay(2, "Waiting for " + (string)time + " seconds");
|
|
llSetTimerEvent(time);
|
|
if (time >= 2)
|
|
{
|
|
integer found;
|
|
integer next_POINTER = SEQUENCE_POINTER;
|
|
while (next_POINTER++ < llGetListLength(CURRENT_SEQUENCE_ACTIONS) && found == FALSE)
|
|
{
|
|
string next_command = llList2String(CURRENT_SEQUENCE_ACTIONS, SEQUENCE_POINTER + 1);
|
|
if (next_command == "WAIT" || next_command == "SOUND")
|
|
{
|
|
found = TRUE;
|
|
if (next_command == "SOUND")
|
|
{
|
|
list next_data_list = llParseStringKeepNulls(llList2String(CURRENT_SEQUENCE_DATAS, next_POINTER), ["|"], []);
|
|
string sound = llList2String(next_data_list, 0);
|
|
DEBUGSay(2, "Preloading sound " + sound);
|
|
llPreloadSound(sound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
no_waits_yet = FALSE;
|
|
}
|
|
return;
|
|
}
|
|
if (++SEQUENCE_POINTER >= llGetListLength(CURRENT_SEQUENCE_ACTIONS))
|
|
{
|
|
integer index = llListFindList(CURRENT_SEQUENCE_ACTIONS, ["LOOP"]);
|
|
if (index != -1)
|
|
{
|
|
SEQUENCE_POINTER = index;
|
|
DEBUGSay(2, "Looping back to line " + (string)SEQUENCE_POINTER + " of sequence");
|
|
if (sequence_running)
|
|
{
|
|
llSetTimerEvent(0.1);
|
|
}
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
stop_sequence(FALSE);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
integer get_number_of_scripts()
|
|
{
|
|
integer i;
|
|
while (llGetInventoryType(main_script + " " + (string)(++i)) == INVENTORY_SCRIPT)
|
|
;
|
|
return i;
|
|
}
|
|
|
|
string parse_text(string say)
|
|
{
|
|
integer i;
|
|
for (i = 0; i < llGetListLength(SITTERS); i++)
|
|
{
|
|
string sitter_name = llList2String(llParseString2List(llKey2Name(llList2String(SITTERS, i)), [" "], []), 0);
|
|
if (sitter_name == "")
|
|
{
|
|
sitter_name = "nobody";
|
|
}
|
|
say = strReplace(say, "/" + (string)i, sitter_name);
|
|
}
|
|
return say;
|
|
}
|
|
|
|
start_sequence(integer index)
|
|
{
|
|
no_waits_yet = sequence_running = TRUE;
|
|
SEQUENCE_POINTER = 0;
|
|
CURRENT_SEQUENCE_NAME = llList2String(SEQUENCE_DATA_NAMES, index);
|
|
CURRENT_SEQUENCE_ACTIONS = llParseStringKeepNulls(llList2String(SEQUENCE_DATA_ACTIONS, index), ["◆"], []);
|
|
CURRENT_SEQUENCE_DATAS = llParseStringKeepNulls(llList2String(SEQUENCE_DATA_DATAS, index), ["◆"], []);
|
|
DEBUGSay(1, "Sequence '" + CURRENT_SEQUENCE_NAME + "' Started!");
|
|
}
|
|
|
|
stop_sequence(integer stopSound)
|
|
{
|
|
if (sequence_running)
|
|
{
|
|
DEBUGSay(1, "Sequence '" + CURRENT_SEQUENCE_NAME + "' Ended!");
|
|
}
|
|
sequence_running = FALSE;
|
|
SEQUENCE_POINTER = -1;
|
|
llSetTimerEvent(0);
|
|
if (stopSound && ~llListFindList(CURRENT_SEQUENCE_ACTIONS, ["SOUND"]))
|
|
{
|
|
llStopSound();
|
|
}
|
|
}
|
|
|
|
sequence_control()
|
|
{
|
|
llListenRemove(menu_handle);
|
|
menu_channel = ((integer)llFrand(0x7FFFFF80) + 1) * -1; // 7FFFFF80 = max float < 2^31
|
|
string pauseplay = "▶";
|
|
if (sequence_running)
|
|
{
|
|
pauseplay = "▮▮";
|
|
}
|
|
list menu_items = ["◀◀", pauseplay, "▶▶"];
|
|
menu_handle = llListen(menu_channel, "", CONTROLLER, "");
|
|
llDialog(CONTROLLER, product + " " + version + "\n\n[" + CURRENT_SEQUENCE_NAME + "]\n◀◀ = previous anim in sequence.\n▮▮ = pause sequence.\n▶▶ = skip to next anim in sequence.", order_buttons(["[BACK]"] + menu_items), menu_channel);
|
|
}
|
|
|
|
list order_buttons(list buttons)
|
|
{
|
|
return llList2List(buttons, -3, -1) + llList2List(buttons, -6, -4) + llList2List(buttons, -9, -7) + llList2List(buttons, -12, -10);
|
|
}
|
|
|
|
commit_sequence_data()
|
|
{
|
|
SEQUENCE_DATA_NAMES += CURRENT_SEQUENCE_NAME;
|
|
SEQUENCE_DATA_ACTIONS += llDumpList2String(CURRENT_SEQUENCE_ACTIONS, "◆");
|
|
SEQUENCE_DATA_DATAS += llDumpList2String(CURRENT_SEQUENCE_DATAS, "◆");
|
|
}
|
|
|
|
default
|
|
{
|
|
state_entry()
|
|
{
|
|
notecard_key = llGetInventoryKey(notecard_name);
|
|
if (llGetInventoryType(notecard_name) == INVENTORY_NOTECARD)
|
|
{
|
|
Out(0, "Loading...");
|
|
notecard_query = llGetNotecardLine(notecard_name, notecard_line);
|
|
}
|
|
}
|
|
|
|
changed(integer change)
|
|
{
|
|
if (change & CHANGED_INVENTORY)
|
|
{
|
|
if (llGetInventoryKey(notecard_name) != notecard_key)
|
|
{
|
|
llResetScript();
|
|
}
|
|
}
|
|
}
|
|
|
|
dataserver(key query_id, string data)
|
|
{
|
|
if (query_id == notecard_query)
|
|
{
|
|
if (data == EOF)
|
|
{
|
|
commit_sequence_data();
|
|
state running;
|
|
}
|
|
else
|
|
{
|
|
list datalist = llParseString2List(data, [" "], []);
|
|
string command = llList2String(datalist, 0);
|
|
data = llStringTrim(llDumpList2String(llList2List(datalist, 1, -1), " "), STRING_TRIM);
|
|
list commands = ["PLAY", "WAIT", "SAY", "WHISPER", "SOUND", "LOOP"];
|
|
if (command == "DEBUG")
|
|
{
|
|
DEBUG = (integer)data;
|
|
}
|
|
else if (command == "SEQUENCE")
|
|
{
|
|
if (CURRENT_SEQUENCE_NAME != "")
|
|
{
|
|
commit_sequence_data();
|
|
}
|
|
CURRENT_SEQUENCE_NAME = data;
|
|
CURRENT_SEQUENCE_ACTIONS = [];
|
|
CURRENT_SEQUENCE_DATAS = [];
|
|
}
|
|
else if (llListFindList(commands, [command]) != -1)
|
|
{
|
|
CURRENT_SEQUENCE_ACTIONS += command;
|
|
CURRENT_SEQUENCE_DATAS += data;
|
|
}
|
|
notecard_query = llGetNotecardLine(notecard_name, ++notecard_line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
state running
|
|
{
|
|
state_entry()
|
|
{
|
|
Out(0, (string)llGetListLength(SEQUENCE_DATA_NAMES) + " Sequences Ready, Mem=" + (string)(65536 - llGetUsedMemory()));
|
|
integer i;
|
|
for (i = 0; i < get_number_of_scripts(); i++)
|
|
{
|
|
SITTERS += NULL_KEY;
|
|
}
|
|
}
|
|
|
|
link_message(integer sender, integer num, string msg, key id)
|
|
{
|
|
if (sender == llGetLinkNumber())
|
|
{
|
|
if (num == 90065)
|
|
{
|
|
integer index = llListFindList(SITTERS, [id]);
|
|
if (index != -1)
|
|
{
|
|
SITTERS = llListReplaceList(SITTERS, [NULL_KEY], index, index);
|
|
}
|
|
stop_sequence(TRUE);
|
|
}
|
|
else if (num == 90030)
|
|
{
|
|
SITTERS = llListReplaceList(SITTERS, [NULL_KEY], (integer)msg, (integer)msg);
|
|
SITTERS = llListReplaceList(SITTERS, [NULL_KEY], (integer)((string)id), (integer)((string)id));
|
|
stop_sequence(TRUE);
|
|
}
|
|
else if (num == 90070)
|
|
{
|
|
SITTERS = llListReplaceList(SITTERS, [id], (integer)msg, (integer)msg);
|
|
}
|
|
else if (num == 90000)
|
|
{
|
|
stop_sequence(TRUE);
|
|
integer index = llListFindList(SEQUENCE_DATA_NAMES, [msg]);
|
|
if (index != -1)
|
|
{
|
|
start_sequence(index);
|
|
run_sequence();
|
|
}
|
|
}
|
|
else if (num == 90205)
|
|
{
|
|
llMessageLinked(LINK_SET, 90005, "", id);
|
|
playsounds = !playsounds;
|
|
if (playsounds)
|
|
{
|
|
llSay(0, "Sounds ON");
|
|
}
|
|
else
|
|
{
|
|
llSay(0, "Sounds OFF");
|
|
llStopSound();
|
|
}
|
|
}
|
|
else if (num == SEQUENCE_LINKNUMBER)
|
|
{
|
|
stop_sequence(TRUE);
|
|
list data = llParseStringKeepNulls(id, ["|"], []);
|
|
CONTROLLER = (key)llList2String(data, 0);
|
|
CONTROLLED = (key)llList2String(data, -1);
|
|
integer index = llListFindList(SEQUENCE_DATA_NAMES, [msg]);
|
|
if (index != -1)
|
|
{
|
|
start_sequence(index);
|
|
if (~llListFindList(CURRENT_SEQUENCE_ACTIONS, ["WAIT"]) && ~llListFindList(CURRENT_SEQUENCE_ACTIONS, ["PLAY"]))
|
|
{
|
|
sequence_control();
|
|
}
|
|
else
|
|
{
|
|
llMessageLinked(LINK_SET, 90005, "", id);
|
|
}
|
|
run_sequence();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
listen(integer listen_channel, string name, key id, string msg)
|
|
{
|
|
if (msg == "▮▮")
|
|
{
|
|
sequence_running = FALSE;
|
|
llSetTimerEvent(0);
|
|
DEBUGSay(1, "Sequence '" + CURRENT_SEQUENCE_NAME + "' Paused!");
|
|
}
|
|
else if (msg == "▶")
|
|
{
|
|
sequence_running = TRUE;
|
|
SEQUENCE_POINTER++;
|
|
DEBUGSay(1, "Sequence '" + CURRENT_SEQUENCE_NAME + "' Resumed!");
|
|
run_sequence();
|
|
}
|
|
else if (msg == "▶▶")
|
|
{
|
|
SEQUENCE_POINTER++;
|
|
run_sequence();
|
|
}
|
|
else if (msg == "◀◀")
|
|
{
|
|
integer count_waits;
|
|
while (SEQUENCE_POINTER > -1 && count_waits < 2)
|
|
{
|
|
SEQUENCE_POINTER--;
|
|
if (llList2String(CURRENT_SEQUENCE_ACTIONS, SEQUENCE_POINTER) == "WAIT")
|
|
{
|
|
count_waits++;
|
|
}
|
|
}
|
|
SEQUENCE_POINTER++;
|
|
run_sequence();
|
|
}
|
|
else if (msg == "[BACK]")
|
|
{
|
|
llMessageLinked(LINK_SET, 90005, "", (string)id + "|" + (string)CONTROLLED);
|
|
return;
|
|
}
|
|
sequence_control();
|
|
}
|
|
|
|
timer()
|
|
{
|
|
llSetTimerEvent(0);
|
|
SEQUENCE_POINTER++;
|
|
run_sequence();
|
|
}
|
|
|
|
on_rez(integer start)
|
|
{
|
|
playsounds = TRUE;
|
|
}
|
|
|
|
changed(integer change)
|
|
{
|
|
if (change & CHANGED_LINK)
|
|
{
|
|
}
|
|
if (change & CHANGED_INVENTORY)
|
|
{
|
|
if (llGetInventoryKey(notecard_name) != notecard_key || get_number_of_scripts() != llGetListLength(SITTERS))
|
|
{
|
|
llResetScript();
|
|
}
|
|
}
|
|
}
|
|
}
|