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

ScriptName = "MR_ContinueAnimation"

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

MR_ContinueAnimation = {}

function MR_ContinueAnimation:Name()
	return self:Localize('UILabel')
end

function MR_ContinueAnimation:Version()
	return '1.1'
end

function MR_ContinueAnimation:UILabel()
	return self:Localize('UILabel')
end

function MR_ContinueAnimation:Creator()
	return 'Eugene Babich'
end

function MR_ContinueAnimation:Description()
	return self:Localize('Description')
end


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

function MR_ContinueAnimation:IsRelevant(moho)
	return true
end

function MR_ContinueAnimation:IsEnabled(moho)
	return true
end

-- **************************************************
-- Recurring Values
-- **************************************************

MR_ContinueAnimation.singleFirstFrameProtection = true
MR_ContinueAnimation.useTranslate = true
MR_ContinueAnimation.useAngle = false
MR_ContinueAnimation.useScale = false
MR_ContinueAnimation.useCurvature = false
MR_ContinueAnimation.showBezierHandles = false
MR_ContinueAnimation.continueFromRight = false
MR_ContinueAnimation.transformLayer = false
MR_ContinueAnimation.selRect = LM.Rect:new_local()

-- **************************************************
-- Prefs
-- **************************************************

function MR_ContinueAnimation:LoadPrefs(prefs)
	self.useTranslate = prefs:GetBool("MR_ContinueAnimation.useTranslate", true)
	self.useAngle = prefs:GetBool("MR_ContinueAnimation.useAngle", false)
	self.useScale = prefs:GetBool("MR_ContinueAnimation.useScale", false)
	self.useCurvature = prefs:GetBool("MR_ContinueAnimation.useCurvature", false)
	self.showBezierHandles = prefs:GetBool("MR_ContinueAnimation.showBezierHandles", false)
	self.continueFromRight = prefs:GetBool("MR_ContinueAnimation.continueFromRight", false)
	self.transformLayer = prefs:GetBool("MR_ContinueAnimation.transformLayer", false)
end

function MR_ContinueAnimation:SavePrefs(prefs)
	prefs:SetBool("MR_ContinueAnimation.useTranslate", self.useTranslate)
	prefs:SetBool("MR_ContinueAnimation.useAngle", self.useAngle)
	prefs:SetBool("MR_ContinueAnimation.useScale", self.useScale)
	prefs:SetBool("MR_ContinueAnimation.useCurvature", self.useCurvature)
	prefs:SetBool("MR_ContinueAnimation.showBezierHandles", self.showBezierHandles)
	prefs:SetBool("MR_ContinueAnimation.continueFromRight", self.continueFromRight)
	prefs:SetBool("MR_ContinueAnimation.transformLayer", self.transformLayer)
end

function MR_ContinueAnimation:ResetPrefs()
	self.useTranslate = true
	self.useAngle = false
	self.useScale = false
	self.useCurvature = false
	self.showBezierHandles = false
	self.continueFromRight = false
	self.transformLayer = false
end

-- **************************************************
-- Keyboard/Mouse Control
-- **************************************************

function MR_ContinueAnimation:OnMouseDown(moho, mouseEvent)
	local mesh = moho:DrawingMesh()
	local skel = moho:Skeleton()
	
	if moho.layer:LayerType() == MOHO.LT_VECTOR then	
		if (mesh == nil) then
			return
		end
	else 
		if (skel == nil) then
			return
		end
	end

	self.isMouseDragging = true
	if not mouseEvent.shiftKey and not mouseEvent.altKey and mesh ~= nil then
		mesh:SelectNone()
	end
	
	if not mouseEvent.shiftKey and not mouseEvent.altKey and skel ~= nil then
		skel:SelectNone()
	end
	
	self.selRect.left = mouseEvent.startPt.x
	self.selRect.top = mouseEvent.startPt.y
	self.selRect.right = mouseEvent.pt.x
	self.selRect.bottom = mouseEvent.pt.y
	mouseEvent.view:Graphics():SelectionRect(self.selRect)
	mouseEvent.view:DrawMe()
end

function MR_ContinueAnimation:OnMouseMoved(moho, mouseEvent)
	local mesh = moho:DrawingMesh()
	local skel = moho:Skeleton()
	
	if moho.layer:LayerType() == MOHO.LT_VECTOR then	
		if (mesh == nil) then
			return
		end
	else 
		if (skel == nil) then
			return
		end
	end

	mouseEvent.view:Graphics():SelectionRect(self.selRect)
	self.selRect.right = mouseEvent.pt.x
	self.selRect.bottom = mouseEvent.pt.y
	mouseEvent.view:Graphics():SelectionRect(self.selRect)
	mouseEvent.view:RefreshView()
	mouseEvent.view:DrawMe()
