Jump to content

Using String-to-List functions - Issues


joshyv3
 Share

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

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

Recommended Posts

I have a variable, initialized as such:

list motionBase = [<1,0,0>,ZERO_ROTATION,5,<1,0,0>,ZERO_ROTATION,5];

This is used in a llSetKeyframedMotion function.

This works as expected, and when viewing output for this value I get:

touch_start( integer num_detected ) {
	llOwnerSay(llDumpList2String(motionBase, ","));
}
//output: [13:41] mtrain_object: <1.000000, 0.000000, 0.000000>,<0.000000, 0.000000, 0.000000, 1.000000>,5,<1.000000, 0.000000, 0.000000>,<0.000000, 0.000000, 0.000000, 1.000000>,5
  
//or this way..
touch_start( integer num_detected ) { 
  llOwnerSay((string)motionBase);
}
//ouput: [13:59] mtrain_object: <1.000000, 0.000000, 0.000000><0.000000, 0.000000, 0.000000, 1.000000>5<1.000000, 0.000000, 0.000000><0.000000, 0.000000, 0.000000, 1.000000>5

But when sending in a string (from another object) that is formatted exactly as needed, and converting to a list, it just doesn't work.  (By sending in, I mean using a listen to get the value needed from another object).

Methods tried:

motionBase = llParseString2List(stringValue, ["*"], []);
motionBase = llCSV2List(stringValue);

// The output after sending the string value through these:
// [15:16] mtrain_object: [<1,0,0>,ZERO_ROTATION,5,<1,0,0>,ZERO_ROTATION,5]
// This is exactly the value of that list variable, after being updated. Matching the value when it was initialized.
// But, the output should look like the example from the initialized value:
// I.E. <1.000000, 0.000000, 0.000000>,<0.000000, 0.000000, 0.000000, 1.000000>,5,<1.000000, 0.000000, 0.000000>,<0.000000, 0.000000, 0.000000, 1.000000>,5

So, the value "sent in" with the llSetKeyframedMotion function, results in an error - "expected translation vector in keyframe list."

The string looks fine, and the list variable "value" is set exactly as the value when it is initialized.  That is what is messing with me... 

I've also tried this removing any spaces, with or without braces, nothing seems to make a difference.

Edited by joshyv3
Link to comment
Share on other sites

Type casting.

I've recently had to solve this problem, this might not be the best solution, but it seems to work for my needs.

//--------------------------------------------------------------------------//
// list FixListTypes(list raw)
// Accepts a list and returns the same list with stronger typing .. 
// because some LSL functions are fussy eaters
list FixListTypes(list raw) {
    list fixed;
    integer raw_size = llGetListLength(raw);
    integer i;
    string raw_string;
    for (i=0; i<raw_size; i++) {
        raw_string = llList2String(raw,i);
        // determine type
        if (llList2Key(raw,i)) {
            // keys
            //llOwnerSay("'"+raw_string+"' is key");
            fixed += llList2Key(raw,i);
        } else if (~llSubStringIndex(raw_string,"<") && ~llSubStringIndex(raw_string,">")) {
            // vector or rot
            //llOwnerSay("'"+raw_string+"' is vector or rot");
            integer start = llSubStringIndex(raw_string,"<");
            integer end = llSubStringIndex(raw_string,">");
            list parts = llParseString2List(llGetSubString(raw_string,start+1,end-1),[","," "],[]);
            integer parts_count = llGetListLength(parts);
            if (~parts_count && parts_count == 3) {
                fixed += (vector)llGetSubString(raw_string,start,end);
                //llOwnerSay("vector! "+(string)llList2Vector(fixed,-1));
            } else if (~parts_count && parts_count == 4) {
                fixed += (rotation)llGetSubString(raw_string,start,end);
                //llOwnerSay("rot! "+(string)llList2Rot(fixed,-1));
            } else {
                //well *****
                //llOwnerSay("'"+raw_string+"' is actually just a string");
                fixed += raw_string;
            }
        } else if ((string)llList2Integer(raw,i) == raw_string) {
            // integer
            //llOwnerSay("'"+raw_string+"' is integer");
            fixed += llList2Integer(raw,i);
        } else if ((~llSubStringIndex(raw_string,".")) && ((float)(raw_string + "1") != 0.0)) {
            // float
            //llOwnerSay("'"+raw_string+"' is float");
            fixed += llList2Float(raw,i);
        } else {
            //string .. or who cares, its now a string
            //llOwnerSay("'"+raw_string+"' is string");
            fixed += raw_string;
        }
    }
    return fixed;
}

 

