Jump to content

mySky Phenomena

Resident
  • Posts

    16
  • Joined

  • Last visited

Posts posted by mySky Phenomena

  1. Hello All,

    I have a linked prim that I am trying to rotate about an axis that is not through its origin. I wanted this to happen as smoothly as possible, but I want to make sure that the way I am attempting to accomplish this is actually not possible versus me just doing something wrong.

    I tried llSetKeyframedMotion, but then realized you can only use this on the root prim. I was then experimenting with llTargetOmega, but couldn't figure out how to move the axis such that it doesn't originate at the origin. 

    My wife (the creator of this linked object) has also tried moving the origin to the required point in Blender, but after a ton of digging we've discovered that due to many reasons, this is not possible (without a complicated process to "trick" the SL uploader) when the object is uploaded into SL.

    Here's my question: Is it true that my only course of action here is to use a timer event and move the rotation position in increments with the method discussed in the "Rotation" page of the wiki on how to move the rotation axis ("Rotating Vectors")? Is there another method I'm not thinking of? Or am I using the previously mentioned functions incorrectly/not understanding how they work?

    Thanks!

  2. Hello All,

    I have a little bit of experience scripting using LSL, but I think I'm not understanding either how the timer event works or how to properly remove listeners. When trying to learn how to build a dialog menu, I read many resources that said removing open listeners is very important. In all of my scripts up until now, I've been using a timer event in case the user doesn't click on the menu, like this:

    open_menu(variables)
    {
    	//Do stuff with variables to open a dialog menu
    	llSetTimerEvent(30.0);
    }
    
    close_menu()
    {
    	//remove listeners
    	llSetTimerEvent(0.0);
    }
    
    default
    {
    	//Code
    
    	timer()
    	{
      		close_menu();
    	}
    }

    However, now I need to use the timer event for something else. I've seen other posters on here using a counter in the timer event when they need multiple timer events (I know you can't literally have multiple timer events), like this:

    default
    {
        //Code
    
        timer()
        {
            ++counter;
            if(counter == max)
            {
                //Do something else
            }
            //Do something
        }
    }

    I don't think I understand how this works. For example, let's say my "main use" for the timer event is to blink a light every 5 seconds, but there's a menu as well that asks the user if they want the light to blink or not. Do I set this counter to zero when the menu is opened and then set whatever "max" value?

    I know the blue menu won't go away if counter reaches "max," but I want to make sure there aren't any open listeners if the user doesn't click anything.

    Let me know if I'm not making sense, or if there's another post I missed. Thanks!

  3. 23 minutes ago, Wulfie Reanimator said:

    It would also eliminate any need for massive if-trees.

    Since, if everything is in one list, and you already know which B and which C have been selected, you can immediately calculate the correct position in the main list without any if-checks, and get the right amount of data out.

    Just to make sure I understand: If I did it this way, all I would need in the listen is:

    if(message == C1)
    {
    	//Use stored B# to search for the position B#C1 in the "master" data list
    }
    else if()...

    instead of the nested if-checks I had in my original code snippet?

  4. 11 minutes ago, Nova Convair said:

    How do the menus look. Is that B1-B10 and C1-C15 on the buttons or are there 150 different texts?

    What you do with the result. Do you need 150 different script-actions or are things calculated out of the answers or are you just passing numbers?

     

    Each B and C have a separate button. For example, if you chose button B2, you'd get another menu with buttons C1, C2, C3,..., C14, C15 (of course this would be broken up into two separate menus). With the result, I grab the list associated with the B button (which contains all the values for each C associated with that B button) and then find the C value in that list. For example, if someone chose B3 then C9, I would go into the B3 list and grab the value inside the C9 index (so index 8). The C9 value is a UUID for a texture that I'm applying to an object. 

    Let me know if I'm not explaining myself well.

  5. 12 minutes ago, Wulfie Reanimator said:

    You could always just combine all of the lists into one and do the old XY index search (you have to treat the single list as if it was a two-dimensional array), assuming each C-level menu has the same amount of data. Like:

    
    // menu_length = the number of total indexes that belong to each C in B
    // data_length = the number of indexes that belong to C
    
    // bYcX = a stride of all relevant data for that specific C-level menu.
    list data = [b1c1, b1c2, b1c3... b2c1, b2c2, b3c3...];
    
    list final_data = llList2List(data, (Y * menu_length) + (X * data_length), data_length);

     

    Thank you, that will definitely cut down on the number of separate lists I have!

  6. 41 minutes ago, Qie Niangao said:

    Just to confirm again: it's not that there are fifteen different Cs that appear ten times, once for each B, but rather 150 different Cs, divided up among ten Bs, right?

    In any case, what does the script do when it gets a choice of B & C? What I'm trying to ask is whether there needs to be a monstrous huge if/else tree for the menu responses or if the script can simply do some computed thing based on finding the response in a list. Like, for example, there could be a long list of pairs that associate response "B1C1" with a texture to paint somewhere. The nightmare alternative is that there are 150 altogether different things the script needs to do -- like call a whole different function for each, or the like (because LSL has no concept of computed control flow like function pointers).

    Yes, it's 150 different Cs. Right now, I have all of the C options stored in 10 separate lists (one for each B) because, like Wulfie Reanimator said, I discovered there are no lists within lists allowed. I then store which B# they chose in a variable (call it "numB"). Inside listen I say:

    if(message == C1)
    {
    	if(numB == B1)
    	{
    		//get necessary info from B1 list associated with option C1
    	}
    	else if(numB == B2)
    	.
    	.
    	.
    }
    else if(message == C2)...

    So, as you can see it's getting a little ridiculous, because inside listen there are 15 C if/else if statements, each with 10 B if/else if statements inside. 

    I'm thinking there's an easier way to do this, because I figured someone somewhere must be writing large menus like this.

    • Haha 1
  7. Yes, there are fifteen distinct C options. Originally, I was going to build each menu and store it in a list beforehand. Then, I realized I should just build them only when they're needed because there are sooooo many of them. The control flow for the listen and the dataserver (or whatever the server event is called) events are really really really long. I'm hoping there's some smart way of cutting down on it that I'm not thinking of because I'm a novice, but all of the dialog menu example scripts I'm looking at are short (in terms of the amount of options for each menu) because (obviously) they are just examples.

  8. Hello,

    I am fairly new to lsl scripting, but have some programming experience. I am currently working on a project that includes some dialog menus, which are more complicated than any I have previously worked on. Functionally, the code is working (as far as I can tell), but I'm wondering if there is any way to streamline or simplify what I've written.

    The attached diagram is supposed to show how the menus are organized, sorry if it's confusing. Basically, the part that gets really really long is the control flows associated with levels B and C. For each choice in level B (B1 - B10) there are 15 options (C1 - C15). 

    My question is: Does anyone have an example script of a multilevel menu with a lot of options associated with each level?

    I'm trying to see if anyone has a better way of handling the control flow. I can attach some examples of my code if that would be helpful, and I am also looking at the lsl libraries online.

    Thanks!

    *In Level A of the diagram, that's supposed to be A11 (A eleven), not the word "All".

    menu_diagram.jpg

  9. What if I need to combine those two methods? Would this work?:

    integer iLine;
    key MyQuery;
    key queryA;
    key queryB;
    list lAllData;
    integer A;
    integer B;
    integer someNumber; //Whatever line on which the stuff I need ends
    
    default
    {
        
        state_entry()
        {
            // Check the notecard exists, and has been saved
            if (llGetInventoryKey(notecardName) == NULL_KEY)
            {
                llOwnerSay( "Notecard '" + notecardName + "' missing or unwritten");
            }
            else
            {
                queryA = llGetNotecardLine("My Notecard", 2);
            }
        }
    
        dataserver(key query_id, string data)
        {
            if(query_id == queryA)
            {
            	A = (integer)data;
                queryB = llGetNotecardLine("My Notecard", 4);
            }
            else if(query_id == queryB)
            {
            	B = (integer)data;
                MyQuery = llGetNotecardLine("My Notecard", iLine = 0);
            }
            else if (query_id == MyQuery)  
            {
                if (data != EOF)
                {
                    lAllData += [(integer)data];
                    if (iLine < someNumber)  
                    {
                        MyQuery = llGetNotecardLine("My Notecard", ++iLine);
                    }
                }              
            }	
        }
    }

     

  10. Ohhhhhh ok, that makes sense.

    I actually have a bunch of info I need to grab from that notecard. Is there a more elegant way of doing that, or is the only way to setup the event the way you've done with queryA and queryB? Like if I had to fill A - F, would I need to just keep doing what you've done above, just for each variable?

  11. Hello,

    I have searched for an answer to this question, but either don't understand the answer or am not finding what I'm looking for. I think the problem lies in my understanding of the way dataserver events (or events in general) work. Please let me know if my explanation is confusing.

    (1) Is this how the dataserver event works?:

    When I request a notecard line using llGetNotecardLine("My Notecard", 2), the dataserver event is triggered. Inside the dataserver block I can access whatever string is returned from line 2 in "My Notecard" and manipulate it (or whatever I'm trying to do).

    (2) I have a script that needs to read some values in from specific lines in a notecard. For example, let's say I need to store the integers on lines 2 and 4 from "My Notecard" into two different variables called A and B. Is this true?:

    Every time I call llGetNotecardLine(), the script is going to go into the same dataserver event, so inside the dataserver event block I have to have some way of figuring out which line I asked for to store it in the correct variable? Like this:

    integer A;
    integer B;
    key queryA;
    key queryB;
    
    default
    {
        
        state_entry()
        {
            // Check the notecard exists, and has been saved
            if (llGetInventoryKey(notecardName) == NULL_KEY)
            {
                llOwnerSay( "Notecard '" + notecardName + "' missing or unwritten");
                return;
            }
            queryA = llGetNotecardLine("My Notecard", 2);
    	queryB = llGetNotecardLine("My Notecard", 4);
        }
    
        dataserver(key query_id, string data)
        {
            if (query_id == queryA)
            {
                if (data == EOF)
                    llSay(0,"Done reading notecard, read " + (string) notecardLine + " notecard lines.");
                else
                {
                    A = (integer)data;
                }
            }
    	if (query_id == queryB)
            {
                if (data == EOF)
                    llSay(0,"Done reading notecard, read " + (string) notecardLine + " notecard lines.");
                else
                {
                    B = (integer)data;
                }
            }
        }
    }

    Just FYI, I stole some of this code from an example I saw and added the parts I needed.

     

    Thanks!

     

×
×
  • Create New...