PDA

View Full Version : Updating Position in Layout



xchrisx
11-15-2011, 04:31 PM
I am in the process of creating a motion modifier lscript that bases the current object's position off of a control object in my scene. I would like it to dynamicly update as I move the control object in the viewport. The problem is it does not update in the viewport until I change frames. Anyone have any ideas on how to make it work without changing frames?

thanks
Chris

evenflcw
11-15-2011, 04:50 PM
http://www.mikegreen.name/Lscript/Source/Common_Commands.htm#effectedby

You need the very important but poorly documented effectedby() function. (It's only documented in some old release note, not in any of the lscript pdfs).

(It's equivalent to the useItems callback in the SDK.)

xchrisx
11-15-2011, 05:04 PM
Thanks evenflcw I am definitely taking a look at that. Just fyi I also found that using UpdateMotion(); seems to work as well.

xchrisx
11-15-2011, 05:33 PM
Just incase anyone reads this thread in the future. Although UpdateMotion works.. it is dog slow. Using the effectedby sped up performance like 100 fold.

evenflcw
11-15-2011, 06:13 PM
Np. I'm not accustomed to UpdateMotion(), but likely it is a selective Refresh() of some sort. Imho, neither should be regularly used inside an process/evaluate callback.

Only if one has exhausted all other options should one resort to these methods . And then, one should make absolute sure to have full control over how and when they are issued to prevent self running loops - with a Refresh() inside the process callback of a motion modifier, it will trigger a new evaluation, and thus the Refresh() will be called again and again and again, forcing LW to refresh ad infinitum, even when it doesn't need to. A sluggish feel and wonkyness is the result.

So if it was "dog slow", that's likely what happened(?). Under control, one extra Refresh()/UpdateMotion() for every regular evaluation pass (more should not be necessary and likely pointless) should really only make LW about twice as slow.

That's my take on it anyway.

xchrisx
11-15-2011, 06:41 PM
It was super slow because I cloned it 100 times to check performance if I have to use this a lot in one scene. :) But I completely agree with your assessment. It should not be used inside of anything with a loop or performance will take a huge hit.

xchrisx
11-22-2011, 02:05 PM
I just noticed for some reason effectedby stopped working if I had several of them in the same script instance, except for the very last effectedby call. However if I turn on FPSE (full parameter scene evaluation) it works interactively the way I had wanted. Just incase someone else runs across this thread in the future and isnt seeing their effectedby command work, try turning on the FPSE in the General Options in layout.

evenflcw
11-22-2011, 02:49 PM
Several of them?

In what callback function do you make them? You should only need to call effectedby() when your script state changes. Normally that's only in the create, load, options and possibly destroy callback, never in the evaluate/process callback. Calling effectedby() in the evaluate/process callback might not be good as LW is not always in a valid state for such changes when processing.

How do your effectedby() calls look? Naturally you can change the dependency, but if your script is dependent on multiple items you should provide an array of item names rather than make multiple calls, providing one name at a time - which is what I suspect you are doing(!?).

FSPE shouldn't be necessary for anything! Imho it's mostly there to fix feature/scripts/plugins that weren't written correctly to begin with (and possibly things LW isn't even built to handle). It can also break features that are written correctly and very meticulously (to squeeze more performance/interactivity out of LW than normally available). Ask yourself, do you know any plugin that is as complex or more complex than your script, and did they need FSPE? PLG IK/Curve Bone handle multiple item dependencies interactively. They do not need FSPE.

EDIT: I'm always happy to look at and comment (short) code if you dare post it. :)

xchrisx
11-22-2011, 03:09 PM
Hey Dan,
I really appreciate your insight in this stuff because I dont have a very strong background in coding and I usually hack stuff until i get it to work :). I could be completely wrong in my logic but here is my thought process.

I actually put them into the process code because I am using a requester to set which objects I need to monitor for updates. I contemplated putting the effectedby's in the options portion of my motion modifier instead of the process portion, however, I am thinking about accessing my script in the future via comring to bypass the requester in which case I dont think the effectedby's would be picked up by layout. I completely agree that other plugins do not require the FPSE, but since they are written in C I assumed they have more control over viewport updates than Lscript (which also might be a false assumption).

Because I have so much code going on right now, this pseudo code shows what I am doing.


//global variables
myControlA,myControlB,myControlC;

create:
{
setdesc("script");
}
options
{
// check/set which objects will influence my current object
requester code
myControlA = ctlmesh items
myControlB =ctlmesh items
myControlC =ctlmesh items
}
process
{
// make sure they all have values before proceeding
if(myControlA!=nil; && myControlB!=nil; && myControlC!=nil)
{
// update if the controls are changed
effectedby(myControlA.name);
effectedby(myControlB.name);
effectedby(myControlC.name);

// use the controls positions to change position of the current object
someCalculationCode();
}


//otherUDFs

evenflcw
11-22-2011, 03:37 PM
Looking at your code.

"// update if the controls are changed"
This bit is very important. Especially if you are gonna be stubborn about keeping it in the process callback. Just store the previous items and compare to current items. That's the simplest.

But the correct way is to build a UDF just for setting the dependencies and call this from your options and eventually comring event function.

In this case, plugins and lscript, are on par with one another. They both go through the same evaluation passes and can be made as interactive. (Although plugins have better knowledge about what pass they are in thanks to recent SDK addition. Nothing super-necessary. Just convenient).

xchrisx
11-22-2011, 03:42 PM
Wasn't trying to come across as stubborn :) I guess I am really mentally tired and didnt think about putting it in a custom UDF. It makes perfect sense. Thanks for the suggestion :thumbsup:

evenflcw
11-22-2011, 03:49 PM
Dont forget to use an array if you're gonna have multiple dependancies. This is close to what I'd probably do.

myControlItems;

options {
//controls
//input handling
...

arr = @ctlmesh_itemsA.value, ctlmesh_itemsB.value, [email protected]; //make array
SetControlItems(arr); //send to UDF
}

SetControlItems: arr
{
names = nil;
myControlItems = nil; //clear

for(i=1; i<=arr.count(); i++) {
myControlItems[i] = arr[i]; //keep a copy of the ItemOAs rather than the names
names[i] = arr[i].name;
}
effectedby(names);
}

xchrisx
11-22-2011, 04:31 PM
will do. thanks :)

Kryslin
12-24-2011, 12:54 PM
And the above helps me with my "Targets+" lscript as well.

Thank you very much, evenflcw.