end

function MR_ContinueAnimation:OnMouseUp(moho, mouseEvent)
	local mesh = moho:DrawingMesh()
	local skel = moho:Skeleton()
	
	if moho.layer:LayerType() == MOHO.LT_VECTOR then	
		if (mesh == nil) then
			return
		end
	else 
		if (skel == nil) then
			return
		end
	end

	local mouseDist = math.abs(mouseEvent.pt.x - mouseEvent.startPt.x) + math.abs(mouseEvent.pt.y - mouseEvent.startPt.y)

	self.isMouseDragging = false

	local v = LM.Vector2:new_local()
	local screenPt = LM.Point:new_local()
	local m = LM.Matrix:new_local()

	self.selRect:Normalize()
	moho.drawingLayer:GetFullTransform(moho.frame, m, moho.document)
	if moho.layer:LayerType() == MOHO.LT_VECTOR then
		for i = 0, mesh:CountPoints() - 1 do
			local pt = mesh:Point(i)
			if (not pt.fHidden) then
				v:Set(pt.fPos)
				m:Transform(v)
				mouseEvent.view:Graphics():WorldToScreen(v, screenPt)
				if (self.selRect:Contains(screenPt)) then
					if mouseEvent.altKey then
						pt.fSelected = false
					else
						pt.fSelected = true
					end
				end
			end
		end
	elseif	moho.layer:LayerType() == MOHO.LT_BONE then
		if (skel ~= nil) then
			for i = 0, skel:CountBones() - 1 do
				local bone = skel:Bone(i)
				local boneMatrix = bone.fMovedMatrix
				for j = 0, 10 do
					v:Set(bone.fLength * j / 10.0, 0)
					boneMatrix:Transform(v)
					m:Transform(v)
					mouseEvent.view:Graphics():WorldToScreen(v, screenPt)
					if (self.selRect:Contains(screenPt)) then
						if (mouseEvent.altKey) then
							bone.fSelected = false
						else
							bone.fSelected = true
						end
						break
					end
				end
			end
		end
	end
	moho:UpdateSelectedChannels()
end

function MR_ContinueAnimation:DrawMe(moho, view)
	if self.isMouseDragging then
		local g = view:Graphics()
		g:SelectionRect(self.selRect)
	end
	
	-- Draw bezier handles
	if AE_Utilities then
		if (self.showBezierHandles and self.useCurvature) then
			local mesh = moho:DrawingMesh()
			if (mesh == nil) then
				return
			end
			
			local g = view:Graphics()
			local layerMatrix = LM.Matrix:new_local()
			moho.drawingLayer:GetFullTransform(moho.frame, layerMatrix, moho.document)
			g:Push()
			g:ApplyMatrix(layerMatrix)
			g:SetSmoothing(true)
			
			local meshLayer = moho:LayerAsVector(moho.drawingLayer)
			if (moho:CountSelectedPoints() > 0) then
				meshLayer:DrawHandles(moho.document, g, true)
			else	
				meshLayer:DrawHandles(moho.document, g, false)
			end
			
			g:Pop()
		end
	end
end

-- **************************************************
-- Tool Panel Layout
-- **************************************************

MR_ContinueAnimation.USE_POSITION = MOHO.MSG_BASE
MR_ContinueAnimation.USE_POSITION_ALT = MOHO.MSG_BASE + 1
MR_ContinueAnimation.USE_ANGLE = MOHO.MSG_BASE + 2
MR_ContinueAnimation.USE_ANGLE_ALT = MOHO.MSG_BASE + 3
MR_ContinueAnimation.USE_SCALE = MOHO.MSG_BASE + 4
MR_ContinueAnimation.USE_SCALE_ALT = MOHO.MSG_BASE + 5
MR_ContinueAnimation.CONTINUE = MOHO.MSG_BASE + 6
MR_ContinueAnimation.CONTINUE_ALT = MOHO.MSG_BASE + 7
MR_ContinueAnimation.CONTINUE_FROM_RIGHT = MOHO.MSG_BASE + 8
MR_ContinueAnimation.TRANSFORM_LAYER = MOHO.MSG_BASE + 9
MR_ContinueAnimation.USE_CURVATURE = MOHO.MSG_BASE + 10
MR_ContinueAnimation.USE_CURVATURE_ALT = MOHO.MSG_BASE + 11
MR_ContinueAnimation.SHOW_BEZIER = MOHO.MSG_BASE + 12

