Image
-- **************************************************
-- Provide Moho with the name of this script object
-- **************************************************

ScriptName = "AE_WalkCycle"

-- **************************************************
-- General information about this script
-- **************************************************

AE_WalkCycle = {}

function AE_WalkCycle:Name()
	return 'Walk Cycle'
end

function AE_WalkCycle:Version()
	return '1.0'
end

function AE_WalkCycle:UILabel()
	return 'Walk Cycle'
end

function AE_WalkCycle:Creator()
	return 'Alexandra Evseeva'
end

function AE_WalkCycle:Description()
	return 'Additive walk from PlayStart to PlayEnd'
end


-- **************************************************
-- Is Relevant / Is Enabled
-- **************************************************

function AE_WalkCycle:IsRelevant(moho)
	return true
end

function AE_WalkCycle:IsEnabled(moho)
	return true
end

-- **************************************************
-- The guts of this script
-- **************************************************

function AE_WalkCycle:Run(moho)
	moho.document:SetDirty()
	moho.document:PrepUndo(nil)
	
	local skel = moho:Skeleton()
	if not skel then return LM.GUI.Alert(LM.GUI.ALERT_WARNING, "Skeleton not found") end
	local skelLayer = moho.layer:ControllingBoneLayer() or moho.layer
	
	local startFrame = MOHO.MohoGlobals.PlayStart
	if startFrame == -1 then startFrame = 1 end
	startFrame = startFrame + skelLayer:TotalTimingOffset()
	local endFrame = MOHO.MohoGlobals.PlayEnd
	if endFrame == -1 then endFrame = moho.frame end
	endFrame = endFrame + skelLayer:TotalTimingOffset()
	local centerFrame = (endFrame + startFrame)/2
	
	local rootBones = {}
	for b = 0, skel:CountBones() - 1 do
		local bone = skel:Bone(b)
		if bone.fAnimParent.value == -1 and not bone.fHidden then table.insert(rootBones, bone) end
	end
	
	local addValue = LM.Vector2:new_local()
	local selBone = skel:Bone(skel:SelectedBoneID())
		if not selBone or selBone.fAnimParent.value > -1 then
		local midValue = LM.Vector2:new_local()
		for i, bone in pairs(rootBones) do
			local dist = bone.fAnimPos:GetValue(centerFrame) - bone.fAnimPos:GetValue(startFrame)
			midValue = midValue + dist
		end
		midValue = midValue / #rootBones
		local minDist = math.huge
		for i, bone in pairs(rootBones) do 
			local dist = bone.fAnimPos:GetValue(centerFrame) - bone.fAnimPos:GetValue(startFrame)
			local distDelta = (dist - midValue):Mag()
			if distDelta < minDist then minDist, addValue = distDelta, dist end
		end
		addValue = addValue * 2
	else 
		addValue = selBone.fAnimPos:GetValue(endFrame) - selBone.fAnimPos:GetValue(startFrame)
	end
	
	local interp = MOHO.InterpSetting:new_local()
	interp.interpMode = MOHO.INTERP_CYCLE
	interp.val1 = -1
	interp.val2 = startFrame + 1
	
	for j, i, channel, chInfo in AE_Utilities:IterateAllChannels(moho, skelLayer) do
		channel = AE_Utilities:GetDerivedChannel(moho, channel, true)
		if channel and channel:Duration() > startFrame then
			local startVal = channel:GetValue(startFrame)
			channel:SetValue(startFrame, startVal)
			channel:SetValue(endFrame, startVal)
			channel:SetKeyInterp(endFrame, interp)
		end
	end
	
	interp:SetAdditiveCycle(true)
	for i, bone in pairs(rootBones) do
		local startVal = bone.fAnimPos:GetValue(startFrame)
		local endVal = startVal + addValue
		bone.fAnimPos:SetValue(endFrame, endVal)
		bone.fAnimPos:SetKeyInterp(endFrame, interp)
	end
	
	
end

Additive Walk Cycle
Listed

Script type: Button/Menu

Uploaded: Apr 09 2022, 12:40

Script Version: 1.0

Create additive walk cycle for a bone layer
Select start and end frames with green and red markers (playstart and playend), or, by default, start is 1 and end is current frame. Select a non-parented bone whish position at end frame is just what You wanted. With no bones selected the added part of root bones' movement will be calculated approximately.


Installation Options:

This script, and all other scripts on this site are distributed as free software under the GNU General Public License 3.0 or later.
Downloads count: 1464