aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/LuaSL/Test sim/objects/onefang's test bed/~menu
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--LuaSL/Test sim/objects/onefang's test bed/~menu529
-rw-r--r--LuaSL/Test sim/objects/onefang's test bed/~menucfg296
2 files changed, 825 insertions, 0 deletions
diff --git a/LuaSL/Test sim/objects/onefang's test bed/~menu b/LuaSL/Test sim/objects/onefang's test bed/~menu
new file mode 100644
index 0000000..ea19396
--- /dev/null
+++ b/LuaSL/Test sim/objects/onefang's test bed/~menu
@@ -0,0 +1,529 @@
1// MLPV2 Version 2.3, by Learjeff Innis, based on
2// MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
3// 15-color balls by Lizz Silverstar
4// OpenSim port by Jez Ember
5// Meta 7 fixes by onefang Rejected
6
7// 2.3: sequences
8// 6 avs
9// Adjusting state
10
11integer MAX_BALLS = 6;
12
13string Version = "MLPV2.5";
14
15integer b;
16integer b0;
17integer ballusers;
18list BallColors;
19integer ch;
20integer chat = 1;
21integer group;
22integer i;
23integer menu;
24integer menuusers;
25integer redo = 1;
26integer swap;
27integer visible;
28integer BallCount;
29integer SaneMenuOrder;
30integer ReloadOnRez;
31
32integer Adjusting;
33string LastPose;
34
35integer BallsNeeded;
36
37float alpha;
38string cmd;
39string pose;
40string Posemsg; // for 'AGAIN'
41key owner;
42key user;
43key user0;
44list buttons;
45list buttonindex;
46list commands;
47list menus;
48list balls;
49list users;
50
51list SoundNames;
52list Sounds;
53list LMButtons;
54list LMParms;
55list MenuStack = [0]; // indices to previous menus, for "BACK" command
56
57integer MenuPage; // which page of current menu we're on, 0 for first
58
59// Replacement for llListFindList which is currently broken in OSLSL
60integer myListFind(list a, string b) {
61 integer x;
62 integer l=llGetListLength(a);
63
64 for(x=0; x<l; x++) {
65 if(llList2String(a,x) == b) {
66 return x;
67 }
68 }
69
70 return -1;
71}
72
73stop() {
74 sendStand(); //msg to pos/pose
75 llMessageLinked(LINK_THIS, 1, "STOP", (key)"");
76 llSleep(0.2);
77 killBalls();
78 swap = 0;
79 Adjusting = FALSE;
80}
81
82
83check_poses() {
84 llOwnerSay("Checking configs");
85 llMessageLinked(LINK_THIS,0,"POSEB", (key)"CHECK1"); //msg to memory
86 integer ix;
87 string name;
88 for (ix = 0; ix < llGetListLength(buttons); ++ix) {
89 name = llList2String(buttons, ix);
90 if (((integer)llList2String(commands, ix)) != 0) {
91 llMessageLinked(LINK_THIS,0,"POSEB", (key)name); //msg to memory
92 }
93 }
94 llMessageLinked(LINK_THIS,0,"POSEB", (key)"CHECK2"); //msg to memory
95}
96
97// Return a channel number that's based on the prim's key -- unique per object
98integer channel() {
99 return (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1));
100}
101
102
103// setup for a pose based on menu characteristics
104setup_pose() {
105 if (BallsNeeded) { // if submenu includes balls:
106 if (BallCount != BallsNeeded) {
107 rezBalls(); // if not enough balls present: create balls
108 llSleep(0.5);
109 }
110 integer ix;
111 for (ix = 0; ix < BallsNeeded; ++ix) {
112 llSay(ch + ix, llList2String(BallColors, ix) // to ball: color, ballnum, adjusting
113 + "|" + (string) ix
114 + "|" + (string) Adjusting);
115 }
116 if (ballusers) setBalls("GROUP"); //if group access only
117 }
118}
119
120
121unauth(string button, string who) {
122 llDialog(user0, "\n" + button + " button allowed only for " + who, ["OK"], -1);
123}
124
125continMenu(string str) {
126 llDialog(user0, "\n"+str+llKey2Name(user)+" is using the menu, continue?", ["Yes","Cancel"], ch - 1);
127}
128
129mainMenu() {
130 MenuPage = 0;
131 menu = 0;
132 doMenu(FALSE);
133}
134
135//menu partly based on Menu Engine by Zonax Delorean (BSD License)
136//llDialog(user, menuname, buttons(from index to nextindex-1), channel)
137doMenu(integer inhibit_showing) {
138 integer colors = llList2Integer(balls,menu);
139 integer ix;
140 integer mask = 0xf;
141 integer shift = 0;
142 BallsNeeded = 0;
143 BallColors = [];
144
145 for (ix = 0; ix < MAX_BALLS; ++ix) {
146 integer bc = (colors & mask) >> ix*4;
147 BallColors += (list)bc;
148 if (bc) {
149 BallsNeeded += 1;
150 }
151 mask = mask << 4;
152 }
153
154 if (inhibit_showing) {
155 return;
156 }
157
158 b0 = llList2Integer(buttonindex, menu); //position of first button for this (sub)menu
159 b = llList2Integer(buttonindex, menu+1); //position of first button for next (sub)menu
160
161 b0 += MenuPage * 12;
162 if (b - b0 > 12) {
163 b = b0 + 12;
164 }
165
166 list buttons1;
167 buttons1 = llList2List(buttons, b0, b - 1);
168 if (SaneMenuOrder) {
169 buttons1 =
170 llList2List(buttons1, -3, -1)
171 + llList2List(buttons1, -6, -4)
172 + llList2List(buttons1, -9, -7)
173 + llList2List(buttons1, -12, -10);
174 }
175 llDialog(user, Version + "\n\n" + llList2String(menus,menu), buttons1, ch - 1);
176 llResetTime();
177}
178
179say(string str) {
180 if (menuusers) llWhisper(0,str);
181 else llOwnerSay(str);
182}
183
184killBalls() {
185 integer ix;
186 for (ix = 0; ix < MAX_BALLS; ++ix) {
187 llSay(ch + ix, "DIE"); //msg to balls
188 }
189 BallCount = 0;
190 llSetTimerEvent(0.0);
191}
192
193setBalls(string cmd) {
194 integer ix;
195 for (ix = 0; ix < BallCount; ++ix) {
196 llSay(ch + ix, cmd); //msg to balls
197 }
198}
199
200
201rezBalls() {
202 integer current = BallCount;
203
204 if (BallsNeeded == BallCount) return;
205
206 if (BallCount == 0) {
207 killBalls(); // for reinitialization, if old balls are around
208 }
209
210 while (BallCount > BallsNeeded) {
211 --BallCount;
212 llSay(ch + BallCount, "DIE");
213 }
214
215 while (BallCount < BallsNeeded) {
216 llRezObject("~ball",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,ch+BallCount);
217 ++BallCount;
218 }
219
220 // Only do this if there were no balls
221 if (! current) {
222 llMessageLinked(LINK_THIS,0,"REPOS",(key)""); //msg to pos
223 }
224
225 llSetTimerEvent(30.0);
226}
227
228
229
230sendStand() {
231 llMessageLinked(LINK_THIS,0,"POSE","0,"+(string)BallCount); //msg to pos/pose
232 llMessageLinked(LINK_THIS,0,"POSEB", "stand");
233}
234
235touched(integer same_group) {
236 if (user0 == owner || (menuusers == 1 && same_group) || menuusers == 2) { //0=owner 1=group 2=all
237 if (user0 != user) {
238 if (llGetTime() < 60.0 && user != (key)"") {
239 continMenu("");
240 return;
241 }
242 user = user0;
243 group = same_group;
244 }
245 mainMenu();
246 }
247}
248
249
250// return TRUE if caller should do menu
251integer handle_cmd(string button, integer sequenced) {
252 b = myListFind(buttons, button); //find position of cmd
253 string cmd = llList2String(commands,b); //get command
254
255 if (cmd == "TOMENU") {
256 integer newmenu = myListFind(menus, button); //find submenu
257 if (newmenu == -1) return FALSE;
258 if (sequenced) {
259 integer oldmenu = menu;
260 menu = newmenu;
261 doMenu(TRUE);
262 setup_pose();
263 menu = oldmenu;
264 return FALSE;
265 }
266 i = llList2Integer(users, newmenu);
267 if (user == owner || (i == 1 && group) || i == 2) { //0=owner 1=group 2=all
268 MenuStack = (list)menu + MenuStack;
269 MenuPage = 0;
270 menu = newmenu;
271 doMenu(sequenced);
272 return FALSE;
273 }
274 if (i == 1) unauth(button, "group");
275 else unauth(button, "owner");
276 return FALSE;
277 } else if (cmd == "BACK") {
278 if (MenuPage) {
279 --MenuPage;
280 doMenu(sequenced);
281 return FALSE;
282 }
283 menu = llList2Integer(MenuStack,0);
284 MenuStack = llList2List(MenuStack,1,-1);
285 doMenu(sequenced);
286 return FALSE;
287 } else if (cmd == "MORE") {
288 ++MenuPage;
289 doMenu(sequenced);
290 return FALSE;
291 } else if (cmd == "CHECK") {
292 check_poses();
293 } else if ((integer)cmd > 0) { //POSE
294 if (Adjusting && button != pose) {
295 llMessageLinked(LINK_THIS,0,"SAVE",pose); //msg to pos/pose
296 llSleep(5.);
297 }
298 setup_pose();
299 Posemsg = cmd + "," + (string) BallCount;
300 llMessageLinked(LINK_THIS,0,"POSE", Posemsg); //msg to pose
301 llMessageLinked(LINK_THIS,0,"POSEB", (key)button); //msg to memory
302 if (chat) say(button);
303 pose = button;
304 } else if (cmd == "SWAP") {
305 swap += 1;
306 llMessageLinked(LINK_THIS,0,"SWAP",(key)((string)swap)); //msg to pos/pose
307 } else if (cmd == "STAND") {
308 sendStand(); //msg to pos/pose
309 if (chat) say(button);
310 pose = "stand";
311 } else if (cmd == "STOP") {
312 if (chat) say(button);
313 stop();
314 return FALSE;
315 } else if (cmd == "ADJUST") {
316 Adjusting = ! Adjusting;
317 setBalls("ADJUST|" + (string)Adjusting);
318 } else if (cmd == "HIDE") {
319 setBalls("0");
320 } else if (cmd == "SHOW") {
321 setBalls("SHOW");
322 } else if (cmd == "DUMP") {
323 llMessageLinked(LINK_THIS,1,"DUMP",(key)"");
324 } else if (cmd == "INVISIBLE") {
325 visible = !visible;
326 llSetAlpha((float)visible*alpha, ALL_SIDES);
327 } else if (cmd == "REDO") {
328 redo = !redo;
329 if (redo) say(button+" ON"); else say(button+" OFF");
330 } else if (cmd == "CHAT") {
331 chat = !chat;
332 if (chat) say(button+" ON"); else say(button+" OFF");
333 } else if (cmd == "BALLUSERS") {
334 ballusers = !ballusers;
335 if (ballusers) {
336 llOwnerSay(button+" GROUP");
337 setBalls("GROUP");
338 } else {
339 llOwnerSay(button+" ALL");
340 setBalls("ALL");
341 }
342 } else if (cmd == "MENUUSERS") {
343 if (user == owner) {
344 if (!menuusers) {
345 menuusers = 1;
346 llOwnerSay(button+" GROUP");
347 } else if (menuusers == 1) {
348 menuusers = 2;
349 llOwnerSay(button+" ALL");
350 } else if (menuusers == 2) {
351 menuusers = 0;
352 llOwnerSay(button+" OWNER");
353 }
354 } else unauth(button, "owner");
355 } else if (cmd == "RESET" || cmd == "RELOAD" || cmd == "RESTART") {
356 stop();
357 if (chat) say(button);
358 if (cmd == "RESET") {
359 llResetScript();
360 } else {
361 llResetOtherScript("~memory");
362 if (cmd == "RESTART") {
363 llResetScript();
364 }
365 }
366 } else if (cmd == "OFF") {
367 sendStand(); //msg to pos/pose
368 stop();
369 if (user == owner) {
370 llOwnerSay(button);
371 llResetOtherScript("~run");
372 llResetScript();
373 }
374 unauth(button, "owner");
375 return FALSE;
376 } else if (llGetSubString(cmd, 0, 0) == "Z" || (cmd == "SAVE")) { //SAVE or Z-adjust
377 llSay(0,"Z");
378 llMessageLinked(LINK_THIS,0,cmd,pose); //msg to pos/pose
379 doMenu(sequenced);
380 return FALSE;
381 } else if (cmd == "LINKMSG") {
382 // menu button to send LM to a non-MLPV2 script
383 integer ix = myListFind(LMButtons, button);
384 if (ix != -1) {
385 list lmparms = llCSV2List(llList2String(LMParms, ix));
386 llMessageLinked(
387 llList2Integer(lmparms, 1), // destination link#
388 llList2Integer(lmparms, 2), // 'num' arg
389 llList2String(lmparms, 3), // 'str' arg
390 user0); // key arg
391 if (llList2Integer(lmparms,0)) { // inhibit remenu?
392 return FALSE; // yes, bug out
393 }
394 }
395 } else if (cmd == "SOUND") {
396 integer ix = myListFind(SoundNames, button);
397 if (ix >= 0) {
398 llPlaySound(llList2String(Sounds, ix), 1.);
399 }
400 }
401 return TRUE;
402}
403
404default {
405 state_entry() {
406 ch = channel();
407 killBalls();
408 llSleep(2.0); // give ~run a chance to shut us down
409 llResetOtherScript("~menucfg");
410 llResetOtherScript("~pos");
411 llResetOtherScript("~pose");
412 llResetOtherScript("~poser");
413 llResetOtherScript("~poser 1");
414 llResetOtherScript("~poser 2");
415 llResetOtherScript("~poser 3");
416 llResetOtherScript("~poser 4");
417 llResetOtherScript("~poser 5");
418 alpha = llGetAlpha(0); //store object transparancy (alpha)
419 if (alpha < 0.1) alpha = 0.5; else visible = 1; //if invisible store a visible alpha
420 }
421
422 link_message(integer from, integer num, string str, key id) {
423 if (from != llGetLinkNumber()) { return; }
424 if (num >= 0) { return;}
425
426 // LMs from ~memory, passing configuration
427 if (num == -1) {
428 buttons = llCSV2List(str);
429 } else if (num == -2) {
430 commands = llCSV2List(str);
431 } else if (num == -3) {
432 menus = llCSV2List(str);
433 } else if (num == -4) {
434 buttonindex = llCSV2List(str);
435 } else if (num == -5) {
436 balls = llCSV2List(str);
437 } else if (num == -6) {
438 users = llCSV2List(str);
439 } else if (num == -7) {
440 LMButtons = llCSV2List(str);
441 } else if (num == -8) {
442 LMParms = llParseStringKeepNulls(str, ["|"], []);
443 } else if (num == -9) {
444 SoundNames = llCSV2List(str);
445 } else if (num == -10) {
446 Sounds = llCSV2List(str);
447 } else if (num == -20) {
448 list args = llCSV2List(str);
449 redo = llList2Integer(args,0);
450 chat = llList2Integer(args,1);
451 ballusers = llList2Integer(args,2);
452 menuusers = llList2Integer(args,3);
453 SaneMenuOrder = llList2Integer(args,4);
454 ReloadOnRez = llList2Integer(args,5);
455
456 state on;
457 }
458 }
459
460 state_exit() {
461 llOwnerSay("("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)");
462 llWhisper(0, Version + ": READY");
463 }
464}
465
466state re_on {
467 state_entry() {
468 state on;
469 }
470}
471
472state on {
473 state_entry() {
474 ch = channel();
475 owner = llGetOwner();
476 llListen(ch - 1, "", NULL_KEY, ""); //listen for pressed buttons
477 // llWhisper(0, "Channel: " + (string)ch);
478 }
479
480 on_rez(integer arg) {
481 if (ReloadOnRez) {
482 llResetScript();
483 }
484 BallCount = 0;
485 llSetTimerEvent(0.0);
486 state re_on;
487 }
488
489 touch_start(integer tcount) {
490 user0 = llDetectedKey(0);
491 touched(llDetectedGroup(0));
492 }
493
494 listen(integer channel, string name, key id, string button) {
495 if (id != user) {
496 if (button == "Yes") {
497 user = id;
498 group = llSameGroup(user0);
499 mainMenu();
500 } else if (button != "Cancel") {
501 continMenu("Selection cancelled because ");
502 }
503 return;
504 }
505 if (handle_cmd(button, FALSE) && redo) doMenu(FALSE);
506 }
507
508
509 link_message(integer from, integer num, string str, key id) {
510 if (str == "PRIMTOUCH") {
511 user0 = id;
512 touched(num);
513 return;
514 }
515 if (num == 0 && str == "AGAIN") {
516 llMessageLinked(LINK_THIS,0,"POSE", Posemsg); //msg to pose
517 llMessageLinked(LINK_THIS,0,"POSEB", (key)pose); //msg to memory
518 return;
519 }
520 if (num == -12002) {
521 handle_cmd(str, TRUE);
522 return;
523 }
524 }
525
526 timer() {
527 setBalls("LIVE"); //msg to balls: stay alive
528 }
529}
diff --git a/LuaSL/Test sim/objects/onefang's test bed/~menucfg b/LuaSL/Test sim/objects/onefang's test bed/~menucfg
new file mode 100644
index 0000000..d38843d
--- /dev/null
+++ b/LuaSL/Test sim/objects/onefang's test bed/~menucfg
@@ -0,0 +1,296 @@
1// MLPV2 Version 2.2, by Learjeff Innis, based on
2// MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
3// 15-color balls by Lizz Silverstar
4// autoback, multi-contin menu fixed
5// OpenSim port by Jez Ember
6// Meta 7 fixes by onefang Rejected
7
8integer MAX_BALLS = 6;
9
10// Multicolor ball patch by Lizz Silverstar
11// The colors var used to store the color values is a 32 bit integer (0x00000000)
12// This is broken up into 8 nibbles of which we will currently use the lower 4 nibbles
13// the first ball color is in the lower 4 bits, the second in the next 4 bits, etc
14// Masks and shifting are used to store and extract the data.
15// 4 bits gives us 15 colors. 0 = no ball, 1-15 = color
16// these index values are then used by the ~ball code to set the correct color
17// 1st ball mask is 0x0000000F, no shift
18// 2nd ball mask is 0x000000F0, shift of 4
19// 3rd ball mask is 0x00000F00, shift of 8
20// 4th ball mask is 0x0000F000, shift of 12
21
22list Colornames = [
23 "HIDE", "PINK", "BLUE", "PINK2",
24 "BLUE2", "GREEN", "MAGENTA", "RED",
25 "ORANGE", "WHITE", "BLACK", "YELLOW",
26 "CYAN", "RED2", "TEAL", "GREEN2"];
27
28
29integer PoseIx;
30
31integer CurButtonIx; // index of current button
32integer b0; // index of current button from start of current menu
33
34integer AutoBack;
35integer chat = TRUE;
36integer redo = TRUE;
37integer menuusers;
38integer group;
39integer ballusers;
40integer SaneMenuOrder;
41integer ReloadOnRez = FALSE;
42
43string cmd;
44string pose;
45string pose0;
46
47list buttons;
48list buttonindex;
49list commands;
50list menus;
51list balls;
52list users;
53
54list SoundNames;
55list Sounds;
56list LMButtons;
57list LMParms;
58
59
60// Globals for reading card config
61integer ConfigLineIndex;
62list ConfigCards; // list of names of config cards
63string ConfigCardName; // name of card being read
64integer ConfigCardIndex; // index of next card to read
65key ConfigQueryId;
66
67// Replacement for llListFindList which is currently broken in OSLSL
68integer myListFind(list a, string b) {
69 integer x;
70 integer l=llGetListLength(a);
71
72 for(x=0; x<l; x++) {
73 if(llList2String(a,x) == b) {
74 return x;
75 }
76 }
77
78 return -1;
79}
80
81integer next_card()
82{
83 if (ConfigCardIndex >= llGetListLength(ConfigCards)) {
84 ConfigCards = [];
85 return (FALSE);
86 }
87
88 ConfigLineIndex = 0;
89 ConfigCardName = llList2String(ConfigCards, ConfigCardIndex);
90 ConfigCardIndex++;
91 ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex);
92 llOwnerSay("Reading " + ConfigCardName);
93 return (TRUE);
94}
95
96default {
97 state_entry() {
98 // ch = (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim
99 llMessageLinked(LINK_THIS,1,"OK?",(key)""); //msg to memory: ask if ready
100 }
101 link_message(integer from, integer num, string str, key id) {
102 if (num == 2 && str == "OK") state load; //memory ready
103 }
104}
105
106
107state load {
108 state_entry() {
109 string item;
110 ConfigCards = [];
111 integer n = llGetInventoryNumber(INVENTORY_NOTECARD);
112 while (n-- > 0) {
113 item = llGetInventoryName(INVENTORY_NOTECARD, n);
114 if (llSubStringIndex(item, ".MENUITEMS") != -1) {
115 ConfigCards += (list) item;
116 }
117 }
118
119 ConfigCardIndex = 0;
120 ConfigCards = llListSort(ConfigCards, 1, TRUE);
121 next_card();
122 }
123
124 dataserver(key query_id, string data) {
125 if (query_id != ConfigQueryId) {
126 return;
127 }
128 if (data == EOF) {
129 if (next_card()) {
130 return;
131 }
132 state on;
133 }
134
135 integer ix = llSubStringIndex(data,"//"); //remove comments
136 if (ix != -1) {
137 if (ix == 0) data = "";
138 else data = llGetSubString(data, 0, ix - 1);
139 }
140
141 data = llStringTrim(data, STRING_TRIM_TAIL);
142 if (data != "") {
143 ix = llSubStringIndex(data," ");
144 cmd = data;
145 if (ix != -1) { //split command from data
146 cmd = llGetSubString(data, 0, ix - 1);
147 data = llGetSubString(data, ix+1, -1);
148 }
149 list ldata = llParseStringKeepNulls(data,[" | "," | "," | "," | "," |","| ","|"],[]);
150 string arg1 = llList2String(ldata, 0);
151 // llSay(0, cmd + ":" + data);
152 if (cmd == "MENU") {
153 integer auth;
154
155 if (PoseIx < 2) {
156 llOwnerSay("warning: first two items in .MENUITEMS must be: POSE stand / POSE default");
157 }
158 llOwnerSay("loading '"+arg1+"' menu");
159
160 if (llList2String(ldata, 1) == "GROUP") auth = 1; //access to submenus
161 else if (llList2String(ldata, 1) != "OWNER") auth = 2; //0=owner 1=group 2=all
162
163 integer colors;
164 string ball_color;
165 integer colorIx;
166 integer ixB;
167 for (ixB=0; ixB < MAX_BALLS; ++ixB) { // for each possible ball
168 ball_color = llList2String(ldata, ixB + 2); // get next color name from config
169
170 colorIx = myListFind(Colornames, ball_color);
171
172 if (colorIx != -1) {
173 colors += (colorIx << (4 * ixB)); // 4 = bits per color (16 colors)
174 }
175 }
176
177 menus += (list) arg1;
178 balls += (list) colors;
179 buttonindex += (list) CurButtonIx;
180 users += (list) auth;
181
182// if (llListFindList(buttons, (list)arg1) == -1) {
183
184 if (myListFind(buttons, arg1) == -1) {
185
186 integer jx = myListFind(buttons, "-");
187
188 if (jx != -1) {
189 buttons = llListReplaceList(buttons, (list)arg1, jx, jx);
190 // "TOMENU" is already in commands list from the 'TOMENU -'
191 } else if (CurButtonIx > 2) {
192 llOwnerSay("No unused 'TOMENU -' for " + arg1);
193 }
194 }
195
196 b0 = 0;
197 } else if (cmd == "AUTOBACK") {
198 AutoBack = (arg1 != "0");
199 } else if (cmd == "NORELOAD") {
200 ReloadOnRez = (arg1 != "0"); // whether to reload menu on rez
201 } else if (cmd == "MENUORDER") {
202 SaneMenuOrder = (arg1 != "0"); // keep menu buttons in same order as in file
203 } else {
204
205 // automatic menu extension (don't do for main menu)
206 if (b0 == 12 && llGetListLength(menus) > 1) {
207 // Add a "more" button before last item
208 integer ixA = -1;
209 if (AutoBack) {
210 ixA = -2;
211 // Add a "BACK" button
212 buttons = llListInsertList(buttons, (list)"BACK", ixA);
213 commands = llListInsertList(commands, (list)"BACK", ixA);
214 ++CurButtonIx;
215 }
216 buttons = llListInsertList(buttons, (list)"More-->", ixA);
217 commands = llListInsertList(commands, (list)"MORE", ixA);
218 ++CurButtonIx;
219 b0 = -ixA;
220 }
221 if (cmd == "POSE") {
222 llMessageLinked(LINK_THIS,9+PoseIx,data, (key)"");
223 if (!PoseIx) pose0 = arg1;
224 cmd = (string)PoseIx;
225 ++PoseIx;
226 } else if (cmd == "REDO") {
227 if (llList2String(ldata, 1) != "OFF") redo = 1;
228 } else if (cmd == "CHAT") {
229 if (llList2String(ldata, 1) != "OFF") chat = 1;
230 } else if (cmd == "BALLUSERS") {
231 if (llList2String(ldata, 1) == "GROUP") ballusers = 1;
232 } else if (cmd == "MENUUSERS") {
233 if (llList2String(ldata, 1) == "GROUP") menuusers = 1;
234 else if (llList2String(ldata, 1) != "OWNER") menuusers = 2;
235 } else if (cmd == "LINKMSG") {
236 LMButtons += arg1;
237 LMParms += llList2String(ldata, 1);
238 } else if (cmd == "SOUND") {
239 SoundNames += (list) arg1;
240 Sounds += (list) llList2String(ldata, 1);
241 }
242 commands += (list) cmd;
243 buttons += (list) arg1;
244 ++CurButtonIx;
245 ++b0;
246 }
247 }
248 ++ConfigLineIndex;
249 ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex); //read next line of menuitems notecard
250 }
251 state_exit() {
252 buttonindex += (list) CurButtonIx; //enter last buttonindex
253 commands += (list) ""; //empty command for undefined buttons (-1)
254
255 integer ix;
256 integer count;
257 while ((ix = myListFind(buttons, "-")) != -1) {
258 ++count;
259 buttons = llDeleteSubList(buttons, ix, ix);
260 commands = llDeleteSubList(commands, ix, ix);
261 }
262 if (count) {
263 for (ix = 1; ix < llGetListLength(buttonindex); ++ix) {
264 buttonindex = llListReplaceList(buttonindex,
265 (list)(llList2Integer(buttonindex, ix) - count), ix, ix);
266 }
267 }
268 // llMessageLinked(LINK_THIS,1,"LOADED",(string)PoseIx); //msg to memory
269 llMessageLinked(LINK_THIS,9+PoseIx,"LOADED",(key)""); //msg to pose
270 }
271}
272
273state on {
274 state_entry() {
275 llMessageLinked(LINK_THIS, -3, llList2CSV(menus), (key)""); menus = [];
276 llMessageLinked(LINK_THIS, -4, llList2CSV(buttonindex), (key)""); buttonindex = [];
277 llMessageLinked(LINK_THIS, -5, llList2CSV(balls), (key)""); balls = [];
278 llMessageLinked(LINK_THIS, -6, llList2CSV(users), (key)""); users = [];
279 llMessageLinked(LINK_THIS, -7, llList2CSV(LMButtons), (key)""); LMButtons = [];
280
281 llMessageLinked(LINK_THIS, -8, llDumpList2String(LMParms, "|"), (key)""); LMParms = [];
282
283 llMessageLinked(LINK_THIS, -9, llList2CSV(SoundNames), (key)""); SoundNames = [];
284 llMessageLinked(LINK_THIS, -10, llList2CSV(Sounds), (key)""); Sounds = [];
285
286 llMessageLinked(LINK_THIS, -2, llList2CSV(commands), (key)""); commands = [];
287 llMessageLinked(LINK_THIS, -1, llList2CSV(buttons), (key)""); buttons = [];
288
289
290 // finally, scalars (signals 'done' as well)
291 llMessageLinked(LINK_THIS, -20,
292 llList2CSV([ redo, chat, ballusers, menuusers, SaneMenuOrder, ReloadOnRez ]), (key)"");
293
294 llOwnerSay((string)CurButtonIx+" menuitems loaded ("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)");
295 }
296}