i have a script request! (Poses)

Moho allows users to write new tools and plugins. Discuss scripting ideas and problems here.

Moderators: Víctor Paredes, Belgarath, slowtiger

Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

heyvern wrote:If each of those layers has the same script there would be a unique table array for each layer and set of points.
That's what I thought at the beginning: "if I load the embedded script to each layer, then each layer would have its own array..." Not true. The array is shared by all the scripts!!! I've recently made a simple embedded script that has an array; I embedded it into several layers. When the first script of first layer runs it modify the array of all the scripts at the same time, so no, embedded scripts doesn't create a new instance of the script. They simply run the script again and again and again changing only the moho parameter....

Sincerely I cannot find a solution to avoid store the poses into its own frames from 1 to maxposes.... Have you? :(
DarthFurby
Posts: 510
Joined: Sat Jul 29, 2006 1:34 pm
Location: New York City
Contact:

Post by DarthFurby »

If you want to keep track of the layers maybe you could have a maxlayers variable defined by the user with each layer named layer1 to layerk(where k = maxlayers), similar to the way you have it set for maxposes.

It looks like you resolved the morphing/interpolation problem, so I guess the biggest issue now is performance.

I'm keeping my fingers crossed that this can be overcome with some tweaking of the code, but it's also possible that this may just be a limitation of interfacing with Anime Studio through a script, and that something like this might have to be hard coded directly into Anime Studio to fix the lag/memory/performance issue. In which case I hope Mike Clifton would be receptive to incorporating the code somehow(with Genete's and selgin's permission.)

Afterwards if you decide to add more animatable vector properties to the script I would definitely be willing to help beta test them. Adding something like layer rotation would mean that a single bone could potentially control and animate multiple layers in 3d space at the same time. Who knows what freaky things could be done with the other channels.

Anyway Genete, thanks for figuring out my problem with the simplemodel file. That's what I get for watching the Super Bowl. I can't do Anime Studio and watch my team lose at the same time. The shock must've caused me to switch scripts on accident.
User avatar
heyvern
Posts: 7035
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Sincerely I cannot find a solution to avoid store the poses into its own frames from 1 to maxposes.... Have you?
Oops! I should have seen that!

Easy fix:

Just make the variable "global" but still assigned to each layer. When you do this:

Code: Select all

moho.layer.maxposes = 4
It can be the same script but that variable will only be used by that specific layer. You just have to reference the variable the same way. You can't just use "maxposes" you have to use "moho.layer.maxposes".

-vern
User avatar
Víctor Paredes
Site Admin
Posts: 5660
Joined: Wed Jan 26, 2005 12:18 am
Location: Barcelona/Chile
Contact:

Post by Víctor Paredes »

excuse me I haven't posted several days ago.
I have read all the discussion and it became too technical for me. :oops:
is there anyway i can help you? as darthfurby, i'll be happily to being a beta tester or something.

I was thinking about the speed which needs this script, obviously I have no idea about how to solve it, but maybe Mike can help us, maybe.
is ok if i write him asking help? or perhaps someone wiser should?
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

selgin wrote:excuse me I haven't posted several days ago.
I have read all the discussion and it became too technical for me. :oops:
is there anyway i can help you? as darthfurby, i'll be happily to being a beta tester or something.

I was thinking about the speed which needs this script, obviously I have no idea about how to solve it, but maybe Mike can help us, maybe.
is ok if i write him asking help? or perhaps someone wiser should?
selgin: you've given here the main idea. You can be satisfied!. Maybe you can test the modeltest I prepared to DF and try to do something similar. Watching some nice animation from you or other would encourage me to deep think on what can be done or/and implement heyvern's suggestions.

Regarding to ask to Mike (LM) you can, why not? the script is completely free and open to everyone. We really need some other script interface to make things easier. Also Mike can help us with the (I don't know sure) memory problem I mentioned some post ago.

-G
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

Here is a model test for DF using stored poses in arrays instead of take them from the current poses frames.

I don't see any spectacular performance improvement. Please test it and feed back.

http://www.darthfurby.com/genete/Script ... stored.zip

For scripters reference here is the script:

Code: Select all

--Embed this script into all the vector layers that want to copy poses from frames 1,2,3,4, ..., maxposes
--it must be under a bone type layer and the following ROOT named bones MUST exists:

-- posek (with k form 1 to maxposes)
-- bonelesector

-- Copyright 2008 Genete
-- Released for free.
-- Thanks to Selgin for that great idea.
-- It can be extended for other animated values (curvatures, widths, shape fill colors, shape outline color, etc.)
-- Also weights w[k] can be overweigthed by the pose bone legth. It would allow some sort of variable action weights...
-- Under development...

poses = {}
maxposes = 4
bone = {}
boneselector = nil

function LayerScript(moho)
	local w = {}
	local distance 
	local posk
	local pos_selector
	local r
	local length
	local k
	local layer = moho.layer
	local frame = moho.frame
	local skel = moho:ParentSkeleton()
        if (skel == nil) then
		print ("No parent skeleton found in layer:".. layer:Name())
		return
	end
	local mesh = moho:Mesh()
	if (mesh==nil) then
		print ("No mesh found in layer:".. layer:Name())
		return
	end	
	if (frame <=maxposes) then 
-----------------------------------look for the bones
		for k=1, maxposes do
			bone[k] = nil
			for i=0, skel:CountBones() -1 do 
				local bonei = skel:Bone(i)
				local bonek = "pose" .. tostring(k)
				if (bonei:Name() == bonek) then
					bone[k]=bonei
				elseif (bonei:Name() == "boneselector") then
					boneselector=bonei
				end
			end	
			if (bone[k] == nil) then 
				print("bone "..k.." is missing")
				return
			end
		end
		if boneselector == nil then 
			print("boneselector is missing")
			return
		end
---------------------------------
--------------------------------- creates a new array for the layer
		poses[layer]={} 
		poses[layer]["points"]={} 
		for k=1, maxposes do
			poses[layer]["points"][k]={}
			for i=0, mesh:CountPoints()-1 do
			poses[layer]["points"][k][i]=mesh:Point(i).fAnimPos:GetValue(k) --store all the points/pose/positions
			end
		end
		return 
	end
	pos_selector = boneselector.fPos --position of the selector bone.	
	length = boneselector.fLength*boneselector.fAnimScale:GetValue(moho.frame) --current length of the boneselector
	for k=1, maxposes do
		w[k]=0
		posk = bone[k].fPos
		distance = posk - pos_selector
		r = distance:Mag()
		w[k]=weight(r, length)
	end
	local wtot=0.0 --total weight
	for k=1, maxposes do
		wtot =wtot +w[k]
	end
	if (wtot == 0.0) then return end
	for i=0, mesh:CountPoints()-1 do --- move the points.
		local pi=mesh:Point(i)
		local pimoved =LM.Vector2:new_local()
		pimoved:Set(0,0)
		for k=1, maxposes do
			pimoved = pimoved + poses[layer]["points"][k][i]*w[k]/wtot
		end
		pi.fPos:Set(pimoved)
	end
end

function weight (r, l)
	if (r <= l) then 
	local w =r/l-1
		--print(w)
		return w
	else
		return 0.0
	end
end
User avatar
heyvern
Posts: 7035
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

I have to agree. No change at all in performance. How disappointing. I even copied all the layers into one to cut down on the scripts/variables in memory, not a bit of difference.

This is so coooool! I so want it to work. It is interesting because I have bone scripts that run "slow" but it's "consistent". It runs the same speed all the time so you can just get use to it. The problem here is that it stops and stutters pausing sometimes for a few seconds.

I have another idea: the script still runs many times on each frame which adds to the slow down. Also the script runs continuously when you drag the bone or do anything on the screen. I am thinking to force the script to run just once on each frame AND to only run ONCE after the bone is "released" or being dragged. This should cut down on the number of times the list is accessed and the point positions are updated.

This means of course you won't see the points move as you move the bones (only after you stop dragging the bone) but... it might speed things up.

It's still the coolest script since the 3D script. :)

-vern
slice11217
Posts: 279
Joined: Thu Mar 30, 2006 6:12 pm
Location: Verona, New Jersey

Post by slice11217 »

So hey, is there anything new going on with this idea? I was following this thread for a while because it was really quite interesting. Then all of a sudden it seems to have fizzled out. What's up?
DarthFurby
Posts: 510
Joined: Sat Jul 29, 2006 1:34 pm
Location: New York City
Contact:

Post by DarthFurby »

The script freezes Anime Studio for minutes at a time, and so far no one has been able to come up with a solution. It doesn't help that there are only a very small handful of lua scripters that know how to use Anime Studio.

It's frustrating because we're so close and this script makes it SO EASY to create advanced 2d puppets that are easily manipulated to look like frame by frame animations. A single bone could potentially control all angles for head motion, even a child could use it.

I'm just hoping that some day a lua expert will ride in on his white horse to save the kingdom.
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

Hey guys!
it is very hard to debug this small piece of code because it doesn't have (probably) code bugs. The problem is that we don't have enough information about the internals of Moho core to make this code run faster or don't hang up for some amount of time.

I don't have a solution to improve it :(. If I add more features probably would run slower so it is IMHO as minimalist and fast as it can be.

Any other (scripter or not scripter) have other idea?

-G
User avatar
synthsin75
Posts: 9972
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

I don't know anything about scripting, but has anyone looked into maybe using something other than bone strength? I think Vern has a good idea. We don't really need to see the tween while editting, as long as it tweens in playback.
So why not maybe use radians of a bone's rotation. Maybe even name the actions by radians. (It's my understanding that the scripting interface uses radians internally)

Just my two cents.
slice11217
Posts: 279
Joined: Thu Mar 30, 2006 6:12 pm
Location: Verona, New Jersey

Post by slice11217 »

this could be interesting: a head rotation that's tied into the rotation of a referential bone rather than the position of the bone.

I'm curious: does ASP 5.6 offer anything that improves the performance of this script that 5.5 did not?

-S
Genete
Posts: 3483
Joined: Tue Oct 17, 2006 3:27 pm
Location: España / Spain

Post by Genete »

slice11217 wrote:this could be interesting: a head rotation that's tied into the rotation of a referential bone rather than the position of the bone.

I'm curious: does ASP 5.6 offer anything that improves the performance of this script that 5.5 did not?

-S
That could be easily done. It would work the same than the linear example I did from the DarthFurby head turn. What this one have of advantage is that you can interpolate between ANY two or more (depending its relative position) "poses" what gives interesting results for other things rather a head turn. Oh well, you can rotate also the poses bones and combine any of two poses.

Probably it would work a little more quick. Does anyone feel strong enough to modify the code and use angles instead of linear distances? :rool: ;)
-G
slice11217
Posts: 279
Joined: Thu Mar 30, 2006 6:12 pm
Location: Verona, New Jersey

