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 '2.2.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
	self.modelessDialogSupport = false
	
	if v1 >= 14 and v2 >= 1 then
		self.modelessDialogSupport = true
	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
-- **************************************************

MR_TweenMachine.sliderMode = 1

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.blockOnEvenFrames = false
MR_TweenMachine.blockOnOddFrames = false

MR_TweenMachine.sliderSize1 = 1
MR_TweenMachine.sliderSize2 = 1

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.sliderVal2 = 0
MR_TweenMachine.slidertextVal2 = 0
MR_TweenMachine.isKeysSelected = false
MR_TweenMachine.isMouseDragging = false
MR_TweenMachine.selRect = LM.Rect:new_local()
MR_TweenMachine.channelsList = {}
MR_TweenMachine.channelsValList = {}
MR_TweenMachine.referenceLayersList = {}

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.blockOnEvenFrames = prefs:GetBool("MR_TweenMachine.blockOnEvenFrames", false)
	self.blockOnOddFrames = prefs:GetBool("MR_TweenMachine.blockOnOddFrames", false)
	
	self.sliderSize1 = prefs:GetFloat("MR_TweenMachine.sliderSize1", 1)
	self.sliderSize2 = prefs:GetFloat("MR_TweenMachine.sliderSize2", 1)
	
	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.blockOnEvenFrames", self.blockOnEvenFrames)
	prefs:SetBool("MR_TweenMachine.blockOnOddFrames", self.blockOnOddFrames)
	
	prefs:SetFloat("MR_TweenMachine.sliderSize1", self.sliderSize1)
	prefs:SetFloat("MR_TweenMachine.sliderSize2", self.sliderSize2)

	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.sliderSize1 = 1
	self.sliderSize2 = 1
	
	self.blockOnEvenFrames = false
	self.blockOnOddFrames = 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

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
MR_SettingsDialog.BLOCK_ON_EVEN_FRAMES = MOHO.MSG_BASE + 35
MR_SettingsDialog.BLOCK_ON_ODD_FRAMES = MOHO.MSG_BASE + 36
MR_SettingsDialog.SLIDER_1_SIZE = MOHO.MSG_BASE + 37
MR_SettingsDialog.SLIDER_2_SIZE = MOHO.MSG_BASE + 38
MR_SettingsDialog.APPLY_SLIDERS_SIZE_SETTINGS = MOHO.MSG_BASE + 39

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)
		
		l:AddPadding(-4)
		
		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:'), 0)
			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:'), 0)
			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:'), 0)
			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:'), 0)
			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)
	
	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(60)
		
		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(60)
		
		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)
	
	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(57)
	
		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(38)
			
		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()
	
	l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
	
	l:PushH()
			
		d.blockOnEvenFramesCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Block on even frames'), self.BLOCK_ON_EVEN_FRAMES)
		l:AddChild(d.blockOnEvenFramesCheck, LM.GUI.ALIGN_LEFT, 0)
		
		l:AddPadding(34)
	
		d.blockOnOddFramesCheck = LM.GUI.CheckBox(MR_TweenMachine:Localize('Block on odd frames'), self.BLOCK_ON_ODD_FRAMES)
		l:AddChild(d.blockOnOddFramesCheck, LM.GUI.ALIGN_LEFT, 0)
		
	l:Pop()	
	
	l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
	
	l:PushH()
			
		d.sliderSize1Input = LM.GUI.TextControl(0, '100', self.SLIDER_1_SIZE, LM.GUI.FIELD_FLOAT, MR_TweenMachine:Localize('Slider 1 Size'))
		d.sliderSize1Input:SetWheelInc(0.01)
		l:AddChild(d.sliderSize1Input, LM.GUI.ALIGN_LEFT, 0)
		
		l:AddPadding(5)
		
		d.sliderSize2Input = LM.GUI.TextControl(0, '100', self.SLIDER_2_SIZE, LM.GUI.FIELD_FLOAT, MR_TweenMachine:Localize('Slider 2 Size'))
		d.sliderSize2Input:SetWheelInc(0.01)
		l:AddChild(d.sliderSize2Input, LM.GUI.ALIGN_LEFT, 0)
		
		l:AddPadding(5)
		
		d.applyButton = LM.GUI.ShortButton(MR_TweenMachine:Localize('Apply sliders size settings'), self.APPLY_SLIDERS_SIZE_SETTINGS)
		l:AddChild(d.applyButton, 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)
	
	self.blockOnEvenFramesCheck:SetValue(MR_TweenMachine.blockOnEvenFrames)
	self.blockOnOddFramesCheck:SetValue(MR_TweenMachine.blockOnOddFrames)

	self.sliderSize1Input:SetValue(LM.Clamp(MR_TweenMachine.sliderSize1, 0.3, 2))
	self.sliderSize2Input:SetValue(LM.Clamp(MR_TweenMachine.sliderSize2, 0.3, 2))
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()
	
	MR_TweenMachine.blockOnEvenFrames = self.blockOnEvenFramesCheck:Value()
    MR_TweenMachine.blockOnOddFrames = self.blockOnOddFramesCheck:Value()

	local helper = MOHO.ScriptInterfaceHelper:new_local()
	local moho = helper:MohoObject()
	if moho:CurrentTool() == 'MR_TweenMachine' then
		MR_TweenMachine:UpdateWidgets(moho)
		if MR_TweenMachine.dlog then
			MR_TweenMachine.dlog:UpdateWidgets(moho)
		end
	end
	
	local frame = moho.frame
	self.frame = frame
	if MR_TweenMachine.blockOnEvenFrames and frame % 2 == 0 or MR_TweenMachine.blockOnOddFrames and not (frame % 2 == 0) or frame == 0 then
		if MR_TweenMachine.tweenMachineDlog then
			MR_TweenMachine.tweenMachineDlog.slider:Enable(false)
			MR_TweenMachine.tweenMachineDlog.slider2:Enable(false)
			MR_TweenMachine.tweenMachineDlog.slidertext:Enable(false)
			MR_TweenMachine.tweenMachineDlog.slidertext2:Enable(false)
		end
	else
		if MR_TweenMachine.tweenMachineDlog then
			MR_TweenMachine.tweenMachineDlog.slider:Enable(true)
			MR_TweenMachine.tweenMachineDlog.slider2:Enable(true)
			MR_TweenMachine.tweenMachineDlog.slidertext:Enable(true)
			MR_TweenMachine.tweenMachineDlog.slidertext2:Enable(true)
		end
	end

	helper:delete()
	
	if MR_TweenMachine.tweenMachineDlog then
		MR_TweenMachine.tweenMachineDlog.dlog:UpdateWidgets(moho)
	end
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()	
	elseif msg == self.BLOCK_ON_EVEN_FRAMES then
		MR_TweenMachine.blockOnEvenFrames = self.blockOnEvenFramesCheck:Value()
	elseif msg == self.BLOCK_ON_ODD_FRAMES then
		MR_TweenMachine.blockOnOddFrames = self.blockOnOddFramesCheck:Value()
	elseif msg == self.SLIDER_1_SIZE then
		self.sliderSize1Input:SetValue(LM.Clamp(self.sliderSize1Input:FloatValue(), 0.3, 2))
	elseif msg == self.SLIDER_2_SIZE then
		self.sliderSize2Input:SetValue(LM.Clamp(self.sliderSize2Input:FloatValue(), 0.3, 2))
	elseif msg == self.APPLY_SLIDERS_SIZE_SETTINGS then
		MR_TweenMachine.sliderSize1 = LM.Clamp(self.sliderSize1Input:FloatValue(), 0.3, 2)
		MR_TweenMachine.sliderSize2 = LM.Clamp(self.sliderSize2Input:FloatValue(), 0.3, 2)
		if MR_TweenMachine.modelessDialogSupport then
			local helper = MOHO.ScriptInterfaceHelper:new_local()
			local moho = helper:MohoObject()
			MR_TweenMachine:UpgateLayout(moho)
			helper:delete()
		end
    end
