PDA

View Full Version : LScript: ScrubTimelineTool



faulknermano
08-21-2009, 01:39 AM
I've been experimenting with the newly-found layouttool class in LScript and I'm pretty excited about it. Here's a functionality that I've wanted to do have in LW for a long time: activating the tool will connect the mouse movement to scrub the timeline without having to actually move your mouse pointer over the timeilne.



@version 2.6
@warnings
@script layouttool

firstFrame;
lastFrame;
currentFrame;viewportWidth;
tooldraw: coa
{

}

tooldown: te
{
viewportSize = Scene().viewportRect(te.viewNumber);

viewportWidth = viewportSize[4];
currentFrame = Scene().currenttime * Scene().fps;
firstFrame = Scene().previewstart;
lastFrame = Scene().previewend;
return 1;

}

toolmove: te
{

pixelmoveX = te.dx;
pixelmoveY = -te.dy;

segmentSize = viewportWidth / (lastFrame - firstFrame + 1);

finFrame = (pixelmoveX / segmentSize) + currentFrame;
if(finFrame >= firstFrame && finFrame <= lastFrame)
GoToFrame(finFrame);
RefreshNow();
return;

}

toolup: te
{

}

tooldirty
{
return 1;
}



On the side I'm currently developing several translation tools that I've always wanted to have in LW. But it would take some time in getting used to this. :)

UnCommonGrafx
08-21-2009, 05:54 AM
You still Rock!
Thanks.

faulknermano
08-28-2009, 12:02 AM
Update:
-drawing of motion paths of selected item, and items selected in listbox
-drawing of keyframes and frames
-double-clicking on any part of the viewport will bring up options panel
-current frame display can be situated above the currently selected item, or on mouse point.

To do:
-controls in options panel is not logically arranged yet.
-translation manips (maybe)
-keyframe symbols
-option to change colors
-bigger current frame display (maybe)
-clean up code



@version 2.6
@warnings
@script layouttool
mouseLoc=<0,0,0>;
eventaxis = <0,0,1>;
firstFrame;
lastFrame;
currentFrame;viewportWidth;
eventaxis;
finVec=nil;
tickdown; moved;
doubleclick;
c1..3;
d1;
displayKeys;showMotionPath;displayTimeOnSelected;
itemList; // for requester only
items; // to be processed
process: me
{
info(me);
}

tooldone
{
if(reqisopen())
reqabort();
}

tooldown: te
{

populate_items();
(h,m,s,t) = time();
if(tickdown)
firsttick = tickdown;
else
firsttick = t;
tickdown = t;
if((tickdown - firsttick) <= 1)
doubleclick = true;
else
doubleclick = false;
if(mouseLoc)
firstMouseLoc = mouseLoc;
mouseLoc = <te.posRaw[1],te.posRaw[2],te.posRaw[3]>;

if(mouseLoc == firstMouseLoc)
samePlace = true;
else
samePlace = false;

if(doubleclick == true && samePlace == true)
options();
eventaxis = <te.axis[1],te.axis[2],te.axis[3]>;
viewportSize = Scene().viewportRect(te.viewNumber);

viewportWidth = viewportSize[4];
currentFrame = Scene().currenttime * Scene().fps;
firstFrame = Scene().previewstart;
lastFrame = Scene().previewend;

displayKeys = integer(recall("displayKeys",1));
showMotionPath = integer(recall("showMotionPath",0));
return 1;

}
toolstart: te
{


mouseLoc = <te.posRaw[1],te.posRaw[2],te.posRaw[3]>;
eventaxis = <te.axis[1],te.axis[2],te.axis[3]>;
inittool(te);
}
inittool: te
{
sel = Scene().firstSelect();

if(sel)
distToObject = vmag(sel.getWorldPosition(Scene().currenttime) - Scene().viewportPos(0));
else
distToObject = 1;
finVec = (normalize(eventaxis)*(distToObject) + Scene().viewportPos(0));
}
toolmove: te
{
inittool(te);

pixelmoveX = te.dx;
pixelmoveY = -te.dy;
if(pixelmoveX != 0 || pixelMove != 0)
moved = true;
else
moved = false;
segmentSize = viewportWidth / (lastFrame - firstFrame + 1);

finFrame = (pixelmoveX / segmentSize) + currentFrame;
if(finFrame >= lastFrame)
finFrame = lastFrame;
if(finFrame <= firstFrame)
finFrame = firstFrame;
GoToFrame(finFrame);
RefreshNow();
return;

}

toolup: te
{ eventaxis = <te.axis[1],te.axis[2],te.axis[3]>;
}

