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

ScriptName = "MR_TweenMachine"

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

MR_TweenMachine = {}

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

function MR_TweenMachine:Version()
	return '1.1.1'
end

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

function MR_TweenMachine:Creator()
	return 'Eugene Babich, original idea by davood tabatabei davoodice'
end

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


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

function MR_TweenMachine:IsRelevant(moho)
	local v1, v2, v3 = self:GetMohoVersion(moho)
	self.shortButtonSupport = true
	if not v3 then
		v3 = 0
	end
	if v1 < 13 then
		self.shortButtonSupport = false
	elseif v2 < 5 then
		self.shortButtonSupport = false
	elseif v3 < 2 then	
		self.shortButtonSupport = false
	end

	return true
end

function MR_TweenMachine:IsEnabled(moho)
	return true
end

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

function MR_TweenMachine:LoadPrefs(prefs)
	self.useBonesAngle = prefs:GetBool("MR_TweenMachine.useBonesAngle", true)
	self.useBonesPosition = prefs:GetBool("MR_TweenMachine.useBonesPosition", true)
	self.useBonesScale = prefs:GetBool("MR_TweenMachine.useBonesScale", true)
	self.usePointsPosition = prefs:GetBool("MR_TweenMachine.usePointsPosition", true)
	self.usePointsCurvature = prefs:GetBool("MR_TweenMachine.usePointsCurvature", true)
	self.usePointsWidth = prefs:GetBool("MR_TweenMachine.usePointsWidth", true)
	self.useLayerPosition = prefs:GetBool("MR_TweenMachine.useLayerPosition", true)
	self.useLayerRotationX = prefs:GetBool("MR_TweenMachine.useLayerRotationX", true)
	self.useLayerRotationY = prefs:GetBool("MR_TweenMachine.useLayerRotationY", true)
	self.useLayerRotationZ = prefs:GetBool("MR_TweenMachine.useLayerRotationZ", true)
	self.useLayerScale = prefs:GetBool("MR_TweenMachine.useLayerScale", true)
	self.useLayerShear = prefs:GetBool("MR_TweenMachine.useLayerShear", true)
	self.useLayerFollowing = prefs:GetBool("MR_TweenMachine.useLayerFollowing", true)
	self.useLayerAlpha = prefs:GetBool("MR_TweenMachine.useLayerAlpha", true)
	
	self.useCameraTrack = prefs:GetBool("MR_TweenMachine.useCameraTrack", true)
	self.useCameraPanTilt = prefs:GetBool("MR_TweenMachine.useCameraPanTilt", true)
	self.useCameraZoom = prefs:GetBool("MR_TweenMachine.useCameraZoom", true)
	self.useCameraRoll = prefs:GetBool("MR_TweenMachine.useCameraRoll", true)
	
	self.useX = prefs:GetBool("MR_TweenMachine.useX", true)
	self.useY = prefs:GetBool("MR_TweenMachine.useY", true)
	self.useZ = prefs:GetBool("MR_TweenMachine.useZ", true)
	
	self.ignoreShyBones = prefs:GetBool("MR_TweenMachine.ignoreShyBones", false)
	self.ignoreHiddenBones = prefs:GetBool("MR_TweenMachine.ignoreHiddenBones", true)
	self.ignoreReferenceLayers = prefs:GetBool("MR_TweenMachine.ignoreReferenceLayers", true)
	self.ignoreTargetboneAngle = prefs:GetBool("MR_TweenMachine.ignoreTargetboneAngle", false)
	
	self.ignoreSelectedBones = prefs:GetBool("MR_TweenMachine.ignoreSelectedBones", false)
	self.selectedBonesOnly = prefs:GetBool("MR_TweenMachine.selectedBonesOnly", true)
	self.selectedPointsOnly = prefs:GetBool("MR_TweenMachine.selectedPointsOnly", true)
	self.useCamera = prefs:GetBool("MR_TweenMachine.useCamera", false)
	self.useLayerTransformation = prefs:GetBool("MR_TweenMachine.useLayerTransformation", false)
	self.useNestedLayers = prefs:GetBool("MR_TweenMachine.useNestedLayers", false)
	self.autoBake = prefs:GetBool("MR_TweenMachine.autoBake", false)
	self.interval = prefs:GetInt("MR_TweenMachine.interval", 2)
end

function MR_TweenMachine:SavePrefs(prefs)
	prefs:SetBool("MR_TweenMachine.useBonesAngle", self.useBonesAngle)
	prefs:SetBool("MR_TweenMachine.useBonesPosition", self.useBonesPosition)
	prefs:SetBool("MR_TweenMachine.useBonesScale", self.useBonesPosition)
	prefs:SetBool("MR_TweenMachine.usePointsPosition", self.usePointsPosition)
	prefs:SetBool("MR_TweenMachine.usePointsCurvature", self.usePointsCurvature)
	prefs:SetBool("MR_TweenMachine.usePointsWidth", self.usePointsWidth)
	prefs:SetBool("MR_TweenMachine.useLayerPosition", self.useLayerPosition)
	prefs:SetBool("MR_TweenMachine.useLayerRotationX", self.useLayerRotationX)
	prefs:SetBool("MR_TweenMachine.useLayerRotationY", self.useLayerRotationY)
	prefs:SetBool("MR_TweenMachine.useLayerRotationZ", self.useLayerRotationZ)
	prefs:SetBool("MR_TweenMachine.useLayerScale", self.useLayerScale)
	prefs:SetBool("MR_TweenMachine.useLayerShear", self.useLayerShear)
	prefs:SetBool("MR_TweenMachine.useLayerFollowing", self.useLayerFollowing)
	prefs:SetBool("MR_TweenMachine.useLayerAlpha", self.useLayerAlpha)
	
	prefs:SetBool("MR_TweenMachine.useCameraTrack", self.useCameraTrack)
	prefs:SetBool("MR_TweenMachine.useCameraPanTilt", self.useCameraPanTilt)
	prefs:SetBool("MR_TweenMachine.useCameraZoom", self.useCameraZoom)
	prefs:SetBool("MR_TweenMachine.useCameraRoll", self.useCameraRoll)
	
	prefs:SetBool("MR_TweenMachine.useX", self.useX)
	prefs:SetBool("MR_TweenMachine.useY", self.useY)
	prefs:SetBool("MR_TweenMachine.useZ", self.useZ)
	
	prefs:SetBool("MR_TweenMachine.ignoreShyBones", self.ignoreShyBones)
	prefs:SetBool("MR_TweenMachine.ignoreHiddenBones", self.ignoreHiddenBones)
	prefs:SetBool("MR_TweenMachine.ignoreReferenceLayers", self.ignoreReferenceLayers)
	prefs:SetBool("MR_TweenMachine.ignoreTargetboneAngle", self.ignoreTargetboneAngle)

	prefs:SetBool("MR_TweenMachine.ignoreSelectedBones", self.ignoreSelectedBones)
	prefs:SetBool("MR_TweenMachine.selectedBonesOnly", self.selectedBonesOnly)
	prefs:SetBool("MR_TweenMachine.selectedPointsOnly", self.selectedPointsOnly)
	prefs:SetBool("MR_TweenMachine.useCamera", self.useCamera)
	prefs:SetBool("MR_TweenMachine.useLayerTransformation", self.useLayerTransformation)
	prefs:SetBool("MR_TweenMachine.useNestedLayers", self.useNestedLayers)
	prefs:SetBool("MR_TweenMachine.autoBake", self.autoBake)
	prefs:SetInt("MR_TweenMachine.interval", self.interval)
end

function MR_TweenMachine:ResetPrefs()
	self.useBonesAngle = true
	self.useBonesPosition = true
	self.useBonesScale = true
	
	self.usePointsPosition = true
	self.usePointsCurvature = true
	self.usePointsWidth = true
	
	self.useLayerPosition = true
	self.useLayerRotationX = true
	self.useLayerRotationY = true
	self.useLayerRotationZ = true
	self.useLayerScale = true
	self.useLayerShear = true
	self.useLayerFollowing = true
	self.useLayerAlpha = true
	
	self.useCameraTrack = true
	self.useCameraPanTilt = true
	self.useCameraZoom = true
	self.useCameraRoll = true
	
	self.useX = true
	self.useY = true
	self.useZ = true
	
	self.ignoreShyBones = false
	self.ignoreHiddenBones = true
	self.ignoreReferenceLayers = true
	self.ignoreTargetboneAngle = false
	
	self.ignoreSelectedBones = false
	self.selectedBonesOnly = true
	self.selectedPointsOnly = true
	self.useCamera = false
	self.useLayerTransformation = false
	self.useNestedLayers = false
	self.autoBake = false
	self.interval = 2