end

-- **************************************************
-- Panel
-- **************************************************

local MR_TweenMachineDialog = {}

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

function MR_TweenMachineUpdateDialog(moho)
	if MR_TweenMachine.tweenMachineDlog ~= nil then
		MR_TweenMachine.tweenMachineDlog:UpdateWidgets()
	end
end

table.insert(MOHO.UpdateTable, MR_TweenMachineUpdateDialog)

function MR_TweenMachineDialog:new(moho)
    local d = LM.GUI.SimpleDialog(MR_TweenMachine:Localize('UILabel'), MR_TweenMachineDialog)
    local l = d:GetLayout()

	l:PushH()
	
		d.slider = LM.GUI.Slider(450, false, false, self.SLIDER)
		l:AddChild(d.slider)
		d.slider:SetRange(-100,200)
		d.slider:SetNumTicks(3)
		d.slider:SetShowTicks(true)
		d.slider:SetSnapToTicks(false)
		d.slider:SetFatSlider(true)
		d.slidertext = LM.GUI.TextControl(30, "0", self.SLIDER_TEXT, LM.GUI.FIELD_INT, MOHO.Localize(""))
		d.slidertext:SetWheelInc(1)
		l:AddChild(d.slidertext)
		l:AddPadding(-15)
		d.perc = LM.GUI.StaticText(MR_TweenMachine:Localize('%'))
		l:AddChild(d.perc)
	
	l:Pop()
	
	l:PushH()
	
		d.slider2 = LM.GUI.Slider(450, false, false, self.SLIDER_2)
		l:AddChild(d.slider2)
		d.slider2:SetRange(-200, 200)
		d.slider2:SetNumTicks(4)
		d.slider2:SetShowTicks(true)
		d.slider2:SetSnapToTicks(false)
		d.slider2:SetFatSlider(true)
		d.slidertext2 = LM.GUI.TextControl(30, "0", self.SLIDER_TEXT_2, LM.GUI.FIELD_INT, MOHO.Localize(""))
		d.slidertext2:SetWheelInc(1)
		l:AddChild(d.slidertext2)
		l:AddPadding(-15)
		d.perc2 = LM.GUI.StaticText(MR_TweenMachine:Localize('%'))
		l:AddChild(d.perc2)
	
	l:Pop()
	
	l:PushH()
	
		l:AddPadding(2)
	
		d.dlog = MR_SettingsDialog:new()
		d.settingsPopup = LM.GUI.PopupDialog(MR_TweenMachine:Localize('Settings'), false, 0)
		d.settingsPopup:SetDialog(d.dlog)
		l:AddChild(d.settingsPopup, LM.GUI.ALIGN_LEFT, 0)
	
		d.ignoreSelectedBonesCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_invert_bone_selection', MR_TweenMachine:Localize('Ignore selected bones'), true, self.IGNORE_SELECTED_BONES, false)
		l:AddChild(d.ignoreSelectedBonesCheck, LM.GUI.ALIGN_LEFT, 0)
		
		d.selectedBonesOnlyCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_selected_bones_only', MR_TweenMachine:Localize('Selected bones only'), true, self.SELECTED_BONES_ONLY, false)
		l:AddChild(d.selectedBonesOnlyCheck, LM.GUI.ALIGN_LEFT, 0)
		
		d.selectedPointsOnlyCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_selected_points_only', MR_TweenMachine:Localize('Selected points only'), true, self.SELECTED_POINTS_ONLY, false)
		l:AddChild(d.selectedPointsOnlyCheck, LM.GUI.ALIGN_LEFT, 0)
		
		d.updateReferencesButton = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_update_ref', MR_TweenMachine:Localize('Update all layers'), false, MR_TweenMachine.UPDATE_REFERENCES, false)
		l:AddChild(d.updateReferencesButton, LM.GUI.ALIGN_LEFT, 0)
		
		l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
		
		d.useCameraCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_camera', MR_TweenMachine:Localize('Camera'), true, self.USE_CAMERA, false)
		l:AddChild(d.useCameraCheck, LM.GUI.ALIGN_LEFT, 0)
		
		d.useLayerTransformationCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_transfrorm_layer', MR_TweenMachine:Localize('Layer Transformation'), true, self.USE_LAYER_TRANSFORMATION, false)
		l:AddChild(d.useLayerTransformationCheck, LM.GUI.ALIGN_LEFT, 0)
		
		l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
		
		d.autoBakeCheck = LM.GUI.ImageButton('ScriptResources/mr_tween_machine/mr_auto_bake', MR_TweenMachine:Localize('Auto bake adjacent frames'), true, self.AUTO_BAKE, false)
		l:AddChild(d.autoBakeCheck, LM.GUI.ALIGN_LEFT, 0)
		
		l:AddChild(LM.GUI.StaticText(MR_TweenMachine:Localize("Interval:")))

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

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

