Jump to content

Rotate a child prim of a HUD


Guest
 Share

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

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

Recommended Posts

I am still very new to the concept of rotations in SL and LSL

A few months ago I created a HUD for point-and-click adventure games in SL.I have also added a child mesh prim with one visible face.

This is the principle how I build it: The child mesh prim for the storry telling textures is visible until I reset the script, then this prim with the texture is rotated by 90 degrees to an invisible face.The player takes the HUD from a vendor. When the player attaches the HUD it is still rotated to a side which is invisible. At a certain link-message command, the mesh prim rotates 90 degrees to its visible face and a texture can show a texture which tells part of the story. Here is a picture when the face with the texture is visible for the player:

Snapshot_001.png

It wall works great, but here comes my problem: I need to reset the scripts quite often while I develop a game. If I do not rez the prim on the ground and  edit the child prim so that the visible face is pointing towards the front, the function breaks when I reset the script. I have improvised with a channel listening for a comand ("turn-front") so that I do not have to rez the HUD all the time. But it is still tiring after the 100th reset. It would be so great if I could change this script, so that it works, even if the visible face is turned by 90 degrees to the side at the beginning. What do I need to change in my script?

 

integer timerState;
integer channel01;

//Variables for Rotation of Story screen/////////
integer forwardSwing = 90;

rotation showRot;
rotation hideRot;


default
{
    state_entry()
    {
    channel01 = llListen(5, "", llGetOwner(), ""); 

    showRot = llGetLocalRot();
    hideRot = llEuler2Rot( <0.0, 0.0, forwardSwing> * DEG_TO_RAD );
        
    llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,hideRot]);
  
    }

    
    link_message(integer source, integer num, string str, key id)     
    
    {
        if (str =="STORY_1")
            {   
    llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,showRot]);
    timerState = 1;
    llSetTimerEvent(10.0);
             }

    }
timer()
    {
    if (timerState == 1)
            {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,hideRot]);
        llSetTimerEvent(0.0); //switch off timer               
            }
    }

listen(integer channel, string name, key id, string message)
    {

    if (message == "turn-front")
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,showRot]);
    else if (message == "turn-side")
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,hideRot]);
    
    }

}


 

Link to comment
Share on other sites

Have you tried using an attach event to trigger rotation to the default orientation?

attach (key id){    if (id)    {        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,showRot]);    }}

 All you have to do then is detach and reattach the HUD after you've done your editing.

 

Link to comment
Share on other sites

i use this for my HUD and it seems to work ok?

rotate 90 forward......

 llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROTATION,llGetLocalRot() * llEuler2Rot(<0,0,90>*DEG_TO_RAD)]);

 

rotate negative 90 back to position ......

 llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROTATION,llGetLocalRot() * llEuler2Rot(<0,0,-90>*DEG_TO_RAD)]);

Link to comment
Share on other sites

I would do something like:

show:

llSetLinkPrimitiveParams(child_link_num, [PRIM_ROT_LOCAL, llEuler2Rot(<.0, .0, .0> * DEG_TO_RAD)]);

 hide:

llSetLinkPrimitiveParams(child_link_num, [PRIM_ROT_LOCAL, llEuler2Rot(<.0, .0, 90.0> * DEG_TO_RAD)]);

 

This way there's no need to get the local rotation in state_entry Which also means that it doesn't matter wich way the child is rotated when you reset the script.

Link to comment
Share on other sites

The first question to ask when having difficulty rotating HUDs properly is, "What is the orientation of the HUD's root prim"?

To work successfully, and to avoid tears of rage and frustration on your part, the root prim of the HUD has to be rotated to ZERO_ROTATION.   That means, in practice, that the face that's visible by default to the user is face 4, the lesser x axis,  It's the face that has the red arrow running into it when first you rez the prim, or when you examine the prim in Local Ruler mode.

Check that, please.  Unless that's right, the HUD won't work properly when you start rotating things.

Link to comment
Share on other sites

Thanks to everyone for all your answers so far. I don't have the time to check the proposed solutions tonight, I will do that at the latest in the week-end.

@ Innula: The HUD itself is zero rotation at the start. Also the child prim is zero rotation.

BUT: Since the visible face of the child prim is rotated by 90 degrees counterclock-wise at the 1st state_entry event and it will most probably be out of sight, it is not anymore at the zero rotation when the scripts for the whole HUD are reset.

Your remark might explain why the child prim is NOT rotated by another 90 degrees counterclock-wise after the 2nd state_entry event. I was wondering about that.

And your remark might also explain why I was NOT getting the following to work: Start with the child prim 90 degrees rotated counter-clock wise. At state_entry make it rotate to zero rotaion thus show the visible face.

 

Link to comment
Share on other sites

