A lua greenhorn's question
Moderators: Víctor Paredes, Belgarath, slowtiger
I thought of one restriction, unfortunately. For the point channels, you're going to need access to the mesh which comes from moho and not the layer. Similarly, for bone channels. You might have to compromise and have a tool button that does the synchronization between your floating window and the actual timeline.
Rudiger,
in order to understand things better I tried to apply the principles of your "RT_UtilityWindow" in the "lm_layertrail.lua" script (/scripts/menu/layer effects).
I tried to use your method for changing it to modeless.
So, I changed the code at lines 101 - 108 from:
to:
But, the result is that the script even doesn't appear anymore in the script list.
Do you know what's going wrong?
Of course I could have set the window to modeless by keeping all the code and just changing
stefman
in order to understand things better I tried to apply the principles of your "RT_UtilityWindow" in the "lm_layertrail.lua" script (/scripts/menu/layer effects).
I tried to use your method for changing it to modeless.
So, I changed the code at lines 101 - 108 from:
function LM_LayerTrail:Run(moho)
self.startFrame = 1
self.endFrame = moho.document:EndFrame()
local dlog = LM_LayerTrailDialog:new(moho)
if (dlog:DoModal() == LM.GUI.MSG_CANCEL) then
return
end
to:
function LM_LayerTrail:Run(moho)
self.startFrame = 1
self.endFrame = moho.document:EndFrame()
self.moho = moho
local dlog = LM_LayerTrailDialog:new(moho)
dlog:DoModeless()
end
But, the result is that the script even doesn't appear anymore in the script list.

Do you know what's going wrong?
Of course I could have set the window to modeless by keeping all the code and just changing
toif (dlog:DoModal() == LM.GUI.MSG_CANCEL) then
return
But, I wanted to recreate your structure in order to integrate a button at the next step.if (dlog:DoModeless() == LM.GUI.MSG_CANCEL) then
return
stefman
Hi Stefman,
The reason that the script isn't showing up all is probably that it has a syntax error and there is a bug in version 6.0 that makes it not report lua syntax errors properly.
I suspect you've got one too many ends. Since you got rid of the "if(dlog:DoModal() == LM... ...then" line you have to get rid of the corresponding "end" statement. Don't forget that any other code in the run function will have to be moved to its own function so you can run it when a button is pressed not when the script is first run.
The reason that the script isn't showing up all is probably that it has a syntax error and there is a bug in version 6.0 that makes it not report lua syntax errors properly.
I suspect you've got one too many ends. Since you got rid of the "if(dlog:DoModal() == LM... ...then" line you have to get rid of the corresponding "end" statement. Don't forget that any other code in the run function will have to be moved to its own function so you can run it when a button is pressed not when the script is first run.
Good grief... I'm an idiot.Rudiger wrote:OK, I had a look at the lm_star.lua script and it looks like the moho object is already embedded in the dialog! IE on line 55 is says "d.moho = moho". This means any dialog method can access the scripting interface simply by using self.moho.


Funny... I sort of tried that but it didn't work. I think because I tried to make another GLOBAL variable equal to "moho"! This is what caused AS to crash. "d.moho" is only passed as a LOCAL variable. If I pass moho to other functions using a local variable it works without crashing!!!
Thanks DUDE!!! My brain thanks you to.

