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

ScriptName = "MR_PoseTool"

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

MR_PoseTool = {}

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

function MR_PoseTool:Version()
	return '1.3.2'
end

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

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

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

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

function MR_PoseTool:IsRelevant(moho)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return false
	end
	
	local v1, v2, v3 = self:GetMohoVersion(moho)
	self.mohoVersion = v1
	
	return true
end

function MR_PoseTool:IsEnabled(moho)
	return true
end

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

MR_PoseTool.doubleClickToReset = true
MR_PoseTool.blockOnEvenFrames = false
MR_PoseTool.blockOnOddFrames = false
MR_PoseTool.highlightBones = true
MR_PoseTool.highlightWidth = 3
MR_PoseTool.useHighlightCustomColor = false
MR_PoseTool.highlightOpacity = 1

MR_PoseTool.highlightCustomColorR = 255
MR_PoseTool.highlightCustomColorG = 0
MR_PoseTool.highlightCustomColorB = 0
MR_PoseTool.highlightCustomColorA = 255

MR_PoseTool.alignHandlesAlongBone = false
MR_PoseTool.handlesDistance = 1
MR_PoseTool.handleStrokeOpacity = 1
MR_PoseTool.handleFillOpacity = 1
MR_PoseTool.useCustomColors = false

MR_PoseTool.colorStrokeTranslateHandleR = 255
MR_PoseTool.colorStrokeTranslateHandleG = 0
MR_PoseTool.colorStrokeTranslateHandleB = 0
MR_PoseTool.colorStrokeTranslateHandleA = 255

MR_PoseTool.colorFillTranslateHandleR = 248
MR_PoseTool.colorFillTranslateHandleG = 121
MR_PoseTool.colorFillTranslateHandleB = 114
MR_PoseTool.colorFillTranslateHandleA = 255

MR_PoseTool.colorStrokeScaleHandleR = 255
MR_PoseTool.colorStrokeScaleHandleG = 0
MR_PoseTool.colorStrokeScaleHandleB = 0
MR_PoseTool.colorStrokeScaleHandleA = 255

MR_PoseTool.colorFillScaleHandleR = 248
MR_PoseTool.colorFillScaleHandleG = 121
MR_PoseTool.colorFillScaleHandleB = 114
MR_PoseTool.colorFillScaleHandleA = 255

MR_PoseTool.colorStrokeMoveJointHandleR = 255
MR_PoseTool.colorStrokeMoveJointHandleG = 63
MR_PoseTool.colorStrokeMoveJointHandleB = 15
MR_PoseTool.colorStrokeMoveJointHandleA = 255

MR_PoseTool.colorFillMoveJointHandleR = 255
MR_PoseTool.colorFillMoveJointHandleG = 189
MR_PoseTool.colorFillMoveJointHandleB = 46
MR_PoseTool.colorFillMoveJointHandleA = 255

MR_PoseTool.colorStrokeManipulateHandleR = 255
MR_PoseTool.colorStrokeManipulateHandleG = 63
MR_PoseTool.colorStrokeManipulateHandleB = 15
MR_PoseTool.colorStrokeManipulateHandleA = 255

MR_PoseTool.colorFillManipulateHandleR = 255
MR_PoseTool.colorFillManipulateHandleG = 189
MR_PoseTool.colorFillManipulateHandleB = 46
MR_PoseTool.colorFillManipulateHandleA = 255

MR_PoseTool.keepSelection = false
MR_PoseTool.lockHandles = false
MR_PoseTool.bakeAdjacentFrames = false
MR_PoseTool.firstBoneID = -1
MR_PoseTool.firstBonePos = LM.Vector2:new_local()
MR_PoseTool.firstBoneScalePercent = 50
MR_PoseTool.clickOffset = LM.Vector2:new_local()
MR_PoseTool.secondBoneID = -1
MR_PoseTool.isActive = true
MR_PoseTool.firstBoneOffset = 0
MR_PoseTool.secondBoneOffset = 0
MR_PoseTool.interval = 1
MR_PoseTool.showPath = false
MR_PoseTool.range = false
MR_PoseTool.rangeFrames = 10
MR_PoseTool.secondBonePos = LM.Vector2:new_local()
MR_PoseTool.secondBoneTipPos = LM.Vector2:new_local()
MR_PoseTool.firstDist = 0
MR_PoseTool.secondBoneDist = 0
MR_PoseTool.firstBoneParentID = -1
MR_PoseTool.firstBoneParentIBIK = false
MR_PoseTool.firstBoneSizeDelta = 0
MR_PoseTool.secondBoneSizeDelta = 0
MR_PoseTool.firstBoneAngleDelta = 0
MR_PoseTool.secondBoneAngleDelta = 0
MR_PoseTool.selectedBonesList = {}
MR_PoseTool.mousePickedID = -1
MR_PoseTool.mouseHoverID = -1
MR_PoseTool.dragging = false
MR_PoseTool.lastVec = LM.Vector2:new_local()
MR_PoseTool.lastVec2 = LM.Vector2:new_local()
MR_PoseTool.handlesDist = 0.075
MR_PoseTool.handlesDistY = 0.026
MR_PoseTool.handlesDistYMultiplier = 1
MR_PoseTool.additionmarkerDist = 0.05
MR_PoseTool.markerR = 6
MR_PoseTool.markerR2 = 6
MR_PoseTool.additionHandles = false
MR_PoseTool.startBonePos = LM.Vector2:new_local()
MR_PoseTool.startBoneAngleDelta = 0
MR_PoseTool.startBoneDist = 0
MR_PoseTool.TOLERANCE = 10
MR_PoseTool.transformPath = false
MR_PoseTool.drawMode = -1
MR_PoseTool.keepHandles = false
MR_PoseTool.height = 1080
MR_PoseTool.ignoreZeroScaledBones = true
MR_PoseTool.clickToSelect = false
MR_PoseTool.pickWidth = 10
MR_PoseTool.handlesDistanceTreshhold = 0.2

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

function MR_PoseTool:LoadPrefs(prefs)
	self.doubleClickToReset = prefs:GetBool("MR_PoseTool.doubleClickToReset", true)
	self.blockOnEvenFrames = prefs:GetBool("MR_PoseTool.blockOnEvenFrames", false)
	self.blockOnOddFrames = prefs:GetBool("MR_PoseTool.blockOnOddFrames", false)
	self.highlightBones = prefs:GetBool("MR_PoseTool.highlightBones", true)
	self.highlightWidth = prefs:GetInt("MR_PoseTool.highlightWidth", 3)
	self.useHighlightCustomColor = prefs:GetBool("MR_PoseTool.useHighlightCustomColor", false)
	
	self.highlightCustomColorR = prefs:GetInt("MR_PoseTool.highlightCustomColorR", 255)
	self.highlightCustomColorG = prefs:GetInt("MR_PoseTool.highlightCustomColorG", 0)
	self.highlightCustomColorB = prefs:GetInt("MR_PoseTool.highlightCustomColorB", 0)
	self.highlightCustomColorA = prefs:GetInt("MR_PoseTool.highlightCustomColorA", 255)
	
	self.alignHandlesAlongBone = prefs:GetBool("MR_PoseTool.alignHandlesAlongBone", false)
	self.handlesDistance = prefs:GetFloat("MR_PoseTool.handlesDistance", 1)
	self.handleStrokeOpacity = prefs:GetFloat("MR_PoseTool.handleStrokeOpacity", 1)
	self.handleFillOpacity = prefs:GetFloat("MR_PoseTool.handleFillOpacity", 1)
	self.useCustomColors = prefs:GetBool("MR_PoseTool.useCustomColors", false)
	
	self.colorStrokeTranslateHandleR = prefs:GetInt("MR_PoseTool.colorStrokeTranslateHandleR", 255)
	self.colorStrokeTranslateHandleG = prefs:GetInt("MR_PoseTool.colorStrokeTranslateHandleG", 0)
	self.colorStrokeTranslateHandleB = prefs:GetInt("MR_PoseTool.colorStrokeTranslateHandleB", 0)
	self.colorStrokeTranslateHandleA = prefs:GetInt("MR_PoseTool.colorStrokeTranslateHandleA", 255)
	
	self.colorFillTranslateHandleR = prefs:GetInt("MR_PoseTool.colorFillTranslateHandleR", 248)
	self.colorFillTranslateHandleG = prefs:GetInt("MR_PoseTool.colorFillTranslateHandleG", 121)
	self.colorFillTranslateHandleB = prefs:GetInt("MR_PoseTool.colorFillTranslateHandleB", 114)
	self.colorFillTranslateHandleA = prefs:GetInt("MR_PoseTool.colorFillTranslateHandleA", 255)
	
	self.colorStrokeScaleHandleR = prefs:GetInt("MR_PoseTool.colorStrokeScaleHandleR", 255)
	self.colorStrokeScaleHandleG = prefs:GetInt("MR_PoseTool.colorStrokeScaleHandleG", 0)
	self.colorStrokeScaleHandleB = prefs:GetInt("MR_PoseTool.colorStrokeScaleHandleB", 0)
	self.colorStrokeScaleHandleA = prefs:GetInt("MR_PoseTool.colorStrokeScaleHandleA", 255)
	
	self.colorFillScaleHandleR = prefs:GetInt("MR_PoseTool.colorFillScaleHandleR", 248)
	self.colorFillScaleHandleG = prefs:GetInt("MR_PoseTool.colorFillScaleHandleG", 121)
	self.colorFillScaleHandleB = prefs:GetInt("MR_PoseTool.colorFillScaleHandleB", 114)
	self.colorFillScaleHandleA = prefs:GetInt("MR_PoseTool.colorFillScaleHandleA", 255)
	
	self.colorStrokeMoveJointHandleR = prefs:GetInt("MR_PoseTool.colorStrokeMoveJointHandleR", 255)
	self.colorStrokeMoveJointHandleG = prefs:GetInt("MR_PoseTool.colorStrokeMoveJointHandleG", 63)
	self.colorStrokeMoveJointHandleB = prefs:GetInt("MR_PoseTool.colorStrokeMoveJointHandleB", 15)
	self.colorStrokeMoveJointHandleA = prefs:GetInt("MR_PoseTool.colorStrokeMoveJointHandleA", 255)
	
	self.colorFillMoveJointHandleR = prefs:GetInt("MR_PoseTool.colorFillMoveJointHandleR", 255)
	self.colorFillMoveJointHandleG = prefs:GetInt("MR_PoseTool.colorFillMoveJointHandleG", 189)
	self.colorFillMoveJointHandleB = prefs:GetInt("MR_PoseTool.colorFillMoveJointHandleB", 46)
	self.colorFillMoveJointHandleA = prefs:GetInt("MR_PoseTool.colorFillMoveJointHandleA", 255)
	
	self.colorStrokeManipulateHandleR = prefs:GetInt("MR_PoseTool.colorStrokeManipulateHandleR", 255)
	self.colorStrokeManipulateHandleG = prefs:GetInt("MR_PoseTool.colorStrokeManipulateHandleG", 63)
	self.colorStrokeManipulateHandleB = prefs:GetInt("MR_PoseTool.colorStrokeManipulateHandleB", 15)
	self.colorStrokeManipulateHandleA = prefs:GetInt("MR_PoseTool.colorStrokeManipulateHandleA", 255)
	
	self.colorFillManipulateHandleR = prefs:GetInt("MR_PoseTool.colorFillManipulateHandleR", 255)
	self.colorFillManipulateHandleG = prefs:GetInt("MR_PoseTool.colorFillManipulateHandleG", 189)
	self.colorFillManipulateHandleB = prefs:GetInt("MR_PoseTool.colorFillManipulateHandleB", 46)
	self.colorFillManipulateHandleA = prefs:GetInt("MR_PoseTool.colorFillManipulateHandleA", 255)
	
	self.keepSelection = prefs:GetBool("MR_PoseTool.keepSelection", false)
	self.lockHandles = prefs:GetBool("MR_PoseTool.lockHandles", false)
	self.bakeAdjacentFrames = prefs:GetBool("MR_PoseTool.bakeAdjacentFrames", false)
	self.interval = prefs:GetInt("MR_PoseTool.interval", 1)
	self.showPath = prefs:GetBool("MR_PoseTool.showPath", false)
	self.range = prefs:GetBool("MR_PoseTool.range", false)
	self.rangeFrames = prefs:GetInt("MR_PoseTool.rangeFrames", 10)
end

function MR_PoseTool:SavePrefs(prefs)
	prefs:SetBool("MR_PoseTool.doubleClickToReset", self.doubleClickToReset)
	prefs:SetBool("MR_PoseTool.blockOnEvenFrames", self.blockOnEvenFrames)
	prefs:SetBool("MR_PoseTool.blockOnOddFrames", self.blockOnOddFrames)
	prefs:SetBool("MR_PoseTool.highlightBones", self.highlightBones)
	prefs:SetInt("MR_PoseTool.highlightWidth", self.highlightWidth)
	prefs:SetBool("MR_PoseTool.useHighlightCustomColor", self.useHighlightCustomColor)
	
	prefs:SetInt("MR_PoseTool.highlightCustomColorR", self.highlightCustomColorR)
	prefs:SetInt("MR_PoseTool.highlightCustomColorG", self.highlightCustomColorG)
	prefs:SetInt("MR_PoseTool.highlightCustomColorB", self.highlightCustomColorB)
	prefs:SetInt("MR_PoseTool.highlightCustomColorA", self.highlightCustomColorA)
	
	prefs:SetBool("MR_PoseTool.alignHandlesAlongBone", self.alignHandlesAlongBone)
	prefs:SetFloat("MR_PoseTool.handlesDistance", self.handlesDistance)
	prefs:SetFloat("MR_PoseTool.handleStrokeOpacity", self.handleStrokeOpacity)
	prefs:SetFloat("MR_PoseTool.handleFillOpacity", self.handleFillOpacity)
	prefs:SetBool("MR_PoseTool.useCustomColors", self.useCustomColors)
	
	prefs:SetInt("MR_PoseTool.colorStrokeTranslateHandleR", self.colorStrokeTranslateHandleR)
	prefs:SetInt("MR_PoseTool.colorStrokeTranslateHandleG", self.colorStrokeTranslateHandleG)
	prefs:SetInt("MR_PoseTool.colorStrokeTranslateHandleB", self.colorStrokeTranslateHandleB)
	prefs:SetInt("MR_PoseTool.colorStrokeTranslateHandleA", self.colorStrokeTranslateHandleA)
	
	prefs:SetInt("MR_PoseTool.colorFillTranslateHandleR", self.colorFillTranslateHandleR)
	prefs:SetInt("MR_PoseTool.colorFillTranslateHandleG", self.colorFillTranslateHandleG)
	prefs:SetInt("MR_PoseTool.colorFillTranslateHandleB", self.colorFillTranslateHandleB)
	prefs:SetInt("MR_PoseTool.colorFillTranslateHandleA", self.colorFillTranslateHandleA)
	
	prefs:SetInt("MR_PoseTool.colorStrokeScaleHandleR", self.colorStrokeScaleHandleR)
	prefs:SetInt("MR_PoseTool.colorStrokeScaleHandleG", self.colorStrokeScaleHandleG)
	prefs:SetInt("MR_PoseTool.colorStrokeScaleHandleB", self.colorStrokeScaleHandleB)
	prefs:SetInt("MR_PoseTool.colorStrokeScaleHandleA", self.colorStrokeScaleHandleA)
	
	prefs:SetInt("MR_PoseTool.colorFillScaleHandleR", self.colorFillScaleHandleR)
	prefs:SetInt("MR_PoseTool.colorFillScaleHandleG", self.colorFillScaleHandleG)
	prefs:SetInt("MR_PoseTool.colorFillScaleHandleB", self.colorFillScaleHandleB)
	prefs:SetInt("MR_PoseTool.colorFillScaleHandleA", self.colorFillScaleHandleA)
	
	prefs:SetInt("MR_PoseTool.colorStrokeMoveJointHandleR", self.colorStrokeMoveJointHandleR)
	prefs:SetInt("MR_PoseTool.colorStrokeMoveJointHandleG", self.colorStrokeMoveJointHandleG)
	prefs:SetInt("MR_PoseTool.colorStrokeMoveJointHandleB", self.colorStrokeMoveJointHandleB)
	prefs:SetInt("MR_PoseTool.colorStrokeMoveJointHandleA", self.colorStrokeMoveJointHandleA)
	
	prefs:SetInt("MR_PoseTool.colorFillMoveJointHandleR", self.colorFillMoveJointHandleR)
	prefs:SetInt("MR_PoseTool.colorFillMoveJointHandleG", self.colorFillMoveJointHandleG)
	prefs:SetInt("MR_PoseTool.colorFillMoveJointHandleB", self.colorFillMoveJointHandleB)
	prefs:SetInt("MR_PoseTool.colorFillMoveJointHandleA", self.colorFillMoveJointHandleA)
	
	prefs:SetInt("MR_PoseTool.colorStrokeManipulateHandleR", self.colorStrokeManipulateHandleR)
	prefs:SetInt("MR_PoseTool.colorStrokeManipulateHandleG", self.colorStrokeManipulateHandleG)
	prefs:SetInt("MR_PoseTool.colorStrokeManipulateHandleB", self.colorStrokeManipulateHandleB)
	prefs:SetInt("MR_PoseTool.colorStrokeManipulateHandleA", self.colorStrokeManipulateHandleA)
	
	prefs:SetInt("MR_PoseTool.colorFillManipulateHandleR", self.colorFillManipulateHandleR)
	prefs:SetInt("MR_PoseTool.colorFillManipulateHandleG", self.colorFillManipulateHandleG)
	prefs:SetInt("MR_PoseTool.colorFillManipulateHandleB", self.colorFillManipulateHandleB)
	prefs:SetInt("MR_PoseTool.colorFillManipulateHandleA", self.colorFillManipulateHandleA)
	
	prefs:SetBool("MR_PoseTool.keepSelection", self.keepSelection)
	prefs:SetBool("MR_PoseTool.lockHandles", self.lockHandles)
	prefs:SetBool("MR_PoseTool.bakeAdjacentFrames", self.bakeAdjacentFrames)
	prefs:SetInt("MR_PoseTool.interval", self.interval)
	prefs:SetBool("MR_PoseTool.showPath", self.showPath)
	prefs:SetBool("MR_PoseTool.range", self.range)
	prefs:SetInt("MR_PoseTool.rangeFrames", self.rangeFrames)
end

function MR_PoseTool:ResetPrefs()
	self.doubleClickToReset = true
	self.blockOnEvenFrames = false
	self.blockOnOddFrames = false
	self.highlightBones = true
	self.highlightWidth = 3
	self.useHighlightCustomColor = false
	
	self.highlightCustomColorR = 255
	self.highlightCustomColorG = 0
	self.highlightCustomColorB = 0
	self.highlightCustomColorA = 255
	
	self.alignHandlesAlongBone = false
	self.handlesDistance = 1
	self.handleFillOpacity = 1
	self.useCustomColors = false
	
	self.colorStrokeTranslateHandleR = 255
	self.colorStrokeTranslateHandleG = 0
	self.colorStrokeTranslateHandleB = 0
	self.colorStrokeTranslateHandleA = 255

	self.colorFillTranslateHandleR = 248
	self.colorFillTranslateHandleG = 121
	self.colorFillTranslateHandleB = 114
	self.colorFillTranslateHandleA = 255

	self.colorStrokeScaleHandleR = 255
	self.colorStrokeScaleHandleG = 0
	self.colorStrokeScaleHandleB = 0
	self.colorStrokeScaleHandleA = 255

	self.colorFillScaleHandleR = 248
	self.colorFillScaleHandleG = 121
	self.colorFillScaleHandleB = 114
	self.colorFillScaleHandleA = 255

	self.colorStrokeMoveJointHandleR = 255
	self.colorStrokeMoveJointHandleG = 63
	self.colorStrokeMoveJointHandleB = 15
	self.colorStrokeMoveJointHandleA = 255

	self.colorFillMoveJointHandleR = 255
	self.colorFillMoveJointHandleG = 189
	self.colorFillMoveJointHandleB = 46
	self.colorFillMoveJointHandleA = 255

	self.colorStrokeManipulateHandleR = 255
	self.colorStrokeManipulateHandleG = 63
	self.colorStrokeManipulateHandleB = 15
	self.colorStrokeManipulateHandleA = 255

	self.colorFillManipulateHandleR = 255
	self.colorFillManipulateHandleG = 189
	self.colorFillManipulateHandleB = 46
	self.colorFillManipulateHandleA = 255
	
	self.keepSelection = false
	self.lockHandles = false
	self.bakeAdjacentFrames = false
	self.interval = 1
	self.showPath = false
	self.range = false
	self.rangeFrames = 10
end

function MR_PoseTool:NonDragMouseMove()
	return true -- Call MouseMoved() even if the mouse button is not down
end

-- **************************************************
-- Settings Menu
-- **************************************************

local MR_PoseToolSettingsDialog = {}