function MR_TweenMachineDialog:UpdateWidgets(moho)
	local helper = MOHO.ScriptInterfaceHelper:new_local()
	local moho = helper:MohoObject()
	local frame = moho.frame
	helper:delete()
	
	if MR_TweenMachine.blockOnEvenFrames and frame % 2 == 0 or MR_TweenMachine.blockOnOddFrames and not (frame % 2 == 0) or frame == 0 then
		MR_TweenMachine.tweenMachineDlog.slider:Enable(false)
		MR_TweenMachine.tweenMachineDlog.slider2:Enable(false)
		MR_TweenMachine.tweenMachineDlog.slidertext:Enable(false)
		MR_TweenMachine.tweenMachineDlog.slidertext2:Enable(false)
	else
		MR_TweenMachine.tweenMachineDlog.slider:Enable(true)
		MR_TweenMachine.tweenMachineDlog.slider2:Enable(true)
		MR_TweenMachine.tweenMachineDlog.slidertext:Enable(true)
		MR_TweenMachine.tweenMachineDlog.slidertext2:Enable(true)
	end
	
	self.ignoreSelectedBonesCheck:SetValue(MR_TweenMachine.ignoreSelectedBones)
	self.ignoreSelectedBonesCheck:Enable(MR_TweenMachine.selectedBonesOnly)
	self.selectedBonesOnlyCheck:SetValue(MR_TweenMachine.selectedBonesOnly)
	self.selectedPointsOnlyCheck:SetValue(MR_TweenMachine.selectedPointsOnly)
	self.useCameraCheck:SetValue(MR_TweenMachine.useCamera)
	self.useLayerTransformationCheck:SetValue(MR_TweenMachine.useLayerTransformation)
	self.autoBakeCheck:SetValue(MR_TweenMachine.autoBake)
	self.useNestedLayersCheck:SetValue(MR_TweenMachine.useNestedLayers)
	self.slider:SetValue(MR_TweenMachine.sliderVal)
	self.slidertext:SetValue(MR_TweenMachine.slidertextVal)
	
	if MR_TweenMachine.interval < 1 or MR_TweenMachine.interval > 4 or MR_TweenMachine.interval == nil then
		MR_TweenMachine.interval = 1
	end
	
	self.intervalMenu:SetChecked(self.INTERVAL_1, false)
	self.intervalMenu:SetChecked(self.INTERVAL_2, false)
	self.intervalMenu:SetChecked(self.INTERVAL_3, false)
	self.intervalMenu:SetChecked(self.INTERVAL_4, false)
	
	if (MR_TweenMachine.interval == 1) then
		self.intervalMenu:SetChecked(self.INTERVAL_1, true)
	elseif (MR_TweenMachine.interval == 2) then
		self.intervalMenu:SetChecked(self.INTERVAL_2, true)
	elseif (MR_TweenMachine.interval == 3) then
		self.intervalMenu:SetChecked(self.INTERVAL_3, true)
	elseif (MR_TweenMachine.interval == 4) then
		self.intervalMenu:SetChecked(self.INTERVAL_4, true)
	end

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