tooldirty
{
return 1;
}
toolevent: te
{
helptext = "Left-click / right-click to scrub timeline. Double-click to open options panel.";
StatusMsg(helptext);
//~ populate_itemList();
//~ populate_items();
if(te == 0)
if(reqisopen())
reqabort();
}
tooldraw: coa
{
myTime = string(Scene().currenttime * Scene().fps);
if(finVec)
{
coa.setColor(1,1,0);
displayTimeOnSelected = integer(recall("displayTimeOnSelected",0));
if(displayTimeOnSelected == false)
coa.drawText(finVec,myTime,SYS_WORLD,"center");
else
{
userVec = Scene().firstSelect().getWorldPosition(Scene().cur renttime);
userVec.y = userVec.y + Scene().viewportGridSize(0);
coa.drawText(userVec,myTime,SYS_WORLD,"right");
}
}
for(i=1;i<=items.size();i++)
{
item = items[i];

myArray[1] = getKeys(items[i],"Position");
myArray[2] = getKeys(items[i],"Rotation");
myArray[3] = getKeys(items[i],"Scale");
if(displayKeys == 2)
{
for(k=1;k<=myArray.size();k++)
{
for(l=1;l<=myArray[k].size();l++)
{
keyPos = items[i].getWorldPosition(myArray[k,l]);
coa.drawText(keyPos,string(myArray[k,l]*Scene().fps),SYS_WORLD,"center");

}
}
}

if(showMotionPath == true || displayKeys == 3)
{
// get start and end

if(myArray[1,1] != nil && myArray[2,1] != nil)
min1 = min(myArray[1,1],myArray[2,1]);
else if(myArray[1,1] != nil)
min1 = myArray[1,1];
else if(myArray[2,1] != nil)
min1 = myArray[2,1];

if(myArray[3,1] != nil)
minFin = min(min1,myArray[3,1]);
else
minFin = min1;

a1 = myArray[1].size();
a2 = myArray[2].size();
a3 = myArray[3].size();
if(myArray[1,a1] != nil && myArray[2,a2] != nil)
max1 = max(myArray[1,a1],myArray[2,a2]);
else if(myArray[1,a1] != nil)
max1 = a1;
else if(myArray[2,a2] != nil)
max1 = a2;

if(myArray[3,a3] != nil)
maxFin = max(max1,myArray[3,a3]);
else
maxFin = max1;


frameMin = minFin * Scene().fps;
frameMax = maxFin * Scene().fps;

for(j=frameMin;j<=frameMax;j++)
{
if(j == 0)
pt1 = items[i].getWorldPosition(0);
else
pt1 = items[i].getWorldPosition(j / Scene().fps);
if(j+1 == 0)
pt2 = 0;
else
pt2 = items[i].getWorldPosition((j+1) / Scene().fps);
if(showMotionPath == true)
{
coa.drawLine(pt1,pt2,SYS_WORLD);
}
if(displayKeys == 3)
{
if(j == Scene().currenttime * Scene().fps)
coa.setColor(1,1,0);
else
coa.setColor(.7,.7,.2);
coa.drawText(pt1,string(j),SYS_WORLD,"center");
}

}


}
}

}

getKeys: myitem, type
{
arrayKeyTimes = nil;
chan = myitem.firstChannel();
while(chan)
{
chanName = chan.name;
if(chanName.contains(type))
{
for(i=1;i<=chan.keyCount;i++)
{
mykey = chan.keys[i];
arrayKeyTimes[arrayKeyTimes.size()+1] = chan.getKeyTime(mykey);
}

}
chan = myitem.nextChannel();
}
return(arrayKeyTimes);

for(i=1;i<=chanArray.size();i++)
{
// get keys

}
}
options
{

if(reqisopen())
return;
populate_itemList();
displayKeys = integer(recall("displayKeys",1));
showMotionPath = integer(recall("showMotionPath",0));
displayTimeOnSelected = integer(recall("displayTimeOnSelected",0));
reqbegin("Scrub Timeline Options");
c1 = ctlpopup("Display Keys",displayKeys,@"Hide","Show as numbers","Show every frame"@);
c2 = ctlcheckbox("Show motion path",showMotionPath);
c3 = ctllistbox("Item motion paths",150,150,"list_count","list_names","list_event");
d1 = ctlcheckbox("Display current time on selected",displayTimeOnSelected);
ctlrefresh(c1,"refresh_displayKeys");
ctlrefresh(c2,"refresh_showMotionPath");
ctlrefresh(d1,"refresh_displayTimeOnSelected");
reqopen();
}
populate_itemList
{
itemList = nil;

m = Mesh();
while(m)
{
if(m.id != Scene().firstSelect().id)
itemList[itemList.size()+1] = m;
m = m.next();
}
m = Light();
while(m)
{
if(m.id != Scene().firstSelect().id)
itemList[itemList.size()+1] = m;
m = m.next();
}
m = Camera();
while(m)
{
if(m.id != Scene().firstSelect().id)
itemList[itemList.size()+1] = m;
m = m.next();
}
itemList.pack();itemList.trunc();
}
list_count
{
// get mesh, lights, cameras, and bones
return(itemList.size());

}
list_names: ndx
{
return(itemList[ndx].name);
}
populate_items
{
items = nil;
items[1] = Scene().firstSelect();
if(reqisopen())
{
selectedItems = getvalue(c3);
for(i=1;i<=selectedItems.size();i++)
{
myNdx = selectedItems[i];
items[items.size()+1] = itemList[myNdx];
}
}

items.trunc(); items.pack();
}
list_event: ndx
{
populate_items();
CommandInput("Refresh");
}
refresh_displayKeys: val
{
store("displayKeys",val);
CommandInput("Refresh");
}
refresh_displayTimeOnSelected: val
{
store("displayTimeOnSelected",val);
CommandInput("Refresh");
}
refresh_showMotionPath: val
{
store("showMotionPath",val);
CommandInput("Refresh");
}




I'm planning on expanding this even further and possibly creating a set of navigation/manipulation tools around this LScript class.

papou
08-29-2009, 02:22 PM
very informative, very nice.
And happy to know you still in your lightwave labotory.