function MR_ContinueAnimation:DoLayout(moho, layout)
	self.extendButton = LM.GUI.Button(self:Localize('Continue'), self.CONTINUE)
    layout:AddChild(self.extendButton, LM.GUI.ALIGN_LEFT, 0)
	self.extendButton:SetAlternateMessage(self.CONTINUE_ALT)
    self.extendButton:SetToolTip(self:Localize('Continue Animation'))
	
	layout:AddPadding(3)
	
	self.transformLayerCheckbox = LM.GUI.ImageButton('ScriptResources/mr_continue_animation/mr_transfrorm_layer', self:Localize('Transform Layer Tooltip'), true, self.TRANSFORM_LAYER, false)
	layout:AddChild(self.transformLayerCheckbox, LM.GUI.ALIGN_LEFT, 0)
	
	layout:AddPadding(3)
	
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	if AE_Utilities then
		self.curvatureButton = LM.GUI.ImageButton('ScriptResources/mr_continue_animation/mr_curvature', self:Localize('Continue Curvature'), true, self.USE_CURVATURE, false)
		self.curvatureButton:SetAlternateMessage(self.USE_CURVATURE_ALT)
		layout:AddChild(self.curvatureButton, LM.GUI.ALIGN_LEFT, 0)
		
		self.showBezierHandlesCheckbox = LM.GUI.ImageButton('ScriptResources/mr_continue_animation/mr_show_bezier_handles', self:Localize('Show Bezier Handles'), true, self.SHOW_BEZIER, false)
		layout:AddChild(self.showBezierHandlesCheckbox, LM.GUI.ALIGN_LEFT, 0)
		
		layout:AddPadding(2)
	end
	
	self.positionButton = LM.GUI.ImageButton('ScriptResources/mr_continue_animation/mr_translate', self:Localize('Continue Position'), true, self.USE_POSITION, false)
	self.positionButton:SetAlternateMessage(self.USE_POSITION_ALT)
	layout:AddChild(self.positionButton, LM.GUI.ALIGN_LEFT, 0)

	self.angleButton = LM.GUI.ImageButton('ScriptResources/mr_continue_animation/mr_rotate', self:Localize('Continue Angle'), true, self.USE_ANGLE, false)
	self.angleButton:SetAlternateMessage(self.USE_ANGLE_ALT)
	layout:AddChild(self.angleButton, LM.GUI.ALIGN_LEFT, 0)

	self.scaleButton = LM.GUI.ImageButton('ScriptResources/mr_continue_animation/mr_scale', self:Localize('Continue Scale'), true, self.USE_SCALE, false)
	self.scaleButton:SetAlternateMessage(self.USE_SCALE_ALT)
	layout:AddChild(self.scaleButton, LM.GUI.ALIGN_LEFT, 0)
	
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	layout:AddPadding(3)
	
	self.continueFromRightCheckbox = LM.GUI.ImageButton('ScriptResources/mr_continue_animation/mr_continue_from_right', self:Localize('Continue From Right Tooltip'), true, self.CONTINUE_FROM_RIGHT, false)
	layout:AddChild(self.continueFromRightCheckbox, LM.GUI.ALIGN_LEFT, 0)
end

function MR_ContinueAnimation:UpdateWidgets(moho)
	local mesh = moho:DrawingMesh()
	self.positionButton:SetValue(self.useTranslate)
	self.angleButton:SetValue(self.useAngle)
	self.scaleButton:SetValue(self.useScale)
	
	if AE_Utilities then
		self.curvatureButton:SetValue(self.useCurvature)
		self.showBezierHandlesCheckbox:SetValue(self.showBezierHandles)
	end
	
	self.continueFromRightCheckbox:SetValue(self.continueFromRight)
	self.transformLayerCheckbox:SetValue(self.transformLayer)
	local skel = moho:Skeleton()
	if skel == nil and not self.transformLayer and mesh == nil then
		self.positionButton:Enable(false)
		self.angleButton:Enable(false)
		self.scaleButton:Enable(false)
		self.extendButton:Enable(false)
		self.continueFromRightCheckbox:Enable(false)
		if AE_Utilities then
			self.curvatureButton:Enable(false)
			self.showBezierHandlesCheckbox:Enable(false)
		end
	elseif skel ~= nil and not self.transformLayer then	
		self.positionButton:Enable(true)
		self.angleButton:Enable(true)
		self.scaleButton:Enable(true)
		self.extendButton:Enable(true)
		self.continueFromRightCheckbox:Enable(true)
		if AE_Utilities then
			self.curvatureButton:Enable(false)
			self.showBezierHandlesCheckbox:Enable(false)
		end
	elseif mesh ~= nil and not self.transformLayer then
		self.positionButton:Enable(true)
		self.angleButton:Enable(false)
		self.scaleButton:Enable(false)
		self.extendButton:Enable(true)
		if AE_Utilities then
			self.curvatureButton:Enable(true)
			self.showBezierHandlesCheckbox:Enable(self.useCurvature)
		end
	elseif self.transformLayer then
		self.positionButton:Enable(true)
		self.angleButton:Enable(true)
		self.scaleButton:Enable(true)
		self.extendButton:Enable(true)
		self.continueFromRightCheckbox:Enable(true)
		if AE_Utilities then
			self.curvatureButton:Enable(false)
			self.showBezierHandlesCheckbox:Enable(false)
		end
	end
	if moho.frame == 0 then
		self.positionButton:Enable(false)
		self.angleButton:Enable(false)
		self.scaleButton:Enable(false)
		self.extendButton:Enable(false)
		self.continueFromRightCheckbox:Enable(false)
		self.transformLayerCheckbox:Enable(false)
		if AE_Utilities then
			self.curvatureButton:Enable(false)
			self.showBezierHandlesCheckbox:Enable(false)
		end
	end