is a wider design question to this as well which can be considered

how to preserve current state when a script is restarted?

+

one way is to periodically save the state (a mapping) to linkset object description fields. On restart (state_entry) read from map and restore the last saved state

to reduce the description field space requirement when is lots of state info, then can use a translation table in the script. A codemap

can be quite useful this in game design. for debugging purposes like you wanting

also for users who have reached a state (a game level say) and might need to reset the script on bork, and after doing this can still carry on in the game where they were last at

same also if they detach. Save state so they can carry on when next attach

+

other thing to consider when doing this is having the ability to reset hot or cold

hot meaning restore current state. cold meaning complete reset to default state

can use either a chat command, or a dialog to set the signal (saved to the map) which is acted on in state_entry when the script restarts

Link to comment
Share on other sites

The visible face cannot be in sight after state_entry or attach because it blocks the whole view (see picture). But I think I got the solution now, thanks to your remarks. I need to create a new mesh prim which has another unique face visible. Then face 4 will be invisible and can show to the front after the state_entry entry event.

Link to comment
Share on other sites

I am using global variables instead of states for players to progress in the game. But the problem remains the same of course: after the reset of the script everything is reset to zero.

I can only think of how backing-up to a database or writing/reading of a notecard works. How does mapping to the object description fields work? That sounds like a very interesting technique. Which LSL commands do I use for that?

Link to comment
Share on other sites

read/write to the object description field with llSetObjectDesc and llGetObjectDesc


simple codemap example:

 

//  code = "000"//  1st position: reset signal: 0 = cold reset. 1 = hot reset//  2nd position: orientation:  indice of orient_map: range 0..3//  3rd position: color:        indice of color_map:  range 0..2integer RESET_HOT = 1;   // name as constant for clarity // first element of list maps is the default statelist orient_map = [<0,0,0>,<0,0,90>,<0,0,180>,<0,0,270>];list color_map  = [<1,0,0>, <0,1,0>, <0,0,1>];integer orient_idx;integer color_idx;codemapLoad(){  string code = llGetObjectDesc();  integer reset_signal = (integer)llGetSubString(code, 0, 0);  if (reset_signal == RESET_HOT)  {      orient_idx = (integer)llGetSubString(code, 1, 1);      color_idx = (integer)llGetSubString(code, 2, 2);  }  // when a indice > 9 then adjust getsubstring to accomodate  // when code = "" then each will be 0: the default}codemapSave(integer reset_signal){  string code =     (string)reset_signal +    (string)orient_idx +    (string)color_idx;  llSetObjectDesc(code);}default{   state_entry()    {      codemapLoad();      llSetRot(llEuler2Rot(DEG_TO_RAD * llList2Vector(orient_map, orient_idx)));      llSetColor(llList2Vector(color_map, color_idx), 4);   }    touch_start(integer num_detected)   {      if ((++orient_idx) == llGetListLength(orient_map))         orient_idx = 0;      if ((++color_idx) == llGetListLength(color_map))         color_idx = 0;      codemapSave(RESET_HOT);      llResetScript();   }}

 

+

once get a feel for how codemaps work then can look into extending it further. Down the path you already thinking of. Where have a codemap database script (subsystem) seperate from your main game loop script. Communicating using link messages

the subsytem doing the writing/reading locally to multiple description fields in the linkset if/when the extra storage space is needed. Game loop code treating the subsystem as it would any database

database containing game values (levels, points, etc) as well as object properties

as your game evolves then can go further. Extending the database subsytem to also read/write some data to a external website. Maybe a leaderboard for your players, etc

+

i tend to load/save indices as much as possible rather than read/write actual values to codemaps. Is easier to change the values in the lists when adding new capabilities as your game evolves over versions

and you dont have to fiddle with formatting datatypes in the code string. Just have to add new indice fields to the end 

 

Link to comment
Share on other sites

I would suggest you also keep an eye on developments with the new experience tools, currently being tested in particular regions.    Among other things, they enable scripts to store values on LL's servers and to retrieve and update them in the dataserver event.   

Once experience tools are widely available, I think that's going to make a big difference to how some HUDs are made.

  • Like 1
Link to comment
Share on other sites

other options besides the desc. field are....

 Using SLPPF and storing the info in a string and storing the string in a prim's "texture" field.

i.e.

llSetPrimitiveParams([
    PRIM_TEXTURE, 3, "this is a storage area", <1.0, 1.0, 0.0>, ZERO_VECTOR, 0.0,
    PRIM_TEXTURE, 4, "this is also a storage area", <1.0, 1.0, 0.0>, ZERO_VECTOR, 0.0]);

 

 Using Void's Teacup code.

http://wiki.secondlife.com/wiki/Teacup

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3350 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...