Jump to content

Help needed with script using linkset data to save and set camera parameters


BB Seesaw
 Share

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

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

Recommended Posts

I have a cam HUD script with a custom camera option, and want to modify it to save custom camera parameters users set via the HUD. I was going save the data in the prim description but now that linkset data can save far more and survives script resets (useful for reset on region crossings) I'm trying to save there instead. However, although I can save and retrieve data using the function, it won't actually set the camera parameters. I know I must be making a mistake but can't see it.

Here's the test script I'm using. I'd really appreciate some help getting it to work. I'm using integers for the camera parameters to save bytes so that if I can't get linkset data to work I'll have to go back to using the prim description.


integer on;
string camName;


list testCam = [
    12,1,//camera active
    8,.01,//camera behindness angle
    9,.0,//camera behindness lag
    7, 2.0,//camera distance
    6,.01 ,//camera focus lag
    1,<.0,.0,.75> ,//camera focus offset
    11,.0,//camera focus threshold
    22,0,//camera focus locked
    0,10.0,//camera pitch
    5,.01,//camera position lag
    10,.0,//camera position threshold
    21, 0//camera position locked
    ];
    
take_camera_control(key agent)
{
    llOwnerSay("take_camera_control"); // say function name for debugging
    llRequestPermissions(agent, PERMISSION_CONTROL_CAMERA);
    llSetCameraParams([CAMERA_ACTIVE, 1]); // 1 is active, 0 is inactive
    on = TRUE;
}

default
{
    state_entry()
    {
        llLinksetDataReset( );
        take_camera_control(llGetOwner());
        //llSetCameraParams(testCam);

        camName="testDataWrite";
    }
    touch_start(integer total_number)
    {
        llLinksetDataWrite(camName,llDumpList2String(testCam,"#"));//save parameters as linkset data
        string temp = llLinksetDataRead(camName);//get cam settings from data store
        llOwnerSay("Settings read from linkset "+temp);
        list tempCamSettings = llParseString2List(temp,["#"],[""]);//convert to list
        llClearCameraParams();
        llSetCameraParams(tempCamSettings);
        llOwnerSay(llDumpList2String(tempCamSettings,","));
    }
    run_time_permissions(integer perm)
    {
        if ((perm & PERMISSION_CONTROL_CAMERA) == PERMISSION_CONTROL_CAMERA) {
            llSetCameraParams([CAMERA_ACTIVE, 1]); // 1 is active, 0 is inactive
            llOwnerSay("Camera permissions have been taken llSetCameraParams");
        }
    }
}

 

 

Link to comment
Share on other sites

No. You haven't.

What I meant was you have to do something like this:

        list tempCamSettings = llParseString2List(temp,["#"],[""]);//convert to list
        list testcam2 = [
            (integer)llList2String(tempCamSettings, 0), (integer)llList2String(tempCamSettings, 1),
            (integer)llList2String(tempCamSettings, 2), (float)llList2String(tempCamSettings, 3),
            (integer)llList2String(tempCamSettings, 4), (float)llList2String(tempCamSettings, 5),
            (integer)llList2String(tempCamSettings, 6), (float)llList2String(tempCamSettings, 7),
            (integer)llList2String(tempCamSettings, 8), (float)llList2String(tempCamSettings, 9),
            (integer)llList2String(tempCamSettings, 10), (vector)llList2String(tempCamSettings, 11),
            (integer)llList2String(tempCamSettings, 12), (float)llList2String(tempCamSettings, 13),
            (integer)llList2String(tempCamSettings, 14), (integer)llList2String(tempCamSettings, 15),
            (integer)llList2String(tempCamSettings, 16), (float)llList2String(tempCamSettings, 17),
            (integer)llList2String(tempCamSettings, 18), (float)llList2String(tempCamSettings, 19),
            (integer)llList2String(tempCamSettings, 20), (float)llList2String(tempCamSettings, 21),
            (integer)llList2String(tempCamSettings, 22), (integer)llList2String(tempCamSettings, 23)
        ];
        llClearCameraParams();
        llSetCameraParams(testcam2);

 

  • Like 1
Link to comment
Share on other sites

I don't see any benefit to using llDumpString2List() and llParseString2List() here, because you aren't working with anything but a "normal list". 

I suppose you can't just do the below since llCSV2List() only results in a list of Strings, so llSetCameraParams() would not work (it expects the integers and floats)..?

1) Write the original list settings to LSD after converting the list to CSV with llList2CSV(),

 llLinksetDataWrite(camName,llList2CSV(testCam)); //save parameters as linkset data

2) Then read back the settings from LSD as a string in CSV format,

string temp = llLinksetDataRead(camName);//get cam settings from data store

3) and convert what you read back to a List with llCSV2List(),

list tempCamSettings = llCSV2List(temp);

4) then pass the list to llSetCameraParams()?

 llSetCameraParams(tempCamSettings);

HOWEVER, you could use llList2Json() and llJson2List(), which SHOULD preserve the types so far as I know.

 1) Write the original list settings to LSD after converting the list to Json with llList2Json() - use JSON_ARRAY as the first parameter 

 llLinksetDataWrite(camName,llList2Json(JSON_ARRAY, testCam)); //save parameters as linkset data

2) Then read back the settings from LSD as a string in Json format,

string temp = llLinksetDataRead(camName);//get cam settings from data store

3) and convert what you read back to a List with llJson2List(),

list tempCamSettings = llCSV2List(temp);

4) then pass the list to llSetCameraParams()?

 llSetCameraParams(tempCamSettings);

 

Link to comment
Share on other sites