end

MR_TweenMachine.useBonesAngle = true
MR_TweenMachine.useBonesPosition = true
MR_TweenMachine.useBonesScale = true

MR_TweenMachine.usePointsPosition = true
MR_TweenMachine.usePointsCurvature = true
MR_TweenMachine.usePointsWidth = true

MR_TweenMachine.useLayerPosition = true
MR_TweenMachine.useLayerRotationX = true
MR_TweenMachine.useLayerRotationY = true
MR_TweenMachine.useLayerRotationZ = true
MR_TweenMachine.useLayerScale = true
MR_TweenMachine.useLayerShear = true
MR_TweenMachine.useLayerFollowing = true
MR_TweenMachine.useLayerAlpha = true

MR_TweenMachine.useCameraTrack = true
MR_TweenMachine.useCameraPanTilt = true
MR_TweenMachine.useCameraZoom = true
MR_TweenMachine.useCameraRoll = true

MR_TweenMachine.useX = true
MR_TweenMachine.useY = true
MR_TweenMachine.useZ = true

MR_TweenMachine.ignoreShyBones = false
MR_TweenMachine.ignoreHiddenBones = true
MR_TweenMachine.ignoreReferenceLayers = true
MR_TweenMachine.ignoreTargetboneAngle = false

MR_TweenMachine.ignoreSelectedBones = false
MR_TweenMachine.selectedBonesOnly = true
MR_TweenMachine.selectedPointsOnly = true
MR_TweenMachine.useCamera = false
MR_TweenMachine.useLayerTransformation = false
MR_TweenMachine.useNestedLayers = false
MR_TweenMachine.autoBake = false
MR_TweenMachine.interval = 2
MR_TweenMachine.undoPrepped = false
MR_TweenMachine.sliderVal = 50
MR_TweenMachine.slidertextVal = 50
MR_TweenMachine.isKeysSelected = false
MR_TweenMachine.isMouseDragging = false
MR_TweenMachine.selRect = LM.Rect:new_local()
MR_TweenMachine.channelsList = {}
MR_TweenMachine.referenceLayersList = {}

function MR_TweenMachine:OnMouseDown(moho, mouseEvent)
	local skel = moho:Skeleton()
	local mesh = moho:Mesh()
	if not skel and not mesh then
		return
	end
	
	self.isMouseDragging = true
	if not mouseEvent.shiftKey and not mouseEvent.altKey then
		if skel then
			skel:SelectNone()
		elseif mesh then
			mesh:SelectNone()
		end	
	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_TweenMachine:OnMouseMoved(moho, mouseEvent)
	local skel = moho:Skeleton()
	local mesh = moho:Mesh()
	if not skel and not mesh then
		return
	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_TweenMachine:OnMouseUp(moho, mouseEvent)
	local skel = moho:Skeleton()
	local mesh = moho:Mesh()
	local mouseDist = math.abs(mouseEvent.pt.x - mouseEvent.startPt.x) + math.abs(mouseEvent.pt.y - mouseEvent.startPt.y)

	local id
	
	if skel then
		id = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true)
		if not mouseEvent.shiftKey and not mouseEvent.altKey then
			skel:SelectNone()
		end	
		if id ~= -1 then
			skel:Bone(id).fSelected = not mouseEvent.altKey
		end
	elseif mesh then
		id = mouseEvent.view:PickPoint(mouseEvent.pt)
		if not mouseEvent.shiftKey and not mouseEvent.altKey then
			mesh:SelectNone()
		end	
		if id ~= -1 then
			mesh:Point(id).fSelected = not mouseEvent.altKey
		end
	end

	self.isMouseDragging = false

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

	if	moho.layer:LayerType() == MOHO.LT_BONE then
		if (skel ~= nil) then
			self.selRect:Normalize()
			moho.layer:GetFullTransform(moho.frame, m, moho.document)
			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
	elseif	moho.layer:LayerType() == MOHO.LT_VECTOR then
		if (mesh ~= nil) then
			for i = 0, mesh:CountPoints() - 1 do
				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)
				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
				self.isMouseDragging = false
			end
		end	
	end
	moho:UpdateSelectedChannels()
end

function MR_TweenMachine:DrawMe(moho, view)
	if self.isMouseDragging then
		local g = view:Graphics()
		g:SelectionRect(self.selRect)
	end
end

function MR_TweenMachine:OnKeyDown(moho, keyEvent)
	
end

local MR_SettingsDialog = {}

MR_SettingsDialog.SELECT_ALL = MOHO.MSG_BASE
MR_SettingsDialog.DESELECT_ALL = MOHO.MSG_BASE + 1
MR_SettingsDialog.BONES_SELECT_ALL = MOHO.MSG_BASE + 2
MR_SettingsDialog.BONES_DESELECT_ALL = MOHO.MSG_BASE + 3
MR_SettingsDialog.USE_BONES_ANGLE = MOHO.MSG_BASE + 4
MR_SettingsDialog.USE_BONES_POS = MOHO.MSG_BASE + 5
MR_SettingsDialog.USE_BONES_SCALE = MOHO.MSG_BASE + 6
MR_SettingsDialog.POINTS_SELECT_ALL = MOHO.MSG_BASE + 7
MR_SettingsDialog.POINTS_DESELECT_ALL = MOHO.MSG_BASE + 8
MR_SettingsDialog.USE_POINTS_POS = MOHO.MSG_BASE + 9
MR_SettingsDialog.USE_POINTS_CURVATURE = MOHO.MSG_BASE + 10
MR_SettingsDialog.USE_POINTS_WIDTH = MOHO.MSG_BASE + 11
MR_SettingsDialog.LAYERS_SELECT_ALL = MOHO.MSG_BASE + 12
MR_SettingsDialog.LAYERS_DESELECT_ALL = MOHO.MSG_BASE + 13
MR_SettingsDialog.USE_LAYERS_POSITION = MOHO.MSG_BASE + 14
MR_SettingsDialog.USE_LAYERS_ROTATION_X = MOHO.MSG_BASE + 15
MR_SettingsDialog.USE_LAYERS_ROTATION_Y = MOHO.MSG_BASE + 16
MR_SettingsDialog.USE_LAYERS_ROTATION_Z = MOHO.MSG_BASE + 17
MR_SettingsDialog.USE_LAYERS_SCALE = MOHO.MSG_BASE + 18
MR_SettingsDialog.USE_LAYERS_SHEAR = MOHO.MSG_BASE + 19
MR_SettingsDialog.USE_LAYERS_FOLLOWING = MOHO.MSG_BASE + 20
MR_SettingsDialog.USE_LAYERS_ALPHA = MOHO.MSG_BASE + 21
MR_SettingsDialog.CAMERA_SELECT_ALL = MOHO.MSG_BASE + 22
MR_SettingsDialog.CAMERA_DESELECT_ALL = MOHO.MSG_BASE + 23
MR_SettingsDialog.USE_CAMERA_TRACK = MOHO.MSG_BASE + 24
MR_SettingsDialog.USE_CAMERA_PAN_TILT = MOHO.MSG_BASE + 25
MR_SettingsDialog.USE_CAMERA_ZOOM = MOHO.MSG_BASE + 26
MR_SettingsDialog.USE_CAMERA_ROLL = MOHO.MSG_BASE + 27
MR_SettingsDialog.USE_X_DIMENTION = MOHO.MSG_BASE + 28
MR_SettingsDialog.USE_Y_DIMENTION = MOHO.MSG_BASE + 29
MR_SettingsDialog.USE_Z_DIMENTION = MOHO.MSG_BASE + 30
MR_SettingsDialog.IGNORE_SHY_BONES = MOHO.MSG_BASE + 31
MR_SettingsDialog.IGNORE_HIDDEN_BONES = MOHO.MSG_BASE + 32
MR_SettingsDialog.IGNORE_REFERENCE_LAYERS = MOHO.MSG_BASE + 33
MR_SettingsDialog.IGNORE_TARGETBONE_ANGLE = MOHO.MSG_BASE + 34