end

function MR_ContinueAnimation:HandleMessage(moho, view, msg)
	if msg == self.CONTINUE then
		if self.transformLayer then
			moho.document:SetDirty()
			moho.document:PrepUndo(moho.layer)
			if self.useTranslate then
				if moho.layer.fTranslation:AreDimensionsSplit() then
					self:ContinueAnimationChannel(moho, moho.layer.fTranslation:DimensionChannel(0), 1)
					self:ContinueAnimationChannel(moho, moho.layer.fTranslation:DimensionChannel(1), 1)
					self:ContinueAnimationChannel(moho, moho.layer.fTranslation:DimensionChannel(2), 1)
				else	
					self:ContinueAnimationChannel(moho, moho.layer.fTranslation, 3)
				end
				moho:NewKeyframe(CHANNEL_LAYER_T)
			end	
			if self.useAngle then
				self:ContinueAnimationChannel(moho, moho.layer.fRotationX, 1)
				self:ContinueAnimationChannel(moho, moho.layer.fRotationY, 1)
				self:ContinueAnimationChannel(moho, moho.layer.fRotationZ, 1)
				moho:NewKeyframe(CHANNEL_LAYER_ROT_X)
				moho:NewKeyframe(CHANNEL_LAYER_ROT_Y)
				moho:NewKeyframe(CHANNEL_LAYER_ROT_Z)
			end
			if self.useScale then
				if moho.layer.fScale:AreDimensionsSplit() then
					self:ContinueAnimationChannel(moho, moho.layer.fScale:DimensionChannel(0), 1)
					self:ContinueAnimationChannel(moho, moho.layer.fScale:DimensionChannel(1), 1)
					self:ContinueAnimationChannel(moho, moho.layer.fScale:DimensionChannel(2), 1)
				else	
					self:ContinueAnimationChannel(moho, moho.layer.fScale, 3)
				end
				moho:NewKeyframe(CHANNEL_LAYER_S)
			end
		else
			local mesh = moho:DrawingMesh()
			local skel = moho:Skeleton()
			if mesh ~= nil and moho:CountSelectedPoints() > 0 then
				moho.document:SetDirty()
				moho.document:PrepUndo(moho.layer)
				if self.useTranslate then
					self:ContinuePointsPosition(moho)
					moho:NewKeyframe(CHANNEL_POINT)
				end
				if self.useCurvature and AE_Utilities then
					self:ContinueCurvature(moho)
					moho:NewKeyframe(CHANNEL_CURVE)
				end	
			elseif skel ~= nil and moho:CountSelectedBones() > 0 then
				moho.document:SetDirty()
				moho.document:PrepUndo(moho.layer)
				if self.useTranslate then
					self:ContinueBonesPosition(moho)
					moho:NewKeyframe(CHANNEL_BONE_T)
				end	
				if self.useAngle then
					self:ContinueBonesRotation(moho)
					moho:NewKeyframe(CHANNEL_BONE)
				end
				if self.useScale then
					self:ContinueBonesScale(moho)
					moho:NewKeyframe(CHANNEL_BONE_S)
				end
			end
		end	
		moho:UpdateSelectedChannels()
		moho.layer:UpdateCurFrame()
		moho:UpdateUI()
	elseif msg == self.CONTINUE_ALT then
		if self.transformLayer then
			moho.document:SetDirty()
			moho.document:PrepUndo(moho.layer)
			if moho.layer.fTranslation:AreDimensionsSplit() then
				self:ContinueAnimationChannel(moho, moho.layer.fTranslation:DimensionChannel(0), 1)
				self:ContinueAnimationChannel(moho, moho.layer.fTranslation:DimensionChannel(1), 1)
				self:ContinueAnimationChannel(moho, moho.layer.fTranslation:DimensionChannel(2), 1)
			else	
				self:ContinueAnimationChannel(moho, moho.layer.fTranslation, 3)
			end
			moho:NewKeyframe(CHANNEL_LAYER_T)
			self:ContinueAnimationChannel(moho, moho.layer.fRotationX, 1)
			self:ContinueAnimationChannel(moho, moho.layer.fRotationY, 1)
			self:ContinueAnimationChannel(moho, moho.layer.fRotationZ, 1)
			moho:NewKeyframe(CHANNEL_LAYER_ROT_X)
			moho:NewKeyframe(CHANNEL_LAYER_ROT_Y)
			moho:NewKeyframe(CHANNEL_LAYER_ROT_Z)
			if moho.layer.fScale:AreDimensionsSplit() then
				self:ContinueAnimationChannel(moho, moho.layer.fScale:DimensionChannel(0), 1)
				self:ContinueAnimationChannel(moho, moho.layer.fScale:DimensionChannel(1), 1)
				self:ContinueAnimationChannel(moho, moho.layer.fScale:DimensionChannel(2), 1)
			else	
				self:ContinueAnimationChannel(moho, moho.layer.fScale, 3)
			end
			moho:NewKeyframe(CHANNEL_LAYER_S)
		else
			local mesh = moho:DrawingMesh()
			local skel = moho:Skeleton()
			if mesh ~= nil and moho:CountSelectedPoints() > 0 then
				moho.document:SetDirty()
				moho.document:PrepUndo(moho.layer)
				self:ContinuePointsPosition(moho)
				moho:NewKeyframe(CHANNEL_POINT)
				if AE_Utilities then
					self:ContinueCurvature(moho)
					moho:NewKeyframe(CHANNEL_CURVE)
				end
			elseif skel ~= nil and moho:CountSelectedBones() > 0 then
				moho.document:SetDirty()
				moho.document:PrepUndo(moho.layer)
				self:ContinueBonesPosition(moho)
				moho:NewKeyframe(CHANNEL_BONE_T)
				self:ContinueBonesRotation(moho)
				moho:NewKeyframe(CHANNEL_BONE)
				self:ContinueBonesScale(moho)
				moho:NewKeyframe(CHANNEL_BONE_S)
			end
		end	
		moho:UpdateSelectedChannels()
		moho.layer:UpdateCurFrame()
		moho:UpdateUI()
	elseif msg == self.USE_CURVATURE then
		self.useCurvature = self.curvatureButton:Value()
		self:UpdateWidgets(moho)
	elseif msg == self.USE_CURVATURE_ALT then
		local mesh = moho:DrawingMesh()
		if mesh ~= nil and moho:CountSelectedPoints() > 0 then
			moho.document:SetDirty()
			moho.document:PrepUndo(moho.layer)
			self:ContinueCurvature(moho)
			moho:NewKeyframe(CHANNEL_CURVE)
			moho:UpdateSelectedChannels()
			moho.layer:UpdateCurFrame()
			moho:UpdateUI()
		end
	elseif msg == self.SHOW_BEZIER then
		self.showBezierHandles = self.showBezierHandlesCheckbox:Value()
		self:UpdateWidgets(moho)	
	elseif msg == self.USE_POSITION then
		self.useTranslate = self.positionButton:Value()
		self:UpdateWidgets(moho)
	elseif msg == self.USE_POSITION_ALT then
		if self.transformLayer then
			moho.document:SetDirty()
			moho.document:PrepUndo(moho.layer)
			if moho.layer.fTranslation:AreDimensionsSplit() then
				self:ContinueAnimationChannel(moho, moho.layer.fTranslation:DimensionChannel(0), 1)
				self:ContinueAnimationChannel(moho, moho.layer.fTranslation:DimensionChannel(1), 1)
				self:ContinueAnimationChannel(moho, moho.layer.fTranslation:DimensionChannel(2), 1)
			else	
				self:ContinueAnimationChannel(moho, moho.layer.fTranslation, 3)
			end
			moho:NewKeyframe(CHANNEL_LAYER_T)
		else
			local mesh = moho:DrawingMesh()
			local skel = moho:Skeleton()
			if mesh ~= nil and moho:CountSelectedPoints() > 0 then
				moho.document:SetDirty()
				moho.document:PrepUndo(moho.layer)
				self:ContinuePointsPosition(moho)
				moho:NewKeyframe(CHANNEL_POINT)
			elseif skel ~= nil and moho:CountSelectedBones() > 0 then
				moho.document:SetDirty()
				moho.document:PrepUndo(moho.layer)
				self:ContinueBonesPosition(moho)
				moho:NewKeyframe(CHANNEL_BONE_T)
			end
		end	
		moho:UpdateSelectedChannels()
		moho.layer:UpdateCurFrame()
		moho:UpdateUI()
	elseif msg == self.USE_ANGLE then
		self.useAngle = self.angleButton:Value()
		self:UpdateWidgets(moho)
	elseif msg == self.USE_ANGLE_ALT then
		if self.transformLayer then
			moho.document:SetDirty()
			moho.document:PrepUndo(moho.layer)
			self:ContinueAnimationChannel(moho, moho.layer.fRotationX, 1)
			self:ContinueAnimationChannel(moho, moho.layer.fRotationY, 1)
			self:ContinueAnimationChannel(moho, moho.layer.fRotationZ, 1)
			moho:NewKeyframe(CHANNEL_LAYER_ROT_X)
			moho:NewKeyframe(CHANNEL_LAYER_ROT_Y)
			moho:NewKeyframe(CHANNEL_LAYER_ROT_Z)
		else
			local skel = moho:Skeleton()
			if skel ~= nil and moho:CountSelectedBones() > 0 then
				moho.document:SetDirty()
				moho.document:PrepUndo(moho.layer)
				self:ContinueBonesRotation(moho)
				moho:NewKeyframe(CHANNEL_BONE)
			end
		end	
		moho:UpdateSelectedChannels()
		moho.layer:UpdateCurFrame()
		moho:UpdateUI()
	elseif msg == self.USE_SCALE then
		self.useScale = self.scaleButton:Value()
		self:UpdateWidgets(moho)
	elseif msg == self.USE_SCALE_ALT then
		if self.transformLayer then
			moho.document:SetDirty()
			moho.document:PrepUndo(moho.layer)
			if moho.layer.fScale:AreDimensionsSplit() then
				self:ContinueAnimationChannel(moho, moho.layer.fScale:DimensionChannel(0), 1)
				self:ContinueAnimationChannel(moho, moho.layer.fScale:DimensionChannel(1), 1)
				self:ContinueAnimationChannel(moho, moho.layer.fScale:DimensionChannel(2), 1)
			else	
				self:ContinueAnimationChannel(moho, moho.layer.fScale, 3)
			end
			moho:NewKeyframe(CHANNEL_LAYER_S)
		else
			local skel = moho:Skeleton()
			if skel ~= nil and moho:CountSelectedBones() > 0 then
				moho.document:SetDirty()
				moho.document:PrepUndo(moho.layer)
				self:ContinueBonesScale(moho)
				moho:NewKeyframe(CHANNEL_BONE_S)
			end
		end	
		moho:UpdateSelectedChannels()
		moho.layer:UpdateCurFrame()
		moho:UpdateUI()
	elseif msg == self.CONTINUE_FROM_RIGHT then
		self.continueFromRight = self.continueFromRightCheckbox:Value()
		self:UpdateWidgets(moho)	
	elseif msg == self.TRANSFORM_LAYER then	
		self.transformLayer = self.transformLayerCheckbox:Value()
		self:UpdateWidgets(moho)
	end