function MR_TweenMachineDialog:HandleMessage(msg)
	local helper = MOHO.ScriptInterfaceHelper:new_local()
	local moho = helper:MohoObject()
	if moho.document == nil then
		if msg == self.SLIDER_2 then
			self.slider2:SetValue(0)
		end
		helper:delete()
		return
	end
	
	if msg == self.SLIDER then
		MR_TweenMachine.sliderMode = 1
		if not MR_TweenMachine.undoPrepped then
			if MR_TweenMachine.useNestedLayers then
				if moho.document:CountSelectedLayers() == 1 then
					moho.document:PrepUndo(moho.layer)
				else
					moho.document:PrepUndo()
				end
				MR_TweenMachine:ScanLayers(moho)
			else
				if moho.document:CountSelectedLayers() == 1 then
					moho.document:PrepUndo(moho.layer, true)
				else
					moho.document:PrepUndo()
				end
				MR_TweenMachine.channelsList = {}
				MR_TweenMachine.channelsValList = {}
				for l = 0, moho.document:CountSelectedLayers()-1 do
					local layer = moho.document:GetSelectedLayer(l)
					MR_TweenMachine:TweenLayer(moho, layer, true)
				end	
			end	
			moho.document:SetDirty()
			MR_TweenMachine.undoPrepped = true
		end
		self.slidertext:SetValue(self.slider:Value())
		MR_TweenMachine.slidertextVal = self.slider:Value()
		MR_TweenMachine.sliderVal = self.slider:Value()
		MR_TweenMachine:Tween(moho)
		moho.layer:UpdateCurFrame()
		if(not self.slider:IsMouseDragging()) then	
			MR_TweenMachine.undoPrepped = false
			moho:UpdateUI()
			MR_TweenMachine.channelsList = {}
			self.channelsValList = {}
		end
		moho.view:DrawMe()
	elseif msg == self.SLIDER_TEXT then
		MR_TweenMachine.sliderMode = 1
		MR_TweenMachine.slidertextVal = self.slidertext:FloatValue()
		MR_TweenMachine.sliderVal = self.slidertext:FloatValue()
		self.slider:SetValue(sliderVal)
		if MR_TweenMachine.useNestedLayers then
			if moho.document:CountSelectedLayers() == 1 then
				moho.document:PrepUndo(moho.layer)
			else
				moho.document:PrepUndo()
			end
			MR_TweenMachine:ScanLayers(moho)
		else
			if moho.document:CountSelectedLayers() == 1 then
				moho.document:PrepUndo(moho.layer, true)
			else
				moho.document:PrepUndo()
			end
			MR_TweenMachine.channelsList = {}
			for l = 0, moho.document:CountSelectedLayers()-1 do
				local layer = moho.document:GetSelectedLayer(l)
				MR_TweenMachine:TweenLayer(moho, moho.layer, true)
			end	
		end	
		moho.document:SetDirty()
		MR_TweenMachine:Tween(moho)
		MR_TweenMachine.channelsList = {}
		moho:UpdateUI()
		moho.layer:UpdateCurFrame()
		MR_TweenMachine.sliderVal = self.slider:Value()
		moho.view:DrawMe()
	elseif msg == self.SLIDER_2 then
		MR_TweenMachine.sliderMode = 2
		if not MR_TweenMachine.undoPrepped then
			if MR_TweenMachine.useNestedLayers then
				if moho.document:CountSelectedLayers() == 1 then
					moho.document:PrepUndo(moho.layer)
				else
					moho.document:PrepUndo()
				end
				MR_TweenMachine:ScanLayers(moho)
			else
				if moho.document:CountSelectedLayers() == 1 then
					moho.document:PrepUndo(moho.layer, true)
				else
					moho.document:PrepUndo()
				end
				MR_TweenMachine.channelsList = {}
				MR_TweenMachine.channelsValList = {}
				for l = 0, moho.document:CountSelectedLayers()-1 do
					local layer = moho.document:GetSelectedLayer(l)
					MR_TweenMachine:TweenLayer(moho, layer, true)
				end	
			end	
			moho.document:SetDirty()
			MR_TweenMachine.undoPrepped = true
		end
		self.slidertext2:SetValue(self.slider2:Value())
		MR_TweenMachine.slidertextVal2 = self.slider2:Value()
		MR_TweenMachine.sliderVal2 = self.slider2:Value()
		MR_TweenMachine:Tween(moho)
		moho.layer:UpdateCurFrame()
		if(not self.slider2:IsMouseDragging()) then	
			MR_TweenMachine.undoPrepped = false
			moho:UpdateUI()
			MR_TweenMachine.channelsList = {}
			MR_TweenMachine.channelsValList = {}
			
			self.slidertext2:SetValue(0)
			MR_TweenMachine.slidertextVal2 = 0
			MR_TweenMachine.sliderVal2 = 0
			self.slider2:SetValue(0)
		end
		moho.view:DrawMe()
	elseif msg == self.SLIDER_TEXT_2 then
		MR_TweenMachine.sliderMode = 2
		MR_TweenMachine.slidertextVal2 = self.slidertext2:FloatValue()
		MR_TweenMachine.sliderVal2 = self.slidertext2:FloatValue()
		self.slider2:SetValue(sliderVal2)
		if MR_TweenMachine.useNestedLayers then
			if moho.document:CountSelectedLayers() == 1 then
				moho.document:PrepUndo(moho.layer)
			else
				moho.document:PrepUndo()
			end
			MR_TweenMachine:ScanLayers(moho)
		else
			if moho.document:CountSelectedLayers() == 1 then
				moho.document:PrepUndo(moho.layer, true)
			else
				moho.document:PrepUndo()
			end
			MR_TweenMachine.channelsList = {}
			MR_TweenMachine.channelsValList = {}
			for l = 0, moho.document:CountSelectedLayers()-1 do
				local layer = moho.document:GetSelectedLayer(l)
				MR_TweenMachine:TweenLayer(moho, moho.layer, true)
			end	
		end	
		moho.document:SetDirty()
		MR_TweenMachine:Tween(moho)
		MR_TweenMachine.channelsList = {}
		MR_TweenMachine.channelsValList = {}
		moho:UpdateUI()
		moho.layer:UpdateCurFrame()
		MR_TweenMachine.sliderVal2 = self.slider2:Value()	
		moho.view:DrawMe()
	elseif msg == self.IGNORE_SELECTED_BONES then
		MR_TweenMachine.ignoreSelectedBones = self.ignoreSelectedBonesCheck:Value()	
		if moho:CurrentTool() == 'MR_TweenMachine' then
			MR_TweenMachine:UpdateWidgets(moho)
		end
	elseif msg == self.SELECTED_BONES_ONLY then
		MR_TweenMachine.selectedBonesOnly = self.selectedBonesOnlyCheck:Value()
		self.ignoreSelectedBonesCheck:Enable(MR_TweenMachine.selectedBonesOnly)
		if moho:CurrentTool() == 'MR_TweenMachine' then
			MR_TweenMachine:UpdateWidgets(moho)
		end
	elseif msg == self.SELECTED_POINTS_ONLY then
		MR_TweenMachine.selectedPointsOnly = self.selectedPointsOnlyCheck:Value()	
		if moho:CurrentTool() == 'MR_TweenMachine' then
			MR_TweenMachine:UpdateWidgets(moho)
		end
	elseif msg == self.UPDATE_REFERENCES then
		MR_TweenMachine:UpdateReferenceLayers(moho)
		if moho:CurrentTool() == 'MR_TweenMachine' then
			MR_TweenMachine:UpdateWidgets(moho)
		end
		local curFrame = moho.frame
		if curFrame > 0 then
			moho:SetCurFrame(0)
			moho:SetCurFrame(curFrame)
		elseif curFrame == 0 then
			moho:SetCurFrame(1)
			moho:SetCurFrame(curFrame)
		end
	elseif msg == self.USE_CAMERA then
		MR_TweenMachine.useCamera = self.useCameraCheck:Value()	
		if moho:CurrentTool() == 'MR_TweenMachine' then
			MR_TweenMachine:UpdateWidgets(moho)
		end
	elseif msg == self.USE_LAYER_TRANSFORMATION then
		MR_TweenMachine.useLayerTransformation = self.useLayerTransformationCheck:Value()
		if moho:CurrentTool() == 'MR_TweenMachine' then
			MR_TweenMachine:UpdateWidgets(moho)
		end
	elseif msg == self.USE_NESTED_LAYERS then
		MR_TweenMachine.useNestedLayers = self.useNestedLayersCheck:Value()
		if moho:CurrentTool() == 'MR_TweenMachine' then
			MR_TweenMachine:UpdateWidgets(moho)
		end
	elseif msg == self.AUTO_BAKE then
		MR_TweenMachine.autoBake = self.autoBakeCheck:Value()
		self.intervalPopup:Enable(MR_TweenMachine.autoBake)	
		if moho:CurrentTool() == 'MR_TweenMachine' then
			MR_TweenMachine:UpdateWidgets(moho)
		end
	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	
		
		MR_TweenMachine.interval = int
		
		if moho:CurrentTool() == 'MR_TweenMachine' then
			MR_TweenMachine:UpdateWidgets(moho)
		end
	end
	helper:delete()