MR_PoseToolSettingsDialog.DOUBLE_CLICK_TO_RESET = MOHO.MSG_BASE
MR_PoseToolSettingsDialog.BLOCK_ON_EVEN_FRAMES = MOHO.MSG_BASE + 1
MR_PoseToolSettingsDialog.BLOCK_ON_ODD_FRAMES = MOHO.MSG_BASE + 2
MR_PoseToolSettingsDialog.HIGHLIGHT_BONES = MOHO.MSG_BASE + 3
MR_PoseToolSettingsDialog.HIGHLIGHT_WIDTH = MOHO.MSG_BASE + 4
MR_PoseToolSettingsDialog.HIGHLIGHT_OPACITY = MOHO.MSG_BASE + 5
MR_PoseToolSettingsDialog.USE_HIGHLIGHT_CUSTOM_COLOR = MOHO.MSG_BASE + 6
MR_PoseToolSettingsDialog.HIGHLIGHT_CUSTOM_COLOR = MOHO.MSG_BASE + 7
MR_PoseToolSettingsDialog.ALIGN_HANDLES_ALONG_BONE = MOHO.MSG_BASE + 8
MR_PoseToolSettingsDialog.HANDLES_DISTANCE = MOHO.MSG_BASE + 9
MR_PoseToolSettingsDialog.HANDLES_STROKE_OPACITY = MOHO.MSG_BASE + 10
MR_PoseToolSettingsDialog.HANDLES_FILL_OPACITY = MOHO.MSG_BASE + 11
MR_PoseToolSettingsDialog.USE_CUSTOM_COLORS = MOHO.MSG_BASE + 12
MR_PoseToolSettingsDialog.COLOR_TRANSLATE_STROKE = MOHO.MSG_BASE + 13
MR_PoseToolSettingsDialog.COLOR_TRANSLATE_FILL = MOHO.MSG_BASE + 14
MR_PoseToolSettingsDialog.COLOR_SCALE_STROKE = MOHO.MSG_BASE + 15
MR_PoseToolSettingsDialog.COLOR_SCALE_FILL = MOHO.MSG_BASE + 16
MR_PoseToolSettingsDialog.COLOR_MOVE_JOINT_STROKE = MOHO.MSG_BASE + 17
MR_PoseToolSettingsDialog.COLOR_MOVE_JOINT_FILL = MOHO.MSG_BASE + 18
MR_PoseToolSettingsDialog.COLOR_MANIPULATE_STROKE = MOHO.MSG_BASE + 19
MR_PoseToolSettingsDialog.COLOR_MANIPULATE_FILL = MOHO.MSG_BASE + 20
MR_PoseToolSettingsDialog.RESET_COLOR = MOHO.MSG_BASE + 21

function MR_PoseToolSettingsDialog:new()
	local d = LM.GUI.SimpleDialog(MR_PoseTool:Localize('UILabel'), MR_PoseToolSettingsDialog)
    local l = d:GetLayout()
	
	d.doubleClickToResetCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Double-click to reset'), self.DOUBLE_CLICK_TO_RESET)
    l:AddChild(d.doubleClickToResetCheck, LM.GUI.ALIGN_LEFT, 0)
	
	l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
	
	d.blockOnEvenFramesCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Block on even frames'), self.BLOCK_ON_EVEN_FRAMES)
    l:AddChild(d.blockOnEvenFramesCheck, LM.GUI.ALIGN_LEFT, 0)
	
	d.blockOnOddFramesCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Block on odd frames'), self.BLOCK_ON_ODD_FRAMES)
    l:AddChild(d.blockOnOddFramesCheck, LM.GUI.ALIGN_LEFT, 0)
	
	l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
	
	d.highlightBonesCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Highlight bones'), self.HIGHLIGHT_BONES)
    l:AddChild(d.highlightBonesCheck, LM.GUI.ALIGN_LEFT, 0)
	
	d.highlightWidthInput = LM.GUI.TextControl(0, '100', self.HIGHLIGHT_WIDTH, LM.GUI.FIELD_INT, MR_PoseTool:Localize('Highlight width:'))
    l:AddChild(d.highlightWidthInput, LM.GUI.ALIGN_RIGHT, 0)
	
	d.highlightOpacityInput = LM.GUI.TextControl(0, '100', self.HIGHLIGHT_OPACITY, LM.GUI.FIELD_FLOAT, MR_PoseTool:Localize('Highlight opacity:'))
	d.highlightOpacityInput:SetWheelInc(0.01)
    l:AddChild(d.highlightOpacityInput, LM.GUI.ALIGN_RIGHT, 0)
	
	l:PushH()
	
		d.useHighlightCustomColorCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Custom'), self.USE_HIGHLIGHT_CUSTOM_COLOR)
		l:AddChild(d.useHighlightCustomColorCheck, LM.GUI.ALIGN_LEFT, 0)
		
		d.highlightCustomColorSwatch = LM.GUI.ShortColorSwatch(true, self.HIGHLIGHT_CUSTOM_COLOR)
		l:AddChild(d.highlightCustomColorSwatch, LM.GUI.ALIGN_LEFT)
	
	l:Pop()
	
	l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
	
	d.alignHandlesAlongBoneCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Align handles along bone'), self.ALIGN_HANDLES_ALONG_BONE)
    l:AddChild(d.alignHandlesAlongBoneCheck, LM.GUI.ALIGN_LEFT, 0)
	
	d.handlesDistanceInput = LM.GUI.TextControl(0, '100', self.HANDLES_DISTANCE, LM.GUI.FIELD_FLOAT, MR_PoseTool:Localize('Handles distance:'))
	d.handlesDistanceInput:SetWheelInc(0.01)
    l:AddChild(d.handlesDistanceInput, LM.GUI.ALIGN_RIGHT, 0)
	
	d.handlesStrokeOpacityInput = LM.GUI.TextControl(0, '100', self.HANDLES_STROKE_OPACITY, LM.GUI.FIELD_FLOAT, MR_PoseTool:Localize('Handles stroke opacity:'))
	d.handlesStrokeOpacityInput:SetWheelInc(0.01)
    l:AddChild(d.handlesStrokeOpacityInput, LM.GUI.ALIGN_RIGHT, 0)
	
	d.handlesFillOpacityInput = LM.GUI.TextControl(0, '100', self.HANDLES_FILL_OPACITY, LM.GUI.FIELD_FLOAT, MR_PoseTool:Localize('Handles fill opacity:'))
	d.handlesFillOpacityInput:SetWheelInc(0.01)
    l:AddChild(d.handlesFillOpacityInput, LM.GUI.ALIGN_RIGHT, 0)
	
	l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
	
	d.useCustomColorsInput = LM.GUI.CheckBox(MR_PoseTool:Localize('Use custom colors'), self.USE_CUSTOM_COLORS)
    l:AddChild(d.useCustomColorsInput, LM.GUI.ALIGN_LEFT, 0)
	
	l:PushH()
	
		d.colorTranslateStrokeSwatch = LM.GUI.ShortColorSwatch(true, self.COLOR_TRANSLATE_STROKE)
		l:AddChild(d.colorTranslateStrokeSwatch, LM.GUI.ALIGN_LEFT)
		d.colorTranslateStrokeSwatch:SetToolTip(MR_PoseTool:Localize('Translate handle stroke color Tooltip'))
		
		d.colorTranslateFillSwatch = LM.GUI.ShortColorSwatch(true, self.COLOR_TRANSLATE_FILL)
		l:AddChild(d.colorTranslateFillSwatch, LM.GUI.ALIGN_LEFT)
		d.colorTranslateFillSwatch:SetToolTip(MR_PoseTool:Localize('Translate handle fill color Tooltip'))
	
	l:Pop()
	
	l:PushH()
	
		d.colorScaleStrokeSwatch = LM.GUI.ShortColorSwatch(true, self.COLOR_SCALE_STROKE)
		l:AddChild(d.colorScaleStrokeSwatch, LM.GUI.ALIGN_LEFT)
		d.colorScaleStrokeSwatch:SetToolTip(MR_PoseTool:Localize('Scale handle stroke color Tooltip'))
		
		d.colorScaleFillSwatch = LM.GUI.ShortColorSwatch(true, self.COLOR_SCALE_FILL)
		l:AddChild(d.colorScaleFillSwatch, LM.GUI.ALIGN_LEFT)
		d.colorScaleFillSwatch:SetToolTip(MR_PoseTool:Localize('Scale handle fill color Tooltip'))
	
	l:Pop()
	
	l:PushH()
	
		d.colorMoveJointStrokeSwatch = LM.GUI.ShortColorSwatch(true, self.COLOR_MOVE_JOINT_STROKE)
		l:AddChild(d.colorMoveJointStrokeSwatch, LM.GUI.ALIGN_LEFT)
		d.colorMoveJointStrokeSwatch:SetToolTip(MR_PoseTool:Localize('Move joint handle stroke color Tooltip'))
		
		d.colorMoveJointFillSwatch = LM.GUI.ShortColorSwatch(true, self.COLOR_MOVE_JOINT_FILL)
		l:AddChild(d.colorMoveJointFillSwatch, LM.GUI.ALIGN_LEFT)
		d.colorMoveJointFillSwatch:SetToolTip(MR_PoseTool:Localize('Move joint handle fill color Tooltip'))
	
	l:Pop()
	
	l:PushH()
	
		d.colorManipulateStrokeSwatch = LM.GUI.ShortColorSwatch(true, self.COLOR_MANIPULATE_STROKE)
		l:AddChild(d.colorManipulateStrokeSwatch, LM.GUI.ALIGN_LEFT)
		d.colorManipulateStrokeSwatch:SetToolTip(MR_PoseTool:Localize('Manipulate handle stroke color Tooltip'))
		
		d.colorManipulatFillSwatch = LM.GUI.ShortColorSwatch(true, self.COLOR_MANIPULATE_FILL)
		l:AddChild(d.colorManipulatFillSwatch, LM.GUI.ALIGN_LEFT)
		d.colorManipulatFillSwatch:SetToolTip(MR_PoseTool:Localize('Manipulate handle fill color Tooltip'))
	
	l:Pop()
	
	d.resetColorButton = LM.GUI.Button(MR_PoseTool:Localize('Reset colors'), self.RESET_COLOR)
	l:AddChild(d.resetColorButton, LM.GUI.ALIGN_FILL, 0)
	
	return d
end

function MR_PoseToolSettingsDialog:UpdateWidgets(moho)
    self.doubleClickToResetCheck:SetValue(MR_PoseTool.doubleClickToReset)
    self.blockOnEvenFramesCheck:SetValue(MR_PoseTool.blockOnEvenFrames)
    self.blockOnOddFramesCheck:SetValue(MR_PoseTool.blockOnOddFrames)
    self.highlightBonesCheck:SetValue(MR_PoseTool.highlightBones)
    self.highlightWidthInput:SetValue(MR_PoseTool.highlightWidth)
    self.highlightOpacityInput:SetValue(MR_PoseTool.highlightOpacity)
    self.useHighlightCustomColorCheck:SetValue(MR_PoseTool.useHighlightCustomColor)
    self.alignHandlesAlongBoneCheck:SetValue(MR_PoseTool.alignHandlesAlongBone)
	if MR_PoseTool.alignHandlesAlongBone then
		self.handlesDistanceInput:Enable(false)
	else
		self.handlesDistanceInput:Enable(true)
	end
    self.handlesDistanceInput:SetValue(MR_PoseTool.handlesDistance)
    self.handlesStrokeOpacityInput:SetValue(MR_PoseTool.handleStrokeOpacity)
    self.handlesFillOpacityInput:SetValue(MR_PoseTool.handleFillOpacity)
    self.useCustomColorsInput:SetValue(MR_PoseTool.useCustomColors)
	
	if MR_PoseTool.useCustomColors then
		self.colorTranslateStrokeSwatch:Enable(true)
		self.colorTranslateFillSwatch:Enable(true)
		self.colorScaleStrokeSwatch:Enable(true)
		self.colorScaleFillSwatch:Enable(true)
		self.colorMoveJointStrokeSwatch:Enable(true)
		self.colorMoveJointFillSwatch:Enable(true)
		self.colorManipulateStrokeSwatch:Enable(true)
		self.colorManipulatFillSwatch:Enable(true)
		self.resetColorButton:Enable(true)
	else
		self.colorTranslateStrokeSwatch:Enable(false)
		self.colorTranslateFillSwatch:Enable(false)
		self.colorScaleStrokeSwatch:Enable(false)
		self.colorScaleFillSwatch:Enable(false)
		self.colorMoveJointStrokeSwatch:Enable(false)
		self.colorMoveJointFillSwatch:Enable(false)
		self.colorManipulateStrokeSwatch:Enable(false)
		self.colorManipulatFillSwatch:Enable(false)
		self.resetColorButton:Enable(false)
	end
	
	if MR_PoseTool.highlightBones then
		self.highlightWidthInput:Enable(true)
		self.highlightOpacityInput:Enable(true)
		self.useHighlightCustomColorCheck:Enable(true)
	else
		self.highlightWidthInput:Enable(false)
		self.highlightOpacityInput:Enable(false)
		self.useHighlightCustomColorCheck:Enable(false)
	end
	
	if MR_PoseTool.highlightBones and MR_PoseTool.useHighlightCustomColor then
		self.highlightCustomColorSwatch:Enable(true)
	else
		self.highlightCustomColorSwatch:Enable(false)
	end
	
	local highlightCustomColor = LM.rgb_color:new_local()
	highlightCustomColor.r = MR_PoseTool.highlightCustomColorR
	highlightCustomColor.g = MR_PoseTool.highlightCustomColorG
	highlightCustomColor.b = MR_PoseTool.highlightCustomColorB
	highlightCustomColor.a = 255
	
	self.highlightCustomColorSwatch:SetValue(highlightCustomColor)
	
	local colorTranslateStroke = LM.rgb_color:new_local()
	colorTranslateStroke.r = MR_PoseTool.colorStrokeTranslateHandleR
	colorTranslateStroke.g = MR_PoseTool.colorStrokeTranslateHandleG
	colorTranslateStroke.b = MR_PoseTool.colorStrokeTranslateHandleB
	colorTranslateStroke.a = 255
	
	self.colorTranslateStrokeSwatch:SetValue(colorTranslateStroke)
	
	local colorTranslateFill = LM.rgb_color:new_local()
	colorTranslateFill.r = MR_PoseTool.colorFillTranslateHandleR
	colorTranslateFill.g = MR_PoseTool.colorFillTranslateHandleG
	colorTranslateFill.b = MR_PoseTool.colorFillTranslateHandleB
	colorTranslateFill.a = 255
	
	self.colorTranslateFillSwatch:SetValue(colorTranslateFill)
	
	local colorScaleStroke = LM.rgb_color:new_local()
	colorScaleStroke.r = MR_PoseTool.colorStrokeScaleHandleR
	colorScaleStroke.g = MR_PoseTool.colorStrokeScaleHandleG
	colorScaleStroke.b = MR_PoseTool.colorStrokeScaleHandleB
	colorScaleStroke.a = 255

	self.colorScaleStrokeSwatch:SetValue(colorScaleStroke)
	
	local colorScaleFill = LM.rgb_color:new_local()
	colorScaleFill.r = MR_PoseTool.colorFillScaleHandleR
	colorScaleFill.g = MR_PoseTool.colorFillScaleHandleG
	colorScaleFill.b = MR_PoseTool.colorFillScaleHandleB
	colorScaleFill.a = 255

	self.colorScaleFillSwatch:SetValue(colorScaleFill)
	
	local colorMoveJointStroke = LM.rgb_color:new_local()
	colorMoveJointStroke.r = MR_PoseTool.colorStrokeMoveJointHandleR
	colorMoveJointStroke.g = MR_PoseTool.colorStrokeMoveJointHandleG
	colorMoveJointStroke.b = MR_PoseTool.colorStrokeMoveJointHandleB
	colorMoveJointStroke.a = 255

	self.colorMoveJointStrokeSwatch:SetValue(colorMoveJointStroke)
	
	local colorMoveJointFill = LM.rgb_color:new_local()
	colorMoveJointFill.r = MR_PoseTool.colorFillMoveJointHandleR
	colorMoveJointFill.g = MR_PoseTool.colorFillMoveJointHandleG
	colorMoveJointFill.b = MR_PoseTool.colorFillMoveJointHandleB
	colorMoveJointFill.a = 255

	self.colorMoveJointFillSwatch:SetValue(colorMoveJointFill)

	local colorManipulateStroke = LM.rgb_color:new_local()
	colorManipulateStroke.r = MR_PoseTool.colorStrokeManipulateHandleR
	colorManipulateStroke.g = MR_PoseTool.colorStrokeManipulateHandleG
	colorManipulateStroke.b = MR_PoseTool.colorStrokeManipulateHandleB
	colorManipulateStroke.a = 255

	self.colorManipulateStrokeSwatch:SetValue(colorManipulateStroke)
	
	local colorManipulateFill = LM.rgb_color:new_local()
	colorManipulateFill.r = MR_PoseTool.colorFillManipulateHandleR
	colorManipulateFill.g = MR_PoseTool.colorFillManipulateHandleG
	colorManipulateFill.b = MR_PoseTool.colorFillManipulateHandleB
	colorManipulateFill.a = 255

	self.colorManipulatFillSwatch:SetValue(colorManipulateFill)
end

function MR_PoseToolSettingsDialog:OnOK(moho)
    MR_PoseTool.doubleClickToReset = self.doubleClickToResetCheck:Value()
    MR_PoseTool.blockOnEvenFrames = self.blockOnEvenFramesCheck:Value()
    MR_PoseTool.blockOnOddFrames = self.blockOnOddFramesCheck:Value()
    MR_PoseTool.highlightBones = self.highlightBonesCheck:Value()
    MR_PoseTool.highlightWidth = self.highlightWidthInput:Value()
    MR_PoseTool.highlightOpacity = self.highlightOpacityInput:Value()
    MR_PoseTool.useHighlightCustomColor = self.useHighlightCustomColorCheck:Value()
    MR_PoseTool.alignHandlesAlongBone = self.alignHandlesAlongBoneCheck:Value()
    MR_PoseTool.handlesDistance = self.handlesDistanceInput:Value()
    MR_PoseTool.handleFillOpacity = self.handlesFillOpacityInput:Value()
    MR_PoseTool.useCustomColors = self.useCustomColorsInput:Value()
end