end

function MR_ContinueAnimation:ContinueCurvature(moho)
	local mesh = moho:DrawingMesh()
	for j = 0, mesh:CountPoints() - 1 do
		local point = mesh:Point(j)
		if point.fSelected then
			for c = 0, point:CountCurves() - 1 do
				local myCurve, where = point:Curve(c, -1)
				local curvatureChannel = myCurve:Curvature(where)
				local curvatureOffsetChannel1 = AE_Utilities:GetOffsetChannel(moho, moho.layer, myCurve, where, false)
				local curvatureOffsetChannel2 = AE_Utilities:GetOffsetChannel(moho, moho.layer, myCurve, where, true)
				local curvatureWeightChannel1 = AE_Utilities:GetWeightChannel(moho, moho.layer, myCurve, where, false)
				local curvatureWeightChannel2 = AE_Utilities:GetWeightChannel(moho, moho.layer, myCurve, where, true)
				self:ContinueAnimationChannel(moho, curvatureChannel, 1)
				self:ContinueAnimationChannel(moho, curvatureOffsetChannel1, 1)
				self:ContinueAnimationChannel(moho, curvatureOffsetChannel2, 1)
				self:ContinueAnimationChannel(moho, curvatureWeightChannel1, 1)
				self:ContinueAnimationChannel(moho, curvatureWeightChannel2, 1)
			end
		end	
	end