Edited by Coffee Pancake
syntax highlighting .. oh why on why isn't there a LSL specific option for .. um .. raisins
  • Like 3
  • Thanks 2
Link to comment
Share on other sites

LSL does not properly handle vectors, rotations and keys when they're pulled from lists that were parsed from strings. You need to first type cast them into the appropriate variable.

 

default
{
    state_entry()
    {
        list foo = [1, "1", <1.0, 2.0, 3.0>, "<1.0, 2.0, 3.0>"];
        
        string bar = llDumpList2String(foo, "/");
        
        list baz = llParseStringKeepNulls(bar, ["/"], []);
        
        //Integers and floats will be properly parsed, even if they were strings.
        //Vectors, rotations and keys will not.
        llOwnerSay(llList2CSV(baz) + " || " + (string)llList2Integer(baz, 0) + " || " + (string)llList2Integer(baz, 1) + " || " + (string)llList2Vector(baz, 2) + " || " + (string)llList2Vector(baz, 3));
        
        vector stringified_vector = (vector)llList2String(baz, 2);//In the original list, this was a vector type
        vector stringified_vector_2 = (vector)llList2String(baz, 3);//This one was just a string.
        
        llOwnerSay((string)stringified_vector + " || " + (string)stringified_vector_2);//But to LSL, they're now both just strings and can be typecasted exactly the same.
    }
}

 

So in summary. In order to use a vector, rotation or key from a parsed list. Pull it out using llList2String, then typecast it into what you need.

Edited by Ariu Arai
  • Thanks 1
Link to comment
Share on other sites

If the string being received isn't always going to adhere to a pre-defined format, you can add preceding integers for each sub-component to specify what it should be cast to:

string listInMsg = "integerValFloat, 1.00024, integerValVector, <1.0,24.5,2.4>, integerValRot,<0.74,0.0,0.0,0.74>, integerValString, 'I am the name of your successor and you have been fired'"

integerValFloat, etc is obtained by using llGetLitentryType(index) when first extracting parts of the list to a string.

to break the string up into the required substrings, locate the end of the substring for the required type by searching for , if its an integer or a float, >, for vector and rotations, strings get messy which is why I always encase them in quotes when doing serialisation.

Edited by Profaitchikenz Haiku
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

19 minutes ago, Mollymews said:

i put a formal serialisation method here:

Other than the fact that it uses literal constants, 1,2,4,5,6 rather than the builtin constants TYPE_INTEGER, TYPE_FLOAT etc. I quite like it!

(My personal preference is to avoid 'pulling a number out of thin air' wherever possible)

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

2 hours ago, Quistess Alpha said:

My personal preference is to avoid 'pulling a number out of thin air' wherever possible)

I fully agree (now), and after a few days of hair-tearing and tracking down the problem I no longer write

val = llList2Vector(points, index+3))

but instead declare the offsets into a strided list as

integer FROMOFFSET = 2;

integer TOOFFSET = 3;

and so on, so I then write

val = llList2Vector(points, index+FROMOFFSET);

It took me several days to track down a mind-bogglingly stupid mistake where I had used an incorrect offset value and because it was just a number and not a named literal, I was blind to it.

If you want to use magic numbers, I always go for things like e to the j pi, it adds a sort of mystique to what the code looks like.

Edited by Profaitchikenz Haiku
  • Thanks 1
Link to comment
Share on other sites

4 hours ago, Quistess Alpha said:

Other than the fact that it uses literal constants, 1,2,4,5,6 rather than the builtin constants TYPE_INTEGER, TYPE_FLOAT etc. I quite like it!

(My personal preference is to avoid 'pulling a number out of thin air' wherever possible)

good point. I edited it to use the type constants rather than magic numbers

  • Thanks 2
Link to comment
Share on other sites

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