Can ASP control a switch, based on its bone angle?
Moderators: Víctor Paredes, Belgarath, slowtiger
Can ASP control a switch, based on its bone angle?
The reason I ask this is because it would make things much easier to animate, if one could setup a set of switch options for, say, the lower arm and let ASP decide which option to select, based on the angle.
Animating arms and legs would be so much easier then.
One could simply draw a set of lower arms and let ASP select the one that looks better for that specific angle range (say, 20 to 25 degress, etc...).
If there is no such thing, can it be done in Lua scripting?
Cheers,
Rui
Animating arms and legs would be so much easier then.
One could simply draw a set of lower arms and let ASP select the one that looks better for that specific angle range (say, 20 to 25 degress, etc...).
If there is no such thing, can it be done in Lua scripting?
Cheers,
Rui
- synthsin75
- Posts: 10280
- Joined: Mon Jan 14, 2008 11:20 pm
- Location: Oklahoma
- Contact:
Check out our discussion of this in this thread:
viewtopic.php?t=12376
It is possible with scripting, but the few of us who do script for AS all seem to have huge lists of things we're wanting to script. Check out that thread for at least one alternate solution for this.

viewtopic.php?t=12376
It is possible with scripting, but the few of us who do script for AS all seem to have huge lists of things we're wanting to script. Check out that thread for at least one alternate solution for this.

I have a test version that "works". I can't figure out how to make rotation "ranges" on the bone to match the switches though. It works.. .but... not accurately. You almost have to type in exact rotations of the bone which kind of defeats the purpose of "making it easier" than right clicking the switch.
What happens is that the bone over rotates depending on the space between keys... over shoots the "range" marker and "skips" a switch layer. It might work better with "Step" keys but... once again that adds more work to the process and it should work with any type of key dagnabbit.
I've had to put a lot of my scripts "on hold" for the moment for various reasons.
-vern
What happens is that the bone over rotates depending on the space between keys... over shoots the "range" marker and "skips" a switch layer. It might work better with "Step" keys but... once again that adds more work to the process and it should work with any type of key dagnabbit.
I've had to put a lot of my scripts "on hold" for the moment for various reasons.
-vern
Thanks for the replies guys.
I took a look at the selection script and it looks really good.
I wonder if these would be the steps to modify it:
1. Get the bone itself, not an external control bone, to make make the decisions;
2. Get the angle relative to the parent bone;
3. Divide the angle by, say, 20, resulting in up to 18 positions for a complete 360 degrees rotation;
4. Acivate the switch option that was computed by the division above;
I see a few problems here:
1. Can we select switch option via script?
Yes, Vern was able to do it.
2. How would we define the starting and ending angles?
The interface doesn't seem to provide a place for inputing that kind of data.
The alternative would be that the switch would have to implement all 18 options, despite some of them would be empty or replicated.
I am just thinking about it.
And I see that it would be very difficult to do, specily the part where we can not specify the angle ranges.
Hm... I wonder if there are plans to implement this in a forthcoming version of ASP?
P.S.: The angle range could be limited to, say, 120 degrees, with a 15 degrees precision, resulting in 8 options for the switch, instead of 18.
I took a look at the selection script and it looks really good.
I wonder if these would be the steps to modify it:
1. Get the bone itself, not an external control bone, to make make the decisions;
2. Get the angle relative to the parent bone;
3. Divide the angle by, say, 20, resulting in up to 18 positions for a complete 360 degrees rotation;
4. Acivate the switch option that was computed by the division above;
I see a few problems here:
1. Can we select switch option via script?
Yes, Vern was able to do it.
2. How would we define the starting and ending angles?
The interface doesn't seem to provide a place for inputing that kind of data.
The alternative would be that the switch would have to implement all 18 options, despite some of them would be empty or replicated.
I am just thinking about it.
And I see that it would be very difficult to do, specily the part where we can not specify the angle ranges.
Hm... I wonder if there are plans to implement this in a forthcoming version of ASP?
P.S.: The angle range could be limited to, say, 120 degrees, with a 15 degrees precision, resulting in 8 options for the switch, instead of 18.
In my script I divided "360" by the number of layers in the switch. The main issue is radians. AS uses radians not degrees internally so the code is not... simple. It's been a while since I looked at that script but I think I made the performace sacrifice and just converted the angles in lua to degrees.
The next step was when to "switch" the layer. You have to switch when the angle is "within" that range. Because each switch can have any number of layers the angle range can be... anything. The code has to check if the angle is above one value AND below another value.
Another problem is when the bone rotatates through those ranges. There was no way to "skip over" other switches. The bone rotated through all of them causing all the switches to be selected as it moved back and forth.
I then wanted to try and script a "lock" on the bone rotation. So the bone could not rotate at all and would "snap" only to those angles defined by the number of switch layers....
...
After a while I just got bored with the whole thing and set switches by hand.
-vern
The next step was when to "switch" the layer. You have to switch when the angle is "within" that range. Because each switch can have any number of layers the angle range can be... anything. The code has to check if the angle is above one value AND below another value.
Another problem is when the bone rotatates through those ranges. There was no way to "skip over" other switches. The bone rotated through all of them causing all the switches to be selected as it moved back and forth.
I then wanted to try and script a "lock" on the bone rotation. So the bone could not rotate at all and would "snap" only to those angles defined by the number of switch layers....
...
After a while I just got bored with the whole thing and set switches by hand.