end

function MR_ContinueAnimation:ContinuePointsPosition(moho)
	local mesh = moho:DrawingMesh()
	if mesh == nil then
		return
	end
	
	for i = 0, mesh:CountPoints() - 1 do
		local pt = mesh:Point(i)
		if pt.fSelected then
			if pt.fAnimPos:AreDimensionsSplit() then
				self:ContinueAnimationChannel(moho, pt.fAnimPos:DimensionChannel(0), 1)
				self:ContinueAnimationChannel(moho, pt.fAnimPos:DimensionChannel(1), 1)
			else	
				self:ContinueAnimationChannel(moho, pt.fAnimPos, 2)
			end
		end	
	end
end

function MR_ContinueAnimation:ContinueBonesPosition(moho)
	local skel = moho:Skeleton()
	if skel == nil then
		return
	end
		
	for i = 0, skel:CountBones() - 1 do
		local bone = skel:Bone(i)
		if bone.fSelected then
			if bone.fAnimPos:AreDimensionsSplit() then
				self:ContinueAnimationChannel(moho, bone.fAnimPos:DimensionChannel(0), 1)
				self:ContinueAnimationChannel(moho, bone.fAnimPos:DimensionChannel(1), 1)
			else	
				self:ContinueAnimationChannel(moho, bone.fAnimPos, 2)
			end
		end	
	end
