Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // This source is "OpenSource"
- // It can be freely used under the following CC license
- // by: you need to state it was originally written by Salahzar Stenvaag
- // nc: you cannot use for commercial products
- // sa: you can extend it but you must redistribute it under the same license
- // This software is specifically written to be used by GPLv3 licenced software
- // Wiki3DBuilder (MindMap)
- // This had been built following the ideas (but not the code) of similar
- // object "SpatialMap.org (MindMap 3D) v1.0.18" written by Jonny Bee Cioc and Vision Raymaker
- // which was under a CC by,nc,sa license itself
- // What it is
- // ==========
- // You can build rich 3D wiki architectures made up of NODES, connected with particles BEANS
- // Each NODE can be customized changing its NAME, COLOR, SIZE, FORM and possibly inserting in it
- // 1 Notecard, 1 Landmark, 1 Object, 1 Script, 1 Texture, URL that can be given
- // The network is completely open to the participation of a group of people who can change the
- // newtwork, the position of each node, and freely add or remove portions of the graph
- // Being a Wiki there is no limitation on who can do what. If you don't want that the work can be furtherly
- // changed please set to NOT RUNNING the scripts. To save the mindmap you need to select all the nodes
- // and manually link them together or take in the inventory as aggregate
- // How it works
- // Initially you have a NODE, i.e. a cube which must be touched to start the process
- // Touching it you have a menu specifying color, name, size, content, move, rez, ...
- // * clicking on name you can type the name on the local chat and other menu for resizing, recoloring...
- // * clicking rez you rez a new node when choosing this option you must touch one of the faces of the cube:
- // new node will be rezzed 50cm on that direction.
- // * similarly applies to move clicking on a face will pull the node towards that direction
- // * content. Everybody can move objects, textures and so from their inventory to a node (CTRL-Dragging them).
- // at each moment only one type of object can be in the node and it can be given to whom is asking for content
- // changing the texture will also change the texture of the node
- // Internal architecture
- // This is done in ONLY one script named "Salahzar Map" and an internal object named "nodo"
- // The "Salahzar Map" is implementing a quite interesting mechanism for dealing with "multi-threading", i.e. multiple
- // avatars touching the object at the same time. This is accomplished using an Array of RECORDs representing
- // the waiting avatars and what they were waiting for. So listen(), touch(), and other events can query this QUEUE
- // and understand what is to be made next.
- // This also allows for an interesting handling of MULTI MENU
- // A part from this the rest is relatively simple, except for the communication between the various nodes.
- // A node communicates with its children for example to propagate the DELETE message
- // A node communicates with its parent to emit the particles connector
- // A node receives messages from its parent to llDie and with alert when other related objects are changing UUID
- // the latter happens when objects are re-rezzed from inventory
- // To accomplish this object listens to a
- // channelPublic (taken from Owner key) for transmitting and receiving changes of UUIDs,
- // or to channelPrivate (taken from the object key) for receiving commands from parent
- // CUSTOMIZABLE PARAMETERS
- integer TIMEOUT=30; // menu will be obsolesced after this period of time
- integer CLEANTIMERSEC=30; // timer will run once every this period of time for cleaning timers
- integer DEBUG=2; // 2 maximum level
- // PARTICLES CUSTOMIZATION
- integer PART_COUNT=5;
- float PART_RATE=0.01;
- float PART_AGE=3;
- vector PART_COLOR1=<1,0,0>;
- vector PART_COLOR2=<1,1,0>;
- string PART_TARGET=NULL_KEY;
- // Particles customization
- // END OF CUSTOMIZABLE PARAMETERS
- string url=""; // url associated with this node
- // 0) General utility functions
- // debug this string only if DEBUG is at least 1
- debug(string str)
- {
- if(DEBUG>=1)llSay(999,str);
- }
- // trace the string only if DEBUG is 2
- trace(string str)
- {
- if(DEBUG>=2)llSay(998,str);
- }
- // will put on the hover string
- notify(string str)
- {
- llSetText(str,<1,1,1>,1);
- }
- // 1) RECORD STACK
- // handling. We keep a "queue" or RECORDS for understanding
- // multi-avatar touching and remember prompts and menu and let them expire
- //
- integer STRIDE=6; // we hold 6 field in the waiting list
- list waiting=[]; // this is where we actually keep the queue
- // this will be the RECORD with the 6 fields
- string theType; // it is something like MENUxxxx or PROMPTyyyy
- key theAv; // which avatar is waiting
- integer theTime; // when the RECORD has been stacked
- integer theMenu; // the menu handle so we can clean up it
- integer theChannel; // which channel
- string theRest; // some further information on this RECORD (prompt string?)
- // count how many RECORDS are being stacked waiting to be served
- integer howManyRecords()
- {
- integer ret= llGetListLength(waiting)/STRIDE;
- trace("howManyRecords returning: "+(string)ret);
- return ret;
- }
- // load the record in theXXX variables to ease handling of it
- integer loadTheRecord(integer index)
- {
- if(index>=0)
- {
- theType=llList2String(waiting,index);
- theAv=llList2Key(waiting,index+1);
- theTime=llList2Integer(waiting,index+2);
- theMenu=llList2Integer(waiting,index+3);
- theChannel=llList2Integer(waiting,index+4);
- theRest=llList2String(waiting,index+5);
- debug("Loading the record: \n type: "+theType+"\n Av: "+(string)theAv
- +"\n time: "+(string)theTime+"\n menu: "+(string)theMenu+"\n channel:"
- +(string)theChannel+"\n rest:"+theRest);
- return index;
- }
- else
- {
- theType="";
- theAv=NULL_KEY;
- theTime=-1;
- theMenu=-1;
- theChannel=-1;
- theRest="";
- trace("No record returned");
- return -1;
- }
- }
- // look in our stack for this avatar return the index AND loading in theXXX variables
- integer findWaitingAvatar(key av)
- {
- debug("Looking for avatar: "+(string)av);
- integer pos=llListFindList(waiting,[av]);
- integer index;
- if(~pos) index=pos-1; else index=-1;
- return loadTheRecord(index);
- }
- // change the time of the event at position index
- updateTimer(integer index)
- {
- if(index<0 || index>=howManyRecords()) return;
- trace("Updating timer for index: "+(string)index);
- integer posTime=index*STRIDE+2;
- waiting=llListReplaceList(waiting,[ llGetUnixTime() ], posTime, posTime);
- }
- // remove a record
- integer deleteRecord(integer index)
- {
- if(index>=0 && index<howManyRecords())
- {
- integer i=index*STRIDE;
- waiting=llDeleteSubList(waiting,i,i+STRIDE-1);
- trace("deleteRecord "+(string)index+" array: "+llList2CSV(waiting));
- }
- return TRUE;
- }
- // PSEUDO record containing the avatar for detecting key and message
- key detected_key=NULL_KEY;
- string detected_type="";
- // add a MENU stack in the queue
- addMenu(string type, key av, string title, list options)
- {
- trace("Adding menu "+type+" for "+(string)av);
- integer channel=-1000000-(integer)llFrand(1000000);
- integer menuid=llListen(channel,"",av,"");
- waiting+=[ type, av, llGetUnixTime(), menuid, channel,"" ];
- //debug("List in touch: "+llList2CSV(waiting));
- llDialog(av,title,options,channel);
- }
- // add a PROMPT stack in the queue
- addPrompt(string type, key av, string title)
- {
- trace("Adding prompt "+type+" for "+(string)av);
- integer menuid=llListen(0,"",av,"");
- waiting+=[ type, av, llGetUnixTime(), menuid, 0, title];
- llInstantMessage(av,"Please chat: "+title);
- }
- // add in queue detect option to be able square is TRUE if we only allow boxed movement
- addDetected(string type, key av, string title)
- {
- trace("Adding detected "+type+" for "+(string)av);
- detected_key=av;
- detected_type=type;
- }
- remove_detected()
- {
- trace("remove detected");
- detected_key=NULL_KEY;
- detected_type="";
- }
- // 2) INVENTORY HANDLING
- list currentInventory=[]; // will keep note of current inventory
- // return a list of strings in ls1 NOT in ls2
- // actually implementing set difference : [ a,b,c ] - [a, b] => [c]
- // useful to understan which elements have been added deleted in the inventory
- list diffList(list ls1, list ls2)
- {
- //llSay(0,"ls1: "+llList2CSV(ls1)+" ls2:"+llList2CSV(ls2));
- list ret=[];
- integer i=0;
- for(i=0;i<llGetListLength(ls1);i++)
- {
- list el=llList2List(ls1,i,i);
- // if not found in ls2 add to residual
- if(llListFindList(ls2, el)<0)
- {
- ret+=el;
- }
- }
- return ret;
- }
- // find out the first inventory object of the specified type
- string getFromListOfType(list lst,integer type)
- {
- integer i;
- for(i=0;i<llGetListLength(lst);i++)
- {
- string name=llList2String(lst,i);
- if(name != "nodo" && name != llGetScriptName() && name != "llSetPin")
- {
- if(llGetInventoryType(name)==type) return name;
- }
- }
- return "";
- }
- // will check if inventory changed and make sure that we have JUST one elemento
- // for each type
- inventoryUpdate()
- {
- //llSay(0,"inventory update");
- integer i=0; integer j=0; string ret="";
- integer num=llGetInventoryNumber(INVENTORY_ALL);
- //if(num==llGetListLength(currentInventory)) return;
- list newInventory=[];
- for(i=0;i<num;i++)
- {
- string name=llGetInventoryName(INVENTORY_ALL,i); integer found=0;
- newInventory+=[name];
- }
- // now find added inventory
- list added=diffList(newInventory,currentInventory);
- list removed=diffList(currentInventory,newInventory);
- //llSay(0,"==>Added "+llList2CSV(added));
- //llSay(0,"==>Removed "+llList2CSV(removed));
- // now check for each added if there was a duplicate in currentInventory
- for(i=0;i<llGetListLength(added);i++)
- {
- string name=llList2String(added,i);
- string already=getFromListOfType(currentInventory,llGetInventoryType(name));
- if(already!="")
- {
- llRemoveInventory(already);
- llSay(0,name+" replaced "+already);
- }
- else
- llSay(0,name+" inserted in content");
- if(llGetInventoryType(name)==INVENTORY_TEXTURE)
- llSetTexture(name,ALL_SIDES);
- }
- currentInventory=newInventory;
- return;
- }
- // 3) handles particles
- key target=NULL_KEY;
- particles()
- {
- trace("making particles to "+(string)target);
- integer pattern = PSYS_SRC_PATTERN_EXPLODE;
- integer flags= PSYS_PART_EMISSIVE_MASK
- | PSYS_PART_INTERP_COLOR_MASK
- //| PSYS_PART_FOLLOW_SRC_MASK
- //| PSYS_PART_FOLLOW_VELOCITY_MASK
- | PSYS_PART_INTERP_SCALE_MASK
- | PSYS_PART_TARGET_LINEAR_MASK
- | PSYS_PART_TARGET_POS_MASK;
- // set particles
- llParticleSystem([ PSYS_PART_MAX_AGE,PART_AGE,
- PSYS_PART_FLAGS, flags,
- PSYS_PART_START_COLOR, PART_COLOR1,
- PSYS_PART_END_COLOR, PART_COLOR2,
- PSYS_PART_START_SCALE,<0.1,.1,FALSE>,
- PSYS_PART_END_SCALE,<0.1,.1,FALSE>,
- PSYS_SRC_PATTERN, pattern,
- PSYS_SRC_BURST_RATE,PART_RATE,
- //PSYS_SRC_ACCEL, <0,0,0>,
- PSYS_SRC_BURST_PART_COUNT,PART_COUNT,
- //PSYS_SRC_BURST_RADIUS,0.0,
- PSYS_SRC_BURST_SPEED_MIN,0,
- PSYS_SRC_BURST_SPEED_MAX,0,
- PSYS_SRC_TARGET_KEY,target,
- PSYS_SRC_ANGLE_BEGIN,0.0,
- PSYS_SRC_ANGLE_END,0.0,
- PSYS_SRC_OMEGA, <0,0,0>, // no swirling
- PSYS_SRC_MAX_AGE, 0.0, // particles last for ever
- PSYS_SRC_TEXTURE, PART_TARGET,
- PSYS_PART_START_ALPHA, 1.0,
- PSYS_PART_END_ALPHA, 1.0
- ]);
- }
- // 4) This will convert an id to an integer same id => same key
- // used to easily set up a not easy way to deposit scripts with a PIN
- integer key2int(key id)
- {
- string idstring = (string)id;
- integer ret = 0;
- integer i = 0;
- for(; i < llStringLength(idstring); ++i)
- {
- ret = ret * 10 + (((integer)("0x8"+llGetSubString(idstring, i, i)) - 2) % 17);
- }
- return ret;
- }
- integer isroot=TRUE; // are we the MAIN object? Useful to avoid being deleted
- list children=[]; // will keep the keys of ALL depending children
- // 5) propagate message to all children
- propagate(string message)
- {
- debug("Received message propagating to children: "+llList2CSV(children));
- // received a message from my parent
- // propagate message to my children
- integer i;
- for(i=0;i<llGetListLength(children);i++)
- {
- integer channel=key2int(llList2Key(children,i));
- debug("Saying on channel "+(string)channel+" "+message);
- llSay(channel,message);
- }
- if(message=="DELETE")
- {
- // we must die IF we are not ROOT
- if(isroot==0) llDie();
- else debug("Cannot delete master cube");
- }
- }
- // ============================== MAIN =========================
- integer lstPrivate;
- integer lstPublic;
- integer channelPublic;
- integer channelPrivate;
- key parent=NULL_KEY;
- default
- {
- state_entry()
- {
- llParticleSystem([]);
- llSetText("",<1,1,1>,1);
- // setting the communication channel identity private can change when re-rezzing
- channelPrivate=key2int(llGetKey());
- channelPublic=key2int(llGetOwner());
- debug("My local channel: "+(string)channelPrivate);
- debug("My public channel: "+(string)channelPublic);
- // if we are the main node go directly to ready
- // we know that because we don't have the llSetPin on main Ball
- inventoryUpdate(); // setup inventory
- if(llGetInventoryType("llSetPin")==INVENTORY_NONE)
- {
- isroot=TRUE;
- //llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
- state ready;
- }
- isroot=FALSE;
- // we are in a child node,
- notify("child...");
- trace("child ready");
- // else rezzed by parent wait to listen who is the parent
- // parent will send a message on a special channel computed starting from
- // the child key
- // waiting for knowing who is my parent
- lstPrivate=llListen(channelPrivate,"",NULL_KEY,"");
- }
- on_rez(integer rez)
- {
- if(isroot) return;
- // allow inventory dropping (for content dropping)
- llAllowInventoryDrop(TRUE);
- trace("Object rezzed with new taskUUID");
- // this happens ONLY if I come back from the inventory my UUID has changed
- // then will broadcast my old UUID
- string what="OUID:"+llGetObjectDesc();
- debug("Saying "+what+" in public channel "+(string)channelPublic);
- llSay(channelPublic,what);
- // private channel has to be reset!
- llListenRemove(lstPrivate);
- channelPrivate=key2int(llGetKey());
- trace("Listening to new privateChannel "+(string)channelPrivate);
- lstPrivate=llListen(channelPrivate,"",NULL_KEY,"");
- // reset the description
- llSetObjectDesc((string)llGetKey());
- }
- // this listen only waits until my parent talks to me
- // this happens when rezzing avatar stops the menu
- listen(integer channel,string name, key id, string str)
- {
- debug("received "+str+" on channel "+(string)channel);
- // set my parent to whom is talking to me first
- parent=id;
- // llListenRemove(lstparent);
- // emits the beam towards my parent
- target=id;
- particles();
- // remove listener before leaving this state
- llListenRemove(lstPrivate);
- state ready;
- }
- }
- // =========================== READY =========================
- state ready
- {
- state_entry()
- {
- // reset waiting list
- waiting=[]; children=[]; notify(llGetObjectName());
- llSetTimerEvent(CLEANTIMERSEC); // garbage collector
- // listen on private channel (for messages from parent -- delete)
- lstPrivate=llListen(channelPrivate,"",NULL_KEY,"");
- // listen on public channel (for UUID changing)
- lstPublic=llListen(channelPublic,"",NULL_KEY,"");
- // allow inventory dropping (for content dropping)
- llAllowInventoryDrop(TRUE);
- llSetText("...",<1,1,1>,1);
- // If here it means I'm being creating from scratch... Mark my UUID on the description
- llSetObjectDesc((string)llGetKey());
- }
- on_rez(integer rez)
- {
- trace("Object rezzed with new taskUUID");
- // this happens ONLY if I come back from the inventory my UUID has changed
- // then will broadcast my old UUID
- string what="OUID:"+llGetObjectDesc();
- debug("Saying "+what+" in public channel "+(string)channelPublic);
- llSay(channelPublic,what);
- // private channel has to be reset!
- llListenRemove(lstPrivate);
- channelPrivate=key2int(llGetKey());
- trace("Listening to new privateChannel "+(string)channelPrivate);
- lstPrivate=llListen(channelPrivate,"",NULL_KEY,"");
- // reset the description
- llSetObjectDesc((string)llGetKey());
- }
- // If we changed owner or inventory
- changed(integer change)
- {
- //llSay(0,"change: "+(string)change);
- if(change & CHANGED_OWNER)
- {
- debug("Changed owner, resetting");
- llResetScript();
- }
- // handle changing of the inventory or somebody dropped
- if(change & CHANGED_INVENTORY || change & CHANGED_ALLOWED_DROP)
- {
- inventoryUpdate();
- }
- }
- // timer is trying to get all the menu listener clean
- // if they are exhausted then proceed to cancel them
- timer()
- {
- integer i;
- for(i=0;i<howManyRecords();i++)
- {
- loadTheRecord(i); // into theXXXX fields
- // check if timeout (60 seconds
- if( (llGetUnixTime() - theTime ) > TIMEOUT )
- {
- debug("Removing listener for "+llKey2Name(theAv));
- // if we were on particular menu should also delete the
- llListenRemove(theMenu);
- deleteRecord(i);
- // if timeout something related to the detected avatar need to remove from list
- if(detected_key==theAv) remove_detected();
- }
- }
- //debug("List in timer exit: "+llList2CSV(waiting));
- }
- // main menu listening for waiting avatars
- // we answer only to
- touch_start(integer total_number)
- {
- integer i;
- for(i=0;i<total_number;i++)
- {
- key av=llDetectedKey(i);
- debug("touched by "+llKey2Name(av));
- // check if we already have this avatar waiting. Don't allow touches if in a menu or a prompt!!!!
- integer index=findWaitingAvatar(av);
- if(index>=0)
- {
- debug("Has already a menu waiting");
- // we have a menu for this avatar.. Check if we have it in detected_key
- // in such case we allow touching for detecting
- if(av==detected_key)
- {
- trace("We have a detected_key for this avatar type:"+detected_type);
- // handle this event
- if(detected_type=="DETECTMOVE")
- {
- debug("Moving the prim");
- llSetPos(llGetPos()+llDetectedTouchNormal(i)*0.2);
- }
- if(detected_type=="DETECTPOSREZ")
- {
- debug("rezzing a new cube");
- vector posrez=llDetectedTouchNormal(i);
- llRezAtRoot("nodo",llGetPos()+posrez,ZERO_VECTOR,ZERO_ROTATION,1);
- // execution is going on at rez_object
- }
- //upgrade time for this event extend it so that timer won't remove it for next 60 secs
- updateTimer(index);
- // do NOT consume this event will be ended by ctimeout
- return;
- }
- // touch this when avatar has already a queue, will remove the queue
- deleteRecord(index);
- // informing the avatar the menu has been reset
- llInstantMessage(av,"Removing pending menu/promt");
- return;
- }
- // avatar hasn't any pending menu so start with main menu
- // start the initial menu
- addMenu("MENUMAIN",av,"Main menu:\nDELETE: delete this and children,\nNAME: you can type the new name,\nCOLOR: change the color,\nSIZE: change the scale,\nREZ: rez another node (click next on face for where to rez)\nMOVE: pull the object in a direction (click next on face for where to rez),\nTYPE: changes the object type,\nHELP: go to online help,\nUNLINK: remove the connecting beam",
- ["DELETE","NAME","COLOR",
- "SIZE","REZ","MOVE",
- "TYPE","HELP","UNLINK",
- "CONTENT" ]);
- trace("List in touch exit: "+llList2CSV(waiting));
- return;
- }
- }
- // listen must understand if this avatar already has pending menu
- // and correctly sort out of them
- listen(integer channel,string name, key id, string message)
- {
- debug("receiving a message in channel "+(string)channel+" message "+message);
- // PRIVATE CHANNEL
- if(channel==channelPrivate)
- {
- debug("Received a message for me from my parent "+message);
- propagate(message);
- return;
- }
- // PUBLIC CHANNEL
- if(channel==channelPublic)
- {
- // on channel public we ONLY receive OLD UUID in the format
- // UUID:
- if(llGetSubString(message,0,4)=="OUID:")
- {
- key olduuid=(key)llGetSubString(message,5,-1);
- debug("Received from "+(string)id+" UUID change from old "+(string)olduuid);
- // need to understand if it was MY target
- if(target==olduuid){
- target=id;
- particles(); // change the beam to this new target
- }
- // check my children
- integer pos=llListFindList(children,[olduuid]);
- if(pos>=0)
- {
- debug("Replacing in children olduuid: "+(string)olduuid+" with "+(string)id);
- children=llListReplaceList(children,[id],pos,pos);
- }
- }
- return;
- }
- // if not channel public or private then it shoudl be on stack
- integer index=findWaitingAvatar(id);
- debug("listen index found on waiting list: "+(string)index);
- if(index<0) return;
- // only here if we found on the stack
- integer elapsed=llGetUnixTime()-theTime;
- // remove handle AND the record from waiting list
- llListenRemove(theMenu);
- deleteRecord(index);
- debug("Found listen menu type: "+theType+" mesg "+message);
- // stopping menus
- if(theType=="MENUSTOPMOVE")
- {
- remove_detected();
- llInstantMessage(id,"Stop moving");
- return;
- }
- if(theType=="MENUSTOPREZ")
- {
- remove_detected();
- llInstantMessage(id,"Stop rezzing");
- return;
- }
- // handling menu content allow for setting content
- if(theType=="MENUCONTENT")
- {
- // allows for specifying a URL
- if(message=="SETURL")
- {
- addPrompt("PROMPTURL",id,"Say in chat the url where to go");
- return;
- }
- // just send help on how ctrl-dragging objects
- if(message=="SETCONTENT")
- {
- // send help
- llInstantMessage(id,"Please ctrl-drag something from your inventory on me. You can change the texture dragging a texture");
- return;
- }
- // going to stored URL
- if(message=="GIVE URL")
- {
- if(url!="")
- {
- llLoadURL(id,"Go to webpage",url);
- }
- return;
- }
- // handle all GETXXX buttons
- string name1; string desc;
- if(message=="GIVE NOTE")
- {
- name1=getFromListOfType(currentInventory,INVENTORY_NOTECARD);
- desc="notecard";
- }
- if(message=="GIVE LMARK")
- {
- name1=getFromListOfType(currentInventory,INVENTORY_LANDMARK);
- desc="landmark";
- }
- if(message=="GIVE OBJECT")
- {
- name1=getFromListOfType(currentInventory,INVENTORY_OBJECT);
- desc="object";
- }
- if(message=="GIVE TEXTURE")
- {
- name1=getFromListOfType(currentInventory,INVENTORY_TEXTURE);
- desc="texture";
- }
- if(name1=="")
- {
- llInstantMessage(id,"No "+desc+" to give you");
- return;
- }
- // giving actually the object
- llGiveInventory(id,name1);
- llInstantMessage(id,"You have been given a "+desc+" named "+name1);
- return;
- }
- // Handling of the options in MAIN MENU
- if(theType=="MENUMAIN")
- {
- if(message=="HELP")
- {
- llLoadURL(id,"Load this page for help","http://opensimita.org/lsl/mindmap/README.html");
- return;
- }
- if(message=="CONTENT")
- {
- integer i;
- string texture=getFromListOfType(currentInventory,INVENTORY_TEXTURE);
- string object=getFromListOfType(currentInventory,INVENTORY_OBJECT);
- string note=getFromListOfType(currentInventory,INVENTORY_NOTECARD);
- string landmark=getFromListOfType(currentInventory,INVENTORY_LANDMARK);
- string prompt = "Choose an action:\nSETCONTENT: explains how to insert an object\nSETURL: allows for specifying a url";
- list buttons=["SETCONTENT","SETURL" ];
- if(url!="")
- {
- prompt+="\nGIVE URL: go to the url "+url;
- buttons+=["GIVE URL"];
- }
- if(note!="")
- {
- prompt+="\nGIVE NOTE: get the note "+note;
- buttons+=["GIVE NOTE"];
- }
- if(object!="")
- {
- prompt+="\nGIVE OBJECT: get the object "+object;
- buttons+=["GIVE OBJECT"];
- }
- if(landmark!="")
- {
- prompt+="\nGIVE LMARK: get the landmark "+landmark;
- buttons+=["GIVE LMARK"];
- }
- if(texture!="")
- {
- prompt+="\nGETTEXTURE: get the texture "+texture;
- buttons+=["GIVE TEXTURE"];
- }
- addMenu("MENUCONTENT",id,prompt,buttons);
- return;
- }
- if(message=="NAME")
- {
- addPrompt("PROMPTNAME",id,"Say in chat name of this concept");
- return;
- }
- if(message=="DELETE")
- {
- addPrompt("PROMPTDELETE",id,"Say DELETE in chat to be absolutely sure to delete from here");
- return;
- }
- if(message=="COLOR")
- {
- addMenu("MENUCOLOR",id,"Enter color",["RED","GREEN","BLUE","WHITE","BLACK","VIOLET","TURQUESE","YELLOW"]);
- return;
- }
- if(message=="SIZE")
- {
- addMenu("MENUSIZE",id,"Enter size",["HALF", "DOUBLE", "+0.2","-0.2","DEFAULT"]);
- return;
- }
- if(message=="UNLINK")
- {
- llParticleSystem([]); target=NULL_KEY;
- llInstantMessage(id,"Removed particles");
- return;
- }
- // detected category
- if(message=="REZ")
- {
- addDetected("DETECTPOSREZ",id,"Enter position where rez");
- addMenu("MENUSTOPREZ",id,"Click on a face of the concept to rez a new cube in that direction.\nClick 'stop' after chosing",["STOP"]);
- return;
- }
- if(message=="MOVE")
- {
- addDetected("DETECTMOVE",id,"Click on a face of the concept and the cube will move 20cm in that direction.");
- addMenu("MENUSTOPMOVE",id,"Click to stop moving",["STOP"]);
- return;
- }
- if(message=="TYPE")
- {
- addMenu("MENUTYPE",id,"Select type of this concept",["SPHERE","CUBE","FLAT","CYLINDER","PYRAMID","POINT","STAR","ENDTYPE"]);
- return;
- }
- }
- // change the type of this prim
- if(theType=="MENUTYPE")
- {
- if(message=="ENDTYPE")
- {
- llInstantMessage(id,"Finished with typing");
- return;
- }
- list typ=[];
- if(message=="FLAT")
- {
- vector scale=llGetScale();
- llSetScale(<0.01,scale.y,scale.z>);
- return;
- }
- if(message=="POINT")
- {
- llSetScale(<0.01,0.01,0.01>);
- return;
- }
- if(message=="STAR")
- {
- llInstantMessage(id,"STAR not yet implemented");
- return;
- }
- if(message=="SPHERE") typ=[ PRIM_TYPE, PRIM_TYPE_SPHERE, 0, <0,1,0>, 0.0, <0,0,0>,<0,1,0> ];
- if(message=="CUBE") typ=[ PRIM_TYPE, PRIM_TYPE_BOX,0, <0.0, 1.0, 0.0>, 0.0, <0.0, 0.0, 0.0>, <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>];
- if(message=="CYLINDER") typ=[ PRIM_TYPE, PRIM_TYPE_CYLINDER, 0, <0.0, 1.0, 0.0>, 0.0, <0.0, 0.0, 0.0>, <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>];
- if(message=="PYRAMID") typ=[ PRIM_TYPE, PRIM_TYPE_BOX,0, <0.0, 1.0, 0.0>, 0.0, <0.0, 0.0, 0.0>, <0.0, 0.0, 0.0>, <0.0, 0.0, 0.0>];
- llSetPrimitiveParams(typ);
- addMenu("MENUTYPE",id,"Select type of this concept",["SPHERE","CUBE","FLATBOX","CYLINDER","PYRAMID","POINT","STAR","ENDTYPE"]);
- return;
- }
- // change the size of this prim
- if(theType=="MENUSIZE")
- {
- vector current=llGetScale();
- if(message=="HALF") current=current/2;
- if(message=="DOUBLE") current=current*2;
- if(message=="+0.2") current=current+<0.2,0.2,0.2>;
- if(message=="-0.2") current=current-<0.2,0.2,0.2>;
- if(message=="DEFAULT") current=<0.5,0.5,0.5>;
- llSetScale(current);
- llInstantMessage(id,"Size changed to '"+(string)current+"'");
- return;
- }
- // change the color of this prim
- if(theType=="MENUCOLOR")
- {
- if(message=="RED") llSetColor(<1,0,0>,ALL_SIDES);
- if(message=="GREEN") llSetColor(<0,1,0>,ALL_SIDES);
- if(message=="BLUE") llSetColor(<0,0,1>,ALL_SIDES);
- if(message=="WHITE") llSetColor(<1,1,1>,ALL_SIDES);
- if(message=="BLACK") llSetColor(<0,0,0>,ALL_SIDES);
- if(message=="VIOLET") llSetColor(<1,0,1>,ALL_SIDES);
- if(message=="TURQUESE") llSetColor(<0,1,1>,ALL_SIDES);
- if(message=="YELLOW") llSetColor(<1,1,0>,ALL_SIDES);
- llInstantMessage(id,"Color changed to '"+message+"'");
- return;
- }
- // change the name
- if(theType=="PROMPTNAME")
- {
- notify(message);
- llSetObjectName(message);
- llInstantMessage(id,"Name changed to '"+message+"'");
- return;
- }
- if(theType=="PROMPTDELETE")
- {
- if(message=="DELETE")
- {
- // handle delete message
- propagate(message);
- return;
- }
- }
- // change the url
- if(theType=="PROMPTURL")
- {
- url=message;
- llInstantMessage(id,"URL accepted: "+url);
- return;
- }
- }
- // when new node is rezzed then we give this script running and tell it
- // my id so that it can emit particles
- object_rez(key id)
- {
- integer childchannel=key2int(id);
- // memorize this channel so to be able to speak to all my children in case of die
- children+=[id];
- llGiveInventory(id,"nodo");
- debug("Chatting "+(string)llGetKey()+" on channel "+(string)key2int(id)+ "children: "+llList2CSV(children));
- llSay(childchannel,(string)llGetKey());
- //llInstantMessage("Node created");
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement