Clone Curve Tool

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

Moderators: Víctor Paredes, Belgarath, slowtiger

Post Reply
burans
Posts: 10
Joined: Tue Jun 20, 2023 4:22 pm

Clone Curve Tool

Post by burans »

Hey!

Trying to write my first script here and am running into some issues.

What I want to achieve -
A tool that you can use to make one curve take the shape of another.

A simple example -
Lets say I have two vector layers and both of them have a single curve with 4 points inside. The curves have different point positions and curvatures. With the Layer 1 active I can use this tool to select the curve un Layer 2. By doing so the curve in Layer 1 would take the exact shape of the selected curve. The shape would be maintained identical throughout animation as the curve in Layer 2 is deformed with actions / smart bones etc.

What I have so far -
1. I've dissected the follow path tool to get the "selecting curve functionality"
2. I can loop over the points of the curve in the active layer and set their position to match the other curve

What I need help with -
1. How to correctly copy over the curvature from one curve to the other? I tried using :GetCurvature() and :SetCurvature() and that sometimes worked but mostly did not. I guess I don't fully understand how the curvature is stored/defined.

Code: Select all

local followCurvature = followCurve:GetCurvature(i)
activeCurve:SetCurvature(i,followCurvature,0)
2. How to make make the shape of the curve to be maintained throughout animation? Should the tool script somehow create a layer script? If so - how?

3. Extra question - is there a way to quickly refresh the tool script without closing Moho?

Any advice will be greatly appreciated!
Thanks!
Toms
burans
Posts: 10
Joined: Tue Jun 20, 2023 4:22 pm

Re: Clone Curve Tool

Post by burans »

Here are the guts of the script so far.
It works (the curve shape is cloned correctly) sometimes but I don't really understand how, why and why only sometimes.
1. I have closed curves with equal amount of points in layers A and B.
2. If I try to convert A into B it takes approximately correct shape sometimes
3. If I then try to convert B into A it perfectly takes the exact shape.
4. If I manually rearrange the shapes and repeat steps 1-3 the same thing happens.

Code: Select all

if (moho.frame == 0) then
		followLayer, curveID, segID = mouseEvent.view:PickGlobalEdge(mouseEvent.pt, curveID, segID)
		if (curveID >= 0) then
	
			local meshLayer = moho:LayerAsVector(followLayer)
			local mesh = meshLayer:Mesh()
			local followCurve = mesh:Curve(curveID)
			print(followLayer:Name())	

			local activeCurve = moho:Mesh():Curve(0)
			
			-- loop over activeCurve points
			for i = 0, activeCurve:CountPoints() - 1 do

				-- copy point position
				local followPoint = followCurve:Point(i)
				local activePoint = activeCurve:Point(i)

				activePoint:SetPos(followPoint.fPos,0)
				
				-- copy handles
				local handle01 = followCurve:GetControlHandle(i, 0, false)
				local handle02 = followCurve:GetControlHandle(i, 0, true)
				
				activeCurve:SetControlHandle(i, handle01, 0, false, true)
				activeCurve:SetControlHandle(i, handle02, 0, true, true)

				-- copy curvature
				local followCurvature = followCurve:GetCurvature(i)
				activeCurve:SetCurvature(i,followCurvature,0)
				
				-- Tried :ResetControlHandles but does not seem to do anything...
				-- activeCurve:ResetControlHandles(i,0) 
			end
		else
			-- nothing selected
			print('nothing selected')
		end
	end
Thanks!
Toms
burans
Posts: 10
Joined: Tue Jun 20, 2023 4:22 pm

Re: Clone Curve Tool

Post by burans »

Half way there.
Looks like the properties I need to copy over are point position, weight and offset.

Code: Select all

if (moho.frame == 0) then
		followLayer, curveID, segID = mouseEvent.view:PickGlobalEdge(mouseEvent.pt, curveID, segID)
		if (curveID >= 0) then
	
			local meshLayer = moho:LayerAsVector(followLayer)
			local mesh = meshLayer:Mesh()
			local followCurve = mesh:Curve(curveID)
			-- print(followLayer:Name())	

			local activeCurve = moho:Mesh():Curve(0)
			
			-- loop over activeCurve points
			for i = 0, activeCurve:CountPoints() - 1 do

				-- copy point position
				local followPoint = followCurve:Point(i)
				local activePoint = activeCurve:Point(i)

				activePoint:SetPos(followPoint.fPos,0)

				-- copy weight
				local weight1 = followCurve:GetWeight(i, 0, false)
				local weight2 = followCurve:GetWeight(i, 0, true)

				activeCurve:SetWeight(i, weight1, 0, false)
				activeCurve:SetWeight(i, weight2, 0, true)

				-- copy offset
				local offset1 = followCurve:GetOffset(i, 0, false)
				local offset2 = followCurve:GetOffset(i, 0, true)

				activeCurve:SetOffset(i, offset1, 0, false)
				activeCurve:SetOffset(i, offset2, 0, true)
				
			end
		else
			-- nothing selected
			print('nothing selected')
		end
	end
Now I need to figure out how to do this for every frame so curve B moves together with A as A is animated with smart actions.
User avatar
hayasidist
Posts: 3525
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Clone Curve Tool

Post by hayasidist »

just out of curiosity -- why? A bit more on the background to the effect you're trying to achieve might point to a different solution.

---
in any event:
> are A and B in the same group / bone layer?
> would a copy by ref do what you wanted?
> or, as you've mentioned, a layerscript? (https://mohoscripting.com/script_structure -- and scroll down to the section on layerscripts)

---

to answer 3: shift-ctrl-alt-L reloads Moho 12.x, 13.5.x (IOW all versions except 13.0.x)
burans
Posts: 10
Joined: Tue Jun 20, 2023 4:22 pm

Re: Clone Curve Tool

Post by burans »

Thanks for the reply @hayasidist!
hayasidist wrote: Tue Jul 04, 2023 1:43 pm just out of curiosity -- why? A bit more on the background to the effect you're trying to achieve might point to a different solution.
Idea for this came from a frustration of not being able to achieve a specific design - multiple overlapping strokes that follow the same basic path but have different stroke exposures / line width / color points etc. I tried to achieve this by welding two paths together but found the results to be very... unpredictable.
hayasidist wrote: Tue Jul 04, 2023 1:43 pm > are A and B in the same group / bone layer?
In this specific case - yes. But i think this should work with any layer structure.
hayasidist wrote: Tue Jul 04, 2023 1:43 pm > would a copy by ref do what you wanted?
Not sure what "copy by ref" is, but I assume that would include things like stroke exposure and line width - things that I want to be different between the two layers/shapes.

I managed to put together a layerscript that i think works. (have to do testing with smart bones etc)

Code: Select all

function LayerScript(moho)

	if (moho:Mesh() == nil) then
		print("No mesh found in layer:", moho.layer:Name())
		return
	end

	local doc = moho.document
	local sourceLayer = doc:LayerByName('layer to follow')
	
	local meshLayer = moho:LayerAsVector(sourceLayer)
	local mesh = meshLayer:Mesh()
	local followCurve = mesh:Curve(0)

	local activeCurve = moho:Mesh():Curve(0)
	
	-- loop over activeCurve points
	for i = 0, activeCurve:CountPoints() - 1 do

		-- copy point position
		local followPoint = followCurve:Point(i)
		local activePoint = activeCurve:Point(i)

		activePoint:SetPos(followPoint.fPos,moho.frame)

		-- copy weight
		local weight1 = followCurve:GetWeight(i, moho.frame, false)
		local weight2 = followCurve:GetWeight(i, moho.frame, true)

		activeCurve:SetWeight(i, weight1, moho.frame, false)
		activeCurve:SetWeight(i, weight2, moho.frame, true)

		-- copy offset
		local offset1 = followCurve:GetOffset(i, moho.frame, false)
		local offset2 = followCurve:GetOffset(i, moho.frame, true)

		activeCurve:SetOffset(i, offset1, moho.frame, false)
		activeCurve:SetOffset(i, offset2, moho.frame, true)
	
	end
end
Some questions about the layer script:
1. The layer that has the scrip applied gets keyframes automatically created on each frame. Is that the normal/expected/preferred result?
2. How do I create this layer script automatically with a tool? Ie - set the "layer to follow" by selecting the path in the canvas not hard coding it.

Thanks!
Toms
burans
Posts: 10
Joined: Tue Jun 20, 2023 4:22 pm

Re: Clone Curve Tool

Post by burans »

Nice.
Accidentally found Meshinstance script by A.Evseeva and it looks like it does exactly what I need.
https://mohoscripts.com/script/ae_meshinstance_tool

I was looking forward to building it out myself but oh well... :)
Post Reply