end

function MR_TweenMachineDialog:OnOK(moho)
	MR_TweenMachine.tweenMachineDlog = nil
end

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

function MR_TweenMachine:DoLayout(moho, layout)
	self.slider = LM.GUI.Slider(400 * LM.Clamp(self.sliderSize1, 0.3, 2), 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)
	
	self.slider2 = LM.GUI.Slider(400 * LM.Clamp(self.sliderSize2, 0.3, 2), false,false, self.SLIDER_2)
	layout:AddChild(self.slider2)
	self.slider2:SetRange(-200, 200)
	self.slider2:SetNumTicks(4)
	self.slider2:SetShowTicks(true)
	self.slider2:SetSnapToTicks(false)
	self.slider2:SetFatSlider(true)
	
	self.slidertext2 = LM.GUI.TextControl(30, "0", self.SLIDER_TEXT_2, LM.GUI.FIELD_INT, MOHO.Localize(""))
	self.slidertext2:SetWheelInc(1)
	layout:AddChild(self.slidertext2)
	
	layout:AddPadding(-15)
	
	self.perc2 = LM.GUI.StaticText(self:Localize('%'))
	layout:AddChild(self.perc2)

	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)
	
	if self.modelessDialogSupport then
		layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
		
		self.openPanelButton = LM.GUI.Button(self:Localize('Open in panel'), self.OPEN_PANEL)
		layout:AddChild(self.openPanelButton, LM.GUI.ALIGN_LEFT, 0)
	end
	
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	layout:AddChild(LM.GUI.StaticText('v'..MR_TweenMachine:Version()))
end

