Jump to content

Object IDs/keys: Do they change?


Vindictii
 Share

You are about to reply to a thread that has been inactive for 1577 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I seem to recall reading that objects have two IDs: asset ID and an instance ID. It was my impression that the asset ID is fixed and never changes while the instance ID exists only while the object is rezzed (place in world, worn on character as gear or attached as a HUD). Is this accurate? Is the asset ID permanent? Can the asset's ID be used to identify the object when it is rezzed or is only the instance ID valid at that time? 

Link to comment
Share on other sites

The only UUID we ever see is associated with a rezzed object, and that unique UUID is assigned to that particular instance. There is obviously a file in the asset servers that defines each object, but it does not have an identifier that we can access.  As far as we are concerned, it does not exist.

Link to comment
Share on other sites

We will soon have scripted access to an object's (link's) creation time. These times are stored in full ISO-8601 (YYYY-MM-DDThh:mm:ss.SSSSSSZ) format and are unchangeable. There are only two occasions when these times are created, with raw material creation, such as rezzing a cube, sphere, torus through the build menu and with mesh uploading. I have yet to see duplicates with either means.

This will be the best universal identifier possible in and out of your inventory.

Once access is grid wide, I encourage creators to start referencing these times in their mod products, especially mesh products that use texture appliers or products that have scripts that reset and check if they are in the original host object/link or not. In mod environments, this identifier will be more resilient than relying on object names, desc, link numbers or settext which might need to be changed by the end user, especially in full-perm products meant to be modded and resold with lesser permissions.

  • Like 6
Link to comment
Share on other sites

  • 2 years later...

I am a little confused by this thread and llGetInventoryKey((string)name). The description from API page for this function is:

Returns a key that is the UUID of the inventory name

A comment at the bottom of the page states:

The UUID returned is that of the asset to which the inventory item points, it is not the UUID of the inventory item itself. The assets themselves are immutable (they never change, they are only ever created and deleted); this allows multiple inventory handles to refer to the same asset without having to duplicate the asset. When it appears an asset is being modified, it is saved as a new asset. The consequence of this is that multiple copies of items in inventory all share the same asset UUID.

 

I have tested llGIK and it seems to work as specified.

What am I missing?

Also, can I find the UUID of a rezzed object from the UI?

Thanks,

G

Link to comment
Share on other sites

The wording is a bit confusing, but the bottom line is that the asset itself resides in the asset servers as a set of descriptors. When you rez an item in world, it is an instance of the asset with a unique UUID.  So, five rezzed copies of the same object will have five different UUIDs.  If you were to use a script in each copy to ask

llSay(0, "My UUID = " + (string)llGetKey() );

you would get five different answers.  Similarly, if your use llSensor to scan for

llSensor("My_Object","",ACTIVE|PASSIVE, 10.);

and it detects 5 instances of My_Object in range, each will report a different llDetectedKey(i) if you step through the list of detected objects.

The part that's confusing is that for many types of assets (textures, animations, sounds, ..) the UUID does not change with each instance in world, so for example you can right click on a sound in inventory and choose "Copy Asset UUID" to get an immutable identifier that you can hard code into a script to produce that sound every time it calls llPlaySound(UUID_goes_here), 1.0); I find it easiest to think of those sorts of assets as prim properties rather than "things" that need a unique UUID each time they appear.

 

Link to comment
Share on other sites

1 hour ago, Rolig Loon said:

The wording is a bit confusing, but the bottom line is that the asset itself resides in the asset servers as a set of descriptors. When you rez an item in world, it is an instance of the asset with a unique UUID.  So, five rezzed copies of the same object will have five different UUIDs.  If you were to use a script in each copy to as

 

Digging deeper:

Considering the swing I am building in the frame object I have put from my inventory the swing object. Here is a screenshot of the contents

https://gyazo.com/96131d52c2977a0f5604b881079c29aa

I had placed the object named "FooSwingFoo" in the contents from *MY*  AV's inventory.

When I call llOwnerSay("Swing Key: " + (string)llGetInventoryKey("FooSwingFoo")); from a script in the frame object I get a key, say 'KofFooSwingFooInContents'. No matter how many times I make this call the returned key is the same, KofFooSwingFooInContents.

If I call  llRezObject("FooSwingFoo", llGetPos() + <0.0,0.0,0.0>, <0.0,0.0,0.0>, <0.0,0.0,0.0,1.0>, 0); I get the multilinked object of the root cube and the swing.

When I call llSay(0, "My UUID = " + (string)llGetKey() ); from a script in the root cube, I get KofRezzedRootCube-1, and when I call it from a script in the swing I get a key KofRezzedFooSwingFoo-1.

If rez another FooSwingFoo I get two new keys KofRezzedRootCube-2 and KofRezzedFooSwingFoo-2.

So, all good and making sense at this point.

If I DELETE the object FooSwingFoo from *MY*  AV's inventory NOTHING CHANGES. The calls and rezzing of FooSwingFoo that is in the contents of the frame object work just the same.