-vern
Hm. Dividing the 360 degrees by the number of options was was very clever.
By doing that you don't need to store the extra information.
Animation would make so much more sense if we had that tool.
I mean, we could easily create the animations 100% hand-drawn, if we wanted to. And, still, we would be able to use the bones appproach for actualy using them.
I am not complaining - I love ASP, so far.
But that tool alone, would make me feel much more comfortable about what can be done and what has to be done.
Cheers,
Rui
By doing that you don't need to store the extra information.
Animation would make so much more sense if we had that tool.
I mean, we could easily create the animations 100% hand-drawn, if we wanted to. And, still, we would be able to use the bones appproach for actualy using them.
I am not complaining - I love ASP, so far.
But that tool alone, would make me feel much more comfortable about what can be done and what has to be done.
Cheers,
Rui
- synthsin75
- Posts: 10280
- Joined: Mon Jan 14, 2008 11:20 pm
- Location: Oklahoma
- Contact:
I've been thinking lately that many of our layer scripts would actually be more useful, performance-wise, as tools. Granted as tools you'd have to delete keyframes manually, but the performance of an OnMouseUp beats the hell out of running three times per frame.
So this would be a rotate bone tool that checks the bone's name (for an extension). OnMouseUp it would do as your layer script does. Divide the degrees by the number of layers in a specifically named switch layer.
This is just off the top of my head, so there may be issues I haven't imagined.
p.s. Perhaps it could even delete keys on the switch from frames that have no key on the bone.
So this would be a rotate bone tool that checks the bone's name (for an extension). OnMouseUp it would do as your layer script does. Divide the degrees by the number of layers in a specifically named switch layer.
This is just off the top of my head, so there may be issues I haven't imagined.