function MR_TweenMachine:UpdateWidgets(moho)
	local frame = moho.frame
	self.frame = frame
	if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0) or frame == 0 then
		self.slider:Enable(false)
		self.slider2:Enable(false)
		self.slidertext:Enable(false)
		self.slidertext2:Enable(false)
	else
		self.slider:Enable(true)
		self.slider2:Enable(true)
		self.slidertext:Enable(true)
		self.slidertext2:Enable(true)
	end

	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
	
	self.intervalMenu:SetChecked(self.INTERVAL_1, false)
	self.intervalMenu:SetChecked(self.INTERVAL_2, false)
	self.intervalMenu:SetChecked(self.INTERVAL_3, false)
	self.intervalMenu:SetChecked(self.INTERVAL_4, false)
	
	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
		self.sliderMode = 1
		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.sliderMode = 1
		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.SLIDER_2 then
		self.sliderMode = 2
		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 = {}
				self.channelsValList = {}
				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.slidertext2:SetValue(self.slider2:Value())
		self.slidertextVal2 = self.slider2:Value()
		self.sliderVal2 = self.slider2:Value()
		self:Tween(moho)
		moho.layer:UpdateCurFrame()
		if(not self.slider2:IsMouseDragging()) then	
			self.undoPrepped = false
			moho:UpdateUI()
			self.channelsList = {}
			self.channelsValList = {}
			
			self.slidertext2:SetValue(0)
			self.slidertextVal2 = 0
			self.sliderVal2 = 0
			self.slider2:SetValue(0)
		end
	elseif msg == self.SLIDER_TEXT_2 then
		self.sliderMode = 2
		self.slidertextVal2 = self.slidertext2:Value()
		self.sliderVal2 = math.floor(self.slidertext2:Value())
		self.slider2:SetValue(sliderVal2)
		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 = {}
			self.channelsValList = {}
			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 = {}
		self.channelsValList = {}
		moho.layer:UpdateCurFrame()
		self.sliderVal2 = self.slider2: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
	elseif msg == self.OPEN_PANEL then
		if self.tweenMachineDlog == nil then
			self.tweenMachineDlog = MR_TweenMachineDialog:new()
			if self.tweenMachineDlog then
				if (self.tweenMachineDlog:DoModeless() == LM.GUI.MSG_CANCEL) then
					return false
				end
			end
		end
		self:UpdateWidgets(moho)
	end
	
	if self.tweenMachineDlog then
		self.tweenMachineDlog:UpdateWidgets(moho)
	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, self.channelsValList[i])
			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, -1)
						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, currentVal)
	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)
							table.insert(self.channelsValList, subChannel:GetValue(curFrame))
						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
							
							if self.sliderMode == 1 then
								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
							elseif self.sliderMode == 2 then
								local prewVal = channel:GetValue(channel:GetKeyWhen(prewKey))
								local originalCurVal = currentVal
								local nextVal = nil
								if nextKey >= channel:CountKeys() then
									nextVal = currentVal + (currentVal - prewVal)
								else
									nextVal = channel:GetValue(channel:GetKeyWhen(nextKey))
								end
							
								if prewVal and nextVal and currentVal then
									local newVal = nil
									if self.sliderVal2 < 0 then
										newVal = (originalCurVal - prewVal) * self.sliderVal2/100 + originalCurVal
									elseif self.sliderVal2 >= 0 then
										newVal = (nextVal - originalCurVal) * self.sliderVal2/100 + originalCurVal
									end

									local oldVal = originalCurVal
									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
		end
	else
		if channel:Duration() > 0 then
			if scan then
				table.insert(self.channelsList, channel)
				table.insert(self.channelsValList, channel:GetValue(curFrame))
			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 self.sliderMode == 1 then
					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
				elseif self.sliderMode == 2 then
					local prewVal = channel:GetValue(channel:GetKeyWhen(prewKey))
					local curVal = channel:GetValue(curFrame)
					local originalCurVal = currentVal
					local nextVal = nil
					if nextKey >= channel:CountKeys() then
						nextVal = currentVal + (currentVal - prewVal)
					else
						nextVal = channel:GetValue(channel:GetKeyWhen(nextKey))
					end

					if prewVal and nextVal and originalCurVal then
						local newVal = nil
						if self.sliderVal2 < 0 then
							newVal = (originalCurVal - prewVal) * self.sliderVal2/100 + originalCurVal
						elseif self.sliderVal2 >= 0 then
							newVal = (nextVal - originalCurVal) * self.sliderVal2/100 + originalCurVal
						end
						
						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 = originalCurVal
						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	
