how to change various prims sizes from a single script?
|
|
Atomo Hosho
Registered User
Join date: 23 Aug 2006
Posts: 7
|
01-06-2007 13:23
Hi everyone, i want to build an object that when touched, creates a grid of prims and resizes them all to different values (stored on the same script). I've successfully built a script that creates the grid of prims, but I'm unable to resize them. I'm used to other OO scripting/programming languages, where you can set values/call methods like this: customObject myChild = new Child(); myChild.setWidth( 50 ); how do you do such a thing in lsl? Thanks a lot 
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
01-06-2007 14:06
LSL doesnt work like that. And logically it cant. You will need scripts in the child prims which will listen for the size information from the master prim.
You can pass an integer as a rez parameter to an object, use it to set up a channel for each prim and then send the size information. Once completed you can have the script delete itself.
|
|
xan Malthus
Registered User
Join date: 25 Apr 2006
Posts: 2
|
01-06-2007 17:08
edit: Perhaps I misinterpreted your goal. Below wont help you to resize already rezzed prims, but may help if you just need to set the scale on rez. If you do not need distinct values for the x,y,z components of scale, just pass in an integer scale value to the start_param value of llRezObject. Then in on_rez in the rezzed object, use start_param as a value for llSetScale() This will give you 1 meter resolution. If you do not need distinct values for the x,y,z components of scale, but need more than 1m resolution, you can multiply the scale value passed to llRezObject by say 100. In the on_rez event in the rezzed prim, divide start_param by 100. If you want to pass in seperate x,y,z scale values, you can use some bitwise operations to encode the scale vector into an integer. The integer is then passed in to llRezObject start_param. This example below uses 8 bits per vector component. If you need more resolution, you could alter the encode and decode functions to use 10 bits per vector component. Below is come code which may help you to pass a scale vector to a rezzed object, using 8 bits per vector component. 8 bits of start_param are unused. In the rezzing script: // "constants" used to index bitfields in start param integer START_PARAM_X = 0; integer START_PARAM_Y = 1; integer START_PARAM_Z = 2; integer START_PARAM_OTHER = 3;
integer encode_param(integer sparam, integer bitparam_id, integer val) { integer mask = (0xff & val) << (bitparam_id * 8); return sparam | mask; }
rez_scaled(string inventory, vector pos, vector scale) { integer rez_param = 0; rez_param = encode_param(rez_param, START_PARAM_X, (integer)scale.x); rez_param = encode_param(rez_param, START_PARAM_Y, (integer)scale.y); rez_param = encode_param(rez_param, START_PARAM_Z, (integer)scale.z); llRezObject(inventory, pos, ZERO_VECTOR, ZERO_ROTATION, rez_param); }
In the rezzed object: // // decode param belongs in the rezzed object script integer decode_param(integer param_id, integer param) { integer mask = 0xff << (param_id * 8); return ((param & mask) >> (param_id * 8)); }
// "constants" used to index bitfields in start param integer START_PARAM_X = 0; integer START_PARAM_Y = 1; integer START_PARAM_Z = 2;
default { on_rez(integer start_param) { vector scale; if (start_param) { scale.x = (float)decode_param(START_PARAM_X, start_param); scale.y = (float)decode_param(START_PARAM_Y, start_param); scale.z = (float)decode_param(START_PARAM_Z, start_param); llSetScale(scale); llRemoveInventory(llGetScriptName()); } else { //scale = llGetScale(); } } }
|
|
Atomo Hosho
Registered User
Join date: 23 Aug 2006
Posts: 7
|
01-07-2007 02:52
Hi again, thanks a lot for your answers. The code listed here was very useful, however, setting the size of rezzed objects is just a first step, for the sake of simplification. In fact, what I have is a notecard with almost complete data about prims. I started using xml but parsing it in lsl is (or at least it seemed to me) pretty difficult, so what I'm using now is a CSV string like this: posX,posY,posZ,sizeX,sizeY,sizeZ,rotX,rotY,rotZ 0,0,0,1,1,1,0,0,0 0,1,1,1,1,2,0,0,0 0,2,2,1,1,4,0,0,0 0,3,3,1,1,6,0,0,0 I want to be able to add as many columns in this list as needed, so that i can eventually set ANY property of those prims. Therefore, I guess my way to go is using listeners/channels as suggested by Newgate Ludd. I've seen some examples about this around the web, but I don't really get it. As far as I understood, channels are "chat" channels. These channels can be used by avatars or objects, so in theory i could rez a prim and script it to listen to channel 256. However, if someone (or some other script) uses the same channel, my script will detect it probably leading to error. Also, once I've rezzed all of my prims, and resizing/customizing has been done, I'd want to stop (or remove, as suggested) their scripts, as those prims are expected to be left there for a long time, and they don't need scripting anymore. Could you provide a super-simple example of this chanel/listener approach? One more thing i found out during research, and which i found specially worrying, is the 0.2 seconds delay when resizing objects. My script is expected to rez about 100 prims per average, so it could take about 20 seconds (in fact it takes quite more, probably because of similar dealys in other methods) each time it is run. Is there a way to avoid or improve this? Thanks a lot for your help and patience 
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
01-07-2007 03:21
From: Atomo Hosho Hi again, thanks a lot for your answers. The code listed here was very useful, however, setting the size of rezzed objects is just a first step, for the sake of simplification. In fact, what I have is a notecard with almost complete data about prims. I started using xml but parsing it in lsl is (or at least it seemed to me) pretty difficult, so what I'm using now is a CSV string like this: posX,posY,posZ,sizeX,sizeY,sizeZ,rotX,rotY,rotZ 0,0,0,1,1,1,0,0,0 0,1,1,1,1,2,0,0,0 0,2,2,1,1,4,0,0,0 0,3,3,1,1,6,0,0,0 I want to be able to add as many columns in this list as needed, so that i can eventually set ANY property of those prims. Therefore, I guess my way to go is using listeners/channels as suggested by Newgate Ludd. I've seen some examples about this around the web, but I don't really get it. As far as I understood, channels are "chat" channels. These channels can be used by avatars or objects, so in theory i could rez a prim and script it to listen to channel 256. However, if someone (or some other script) uses the same channel, my script will detect it probably leading to error. Also, once I've rezzed all of my prims, and resizing/customizing has been done, I'd want to stop (or remove, as suggested) their scripts, as those prims are expected to be left there for a long time, and they don't need scripting anymore. Could you provide a super-simple example of this chanel/listener approach? One more thing i found out during research, and which i found specially worrying, is the 0.2 seconds delay when resizing objects. My script is expected to rez about 100 prims per average, so it could take about 20 seconds (in fact it takes quite more, probably because of similar dealys in other methods) each time it is run. Is there a way to avoid or improve this? Thanks a lot for your help and patience  Several ways to secure you chat, in the first instance you have the full range of channels available to you from -2147483648 to 2147483647. So the likely hood of someone else using the same channel. especially for short periods of time, can be minimised using a simple llFrand call. You can also include your key, or some other 'password', as a part of the comms data to prevent it from activating on someone elses comms. The resize delay is in the receiver object not the sender, so it is totally irrelevant to your sender. You will find it is the dataserver event that is probably causing the delays. Also try looking at llSetPrimitiveParams as this concatenates multiple calls into one list and only causes one 0.2 second delay. To delete the script once you have finished with it just use llRemoveInventoryOf course there is another way,( In LSL there normally is!) Your notecard contains 1 line per target prim. If you passed each prim their number, and the notecard key they could then look up their own parameters. This reduces the communications code but does make the slave prim code more complex.
|
|
Atomo Hosho
Registered User
Join date: 23 Aug 2006
Posts: 7
|
01-07-2007 03:29
I see, thanks a lot. anyway, could you provide a REALLY simple example of this communication (or just a link url to such a example)? The ones i've found are pretty complex as they involve more advaced things.
thanks
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
01-07-2007 04:22
From: Atomo Hosho I see, thanks a lot. anyway, could you provide a REALLY simple example of this communication (or just a link url to such a example)? The ones i've found are pretty complex as they involve more advaced things.
thanks Well you asked for code so I'm not breaking my own rules by posting it. Its untested so have fun! Object Rezzer Script // // Object rezzer problem posted by Atomo Hosho //
string notecardName = "MyData"; // Notecard being read integer lineCounter = 0; // line number being read key dataRequestID= NULL_KEY; // data Server ID
integer Channel = 0; integer Listening; integer TimeOut = 10;
string ObjectName = "MyObject"; // Object to be rezzed
string ProcessStarted = "HELLO"; // Sign on Message to be sent string ProcessData = "DATA"; // data message Identifier string ProcessCompleted = "BYE"; // Sign off message
string strOwner;
string PrimitiveParameters; // Parameters read from notecard string ProcessingData;
//------------------------------------------------------- UpdateListen(key id) { // Cancel the existing Listen CancelListen(); Listening = llListen(Channel,"",id,""); // Timeout llSetTimerEvent(TimeOut); } //------------------------------------------------------- CancelListen() { // If we are listening, remove the listen if(Listening > 0) llListenRemove(Listening); Listening = 0; // Clear the timer llSetTimerEvent(0); } //------------------------------------------------------- default { state_entry() { llSetText("Touch To start Rezing!",<1,1,1>,1); strOwner = (string)llGetOwner() ; } touch_start(integer num_detected) { key user = llDetectedKey(0); if(user == llGetOwner()) { // Check that its a valid Notecard name, just incase its been deleted somehow integer itemtype = llGetInventoryType(notecardName); if(INVENTORY_NOTECARD == itemtype) { state readNotecard; } else { // No note card? llOwnerSay("I'm sorry but I cannot find " + notecardName); } } } // If anything changes reset ourselves changed(integer change) { llResetScript(); } // When ever we rez reset ourselves on_rez(integer num) { llResetScript(); } }
//-------------------------- state readNotecard { state_entry() { llWhisper(0,"Reading notecard " + notecardName + " Line " + (string)lineCounter); llSetObjectName(notecardName); dataRequestID = llGetNotecardLine(notecardName, lineCounter); llSetTimerEvent(TimeOut); } dataserver(key queryid, string data) { //Check to make sure this is the request we are making. //Remember that when data comes back from the dataserver, //it goes to *all* scripts in your prim. //So you have to make sure this is the data you want, and //not data coming from some other script. if (dataRequestID) { llSetTimerEvent(0); //If we haven't reached the end of the file if (data != EOF) { // // Use ; as comments // if(llGetSubString(data, 0,0) != ";") { PrimitiveParameters = data; state ProcessPrim; } } else { llWhisper(0,"+----------------------------- end Of Note Card ----------------------------+ "); llSetTimerEvent(0); state default; } } } timer() { // The notecard read failed so abort llSetTimerEvent(0); llSay(0,"Error reading Data.Aborting."); state default; } } //------------------------------------------------------- // state ProcessPrim { state_entry() { // Choose a channel Channel = 0 - (integer) llFrand(2147483647); // Rez Our Object. - need to calculate its position? vector pos = < 0,0,0>; llRezObject(ObjectName, pos, ZERO_VECTOR, ZERO_ROTATION, Channel); } object_rez(key id) { // Gives us the ID of the rezzed prim // Listen for our newly rezzed object to say Hi UpdateListen(id); llSay(Channel, strOwner + "|" + ProcessStarted); } listen(integer channel, string name, key id, string message) { // Cancel the existing listen CancelListen(); // Process the message if(ProcessStarted == message) { ProcessingData = strOwner + "|" + ProcessData + "|" + PrimitiveParameters; llSay(Channel, ProcessingData); UpdateListen(id); } else if(ProcessingData == message) { llSay(Channel, strOwner + "|" + ProcessCompleted); UpdateListen(id); } else if(ProcessCompleted == message) { // Next Object ++lineCounter; state readNotecard; } } timer() { // No reply CancelListen(); state default; } // If anything changes reset ourselves changed(integer change) { llResetScript(); } // When ever we rez reset ourselves on_rez(integer num) { llResetScript(); } }
Rezzed Object Script // // Child Script for Object rezzer problem posted by Atomo Hosho // integer Channel = 0; string strOwner;
string PrimitiveParameters; // Parameters read from notecard
string ProcessStarted = "HELLO"; // Sign on Message to be sent string ProcessData = "DATA"; // data message Identifier string ProcessCompleted = "BYE"; // Sign off message
// Do the actual work ProcessInformation() { } //------------------------------------------------------- default { on_rez(integer num) { Channel = num; llListen(Channel,"","",""); strOwner = (string)llGetOwner() ; }
listen(integer channel, string name, key id, string message) { list data = llParseString2List(message,["|"],[""]); string str = llList2String(data,0); string command = llList2String(data,1); if(str == strOwner) { // Process the message if(ProcessStarted == command) { llSay(Channel, message); } else if(ProcessData == command) { PrimitiveParameters = llList2String(data,2); ProcessInformation(); llSay(Channel, message); } else if(ProcessCompleted == command) { llSay(Channel, message); llSleep(0.1); llRemoveInventory(llGetScriptName()); // delete this script } } } }
I've left the actual processing of the data up to you.
|
|
Atomo Hosho
Registered User
Join date: 23 Aug 2006
Posts: 7
|
01-08-2007 08:37
Cool! I get it, everything's working fine now. Thanks a lot for your help 
|