p.s. Perhaps it could even delete keys on the switch from frames that have no key on the bone.
Vern,heyvern wrote:I have a test version that "works". I can't figure out how to make rotation "ranges" on the bone to match the switches though. It works.. .but... not accurately. You almost have to type in exact rotations of the bone which kind of defeats the purpose of "making it easier" than right clicking the switch.
What happens is that the bone over rotates depending on the space between keys... over shoots the "range" marker and "skips" a switch layer. It might work better with "Step" keys but... once again that adds more work to the process and it should work with any type of key dagnabbit.
I've had to put a lot of my scripts "on hold" for the moment for various reasons.
-vern
can I have a copy of your test version? Maybe I can fix the "radian problem" and add some of the features that have been commented here.
Cheers
-G
Yes. That would be sweeeet.
One would be able to rotate the bone and as he/she did it, it would be possible to see the different results.
That is, the drawing (shape) would change as we rotate the angle.
Animations could be done on a frame-by-frame basis, hand-drawn, if we wanted to.
But we would still use bones to animate the characters.
One would be able to rotate the bone and as he/she did it, it would be possible to see the different results.
That is, the drawing (shape) would change as we rotate the angle.
Animations could be done on a frame-by-frame basis, hand-drawn, if we wanted to.
But we would still use bones to animate the characters.
Here it is...
http://www.lowrestv.com/anime_studio/sc ... -scrpt.zip
It was created a long time ago as you will note by the extension (.moho) but I think I played with it recently. The script is useless for much except testing. It works on one bone (bone 0) and one switch layer. I've included the test file.
It adds and removes key frames from the switch layer based on the rotation of the bone and the bones keys. That much works well. If you move the bone keys and play or rescrub the time line it will remove and add the new keys. This means you don't need the script after the switch has been keyed. Those keys are still in the switch layer. Just like the "slave switch" scripts.
-vern
http://www.lowrestv.com/anime_studio/sc ... -scrpt.zip
It was created a long time ago as you will note by the extension (.moho) but I think I played with it recently. The script is useless for much except testing. It works on one bone (bone 0) and one switch layer. I've included the test file.
It adds and removes key frames from the switch layer based on the rotation of the bone and the bones keys. That much works well. If you move the bone keys and play or rescrub the time line it will remove and add the new keys. This means you don't need the script after the switch has been keyed. Those keys are still in the switch layer. Just like the "slave switch" scripts.
-vern
Thanks a lot, Vern.
I really appreciated it.
I looked into the script and made this small change:
Right after:
keySwitch = crtlBone.fAngle
I have added this:
keySwitch = math.mod(keySwitch, math.rad(360))
if (keySwitch < 0) then
keySwitch = keySwitch + math.rad(360)
end
So that no matter how many complete loops around the bone's pivot, the angle is alwas right (0 to 2 PI radians).
I loved your scrit and am hoping to be able to make it work the way I expect.
Unfortunalely, I am not used to the moho API, so it may tke a looong time before I can actualy adapt t to my needs.
Thanks again.
Thanks, again...
I really appreciated it.
I looked into the script and made this small change:
Right after:
keySwitch = crtlBone.fAngle
I have added this:
keySwitch = math.mod(keySwitch, math.rad(360))
if (keySwitch < 0) then
keySwitch = keySwitch + math.rad(360)
end
So that no matter how many complete loops around the bone's pivot, the angle is alwas right (0 to 2 PI radians).
I loved your scrit and am hoping to be able to make it work the way I expect.
Unfortunalely, I am not used to the moho API, so it may tke a looong time before I can actualy adapt t to my needs.
Thanks again.
Thanks, again...
I think I managed to fix the range problem.
Here is the modified version:
It looks like it works every tme.
I will test it some more and, if it does woe]rk fine, then I am going to start using it right away.
Thanks so much for your valuable help.
Here is the modified version:
Code: Select all
function LayerScript(moho)
local layer = moho.layer
if ( not layer:IsBoneType() ) then
return
end
local group = moho:LayerAsGroup(layer)
local layerCount = group:CountLayers()
if ( layerCount == 0 ) then
return
end
local skel = moho:Skeleton()
local boneCount = skel:CountBones()
if ( boneCount == 0) then
return
end
local ctrlLayer = nil
local crtlBone = skel:Bone(0)
local keySwitch = nil
local Lcount = nil
local SWunits = nil
local keySwitch = nil
local tUnit = math.rad(360)
local bob = {}
if ( moho.frame > 0 ) then
local subSwitch = nil
if ( crtlBone.fAnimAngle:HasKey(moho.frame) ) then
keySwitch = crtlBone.fAngle * 10000 -- for using INT math
keySwitch = math.mod(keySwitch, 62831) -- locks to 0-360
if (keySwitch < 0) then -- If negative, add one complete lap
keySwitch = keySwitch + 62831
end
keySwitch = keySwitch / 10000 -- back to floating point
keySwitch = keySwitch + tUnit -- Make it 360 to 720
-- 360 to 720 to make sure it is always progressive,
-- otherwise, we would have to check the lst select differently
end
for i = 0, layerCount - 1 do
local testlayer = group:Layer(i)
if (testlayer:LayerType() == MOHO.LT_SWITCH) then
group2 = moho:LayerAsGroup(testlayer)
subSwitch = moho:LayerAsSwitch(testlayer)
Lcount = group2:CountLayers()
SWunits = tUnit / (Lcount)
-- SWunits = math.rad(360)/Lcount
end
end
--[[
print(math.rad(60))
print(math.rad(120))
print(math.rad(180))
print(math.rad(240))
print(tUnit/6)
print(math.deg(1))
print("----------")
--]]
--[[
L=360/N (converted to radians of course). L is an angle value
x0 = x0 + 0*SWunits
x1 = x0 + 1*SWunits
x2 = x0 + 2*SWunits
--]]
for b = 0, Lcount - 1 do
-- print(b-1)
local swLayers = group2:Layer(b)
local SWname = swLayers:Name()
local swUnit = tUnit + (b * SWunits) -- tUnit, to make it 360-720
local swUnitB = swUnit + SWunits
if ( keySwitch ~= nil) then
if (keySwitch <= swUnitB and keySwitch >= swUnit) then
subSwitch:SwitchValues():SetValue(moho.frame, SWname)
-- print(SWname)
-- print(math.deg(swUnitB))
-- moho:Skeleton():UpdateBoneMatrix()
end
elseif ( keySwitch == nil) then
subSwitch:SwitchValues():DeleteKey(moho.frame)
-- moho:Skeleton():UpdateBoneMatrix()
end
end
end
end
I will test it some more and, if it does woe]rk fine, then I am going to start using it right away.
Thanks so much for your valuable help.
Code: Select all
function LayerScript(moho)
local layer = moho.layer
if ( not layer:IsBoneType() ) then
return
end
local group = moho:LayerAsGroup(layer)
local layerCount = group:CountLayers()
if ( layerCount == 0 ) then
return
end
local skel = moho:Skeleton()
local boneCount = skel:CountBones()
if ( boneCount == 0) then
return
end
local ctrlLayer = nil
local crtlBone = skel:Bone(0)
local keySwitch = nil
local group2 = nil
local Lcount = nil
local SWunits = nil
local keySwitch = nil
local tUnit = math.rad(360)
local bob = {}
if ( moho.frame > 0 ) then
local subSwitch = nil
if ( crtlBone.fAnimAngle:HasKey(moho.frame) ) then
keySwitch = math.mod(crtlBone.fAngle,tUnit)
end
for i = 0, layerCount - 1 do
local testlayer = group:Layer(i)
if (testlayer:LayerType() == MOHO.LT_SWITCH) then
group2 = moho:LayerAsGroup(testlayer)
subSwitch = moho:LayerAsSwitch(testlayer)
Lcount = group2:CountLayers()
SWunits = tUnit / Lcount
end
end
for b = 0, Lcount-1 do
local swLayers = group2:Layer(b)
local SWname = swLayers:Name()
local swUnit = b * SWunits
local swUnitB = swUnit + SWunits
if ( keySwitch ~= nil) then
if (keySwitch <= swUnitB and keySwitch >= swUnit) then
subSwitch:SwitchValues():SetValue(moho.frame, SWname)
end
elseif ( keySwitch == nil) then
subSwitch:SwitchValues():DeleteKey(moho.frame)
end
end
end
end
Code: Select all
keySwitch = math.mod(crtlBone.fAngle,tUnit)
Code: Select all
local swUnit = b * SWunits
local swUnitB = swUnit + SWunits
-G