35 minutes ago, Love Zhaoying said:

HOWEVER, you could use llList2Json() and llJson2List(), which SHOULD preserve the types so far as I know.

Json doesn't support vectors or rotations AFAIK, and I think the conversion casts integers to floats.

  • Thanks 1
Link to comment
Share on other sites

1 hour ago, Quistess Alpha said:

Json doesn't support vectors or rotations AFAIK, and I think the conversion casts integers to floats.

Ugh, I remember having to interpret the type for each element when doing this with lists. Do not miss lists!

Edited by Love Zhaoying
Link to comment
Share on other sites

Instead of typecasting manually, it might be easier to use this function:

list CastList(list L) {
    integer i = llGetListLength(L);
    while(--i > -1) {
        string d = llStringTrim(llList2String(L, i), STRING_TRIM);
        if (llGetSubString(d, 0, 0) == "<") {
            if (llGetSubString(d, -1, -1) == ">") {
                list s = llParseString2List(d, [","], []);
                integer sl= llGetListLength(s);
                if (sl == 3) L = llListReplaceList(L, [(vector)d], i, i);
                else if(sl == 4) L = llListReplaceList(L, [(rotation)d], i, i);
            }
        }
        else {
            if (~llSubStringIndex(d, ".")) {
                if ((float)(d + "1") != 0.0) L = llListReplaceList(L, [(float)d], i, i);
            }
            else {
                if ((string)((integer)d) == d) L = llListReplaceList(L, [(integer)d], i, i);
                else {
                    if ((key)d) L = llListReplaceList(L, [(key)d], i, i);
                }
            }            
        }
    }
    return L;
}

Use it like:

list tempCamSettings = CastList(llParseString2List(temp,["#"],[""]));//convert to list

and then llSetCameraParams(tempCamSettings); should work as intended.

  • Thanks 1
Link to comment
Share on other sites

Another alternative: amend the list with the entry types before dumping it into string. Separator needs changing if your list contains strings with semicolons.

string list2typedstring(list l) {
    integer i = llGetListLength(l);
    while(~--i)
        l = llListInsertList(l, (list)llGetListEntryType(l, i), i);
    return llDumpList2String(l, ";");
}

list typedstring2list(string s) {
    list l = llParseString2List(s, [";"], []);
    integer i = llGetListLength(l)+1;
    integer t;
    while(~(i-=2)) {
        t = llList2Integer(l, i-1);
        if(t == TYPE_INTEGER) l = llListReplaceList(l, (list)llList2Integer(l, i), i-1, i);
        else if(t == TYPE_FLOAT) l = llListReplaceList(l, (list)llList2Float(l, i), i-1, i);
        else if(t == TYPE_STRING) l = llListReplaceList(l, (list)llList2String(l, i), i-1, i);
        else if(t == TYPE_VECTOR) l = llListReplaceList(l, (list)((vector)llList2String(l, i)), i-1, i);
        else if(t == TYPE_ROTATION) l = llListReplaceList(l, (list)((rotation)llList2String(l, i)), i-1, i);
        else if(t == TYPE_KEY) l = llListReplaceList(l, (list)llList2Key(l, i), i-1, i);
    }
    return l;
}

 

Edited by Frionil Fang
Link to comment
Share on other sites

@Ron KhondjiYour snippet solved the problem, thanks so much. I have no idea how I managed after years of scripting not to realise that when you convert strings to lists you have to explicitly typecast each element. I somehow got it fixed in my mind that lsl automatically recognised the type from the form.

@Frionil FangI haven't tried your solution yet as Ron's solution worked, but I'll try it later and respond.

 

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

11 hours ago, Ron Khondji said:

Instead of typecasting manually, it might be easier to use this function:

 

list CastList(list L) {
    integer i = llGetListLength(L);
    while(--i > -1) {
        string d = llStringTrim(llList2String(L, i), STRING_TRIM);
        if (llGetSubString(d, 0, 0) == "<") {
            if (llGetSubString(d, -1, -1) == ">") {
                list s = llParseString2List(d, [","], []);
                integer sl= llGetListLength(s);
                if (sl == 3) L = llListReplaceList(L, [(vector)d], i, i);
                else if(sl == 4) L = llListReplaceList(L, [(rotation)d], i, i);
            }
        }
        else {
            if (~llSubStringIndex(d, ".")) {
                if ((float)(d + "1") != 0.0) L = llListReplaceList(L, [(float)d], i, i);
            }
            else {
                if ((string)((integer)d) == d) L = llListReplaceList(L, [(integer)d], i, i);
                else {
                    if ((key)d) L = llListReplaceList(L, [(key)d], i, i);
                }
            }            
        }
    }
    return L;
}

Use it like:

list tempCamSettings = CastList(llParseString2List(temp,["#"],[""]));//convert to list

and then llSetCameraParams(tempCamSettings); should work as intended.

Nice function, looks pretty "clean"!

Link to comment
Share on other sites

Not sure what happened for you, but I tested it out on typical lists and it should be ok, and since you already have a working solution it doesn't matter much!

For completeness' sake though, this works for me:

        list testCam = [12,1, 8,.01, 9,.0, 7, 2.0, 6,.01, 1,<.0,.0,.75>,
            11,.0, 22,0, 0,10.0, 5,.01, 10,.0, 21, 0];
        llLinksetDataWrite("save", list2typedstring(testCam));
        // ...
        list loaded_params = typedstring2list(llLinksetDataRead("save"));
        llOwnerSay(llList2CSV(loaded_params));

 

Link to comment
Share on other sites

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