function MR_PoseToolSettingsDialog:HandleMessage(msg)
	local needRedraw = false
	if msg == self.DOUBLE_CLICK_TO_RESET then
		MR_PoseTool.doubleClickToReset = self.doubleClickToResetCheck:Value()
	elseif msg == self.BLOCK_ON_EVEN_FRAMES then
		MR_PoseTool.blockOnEvenFrames = self.blockOnEvenFramesCheck:Value()
	elseif msg == self.BLOCK_ON_ODD_FRAMES then
		MR_PoseTool.blockOnOddFrames = self.blockOnOddFramesCheck:Value()
	elseif msg == self.HIGHLIGHT_BONES then
		MR_PoseTool.highlightBones = self.highlightBonesCheck:Value()
		if MR_PoseTool.highlightBones then
			self.highlightWidthInput:Enable(true)
			self.highlightOpacityInput:Enable(true)
			self.useHighlightCustomColorCheck:Enable(true)
		else
			self.highlightWidthInput:Enable(false)
			self.highlightOpacityInput:Enable(false)
			self.useHighlightCustomColorCheck:Enable(false)
		end
		
		if MR_PoseTool.highlightBones and MR_PoseTool.useHighlightCustomColor then
			self.highlightCustomColorSwatch:Enable(true)
		else
			self.highlightCustomColorSwatch:Enable(false)
		end
		needRedraw = true
	elseif msg == self.HIGHLIGHT_WIDTH then
		MR_PoseTool.highlightWidth = LM.Clamp(self.highlightWidthInput:Value(), 1, 12)
		self.highlightWidthInput:SetValue(MR_PoseTool.highlightWidth)
		needRedraw = true
	elseif msg == self.HIGHLIGHT_OPACITY then
		MR_PoseTool.highlightOpacity = LM.Clamp(self.highlightOpacityInput:Value(), 0, 1)
		self.highlightOpacityInput:SetValue(MR_PoseTool.highlightOpacity)
		needRedraw = true
	elseif msg == self.USE_HIGHLIGHT_CUSTOM_COLOR then
		MR_PoseTool.useHighlightCustomColor = self.useHighlightCustomColorCheck:Value()
		if MR_PoseTool.highlightBones and MR_PoseTool.useHighlightCustomColor then
			self.highlightCustomColorSwatch:Enable(true)
		else
			self.highlightCustomColorSwatch:Enable(false)
		end
		needRedraw = true
	elseif msg == self.HIGHLIGHT_CUSTOM_COLOR then
		local colorSwatchValue = self.highlightCustomColorSwatch:Value()
		MR_PoseTool.highlightCustomColorR = colorSwatchValue.r
		MR_PoseTool.highlightCustomColorG = colorSwatchValue.g
		MR_PoseTool.highlightCustomColorB = colorSwatchValue.b
		MR_PoseTool.highlightCustomColorA = 255
		needRedraw = true
	elseif msg == self.ALIGN_HANDLES_ALONG_BONE then
		MR_PoseTool.alignHandlesAlongBone = self.alignHandlesAlongBoneCheck:Value()
		if MR_PoseTool.alignHandlesAlongBone then
		self.handlesDistanceInput:Enable(false)
		else
			self.handlesDistanceInput:Enable(true)
		end
		needRedraw = true
	elseif msg == self.HANDLES_DISTANCE then
		MR_PoseTool.handlesDistance = LM.Clamp(self.handlesDistanceInput:Value(), 0.5, 2)
		self.handlesDistanceInput:SetValue(MR_PoseTool.handlesDistance)
		needRedraw = true
	elseif msg == self.HANDLES_STROKE_OPACITY then
		MR_PoseTool.handleStrokeOpacity = LM.Clamp(self.handlesStrokeOpacityInput:Value(), 0, 1)
		self.handlesStrokeOpacityInput:SetValue(MR_PoseTool.handleStrokeOpacity)
		needRedraw = true
	elseif msg == self.HANDLES_FILL_OPACITY then
		MR_PoseTool.handleFillOpacity = LM.Clamp(self.handlesFillOpacityInput:Value(), 0, 1)
		self.handlesFillOpacityInput:SetValue(MR_PoseTool.handleFillOpacity)
		needRedraw = true
	elseif msg == self.USE_CUSTOM_COLORS then
		MR_PoseTool.useCustomColors = self.useCustomColorsInput:Value()
		if MR_PoseTool.useCustomColors then
			self.colorTranslateStrokeSwatch:Enable(true)
			self.colorTranslateFillSwatch:Enable(true)
			self.colorScaleStrokeSwatch:Enable(true)
			self.colorScaleFillSwatch:Enable(true)
			self.colorMoveJointStrokeSwatch:Enable(true)
			self.colorMoveJointFillSwatch:Enable(true)
			self.colorManipulateStrokeSwatch:Enable(true)
			self.colorManipulatFillSwatch:Enable(true)
			self.resetColorButton:Enable(true)
		else
			self.colorTranslateStrokeSwatch:Enable(false)
			self.colorTranslateFillSwatch:Enable(false)
			self.colorScaleStrokeSwatch:Enable(false)
			self.colorScaleFillSwatch:Enable(false)
			self.colorMoveJointStrokeSwatch:Enable(false)
			self.colorMoveJointFillSwatch:Enable(false)
			self.colorManipulateStrokeSwatch:Enable(false)
			self.colorManipulatFillSwatch:Enable(false)
			self.resetColorButton:Enable(false)
		end
		needRedraw = true
	elseif msg == self.COLOR_TRANSLATE_STROKE then
		local colorSwatchValue = self.colorTranslateStrokeSwatch:Value()
		MR_PoseTool.colorStrokeTranslateHandleR = colorSwatchValue.r
		MR_PoseTool.colorStrokeTranslateHandleG = colorSwatchValue.g
		MR_PoseTool.colorStrokeTranslateHandleB = colorSwatchValue.b
		MR_PoseTool.colorStrokeTranslateHandleA = 255
		needRedraw = true
	elseif msg == self.COLOR_TRANSLATE_FILL then
		local colorSwatchValue = self.colorTranslateFillSwatch:Value()
		MR_PoseTool.colorFillTranslateHandleR = colorSwatchValue.r
		MR_PoseTool.colorFillTranslateHandleG = colorSwatchValue.g
		MR_PoseTool.colorFillTranslateHandleB = colorSwatchValue.b
		MR_PoseTool.colorFillTranslateHandleA = 255
		needRedraw = true
	elseif msg == self.COLOR_SCALE_STROKE then
		local colorSwatchValue = self.colorScaleStrokeSwatch:Value()
		MR_PoseTool.colorStrokeScaleHandleR = colorSwatchValue.r
		MR_PoseTool.colorStrokeScaleHandleG = colorSwatchValue.g
		MR_PoseTool.colorStrokeScaleHandleB = colorSwatchValue.b
		MR_PoseTool.colorStrokeScaleHandleA = 255
		needRedraw = true
	elseif msg == self.COLOR_SCALE_FILL then
		local colorSwatchValue = self.colorScaleFillSwatch:Value()
		MR_PoseTool.colorFillScaleHandleR = colorSwatchValue.r
		MR_PoseTool.colorFillScaleHandleG = colorSwatchValue.g
		MR_PoseTool.colorFillScaleHandleB = colorSwatchValue.b
		MR_PoseTool.colorFillScaleHandleA = 255
		needRedraw = true
	elseif msg == self.COLOR_MOVE_JOINT_STROKE then
		local colorSwatchValue = self.colorMoveJointStrokeSwatch:Value()
		MR_PoseTool.colorStrokeMoveJointHandleR = colorSwatchValue.r
		MR_PoseTool.colorStrokeMoveJointHandleG = colorSwatchValue.g
		MR_PoseTool.colorStrokeMoveJointHandleB = colorSwatchValue.b
		MR_PoseTool.colorStrokeMoveJointHandleA = 255
		needRedraw = true
	elseif msg == self.COLOR_MOVE_JOINT_FILL then
		local colorSwatchValue = self.colorMoveJointFillSwatch:Value()
		MR_PoseTool.colorFillMoveJointHandleR = colorSwatchValue.r
		MR_PoseTool.colorFillMoveJointHandleG = colorSwatchValue.g
		MR_PoseTool.colorFillMoveJointHandleB = colorSwatchValue.b
		MR_PoseTool.colorFillMoveJointHandleA = 255
		needRedraw = true
	elseif msg == self.COLOR_MANIPULATE_STROKE then
		local colorSwatchValue = self.colorManipulateStrokeSwatch:Value()
		MR_PoseTool.colorStrokeManipulateHandleR = colorSwatchValue.r
		MR_PoseTool.colorStrokeManipulateHandleG = colorSwatchValue.g
		MR_PoseTool.colorStrokeManipulateHandleB = colorSwatchValue.b
		MR_PoseTool.colorStrokeManipulateHandleA = 255
		needRedraw = true
	elseif msg == self.COLOR_MANIPULATE_FILL then
		local colorSwatchValue = self.colorManipulatFillSwatch:Value()
		MR_PoseTool.colorFillManipulateHandleR = colorSwatchValue.r
		MR_PoseTool.colorFillManipulateHandleG = colorSwatchValue.g
		MR_PoseTool.colorFillManipulateHandleB = colorSwatchValue.b
		MR_PoseTool.colorFillManipulateHandleA = 255
		needRedraw = true
	elseif msg == self.RESET_COLOR then
		MR_PoseTool.colorStrokeTranslateHandleR = 255
		MR_PoseTool.colorStrokeTranslateHandleG = 0
		MR_PoseTool.colorStrokeTranslateHandleB = 0
		MR_PoseTool.colorStrokeTranslateHandleA = 255

		MR_PoseTool.colorFillTranslateHandleR = 248
		MR_PoseTool.colorFillTranslateHandleG = 121
		MR_PoseTool.colorFillTranslateHandleB = 114
		MR_PoseTool.colorFillTranslateHandleA = 255

		MR_PoseTool.colorStrokeScaleHandleR = 255
		MR_PoseTool.colorStrokeScaleHandleG = 0
		MR_PoseTool.colorStrokeScaleHandleB = 0
		MR_PoseTool.colorStrokeScaleHandleA = 255

		MR_PoseTool.colorFillScaleHandleR = 248
		MR_PoseTool.colorFillScaleHandleG = 121
		MR_PoseTool.colorFillScaleHandleB = 114
		MR_PoseTool.colorFillScaleHandleA = 255

		MR_PoseTool.colorStrokeMoveJointHandleR = 255
		MR_PoseTool.colorStrokeMoveJointHandleG = 63
		MR_PoseTool.colorStrokeMoveJointHandleB = 15
		MR_PoseTool.colorStrokeMoveJointHandleA = 255

		MR_PoseTool.colorFillMoveJointHandleR = 255
		MR_PoseTool.colorFillMoveJointHandleG = 189
		MR_PoseTool.colorFillMoveJointHandleB = 46
		MR_PoseTool.colorFillMoveJointHandleA = 255

		MR_PoseTool.colorStrokeManipulateHandleR = 255
		MR_PoseTool.colorStrokeManipulateHandleG = 63
		MR_PoseTool.colorStrokeManipulateHandleB = 15
		MR_PoseTool.colorStrokeManipulateHandleA = 255

		MR_PoseTool.colorFillManipulateHandleR = 255
		MR_PoseTool.colorFillManipulateHandleG = 189
		MR_PoseTool.colorFillManipulateHandleB = 46
		MR_PoseTool.colorFillManipulateHandleA = 255
		
		local colorTranslateStroke = LM.rgb_color:new_local()
		colorTranslateStroke.r = MR_PoseTool.colorStrokeTranslateHandleR
		colorTranslateStroke.g = MR_PoseTool.colorStrokeTranslateHandleG
		colorTranslateStroke.b = MR_PoseTool.colorStrokeTranslateHandleB
		colorTranslateStroke.a = MR_PoseTool.colorStrokeTranslateHandleA
		
		self.colorTranslateStrokeSwatch:SetValue(colorTranslateStroke)
		
		local colorTranslateFill = LM.rgb_color:new_local()
		colorTranslateFill.r = MR_PoseTool.colorFillTranslateHandleR
		colorTranslateFill.g = MR_PoseTool.colorFillTranslateHandleG
		colorTranslateFill.b = MR_PoseTool.colorFillTranslateHandleB
		colorTranslateFill.a = MR_PoseTool.colorFillTranslateHandleA
		
		self.colorTranslateFillSwatch:SetValue(colorTranslateFill)
		
		local colorScaleStroke = LM.rgb_color:new_local()
		colorScaleStroke.r = MR_PoseTool.colorStrokeScaleHandleR
		colorScaleStroke.g = MR_PoseTool.colorStrokeScaleHandleG
		colorScaleStroke.b = MR_PoseTool.colorStrokeScaleHandleB
		colorScaleStroke.a = MR_PoseTool.colorStrokeScaleHandleA

		self.colorScaleStrokeSwatch:SetValue(colorScaleStroke)
		
		local colorScaleFill = LM.rgb_color:new_local()
		colorScaleFill.r = MR_PoseTool.colorFillScaleHandleR
		colorScaleFill.g = MR_PoseTool.colorFillScaleHandleG
		colorScaleFill.b = MR_PoseTool.colorFillScaleHandleB
		colorScaleFill.a = MR_PoseTool.colorFillScaleHandleA

		self.colorScaleFillSwatch:SetValue(colorScaleFill)
		
		local colorMoveJointStroke = LM.rgb_color:new_local()
		colorMoveJointStroke.r = MR_PoseTool.colorStrokeMoveJointHandleR
		colorMoveJointStroke.g = MR_PoseTool.colorStrokeMoveJointHandleG
		colorMoveJointStroke.b = MR_PoseTool.colorStrokeMoveJointHandleB
		colorMoveJointStroke.a = MR_PoseTool.colorStrokeMoveJointHandleA

		self.colorMoveJointStrokeSwatch:SetValue(colorMoveJointStroke)
		
		local colorMoveJointFill = LM.rgb_color:new_local()
		colorMoveJointFill.r = MR_PoseTool.colorFillMoveJointHandleR
		colorMoveJointFill.g = MR_PoseTool.colorFillMoveJointHandleG
		colorMoveJointFill.b = MR_PoseTool.colorFillMoveJointHandleB
		colorMoveJointFill.a = MR_PoseTool.colorFillMoveJointHandleA

		self.colorMoveJointFillSwatch:SetValue(colorMoveJointFill)

		local colorManipulateStroke = LM.rgb_color:new_local()
		colorManipulateStroke.r = MR_PoseTool.colorStrokeManipulateHandleR
		colorManipulateStroke.g = MR_PoseTool.colorStrokeManipulateHandleG
		colorManipulateStroke.b = MR_PoseTool.colorStrokeManipulateHandleB
		colorManipulateStroke.a = MR_PoseTool.colorStrokeManipulateHandleA

		self.colorManipulateStrokeSwatch:SetValue(colorManipulateStroke)
		
		local colorManipulateFill = LM.rgb_color:new_local()
		colorManipulateFill.r = MR_PoseTool.colorFillManipulateHandleR
		colorManipulateFill.g = MR_PoseTool.colorFillManipulateHandleG
		colorManipulateFill.b = MR_PoseTool.colorFillManipulateHandleB
		colorManipulateFill.a = MR_PoseTool.colorFillManipulateHandleA

		self.colorManipulatFillSwatch:SetValue(colorManipulateFill)
		needRedraw = true
	end
	if needRedraw then
		if MR_PoseTool.mohoVersion >= 14 then
			local helper = MOHO.ScriptInterfaceHelper:new_local()
			local moho = helper:MohoObject()
			moho.view:DrawMe()
			helper:delete()
		end
	end	
end

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