I did not test logging out after deleting FooSwingFoo then logging in...

What I can infer is that an object placed in the contents of another object from a users inventory has a unique, stable, (maybe immutable) UUID. And it seems like this is NOT a reference to the object in a user's inventory. When I rez an instance of the object from the contents it then gets an instance UUID (one for the root prim and another for each child prim

Again, Thanks Rolig, for getting me going on this path. I believe I understand UUIDs well enough to proceed.

 

Cheers,

G

Link to comment
Share on other sites

There's another tool in your arsenal, too.  Take a look at the object_rez event, which lets you capture the UUID of whatever it was that you just rezzed.  Save that value as a global key so you can use it whenever you need to identify that particular instance.

Link to comment
Share on other sites

If you intend to pass information from a rezzer to a rezzed object (say, for example, the UUID of whoever touched the rezzer), the smartest way to do that is to have the rezzed object send a "OK, I'm ready!" message back to the rezzer.  When the rezzer receives that go-ahead prompt, it can send the important information in a quick llRegionSayTo message.  That simple handshake protocol guarantees that the information is not passed prematurely.  You can of course send the comm channel's value as the integer that's passed on_rez, so you put both a llListen statement and your "OK, I'm ready!" message in the on_rez event. 

Link to comment
Share on other sites

1 hour ago, Rolig Loon said:

If you intend to pass information from a rezzer to a rezzed object (say, for example, the UUID of whoever touched the rezzer), the smartest way to do that is to have the rezzed object send a "OK, I'm ready!" message back to the rezzer.  When the rezzer receives that go-ahead prompt, it can send the important information in a quick llRegionSayTo message.  That simple handshake protocol guarantees that the information is not passed prematurely.  You can of course send the comm channel's value as the integer that's passed on_rez, so you put both a llListen statement and your "OK, I'm ready!" message in the on_rez event. 

Couple tricks:

  • A rezzed object's scripts are not reset.
  • You can call llListen in state_entry to initialize a listen, then take the object into your inventory and put it into a rezzer.
  • When the rezzer creates a copy of that object, it will get an objec_rez event when the object is guaranteed to exist (since the event includes its UUID).
  • The rezzer can then send a message to the object.
  • Because of the way chat messages work, the object is guaranteed to receive all chat messages in its range (including llRegionSay/To) even if its scripts weren't initialized the moment the original message was sent.

This allows you to reduce the time between rezzing the object and sending data to it. I've been using it without fail with guns that fire multiple (nonphysical) "projectiles" at once, even in sims under heavy lag.

Edited by Wulfie Reanimator
Link to comment
Share on other sites

1 hour ago, Rolig Loon said:

If you intend to pass information from a rezzer to a rezzed object (say, for example, the UUID of whoever touched the rezzer), the smartest way to do that is to have the rezzed object send a "OK, I'm ready!" message back to the rezzer.  When the rezzer receives that go-ahead prompt, it can send the important information in a quick llRegionSayTo message.  That simple handshake protocol guarantees that the information is not passed prematurely.  You can of course send the comm channel's value as the integer that's passed on_rez, so you put both a llListen statement and your "OK, I'm ready!" message in the on_rez event. 

Here is another method which I use sometimes:

You can write into the rezzer's description, the message intented for the rezzed object.

When the rezzed object wakes up, you can use llGetObjectDetails() and OBJECT_REZZER_KEY to know which object rezzed it, and then OBJECT_DESC to read that string.

For me the main advantage is that there is no message that can get lost, delayed, requires parsing, or sanity checking, you set the description upon rezzing the object, and it will be there, read for reading as soon as on_rez() fires.

Link to comment
Share on other sites

OK, Thanks Kyrah and Wulfie! Good tricks.

I am reasonably satisfied with my ability to have the swing frame rez the swing in the proper position.

Now, what do I need to do when the owner 'Edits' either the frame (or swing, but let me figure out the simpler case first) and moves and rotates it where he/she wants it? How do I

  1. know when the frame is being moved and/or rotated
    1. I looked at the 'changed' event and didn't see that it would tell me.
  2. should I have the frame continuously reposition/re-rotate the swing as the owner is changing the position/rotation of the frame
    1. I have the feeling that would make moving the frame slow and probably result in some missed messages
  3. If not 2 then maybe
    1. delete the swing when the edit UI opens
    2. have the owner move/rotate the frame w/o swing
    3. once edit UI is closed re-rez the swing?

Thanks,

G

Link to comment
Share on other sites

Since the frame will stay put, non-rotating, once it's where the owner wants it, have your script save its position in a safe place, like the frame's Description field. Then, either have a timer compare that saved position to the frame's actual position periodically or simply make that comparison whenever you touch it.  If the frame has moved, trigger your re-alignment routine again.

You could do the same trick the other way too, but you'd have to be careful because the swing rotates. So, find some condition when the swing is going to be at a specific orientation (with Z vertical, for example) and use that as the orientation at which you save the reference position.  Then script the swing to recreate that orientation (maybe when you stand up?) and then automatically compare its position to the stored position and make any necessary correction.