end

function MR_ContinueAnimation:ContinueBonesRotation(moho)
	local skel = moho:Skeleton()
	if skel == nil then
		return
	end
		
	for i = 0, skel:CountBones() - 1 do
		local bone = skel:Bone(i)
		if bone.fSelected then
			self:ContinueAnimationChannel(moho, bone.fAnimAngle, 1)
		end	
	end
end

function MR_ContinueAnimation:ContinueBonesScale(moho)
	local skel = moho:Skeleton()
	if skel == nil then
		return
	end

	for i = 0, skel:CountBones() - 1 do
		local bone = skel:Bone(i)
		if bone.fSelected then
			self:ContinueAnimationChannel(moho, bone.fAnimScale, 1)	
		end	
	end
end

function MR_ContinueAnimation:ContinueAnimationChannel(moho, channel, channelType)
	-- channelType 1 = AnimVal, 2 = Vector2, 3 = Vector3
	local newValue
	local valueDif
	local averageFrameValue
	if channelType == 1 then
	elseif channelType == 2 then
		newValue = LM.Vector2:new_local()
		valueDif = LM.Vector2:new_local()
		averageFrameValue = LM.Vector2:new_local()
	elseif channelType == 3 then
		newValue = LM.Vector3:new_local()
		valueDif = LM.Vector3:new_local()
		averageFrameValue = LM.Vector3:new_local()
	end	
	local keyId = 0
	if self.continueFromRight then
		keyId = channel:GetClosestKeyID(moho.layerFrame)
	else
		keyId = channel:GetClosestKeyID(moho.layerFrame -1)
	end	
	if keyId -1 >= 0 and not self.continueFromRight then
		local targetFrame1 = channel:GetKeyWhen(keyId - 1)
		local targetFrame2 = channel:GetKeyWhen(keyId)
		if targetFrame1 == 0 and targetFrame2 == 1 and self.singleFirstFrameProtection then
			return
		end
		valueDif = (channel:GetValue(targetFrame2) - channel:GetValue(targetFrame1))
		if channelType == 1 then
			averageFrameValue = valueDif / (targetFrame2 - targetFrame1)
			newValue = averageFrameValue * (moho.layerFrame - targetFrame2)
		elseif channelType == 2 then
			averageFrameValue:Set(valueDif.x / (targetFrame2 - targetFrame1), valueDif.y / (targetFrame2 - targetFrame1))
			newValue:Set(averageFrameValue.x * (moho.layerFrame - targetFrame2), averageFrameValue.y * (moho.layerFrame - targetFrame2))
		elseif channelType == 3 then
			averageFrameValue:Set(valueDif.x / (targetFrame2 - targetFrame1), valueDif.y / (targetFrame2 - targetFrame1), valueDif.z / (targetFrame2 - targetFrame1))
			newValue:Set(averageFrameValue.x * (moho.layerFrame - targetFrame2), averageFrameValue.y * (moho.layerFrame - targetFrame2), averageFrameValue.z * (moho.layerFrame - targetFrame2))
		end
		channel:SetValue(moho.layerFrame, channel:GetValue(targetFrame2) + newValue)
	elseif keyId + 2 <= channel:CountKeys() - 1 and self.continueFromRight then
		local targetFrame1 = channel:GetKeyWhen(keyId + 2)
		local targetFrame2 = channel:GetKeyWhen(keyId + 1)
		valueDif = (channel:GetValue(targetFrame2) - channel:GetValue(targetFrame1))
		if channelType == 1 then
			averageFrameValue = valueDif / (targetFrame2 - targetFrame1)
			newValue = averageFrameValue * (moho.layerFrame - targetFrame2)
		elseif channelType == 2 then
			averageFrameValue:Set(valueDif.x / (targetFrame2 - targetFrame1), valueDif.y / (targetFrame2 - targetFrame1))
			newValue:Set(averageFrameValue.x * (moho.layerFrame - targetFrame2), averageFrameValue.y * (moho.layerFrame - targetFrame2))
		elseif channelType == 3 then
			averageFrameValue:Set(valueDif.x / (targetFrame2 - targetFrame1), valueDif.y / (targetFrame2 - targetFrame1), valueDif.z / (targetFrame2 - targetFrame1))
			newValue:Set(averageFrameValue.x * (moho.layerFrame - targetFrame2), averageFrameValue.y * (moho.layerFrame - targetFrame2), averageFrameValue.z * (moho.layerFrame - targetFrame2))
		end		
		channel:SetValue(moho.layerFrame, channel:GetValue(targetFrame2) + newValue)
	end