function MR_PoseTool:OnMouseDown(moho, mouseEvent)
	local frame = moho.frame
	local skel = moho:Skeleton()
	if skel == nil or frame == 0 then
		return
	end
	if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0) then
		return
	end

	local lockHandles = self.lockHandles
	
	local selBoneID = -1
	self.selBones = moho:CountSelectedBones()
	if self.selBones == 1 then
		selBoneID = skel:SelectedBoneID()
	else
		lockHandles = false
	end
	
	self.translationFrame = frame
	if self.keepSelection then
		self.selectedBonesList = {}
		for i=0, skel:CountBones()-1 do
			local bone = skel:Bone(i)
			if bone.fSelected then
				table.insert(self.selectedBonesList, i)
			end
		end
	end
	
	self.trPathBone = nil
	self.keepHandles = false
	self.dragging = true
	self.lastVec:Set(mouseEvent.vec)

	local id = -1
	local mouseHoverID = -1
	local secondId = -1
	
	local pickWidth = self.pickWidth
	
	if lockHandles and selBoneID ~= -1 then
		local bonesVisibilityList = {}
		for i=0, skel:CountBones()-1 do
			local bone = skel:Bone(i)
			if not bone.fSelected then
				bonesVisibilityList[i+1] = bone.fHidden
				bone.fHidden = true
			end	
		end

		id = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)

		for i=0, skel:CountBones()-1 do
			local bone = skel:Bone(i)
			if not bone.fSelected then
				bone.fHidden = bonesVisibilityList[i+1]
			end
		end

		if id == -1 then
			secondId = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)
		end
	else
		id = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, false)
	end

	mouseHoverID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)
	local clickToSelect = self.clickToSelect
	local pickID = id
	local firstBone
	local secondBone
	local firstBoneParent
	self.isActive = false
	self.transformPath = false
	if not (mouseEvent.ctrlKey) then
		if lockHandles then
			if selBoneID == -1 and secondId == -1 then
				self.mousePickedID = id
				self.secondBoneID = id
				
				if mouseHoverID > -1 and clickToSelect then
					skel:SelectNone()
					local bone = skel:Bone(id)
					bone.fSelected = true
					self.dragging = false
					return
				end	
			else
				self.mode = self:TestMousePoint(moho, mouseEvent, selBoneID)
				if secondId > -1 and self.mode == 1 then
					id = secondId
					skel:SelectNone()
					local bone = skel:Bone(id)
					bone.fSelected = true
					self.mousePickedID = id
					self.secondBoneID = id
					selBoneID = id
					self.dragging = false
					return
				else
					self.mousePickedID = selBoneID
					self.secondBoneID = selBoneID
				end
			end
		else
			self.mousePickedID = id
			self.secondBoneID = id
		end
	else
		if lockHandles then
			if selBoneID == -1 and secondId == -1 then
				self.mousePickedID = id
				self.secondBoneID = id

				if mouseHoverID > -1 and clickToSelect then
					skel:SelectNone()
					local bone = skel:Bone(id)
					bone.fSelected = true
					self.dragging = false
					return
				end	
			else
				id = selBoneID
				self.mousePickedID = selBoneID
				self.secondBoneID = selBoneID
			end
		else
			id = self.mousePickedID
			self.secondBoneID = id
		end
	end

	self.mode = self:TestMousePoint(moho, mouseEvent, selBoneID)

	if self.mode > 1 and mouseHoverID < 0 then
		id = selBoneID
		self.mousePickedID = id
		self.secondBoneID = id
	end

	if mouseHoverID == -1 and self.mode ~= 5 then
		skel:SelectNone()
		return
	end
	
	moho.document:PrepUndo(moho.layer, true)
	moho.document:SetDirty()
	
	if mouseEvent.doubleClick and self.secondBoneID > -1 and self.doubleClickToReset then
		local bone = skel:Bone(self.secondBoneID)
		if self.mode == 0 then
			if mouseEvent.altKey then
				bone.fTempScale = bone.fScale
				
				self.childBones = {}
				self.childBonesAngelP = {}
				self.childBonesAngelN = {}
				
				for i=0, skel:CountBones()-1 do
					local childBone = skel:Bone(i)
					if  childBone.fParent == self.secondBoneID and not childBone.fFixedAngle and not childBone.fIgnoredByIK then
						local angle = childBone.fAnimAngle:GetValue(moho.layerFrame)
						childBone.fTempAngle = angle
						table.insert(self.childBones, i)
						
						if moho.layerFrame - self.interval > 0 then
							table.insert(self.childBonesAngelP, childBone.fAnimAngle:GetValue(moho.layerFrame - self.interval))
						else
							table.insert(self.childBonesAngelP, 0)
						end
						
						if moho.layerFrame + self.interval > 0 then
							table.insert(self.childBonesAngelN, childBone.fAnimAngle:GetValue(moho.layerFrame + self.interval))
						else
							table.insert(self.childBonesAngelN, 0)
						end
					end
				end
				
				local secondBoneSizeDelta = bone.fScale - bone.fAnimScale:GetValue(moho.layerFrame)
				local secondBoneAngleDelta = bone.fAngle - bone.fAnimAngle:GetValue(moho.layerFrame)
				
				local secondTipVec = LM.Vector2:new_local()
				secondTipVec:Set(bone.fLength, 0)
				bone.fMovedMatrix:Transform(secondTipVec)
				
				local secondVec = LM.Vector2:new_local()
				secondVec:Set(0, 0)
				bone.fMovedMatrix:Transform(secondVec)
				
				local boneDist = self:GetDistance(secondVec, secondTipVec)
				
				bone.fAnimPos:SetValue(moho.layerFrame, bone.fAnimPos:GetValue(0))
				skel:UpdateBoneMatrix()
				moho.layer:UpdateCurFrame()
				secondVec:Set(0, 0)
				bone.fMovedMatrix:Transform(secondVec)
				
				local NewboneDist = self:GetDistance(secondVec, secondTipVec)
				local secondDelta = (NewboneDist / boneDist)
				local newScale = (bone.fTempScale * secondDelta) - secondBoneSizeDelta
				
				bone.fAnimScale:SetValue(moho.layerFrame, newScale)
				
				local isIgnoredByIK = bone.fIgnoredByIK
				bone.fIgnoredByIK = false
				moho.layer:UpdateCurFrame()
				
				skel:IKAngleSolver(self.secondBoneID, secondTipVec, 1, true, true)

				bone.fAnimAngle:SetValue(moho.layerFrame, bone.fAngle - secondBoneAngleDelta)
				bone.fAnimAngle.value = bone.fAngle
				
				local angleSign = 1
				if (bone.fFlipH.value and not bone.fFlipV.value) or (not bone.fFlipH.value and bone.fFlipV.value) then
					angleSign = -1
				end

				local angleDelta = bone.fAngle - bone.fTempAngle
				
				for i, q in ipairs(self.childBones) do
					local childBone = skel:Bone(q)
					childBone.fAnimAngle:SetValue(moho.layerFrame, childBone.fTempAngle - (angleDelta * angleSign))
				end
				
				bone.fIgnoredByIK = isIgnoredByIK
			else	
				bone.fAnimPos:SetValue(moho.layerFrame, bone.fAnimPos:GetValue(0))
			end

			moho.layer:UpdateCurFrame()
			moho:NewKeyframe(CHANNEL_BONE_T)
			self:UpdateWidgets(moho)
			return
		elseif self.mode == 1 then
			bone.fAnimAngle:SetValue(moho.layerFrame, bone.fAnimAngle:GetValue(0))
			moho.layer:UpdateCurFrame()
			moho:NewKeyframe(CHANNEL_BONE)
			self:UpdateWidgets(moho)
			return
		elseif self.mode == 2 then
			bone.fAnimScale:SetValue(moho.layerFrame, bone.fAnimScale:GetValue(0))
			moho.layer:UpdateCurFrame()
			moho:NewKeyframe(CHANNEL_BONE_S)
			self:UpdateWidgets(moho)
			return
		end
	end
	
	skel:SelectNone()
	self.startAngle = 0
	self.startAngle2 = 0
	secondBone = skel:Bone(self.secondBoneID)
	self.jointChain = false
	self.firstBoneID = -1
	
	if self.mode == 5 then
		local bone = skel:Bone(selBoneID)
		bone.fSelected = true
		self.selID = skel:BoneID(self.trPathBone)
		self.secondBoneID = selBoneID
		
		local boneVec = LM.Vector2:new_local()
		boneVec:Set(0, 0)
		bone.fRestMatrix:Transform(boneVec)
		boneVec = boneVec - mouseEvent.startVec
		local d = boneVec:Mag()
		self.boneEnd = 0
		boneVec:Set(bone.fLength, 0)
		bone.fRestMatrix:Transform(boneVec)
		boneVec = boneVec - mouseEvent.startVec
		if (boneVec:Mag() < d) then
			self.boneEnd = 1
		end

		if (self.translationFrame ~= 0 and bone.fSelected) then
			self.boneChanged = true
			bone.fTempPos = bone.fAnimPos:GetValue(self.translationFrame)
			bone.fAnimPos:SetValue(self.translationFrame, bone.fTempPos)
		end
		
		self.isActive = true
		return
	elseif self.mode == 4 then -- manipulate bones
		self.selID = id
		self.boneBakedA = false
		self.boneBakedP = false
		self.boneBakedS = false
		if self.bakeAdjacentFrames then
			self.boneSAngleP = secondBone.fAnimAngle:GetValue(moho.layerFrame - self.interval)
			self.boneSAngleN = secondBone.fAnimAngle:GetValue(moho.layerFrame + self.interval)
			self.boneSScaleP = secondBone.fAnimScale:GetValue(moho.layerFrame - self.interval)
			self.boneSScaleN = secondBone.fAnimScale:GetValue(moho.layerFrame + self.interval)
		end
		local bone = skel:Bone(id)

		bone.fTempPos:Set(bone.fAnimPos:GetValue(moho.layerFrame))
		bone.fTempAngle = bone.fAnimAngle:GetValue(moho.layerFrame)
		bone.fTempScale = bone.fAnimScale:GetValue(moho.layerFrame)
		
		self.secondTarget = skel:TargetOfBoneChain(id, moho.layerFrame)
	
		if self.secondTarget >= 0 then
			self.isChainTargeted = true
			local targetBone = skel:Bone(self.secondTarget)
			targetBone.fTempPos = targetBone.fAnimPos:GetValue(moho.layerFrame)
			
			self.targetBonePosP = targetBone.fAnimPos:GetValue(moho.layerFrame - self.interval)
			
			self.targetBonePosN = targetBone.fAnimPos:GetValue(moho.layerFrame + self.interval)
			
			self.isTargetBonePosPBaked = false
			self.isTargetBonePosNBaked = false
		else
			self.isChainTargeted = false
		end
		
		bone.fSelected = true
		local isSmartBone = moho.layer:IsSmartBoneAction(bone:Name())

		self.isParentBonesBaked = false
		self.lastVec:Set(mouseEvent.vec)
		self.parentBones = {}
		self.parentBonesAngleP = {}
		self.parentBonesAngleN = {}
		self.parentBonesScaleP = {}
		self.parentBonesScaleN = {}
		self.startAngle = 0
		self.boneStartAngles = {}
		self.boneStartActualAngles = {}
		table.insert(self.boneStartAngles, bone.fAnimAngle:GetValue(moho.layerFrame))
		table.insert(self.boneStartActualAngles, bone.fAnimAngle.value)

		while bone.fParent >= 0 do
			local parentBone = skel:Bone(bone.fParent)
			parentBone.fTempAngle = parentBone.fAnimAngle:GetValue(moho.layerFrame)
			parentBone.fTempScale = parentBone.fAnimScale:GetValue(moho.layerFrame)
			if (self:CountBoneChildren(skel, bone.fParent, true) > 1) or parentBone.fIgnoredByIK or parentBone.fFixedAngle then
				break
			end
			local parenBoneID = bone.fParent
			bone = skel:Bone(parenBoneID)
			bone.fTempScale = bone.fAnimScale:GetValue(moho.layerFrame)
			table.insert(self.parentBones, parenBoneID)
			
			if moho.layerFrame - self.interval > 0 then
				table.insert(self.parentBonesAngleP, bone.fAnimAngle:GetValue(moho.layerFrame - self.interval))
				table.insert(self.parentBonesScaleP, bone.fAnimScale:GetValue(moho.layerFrame - self.interval))
			else
				table.insert(self.parentBonesAngleP, 0)
				table.insert(self.parentBonesScaleP, 0)
			end
			
			if moho.layerFrame + self.interval > 0 then
				table.insert(self.parentBonesAngleN, bone.fAnimAngle:GetValue(moho.layerFrame + self.interval))
				table.insert(self.parentBonesScaleN, bone.fAnimScale:GetValue(moho.layerFrame + self.interval))
			else
				table.insert(self.parentBonesAngleN, 0)
				table.insert(self.parentBonesScaleN, 0)
			end
			
			table.insert(self.boneStartAngles, bone.fAnimAngle:GetValue(moho.layerFrame))
			table.insert(self.boneStartActualAngles, bone.fAnimAngle.value)
		end

		local startBoneID = self.parentBones[#self.parentBones]
		local startBone = skel:Bone(startBoneID)
		startBone.fTempAngle = startBone.fAnimAngle:GetValue(moho.layerFrame)

		local startBonePos = LM.Vector2:new_local()
		startBonePos:Set(0, 0)
		startBone.fMovedMatrix:Transform(startBonePos)
		self.startBonePos:Set(startBonePos)
		self.startBoneDist = self:GetDistance(startBonePos, mouseEvent.vec)
		
		self.isChildBonesBaked = false

		self.childBones = {}
		self.childBonesAngelP = {}
		self.childBonesAngelN = {}

		for i=0, skel:CountBones()-1 do
			local childBone = skel:Bone(i)

			if childBone.fParent == id and not childBone.fFixedAngle and not childBone.fIgnoredByIK then
				local angle = childBone.fAnimAngle:GetValue(moho.layerFrame)
				childBone.fTempAngle = angle
				table.insert(self.childBones, i)
				if moho.layerFrame - self.interval > 0 then
					table.insert(self.childBonesAngelP, childBone.fAnimAngle:GetValue(moho.layerFrame - self.interval))
				else
					table.insert(self.childBonesAngelP, 0)
				end
				
				if moho.layerFrame + self.interval > 0 then
					table.insert(self.childBonesAngelN, childBone.fAnimAngle:GetValue(moho.layerFrame + self.interval))
				else
					table.insert(self.childBonesAngelN, 0)
				end
			end
		end
		
		if self.mode == 4 then
			self.isActive = true
			moho:UpdateBonePointSelection()
			mouseEvent.view:DrawMe()
			moho:UpdateSelectedChannels()
			self.lastVec:Set(mouseEvent.vec)
			return
		end
		
	end

	if secondBone.fParent > -1 and not secondBone:IsZeroLength() then
		self.firstBoneID = secondBone.fParent
		firstBone = skel:Bone(self.firstBoneID)
		local firstBoneChilds = skel:CountBoneChildren(self.firstBoneID, true)
		local secondBonePos = LM.Vector2:new_local()
		secondBonePos:Set(secondBone.fAnimPos:GetValue(moho.layerFrame))
		if firstBone.fIgnoredByIK == false and not firstBone.fFixedAngle and not secondBone.fFixedAngle and secondBone.fIgnoredByIK == false and firstBoneChilds == 1 and self:Round(secondBone.fPos.y) == 0 
		and not self:IsEqual(secondBonePos.x, 0, 0.0001) and not firstBone:IsZeroLength() then
			self.jointChain = true
		end
	end	
	
	self.secondBoneID = id
	secondBone.fSelected = true
	
	local useFirstBone = self.jointChain and (self.mode == 0 or self.mode == 3)
	
	if self.bakeAdjacentFrames then
		self.boneBakedA = false
		self.boneBakedP = false
		self.boneBakedS = false
		
		if useFirstBone then
			self.boneFAngleP = firstBone.fAnimAngle:GetValue(moho.layerFrame - self.interval)
			self.boneFAngleN = firstBone.fAnimAngle:GetValue(moho.layerFrame + self.interval)
			self.boneFScaleP = firstBone.fAnimScale:GetValue(moho.layerFrame - self.interval)
			self.boneFScaleN = firstBone.fAnimScale:GetValue(moho.layerFrame + self.interval)
		end	
		
		self.boneSAngleP = secondBone.fAnimAngle:GetValue(moho.layerFrame - self.interval)
		self.boneSAngleN = secondBone.fAnimAngle:GetValue(moho.layerFrame + self.interval)
		
		
		self.boneSPosP = secondBone.fAnimPos:GetValue(moho.layerFrame - self.interval) 
		self.boneSPosN = secondBone.fAnimPos:GetValue(moho.layerFrame + self.interval)
		
		self.boneSScaleP = secondBone.fAnimScale:GetValue(moho.layerFrame - self.interval)
		self.boneSScaleN = secondBone.fAnimScale:GetValue(moho.layerFrame + self.interval)
	end
	
	moho.layer:UpdateCurFrame()
	
	self.secondTarget = skel:TargetOfBoneChain(self.secondBoneID, moho.layerFrame)
	
	if self.secondTarget >= 0 then
		self.isChainTargeted = true
		local targetBone = skel:Bone(self.secondTarget)
		targetBone.fTempPos = targetBone.fAnimPos:GetValue(moho.layerFrame)
		
		self.targetBonePosP = targetBone.fAnimPos:GetValue(moho.layerFrame - self.interval)
		
		self.targetBonePosN = targetBone.fAnimPos:GetValue(moho.layerFrame + self.interval)
		
		self.isTargetBonePosPBaked = false
		self.isTargetBonePosNBaked = false
		
	else
		self.isChainTargeted = false
	end
	
	local firstBoneAngleDelta = 0
	local secondBoneAngleDelta = 0

	if self.isChainTargeted then
		local firstBoneStretchDelta
		local firstBoneIKStratching
		if useFirstBone then
			firstBoneStretchDelta = 0
			firstBoneIKStratching = firstBone.fMaxAutoScaling
			firstBone.fMaxAutoScaling = 10000
		end
		
		local secondBoneStretchDelta = 0
		local secondBoneIKStratching = secondBone.fMaxAutoScaling
		
		secondBone.fMaxAutoScaling = 10000
		
		moho.layer:UpdateCurFrame()
		
		local firstBoneFSize
		local firstBoneFAngle
		local isFirstBoneIgnoredByIK
		if useFirstBone then
			firstBoneFSize = firstBone.fScale
			firstBoneFAngle = firstBone.fAngle
			isFirstBoneIgnoredByIK = firstBone.fIgnoredByIK
		end
		
		local secondBoneFSize = secondBone.fScale
		local secondBoneFAngle = secondBone.fAngle
		
		local isSecondBoneIgnoredByIK = secondBone.fIgnoredByIK
		if useFirstBone then
			firstBone.fIgnoredByIK = true
		end
		
		secondBone.fIgnoredByIK = true
		
		moho.layer:UpdateCurFrame()
		
		if useFirstBone then
			firstBoneStretchDelta = firstBoneFSize - firstBone.fScale
			firstBoneAngleDelta = firstBoneFAngle - firstBone.fAngle
		end
		
		secondBoneStretchDelta = secondBoneFSize - secondBone.fScale
		secondBoneAngleDelta = secondBoneFAngle - secondBone.fAngle
		
		if useFirstBone then
			firstBone.fIgnoredByIK = isFirstBoneIgnoredByIK
			firstBone.fMaxAutoScaling = firstBoneIKStratching
		end
		
		secondBone.fIgnoredByIK = isSecondBoneIgnoredByIK
		secondBone.fMaxAutoScaling = secondBoneIKStratching
		if useFirstBone then
			if (self.ignoreZeroScaledBones and self:Round(firstBone.fAnimScale:GetValue(0), 1) == 1) or not self.ignoreZeroScaledBones then
				firstBone.fAnimScale:SetValue(moho.layerFrame, firstBone.fAnimScale:GetValue(moho.layerFrame) + firstBoneStretchDelta)
			end	
			firstBone.fAnimAngle:SetValue(moho.layerFrame, firstBone.fAnimAngle:GetValue(moho.layerFrame) + firstBoneAngleDelta)
		end
		if (self.ignoreZeroScaledBones and self:Round(secondBone.fAnimScale:GetValue(0), 1) == 1) or not self.ignoreZeroScaledBones then
			secondBone.fAnimScale:SetValue(moho.layerFrame, secondBone.fAnimScale:GetValue(moho.layerFrame) + secondBoneStretchDelta)
		end	
		secondBone.fAnimAngle:SetValue(moho.layerFrame, secondBone.fAnimAngle:GetValue(moho.layerFrame) + secondBoneAngleDelta)
		
		moho.layer:UpdateCurFrame()
	end	
	self.isTargetMoved = false
	
	local secondTipVec = LM.Vector2:new_local()
	local firstVec = LM.Vector2:new_local()
	local secondVec = LM.Vector2:new_local()
	secondTipVec:Set(secondBone.fLength, 0)
	firstVec:Set(0, 0)
	secondVec:Set(0, 0)
	secondBone.fMovedMatrix:Transform(secondTipVec)
	secondBone.fMovedMatrix:Transform(secondVec)
	
	self.secondBonePos:Set(secondVec)
	
	if useFirstBone then
		firstBone.fMovedMatrix:Transform(firstVec)
		self.firstBonePos:Set(firstVec)
		self.firstDist = self:GetDistance(self.firstBonePos, self.secondBonePos)
	end
	
	self.secondBoneTipPos:Set(secondTipVec)
	self.secondBoneDist = self:GetDistance(self.secondBonePos, self.secondBoneTipPos)
	local mousePos = mouseEvent.vec
	
	self.clickOffset = self.secondBonePos - mousePos
	
	if self.mode == 2 then
		self.clickOffset = self.secondBoneTipPos - mousePos
	end
	
	if useFirstBone then
		self.firstBoneSizeDelta = firstBone.fScale - firstBone.fAnimScale:GetValue(moho.layerFrame)
	end	
	self.secondBoneSizeDelta = secondBone.fScale - secondBone.fAnimScale:GetValue(moho.layerFrame)
	
	self.isChildBonesBaked = false

	self.childBones = {}
	self.childBonesAngelP = {}
	self.childBonesAngelN = {}
	
	for i=0, skel:CountBones()-1 do
		local bone = skel:Bone(i)
		if  bone.fParent == self.secondBoneID and not bone.fFixedAngle and not bone.fIgnoredByIK then
			local angle = bone.fAnimAngle:GetValue(moho.layerFrame)
			bone.fTempAngle = angle
			table.insert(self.childBones, i)
			
			if moho.layerFrame - self.interval > 0 then
				table.insert(self.childBonesAngelP, bone.fAnimAngle:GetValue(moho.layerFrame - self.interval))
			else
				table.insert(self.childBonesAngelP, 0)
			end
			
			if moho.layerFrame + self.interval > 0 then
				table.insert(self.childBonesAngelN, bone.fAnimAngle:GetValue(moho.layerFrame + self.interval))
			else
				table.insert(self.childBonesAngelN, 0)
			end
		end
	end
	
	local firstBoneActualAngle
	
	if useFirstBone then
		firstBoneActualAngle = firstBone.fAngle
		self.firstBoneAngleDelta = firstBoneActualAngle - firstBone.fAnimAngle:GetValue(moho.layerFrame)
	end
	
	local secondBoneActualAngle = secondBone.fAngle
	self.secondBoneAngleDelta = secondBoneActualAngle - secondBone.fAnimAngle:GetValue(moho.layerFrame)
	
	self.lastVec2:Set(0, 0)
	skel:UpdateBoneMatrix()
	secondBone.fMovedMatrix:Transform(self.lastVec2)
	
	if self.mode > 1 then
		if useFirstBone then
			firstBone.fAnimAngle:SetValue(moho.layerFrame, firstBone.fAnimAngle:GetValue(moho.layerFrame))
			firstBone.fAnimAngle.value = firstBoneActualAngle
		end
	
		secondBone.fAnimAngle:SetValue(moho.layerFrame, secondBone.fAnimAngle:GetValue(moho.layerFrame))
		secondBone.fAnimAngle.value = secondBoneActualAngle
	end	
	
	if useFirstBone then
		firstBone.fTempScale = firstBone.fScale
		firstBone.fTempAngle = firstBone.fAngle
	end

	secondBone.fTempScale = secondBone.fScale
	secondBone.fTempAngle = secondBone.fAngle
	
	if self.mode == 0 then
		secondBone.fTempPos:Set(secondBone.fAnimPos:GetValue(moho.layerFrame))
	end
	
	self.isActive = true
	
	if useFirstBone then
		self.firstBoneParentID = firstBone.fParent
		if self.firstBoneParentID > -1 then
			firstBoneParent = skel:Bone(self.firstBoneParentID)
			self.firstBoneParentIBIK = firstBoneParent.fIgnoredByIK
			firstBoneParent.fIgnoredByIK = true
		end
	end

	local boneFirstLenght
	local boneFirstScale
	if useFirstBone then
		boneFirstLenght = secondBone.fPos.x
		boneFirstScale = firstBone.fScale
	end
	local boneSecondLenght = secondBone.fLength
	local boneSecondScale = secondBone.fScale
	if useFirstBone then
		self.firstBoneScalePercent = ((boneFirstLenght * boneFirstScale) / ((boneFirstLenght * boneFirstScale) + (boneSecondLenght * boneSecondScale))) * 100
		self.firstBoneOffset = firstBone.fScale - firstBone.fAnimScale:GetValue(moho.layerFrame)
	end
	self.secondBoneOffset = secondBone.fScale - secondBone.fAnimScale:GetValue(moho.layerFrame)
	moho.layer:UpdateCurFrame()
	moho:UpdateBonePointSelection()
	mouseEvent.view:DrawMe()
	moho:UpdateSelectedChannels()
end

function MR_PoseTool:OnMouseMoved(moho, mouseEvent)
	local frame = moho.frame
	local skel = moho:Skeleton()
	if skel == nil or frame == 0 then
		mouseEvent.view:SetCursor(MOHO.disabledCursor)
		return
	end
	
	
	if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0)then
		mouseEvent.view:SetCursor(MOHO.disabledCursor)
		return
	end

	local boneID = -1
	local bone
	local lockMousePickedID = -1
	local selectedBones = moho:CountSelectedBones()
	local lockHandles = self.lockHandles
	
	if selectedBones == 1 then
		boneID = skel:SelectedBoneID()
		bone = skel:Bone(boneID)
	else
		selectedBones = false
	end
	
	local pickWidth = self.pickWidth

	if (not self.dragging) then
		if (not mouseEvent.ctrlKey and not lockHandles) or lockHandles then
			self.mousePickedID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, false)
		end

		self.mouseHoverID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)
		if not (mouseEvent.ctrlKey) then
			if lockHandles and selectedBones == 1 then
				self.additionHandles = self:CheckBone(moho, boneID)
				lockMousePickedID = self.mousePickedID 
				self.mousePickedID = boneID
			else
				if self.mouseHoverID == -1 then
					self.mousePickedID = -1
				end
				self.additionHandles = self:CheckBone(moho, self.mousePickedID)
			end	
		else
			if lockHandles and selectedBones == 1 then
				self.additionHandles = self:CheckBone(moho, boneID)
				lockMousePickedID = self.mousePickedID 
				self.mousePickedID = boneID
			end
		end
		local mode
		
		if lockHandles and selectedBones == 1 then
			mode = self:TestMousePoint(moho, mouseEvent, boneID)
			self.drawMode = mode
			
			if self.mouseHoverID > -1 then
				if mode == 0 or mode == 5 then
					mouseEvent.view:SetCursor(MOHO.moveCursor)
				elseif (mode == 1) then
					if lockMousePickedID ~= boneID then
						mouseEvent.view:SetCursor(self.mainCursor)
					else
						mouseEvent.view:SetCursor(MOHO.rotateCursor)
					end
				elseif (mode == 2) then
					mouseEvent.view:SetCursor(MOHO.scaleCursor)
				elseif (mode == 3) then
					mouseEvent.view:SetCursor(self.mjCursor)
				elseif (mode == 4) then
					mouseEvent.view:SetCursor(self.mbCursor)		
				end
			else
				mouseEvent.view:SetCursor(self.mainCursor)
			end
		else
			if self.mouseHoverID > -1 or bone ~= nil then
				mode = self:TestMousePoint(moho, mouseEvent, boneID)
				self.drawMode = mode

				if not (self.mouseHoverID < 0 and mode ~= 5) then
					if mode == 0 or mode == 5 then
						mouseEvent.view:SetCursor(MOHO.moveCursor)
					elseif (mode == 1) then
						if self.mousePickedID ~= self.mouseHoverID and mouseEvent.ctrlKey then
							mouseEvent.view:SetCursor(self.mainCursor)
						else
							mouseEvent.view:SetCursor(MOHO.rotateCursor)
						end
					elseif (mode == 2) then
						mouseEvent.view:SetCursor(MOHO.scaleCursor)
					elseif (mode == 3) then
						mouseEvent.view:SetCursor(self.mjCursor)
					elseif (mode == 4) then
						mouseEvent.view:SetCursor(self.mbCursor)		
					end
				else
					mouseEvent.view:SetCursor(self.mainCursor)
				end
			else
				mouseEvent.view:SetCursor(self.mainCursor)
			end
		end
		mouseEvent.view:DrawMe()
		return
	end
	
	if self.isActive == false then
		return
	end

	if self.mode == 0 or self.mode == 5 then -- move
		self:OnMouseMovedT(moho, mouseEvent)
	elseif self.mode == 1 then -- rotate
		self:OnMouseMovedR(moho, mouseEvent)
	elseif self.mode == 2 then -- scale rotate
		self:OnMouseMovedS(moho, mouseEvent)
	elseif self.mode == 3 then -- move joint
		if self.jointChain then
			self:OnMouseMovedJ(moho, mouseEvent)
		end
	elseif self.mode == 4 then -- manipulate bones
		self:OnMouseMovedM(moho, mouseEvent)
	end
end