function MR_SettingsDialog:new()
    local d = LM.GUI.SimpleDialog(MR_TweenMachine:Localize('UILabel'), MR_SettingsDialog)
    local l = d:GetLayout()
	
	l:PushH()
	
		d.selectAllButton = LM.GUI.Button(MR_TweenMachine:Localize('   Select all   '), self.SELECT_ALL)
		l:AddChild(d.selectAllButton, LM.GUI.ALIGN_LEFT, 0)
		
		d.deselectAllButton = LM.GUI.Button(MR_TweenMachine:Localize('   Deselect all   '), self.DESELECT_ALL)
		l:AddChild(d.deselectAllButton, LM.GUI.ALIGN_LEFT, 0)
		
	l:Pop()
	
	l:PushH()
	
		l:PushV()
		
			d.bonesText = LM.GUI.DynamicText(MR_TweenMachine:Localize('Bones settings:'), nil)
			l:AddChild(d.bonesText, LM.GUI.ALIGN_CENTER, 0)
			
			l:PushH()
				
				if MR_TweenMachine.shortButtonSupport then
					d.selectAllBonesButton = LM.GUI.ShortButton(MR_TweenMachine:Localize('Select all'), self.BONES_SELECT_ALL)
					l:AddChild(d.selectAllBonesButton, LM.GUI.ALIGN_LEFT, 0)
					
					d.deselectAllBonesButton = LM.GUI.ShortButton(MR_TweenMachine:Localize('Deselect all'), self.BONES_DESELECT_ALL)
					l:AddChild(d.deselectAllBonesButton, LM.GUI.ALIGN_LEFT, 0)
				else
					d.selectAllBonesButton = LM.GUI.Button(MR_TweenMachine:Localize('Select all'), self.BONES_SELECT_ALL)
					l:AddChild(d.selectAllBonesButton, LM.GUI.ALIGN_LEFT, 0)
					
					d.deselectAllBonesButton = LM.GUI.Button(MR_TweenMachine:Localize('Deselect all'), self.BONES_DESELECT_ALL)
					l:AddChild(d.deselectAllBonesButton, LM.GUI.ALIGN_LEFT, 0)
				end	
				
			l:Pop()
				
			d.useBonesAngleCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use angle channel'), self.USE_BONES_ANGLE)
			l:AddChild(d.useBonesAngleCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useBonesPositionCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use position channel'), self.USE_BONES_POS)
			l:AddChild(d.useBonesPositionCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useBonesScaleCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use scale channel'), self.USE_BONES_SCALE)
			l:AddChild(d.useBonesScaleCheck, LM.GUI.ALIGN_LEFT, 0)
			
			l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
			
			d.pointsText = LM.GUI.DynamicText(MR_TweenMachine:Localize('Points settings:'), nil)
			l:AddChild(d.pointsText, LM.GUI.ALIGN_CENTER, 0)
				
			l:PushH()
				
				if MR_TweenMachine.shortButtonSupport then
					d.selectAllPointsButton = LM.GUI.ShortButton(MR_TweenMachine:Localize('Select all'), self.POINTS_SELECT_ALL)
					l:AddChild(d.selectAllPointsButton, LM.GUI.ALIGN_LEFT, 0)
					
					d.deselectAllPointsButton = LM.GUI.ShortButton(MR_TweenMachine:Localize('Deselect all'), self.POINTS_DESELECT_ALL)
					l:AddChild(d.deselectAllPointsButton, LM.GUI.ALIGN_LEFT, 0)
				else
					d.selectAllPointsButton = LM.GUI.Button(MR_TweenMachine:Localize('Select all'), self.POINTS_SELECT_ALL)
					l:AddChild(d.selectAllPointsButton, LM.GUI.ALIGN_LEFT, 0)
					
					d.deselectAllPointsButton = LM.GUI.Button(MR_TweenMachine:Localize('Deselect all'), self.POINTS_DESELECT_ALL)
					l:AddChild(d.deselectAllPointsButton, LM.GUI.ALIGN_LEFT, 0)
				end
					
			l:Pop()
				
			d.usePointsPositionCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use position channel'), self.USE_POINTS_POS)
			l:AddChild(d.usePointsPositionCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.usePointsCurvatureCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use curvature channel'), self.USE_POINTS_CURVATURE)
			l:AddChild(d.usePointsCurvatureCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.usePointsWidthCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use width channel'), self.USE_POINTS_WIDTH)
			l:AddChild(d.usePointsWidthCheck, LM.GUI.ALIGN_LEFT, 0)
			
		l:Pop()
		
		l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
		
		l:PushV()
		
			d.layersText = LM.GUI.DynamicText(MR_TweenMachine:Localize('Layers settings:'), nil)
			l:AddChild(d.layersText, LM.GUI.ALIGN_CENTER, 0)
			
			l:PushH()
			
					if MR_TweenMachine.shortButtonSupport then
						d.selectAllLayersButton = LM.GUI.ShortButton(MR_TweenMachine:Localize('Select all'), self.LAYERS_SELECT_ALL)
						l:AddChild(d.selectAllLayersButton, LM.GUI.ALIGN_LEFT, 0)
						
						d.deselectAllLayersButton = LM.GUI.ShortButton(MR_TweenMachine:Localize('Deselect all'), self.LAYERS_DESELECT_ALL)
						l:AddChild(d.deselectAllLayersButton, LM.GUI.ALIGN_LEFT, 0)
					else
						d.selectAllLayersButton = LM.GUI.Button(MR_TweenMachine:Localize('Select all'), self.LAYERS_SELECT_ALL)
						l:AddChild(d.selectAllLayersButton, LM.GUI.ALIGN_LEFT, 0)
						
						d.deselectAllLayersButton = LM.GUI.Button(MR_TweenMachine:Localize('Deselect all'), self.LAYERS_DESELECT_ALL)
						l:AddChild(d.deselectAllLayersButton, LM.GUI.ALIGN_LEFT, 0)
					end
					
			l:Pop()
				
			d.useLayerPositionCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use position channel'), self.USE_LAYERS_POSITION)
			l:AddChild(d.useLayerPositionCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useLayerRotationXCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use rotation X channel'), self.USE_LAYERS_ROTATION_X)
			l:AddChild(d.useLayerRotationXCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useLayerRotationYCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use rotation Y channel'), self.USE_LAYERS_ROTATION_Y)
			l:AddChild(d.useLayerRotationYCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useLayerRotationZCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use rotation Z channel'), self.USE_LAYERS_ROTATION_Z)
			l:AddChild(d.useLayerRotationZCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useLayerScaleCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use scale channel'), self.USE_LAYERS_SCALE)
			l:AddChild(d.useLayerScaleCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useLayerShearCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use shear channel'), self.USE_LAYERS_SHEAR)
			l:AddChild(d.useLayerShearCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useLayerFollowingCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use following channel'), self.USE_LAYERS_FOLLOWING)
			l:AddChild(d.useLayerFollowingCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useLayerAlphaCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use alpha channel'), self.USE_LAYERS_ALPHA)
			l:AddChild(d.useLayerAlphaCheck, LM.GUI.ALIGN_LEFT, 0)
	
		l:Pop()
		
		l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
		
		l:PushV()
		
			d.layersText = LM.GUI.DynamicText(MR_TweenMachine:Localize('Camera settings:'), nil)
			l:AddChild(d.layersText, LM.GUI.ALIGN_CENTER, 0)
			
			l:PushH()
					
					if MR_TweenMachine.shortButtonSupport then
						d.selectAllCameraButton = LM.GUI.ShortButton(MR_TweenMachine:Localize('Select all'), self.CAMERA_SELECT_ALL)
						l:AddChild(d.selectAllCameraButton, LM.GUI.ALIGN_LEFT, 0)
						
						d.deselectAllCameraButton = LM.GUI.ShortButton(MR_TweenMachine:Localize('Deselect all'), self.CAMERA_DESELECT_ALL)
						l:AddChild(d.deselectAllCameraButton, LM.GUI.ALIGN_LEFT, 0)
					else	
						d.selectAllCameraButton = LM.GUI.Button(MR_TweenMachine:Localize('Select all'), self.CAMERA_SELECT_ALL)
						l:AddChild(d.selectAllCameraButton, LM.GUI.ALIGN_LEFT, 0)
						
						d.deselectAllCameraButton = LM.GUI.Button(MR_TweenMachine:Localize('Deselect all'), self.CAMERA_DESELECT_ALL)
						l:AddChild(d.deselectAllCameraButton, LM.GUI.ALIGN_LEFT, 0)
					end
					
			l:Pop()
				
			d.useCameraTrackCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use track channel'), self.USE_CAMERA_TRACK)
			l:AddChild(d.useCameraTrackCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useCameraPanTiltCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use pan tilt channel'), self.USE_CAMERA_PAN_TILT)
			l:AddChild(d.useCameraPanTiltCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useCameraZoomCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use zoom channel'), self.USE_CAMERA_ZOOM)
			l:AddChild(d.useCameraZoomCheck, LM.GUI.ALIGN_LEFT, 0)
			
			d.useCameraRollCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use roll channel'), self.USE_CAMERA_ROLL)
			l:AddChild(d.useCameraRollCheck, LM.GUI.ALIGN_LEFT, 0)
	
		l:Pop()
		
	l:Pop()	
	
		l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
		
		d.multidementionChannelsText = LM.GUI.DynamicText(MR_TweenMachine:Localize('Multidimention channels settings:'), nil)
		l:AddChild(d.multidementionChannelsText, LM.GUI.ALIGN_CENTER, 0)
		
		l:PushH()
		
			d.useXCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use X dimention'), self.USE_X_DIMENTION)
			l:AddChild(d.useXCheck, LM.GUI.ALIGN_LEFT, 0)
			
			l:AddPadding(50)
			
			d.useYCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use Y dimention'), self.USE_Y_DIMENTION)
			l:AddChild(d.useYCheck, LM.GUI.ALIGN_LEFT, 0)
			
			l:AddPadding(50)
			
			d.useZCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Use Z dimention'), self.USE_Z_DIMENTION)
			l:AddChild(d.useZCheck, LM.GUI.ALIGN_LEFT, 0)
			
		l:Pop()	
		
		l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
		
		d.ignoreSettingsText = LM.GUI.DynamicText(MR_TweenMachine:Localize('Ignore settings:'), nil)
		l:AddChild(d.ignoreSettingsText, LM.GUI.ALIGN_CENTER, 0)
		
		l:PushH()
		
			d.ignoreShyBonesCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Ignore shy bones'), self.IGNORE_SHY_BONES)
			l:AddChild(d.ignoreShyBonesCheck, LM.GUI.ALIGN_LEFT, 0)
		
			l:AddPadding(47)
		
			d.ignoreHiddenBonesCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Ignore hidden bones'), self.IGNORE_HIDDEN_BONES)
			l:AddChild(d.ignoreHiddenBonesCheck, LM.GUI.ALIGN_LEFT, 0)
			
			l:AddPadding(28)
				
			d.ignoreReferenceLayersCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Ignore reference layers'), self.IGNORE_REFERENCE_LAYERS)
			l:AddChild(d.ignoreReferenceLayersCheck, LM.GUI.ALIGN_LEFT, 0)
		
		l:Pop()
		
		l:PushH()
		
			d.ignoreTargetboneAngleCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Ignore target bones angle'), self.IGNORE_TARGETBONE_ANGLE)
			l:AddChild(d.ignoreTargetboneAngleCheck, LM.GUI.ALIGN_LEFT, 0)
			
		l:Pop()
		
    return d
end

function MR_SettingsDialog:UpdateWidgets(moho)
    self.useBonesAngleCheck:SetValue(MR_TweenMachine.useBonesAngle)
    self.useBonesPositionCheck:SetValue(MR_TweenMachine.useBonesPosition)
    self.useBonesScaleCheck:SetValue(MR_TweenMachine.useBonesScale)
	
    self.usePointsPositionCheck:SetValue(MR_TweenMachine.usePointsPosition)
    self.usePointsCurvatureCheck:SetValue(MR_TweenMachine.usePointsCurvature)
    self.usePointsWidthCheck:SetValue(MR_TweenMachine.usePointsWidth)
	
	self.useLayerPositionCheck:SetValue(MR_TweenMachine.useLayerPosition)
    self.useLayerRotationXCheck:SetValue(MR_TweenMachine.useLayerRotationX)
    self.useLayerRotationYCheck:SetValue(MR_TweenMachine.useLayerRotationY)
    self.useLayerRotationZCheck:SetValue(MR_TweenMachine.useLayerRotationZ)
    self.useLayerScaleCheck:SetValue(MR_TweenMachine.useLayerScale)
    self.useLayerShearCheck:SetValue(MR_TweenMachine.useLayerShear)
    self.useLayerFollowingCheck:SetValue(MR_TweenMachine.useLayerFollowing)
    self.useLayerAlphaCheck:SetValue(MR_TweenMachine.useLayerAlpha)
	
	self.useCameraTrackCheck:SetValue(MR_TweenMachine.useCameraTrack)
	self.useCameraPanTiltCheck:SetValue(MR_TweenMachine.useCameraPanTilt)
	self.useCameraZoomCheck:SetValue(MR_TweenMachine.useCameraZoom)
	self.useCameraRollCheck:SetValue(MR_TweenMachine.useCameraRoll)
	
	self.useXCheck:SetValue(MR_TweenMachine.useX)
	self.useYCheck:SetValue(MR_TweenMachine.useY)
	self.useZCheck:SetValue(MR_TweenMachine.useZ)
	
	self.ignoreShyBonesCheck:SetValue(MR_TweenMachine.ignoreShyBones)
	self.ignoreHiddenBonesCheck:SetValue(MR_TweenMachine.ignoreHiddenBones)
	self.ignoreReferenceLayersCheck:SetValue(MR_TweenMachine.ignoreReferenceLayers)
	self.ignoreTargetboneAngleCheck:SetValue(MR_TweenMachine.ignoreTargetboneAngle)
end

function MR_SettingsDialog:OnOK(moho)
    MR_TweenMachine.useBonesAngle = self.useBonesAngleCheck:Value()
    MR_TweenMachine.useBonesPosition = self.useBonesPositionCheck:Value()
    MR_TweenMachine.useBonesScale = self.useBonesScaleCheck:Value()
	
    MR_TweenMachine.usePointsPosition = self.usePointsPositionCheck:Value()
    MR_TweenMachine.usePointsCurvature = self.usePointsCurvatureCheck:Value()
    MR_TweenMachine.usePointsWidth = self.usePointsWidthCheck:Value()
	
	MR_TweenMachine.useLayerPosition = self.useLayerPositionCheck:Value()
    MR_TweenMachine.useLayerRotationX = self.useLayerRotationXCheck:Value()
    MR_TweenMachine.useLayerRotationY = self.useLayerRotationYCheck:Value()
	MR_TweenMachine.useLayerRotationZ = self.useLayerRotationZCheck:Value()
    MR_TweenMachine.useLayerScale = self.useLayerScaleCheck:Value()
    MR_TweenMachine.useLayerShear = self.useLayerShearCheck:Value()
	MR_TweenMachine.useLayerFollowing = self.useLayerFollowingCheck:Value()
    MR_TweenMachine.useLayerAlpha = self.useLayerAlphaCheck:Value()
	
	MR_TweenMachine.useCameraTrack = self.useCameraTrackCheck:Value()
    MR_TweenMachine.useCameraPanTilt = self.useCameraPanTiltCheck:Value()
	MR_TweenMachine.useCameraZoom = self.useCameraZoomCheck:Value()
    MR_TweenMachine.useCameraRoll = self.useCameraRollCheck:Value()
	
	MR_TweenMachine.useX = self.useXCheck:Value()
	MR_TweenMachine.useY = self.useYCheck:Value()
    MR_TweenMachine.useZ = self.useZCheck:Value()
	
	MR_TweenMachine.ignoreShyBones = self.ignoreShyBonesCheck:Value()
	MR_TweenMachine.ignoreHiddenBones = self.ignoreHiddenBonesCheck:Value()
    MR_TweenMachine.ignoreReferenceLayers = self.ignoreReferenceLayersCheck:Value()
    MR_TweenMachine.ignoreTargetboneAngle = self.ignoreTargetboneAngleCheck:Value()
end

function MR_SettingsDialog:HandleMessage(msg)
	if msg == self.SELECT_ALL then
		self.useBonesAngleCheck:SetValue(true)
		self.useBonesPositionCheck:SetValue(true)
		self.useBonesScaleCheck:SetValue(true)
		
		self.usePointsPositionCheck:SetValue(true)
		self.usePointsCurvatureCheck:SetValue(true)
		self.usePointsWidthCheck:SetValue(true)
		
		self.useLayerPositionCheck:SetValue(true)
		self.useLayerRotationXCheck:SetValue(true)
		self.useLayerRotationYCheck:SetValue(true)
		self.useLayerRotationZCheck:SetValue(true)
		self.useLayerScaleCheck:SetValue(true)
		self.useLayerShearCheck:SetValue(true)
		self.useLayerFollowingCheck:SetValue(true)
		self.useLayerAlphaCheck:SetValue(true)
		
		self.useCameraTrackCheck:SetValue(true)
		self.useCameraPanTiltCheck:SetValue(true)
		self.useCameraZoomCheck:SetValue(true)
		self.useCameraRollCheck:SetValue(true)
	elseif msg == self.DESELECT_ALL then
		self.useBonesAngleCheck:SetValue(false)
		self.useBonesPositionCheck:SetValue(false)
		self.useBonesScaleCheck:SetValue(false)
		
		self.usePointsPositionCheck:SetValue(false)
		self.usePointsCurvatureCheck:SetValue(false)
		self.usePointsWidthCheck:SetValue(false)
		
		self.useLayerPositionCheck:SetValue(false)
		self.useLayerRotationXCheck:SetValue(false)
		self.useLayerRotationYCheck:SetValue(false)
		self.useLayerRotationZCheck:SetValue(false)
		self.useLayerScaleCheck:SetValue(false)
		self.useLayerShearCheck:SetValue(false)
		self.useLayerFollowingCheck:SetValue(false)
		self.useLayerAlphaCheck:SetValue(false)
		
		self.useCameraTrackCheck:SetValue(false)
		self.useCameraPanTiltCheck:SetValue(false)
		self.useCameraZoomCheck:SetValue(false)
		self.useCameraRollCheck:SetValue(false)
	-- Bones channels
	elseif msg == self.BONES_SELECT_ALL then
		self.useBonesAngleCheck:SetValue(true)
		self.useBonesPositionCheck:SetValue(true)
		self.useBonesScaleCheck:SetValue(true)
	elseif msg == self.BONES_DESELECT_ALL then
		self.useBonesAngleCheck:SetValue(false)
		self.useBonesPositionCheck:SetValue(false)
		self.useBonesScaleCheck:SetValue(false)
    elseif msg == self.USE_BONES_ANGLE then
		MR_TweenMachine.useBonesAngle = self.useBonesAngleCheck:Value()
	elseif msg == self.USE_BONES_POS then
		MR_TweenMachine.useBonesPosition = self.useBonesPositionCheck:Value()	
	elseif msg == self.USE_BONES_SCALE then
		MR_TweenMachine.useBonesScale = self.useBonesScaleCheck:Value()
	-- Points channels	
	elseif msg == self.POINTS_SELECT_ALL then
		self.usePointsPositionCheck:SetValue(true)
		self.usePointsCurvatureCheck:SetValue(true)
		self.usePointsWidthCheck:SetValue(true)
	elseif msg == self.POINTS_DESELECT_ALL then
		self.usePointsPositionCheck:SetValue(false)
		self.usePointsCurvatureCheck:SetValue(false)
		self.usePointsWidthCheck:SetValue(false)
    elseif msg == self.USE_POINTS_POS then
		MR_TweenMachine.usePointsPosition = self.usePointsPositionCheck:Value()
	elseif msg == self.USE_POINTS_CURVATURE then
		MR_TweenMachine.usePointsCurvature = self.usePointsCurvatureCheck:Value()	
	elseif msg == self.USE_POINTS_WIDTH then
		MR_TweenMachine.usePointsWidth = self.usePointsWidthCheck:Value()
	-- Layers channels
	elseif msg == self.LAYERS_SELECT_ALL then
		self.useLayerPositionCheck:SetValue(true)
		self.useLayerRotationXCheck:SetValue(true)
		self.useLayerRotationYCheck:SetValue(true)
		self.useLayerRotationZCheck:SetValue(true)
		self.useLayerScaleCheck:SetValue(true)
		self.useLayerShearCheck:SetValue(true)
		self.useLayerFollowingCheck:SetValue(true)
		self.useLayerAlphaCheck:SetValue(true)
	elseif msg == self.LAYERS_DESELECT_ALL then
		self.useLayerPositionCheck:SetValue(false)
		self.useLayerRotationXCheck:SetValue(false)
		self.useLayerRotationYCheck:SetValue(false)
		self.useLayerRotationZCheck:SetValue(false)
		self.useLayerScaleCheck:SetValue(false)
		self.useLayerShearCheck:SetValue(false)
		self.useLayerFollowingCheck:SetValue(false)
		self.useLayerAlphaCheck:SetValue(false)
	elseif msg == self.USE_LAYERS_POSITION then
		MR_TweenMachine.useLayerPosition = self.useLayerPositionCheck:Value()
	elseif msg == self.USE_LAYERS_ROTATION_X then
		MR_TweenMachine.useLayerRotationX = self.useLayerRotationXCheck:Value()	
	elseif msg == self.USE_LAYERS_ROTATION_Y then
		MR_TweenMachine.useLayerRotationY = self.useLayerRotationYCheck:Value()
	elseif msg == self.USE_LAYERS_ROTATION_Z then
		MR_TweenMachine.useLayerRotationZ = self.useLayerRotationZCheck:Value()
	elseif msg == self.USE_LAYERS_SCALE then
		MR_TweenMachine.useLayerScale = self.useLayerScaleCheck:Value()	
	elseif msg == self.USE_LAYERS_SHEAR then
		MR_TweenMachine.useLayerShear = self.useLayerShearCheck:Value()	
	elseif msg == self.USE_LAYERS_FOLLOWING then
		MR_TweenMachine.useLayerFollowing = self.useLayerFollowingCheck:Value()
	elseif msg == self.USE_LAYERS_ALPHA then
		MR_TweenMachine.useLayerAlpha = self.useLayerAlphaCheck:Value()
	-- Camera channels	
	elseif msg == self.CAMERA_SELECT_ALL then
		self.useCameraTrackCheck:SetValue(true)
		self.useCameraPanTiltCheck:SetValue(true)
		self.useCameraZoomCheck:SetValue(true)
		self.useCameraRollCheck:SetValue(true)
	elseif msg == self.CAMERA_DESELECT_ALL then
		self.useCameraTrackCheck:SetValue(false)
		self.useCameraPanTiltCheck:SetValue(false)
		self.useCameraZoomCheck:SetValue(false)
		self.useCameraRollCheck:SetValue(false)
	elseif msg == self.USE_CAMERA_TRACK then
		MR_TweenMachine.useCameraTrack = self.useCameraTrackCheck:Value()
	elseif msg == self.USE_CAMERA_PAN_TILT then
		MR_TweenMachine.useCameraPanTilt = self.useCameraPanTiltCheck:Value()	
	elseif msg == self.USE_CAMERA_ZOOM then
		MR_TweenMachine.useCameraZoom = self.useCameraZoomCheck:Value()
	elseif msg == self.USE_CAMERA_ROLL then
		MR_TweenMachine.useCameraRoll = self.useCameraRollCheck:Value()	
	-- Multidimention channels settings
	elseif msg == self.USE_X_DIMENTION then
		MR_TweenMachine.useX = self.useXCheck:Value()	
	elseif msg == self.USE_Y_DIMENTION then
		MR_TweenMachine.useY = self.useYCheck:Value()
	elseif msg == self.USE_Z_DIMENTION then
		MR_TweenMachine.useZ = self.useZCheck:Value()
	-- Ignore settings
	elseif msg == self.IGNORE_SHY_BONES then
		MR_TweenMachine.ignoreShyBones = self.ignoreShyBonesCheck:Value()	
	elseif msg == self.IGNORE_HIDDEN_BONES then
		MR_TweenMachine.ignoreHiddenBones = self.ignoreHiddenBonesCheck:Value()
	elseif msg == self.IGNORE_REFERENCE_LAYERS then
		MR_TweenMachine.ignoreReferenceLayers = self.ignoreReferenceLayersCheck:Value()	
	elseif msg == self.IGNORE_TARGETBONE_ANGLE then
		MR_TweenMachine.ignoreTargetboneAngle = self.ignoreTargetboneAngleCheck:Value()	
    end
end

MR_TweenMachine.SLIDER = MOHO.MSG_BASE
MR_TweenMachine.SLIDER_TEXT = MOHO.MSG_BASE + 1
MR_TweenMachine.IGNORE_SELECTED_BONES = MOHO.MSG_BASE + 2
MR_TweenMachine.SELECTED_BONES_ONLY = MOHO.MSG_BASE + 3
MR_TweenMachine.SELECTED_POINTS_ONLY = MOHO.MSG_BASE + 4
MR_TweenMachine.UPDATE_REFERENCES = MOHO.MSG_BASE + 5
MR_TweenMachine.USE_CAMERA = MOHO.MSG_BASE + 6
MR_TweenMachine.USE_LAYER_TRANSFORMATION = MOHO.MSG_BASE + 7
MR_TweenMachine.AUTO_BAKE = MOHO.MSG_BASE + 8
MR_TweenMachine.INTERVAL = MOHO.MSG_BASE + 9
MR_TweenMachine.INTERVAL_1 = MOHO.MSG_BASE + 10
MR_TweenMachine.INTERVAL_2 = MOHO.MSG_BASE + 11
MR_TweenMachine.INTERVAL_3 = MOHO.MSG_BASE + 12
MR_TweenMachine.INTERVAL_4 = MOHO.MSG_BASE + 13
MR_TweenMachine.USE_NESTED_LAYERS = MOHO.MSG_BASE + 14

function MR_TweenMachine:DoLayout(moho, layout)
	self.slider = LM.GUI.Slider(400,false,false, self.SLIDER)
	layout:AddChild(self.slider)
	self.slider:SetRange(-100,200)
	self.slider:SetNumTicks(3)
	self.slider:SetShowTicks(true)
	self.slider:SetSnapToTicks(false)
	self.slider:SetFatSlider(true)
	self.slidertext = LM.GUI.TextControl(30, "0", self.SLIDER_TEXT, LM.GUI.FIELD_INT, MOHO.Localize(""))
	self.slidertext:SetWheelInc(1)
	layout:AddChild(self.slidertext)
	layout:AddPadding(-15)
	self.perc = LM.GUI.StaticText(self:Localize("%"))
	layout:AddChild(self.perc)

	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	self.dlog = MR_SettingsDialog:new()
    self.settingsPopup = LM.GUI.PopupDialog(self:Localize('Settings'), false, 0)
    self.settingsPopup:SetDialog(self.dlog)
    layout:AddChild(self.settingsPopup, LM.GUI.ALIGN_LEFT, 0)
	
	self.ignoreSelectedBonesCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_invert_bone_selection', self:Localize('Ignore selected bones'), true, self.IGNORE_SELECTED_BONES, false)
    layout:AddChild(self.ignoreSelectedBonesCheck, LM.GUI.ALIGN_LEFT, 0)
	
	self.selectedBonesOnlyCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_selected_bones_only', self:Localize('Selected bones only'), true, self.SELECTED_BONES_ONLY, false)
    layout:AddChild(self.selectedBonesOnlyCheck, LM.GUI.ALIGN_LEFT, 0)
	
	self.selectedPointsOnlyCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_selected_points_only', self:Localize('Selected points only'), true, self.SELECTED_POINTS_ONLY, false)
    layout:AddChild(self.selectedPointsOnlyCheck, LM.GUI.ALIGN_LEFT, 0)
	
	self.updateReferencesButton = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_update_ref', self:Localize('Update all layers'), false, self.UPDATE_REFERENCES, false)
    layout:AddChild(self.updateReferencesButton, LM.GUI.ALIGN_LEFT, 0)
	
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	self.useCameraCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_camera', self:Localize('Camera'), true, self.USE_CAMERA, false)
    layout:AddChild(self.useCameraCheck, LM.GUI.ALIGN_LEFT, 0)
	
	self.useLayerTransformationCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_transfrorm_layer', self:Localize('Layer Transformation'), true, self.USE_LAYER_TRANSFORMATION, false)
    layout:AddChild(self.useLayerTransformationCheck, LM.GUI.ALIGN_LEFT, 0)
	
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	self.autoBakeCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_auto_bake', self:Localize('Auto bake adjacent frames'), true, self.AUTO_BAKE, false)
    layout:AddChild(self.autoBakeCheck, LM.GUI.ALIGN_LEFT, 0)
	
	layout:AddChild(LM.GUI.StaticText(self:Localize("Interval:")))

	self.intervalMenu = LM.GUI.Menu(MOHO.Localize("Interval=Interval"))
	self.intervalMenu:AddItem(MOHO.Localize("1=1"), 0, self.INTERVAL_1)
	self.intervalMenu:AddItemAlphabetically(MOHO.Localize("2=2"), 0, self.INTERVAL_2)
	self.intervalMenu:AddItemAlphabetically(MOHO.Localize("3=3"), 0, self.INTERVAL_3)
	self.intervalMenu:AddItemAlphabetically(MOHO.Localize("4=4"), 0, self.INTERVAL_4)

	self.intervalPopup = LM.GUI.PopupMenu(50, true)
	self.intervalPopup:SetMenu(self.intervalMenu)
	layout:AddChild(self.intervalPopup)
	
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	self.useNestedLayersCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_multilayer', self:Localize('Use nested layers'), true, self.USE_NESTED_LAYERS, false)
    layout:AddChild(self.useNestedLayersCheck, LM.GUI.ALIGN_LEFT, 0)
end

function MR_TweenMachine:UpdateWidgets(moho)
	self.ignoreSelectedBonesCheck:SetValue(self.ignoreSelectedBones)
	self.ignoreSelectedBonesCheck:Enable(self.selectedBonesOnly)
	self.selectedBonesOnlyCheck:SetValue(self.selectedBonesOnly)
	self.selectedPointsOnlyCheck:SetValue(self.selectedPointsOnly)
	self.useCameraCheck:SetValue(self.useCamera)
	self.useLayerTransformationCheck:SetValue(self.useLayerTransformation)
	self.autoBakeCheck:SetValue(self.autoBake)
	self.useNestedLayersCheck:SetValue(self.useNestedLayers)
	self.slider:SetValue(self.sliderVal)
	self.slidertext:SetValue(self.slidertextVal)
	
	if self.interval < 1 or self.interval > 4 or self.interval == nil then
		self.interval = 1
	end
	
	if (self.interval == 1) then
		self.intervalMenu:SetChecked(self.INTERVAL_1, true)
	elseif (self.interval == 2) then
		self.intervalMenu:SetChecked(self.INTERVAL_2, true)
	elseif (self.interval == 3) then
		self.intervalMenu:SetChecked(self.INTERVAL_3, true)
	elseif (self.interval == 4) then
		self.intervalMenu:SetChecked(self.INTERVAL_4, true)
	end

	self.intervalPopup:Redraw()
	self.intervalPopup:Enable(self.autoBake)
end

function MR_TweenMachine:HandleMessage(moho, view, msg)
	if msg == self.SLIDER then
		if not self.undoPrepped then
			if self.useNestedLayers then
				if moho.document:CountSelectedLayers() == 1 then
					moho.document:PrepUndo(moho.layer)
				else
					moho.document:PrepUndo()
				end
				self:ScanLayers(moho)
			else
				if moho.document:CountSelectedLayers() == 1 then
					moho.document:PrepUndo(moho.layer, true)
				else
					moho.document:PrepUndo()
				end
				self.channelsList = {}
				for l = 0, moho.document:CountSelectedLayers()-1 do
					local layer = moho.document:GetSelectedLayer(l)
					self:TweenLayer(moho, layer, true)
				end	
			end	
			moho.document:SetDirty()
			self.undoPrepped = true
		end
		self.slidertext:SetValue(self.slider:Value())
		self.slidertextVal = self.slider:Value()
		self.sliderVal = self.slider:Value()
		self:Tween(moho)
		moho.layer:UpdateCurFrame()
		if(not self.slider:IsMouseDragging()) then	
			self.undoPrepped = false
			moho:UpdateUI()
			self.channelsList = {}
		end
	elseif msg == self.SLIDER_TEXT then
		self.slidertextVal = self.slidertext:Value()
		self.sliderVal = self.slidertext:Value()
		self.slider:SetValue(sliderVal)
		if self.useNestedLayers then
			if moho.document:CountSelectedLayers() == 1 then
				moho.document:PrepUndo(moho.layer)
			else
				moho.document:PrepUndo()
			end
			self:ScanLayers(moho)
		else
			if moho.document:CountSelectedLayers() == 1 then
				moho.document:PrepUndo(moho.layer, true)
			else
				moho.document:PrepUndo()
			end
			self.channelsList = {}
			for l = 0, moho.document:CountSelectedLayers()-1 do
				local layer = moho.document:GetSelectedLayer(l)
				self:TweenLayer(moho, moho.layer, true)
			end	
		end	
		moho.document:SetDirty()
		self:Tween(moho)
		self.channelsList = {}
		moho:UpdateUI()
		moho.layer:UpdateCurFrame()
		self.sliderVal = self.slider:Value()
	elseif msg == self.IGNORE_SELECTED_BONES then
		self.ignoreSelectedBones = self.ignoreSelectedBonesCheck:Value()	
	elseif msg == self.SELECTED_BONES_ONLY then
		self.selectedBonesOnly = self.selectedBonesOnlyCheck:Value()
		self.ignoreSelectedBonesCheck:Enable(self.selectedBonesOnly)
	elseif msg == self.SELECTED_POINTS_ONLY then
		self.selectedPointsOnly = self.selectedPointsOnlyCheck:Value()		
	elseif msg == self.UPDATE_REFERENCES then
		self:UpdateReferenceLayers(moho)
	elseif msg == self.USE_CAMERA then
		self.useCamera = self.useCameraCheck:Value()	
	elseif msg == self.USE_LAYER_TRANSFORMATION then
		self.useLayerTransformation = self.useLayerTransformationCheck:Value()
	elseif msg == self.USE_NESTED_LAYERS then
		self.useNestedLayers = self.useNestedLayersCheck:Value()
	elseif msg == self.AUTO_BAKE then
		self.autoBake = self.autoBakeCheck:Value()
		self.intervalPopup:Enable(self.autoBake)	
	elseif (msg >= self.INTERVAL_1 and msg <= self.INTERVAL_4) then
		local int = 1
		if (msg == self.INTERVAL_1) then
			int = 1
		elseif (msg == self.INTERVAL_2) then
			int = 2
		elseif (msg == self.INTERVAL_3) then
			int = 3
		elseif (msg == self.INTERVAL_4) then
			int = 4
		end	
		self.interval = int
	end
end

function MR_TweenMachine:Tween(moho)
	if self.channelsList then
		for i=1, #self.channelsList do
			local channel = self.channelsList[i]
			if channel then
				self:TweenChannel(moho, channel, nil, false)
			end
		end
	end	
end

function MR_TweenMachine:TweenLayer(moho, layer, scan)
	local layer = layer or moho.layer
	local skel = nil
	local mesh = nil
	if moho:LayerAsBone(layer) then
		skel = moho:LayerAsBone(layer):Skeleton()
	end
	if moho:LayerAsVector(layer) then
		mesh = moho:LayerAsVector(layer):Mesh()
	end
	self.isKeysSelected = false
	
	local targetBonesList = {}
	if scan and self.ignoreTargetboneAngle and skel then
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			for b = 0, skel:CountBones() - 1 do
				local isTargetFound = false
				local targetBoneCandidat = skel:Bone(b)
				if targetBoneCandidat.fParent == -1 then
					if bone.fTargetBone.value == b then
						isTargetFound = true
					else	
						for actionID = 0, bone.fTargetBone:CountActions() - 1 do
							local actionChannel = moho:ChannelAsAnimVal(bone.fTargetBone:Action(actionID))
							if actionChannel ~= nil then
								for keyID = 0, actionChannel:CountKeys() - 1 do
									local actionFrame = actionChannel:GetKeyWhen(keyID)
									if (actionFrame > 0) then
										if actionChannel:GetValue(actionFrame) == b then
											isTargetFound = true
											break
										end
									end
								end
							end
						end	
					end
					local isCandidatSmartbone = false
					for i=0, targetBoneCandidat.fAnimAngle:CountActions() -1 do
						local actioName = targetBoneCandidat.fAnimAngle:ActionName(i)
						if string.find(actioName, targetBoneCandidat:Name()) then
							isCandidatSmartbone = true
						end	
					end
					
					if isTargetFound and isCandidatSmartbone and skel:CountBoneChildren(b) == 0 then
						local isBoneNotInList = true
						for k, tBoneId in pairs(targetBonesList) do
							if tBoneId == b then
								isBoneNotInList = false
								break
							end
						end
						if isBoneNotInList then
							table.insert(targetBonesList, b)
							break
						end	
					end
				end	
			end
		end
	end	
	
	if skel then
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			if ((bone.fSelected and self.selectedBonesOnly and not self.ignoreSelectedBones) or (not bone.fSelected and self.selectedBonesOnly and self.ignoreSelectedBones))or not self.selectedBonesOnly then
				if (not self.ignoreHiddenBones or (not (bone.fHidden and not bone.fShy and self.ignoreHiddenBones)))
				and (not self.ignoreShyBones or (not (bone.fHidden and bone.fShy and self.ignoreShyBones))) then
					if self.useBonesAngle then
						if  self.ignoreTargetboneAngle and scan then
							local isBoneTarget = false
							for k, tBoneId in pairs(targetBonesList) do
								if tBoneId == i then
									isBoneTarget = true
									break
								end
							end
							if not isBoneTarget then
								self:TweenChannel(moho, bone.fAnimAngle, layer, scan)
							end
						else
							self:TweenChannel(moho, bone.fAnimAngle, layer, scan)
						end
					end
					if self.useBonesPosition then
						self:TweenChannel(moho, bone.fAnimPos, layer, scan)
					end
					if self.useBonesScale then
						self:TweenChannel(moho, bone.fAnimScale, layer, scan)
					end
				end	
			end	
		end
	elseif mesh then
		for i = 0, mesh:CountPoints() - 1 do
			local point = mesh:Point(i)
			if point.fSelected or not self.selectedPointsOnly then
				if self.usePointsPosition then
					self:TweenChannel(moho, point.fAnimPos, layer, scan)
				end	
				if self.usePointsWidth then
					self:TweenChannel(moho, point.fWidth, layer, scan)
				end	
				if self.usePointsCurvature then
					for c = 0, point:CountCurves() - 1 do
						local myCurve, where = point:Curve(c)
						local curvatureChannel = myCurve:Curvature(where)
						self:TweenChannel(moho, curvatureChannel, layer, scan)
						if AE_Utilities then
							local curvatureOffsetChannel1 = AE_Utilities:GetOffsetChannel(moho, layer, myCurve, where, false)
							local curvatureOffsetChannel2 = AE_Utilities:GetOffsetChannel(moho, layer, myCurve, where, true)
							local curvatureWeightChannel1 = AE_Utilities:GetWeightChannel(moho, layer, myCurve, where, false)
							local curvatureWeightChannel2 = AE_Utilities:GetWeightChannel(moho, layer, myCurve, where, true)
							self:TweenChannel(moho, curvatureOffsetChannel1, layer, scan)
							self:TweenChannel(moho, curvatureOffsetChannel2, layer, scan)
							self:TweenChannel(moho, curvatureWeightChannel1, layer, scan)
							self:TweenChannel(moho, curvatureWeightChannel2, layer, scan)
						end	
					end
				end	
			end	
		end
	end

	if self.useLayerTransformation then
		if self.useLayerPosition then
			self:TweenChannel(moho, layer.fTranslation, layer, scan)
		end
		if self.useLayerRotationX then
			self:TweenChannel(moho, layer.fRotationX, layer, can)
		end
		if self.useLayerRotationY then
			self:TweenChannel(moho, layer.fRotationY, layer, scan)
		end
		if self.useLayerRotationZ then
			self:TweenChannel(moho, layer.fRotationZ, layer, scan)
		end
		if self.useLayerScale then
			self:TweenChannel(moho, layer.fScale, layer, scan)
		end
		if self.useLayerShear then
			self:TweenChannel(moho, layer.fShear, layer, scan)
		end
		if self.useLayerFollowing then
			self:TweenChannel(moho, layer.fFollowing, layer, scan)
		end
		if self.useLayerFollowing then
			self:TweenChannel(moho, layer.fAlpha, layer, scan)
		end	
	end
	if self.useCamera then
		if self.useCameraTrack then
			self:TweenChannel(moho, moho.document.fCameraTrack, nil, scan)
		end	
		if self.useCameraPanTilt then
			self:TweenChannel(moho, moho.document.fCameraPanTilt, nil, scan)
		end	
		if self.useCameraZoom then
			self:TweenChannel(moho, moho.document.fCameraZoom, nil, scan)
		end	
		if self.useCameraRoll then
			self:TweenChannel(moho, moho.document.fCameraRoll, nil, scan)
		end	
	end
	moho:UpdateSelectedChannels()
end

function MR_TweenMachine:TweenChannel(moho, channel, layer, scan)
	local layer = layer or moho.layer
	if not channel then
		return
	end
	
	local curFrame = layer:TotalTimingOffset() + moho.frame
	if curFrame == 0 then
		return
	end
	
	local chanType = channel:ChannelType()
	local vec3 = false
	local dimentionsSplit = false
	
	if chanType == MOHO.CHANNEL_VEC3 then
		vec3 = true
	end
	if chanType == MOHO.CHANNEL_VEC3 or chanType == MOHO.CHANNEL_VEC2 then
		if channel:AreDimensionsSplit() then
			dimentionsSplit = true
		end
	end
	
	if dimentionsSplit then
		for c = 0, 2 do
			local subChannel = channel:DimensionChannel(c)
			if subChannel then
				if (c == 0 and self.useX) or (c == 1 and self.useY) or (c == 2 and self.useZ) then
					if subChannel:Duration() > 0 then
						if scan then
							table.insert(self.channelsList, subChannel)
						else
							if self.autoBake then
								self:BakeChannel(moho, subChannel, curFrame, self.interval)
							end
							local currentKeyID = subChannel:GetClosestKeyID(curFrame)
							local prewKey = currentKeyID
							local nextKey = currentKeyID + 1
							if(subChannel:HasKey(curFrame)) then
								prewKey = currentKeyID - 1
								nextKey = currentKeyID + 1
							end	
							
							if nextKey > subChannel:CountKeys() then
								return
							end
							
							local prewVal = subChannel:GetValue(subChannel:GetKeyWhen(prewKey))
							local nextVal = subChannel:GetValue(subChannel:GetKeyWhen(nextKey))
						
							if prewVal and nextVal then
								local newVal = (nextVal - prewVal) * self.sliderVal/100 + prewVal
								local oldVal = subChannel:GetValue(curFrame)
								if AE_Utilities then
									if not AE_Utilities:IsEqualValues(subChannel, newVal, oldVal) then
										subChannel:SetValue(curFrame, newVal)
									end
								else
									subChannel:SetValue(curFrame, newVal)
								end
							end
						end
					end
				end	
			end
		end
	else
		if channel:Duration() > 0 then
			if scan then
				table.insert(self.channelsList, channel)
			else
				if self.autoBake then
					self:BakeChannel(moho, channel, curFrame, self.interval)
				end
				local currentKeyID = channel:GetClosestKeyID(curFrame)
				local prewKey = currentKeyID
				local nextKey = currentKeyID + 1
				if(channel:HasKey(curFrame)) then
					prewKey = currentKeyID - 1
					nextKey = currentKeyID + 1
				end

				if nextKey >= channel:CountKeys() then
					return
				end
				local prewVal = channel:GetValue(channel:GetKeyWhen(prewKey))
				local nextVal = channel:GetValue(channel:GetKeyWhen(nextKey))
				local curVal = channel:GetValue(curFrame)

				if prewVal and nextVal then
					local newVal = (nextVal - prewVal) * self.sliderVal/100 + prewVal
					if chanType == MOHO.CHANNEL_VEC2 then
						if not self.useX then
							newVal:Set(curVal.x, newVal.y)
						end
						if not self.useY then
							newVal:Set(newVal.x, curVal.y)
						end
					elseif chanType == MOHO.CHANNEL_VEC3 then
						if not self.useX then
							newVal:Set(curVal.x, newVal.y, newVal.z)
						end
						if not self.useY then
							newVal:Set(newVal.x, curVal.y, newVal.z)
						end
						if not self.useZ then
							newVal:Set(newVal.x, newVal.y, curVal.z)
						end
					end
		
					local oldVal = channel:GetValue(curFrame)
					if AE_Utilities then
						if not AE_Utilities:IsEqualValues(channel, newVal, oldVal) then
							channel:SetValue(curFrame, newVal)
						end
					else
						channel:SetValue(curFrame, newVal)
					end
				end
			end	
		end
	end	
end

function MR_TweenMachine:BakeChannel(moho, channel, frame, interval)
	local prewFrame = frame - interval
	local nextFrame = frame + interval
	if prewFrame > 0 then
		channel:SetValue(prewFrame, channel:GetValue(prewFrame))
	end
	channel:SetValue(nextFrame, channel:GetValue(nextFrame))
end

function MR_TweenMachine:UpdateReferenceLayers(moho)
	local count = 0
	repeat
		local layer = moho.document:LayerByAbsoluteID(count)
		if layer then
			if layer:IsReferencedLayer() then
				layer:MarkReferenceOutdated()
			end
			layer:UpdateCurFrame()
			count = count + 1
		end
	until not layer
	
	moho.layer:UpdateCurFrame()
	moho:UpdateUI()
end

function MR_TweenMachine:ScanLayers(moho)
	self.channelsList = {}
	local count = 0
	repeat
		local layer = moho.document:LayerByAbsoluteID(count)
		if layer then
			if self.autoUpdateReferences and layer:IsReferencedLayer() then
				table.insert(self.referenceLayersList, count)
			end
			count = count + 1
			if layer:IsAncestorSelected() or layer:SecondarySelection() or layer == moho.layer then
				if not self.ignoreReferenceLayers or (not layer:IsReferencedLayer() and self.ignoreReferenceLayers) then
					if layer:AnimDuration() > 0 then
						self:TweenLayer(moho, layer, true)
					end
				end	
			end
		end
	until not layer
end

function MR_TweenMachine:GetMohoVersion(moho)
	local numVers = {}
	local vers = moho:AppVersion()
	for n in string.gmatch (vers, "%d+") do
		table.insert(numVers, tonumber(n))
	end
	return numVers[1], numVers[2], numVers[3]
end

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

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

	phrase['Description'] = 'This script is very helpful in controlling the rhythm of animation. Create overshoots and just adjust the spacing.'
	phrase['UILabel'] = 'MR Tween Machine'
	
	phrase['Settings'] = 'Settings'
	
	phrase['   Select all   '] = '                              Select all                            '
	phrase['   Deselect all   '] = '                            Deselect all                            '
	
	phrase['Bones settings:'] = 'Bones settings:'
	phrase['Select all'] = 'Select all'
	phrase['Deselect all'] = 'Deselect all'
	phrase['Bones settings:'] = 'Bones settings:'
	phrase['Use angle channel'] = 'Use angle channel'
	phrase['Points settings:'] = 'Points settings:'
	phrase['Use scale channel'] = 'Use scale channel'
	phrase['Use position channel'] = 'Use position channel'
	phrase['Use curvature channel'] = 'Use curvature channel'
	phrase['Use width channel'] = 'Use width channel'
	phrase['Layers settings:'] = 'Layers settings:'
	phrase['Use rotation X channel'] = 'Use rotation X channel'
	phrase['Use rotation Y channel'] = 'Use rotation Y channel'
	phrase['Use rotation Z channel'] = 'Use rotation Z channel'
	phrase['Use shear channel'] = 'Use shear channel'
	phrase['Use following channel'] = 'Use following channel'
	phrase['Use alpha channel'] = 'Use alpha channel'
	phrase['Camera settings:'] = 'Camera settings:'
	phrase['Use track channel'] = 'Use track channel'
	phrase['Use pan tilt channel'] = 'Use pan tilt channel'
	phrase['Use zoom channel'] = 'Use zoom channel'
	phrase['Use roll channel'] = 'Use roll channel'
	phrase['Multidimention channels settings:'] = 'Multidimention channels settings:'
	phrase['Ignore settings:'] = 'Ignore settings:'
	phrase['Ignore hidden bones'] = 'Ignore hidden bones'
	phrase['Ignore hidden points'] = 'Ignore hidden points'
	phrase['Ignore shy bones'] = 'Ignore shy bones'
	phrase['Ignore hidden layers'] = 'Ignore hidden layers'
	phrase['Ignore reference layers'] = 'Ignore reference layers'
	phrase['Ignore target bones angle'] = 'Ignore target bones angle'
	
	phrase['Selected channels only'] = 'Selected channels only'
	phrase['Ignore selected bones'] = 'Ignore selected bones'
	phrase['Selected bones only'] = 'Selected bones only'
	phrase['Selected points only'] = 'Selected points only'
	phrase['Update all layers'] = 'Update all layers'
	phrase['Use X dimention'] = 'Use X dimention'
	phrase['Use Y dimention'] = 'Use Y dimention'
	phrase['Use Z dimention'] = 'Use Z dimention'
	phrase['Camera'] = 'Camera'
	phrase['Layer Transformation'] = 'Layer Transformation'
	phrase['Auto bake adjacent frames'] = 'Auto bake adjacent frames'
	phrase['Interval:'] = 'Interval:'
	phrase['Use nested layers'] = 'Use nested layers'
	return phrase[text]
end

Icon
MR Tween Machine
Listed

Script type: Tool

Uploaded: Mar 19 2023, 17:02

Last modified: Mar 22 2023, 08:19

This script is very helpful in controlling the rhythm of the animation. Create overshoots and just adjust the spacing.
The Tween Machine is a script written by Davoodice. I love that script and it has helped me many times. The link to the original script: https://mohoscripts.com/script/DV_TweenMachine

Unfortunately, the original has some issues that can prevent it from working correctly. So, I rewrote it almost from scratch to get rid of those problems and have the ability to develop it in my own vision.



Forum page
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: 299