-vern
Rudiger wrote: I suspect you've got one too many ends. Since you got rid of the "if(dlog:DoModal() == LM... ...then" line you have to get rid of the corresponding "end" statement.
Rudiger, thank you very much!
Indeed, there was one "end" too much.
Now, the script appears properly in the menu and the window also opens well.
I managed to integrate the button, to create the message and I created an own function for the code that was remaining underneath.
The isolated code for the run function is as follows:
(I kept the definitions of self.startFrame and self.endFrame in that function because the display needs them to update themselves when the window opens.) This works fine. The window opens properly.function LM_LayerTrail:Run(moho)
self.startFrame = moho.document:StartFrame()
self.endFrame = moho.document:EndFrame()
self.moho = moho
local dlog = LM_LayerTrailDialog:new(moho)
dlog:DoModeless()
end
I put the remaining code into a new function which is triggered by the button.
The triggering works fine but I think there are things in this function which shouldn't be there.
When pushing the button the lua console shows this error message:
attempt to index global 'moho' (a nil value)
This is the code of my bearish function:
The error message referes to line 3function LM_LayerTrail:ButtonAction(parent)
moho.document:PrepUndo(nil)
moho.document:SetDirty()
local parentLayer = moho.layer
local layer = moho:CreateNewLayer(MOHO.LT_VECTOR)
layer:SetName("Layer Trail")
local mesh = moho:Mesh()
if (mesh == nil) then
return
end
local startFrame = self.startFrame
local endFrame = self.endFrame
local curFrame = moho.frame
local m = LM.Matrix:new_local()
local origM = LM.Matrix:new_local()
local vec = LM.Vector2:new_local()
local origin = parentLayer:Origin()
-- first, create a curve with a new point for each frame of movement
local dashedOn = true
for frame = startFrame, endFrame do
moho:SetCurFrame(frame)
parentLayer:GetFullTransform(frame, m, nil)
vec:Set(origin)
m:Transform(vec)
if (frame == startFrame) then
mesh:AddLonePoint(vec, 0)
else
mesh:AppendPoint(vec, 0)
mesh:SelectNone()
local id = mesh:CountPoints() - 1
mesh:Point(id).fSelected = true
mesh:Point(id - 1).fSelected = true
if (self.dashed) then
if (dashedOn) then
moho:CreateShape(false, layer:CurFrame(), false)
end
else
moho:CreateShape(false, layer:CurFrame(), false)
end
mesh:Point(0).fParent = -1
mesh:Point(mesh:CountPoints() - 1).fParent = -1
dashedOn = not dashedOn
end
end
mesh:SelectNone()
-- next, compensate these points for any movement higher up in the hierarchy
-- examples: the target layer is part of a group with motion of its own, or is attached to a bone
layer:GetFullTransform(0, origM, nil)
for frame = startFrame, endFrame do
layer:GetFullTransform(frame, m, nil)
m:Invert()
for i = 0, mesh:CountPoints() - 1 do
vec:Set(mesh:Point(i).fAnimPos:GetValue(0))
origM:Transform(vec)
m:Transform(vec)
mesh:Point(i).fAnimPos:SetValue(frame, vec)
end
end
moho:SetCurFrame(curFrame)
end
Well, I managed to resolve the problem at line 3 by putting code back to the run function. This worked fine untilmoho.document:PrepUndo(nil)
local curFrame = moho.frame
AS didn't know what to do with it (a nil value). But, I managed it by creating a self object.
But, now I'm stuck at
local origin = parentLayer:Origin()
Do you know why he doesn't find this value and what I could do? Or, am I completely wrong when doing all this?
stefman
Not yet but I sort of know how to do it now.
The dialog box creation is the key to it. You have to create all the variables there that you need IN the dialog box widgets. So... if you need the LAYER to do stuff to it, create a variable for the layer in the dialog box:
If you try to use the "self.moho" anywhere in the script, AS will crash. But I can use the "self.myLayer" variable without a crash. So the trick is to create those variables in the dialog box creation at the top of the script. I haven't had a chance yet to take this further BUT it should work now because I was able to access the layer name and print it out using a button in the dialog box. This means the layer contents like bones, or points is accessible from that button.
-vern
The dialog box creation is the key to it. You have to create all the variables there that you need IN the dialog box widgets. So... if you need the LAYER to do stuff to it, create a variable for the layer in the dialog box:
Code: Select all
d.moho = moho
d.myLayer = moho.layer
-vern
If only, but not quite. Skeleton() and Mesh() are both methods of moho and not layer, so you will have to store them in the dialog as well. If you really want a floating layer-independent window, you would really require a fresh moho variable to be supplied to the handle_message method each time it's called.heyvern wrote: If you try to use the "self.moho" anywhere in the script, AS will crash. But I can use the "self.myLayer" variable without a crash. So the trick is to create those variables in the dialog box creation at the top of the script. I haven't had a chance yet to take this further BUT it should work now because I was able to access the layer name and print it out using a button in the dialog box. This means the layer contents like bones, or points is accessible from that button.
-vern
Hi Stefman,
Basically, when you store moho inside your script object, you are only storing the address of the interface, not the interface itself. What happens is that after the script is run and the modeless dialog is created, the interface that moho points to is no longer valid, so that's why AnimeStudio crashes if you try and do things like self.moho.layer or self.moho:Mesh(). However, static functions like self.moho:LayerAsGroup() seemed to be OK.
So that means you have to replace moho in your function with self.moho and things like layer and mesh you also have to pre-store in self before you create the dialog.
Basically, when you store moho inside your script object, you are only storing the address of the interface, not the interface itself. What happens is that after the script is run and the modeless dialog is created, the interface that moho points to is no longer valid, so that's why AnimeStudio crashes if you try and do things like self.moho.layer or self.moho:Mesh(). However, static functions like self.moho:LayerAsGroup() seemed to be OK.
So that means you have to replace moho in your function with self.moho and things like layer and mesh you also have to pre-store in self before you create the dialog.
Thank you Rudiger;
But, I still didn't get it work.
As 'self.moho.layer' doesn't work I don't know how I have to modify
Or, did you mention this just as an example?
stefman
But, I still didn't get it work.
As 'self.moho.layer' doesn't work I don't know how I have to modify
in order to be used in this line of the 'ButtonAction' function:local parentLayer = moho.layer
How can I integrate 'self.moho:LayerAsGroup()' into that?local origin = parentLayer:Origin()
Or, did you mention this just as an example?
stefman
Look at the top of the script, any menu script that has a dialog box.
You see where it has the:
"d" is passed to the dialog box. It is a "table" that has all of those variables stored in it that reference the elements you need. So if you need "moho.layer" then create a variable in the table in the dialog creation:
Then you could use "self.layer".
I am still very confused how and what can be accessed in a modeless dialog box. I seriously doubt a full fledged timeline or comprehensive gizmo can be done this way. For example if the modeless window is open and you select a different layer in the layer palette is the "moho.layer" updated? That layer object is defined with the layer selected... if you can't access "moho" after the dialog is open how do you get channel info from any other layers?
-vern
You see where it has the:
Code: Select all
function LM_BoneSoundDialog:new(moho)
local d = LM.GUI.SimpleDialog(MOHO.Localize("/Scripts/Menu/BoneSound/Title=Bone Audio Wiggle"), LM_BoneSoundDialog)
local l = d:GetLayout()
d.moho = moho
Code: Select all
d.layer = moho.layer
I am still very confused how and what can be accessed in a modeless dialog box. I seriously doubt a full fledged timeline or comprehensive gizmo can be done this way. For example if the modeless window is open and you select a different layer in the layer palette is the "moho.layer" updated? That layer object is defined with the layer selected... if you can't access "moho" after the dialog is open how do you get channel info from any other layers?
-vern
Thank you Vern.
But I unforunately still don't get it done.
In the local "LM_LayerTrailDialog" function I integrated:
And this part of the code I added the first bolt line to define "self.moho" again and replaced "moho.layer" with "self.layer" in the second bolt line.
But, I still get the nil value in the third bolt line.
Do you know what I am doing wrong?
stefman
But I unforunately still don't get it done.
In the local "LM_LayerTrailDialog" function I integrated:
d.layer = moho.layer
And this part of the code I added the first bolt line to define "self.moho" again and replaced "moho.layer" with "self.layer" in the second bolt line.
But, I still get the nil value in the third bolt line.