With a little imagination, you can think of many variations on that theme, using stored positions or relative positions as points for comparison.

Edited by Rolig Loon
typos, of course
Link to comment
Share on other sites

8 hours ago, GManB said:

Is there no event that can execute with an object goes into and out of Edit mode (from the Pie Menu)?

No, but I've thought about filing a feature request for a CHANGED_SELECTED return for the changed() event as well as a llGetSelectingAgents() function to allow scripts in physical, KFM, Animesh or other relevant applications to change operational behavior, particularly if selection would stop velocity, translation, rotation and/or animation.

Link to comment
Share on other sites

6 hours ago, Lucia Nightfire said:

No, but I've thought about filing a feature request for a CHANGED_SELECTED return for the changed() event as well as a llGetSelectingAgents() function to allow scripts in physical, KFM, Animesh or other relevant applications to change operational behavior, particularly if selection would stop velocity, translation, rotation and/or animation.

I'd suggest both CHANGED_SELECTED_START and CHANGED_SELECTED_END. With these we could start a high frequency polling loop to check for whatever condition and make appropriate adjustments. In my case I could write a haveIMovedorRotated() function which polled pos and rot at subsecond intervals and make the appropriate alignment between swing and frame as the frame or swing moved/rotated.

 

There must be a better way. I simply cannot bring myself to write a polling loop, with a reasonable frequency, that executes continuously and that may not be needed in even the life of an object. Such a waste of compute resources.

Puts on thinking cap.....

 

Thanks,

G

Link to comment
Share on other sites

42 minutes ago, GManB said:

I simply cannot bring myself to write a polling loop, with a reasonable frequency, that executes continuously and that may not be needed in even the life of an object. Such a waste of compute resources.

I agree.  A polling loop is a last resort.  That's why I suggested hiding the trigger for your "Did something move?" test in another action, like standing up from the swing. Have the script set the swing's rotation so that +Z points straight up every time a user stands, and then automatically check the position of the swing and the frame to be sure that they are where you left them the last time.

Link to comment
Share on other sites

1 hour ago, Rolig Loon said:

I agree.  A polling loop is a last resort.  That's why I suggested hiding the trigger for your "Did something move?" test in another action, like standing up from the swing. Have the script set the swing's rotation so that +Z points straight up every time a user stands, and then automatically check the position of the swing and the frame to be sure that they are where you left them the last time.

But, excuse my ignorance, what action correlates to an object being moved by the build tool? I don't see any. Certainly, an agent could rez the swing and move it into position without any av ever sitting on it.

(IMHO) A compromise solution is to make the alignment of the swing and frame, post initial rez, completely user controlled. Provide an 'Align' option in the dialog for both the frame and swing. User can then move either the frame or the swing independently and then bring up the dialog from either and select 'Align' to get them properly positioned. In this way there is the least possible likelihood of unexpected, from the pov of the user, behavior. Clunky, yes, but avoids the situation where user moves either frame or swing and scripts fail to notice and no way to align other than via build tool.

Thanks,
G

Link to comment
Share on other sites

1 minute ago, GManB said:

But, excuse my ignorance, what action correlates to an object being moved by the build tool? I don't see any. Certainly, an agent could rez the swing and move it into position without any av ever sitting on it.

That's quite true.  And, no, there's no way to tell why the swing or its frame moved. That really doesn't matter, though.  What's important is that it did move and you need to be sure that both parts moved to the new location. That's why I was suggesting that you always store the current location of the frame in its Description field.  Make that the final step in the setup script.  Do the same thing in the swinging part.

Then, you build the "What if it moved?" routine into the swing script, activated every time that the swing is used.  The swing always checks its own ending position with each use and queries the frame to see if its position matches its stored value.  Most of the time, when it compares positions to the stored values, it will find that nothing has moved so no correction is necessary.  On those rare occasions when you moved things for whatever reason, though, the position values won't match.  At that point, have your script execute the setup routine again, realign the parts, and overwrite the position vector in the Description field, ready for the next time.

So, what if the owner moves something on purpose?  You tell her she can do either of two things:

1. Click the setup tool (wherever you put it), or

2. Sit on the swing and stand up again.

Anyway, I'm not wedded to this idea, simply explaining it.  I'm sure there are plenty of other clever tricks to do the same thing

Link to comment
Share on other sites

Ah, I have seen similar in objects I own. There is an automatic section that mostly works and a manual section that always works. As you say then, instruct the user to do the manual operation if things go wrong.

Looked through all the events today. It's a shame that the behavior of moving_start and moving_end were defined for moves by the build tool... sighs...

G

Link to comment
Share on other sites

I agree.  It would be handy if moving_start and moving_end worked, but sadly they are meant for physics-enabled objects only and do not respond to things that are moved by the editor.  Except for that, they would be my clear choice too. So, we get creative.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1577 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...