end

function MR_TweenMachine:BakeChannel(moho, channel, frame, interval)
	local prewFrame = frame - interval
	local nextFrame = frame + interval
	local prewVal = channel:GetValue(prewFrame)
	local nextVal = channel:GetValue(nextFrame)
	
	if prewFrame > 0 then
		channel:SetValue(prewFrame, prewVal)
	end
	channel:SetValue(nextFrame, nextVal)
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 = {}
	self.channelsValList = {}
	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

function MR_TweenMachine:UpgateLayout(moho)
	local drawingToolsNonZero = MOHO.MohoGlobals.DisableDrawingToolsNonZero
	if not drawingToolsNonZero then
		MOHO.MohoGlobals.DisableDrawingToolsNonZero = true
	end
	local frame = moho.frame
	if frame == 0 then
		moho:SetCurFrame(1)
		moho:SetCurFrame(0)
	elseif frame ~= 0 then
		moho:SetCurFrame(0)
		moho:SetCurFrame(frame)
	end
	if not drawingToolsNonZero then
		MOHO.MohoGlobals.DisableDrawingToolsNonZero = drawingToolsNonZero
	end
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 '..self:Version()
	
	phrase['%'] = ''
	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['Sliders settings:'] = 'Sliders settings:'
	phrase['Show slider 1'] = 'Show slider 1'
	phrase['Show slider 2'] = 'Show slider 2'
	phrase['Slider 1 Size'] = 'Slider 1 Size:'
	phrase['Slider 2 Size'] = 'Slider 2 Size:'
	phrase['Block on even frames'] = 'Block on even frames'
	phrase['Block on odd frames'] = 'Block on odd frames'
	phrase['Apply sliders size settings'] = '                          Apply sliders settings                           '
	phrase['Close'] = 'Close'
	
	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'
	phrase['Open in panel'] = 'Open in panel'
	return phrase[text]
end

Icon
MR Tween Machine
Listed

Script type: Tool

Uploaded: Mar 19 2023, 17:02

Last modified: Feb 18 2024, 05:52

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: 1613