-- **************************************************
-- The guts of this script
-- **************************************************
function LM_LayerTrail:Run(moho)
self.startFrame = moho.document:StartFrame()
self.endFrame = moho.document:EndFrame()
self.moho = moho
self.curFrame = moho.frame
self.layer = moho.layer
moho.document:PrepUndo(nil)
moho.document:SetDirty()
local dlog = LM_LayerTrailDialog:new(moho)
dlog:DoModeless()
local parentLayer = self.layer
local layer = moho:CreateNewLayer(MOHO.LT_VECTOR)
layer:SetName("Layer Trail")
local mesh = moho:Mesh()
if (mesh == nil) then
return
end
end
function LM_LayerTrail:ButtonAction(parent)
local startFrame = self.startFrame
local endFrame = self.endFrame
local curFrame = self.curFrame
local m = LM.Matrix:new_local()
local origM = LM.Matrix:new_local()
local vec = LM.Vector2:new_local()
local origin = parentLayer:Origin()
-- first, create a curve with a new point for each frame of movement
local dashedOn = true
for frame = startFrame, endFrame do
moho:SetCurFrame(frame)
parentLayer:GetFullTransform(frame, m, nil)
vec:Set(origin)
m:Transform(vec)
if (frame == startFrame) then
mesh:AddLonePoint(vec, 0)
else
mesh:AppendPoint(vec, 0)
mesh:SelectNone()
local id = mesh:CountPoints() - 1
mesh:Point(id).fSelected = true
mesh:Point(id - 1).fSelected = true
if (self.dashed) then
if (dashedOn) then
moho:CreateShape(false, layer:CurFrame(), false)
end
else
moho:CreateShape(false, layer:CurFrame(), false)
end
mesh:Point(0).fParent = -1
mesh:Point(mesh:CountPoints() - 1).fParent = -1
dashedOn = not dashedOn
end
end
mesh:SelectNone()
-- next, compensate these points for any movement higher up in the hierarchy
-- examples: the target layer is part of a group with motion of its own, or is attached to a bone
layer:GetFullTransform(0, origM, nil)
for frame = startFrame, endFrame do
layer:GetFullTransform(frame, m, nil)
m:Invert()
for i = 0, mesh:CountPoints() - 1 do
vec:Set(mesh:Point(i).fAnimPos:GetValue(0))
origM:Transform(vec)
m:Transform(vec)
mesh:Point(i).fAnimPos:SetValue(frame, vec)
end
end
moho:SetCurFrame(curFrame)
end
Do you know what I am doing wrong?
stefman
Yes, thanks Rudiger. That worked.
Now I'm stuck again.
Does anyone know how I could replace 'moho' in this line?
I'm lost because self.moho makes crash all.
stefman
Now I'm stuck again.
Does anyone know how I could replace 'moho' in this line?
Code: Select all
moho:SetCurFrame(frame)
stefman