function MR_PoseTool:OnMouseMovedJ(moho, mouseEvent)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return
	end
	local firstBone = skel:Bone(self.firstBoneID)
	local secondBone = skel:Bone(self.secondBoneID)
	
	if self.bakeAdjacentFrames and not self.boneBakedA then
		self:BakeFrames(moho, secondBone, firstBone, true, false, true)
		self.boneBakedA = true
	end
	
	local vectorMousePos = (mouseEvent.vec + self.clickOffset)

	local firstCursorDist = self:GetDistance(vectorMousePos, self.firstBonePos)

	local firstDelta = (firstCursorDist / self.firstDist)
	firstBone.fAnimScale:SetValue(moho.layerFrame, (firstBone.fTempScale * firstDelta) - self.firstBoneSizeDelta)
	
	if self.isChainTargeted then
		local secondCursorDist = self:GetDistance(vectorMousePos, self.secondBoneTipPos)
		local secondDelta = (secondCursorDist / self.secondBoneDist)
		secondBone.fAnimScale:SetValue(moho.layerFrame, (secondBone.fTempScale * secondDelta) - self.secondBoneSizeDelta)
		
		if mouseEvent.shiftKey then
			local totalDist = firstCursorDist + secondCursorDist
			local distP = (totalDist / 100) * self.firstBoneScalePercent
			distP = distP / firstBone.fLength
			local secondDistP = (totalDist / 100) * (100 - self.firstBoneScalePercent)
			secondDistP = secondDistP / secondBone.fLength
			firstBone.fAnimScale:SetValue(moho.layerFrame, distP - self.firstBoneOffset)
			secondBone.fAnimScale:SetValue(moho.layerFrame, secondDistP - self.secondBoneOffset)
		end
		
		skel:IKAngleSolver(self.firstBoneID, vectorMousePos, 1, true, false)
		local firstBoneNewAngle = firstBone.fAngle - self.firstBoneAngleDelta
		
		firstBone.fAnimAngle:SetValue(moho.layerFrame, firstBoneNewAngle)
		firstBone.fAnimAngle.value = firstBone.fAngle

		if not secondBone.fFixedAngle then
			firstBone.fIgnoredByIK = true
			skel:IKAngleSolver(self.secondBoneID, self.secondBoneTipPos, 1, true, true)
			
			secondBone.fAnimAngle:SetValue(moho.layerFrame, secondBone.fAngle - self.secondBoneAngleDelta)
			secondBone.fAnimAngle.value = secondBone.fAngle

			firstBone.fIgnoredByIK = false

			moho.layer:UpdateCurFrame()

			skel:IKAngleSolver(self.secondBoneID, self.secondBoneTipPos, 1, true, true)
			
			local secondBoneNewAngle = secondBone.fAngle - self.secondBoneAngleDelta
			
			secondBone.fAnimAngle:SetValue(moho.layerFrame, secondBoneNewAngle)
			secondBone.fAnimAngle.value = secondBone.fAngle

			firstBone.fAnimAngle:SetValue(moho.layerFrame, firstBone.fAngle - self.firstBoneAngleDelta)
			firstBone.fAnimAngle.value = firstBone.fAngle
			
			firstBone.fIgnoredByIK = currentIgnoredByIK
		end
	else
		if mouseEvent.shiftKey then
			local firstCursorDist = self:GetDistance(vectorMousePos, self.firstBonePos)
			local secondCursorDist = self:GetDistance(vectorMousePos, self.secondBoneTipPos)

			local firstDelta = (firstCursorDist / self.firstDist)
			local secondDelta = (secondCursorDist / self.secondBoneDist)
			firstBone.fAnimScale:SetValue(moho.layerFrame, (firstBone.fTempScale * firstDelta) - self.firstBoneSizeDelta)
			secondBone.fAnimScale:SetValue(moho.layerFrame, (secondBone.fTempScale * secondDelta) - self.secondBoneSizeDelta)
			
			local totalDist = firstCursorDist + secondCursorDist
			local distP = (totalDist / 100) * self.firstBoneScalePercent
			distP = distP / firstBone.fLength
			local secondDistP = (totalDist / 100) * (100 - self.firstBoneScalePercent)
			secondDistP = secondDistP / secondBone.fLength
			firstBone.fAnimScale:SetValue(moho.layerFrame, distP - self.firstBoneOffset)
			secondBone.fAnimScale:SetValue(moho.layerFrame, secondDistP - self.secondBoneOffset)
			
			skel:IKAngleSolver(self.firstBoneID, vectorMousePos, 1, true, false)
			
			local originalAngle = firstBone.fTempAngle
			local correctedAngle = firstBone.fAngle
			local delta = originalAngle - correctedAngle

			while math.abs(delta) > math.rad(180) do
				if delta > math.rad(180) then
					correctedAngle = correctedAngle + math.rad(360)
				elseif delta < math.rad(-180) then
					correctedAngle = correctedAngle - math.rad(360)
				end
				delta = originalAngle - correctedAngle
			end

			local restoredAngle = correctedAngle - self.firstBoneAngleDelta
			
			firstBone.fAnimAngle:SetValue(moho.layerFrame, restoredAngle)
			firstBone.fAnimAngle.value = firstBone.fAngle
			
			secondBone.fAnimScale.value = secondBone.fScale
			local currentIgnoredByIK = firstBone.fIgnoredByIK
			
			if not secondBone.fFixedAngle then
				firstBone.fIgnoredByIK = true
				skel:IKAngleSolver(self.secondBoneID, self.secondBoneTipPos, 10, true, true)
				
				secondBone.fAnimAngle:SetValue(moho.layerFrame, secondBone.fAngle - self.secondBoneAngleDelta)
				secondBone.fAnimAngle.value = secondBone.fAngle

				firstBone.fIgnoredByIK = false

				moho.layer:UpdateCurFrame()

				skel:IKAngleSolver(self.secondBoneID, self.secondBoneTipPos, 10, true, true)
				
				originalAngle = secondBone.fTempAngle
				correctedAngle = secondBone.fAngle
				delta = originalAngle - correctedAngle

				while math.abs(delta) > math.rad(180) do
					if delta > math.rad(180) then
						correctedAngle = correctedAngle + math.rad(360)
					elseif delta < math.rad(-180) then
						correctedAngle = correctedAngle - math.rad(360)
					end
					delta = originalAngle - correctedAngle
				end

				restoredAngle = correctedAngle - self.secondBoneAngleDelta
				
				secondBone.fAnimAngle:SetValue(moho.layerFrame, restoredAngle)
				secondBone.fAnimAngle.value = secondBone.fAngle

				originalAngle = firstBone.fTempAngle
				correctedAngle = firstBone.fAngle
				delta = originalAngle - correctedAngle

				while math.abs(delta) > math.rad(180) do
					if delta > math.rad(180) then
						correctedAngle = correctedAngle + math.rad(360)
					elseif delta < math.rad(-180) then
						correctedAngle = correctedAngle - math.rad(360)
					end
					delta = originalAngle - correctedAngle
				end

				restoredAngle = correctedAngle - self.firstBoneAngleDelta
				
				firstBone.fAnimAngle:SetValue(moho.layerFrame, restoredAngle)
				firstBone.fAnimAngle.value = firstBone.fAngle
				
				firstBone.fIgnoredByIK = currentIgnoredByIK
			end
		else
			local bone = firstBone
			local center = LM.Vector2:new_local()
			center:Set(0, 0)
			skel:UpdateBoneMatrix(self.firstBoneID)
			bone.fMovedMatrix:Transform(center)
			
			local mousePos = mouseEvent.vec
			
			local angle = self.startAngle
			local v1 = self.lastVec - center
			local v2 = mousePos - center
			v2:Rotate(-math.atan2(v1.y, v1.x))
			angle = angle + math.atan2(v2.y, v2.x)
			self.startAngle = angle
			self.lastVec:Set(mousePos)
			local angleSign = 1.0
			if (not bone.fFixedAngle) then
				angleSign = bone:ParentalFlipFactor()
			end

			local newAgle = (bone.fTempAngle + (angle * angleSign)) - self.firstBoneAngleDelta

			if not bone.fFixedAngle then
				if bone.fConstraints then
					local min = bone.fAnimAngle:GetValue(0) - self.firstBoneAngleDelta
					local max = min + bone.fMaxConstraint
					min = min + bone.fMinConstraint
					newAgle = LM.Clamp(newAgle, min, max)
				end
			end
			if not self:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
				bone.fAnimAngle:SetValue(moho.layerFrame, newAgle)
				bone.fAnimAngle.value = bone.fAngle
				if self.bakeAdjacentFrames and not self.boneBakedA then
					self:BakeFrames(moho, firstBone, nil, true, false, false)
					self.boneBakedA = true
				end
			end
			
			moho.layer:UpdateCurFrame()

			local bone = secondBone
			local center = LM.Vector2:new_local()

			center:Set(0, 0)
			skel:UpdateBoneMatrix(self.secondBoneID)
			bone.fMovedMatrix:Transform(center)
			
			local angle2 = self.startAngle2
			local v1 = self.lastVec2 - self.secondBoneTipPos
			local v2 = center - self.secondBoneTipPos
			v2:Rotate(-math.atan2(v1.y, v1.x))
			angle2 = angle2 + math.atan2(v2.y, v2.x)
			self.startAngle2 = angle2
			self.lastVec2:Set(center)
			
			local angleSign2 = 1.0
			if (not bone.fFixedAngle) then
				angleSign2 = bone:ParentalFlipFactor()
			end

			local newAgle2 = (bone.fTempAngle + (angle2 * angleSign2)) - (angle * angleSign2) - self.secondBoneAngleDelta
			if not bone.fFixedAngle then
				if bone.fConstraints then
					local min = bone.fAnimAngle:GetValue(0) - self.secondBoneAngleDelta
					local max = min + bone.fMaxConstraint
					min = min + bone.fMinConstraint
					newAgle2 = LM.Clamp(newAgle2, min, max)
				end
			end
			if not self:IsEqual(newAgle2, bone.fAnimAngle:GetValue(moho.layerFrame), 0.0001) then
				bone.fAnimAngle:SetValue(moho.layerFrame, newAgle2)
				bone.fAnimAngle.value = bone.fAngle
				if self.bakeAdjacentFrames and not self.boneBakedA then
					self:BakeFrames(moho, secondBone, nil, true, false, false)
					self.boneBakedA = true
				end
			end

			moho.layer:UpdateCurFrame()
		
			local center = LM.Vector2:new_local()
			center:Set(0, 0)
			skel:UpdateBoneMatrix()
			secondBone.fMovedMatrix:Transform(center)
			local secondCursorDist = self:GetDistance(center, self.secondBoneTipPos)
			local secondDelta = (secondCursorDist / self.secondBoneDist)
			secondBone.fAnimScale:SetValue(moho.layerFrame, (secondBone.fTempScale * secondDelta) - self.secondBoneSizeDelta)
		end
		
		local angleSign = 1
		if (secondBone.fFlipH.value and not secondBone.fFlipV.value) or (not secondBone.fFlipH.value and secondBone.fFlipV.value) then
			angleSign = -1
		end
	end
	
	if self.isChainTargeted and self.isTargetMoved then
		local targetBone = skel:Bone(self.secondTarget)
		targetBone.fAnimPos:SetValue(moho.layerFrame, targetBone.fTempPos)
	end
	secondBone.fAnimScale.value = secondBone.fScale
	
	if mouseEvent.altKey then
		local angleSign = 1
		local angleSignS = 1
		if (secondBone.fFlipH.value and not secondBone.fFlipV.value) or (not secondBone.fFlipH.value and secondBone.fFlipV.value) then
			angleSignS = -1
		end
		local angleSignF = 1
		if (firstBone.fFlipH.value and not firstBone.fFlipV.value) or (not firstBone.fFlipH.value and firstBone.fFlipV.value) then
			angleSignF = -1
		end
		
		local angleDelta = 0
		if angleSignF == 1 and angleSignS == -1 then
			angleSign = -1
			angleDelta = (firstBone.fAngle - firstBone.fTempAngle) + (secondBone.fAngle - secondBone.fTempAngle)
		elseif angleSignF == 1 and angleSignS == 1 then
			angleDelta = (firstBone.fAngle - firstBone.fTempAngle) + (secondBone.fAngle - secondBone.fTempAngle)	
		elseif angleSignF == -1 and angleSignS == -1 then
			angleDelta = (firstBone.fAngle - firstBone.fTempAngle) + ((secondBone.fAngle - secondBone.fTempAngle) * angleSignF)
		elseif angleSignF == -1 and angleSignS == 1 then
			angleSign = -1
			angleDelta = (firstBone.fAngle - firstBone.fTempAngle) + ((secondBone.fAngle - secondBone.fTempAngle) * angleSignF)
		end
		
		while angleDelta > math.rad(180) do
			angleDelta = angleDelta - math.rad(360)
		end
		
		while angleDelta < math.rad(-180) do
			angleDelta = angleDelta + math.rad(360)
		end

		if not self.isChildBonesBaked and self.bakeAdjacentFrames then
			for i, q in ipairs(self.childBones) do
				local bone = skel:Bone(q)
				if not self.isChildBonesBaked then
					if moho.layerFrame - self.interval > 0 then
						bone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.childBonesAngelP[i])
					end
				end
				if not self.isChildBonesBaked then
					if moho.layerFrame + self.interval > 0 then
						bone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.childBonesAngelN[i])
					end
				end
			end
			self.isChildBonesBaked = true
		end	
		for i, q in ipairs(self.childBones) do
			local bone = skel:Bone(q)
			local newAngle = bone.fTempAngle - (angleDelta * angleSign)
			bone.fAnimAngle:SetValue(moho.layerFrame, newAngle)
		end
	else
		for i, q in ipairs(self.childBones) do
			local firstBone = skel:Bone(q)
			if not self:IsEqual(firstBone.fTempAngle, firstBone.fAnimAngle:GetValue(moho.layerFrame), 0.0001) then
				firstBone.fAnimAngle:SetValue(moho.layerFrame, firstBone.fTempAngle)
			end	
		end
	end
	
	moho.layer:UpdateCurFrame()
	mouseEvent.view:DrawMe()
end