Post by slice11217 »

Genete wrote: Probably it would work a little more quick. Does anyone feel strong enough to modify the code and use angles instead of linear distances? :rool: ;)
-G
Uh, I feel strongly enough about it, but alas, I cannot code. :cry:
_Trip
Posts: 5
Joined: Thu Jun 05, 2008 3:37 pm
Location: WI
Contact:

Updated Script - no memory leaks

Post by _Trip »

Genete, et al.

Thanks for the script! Have no idea when I would need it as I just use anime studio for comic book work (kindof static images, ya know? ;) )
I've only owned the software a bit over a week, but like it better than anything else - very impressive stuff!

Anyway, I did modify the script a bit to fix the memory leak that was occuring and changed a couple of the "for" loops to ensure the fastest possible interpretation. I think what I've added could be used in most all of the scripts I've seen to help with those niggling and intemittent memory leaks/speed issues.

Code: Select all

--Embed this script into all the vector layers that want to copy poses from frames 1,2,3,4, ..., maxposes
--it must be under a bone type layer and the following ROOT named bones MUST exists:

-- posek (with k form 1 to maxposes)
-- bonelesector

-- Copyright 2008 Genete
-- Released for free.
-- Thanks to Selgin for that great idea.
-- It can be extended for other animated values (curvatures, widths, shape fill colors, shape outline color, etc.)
-- Also weights w[k] can be overweigthed by the pose bone legth. It would allow some sort of variable action weights...
-- Under development...
-- Modififed June 5th, 2008:
-- Tim Fischer:  Added local variables to speed up looping (interpreted languages recalculate every iteration so a variable can be much faster)
--                        Added garbage collection routine to free memory (Auto GC doesn't appear to work).  This fixes hanging, etc

poses = {}

maxposes = 4

bone = {}
boneselector = nil

function LayerScript(moho)
	local w = {}
	local distance 
	local posk
	local pos_selector
	local r
	local length

	local k
	local layer = moho.layer
	local frame = moho.frame

	local skel = moho:ParentSkeleton()
	
	if (skel == nil) then
		print ("No parent skeleton found in layer:".. layer:Name())
		return
	end

	local mesh = moho:Mesh()
	
	if (mesh==nil) then
		print ("No mesh found in layer:".. layer:Name())
		return
	end	
	
	if (frame <=maxposes) then 
-----------------------------------look for the bones
		for k=1, maxposes do
			bone[k] = nil
			local fc1 = skel:CountBones()-1   -- added to speed up loops
			for i=0, fc1 do 
				local bonei = skel:Bone(i)
				local bonek = "pose" .. tostring(k)
				if (bonei:Name() == bonek) then
					bone[k]=bonei
				elseif (bonei:Name() == "boneselector") then
					boneselector=bonei
				end
			end	
			if (bone[k] == nil) then 
				print("bone "..k.." is missing")
				return
			end
		end
		if boneselector == nil then 
			print("boneselector is missing")
			return
		end
		collectgarbage()
---------------------------------
--------------------------------- creates a new array for the layer
		poses[layer]={} 
		poses[layer]["points"]={} 
		local fc2 = mesh:CountPoints()-1   -- added to speed up loops
		for k=1, maxposes do
			poses[layer]["points"][k]={}
			for i=0, fc2 do
				poses[layer]["points"][k][i]=mesh:Point(i).fAnimPos:GetValue(k) --store all the points/pose/positions
			end
		end
		collectgarbage()
		return 
	end
	
	pos_selector = boneselector.fPos --position of the selector bone.	
	length = boneselector.fLength*boneselector.fAnimScale:GetValue(moho.frame) --current length of the boneselector
	for k=1, maxposes do
		w[k]=0
		posk = bone[k].fPos
		distance = posk - pos_selector
		r = distance:Mag()
		w[k]=weight(r, length)
	end
	
	local wtot=0.0 --total weight
	for k=1, maxposes do
		wtot =wtot +w[k]
	end
	if (wtot == 0.0) then  return  end
	
    local fc3=mesh:CountPoints()-1  -- added to speed up loops
	for i=0, fc3 do --- move the points.
		local pi=mesh:Point(i)
		local pimoved =LM.Vector2:new_local()
		pimoved:Set(0,0)
		for k=1, maxposes do
			pimoved = pimoved + poses[layer]["points"][k][i]*w[k]/wtot
		end
		pi.fPos:Set(pimoved)
	end
	collectgarbage ()
end


function weight (r, l)
	if (r <= l) then 
	local w =r/l-1
		--print(w)
		return w
	else
		return 0.0
	end
end
Thanks again!
-Tim
Post Reply