end

-- **************************************************
-- Localization
-- **************************************************

function MR_ContinueAnimation:Localize(text)
	local phrase = {}

	phrase['Description'] = 'Continues existing animation (translate, scale, rotation) to the current frame based on two neighboring keyframes. Hold <Alt> when clicking on the action button to apply that action only.'
	phrase['UILabel'] = 'Continue Animation 1.1'

	phrase['Continue Position'] = 'Use Translation. Alt + click to continue just translation'
	phrase['Continue Angle'] = 'Use Rotation. Alt + click to continue just angle'
	phrase['Continue Scale'] = 'Use Scale. Alt + click to continue just scale'
	phrase['Continue Curvature'] = 'Use Curvature. Alt + click to continue just curvature'
	phrase['Show Bezier Handles'] = 'Show Bezier handles'
	phrase['Continue'] = 'Continue Animation'
	phrase['Continue Animation'] = 'Apply enabled transformations. Alt+click to apply all even if they turned off.'
	phrase['Continue From Right Tooltip'] = 'Continue From Right. Continues existing animation to the current frame based on the next 2 keyframes.'
	phrase['Transform Layer Tooltip'] = 'Layer Transformation. Continues existing layer animation'

	local fileWord = MOHO.Localize("/Menus/File/File=File")
	if fileWord == "Файл" then
		phrase['Description'] = 'Продлить существующую анимацию (смещение, масштаб, вращение, кривизна) до текущего кадра основываясь на двух соседних ключах. Alt + клик по одной из кнопок трансформации запускает только её действие.' 
		phrase['UILabel'] = 'Продлить анимацию 1.1'

		phrase['Continue Position'] = 'Использовать смещение. Alt + клик - продлить только смещение.'
		phrase['Continue Angle'] = 'Использовать поворот. Alt + клик - продлить только поворот'
		phrase['Continue Scale'] = 'Использовать кривизну. Alt + клик - продлить только кривизну'
		phrase['Continue Curvature'] = 'Использовать масштаб. Alt + клик - продлить только масштаб'
		phrase['Show Bezier Handles'] = 'Показывать ручки Безье'
		phrase['Continue'] = 'Продлить анимацию'
		phrase['Continue Animation'] = 'Продлить включённые трансформации. Alt + клик - продлить все трансформации даже если они выключены.'
		phrase['Continue From Right Tooltip'] = 'Продлить справа. Продлить существующую анимацию до текущего кадра основываясь на двух следующих ключах.'
		phrase['Transform Layer Tooltip'] = 'Трансформация слоя. Продлить существующую анимацию слоя'
		end
	return phrase[text]
end

Icon
MR Continue Animation
Listed

Script type: Tool

Uploaded: Dec 27 2021, 06:56

Last modified: Sep 12 2023, 11:56

Script Version: 1.1

Script allows you to extend the existing animation to the current frame based on two neighboring keyframes.
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: 1877