function MR_PoseTool:OnMouseMovedT(moho, mouseEvent)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return
	end

	local bone = skel:Bone(self.secondBoneID)
	bone.fPos:Set(bone.fTempPos)

	local offset = mouseEvent.vec - mouseEvent.startVec
	
	local boneVec = LM.Vector2:new_local()
	local inverseM = LM.Matrix:new_local()
	
	local parent = nil
	boneVec:Set(0, 0)
	if (bone.fParent >= 0) then
		parent = skel:Bone(bone.fParent)
		parent.fMovedMatrix:Transform(boneVec)
	end
	boneVec = boneVec + offset
	if (parent) then
		inverseM:Set(parent.fMovedMatrix)
		inverseM:Invert()
		inverseM:Transform(boneVec)
	end
	if (mouseEvent.shiftKey) then
		if (math.abs(boneVec.x) > math.abs(boneVec.y)) then
			boneVec.y = 0
		else
			boneVec.x = 0
		end
	end
	local v = nil
	v = bone.fPos + boneVec
	if self.mode == 5 then
			bone.fAnimPos:SetValue(self.translationFrame, v)
	elseif self.mode == 0 then
		local bonePos = bone.fAnimPos:GetValue(moho.layerFrame)
		if not self:IsEqual(v.x, bonePos.x, 0.000001) or not self:IsEqual(v.y, bonePos.y, 0.000001) then
			bone.fAnimPos:SetValue(moho.layerFrame, v)
			if self.bakeAdjacentFrames and not self.boneBakedP then
				self:BakeFrames(moho, bone, nil, false, true, false)
				self.boneBakedP = true
			end
		end	
	end	
	if self.mode == 0 then
		if (self.ignoreZeroScaledBones and self:Round(bone.fAnimScale:GetValue(0), 1) == 1) or not self.ignoreZeroScaledBones then
			if mouseEvent.altKey and bone.fLength > 0 then
				local vectorMousePos = mouseEvent.vec + self.clickOffset
				local secondCursorDist = self:GetDistance(vectorMousePos, self.secondBoneTipPos)
				local secondDelta = (secondCursorDist / self.secondBoneDist)
				local newScale = (bone.fTempScale * secondDelta) - self.secondBoneSizeDelta
				if not self:IsEqual(newScale, bone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then
					bone.fAnimScale:SetValue(moho.layerFrame, newScale)
					if self.bakeAdjacentFrames and not self.boneBakedS then
						self:BakeFrames(moho, bone, nil, false, false, true)
						self.boneBakedS = true
					end
				end
				moho.layer:UpdateCurFrame()

				local center = LM.Vector2:new_local()

				center:Set(0, 0)
				skel:UpdateBoneMatrix(self.secondBoneID)
				bone.fMovedMatrix:Transform(center)
				
				local angle = self.startAngle2
				local v1 = self.lastVec2 - self.secondBoneTipPos
				local v2 = center - self.secondBoneTipPos
				v2:Rotate(-math.atan2(v1.y, v1.x))
				angle = angle + math.atan2(v2.y, v2.x)
				self.startAngle2 = angle
				self.lastVec2:Set(center)

				local angleSign = 1.0
				if (not bone.fFixedAngle) then
					angleSign = bone:ParentalFlipFactor()
				end
				
				local newAgle = (bone.fTempAngle + (angle * angleSign)) - self.secondBoneAngleDelta
				if not bone.fFixedAngle then
					if bone.fConstraints then
						local min = bone.fAnimAngle:GetValue(0) - self.secondBoneAngleDelta
						local max = min + bone.fMaxConstraint
						min = min + bone.fMinConstraint
						newAgle = LM.Clamp(newAgle, min, max)
					end
				end
				if not self:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
					bone.fAnimAngle:SetValue(moho.layerFrame, newAgle)
					bone.fAnimAngle.value = bone.fAngle
				end
				if self.bakeAdjacentFrames and not self.boneBakedA then
					self:BakeFrames(moho, bone, nil, true, false, false)
					self.boneBakedA = true
					if not self.isChildBonesBaked then
						for i, q in ipairs(self.childBones) do
							local bone = skel:Bone(q)
							if moho.layerFrame - self.interval > 0 then
								bone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.childBonesAngelP[i])
								bone.fAnimAngle.value = bone.fAngle
							end
							if moho.layerFrame + self.interval > 0 then
								bone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.childBonesAngelN[i])
								bone.fAnimAngle.value = bone.fAngle
							end
						end
						self.isChildBonesBaked = true
					end
					
				end

				local angleSign = 1
				if (bone.fFlipH.value and not bone.fFlipV.value) or (not bone.fFlipH.value and bone.fFlipV.value) then
					angleSign = -1
				end
				
				moho.layer:UpdateCurFrame()
				
				local angleDelta = bone.fAngle - bone.fTempAngle
				
				for i, q in ipairs(self.childBones) do
					local bone = skel:Bone(q)
					bone.fAnimAngle:SetValue(moho.layerFrame, bone.fTempAngle - (angleDelta * angleSign))
					bone.fAnimAngle.value = bone.fAngle
				end
			end	
		else
			if not self:IsEqual(bone.fTempScale - self.secondBoneSizeDelta, bone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then
				bone.fAnimScale:SetValue(moho.layerFrame, bone.fTempScale)
			end
			local newAngle = bone.fTempAngle - self.secondBoneAngleDelta
			if not self:IsEqual(newAngle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
				bone.fAnimAngle:SetValue(moho.layerFrame, newAngle)
			end	
			for i, q in ipairs(self.childBones) do
				local bone = skel:Bone(q)
				if not self:IsEqual(bone.fTempAngle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
					bone.fAnimAngle:SetValue(moho.layerFrame, bone.fTempAngle)
				end	
			end
		end
	end
	
	moho.layer:UpdateCurFrame()
	mouseEvent.view:DrawMe()
end

function MR_PoseTool:OnMouseMovedR(moho, mouseEvent)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return
	end

	local secondBone = skel:Bone(self.secondBoneID)

	local bone = secondBone
	local center = LM.Vector2:new_local()
	center:Set(0, 0)
	skel:UpdateBoneMatrix()
	bone.fMovedMatrix:Transform(center)
	
	local layerMatrix = LM.Matrix:new_local()
	local mousePos = mouseEvent.vec
	local angle = self.startAngle
	local v1 = self.lastVec - center
	local v2 = mousePos - center
	v2:Rotate(-math.atan2(v1.y, v1.x))
	angle = angle + math.atan2(v2.y, v2.x)
	self.startAngle = angle
	self.lastVec:Set(mousePos)
	local angleSign = 1.0
	if (not bone.fFixedAngle) then
		angleSign = bone:ParentalFlipFactor()
	end

	local newAgle = (bone.fTempAngle + (angle * angleSign)) - self.secondBoneAngleDelta
	
	if not bone.fFixedAngle then
		if bone.fConstraints then
			local min = bone.fAnimAngle:GetValue(0) - self.secondBoneAngleDelta
			local max = min + bone.fMaxConstraint
			min = min + bone.fMinConstraint
			newAgle = LM.Clamp(newAgle, min, max)
		end
	end
	
	if (mouseEvent.shiftKey) then
		newAgle = newAgle / (math.pi / 4)
		newAgle = (math.pi / 4) * LM.Round(newAgle)
	end
	
	if not self:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
		bone.fAnimAngle:SetValue(moho.layerFrame, newAgle)
		if self.bakeAdjacentFrames and not self.boneBakedA then
			self:BakeFrames(moho, secondBone, nil, true, false, false)
			self.boneBakedA = true
		end
	end	

	local angleSign = 1
	if (bone.fFlipH.value and not bone.fFlipV.value) or (not bone.fFlipH.value and bone.fFlipV.value) then
		angleSign = -1
	end
	
	if self.isChainTargeted then
		local targetBone = skel:Bone(self.secondTarget)
		local newTargetPos = targetBone.fTempPos - (mouseEvent.startVec - mouseEvent.vec)
		targetBone.fAnimPos:SetValue(moho.layerFrame, newTargetPos)
		self.isTargetMoved = true
		if self.bakeAdjacentFrames then
			if not self.isTargetBonePosPBaked then
				if moho.layerFrame - self.interval > 0 then
					targetBone.fAnimPos:SetValue(moho.layerFrame - self.interval, self.targetBonePosP)
				end
				self.isTargetBonePosPBaked = true
			end
			
			if not self.isTargetBonePosNBaked then
				if moho.layerFrame + self.interval > 0 then
					targetBone.fAnimPos:SetValue(moho.layerFrame + self.interval, self.targetBonePosN)
				end
				self.isTargetBonePosNBaked = true
			end
		end	
	end
	
	if mouseEvent.altKey then
		moho.layer:UpdateCurFrame()
		local angleDelta = secondBone.fAngle - secondBone.fTempAngle
		
		if self.bakeAdjacentFrames and not self.isChildBonesBaked then
			for i, q in ipairs(self.childBones) do
				local childBone = skel:Bone(q)
				if moho.layerFrame - self.interval > 0 then
					childBone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.childBonesAngelP[i])
				end
				if moho.layerFrame + self.interval > 0 then
					childBone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.childBonesAngelN[i])
				end
			end	
			self.isChildBonesBaked = true
		end
		
		for i, q in ipairs(self.childBones) do
			local childBone = skel:Bone(q)
			childBone.fAnimAngle:SetValue(moho.layerFrame, childBone.fTempAngle - (angleDelta * angleSign))
		end
	else
		for i, q in ipairs(self.childBones) do
			local childBone = skel:Bone(q)
			if not self:IsEqual(childBone.fTempAngle, childBone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
				childBone.fAnimAngle:SetValue(moho.layerFrame, childBone.fTempAngle)
			end	
		end
	end
	
	moho.layer:UpdateCurFrame()
	mouseEvent.view:DrawMe()
end

function MR_PoseTool:OnMouseMovedS(moho, mouseEvent)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return
	end
	local secondBone = skel:Bone(self.secondBoneID)
	if secondBone:IsZeroLength() then
		local scaleFactor = (mouseEvent.pt.x - mouseEvent.startPt.x) / 100
		if (scaleFactor < 0) then
			scaleFactor = 1 / (-scaleFactor + 1)
		else
			scaleFactor = scaleFactor + 1
		end
		local newScale = (secondBone.fTempScale * scaleFactor) - self.secondBoneSizeDelta
		
		if not self:IsEqual(newScale, secondBone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then
			secondBone.fAnimScale:SetValue(moho.layerFrame, newScale)
			if self.bakeAdjacentFrames and not self.boneBakedS then
				self:BakeFrames(moho, secondBone, nil, false, false, true)
				self.boneBakedS = true
			end
		end
	else
		local vectorMousePos = mouseEvent.vec + self.clickOffset
		local secondCursorDist = self:GetDistance(vectorMousePos, self.secondBonePos)
		local secondDelta = (secondCursorDist / self.secondBoneDist)
		local newScale = (secondBone.fTempScale * secondDelta) - self.secondBoneSizeDelta
		if not self:IsEqual(newScale, secondBone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then
			secondBone.fAnimScale:SetValue(moho.layerFrame, newScale)
			if self.bakeAdjacentFrames and not self.boneBakedS then
				self:BakeFrames(moho, secondBone, nil, false, false, true)
				self.boneBakedS = true
			end
		end
		
		if not mouseEvent.shiftKey then
			local bone = secondBone
			local center = LM.Vector2:new_local()
			center:Set(0, 0)
			skel:UpdateBoneMatrix()
			bone.fMovedMatrix:Transform(center)
			
			local mousePos = mouseEvent.vec
			
			local angle = self.startAngle
			local v1 = self.lastVec - center
			local v2 = mousePos - center
			v2:Rotate(-math.atan2(v1.y, v1.x))
			angle = angle + math.atan2(v2.y, v2.x)
			self.startAngle = angle
			self.lastVec:Set(mousePos)
			local angleSign = 1.0
			if (not bone.fFixedAngle) then
				angleSign = bone:ParentalFlipFactor()
			end

			local newAgle = (bone.fTempAngle + (angle * angleSign)) - self.secondBoneAngleDelta
			
			if not bone.fFixedAngle then
				if bone.fConstraints then
					local min = bone.fAnimAngle:GetValue(0) - self.secondBoneAngleDelta
					local max = min + bone.fMaxConstraint
					min = min + bone.fMinConstraint
					newAgle = LM.Clamp(newAgle, min, max)
				end
			end
			if not self:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
				bone.fAnimAngle:SetValue(moho.layerFrame, newAgle)
				if self.bakeAdjacentFrames and not self.boneBakedA then
					self:BakeFrames(moho, secondBone, nil, true, false, false)
					self.boneBakedA = true
				end
			end	
		else
			local bone = secondBone
			local newAngle = bone.fTempAngle - self.secondBoneAngleDelta
			if not self:IsEqual(newAngle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
				bone.fAnimAngle:SetValue(moho.layerFrame, newAngle)
				if self.bakeAdjacentFrames and not self.boneBakedA then
					self:BakeFrames(moho, secondBone, nil, true, false, false)
					self.boneBakedA = true
				end
			end	
		end
	end
	
	local angleSign = 1
	if (secondBone.fFlipH.value and not secondBone.fFlipV.value) or (not secondBone.fFlipH.value and secondBone.fFlipV.value) then
		angleSign = -1
	end
	
	if self.isChainTargeted then
		local targetBone = skel:Bone(self.secondTarget)
		local newTargetPos = targetBone.fTempPos - (mouseEvent.startVec - mouseEvent.vec)
		targetBone.fAnimPos:SetValue(moho.layerFrame, newTargetPos)
		self.isTargetMoved = true
		if self.bakeAdjacentFrames then
			if not self.isTargetBonePosPBaked then
				if moho.layerFrame - self.interval > 0 then
					targetBone.fAnimPos:SetValue(moho.layerFrame - self.interval, self.targetBonePosP)
				end
				self.isTargetBonePosPBaked = true
			end
			
			if not self.isTargetBonePosNBaked then
				if moho.layerFrame + self.interval > 0 then
					targetBone.fAnimPos:SetValue(moho.layerFrame + self.interval, self.targetBonePosN)
				end
				self.isTargetBonePosNBaked = true
			end
		end	
	end
	
	if mouseEvent.altKey then
		moho.layer:UpdateCurFrame()
		if self.bakeAdjacentFrames and not self.isChildBonesBaked then
			for i, q in ipairs(self.childBones) do
				local bone = skel:Bone(q)
				if moho.layerFrame - self.interval > 0 then
					bone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.childBonesAngelP[i])
				end
				if moho.layerFrame + self.interval > 0 then
					bone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.childBonesAngelN[i])
				end
			end
			self.isChildBonesBaked = true
		end

		local angleDelta = secondBone.fAngle - secondBone.fTempAngle
		
		for i, q in ipairs(self.childBones) do
			local bone = skel:Bone(q)
			bone.fAnimAngle:SetValue(moho.layerFrame, bone.fTempAngle - (angleDelta * angleSign))
		end
	else
		for i, q in ipairs(self.childBones) do
			local bone = skel:Bone(q)
			if not self:IsEqual(bone.fTempAngle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
				bone.fAnimAngle:SetValue(moho.layerFrame, bone.fTempAngle)
			end	
		end
	end
	
	moho.layer:UpdateCurFrame()
	mouseEvent.view:DrawMe()
end

function MR_PoseTool:OnMouseMovedM(moho, mouseEvent)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return
	end

	local riggingFrame = 0
	local bone = skel:Bone(self.selID)
	local secondBone = skel:Bone(self.selID)
	
	if self.bakeAdjacentFrames and not self.boneBakedA then
		self:BakeFrames(moho, secondBone, nil, true, false, false)
		self.boneBakedA = true
	end
	skel:UpdateBoneMatrix(self.selID)

	local tipVec = LM.Vector2:new_local()

	tipVec:Set(bone.fLength, 0)
	bone.fMovedMatrix:Transform(tipVec)
	tipVec = tipVec + (mouseEvent.vec - self.lastVec)
	
	local startBone = skel:Bone(self.parentBones[#self.parentBones])
	local center = LM.Vector2:new_local()
	center:Set(0, 0)
	skel:UpdateBoneMatrix()
	startBone.fMovedMatrix:Transform(center)

	local mousePos = mouseEvent.vec
	
	local angle = self.startAngle
	local v1 = self.lastVec - center
	local v2 = mousePos - center
	v2:Rotate(-math.atan2(v1.y, v1.x))
	angle = angle + math.atan2(v2.y, v2.x)
	self.startAngle = angle
	self.lastVec:Set(mousePos)
	local angleSign = 1.0
	if (not startBone.fFixedAngle) then
		angleSign = startBone:ParentalFlipFactor()
	end

	local newAgle = (startBone.fTempAngle + (angle * angleSign))
	if mouseEvent.shiftKey then
		if self.bakeAdjacentFrames and not self.boneBakedS then
			self:BakeFrames(moho, secondBone, nil, false, false, true)
			for i, q in ipairs(self.parentBones) do
				local bone = skel:Bone(q)
				if moho.layerFrame - self.interval > 0 then
					bone.fAnimScale:SetValue(moho.layerFrame - self.interval, self.parentBonesScaleP[i])
				end
				if moho.layerFrame + self.interval > 0 then
					bone.fAnimScale:SetValue(moho.layerFrame + self.interval, self.parentBonesScaleN[i])
				end
			end	
			self.boneBakedS = true
		end
	
		if self.bakeAdjacentFrames and not self.boneBakedS then
			self:BakeFrames(moho, secondBone, nil, false, false, true)
			self.boneBakedS = true
		end
		
		local newStartBoneDist = self:GetDistance(self.startBonePos, mouseEvent.vec)
		local startBoneDistDelta = newStartBoneDist / self.startBoneDist
		bone.fAnimScale:SetValue(moho.layerFrame, bone.fTempScale * startBoneDistDelta)
		
		if not startBone.fFixedAngle then
			if startBone.fConstraints then
				local min = startBone.fAnimAngle:GetValue(0) - self.startBoneAngleDelta
				local max = min + startBone.fMaxConstraint
				min = min + startBone.fMinConstraint
				newAgle = LM.Clamp(newAgle, min, max)
			end
		end

		for i, q in ipairs(self.parentBones) do
			local parentBone = skel:Bone(q)
			parentBone.fAnimScale:SetValue(moho.layerFrame, parentBone.fTempScale * startBoneDistDelta)
			if not self:IsEqual(parentBone.fTempAngle, parentBone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
				parentBone.fAnimAngle:SetValue(moho.layerFrame, parentBone.fTempAngle)
			end	
		end	
		if not self:IsEqual(bone.fTempAngle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
			bone.fAnimAngle:SetValue(moho.layerFrame, bone.fTempAngle)
		end	
		startBone.fAnimAngle:SetValue(moho.layerFrame, newAgle)
	else
		skel:IKAngleSolver(self.selID, tipVec)
		local boneID = 1
		bone.fAnimAngle:SetValue(moho.layerFrame, bone.fAngle - (self.boneStartActualAngles[boneID] - self.boneStartAngles[boneID]))
		bone.fAnimAngle.value = bone.fAngle
		boneID = boneID + 1
		while bone.fParent >= 0 do
			if (self:CountBoneChildren(skel, bone.fParent, true) > 1) then
				break
			end
			local parentBone = skel:Bone(bone.fParent)
			if self.mohoVersion >= 14 then
				if (parentBone.fAngleControlParent >= 0 or
					parentBone.fPosControlParent >= 0 or
					parentBone.fScaleControlParent >= 0 or
					parentBone:AreDynamicsActive() or
					parentBone.fFixedAngle or
					parentBone.fIgnoredByIK) then
					break
				end
			else
				if (parentBone.fAngleControlParent >= 0 or
					parentBone.fPosControlParent >= 0 or
					parentBone.fScaleControlParent >= 0 or
					parentBone.fBoneDynamics.value or
					parentBone.fFixedAngle or
					parentBone.fIgnoredByIK) then
					break
				end
			end	

			bone = skel:Bone(bone.fParent)
			bone.fAnimAngle:SetValue(moho.layerFrame, bone.fAngle - (self.boneStartActualAngles[boneID] - self.boneStartAngles[boneID]))
			bone.fAnimAngle.value = bone.fAngle
			boneID = boneID + 1
		end
	end

	if #self.parentBones == 1 then
		local firstBone = skel:Bone(self.parentBones[1])
		if mouseEvent.altKey then
			moho.layer:UpdateCurFrame()
			local angleSign = 1
			local angleSignS = 1
			if (secondBone.fFlipH.value and not secondBone.fFlipV.value) or (not secondBone.fFlipH.value and secondBone.fFlipV.value) then
				angleSignS = -1
			end
			local angleSignF = 1
			if (firstBone.fFlipH.value and not firstBone.fFlipV.value) or (not firstBone.fFlipH.value and firstBone.fFlipV.value) then
				angleSignF = -1
			end
			
			local angleDelta = 0
			if angleSignF == 1 and angleSignS == -1 then
				angleSign = -1
				angleDelta = (firstBone.fAngle - firstBone.fTempAngle) + (secondBone.fAngle - secondBone.fTempAngle)
			elseif angleSignF == 1 and angleSignS == 1 then
				angleDelta = (firstBone.fAngle - firstBone.fTempAngle) + (secondBone.fAngle - secondBone.fTempAngle)	
			elseif angleSignF == -1 and angleSignS == -1 then
				angleDelta = (firstBone.fAngle - firstBone.fTempAngle) + ((secondBone.fAngle - secondBone.fTempAngle) * angleSignF)
			elseif angleSignF == -1 and angleSignS == 1 then
				angleSign = -1
				angleDelta = (firstBone.fAngle - firstBone.fTempAngle) + ((secondBone.fAngle - secondBone.fTempAngle) * angleSignF)
			end
		
			moho.layer:UpdateCurFrame()

			if not self.isChildBonesBaked and self.bakeAdjacentFrames then
				for i, q in ipairs(self.childBones) do
					local bone = skel:Bone(q)
					if not self.isChildBonesBaked then
						if moho.layerFrame - self.interval > 0 then
							bone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.childBonesAngelP[i])
						end
					end
					if not self.isChildBonesBaked then
						if moho.layerFrame + self.interval > 0 then
							bone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.childBonesAngelN[i])
						end
					end
				end
				self.isChildBonesBaked = true
			end	
			for i, q in ipairs(self.childBones) do
				local bone = skel:Bone(q)
				local newAngle = bone.fTempAngle - (angleDelta * angleSign)
				bone.fAnimAngle:SetValue(moho.layerFrame, newAngle)
			end
		else
			for i, q in ipairs(self.childBones) do
				local firstBone = skel:Bone(q)
				if not self:IsEqual(firstBone.fTempAngle, firstBone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
					firstBone.fAnimAngle:SetValue(moho.layerFrame, firstBone.fTempAngle)
				end	
			end
		end
	end
	
	if self.bakeAdjacentFrames and not self.isParentBonesBaked then
		for i, q in ipairs(self.parentBones) do
			local bone = skel:Bone(q)
			if moho.layerFrame - self.interval > 0 then
				bone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.parentBonesAngleP[i])
			end
			if moho.layerFrame + self.interval > 0 then
				bone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.parentBonesAngleN[i])
			end
		end	
		self.isParentBonesBaked = true
	end
	
	if self.isChainTargeted then
		local targetBone = skel:Bone(self.secondTarget)
		local newTargetPos = targetBone.fTempPos - (mouseEvent.startVec - mouseEvent.vec)
		targetBone.fAnimPos:SetValue(moho.layerFrame, newTargetPos)
		self.isTargetMoved = true
		if self.bakeAdjacentFrames then
			if not self.isTargetBonePosPBaked then
				if moho.layerFrame - self.interval > 0 then
					targetBone.fAnimPos:SetValue(moho.layerFrame - self.interval, self.targetBonePosP)
				end
				self.isTargetBonePosPBaked = true
			end
			
			if not self.isTargetBonePosNBaked then
				if moho.layerFrame + self.interval > 0 then
					targetBone.fAnimPos:SetValue(moho.layerFrame + self.interval, self.targetBonePosN)
				end
				self.isTargetBonePosNBaked = true
			end
		end	
	end
	
	skel:UpdateBoneMatrix()
	moho.layer:UpdateCurFrame()
	mouseEvent.view:DrawMe()
	self.lastVec:Set(mouseEvent.vec)
end	

function MR_PoseTool:OnMouseUp(moho, mouseEvent)
	local frame = moho.frame
	if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0) then
		return
	end
	
	self.dragging = false
	local skel = moho:Skeleton()
	if skel == nil or frame == 0 then
		return
	end

	if self.isActive == false then
		return
	end
	
	local bone
	if self.firstBoneID > -1 then
		bone = skel:Bone(self.firstBoneID)
	end	
	local secondBoneID = skel:Bone(self.secondBoneID)
	
	if self.firstBoneParentID > -1 then
		local firstBoneParent = skel:Bone(self.firstBoneParentID)
		if firstBoneParent then
			firstBoneParent.fIgnoredByIK = self.firstBoneParentIBIK
		end	
	end
	
	if self.keepSelection and self.selBones > 0 then
		skel:SelectNone()
		for i, boneID in ipairs(self.selectedBonesList) do
			local bone = skel:Bone(boneID)
			bone.fSelected = true
		end
	end
	
	moho.layer:UpdateCurFrame()
	moho:UpdateUI()
	mouseEvent.view:DrawMe()
	moho:UpdateSelectedChannels()
end

function MR_PoseTool:DrawMe(moho, view)
	local skel = moho:Skeleton()
	if (skel == nil) or moho.frame == 0 then
		return
	end

	local markerR = self.markerR
	
	if self.additionHandles then
		markerR = self.markerR2
	end
	local selBones = moho:CountSelectedBones()
	local v = LM.Vector2:new_local()
	local g = view:Graphics()
	local layerMatrix = LM.Matrix:new_local()
	local vc1 = LM.ColorVector:new_local()
	local vc2 = LM.ColorVector:new_local()
	local interp = MOHO.InterpSetting:new_local()
	local center = LM.Vector2:new_local()
	local tip = LM.Vector2:new_local()
	local offset = LM.Vector2:new_local()
	local boneCenterPos = LM.Vector2:new_local()
	local boneHandlePos = LM.Vector2:new_local()
	local angle = 0
	local newAngle = 0
	local offsetAngle = 0
	local alignHandlesAdaptation = false
	local handlesZoomAdaptationVal = 1
	local handlesAdaptation = false
	
	vc1:Set(MOHO.MohoGlobals.SelCol)
	vc2:Set(MOHO.MohoGlobals.BackCol)
	
	local whiteColor = LM.rgb_color:new_local()
	whiteColor.r = 255
	whiteColor.g = 255
	whiteColor.b = 255
	whiteColor.a = 255 * self.handleFillOpacity
	
	vc1 = (vc1 + vc2) / 2
	local fillCol = vc1:AsColorStruct()
	fillCol.a = 255 * self.handleFillOpacity
	
	local colorHighlightBone = LM.rgb_color:new_local()
	local colorTranslateStroke = LM.rgb_color:new_local()
	local colorTranslateFill = LM.rgb_color:new_local()
	local colorTranslateFillHL = LM.rgb_color:new_local()
	local colorScaleStroke = LM.rgb_color:new_local()
	local colorScaleFill = LM.rgb_color:new_local()
	local colorScaleFillHL = LM.rgb_color:new_local()
	local colorMoveJointStroke = LM.rgb_color:new_local()
	local colorMoveJointFill = LM.rgb_color:new_local()
	local colorMoveJointFillHL = LM.rgb_color:new_local()
	local colorManipulateStroke = LM.rgb_color:new_local()
	local colorManipulateFill = LM.rgb_color:new_local()
	local colorManipulateFillHL = LM.rgb_color:new_local()
	
	if self.useCustomColors then
		colorTranslateStroke.r = self.colorStrokeTranslateHandleR
		colorTranslateStroke.g = self.colorStrokeTranslateHandleG
		colorTranslateStroke.b = self.colorStrokeTranslateHandleB
		colorTranslateStroke.a = 255 * self.handleStrokeOpacity
		
		colorTranslateFill.r = self.colorFillTranslateHandleR
		colorTranslateFill.g = self.colorFillTranslateHandleG
		colorTranslateFill.b = self.colorFillTranslateHandleB
		colorTranslateFill.a = 255 * self.handleFillOpacity
		
		colorTranslateFillHL.r = ((colorTranslateFill.r * 3) + whiteColor.r) / 4
		colorTranslateFillHL.g = ((colorTranslateFill.g * 3) + whiteColor.g) / 4
		colorTranslateFillHL.b = ((colorTranslateFill.b * 3) + whiteColor.b) / 4
		colorTranslateFillHL.a = 255 * self.handleFillOpacity
		
		colorScaleStroke.r = self.colorStrokeScaleHandleR
		colorScaleStroke.g = self.colorStrokeScaleHandleG
		colorScaleStroke.b = self.colorStrokeScaleHandleB
		colorScaleStroke.a = 255 * self.handleStrokeOpacity

		colorScaleFill.r = self.colorFillScaleHandleR
		colorScaleFill.g = self.colorFillScaleHandleG
		colorScaleFill.b = self.colorFillScaleHandleB
		colorScaleFill.a = 255 * self.handleFillOpacity
		
		colorScaleFillHL.r = ((colorScaleFill.r * 3) + whiteColor.r) / 4
		colorScaleFillHL.g = ((colorScaleFill.g * 3) + whiteColor.g) / 4
		colorScaleFillHL.b = ((colorScaleFill.b * 3) + whiteColor.b) / 4
		colorScaleFillHL.a = 255 * self.handleFillOpacity

		colorMoveJointStroke.r = self.colorStrokeMoveJointHandleR
		colorMoveJointStroke.g = self.colorStrokeMoveJointHandleG
		colorMoveJointStroke.b = self.colorStrokeMoveJointHandleB
		colorMoveJointStroke.a = 255 * self.handleStrokeOpacity

		colorMoveJointFill.r = self.colorFillMoveJointHandleR
		colorMoveJointFill.g = self.colorFillMoveJointHandleG
		colorMoveJointFill.b = self.colorFillMoveJointHandleB
		colorMoveJointFill.a = 255 * self.handleFillOpacity
		
		colorMoveJointFillHL.r = ((colorMoveJointFill.r * 3) + whiteColor.r) / 4
		colorMoveJointFillHL.g = ((colorMoveJointFill.g * 3) + whiteColor.g) / 4
		colorMoveJointFillHL.b = ((colorMoveJointFill.b * 3) + whiteColor.b) / 4
		colorMoveJointFillHL.a = 255 * self.handleFillOpacity

		colorManipulateStroke.r = self.colorStrokeManipulateHandleR
		colorManipulateStroke.g = self.colorStrokeManipulateHandleG
		colorManipulateStroke.b = self.colorStrokeManipulateHandleB
		colorManipulateStroke.a = 255 * self.handleStrokeOpacity

		colorManipulateFill.r = self.colorFillManipulateHandleR
		colorManipulateFill.g = self.colorFillManipulateHandleG
		colorManipulateFill.b = self.colorFillManipulateHandleB
		colorManipulateFill.a = 255 * self.handleFillOpacity
		
		colorManipulateFillHL.r = ((colorManipulateFill.r * 3) + whiteColor.r) / 4
		colorManipulateFillHL.g = ((colorManipulateFill.g * 3) + whiteColor.g) / 4
		colorManipulateFillHL.b = ((colorManipulateFill.b * 3) + whiteColor.b) / 4
		colorManipulateFillHL.a = 255 * self.handleFillOpacity
	else
		colorTranslateStroke.r = MOHO.MohoGlobals.SelCol.r
		colorTranslateStroke.g = MOHO.MohoGlobals.SelCol.g
		colorTranslateStroke.b = MOHO.MohoGlobals.SelCol.b
		colorTranslateStroke.a = 255 * self.handleStrokeOpacity
		
		colorTranslateFill.r = fillCol.r
		colorTranslateFill.g = fillCol.g
		colorTranslateFill.b = fillCol.b
		colorTranslateFill.a = 255 * self.handleFillOpacity
		
		colorTranslateFillHL.r = ((colorTranslateFill.r * 3) + whiteColor.r) / 4
		colorTranslateFillHL.g = ((colorTranslateFill.g * 3) + whiteColor.g) / 4
		colorTranslateFillHL.b = ((colorTranslateFill.b * 3) + whiteColor.b) / 4
		colorTranslateFillHL.a = 255 * self.handleFillOpacity
		
		colorScaleStroke.r = MOHO.MohoGlobals.SelCol.r
		colorScaleStroke.g = MOHO.MohoGlobals.SelCol.g
		colorScaleStroke.b = MOHO.MohoGlobals.SelCol.b
		colorScaleStroke.a = 255 * self.handleStrokeOpacity

		colorScaleFill.r = fillCol.r
		colorScaleFill.g = fillCol.g
		colorScaleFill.b = fillCol.b
		colorScaleFill.a = 255 * self.handleFillOpacity
		
		colorScaleFillHL.r = ((colorScaleFill.r * 3) + whiteColor.r) / 4
		colorScaleFillHL.g = ((colorScaleFill.g * 3) + whiteColor.g) / 4
		colorScaleFillHL.b = ((colorScaleFill.b * 3) + whiteColor.b) / 4
		colorScaleFillHL.a = 255 * self.handleFillOpacity

		colorMoveJointFill.r = 255
		colorMoveJointFill.g = 189
		colorMoveJointFill.b = 46
		colorMoveJointFill.a = 255 * self.handleFillOpacity

		colorMoveJointStroke.r = (colorMoveJointFill.r + (MOHO.MohoGlobals.SelCol.r * 2)) / 3
		colorMoveJointStroke.g = (colorMoveJointFill.g + (MOHO.MohoGlobals.SelCol.g * 2)) / 3
		colorMoveJointStroke.b = (colorMoveJointFill.b + (MOHO.MohoGlobals.SelCol.b * 2)) / 3
		colorMoveJointStroke.a = 255 * self.handleStrokeOpacity
		
		colorMoveJointFillHL.r = ((colorMoveJointFill.r * 3) + whiteColor.r) / 4
		colorMoveJointFillHL.g = ((colorMoveJointFill.g * 3) + whiteColor.g) / 4
		colorMoveJointFillHL.b = ((colorMoveJointFill.b * 3) + whiteColor.b) / 4
		colorMoveJointFillHL.a = 255 * self.handleFillOpacity

		colorManipulateFill.r = 255
		colorManipulateFill.g = 189
		colorManipulateFill.b = 46
		colorManipulateFill.a = 255 * self.handleFillOpacity

		colorManipulateStroke.r = (colorManipulateFill.r + (MOHO.MohoGlobals.SelCol.r * 2)) / 3
		colorManipulateStroke.g = (colorManipulateFill.g + (MOHO.MohoGlobals.SelCol.g * 2)) / 3
		colorManipulateStroke.b = (colorManipulateFill.b + (MOHO.MohoGlobals.SelCol.b * 2)) / 3
		colorManipulateStroke.a = 255 * self.handleStrokeOpacity
		
		colorManipulateFillHL.r = ((colorManipulateFill.r * 3) + whiteColor.r) / 4
		colorManipulateFillHL.g = ((colorManipulateFill.g * 3) + whiteColor.g) / 4
		colorManipulateFillHL.b = ((colorManipulateFill.b * 3) + whiteColor.b) / 4
		colorManipulateFillHL.a = 255 * self.handleFillOpacity
	end
	
	if self.useHighlightCustomColor then
		colorHighlightBone.r = self.highlightCustomColorR
		colorHighlightBone.g = self.highlightCustomColorG
		colorHighlightBone.b = self.highlightCustomColorB
		colorHighlightBone.a = 255 * self.highlightOpacity
	else
		colorHighlightBone.r = MOHO.MohoGlobals.SelCol.r
		colorHighlightBone.g = MOHO.MohoGlobals.SelCol.g
		colorHighlightBone.b = MOHO.MohoGlobals.SelCol.b
		colorHighlightBone.a = 255 * self.highlightOpacity
	end
	
	local hlDelta = 0
	
	local handlesDistance = self.handlesDistance
	if self.alignHandlesAlongBone then
		handlesDistance = 1
	end
	
	moho.layer:GetFullTransform(moho.frame, layerMatrix, moho.document)
	g:Push()
	g:ApplyMatrix(layerMatrix)
	local height = g:Height() / moho.document:Height()
	height = g:Height() / self.height
	local markerMultiplier = 0.002
	local additionMarker1 = self.additionHandles
	local currentScale = g:CurrentScale(false)
	g:SetSmoothing(true)
	g:SetBezierTolerance(2)

	if self.mousePickedID > -1 and not (self.dragging or moho:IsPlaying()) then
		local bone = skel:Bone(self.mousePickedID)
		if bone ~= nil then
			local isPin = bone:IsZeroLength()
			if not bone.fHidden and bone:IsGroupVisible() then
				v:Set(bone.fLength - bone.fLength * self.handlesDist, 0)
				bone.fMovedMatrix:Transform(v)

				if self.alignHandlesAlongBone then
					v:Set(bone.fLength - bone.fLength, 0)
					bone.fMovedMatrix:Transform(v)
				
					boneCenterPos:Set(bone.fLength - bone.fLength / 2, 0)
					bone.fMovedMatrix:Transform(boneCenterPos)
					center:Set(0, 0)
					tip:Set(1, 0)
					bone.fMovedMatrix:Transform(center)
					bone.fMovedMatrix:Transform(tip)
					
					offset:Set(v.x, v.y)
					angle = math.atan2(tip.y - center.y, tip.x - center.x)
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					angle = offsetAngle + (angle - offsetAngle)
					v:Set(self:RotateVector2(moho, offset, v, angle))
					
					offset:Set(v.x - ((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height), v.y)
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					newAngle = offsetAngle + (angle - offsetAngle)
					boneHandlePos:Set(self:RotateVector2(moho, offset, v, newAngle))
					
					local layerMatrixNoCam = LM.Matrix:new_local()
					moho.layer:GetFullTransform(moho.frame, layerMatrixNoCam, nil)
					layerMatrixNoCam:Transform(boneHandlePos)
					
					local globalBoneCenterPos = LM.Vector2:new_local()
					globalBoneCenterPos:Set(boneCenterPos)
					layerMatrixNoCam:Transform(globalBoneCenterPos)
					
					if self:GetDistance(globalBoneCenterPos, boneHandlePos) * currentScale * height < 0.065 then
						alignHandlesAdaptation = true
					end
					
					v:Set(bone.fLength * self.handlesDist, 0)
					bone.fMovedMatrix:Transform(v)
					
					local distanceValue = self:GetDistance(center, v) * currentScale * height
					
					if distanceValue > self.handlesDistanceTreshhold then
						handlesZoomAdaptationVal = distanceValue / self.handlesDistanceTreshhold
					end
				else
					v:Set(bone.fLength * self.handlesDist, 0)
					bone.fMovedMatrix:Transform(v)
					center:Set(0, 0)
					bone.fMovedMatrix:Transform(center)
					
					local distanceValue = self:GetDistance(center, v) * currentScale * height
					
					if distanceValue > self.handlesDistanceTreshhold then
						handlesZoomAdaptationVal = distanceValue / self.handlesDistanceTreshhold
					end
				end
		
				v:Set(bone.fLength - bone.fLength * (self.handlesDist / handlesZoomAdaptationVal), 0)
				bone.fMovedMatrix:Transform(v)

				if selBones ~= 1 and self.highlightBones then
					center:Set(0, 0)
					tip:Set(bone.fLength, 0)
					bone.fMovedMatrix:Transform(center)
					bone.fMovedMatrix:Transform(tip)
					g:SetPenWidth(self.highlightWidth)
					g:SetColor(colorHighlightBone)
					g:DrawLine(center.x, center.y, tip.x, tip.y)
					g:SetPenWidth(1)
				end
				
				if additionMarker1 then
					center:Set(0, 0)
					tip:Set(1, 0)
					bone.fMovedMatrix:Transform(center)
					bone.fMovedMatrix:Transform(tip)
					
					if self.alignHandlesAlongBone then
						offset:Set(v.x, v.y)
						if alignHandlesAdaptation then
							offset:Set(boneCenterPos.x + (((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height) * 1.5), boneCenterPos.y)
						end
					else
						offset:Set(v.x, v.y - ((markerR * markerMultiplier * handlesDistance) / currentScale / height))
					end	
					angle = math.atan2(tip.y - center.y, tip.x - center.x)
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					angle = offsetAngle + (angle - offsetAngle)
					if alignHandlesAdaptation then
						v:Set(self:RotateVector2(moho, offset, boneCenterPos, angle))
					else
						v:Set(self:RotateVector2(moho, offset, v, angle))
					end
				end
				if self.drawMode == 2 then
					if isPin then
						g:SetColor(colorScaleFillHL)
					else
						g:SetColor(colorScaleFillHL)
					end	
					markerR = self.markerR + hlDelta
				else
					if isPin then
						g:SetColor(colorScaleFill)
					else
						g:SetColor(colorScaleFill)
					end	
					markerR = self.markerR
				end
				
				if bone.fLength == 0 and self.keepHandles then
					markerR = markerR * 3
				end
				if (self.ignoreZeroScaledBones and self:Round(bone.fAnimScale:GetValue(0), 1) == 1) or not self.ignoreZeroScaledBones then
					g:FillCirclePixelRadius(v, markerR)
					g:SetColor(colorScaleStroke)
					g:FrameCirclePixelRadius(v, markerR)
				end
				
				markerR = self.markerR
				if additionMarker1 then
					if self.alignHandlesAlongBone then
						offset:Set(v.x - ((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height), v.y)
					else
						v:Set(bone.fLength - (bone.fLength * (self.handlesDist / handlesZoomAdaptationVal)), 0)
						bone.fMovedMatrix:Transform(v)
						offset:Set(v.x, v.y + ((markerR * markerMultiplier * handlesDistance) / currentScale / height))
					end	
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					newAngle = offsetAngle + (angle - offsetAngle)
					v:Set(self:RotateVector2(moho, offset, v, newAngle))
					
					if self.drawMode == 4 then
						g:SetColor(colorManipulateFillHL)
						markerR = self.markerR + hlDelta
					else
						g:SetColor(colorManipulateFill)
						markerR = self.markerR
					end
					g:FillCirclePixelRadius(v, markerR)
					g:SetColor(colorManipulateStroke)
					g:FrameCirclePixelRadius(v, markerR)
					markerR = self.markerR
				end	
				
				v:Set(bone.fLength * (self.handlesDist / handlesZoomAdaptationVal), 0)
				bone.fMovedMatrix:Transform(v)
				
				if additionMarker1 then
					if self.alignHandlesAlongBone then
						offset:Set(v.x, v.y)
						if alignHandlesAdaptation then
							offset:Set(boneCenterPos.x - (((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height)* 1.5), boneCenterPos.y)
						end
					else
						offset:Set(v.x, v.y - ((markerR * markerMultiplier * handlesDistance) / currentScale / height))
					end
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					newAngle = offsetAngle + (angle - offsetAngle)
					
					if alignHandlesAdaptation then
						v:Set(self:RotateVector2(moho, offset, boneCenterPos, newAngle))
					else
						v:Set(self:RotateVector2(moho, offset, v, newAngle))
					end
				end

				if self.drawMode == 0 or self.drawMode == 5 then
					g:SetColor(colorTranslateFillHL)
					markerR = self.markerR + hlDelta
				else
					g:SetColor(colorTranslateFill)
					markerR = self.markerR
				end
				
				g:FillCirclePixelRadius(v, markerR)
				g:SetColor(colorTranslateStroke)
				g:FrameCirclePixelRadius(v, markerR)
				markerR = self.markerR
				
				if not isPin then
					if additionMarker1 then
						if self.alignHandlesAlongBone then
							offset:Set(v.x  + ((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height), v.y)
						else	
							v:Set(bone.fLength * (self.handlesDist / handlesZoomAdaptationVal), 0)
							bone.fMovedMatrix:Transform(v)
							offset:Set(v.x, v.y + ((markerR * markerMultiplier * handlesDistance) / currentScale / height))
						end
						offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
						newAngle = offsetAngle + (angle - offsetAngle)
						v:Set(self:RotateVector2(moho, offset, v, newAngle))
						
						if self.drawMode == 3 then
							g:SetColor(colorMoveJointFillHL)
							markerR = self.markerR + hlDelta
						else
							g:SetColor(colorMoveJointFill)
							markerR = self.markerR
						end
						g:FillCirclePixelRadius(v, markerR)
						g:SetColor(colorMoveJointStroke)
						g:FrameCirclePixelRadius(v, markerR)
						markerR = self.markerR
					end	
				end
			end
		end
	end
	if selBones == 1 then
		local bone = skel:Bone(skel:SelectedBoneID())
		if bone ~= nil then
			if (bone.fSelected and self.showPath and bone.fParent < 0) then
				-- draw path
				local channelPos = bone.fAnimPos
				local startFrame = channelPos:GetKeyWhen(0)
				local channelDuration = channelPos:Duration()
				local endFrame = channelDuration
				local totalTimingOffset = moho.layer:TotalTimingOffset()

				if (startFrame - totalTimingOffset < 0) then
					startFrame = totalTimingOffset
				end
				channelPos:GetKeyInterp(endFrame, interp)
				if (interp:IsAdditiveCycle()) then
					endFrame = moho.document:EndFrame() + totalTimingOffset
				end

				if (endFrame > startFrame) then
					local vec = LM.Vector2:new_local()
					local oldVec = LM.Vector2:new_local()
					if self.range then
						startFrame = LM.Clamp(moho.layerFrame - self.rangeFrames, 1, channelDuration)
						endFrame = LM.Clamp(moho.layerFrame + self.rangeFrames, 1, channelDuration)
					end
					g:SetColor(102, 152, 203)
					for frame = startFrame, endFrame do
						vec = channelPos:GetValue(frame)
						if (frame > startFrame) then
							g:DrawLine(oldVec.x, oldVec.y, vec.x, vec.y)
						end
						if (channelPos:HasKey(frame)) then
							g:DrawFatMarker(vec.x, vec.y, 5)
						else
							g:DrawMarker(vec.x, vec.y)
						end
						oldVec:Set(vec)
					end
				end
			end
		end	
	end	
	g:Pop()
end

function MR_PoseTool:Round(x, n)
	n = 10 ^ (n or 3)
	x = x * n
	if x >= 0 then x = math.floor(x + 0.5) else x = math.ceil(x - 0.5) end
	return x / n
end

function MR_PoseTool:GetDistance(Pos1, Pos2)
	return math.sqrt((Pos2.x-Pos1.x)^2+(Pos2.y-Pos1.y)^2)
end

function MR_PoseTool: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

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

MR_PoseTool.KEEP_SELECTION = MOHO.MSG_BASE
MR_PoseTool.LOCK_HANDLES = MOHO.MSG_BASE + 1
MR_PoseTool.BAKE_ADJACENT_FRAMES = MOHO.MSG_BASE + 2
MR_PoseTool.INTERVAL_1 = MOHO.MSG_BASE + 3
MR_PoseTool.INTERVAL_2 = MOHO.MSG_BASE + 4
MR_PoseTool.INTERVAL_3 = MOHO.MSG_BASE + 5
MR_PoseTool.INTERVAL_4 = MOHO.MSG_BASE + 6
MR_PoseTool.SHOW_PATH = MOHO.MSG_BASE + 7
MR_PoseTool.RANGE = MOHO.MSG_BASE + 8
MR_PoseTool.RANGE_FRAMES = MOHO.MSG_BASE + 9
MR_PoseTool.FLIP_H = MOHO.MSG_BASE + 10
MR_PoseTool.FLIP_V = MOHO.MSG_BASE + 11

function MR_PoseTool:DoLayout(moho, layout)
	self.dlog = MR_PoseToolSettingsDialog: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)
	
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	self.keepSelectionCheckbox = LM.GUI.CheckBox(self:Localize('Keep selection'), self.KEEP_SELECTION)
    layout:AddChild(self.keepSelectionCheckbox, LM.GUI.ALIGN_LEFT, 0)
	
	self.lockHandlesCheckbox = LM.GUI.CheckBox(self:Localize('Lock handles'), self.LOCK_HANDLES)
    layout:AddChild(self.lockHandlesCheckbox, LM.GUI.ALIGN_LEFT, 0)

	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	self.bakeAdjacentFramesCheckbox = LM.GUI.CheckBox(self:Localize('Bake Adjacent Frames'), self.BAKE_ADJACENT_FRAMES)
    layout:AddChild(self.bakeAdjacentFramesCheckbox, 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.showPathCheckbox = LM.GUI.CheckBox(self:Localize('Show path'), self.SHOW_PATH)
    layout:AddChild(self.showPathCheckbox, LM.GUI.ALIGN_LEFT, 0)
	
	self.rangeCheckbox = LM.GUI.CheckBox(self:Localize('Range'), self.RANGE)
    layout:AddChild(self.rangeCheckbox, LM.GUI.ALIGN_LEFT, 0)
	
	self.rangeFramesInput = LM.GUI.TextControl(0, '1000', self.RANGE_FRAMES, LM.GUI.FIELD_INT, self:Localize('Range frames:'))
    layout:AddChild(self.rangeFramesInput, LM.GUI.ALIGN_LEFT, 0)
	
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	layout:AddChild(LM.GUI.ImageButton("ScriptResources/flip_bone_h", self:Localize('End flip'), false, self.FLIP_H, true))
	layout:AddChild(LM.GUI.ImageButton("ScriptResources/flip_bone_v", self:Localize('Side flip'), false, self.FLIP_V, true))
	
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
	
	layout:AddChild(LM.GUI.StaticText('v'..MR_PoseTool:Version()))
end

function MR_PoseTool:UpdateWidgets(moho)
	if self.mainCursor == nil then
		self.mainCursor = LM.GUI.Cursor(moho:UserContentDir()..'/Scripts/Tool/mr_pose_tool_cursor', 1, 1)
	end	
	if self.mjCursor == nil then
		self.mjCursor = LM.GUI.Cursor(moho:UserContentDir()..'/Scripts/ScriptResources/mr_pose_tool/mr_mj_cursor', 1, 1)
	end	
	if self.mbCursor == nil then
		self.mbCursor = LM.GUI.Cursor(moho:UserContentDir()..'/Scripts/ScriptResources/mr_pose_tool/mr_mb_cursor', 1, 1)
	end	
	
	local frame = moho.frame
	
	if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0) then
		moho.view:SetCursor(MOHO.disabledCursor)
	else
		moho.view:SetCursor(self.mainCursor)
	end

	self.keepSelectionCheckbox:SetValue(self.keepSelection)
	self.lockHandlesCheckbox:SetValue(self.lockHandles)
	self.bakeAdjacentFramesCheckbox:SetValue(self.bakeAdjacentFrames)
	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:Enable(self.bakeAdjacentFrames)
	self.intervalPopup:Redraw()
	self.showPathCheckbox:SetValue(self.showPath)
	self.rangeCheckbox:SetValue(self.range)
	self.rangeFramesInput:SetValue(self.rangeFrames)
	self.rangeCheckbox:Enable(self.showPath)
	self.rangeFramesInput:Enable(self.range and self.showPath)
end

function MR_PoseTool:HandleMessage(moho, view, msg)
	if msg == self.KEEP_SELECTION then
        self.keepSelection = self.keepSelectionCheckbox:Value()
	elseif msg == self.LOCK_HANDLES then
        self.lockHandles = self.lockHandlesCheckbox:Value()
	elseif msg == self.BAKE_ADJACENT_FRAMES then
		self.bakeAdjacentFrames = self.bakeAdjacentFramesCheckbox:Value()
		self.intervalPopup:Enable(self.bakeAdjacentFrames)
	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
		self:UpdateWidgets(moho)
	elseif msg == self.SHOW_PATH then
        self.showPath = self.showPathCheckbox:Value()
		self.rangeCheckbox:Enable(self.showPath)
		self.rangeFramesInput:Enable(self.range and self.showPath)
	elseif msg == self.RANGE then
        self.range = self.rangeCheckbox:Value()	
		self.rangeCheckbox:Enable(self.showPath)
		self.rangeFramesInput:Enable(self.range and self.showPath)
	elseif msg == self.RANGE_FRAMES then
        self.rangeFrames = LM.Clamp(self.rangeFramesInput:Value(), 1, 1000)	
		self.rangeFramesInput:SetValue(self.rangeFrames)
	elseif (msg == self.FLIP_H) then
		self:FlipBones(moho, true)
	elseif (msg == self.FLIP_V) then
		self:FlipBones(moho, false)
	end	
end

function MR_PoseTool:IsEqual(a, b, epsilon)
    local absA = math.abs(a)
    local absB = math.abs(b)
    local diff = math.abs(a - b)

    if a == b then 
        return true 
    elseif diff < epsilon then 
        return true
    else 
        return false
    end
end

function MR_PoseTool:CheckBone(moho, id)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return false
	end
	if id < 0 or not id then
		return false
	end
	local secondBone = skel:Bone(id)
	if secondBone then
		if secondBone.fParent > -1 and not secondBone:IsZeroLength() and not secondBone.fFixedAngle then
			local firstBoneID = secondBone.fParent
			local firstBone = skel:Bone(firstBoneID)
			local firstBoneChilds = skel:CountBoneChildren(firstBoneID, true)
			local secondBonePos = LM.Vector2:new_local()
			secondBonePos:Set(secondBone.fAnimPos:GetValue(moho.layerFrame))
			if firstBone.fIgnoredByIK == false and secondBone.fIgnoredByIK == false and firstBoneChilds == 1 and self:Round(secondBone.fPos.y) == 0 
			and not self:IsEqual(secondBonePos.x, 0, 0.0001) and not firstBone:IsZeroLength() and not firstBone.fFixedAngle then
				return true
			end
		end
	end	
	return false
end

function MR_PoseTool:TestMousePoint(moho, mouseEvent, id)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return 1
	end

	local markerR = self.markerR
	if self.additionHandles then
		markerR = self.markerR2
	end
	
	local v = LM.Vector2:new_local()
	local pt = LM.Point:new_local()
	local m = LM.Matrix:new_local()
	local center = LM.Vector2:new_local()
	local tip = LM.Vector2:new_local()
	local offset = LM.Vector2:new_local()
	local boneCenterPos = LM.Vector2:new_local()
	local boneHandlePos = LM.Vector2:new_local()
	local localV = LM.Vector2:new_local()
	local angle = 0
	local newAngle = 0
	local offsetAngle = 0
	local alignHandlesAdaptation = false
	local handlesZoomAdaptationVal = 1
	
	moho.layer:GetFullTransform(moho.frame, m, moho.document)
	local g = mouseEvent.view:Graphics()
	g:Push()
	g:ApplyMatrix(m)
	local height = g:Height() / moho.document:Height()
	height = g:Height() / self.height
	local markerMultiplier = 0.002

	local additionMarker1 = self.additionHandles
	local currentScale = g:CurrentScale(false)
	g:Pop()
	
	self.keepHandles = mouseEvent.ctrlKey

	local handlesDistance = self.handlesDistance
	if self.alignHandlesAlongBone then
		handlesDistance = 1
	end

	if self.mousePickedID > -1 then
		local bone = skel:Bone(self.mousePickedID)
		if bone ~= nil then
			if not bone.fHidden and bone:IsGroupVisible() then
				v:Set(bone.fLength * self.handlesDist, 0)
				bone.fMovedMatrix:Transform(v)
				
				if self.alignHandlesAlongBone then
					v:Set(bone.fLength - bone.fLength, 0)
					bone.fMovedMatrix:Transform(v)
				
					boneCenterPos:Set(bone.fLength - bone.fLength / 2, 0)
					bone.fMovedMatrix:Transform(boneCenterPos)
					
					center:Set(0, 0)
					tip:Set(1, 0)
					bone.fMovedMatrix:Transform(center)
					bone.fMovedMatrix:Transform(tip)
					
					offset:Set(v.x, v.y)
					angle = math.atan2(tip.y - center.y, tip.x - center.x)
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					angle = offsetAngle + (angle - offsetAngle)
					v:Set(self:RotateVector2(moho, offset, v, angle))
					
					offset:Set(v.x - ((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height), v.y)
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					newAngle = offsetAngle + (angle - offsetAngle)
					boneHandlePos:Set(self:RotateVector2(moho, offset, v, newAngle))
					
					local layerMatrixNoCam = LM.Matrix:new_local()
					moho.layer:GetFullTransform(moho.frame, layerMatrixNoCam, nil)
					
					
					layerMatrixNoCam:Transform(boneHandlePos)
					
					local globalBoneCenterPos = LM.Vector2:new_local()
					globalBoneCenterPos:Set(boneCenterPos)
					layerMatrixNoCam:Transform(globalBoneCenterPos)
					
					if self:GetDistance(globalBoneCenterPos, boneHandlePos) * currentScale * height < 0.065 then
						alignHandlesAdaptation = true
					end
					
					v:Set(bone.fLength * self.handlesDist, 0)
					bone.fMovedMatrix:Transform(v)
					
					local distanceValue = self:GetDistance(center, v) * currentScale * height
					
					if distanceValue > self.handlesDistanceTreshhold then
						handlesZoomAdaptationVal = distanceValue / self.handlesDistanceTreshhold
					end
				else
					v:Set(bone.fLength * self.handlesDist, 0)
					bone.fMovedMatrix:Transform(v)
					center:Set(0, 0)
					bone.fMovedMatrix:Transform(center)
					local distanceValue = self:GetDistance(center, v) * currentScale * height
					
					if distanceValue > self.handlesDistanceTreshhold then
						handlesZoomAdaptationVal = distanceValue / self.handlesDistanceTreshhold
					end
				end
				
				v:Set(bone.fLength * (self.handlesDist / handlesZoomAdaptationVal), 0)
				bone.fMovedMatrix:Transform(v)
				
				if additionMarker1 then
					center:Set(0, 0)
					tip:Set(1, 0)
					bone.fMovedMatrix:Transform(center)
					bone.fMovedMatrix:Transform(tip)
					if self.alignHandlesAlongBone then
						offset:Set(v.x, v.y)
						if alignHandlesAdaptation then
							offset:Set(boneCenterPos.x - (((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height) * 1.5), boneCenterPos.y)
						end
					else
						offset:Set(v.x, v.y - ((markerR * markerMultiplier * handlesDistance) / currentScale / height))
					end
					angle = math.atan2(tip.y - center.y, tip.x - center.x)
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					newAngle = offsetAngle + (angle - offsetAngle)
					if alignHandlesAdaptation then
						v:Set(self:RotateVector2(moho, offset, boneCenterPos, newAngle))
					else
						v:Set(self:RotateVector2(moho, offset, v, newAngle))
					end
				end
				
				localV:Set(v)
				m:Transform(v)
				
				mouseEvent.view:Graphics():WorldToScreen(v, pt)
				if (math.abs(pt.x - mouseEvent.pt.x) < markerR and math.abs(pt.y - mouseEvent.pt.y) < markerR) then
					return 0
				end
				
				if additionMarker1 then	
					if self.alignHandlesAlongBone then
						v:Set(localV)
						offset:Set(v.x + ((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height), v.y)
					else
						v:Set(bone.fLength * (self.handlesDist / handlesZoomAdaptationVal), 0)
						bone.fMovedMatrix:Transform(v)
						offset:Set(v.x, v.y + ((markerR * markerMultiplier * handlesDistance) / currentScale / height))
					end
					angle = math.atan2(tip.y - center.y, tip.x - center.x)
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					newAngle = offsetAngle + (angle - offsetAngle)
					v:Set(self:RotateVector2(moho, offset, v, newAngle))
				
					local testPos = LM.Vector2:new_local()
					testPos:Set(v)
					local layerMatrixNoCam = LM.Matrix:new_local()
					moho.layer:GetFullTransform(moho.frame, layerMatrixNoCam, nil)
					layerMatrixNoCam:Transform(testPos)
					
					m:Transform(v)
					mouseEvent.view:Graphics():WorldToScreen(v, pt)
					if (math.abs(pt.x - mouseEvent.pt.x) < markerR and math.abs(pt.y - mouseEvent.pt.y) < markerR) then
						return 3
					end
				end
			end	

			if not bone.fHidden and bone:IsGroupVisible() then
				v:Set(bone.fLength - bone.fLength * (self.handlesDist / handlesZoomAdaptationVal), 0)
				bone.fMovedMatrix:Transform(v)
				
				if additionMarker1 then
					if self.alignHandlesAlongBone then
						offset:Set(v.x, v.y)
						if alignHandlesAdaptation then
							offset:Set(boneCenterPos.x + (((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height) * 1.5), boneCenterPos.y)
						end
					else
						offset:Set(v.x, v.y - ((markerR * markerMultiplier * handlesDistance) / currentScale / height))
					end
					angle = math.atan2(tip.y - center.y, tip.x - center.x)
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					newAngle = offsetAngle + (angle - offsetAngle)

					if alignHandlesAdaptation then
						v:Set(self:RotateVector2(moho, offset, boneCenterPos, newAngle))
					else
						v:Set(self:RotateVector2(moho, offset, v, newAngle))
					end
				end
				
				localV:Set(v)
				
				m:Transform(v)
				mouseEvent.view:Graphics():WorldToScreen(v, pt)
				if bone:IsZeroLength() and mouseEvent.ctrlKey then
					if (math.abs(pt.x - mouseEvent.pt.x) < markerR * 3 and math.abs(pt.y - mouseEvent.pt.y) < markerR * 3) then
						return 2
					end
				else
					if (self.ignoreZeroScaledBones and self:Round(bone.fAnimScale:GetValue(0), 1) == 1) or not self.ignoreZeroScaledBones then
						if (math.abs(pt.x - mouseEvent.pt.x) < markerR and math.abs(pt.y - mouseEvent.pt.y) < markerR) then
							return 2
						end
					end	
				end	
				
				if additionMarker1 then
					if self.alignHandlesAlongBone then
						v:Set(localV)
						offset:Set(v.x  - ((markerR * markerMultiplier * 2 * handlesDistance) / currentScale / height), v.y)
					else
						v:Set(bone.fLength - (bone.fLength * (self.handlesDist / handlesZoomAdaptationVal)), 0)
						bone.fMovedMatrix:Transform(v)
						offset:Set(v.x, v.y + ((markerR * markerMultiplier * handlesDistance) / currentScale / height))
					end
					offsetAngle = math.atan2(offset.y - center.y, offset.x - center.x)
					newAngle = offsetAngle + (angle - offsetAngle)
					v:Set(self:RotateVector2(moho, offset, v, newAngle))
					m:Transform(v)

					mouseEvent.view:Graphics():WorldToScreen(v, pt)
					if (math.abs(pt.x - mouseEvent.pt.x) < markerR and math.abs(pt.y - mouseEvent.pt.y) < markerR) then
						return 4
					end
				end
			end
		end
	end

	if id then
		if id > -1 and self.showPath then
			local bone = skel:Bone(id)
			if bone ~= nil then
				local channelPos = bone.fAnimPos
				local translationWhen = -20000
				local g = mouseEvent.view:Graphics()
				local m = LM.Matrix:new_local()
				local vec = LM.Vector2:new_local()
				local pt = LM.Point:new_local()
				local totalTimingOffset = moho.layer:TotalTimingOffset()
				moho.layer:GetFullTransform(moho.frame, m, moho.document)
				-- First see if any keyframes were picked
				for i = 0, bone.fAnimPos:CountKeys() - 1 do
					local frame = bone.fAnimPos:GetKeyWhen(i)
					if frame > 0 then
						vec = bone.fAnimPos:GetValue(frame)
						m:Transform(vec)
						g:WorldToScreen(vec, pt)
						if (math.abs(pt.x - mouseEvent.pt.x) < self.TOLERANCE and math.abs(pt.y - mouseEvent.pt.y) < self.TOLERANCE) then
							translationWhen = frame
							self.trPathBone = bone
							break
						end
					end	
				end
				-- If no keyframes were picked, try picking a random point along the curve.
				if (translationWhen <= -10000) then
					local startFrame = channelPos:GetKeyWhen(0)
					local channelDuration = channelPos:Duration()
					local endFrame = channelDuration
					if self.range then
						startFrame = LM.Clamp(moho.layerFrame - self.rangeFrames, 1, channelDuration)
						endFrame = LM.Clamp(moho.layerFrame + self.rangeFrames, 1, channelDuration)
					end
					if (endFrame > startFrame) then
						local oldVec = LM.Vector2:new_local()
						g:Clear(0, 0, 0, 0)
						g:SetColor(255, 255, 255)
						g:BeginPicking(mouseEvent.pt, 4)
						for frame = startFrame, endFrame do
							vec = channelPos:GetValue(frame)
							m:Transform(vec)
							if (frame > startFrame) then
								g:DrawLine(oldVec.x, oldVec.y, vec.x, vec.y)
							end
							if (g:Pick()) then
								translationWhen = frame
								self.trPathBone = bone
								break
							end
							oldVec:Set(vec)
						end
					end
				end
				if (translationWhen > -10000) then
					self.translationFrame = translationWhen
					return 5
				end
			end	
		end
	end
	return 1
end

function MR_PoseTool:FlipBones(moho, horizontal)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return 1
	end
	
	if (moho:CountSelectedBones(true) < 1) then
		return
	end

	moho.document:PrepUndo(moho.layer, true)
	moho.document:SetDirty()
	for i = 0, skel:CountBones() - 1 do
		local bone = skel:Bone(i)
		if (bone.fSelected) then
			if (horizontal) then
				bone.fFlipH:SetValue(moho.layerFrame, not bone.fFlipH.value)
			else
				bone.fFlipV:SetValue(moho.layerFrame, not bone.fFlipV.value)
			end
		end
	end
	moho.layer:UpdateCurFrame()
	if (horizontal) then
		moho:NewKeyframe(CHANNEL_BONE_FLIPH)
	else
		moho:NewKeyframe(CHANNEL_BONE_FLIPV)
	end
end

function MR_PoseTool:BakeFrames(moho, secondBone, firstBone, angle, pos, scale)
	if moho.layerFrame - self.interval > 0 then
		if firstBone then
			if angle and self.boneFAngleP then
				firstBone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.boneFAngleP)
			end	
			if pos and self.boneFPosP then
				local channel = firstBone.fAnimPos
				if channel:AreDimensionsSplit() then
					local channelX = channel:DimensionChannel(0)
					local channelY = channel:DimensionChannel(1)
					channelX:SetValue(moho.layerFrame - self.interval, self.boneFPosP.x)
					channelY:SetValue(moho.layerFrame - self.interval, self.boneFPosP.y)
				else
					firstBone.fAnimPos:SetValue(moho.layerFrame - self.interval, self.boneFPosP)
				end	
			end	
			if scale and self.boneFScaleP then
				firstBone.fAnimScale:SetValue(moho.layerFrame - self.interval, self.boneFScaleP)
			end	
		end
		if secondBone then
			if angle and self.boneSAngleP then
				secondBone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.boneSAngleP)
			end
			if pos and self.boneSPosP then
				local channel = secondBone.fAnimPos
				if channel:AreDimensionsSplit() then
					local channelX = channel:DimensionChannel(0)
					local channelY = channel:DimensionChannel(1)
					channelX:SetValue(moho.layerFrame - self.interval, self.boneSPosP.x)
					channelY:SetValue(moho.layerFrame - self.interval, self.boneSPosP.y)
				else
					secondBone.fAnimPos:SetValue(moho.layerFrame - self.interval, self.boneSPosP)
				end
			end	
			if scale and self.boneSScaleP then
				secondBone.fAnimScale:SetValue(moho.layerFrame - self.interval, self.boneSScaleP)
			end	
		end	
	end
	if moho.layerFrame + self.interval > 0 then
		if firstBone then
			if angle and self.boneFAngleN then
				firstBone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.boneFAngleN)
			end	
			if pos and self.boneFPosN then
				local channel = firstBone.fAnimPos
				if channel:AreDimensionsSplit() then
					local channelX = channel:DimensionChannel(0)
					local channelY = channel:DimensionChannel(1)
					channelX:SetValue(moho.layerFrame + self.interval, self.boneFPosN.x)
					channelY:SetValue(moho.layerFrame + self.interval, self.boneFPosN.y)
				else
					firstBone.fAnimPos:SetValue(moho.layerFrame + self.interval, self.boneFPosN)
				end
			end
			if scale and self.boneFScaleN then
				firstBone.fAnimScale:SetValue(moho.layerFrame + self.interval, self.boneFScaleN)
			end	
		end
		if secondBone then
			if angle and self.boneSAngleN then
				secondBone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.boneSAngleN)
			end
			if pos and self.boneSPosN then
				local channel = secondBone.fAnimPos
				if channel:AreDimensionsSplit() then
					local channelX = channel:DimensionChannel(0)
					local channelY = channel:DimensionChannel(1)
					channelX:SetValue(moho.layerFrame + self.interval, self.boneSPosN.x)
					channelY:SetValue(moho.layerFrame + self.interval, self.boneSPosN.y)
				else
					secondBone.fAnimPos:SetValue(moho.layerFrame + self.interval, self.boneSPosN)
				end	
			end	
			if scale and self.boneSScaleN then
				secondBone.fAnimScale:SetValue(moho.layerFrame + self.interval, self.boneSScaleN)
			end	
		end	
	end
end

function MR_PoseTool:CountBoneChildren(skel, boneID, ignoreControlledBones)
	local n = 0
	for i = 0, skel:CountBones() - 1 do
		local bone = skel:Bone(i)
		if (bone.fParent == boneID) then
			n = n + 1
			if (ignoreControlledBones) then
				if self.mohoVersion >= 14 then
					if (bone.fAngleControlParent >= 0 or bone.fPosControlParent >= 0 or bone.fScaleControlParent >= 0 
					or (bone.fBoneDynamics.value and (bone.fAngleDynamics or bone.fPosDynamics or bone.fScaleDynamics)) or bone.fIgnoredByIK) then
						n = n - 1 -- ignore this bone, as it is not free to move by itself
					end
				else
					if (bone.fAngleControlParent >= 0 or bone.fPosControlParent >= 0 or bone.fScaleControlParent >= 0 or bone.fBoneDynamics.value or bone.fIgnoredByIK) then
						n = n - 1 -- ignore this bone, as it is not free to move by itself
					end
				end
			end
		end
	end
	return n
end

function MR_PoseTool:RotateVector2(moho, vector2, center, angle)
	local centerVec = LM.Vector2:new_local()
	local newVector2 = LM.Vector2:new_local()
	local dif = LM.Vector2:new_local()
	centerVec:Set(center)
	dif:Set(vector2 - centerVec)
	local px = dif.x * math.cos(angle) - dif.y * math.sin(angle)
	local py = dif.x * math.sin(angle) + dif.y * math.cos(angle)
	newVector2:Set(px + centerVec.x, py + centerVec.y)
	return newVector2
end

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

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

	phrase['Description'] = 'Set up the pose of your character (hold <ctrl/cmd> to keep active handles visible, <alt> for compensation of child bone transformation, <shift> for additional transformation variations)'
	phrase['UILabel'] = 'MR Pose Tool '..self:Version()
	
	phrase['Settings'] = 'Settings'
	phrase['Double-click to reset'] = 'Double-click to reset'
	phrase['Block on even frames'] = 'Block on even frames'
	phrase['Block on odd frames'] = 'Block on odd frames'
	phrase['Highlight bones'] = 'Highlight bones'
	phrase['Highlight width:'] = 'Highlight width:'
	phrase['Highlight opacity:'] = 'Highlight opacity:'
	phrase['Custom'] = 'Use custom:'
	phrase['Align handles along bone'] = 'Align handles along bone'
	phrase['Handles distance:'] = 'Handles distance:'
	phrase['Handles stroke opacity:'] = 'Handles stroke opacity:'
	phrase['Handles fill opacity:'] = 'Handles fill opacity:'
	phrase['Use custom colors'] = 'Use custom colors'
	phrase['Translate handle stroke color Tooltip'] = 'Translate handle stroke color'
	phrase['Translate handle fill color Tooltip'] = 'Translate handle fill color'
	phrase['Scale handle stroke color Tooltip'] = 'Scale handle stroke color'
	phrase['Scale handle fill color Tooltip'] = 'Scale handle fill color'
	phrase['Move joint handle stroke color Tooltip'] = 'Move joint handle stroke color'
	phrase['Move joint handle fill color Tooltip'] = 'Move joint handle fill color'
	phrase['Manipulate handle stroke color Tooltip'] = 'Manipulate handle stroke color'
	phrase['Manipulate handle fill color Tooltip'] = 'Manipulate handle fill color'
	phrase['Reset colors'] = 'Reset colors'
	
	phrase['Keep selection'] = 'Keep selection'
	phrase['Lock handles'] = 'Lock handles'
	phrase['Hide bones while moving'] = 'Hide'
	phrase['Keep previous selection'] = 'Keep previous selection'
	phrase['Bake Adjacent Frames'] = 'Smart bake'
	phrase['Interval'] = 'Interval:'
	phrase['Show path'] = 'Show path'
	phrase['Range'] = 'Range'
	phrase['Range frames:'] = 'Range frames:'
	phrase['End flip'] = 'End flip'
	phrase['Side flip'] = 'Side flip'

	return phrase[text]
end

Icon
MR Pose Tool
Listed

Script type: Tool

Uploaded: Aug 14 2023, 06:38

Last modified: Feb 15 2024, 15:08

Plan and polish your animation with ease!
MR Pose Tool allows you to minimize the routine and spend more effort on creativity. This script combines the tools Transform Bone, Manipulate Bones, MR Move Targeted Joint, and even more.



To work correctly the lower bone (the shin or the forearm) must not have any Y-axis translation.
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: 2129