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 '2.0.3'
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.quickMenuTooltips = true
MR_PoseTool.moveTargetParent = false
MR_PoseTool.doubleClickToReset = true
MR_PoseTool.blockOnEvenFrames = true
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.colorFollowBonesR = 46
MR_PoseTool.colorFollowBonesG = 120
MR_PoseTool.colorFollowBonesB = 255
MR_PoseTool.colorFollowBonesA = 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.iconColorR = 34
MR_PoseTool.iconColorG = 70
MR_PoseTool.iconColorB = 65
MR_PoseTool.iconColorA = 255

MR_PoseTool.twosMode = false
MR_PoseTool.keepSelection = false
MR_PoseTool.multiTransform = 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
MR_PoseTool.followBonesList = {}
MR_PoseTool.followBonesList.id = {}
MR_PoseTool.followBonesList.names = {}
MR_PoseTool.followBonesList.startBone = {}
MR_PoseTool.followBonesList.endBone = {}
MR_PoseTool.startFollowBone = -1
MR_PoseTool.endFollowBone = -1
MR_PoseTool.scaleFollowBones = false
MR_PoseTool.isMouseDragging = false
MR_PoseTool.selRect = LM.Rect:new_local()
MR_PoseTool.forceFollowBonesGraphics = false
MR_PoseTool.iconsDistance = 0.08
MR_PoseTool.iconsRadius = 18
MR_PoseTool.showIcons = false
MR_PoseTool.graphicsMenuCenter = LM.Vector2:new_local()
MR_PoseTool.mouseHoverIDGraphicMenu = -1
MR_PoseTool.graphicMenuMode = 0
MR_PoseTool.lockAngleList = {}
MR_PoseTool.lockAngleBoneNamesList = {}
MR_PoseTool.lockPosList = {}
MR_PoseTool.lockPosBoneNamesList = {}
MR_PoseTool.bonesReset = false
MR_PoseTool.followLockLayerUUID = 0
MR_PoseTool.multiSelectionUnselectedMovement = false
MR_PoseTool.showCross = false

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

function MR_PoseTool:LoadPrefs(prefs)
	self.quickMenuTooltips = prefs:GetBool("MR_PoseTool.quickMenuTooltips", true)
	self.doubleClickToReset = prefs:GetBool("MR_PoseTool.doubleClickToReset", true)
	self.moveTargetParent = prefs:GetBool("MR_PoseTool.moveTargetParent", false)
	self.blockOnEvenFrames = prefs:GetBool("MR_PoseTool.blockOnEvenFrames", true)
	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.twosMode = prefs:GetBool("MR_PoseTool.twosMode", false)
	self.keepSelection = prefs:GetBool("MR_PoseTool.keepSelection", false)
	self.multiTransform = prefs:GetBool("MR_PoseTool.multiTransform", 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)
	
	self.scaleFollowBones = prefs:GetBool("MR_PoseTool.scaleFollowBones", false)
end

function MR_PoseTool:SavePrefs(prefs)
	prefs:SetBool("MR_PoseTool.quickMenuTooltips", self.quickMenuTooltips)
	prefs:SetBool("MR_PoseTool.doubleClickToReset", self.doubleClickToReset)
	prefs:SetBool("MR_PoseTool.moveTargetParent", self.moveTargetParent)
	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.twosMode", self.twosMode)
	prefs:SetBool("MR_PoseTool.keepSelection", self.keepSelection)
	prefs:SetBool("MR_PoseTool.multiTransform", self.multiTransform)
	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)
	
	prefs:SetBool("MR_PoseTool.scaleFollowBones", self.scaleFollowBones)
end

function MR_PoseTool:ResetPrefs()
	self.quickMenuTooltips = true
	self.doubleClickToReset = true
	self.moveTargetParent = false
	self.blockOnEvenFrames = true
	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.twosMode = false
	self.keepSelection = false
	self.multiTransform = false
	self.lockHandles = false
	self.bakeAdjacentFrames = false
	self.interval = 1
	self.showPath = false
	self.range = false
	self.rangeFrames = 10
	self.scaleFollowBones = false
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.QUICK_MENU_TOOLTIPS = MOHO.MSG_BASE
MR_PoseToolSettingsDialog.DOUBLE_CLICK_TO_RESET = MOHO.MSG_BASE + 1
MR_PoseToolSettingsDialog.MOVE_TARGET_PARENT = MOHO.MSG_BASE + 2
MR_PoseToolSettingsDialog.BLOCK_ON_EVEN_FRAMES = MOHO.MSG_BASE + 3
MR_PoseToolSettingsDialog.BLOCK_ON_ODD_FRAMES = MOHO.MSG_BASE + 4
MR_PoseToolSettingsDialog.HIGHLIGHT_BONES = MOHO.MSG_BASE + 5
MR_PoseToolSettingsDialog.HIGHLIGHT_WIDTH = MOHO.MSG_BASE + 6
MR_PoseToolSettingsDialog.HIGHLIGHT_OPACITY = MOHO.MSG_BASE + 7
MR_PoseToolSettingsDialog.USE_HIGHLIGHT_CUSTOM_COLOR = MOHO.MSG_BASE + 8
MR_PoseToolSettingsDialog.HIGHLIGHT_CUSTOM_COLOR = MOHO.MSG_BASE + 9
MR_PoseToolSettingsDialog.ALIGN_HANDLES_ALONG_BONE = MOHO.MSG_BASE + 10
MR_PoseToolSettingsDialog.HANDLES_DISTANCE = MOHO.MSG_BASE + 11
MR_PoseToolSettingsDialog.HANDLES_STROKE_OPACITY = MOHO.MSG_BASE + 12
MR_PoseToolSettingsDialog.HANDLES_FILL_OPACITY = MOHO.MSG_BASE + 13
MR_PoseToolSettingsDialog.USE_CUSTOM_COLORS = MOHO.MSG_BASE + 14
MR_PoseToolSettingsDialog.COLOR_TRANSLATE_STROKE = MOHO.MSG_BASE + 15
MR_PoseToolSettingsDialog.COLOR_TRANSLATE_FILL = MOHO.MSG_BASE + 16
MR_PoseToolSettingsDialog.COLOR_SCALE_STROKE = MOHO.MSG_BASE + 17
MR_PoseToolSettingsDialog.COLOR_SCALE_FILL = MOHO.MSG_BASE + 18
MR_PoseToolSettingsDialog.COLOR_MOVE_JOINT_STROKE = MOHO.MSG_BASE + 19
MR_PoseToolSettingsDialog.COLOR_MOVE_JOINT_FILL = MOHO.MSG_BASE + 20
MR_PoseToolSettingsDialog.COLOR_MANIPULATE_STROKE = MOHO.MSG_BASE + 21
MR_PoseToolSettingsDialog.COLOR_MANIPULATE_FILL = MOHO.MSG_BASE + 22
MR_PoseToolSettingsDialog.RESET_COLOR = MOHO.MSG_BASE + 23

function MR_PoseToolSettingsDialog:new()
	local d = LM.GUI.SimpleDialog(MR_PoseTool:Localize('UILabel'), MR_PoseToolSettingsDialog)
    local l = d:GetLayout()
	if HV_Font then
		d.quickMenuTooltipsCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Quick menu tooltips'), self.QUICK_MENU_TOOLTIPS)
		l:AddChild(d.quickMenuTooltipsCheck, LM.GUI.ALIGN_LEFT, 0)
	end
	
	l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
	
	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)
	
	d.moveTargetParentCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Move target parent'), self.MOVE_TARGET_PARENT)
    l:AddChild(d.moveTargetParentCheck, 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)
	if HV_Font then
		self.quickMenuTooltipsCheck:SetValue(MR_PoseTool.quickMenuTooltips)
	end
    self.doubleClickToResetCheck:SetValue(MR_PoseTool.doubleClickToReset)
    self.moveTargetParentCheck:SetValue(MR_PoseTool.moveTargetParent)
    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)
	if HV_Font then
		MR_PoseTool.quickMenuTooltips = self.quickMenuTooltipsCheck:Value()
	end
    MR_PoseTool.doubleClickToReset = self.doubleClickToResetCheck:Value()
    MR_PoseTool.moveTargetParent = self.moveTargetParentCheck: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.QUICK_MENU_TOOLTIPS then
		MR_PoseTool.quickMenuTooltips = self.quickMenuTooltipsCheck:Value()
	elseif msg == self.DOUBLE_CLICK_TO_RESET then
		MR_PoseTool.doubleClickToReset = self.doubleClickToResetCheck:Value()
	elseif msg == self.MOVE_TARGET_PARENT then
		MR_PoseTool.moveTargetParent = self.moveTargetParentCheck: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)
	self.forceFollowBonesGraphics = false
	local frame = moho.frame
	local skel = moho:Skeleton()
	if skel == nil or frame == 0 then
		return
	end
	
	if self.showIcons then
		self.graphicMenuMode = self:TestMousePointGraphicMenu(moho, mouseEvent)
		if self.graphicMenuMode == 1 then
			self:AddToFollowBones(moho)
		elseif self.graphicMenuMode == 2 then	
			self.scaleFollowBones = not self.scaleFollowBones
		elseif self.graphicMenuMode == 3 then	
			self:AddToLockAngleList(moho)
		elseif self.graphicMenuMode == 4 then	
			self:AddToLockPosList(moho)
		elseif self.graphicMenuMode == 5 then
			self:RemoveSelectedBonesFromFollowList(moho)
			self:RemoveFromLockList(moho)
		elseif self.graphicMenuMode == 6 then
			self.lockAngleList = {}
			self.lockPosList = {}
			self.lockAngleBoneNamesList = {}
			self.lockPosBoneNamesList = {}
			self.followBonesList = {}
			self.followBonesList.id = {}
			self.followBonesList.names  = {}
			self.followBonesList.startBone = {}
			self.followBonesList.endBone = {}
		end
		return
	elseif self.showIcons2 then
		self.graphicMenuMode = self:TestMousePointGraphicMenu(moho, mouseEvent)
		if self.graphicMenuMode == 1 then
			if self.keepSelection then
				self.multiTransform = not self.multiTransform
			end
		elseif self.graphicMenuMode == 2 then	
			self.keepSelection = not self.keepSelection
		elseif self.graphicMenuMode == 3 then	
			self.lockHandles = not self.lockHandles
		elseif self.graphicMenuMode == 4 then	
			self.bakeAdjacentFrames = not self.bakeAdjacentFrames
		elseif self.graphicMenuMode == 5 then
			self.showPath = not self.showPath
		elseif self.graphicMenuMode == 6 then
			self.twosMode = not self.twosMode
		end
		return
	end

	if self.twosMode then
		if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0) then
			return
		end
	end

	local lockHandles = self.lockHandles
	
	local selBoneID = -1
	self.selBones = moho:CountSelectedBones()
	if self.selBones == 1 then
		selBoneID = skel:SelectedBoneID()
	end
	self.isLockHandleMouseMoved = false
	self.translationFrame = frame

	if not mouseEvent.doubleClick then
		self.selectedBonesList = {}
		self.multiBoneTranslateList = {}
		for i=0, skel:CountBones()-1 do
			local bone = skel:Bone(i)
			if bone.fSelected then
				table.insert(self.selectedBonesList, i)
				if not skel:IsAncestorSelected(i) then
					table.insert(self.multiBoneTranslateList, i)
				end
			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 self.selBones > 0 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

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

		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 boneRegion == -1 then
			id = -1
			secondId = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, false)
			boneRegion = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)
			if boneRegion == -1 then
				secondId = -1
			end
		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
	self.lockHandlesSelection = 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
					local bone = skel:Bone(id)
					self.mousePickedID = id
					self.secondBoneID = id
					selBoneID = id
					self.dragging = false
					self.lockHandlesSelection = true
					if self.multiTransform and self.keepSelection then
						goto multiTransformSelection
					end
					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 mouseEvent.doubleClick and self.doubleClickToReset then	
		local doubleclickMode = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)
		if doubleclickMode == -1 then
			self.lockAngleList = {}
			self.lockPosList = {}
			self.lockAngleBoneNamesList = {}
			self.lockPosBoneNamesList = {}
			self.followBonesList = {}
			self.followBonesList.id = {}
			self.followBonesList.names  = {}
			self.followBonesList.startBone = {}
			self.followBonesList.endBone = {}
			return
		end
	end

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

	::multiTransformSelection::
	local multiTransformSelection = false
	self.multiSelectionUnselectedMovement = false
	if self.multiTransform and self.keepSelection and self.selBones > 0 then
		local isBoneWasSelected = false
		for i=1, #self.selectedBonesList do
			if self.selectedBonesList[i] == self.secondBoneID then
				isBoneWasSelected = true
				break
			end
		end
		if not isBoneWasSelected then
			skel:SelectNone()
			for _, id in ipairs(self.selectedBonesList) do
				local bone = skel:Bone(id)
				bone.fSelected = true
			end
			self.multiSelectionUnselectedMovement = true
			if mouseHoverID == -1 then
				multiTransformSelection = true
			else
				return
			end
		end
	end
	
	if mouseHoverID == -1 and self.mode ~= 5 or multiTransformSelection then
		self.isMouseDragging = true
		if not mouseEvent.shiftKey and not mouseEvent.altKey then
			if skel then
				skel:SelectNone()
			elseif mesh then
				mesh:SelectNone()
			end	
		end
		
		self.selRect.left = mouseEvent.startPt.x
		self.selRect.top = mouseEvent.startPt.y
		self.selRect.right = mouseEvent.pt.x
		self.selRect.bottom = mouseEvent.pt.y
		mouseEvent.view:Graphics():SelectionRect(self.selRect)
		mouseEvent.view:DrawMe()
		return
	end
	
	moho.document:PrepUndo(moho.layer, true)
	moho.document:SetDirty()
	
	self.isMouseMoved = false
	self.bonesReset = false
	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	
				for i, b in ipairs(self.selectedBonesList) do
					local bone = skel:Bone(b)
					if bone then
						bone.fAnimPos:SetValue(moho.layerFrame, bone.fAnimPos:GetValue(0))
					end	
				end
			end

			moho.layer:UpdateCurFrame()
			moho:NewKeyframe(CHANNEL_BONE_T)
			self:UpdateWidgets(moho)
			self.bonesReset = true
			return
		elseif self.mode == 1 then
			for i, b in ipairs(self.selectedBonesList) do
				local bone = skel:Bone(b)
				if bone then
					bone.fAnimAngle:SetValue(moho.layerFrame, bone.fAnimAngle:GetValue(0))
				end	
			end

			moho.layer:UpdateCurFrame()
			moho:NewKeyframe(CHANNEL_BONE)
			self:UpdateWidgets(moho)
			self.bonesReset = true
			return
		elseif self.mode == 2 then
			for i, b in ipairs(self.selectedBonesList) do
				local bone = skel:Bone(b)
				if bone then
					bone.fAnimScale:SetValue(moho.layerFrame, bone.fAnimScale:GetValue(0))
				end	
			end

			moho.layer:UpdateCurFrame()
			moho:NewKeyframe(CHANNEL_BONE_S)
			self:UpdateWidgets(moho)
			self.bonesReset = true
			return
		end
	end
	
	self.selBoneIsAncestorSelected = false
	if self.multiTransform and self.keepSelection then
		if self.mode == 0 then
			for i=1, #self.selectedBonesList do
				if skel:IsBoneParent(self.secondBoneID, self.selectedBonesList[i]) and self.secondBoneID ~= self.selectedBonesList[i] then
					self.selBoneIsAncestorSelected = true
					break
				end
			end
			
			self.multiBoneTranslateSBValuesPList = {}
			self.multiBoneTranslateSBValuesNList = {}
			self.multiBoneTranslateBakedList = {}
			for i=1, #self.multiBoneTranslateList do
				local sBone = skel:Bone(self.multiBoneTranslateList[i])
				sBone.fTempPos:Set(sBone.fAnimPos:GetValue(moho.layerFrame))
				self.multiBoneTranslateSBValuesPList[i] = sBone.fAnimPos:GetValue(moho.layerFrame - self.interval)
				self.multiBoneTranslateSBValuesNList[i] = sBone.fAnimPos:GetValue(moho.layerFrame + self.interval)
				self.multiBoneTranslateBakedList[i] = false
			end
		elseif self.mode == 1 then
			self.multiBoneAngleSBValuesPList = {}
			self.multiBoneAngleSBValuesNList = {}
			self.multiBoneAngleBakedList = {}
			local lastVec = LM.Vector2:new_local()
			lastVec:Set(mouseEvent.vec)
			for i=1, #self.selectedBonesList do
				local sBone = skel:Bone(self.selectedBonesList[i])
				sBone.fTempAngle = sBone.fAnimAngle:GetValue(moho.layerFrame)
				self.multiBoneAngleSBValuesPList[i] = sBone.fAnimAngle:GetValue(moho.layerFrame - self.interval)
				self.multiBoneAngleSBValuesNList[i] = sBone.fAnimAngle:GetValue(moho.layerFrame + self.interval)
				self.multiBoneAngleBakedList[i] = false
			end
		elseif self.mode == 2 then
			self.multiBoneScaleSBValuesPList = {}
			self.multiBoneScaleSBValuesNList = {}
			self.multiBoneScaleDeltaList = {}
			self.multiBoneScaleBakedList = {}
			for i=1, #self.selectedBonesList do
				local sBone = skel:Bone(self.selectedBonesList[i])
				sBone.fTempScale = sBone.fAnimScale:GetValue(moho.layerFrame)
				self.multiBoneScaleSBValuesPList[i] = sBone.fAnimScale:GetValue(moho.layerFrame - self.interval)
				self.multiBoneScaleSBValuesNList[i] = sBone.fAnimScale:GetValue(moho.layerFrame + self.interval)
				self.multiBoneScaleDeltaList[i] = sBone.fScale - sBone.fAnimScale:GetValue(moho.layerFrame)
				self.multiBoneScaleBakedList[i] = false
			end
		end
	end

	skel:SelectNone()
	self.startAngle = 0
	self.startAngle2 = 0
	secondBone = skel:Bone(self.secondBoneID)
	self.jointChain = false
	self.firstBoneID = -1
	
	self:ValidateLockList(moho)
	
	if #self.lockAngleList > 0 then
		self.lockedBonesSBAngleValuesP = {}
		self.lockedBonesSBAngleValuesN = {}
		self.lockBonesParentStartAngle = {}
		self.lockBonesLastParentTipVec = {}
		self.lockBonesLastParentBaseVec = {}
		self.lockAngleBaked = {}
		
		for l=1, #self.lockAngleList do
			local lBone = skel:Bone(self.lockAngleList[l])
			if lBone then
				if lBone.fParent > -1 then
					local parentBoneTipPos = LM.Vector2:new_local()
					local parentBoneBasePos = LM.Vector2:new_local()
					local parentBone = skel:Bone(lBone.fParent)
					parentBoneBasePos:Set(0, 0)
					
					if (parentBone:IsZeroLength()) then
						parentBoneTipPos:Set(0.1, 0)
					else
						if lBone:IsZeroLength() then
							parentBoneTipPos:Set(0.1, 0)
						else
							parentBoneTipPos:Set(lBone.fLength, 0)
						end
					end
					
					if moho.frame == 0 then
						parentBone.fRestMatrix:Transform(parentBoneBasePos)
						parentBone.fRestMatrix:Transform(parentBoneTipPos)
					else
						parentBone.fMovedMatrix:Transform(parentBoneBasePos)
						parentBone.fMovedMatrix:Transform(parentBoneTipPos)
					end
					
					lBone.fTempAngle = lBone.fAnimAngle:GetValue(moho.layerFrame)
					
					self.lockedBonesSBAngleValuesP[l] = lBone.fAnimAngle:GetValue(moho.layerFrame - self.interval)
					self.lockedBonesSBAngleValuesN[l] = lBone.fAnimAngle:GetValue(moho.layerFrame + self.interval)
					self.lockBonesLastParentTipVec[l] = parentBoneTipPos
					self.lockBonesLastParentBaseVec[l] = parentBoneBasePos
					self.lockBonesParentStartAngle[l] = 0
					self.lockAngleBaked[l] = false
				end
			end
		end
	end
	
	if #self.lockPosList > 0 then
		self.lockedBonesSBPosValuesP = {}
		self.lockedBonesSBPosValuesN = {}
		self.lockedBonesPos = {}
		self.lockedBonesDeltaPos = {}
		self.lockPosBaked = {}
		for l=1, #self.lockPosList do
			local lBone = skel:Bone(self.lockPosList[l])
			if lBone then
				local bonePos = LM.Vector2:new_local()
				bonePos:Set(0, 0)
				
				if moho.frame == 0 then
					lBone.fRestMatrix:Transform(bonePos)
				else
					lBone.fMovedMatrix:Transform(bonePos)
				end
				
				self.lockPosBaked[l] = false
				self.lockedBonesDeltaPos[l] = lBone.fPos - lBone.fAnimPos:GetValue(moho.layerFrame)
				self.lockedBonesPos[l] = bonePos
				self.lockedBonesSBPosValuesP[l] = lBone.fAnimPos:GetValue(moho.layerFrame - self.interval)
				self.lockedBonesSBPosValuesN[l] = lBone.fAnimPos:GetValue(moho.layerFrame + self.interval)
			end
		end
	end
	
	if #self.followBonesList.id > 0 then
		self:ValidateFollowList(moho)
	end
	
	if #self.followBonesList.id > 0 then
		self.followBonesDataList = {}
		self.followBonesDataList.sBValuesP = {}
		self.followBonesDataList.sBValuesN = {}
		self.followBonesDataList.sBValuesBakedS = {}
		self.followBonesDataList.scaleDelta = {}
		self.followBonesDataList.targetPos = {}
		self.followBonesDataList.distance = {}
		self.followBonesDataList.startAngle = {}
		self.followBonesDataList.lastVec = {}
		self.followBonesDataList.angleDelta = {}
		self.followBonesDataList.lastParentBaseVec = {}
		self.followBonesDataList.lastParentTipVec = {}
		self.followBonesDataList.parentStartAngle = {}
		self.followBonesDataList.bakedA = {}
		self.followBonesDataList.bakedS = {}
		self.followBonesDataList.FAngleP = {}
		self.followBonesDataList.FAngleN = {}
		self.followBonesDataList.block = {}
		for b=1, #self.followBonesList.id do
			local startFollowBone = skel:Bone(self.followBonesList.startBone[b])
			local endFollowBone = skel:Bone(self.followBonesList.endBone[b])
			if startFollowBone and endFollowBone then
				local boneTipPos = LM.Vector2:new_local()
				local boneBasePos = LM.Vector2:new_local()
				local valuesPLis = {}
				local valuesNLis = {}
				local scaleDeltaList = {}
				local bakedSList = {}
				local block = false
				for i=1, #self.followBonesList.id[b] do
					local fBone = skel:Bone(self.followBonesList.id[b][i])
					if fBone then
						if self.followBonesList.id[b][i] == self.secondBoneID then
							block = true
						end
						fBone.fTempScale = fBone.fScale
						table.insert(valuesPLis, fBone.fAnimScale:GetValue(moho.layerFrame - self.interval))
						table.insert(valuesNLis, fBone.fAnimScale:GetValue(moho.layerFrame + self.interval))
						table.insert(scaleDeltaList, fBone.fScale - fBone.fAnimScale:GetValue(moho.layerFrame))
						table.insert(bakedSList, false)
					end
				end
				
				self.followBonesDataList.sBValuesP[b] = valuesPLis
				self.followBonesDataList.sBValuesN[b] = valuesNLis
				self.followBonesDataList.scaleDelta[b] = scaleDeltaList
				self.followBonesDataList.sBValuesBakedS[b] = bakedSList
				self.followBonesDataList.block[b] = block
				
				boneBasePos:Set(0, 0)
				if (startFollowBone:IsZeroLength()) then
					boneTipPos:Set(0.1, 0)
				else
					boneTipPos:Set(endFollowBone.fLength, 0)
				end
				
				if moho.frame == 0 then
					startFollowBone.fRestMatrix:Transform(boneBasePos)
					endFollowBone.fRestMatrix:Transform(boneTipPos)
				else
					startFollowBone.fMovedMatrix:Transform(boneBasePos)
					endFollowBone.fMovedMatrix:Transform(boneTipPos)
				end
				self.followBonesDataList.targetPos[b] = boneTipPos
				
				self.followBonesDataList.distance[b] = self:GetDistance(boneBasePos, boneTipPos)
				self.followBonesDataList.startAngle[b] = 0
				
				self.followBonesDataList.lastVec[b] = boneBasePos
				startFollowBone.fTempAngle = startFollowBone.fAnimAngle:GetValue(moho.layerFrame)
				local followBoneActualAngle = startFollowBone.fAngle
				self.followBonesDataList.angleDelta[b] = followBoneActualAngle - startFollowBone.fAnimAngle:GetValue(moho.layerFrame)
				
				if startFollowBone.fParent > -1 then
					local parentBoneTipPos = LM.Vector2:new_local()
					local parentBoneBasePos = LM.Vector2:new_local()
					local parentBone = skel:Bone(startFollowBone.fParent)
					parentBoneBasePos:Set(0, 0)
					
					if (parentBone:IsZeroLength()) then
						parentBoneTipPos:Set(0.1, 0)
					else
						parentBoneTipPos:Set(endFollowBone.fLength, 0)
					end
					
					if moho.frame == 0 then
						parentBone.fRestMatrix:Transform(parentBoneBasePos)
						parentBone.fRestMatrix:Transform(parentBoneTipPos)
					else
						parentBone.fMovedMatrix:Transform(parentBoneBasePos)
						parentBone.fMovedMatrix:Transform(parentBoneTipPos)
					end
					self.followBonesDataList.lastParentBaseVec[b] = parentBoneBasePos
					self.followBonesDataList.lastParentTipVec[b] = parentBoneTipPos
					self.followBonesDataList.parentStartAngle[b] = 0
				end
				self.followBonesDataList.bakedA[b] = false
				self.followBonesDataList.bakedS[b] = false
				self.followBonesDataList.FAngleP[b] = startFollowBone.fAnimAngle:GetValue(moho.layerFrame - self.interval)
				self.followBonesDataList.FAngleN[b] = startFollowBone.fAnimAngle:GetValue(moho.layerFrame + self.interval)
			end
		end
	end
	
	self.followLockedBonesList = {}
	self.followLockedBonesList.id = {}
	self.followLockedBonesList.listIndex = {}
	self.followLockedBonesList.list = {} -- 1 follow, 2 lock angle, 3 lock pos
	
	for b=1, #self.followBonesList.id do
		table.insert(self.followLockedBonesList.id, self.followBonesList.id[b][1])
		table.insert(self.followLockedBonesList.listIndex, b)
		table.insert(self.followLockedBonesList.list, 1)
	end
	
	for b=1, #self.lockAngleList do
		table.insert(self.followLockedBonesList.id, self.lockAngleList[b])
		table.insert(self.followLockedBonesList.listIndex, b)
		table.insert(self.followLockedBonesList.list, 2)
	end
	
	for b=1, #self.lockPosList do
		table.insert(self.followLockedBonesList.id, self.lockPosList[b])
		table.insert(self.followLockedBonesList.listIndex, b)
		table.insert(self.followLockedBonesList.list, 3)
	end
	
	local isChanges = false
	
	repeat
		isChanges = false
		for i, y in ipairs(self.followLockedBonesList.id) do
			local myBone = skel:Bone(self.followLockedBonesList.id[i])
			if myBone.fParent > -1 then
				local newParentId = myBone.fParent
				for a, t in ipairs(self.followLockedBonesList.id) do
					if newParentId == self.followLockedBonesList.id[a] then
						if i < a then
							isChanges = true
							self.followLockedBonesList.id[i], self.followLockedBonesList.id[a] = self:SwapTwoArrayKeys(self.followLockedBonesList.id, i, a)
							self.followLockedBonesList.listIndex[i], self.followLockedBonesList.listIndex[a] = self:SwapTwoArrayKeys(self.followLockedBonesList.listIndex, i, a)
							self.followLockedBonesList.list[i], self.followLockedBonesList.list[a] = self:SwapTwoArrayKeys(self.followLockedBonesList.list, i, a)
							break
						end	
					else
						local nextBone = skel:Bone(newParentId)
						repeat 
							local prevBone = nextBone
							for b, g in ipairs(self.followLockedBonesList.id) do
								if prevBone.fParent == self.followLockedBonesList.id[b] then
									if i < b then
										isChanges = true
										self.followLockedBonesList.id[i], self.followLockedBonesList.id[b] = self:SwapTwoArrayKeys(self.followLockedBonesList.id, i, b)
										self.followLockedBonesList.listIndex[i], self.followLockedBonesList.listIndex[b] = self:SwapTwoArrayKeys(self.followLockedBonesList.listIndex, i, b)
										self.followLockedBonesList.list[i], self.followLockedBonesList.list[b] = self:SwapTwoArrayKeys(self.followLockedBonesList.list, i, b)
									end	
								end		
							end
							if nextBone.fParent > -1 then
								nextBone = skel:Bone(nextBone.fParent)
							end
						until nextBone == prevBone
					end
				end
			end	
		end	
	until isChanges == false

	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.fScale
		
		self.secondBoneSecondDelta = bone.fScale - bone.fAnimScale:GetValue(moho.layerFrame)
		
		self.secondTarget = skel:TargetOfBoneChain(id, moho.layerFrame)
		
		if self.moveTargetParent then
			for b=0, skel:CountBones()-1 do
				local bone = skel:Bone(b)
				if bone.fParent == -1 and skel:IsBoneParent(self.secondTarget, b) then
					self.secondTarget = b
					break
				end
			end
		end
		
		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.parentBonesScaleDelta = {}
		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.fScale
			table.insert(self.parentBones, parenBoneID)
			
			table.insert(self.parentBonesScaleDelta, bone.fScale - bone.fAnimScale:GetValue(moho.layerFrame))
			
			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.moveTargetParent then
		for b=0, skel:CountBones()-1 do
			local bone = skel:Bone(b)
			if bone.fParent == -1 and skel:IsBoneParent(self.secondTarget, b) then
				self.secondTarget = b
				break
			end
		end
	end
	
	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()
	self.isMouseMoved = false
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 not (mouseEvent.ctrlKey) then
		local pos = LM.Vector2:new_local()
		pos:Set(mouseEvent.vec)
		local m = LM.Matrix:new_local()
		moho.layer:GetFullTransform(moho.frame, m, moho.document)
		m:Transform(pos)
		self.graphicsMenuCenter:Set(pos)
	end
	
	if self.twosMode then
		if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0)then
			self.showIcons = false
			self.showIcons2 = false
			
			local pickWidth = self.pickWidth
			if not mouseEvent.ctrlKey then
				self.mouseHoverIDGraphicMenu = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)
				self.showIcons = false
				self.showIcons2 = false
				mouseEvent.view:SetCursor(MOHO.disabledCursor)
			elseif mouseEvent.ctrlKey and self.mouseHoverIDGraphicMenu == -1 then
				if mouseEvent.shiftKey then
					self.showIcons2 = true
					if self.showIcons or self.showIcons2 then
						self.graphicMenuMode = self:TestMousePointGraphicMenu(moho, mouseEvent)
					end
					mouseEvent.view:SetCursor(self.mainCursor)
				else
					self.showIcons2 = false
					mouseEvent.view:SetCursor(MOHO.disabledCursor)
				end
			end
			mouseEvent.view:DrawMe()
			return
		end
	end

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

	if self.multiSelectionUnselectedMovement then
		self.isMouseMoved = true
		return
	end
		
	if self.lockHandlesSelection then
		self.isLockHandleMouseMoved = true
	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)
	end
	self.showIcons = false
	self.showIcons2 = false
	
	local pickWidth = self.pickWidth
	if not mouseEvent.ctrlKey then
		self.mouseHoverIDGraphicMenu = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)
		self.showIcons = false
		self.showIcons2 = false
	elseif mouseEvent.ctrlKey and self.mouseHoverIDGraphicMenu == -1 then
		if mouseEvent.shiftKey then
			self.showIcons2 = true
		else
			self.showIcons2 = false
		end
		
		if not mouseEvent.shiftKey then
			self.showIcons = true
		else
			self.showIcons = false
		end
	end

	if self.showIcons or self.showIcons2 then
		self.graphicMenuMode = self:TestMousePointGraphicMenu(moho, mouseEvent)
	end
	
	self.mouseHoverID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)

	if (not self.dragging) then
		if (not mouseEvent.ctrlKey and not lockHandles) or lockHandles then
			if self.multiTransform and self.keepSelection and not lockHandles and selectedBones > 1 then
				local bones = {}
				for i=0, skel:CountBones()-1 do
					local tBone = skel:Bone(i)
					table.insert(bones, tBone.fHidden)
					if not tBone.fSelected then
						tBone.fHidden = true
					end
				end
				self.mousePickedID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, false)
				self.mouseHoverID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)
				for i, bool in ipairs(bones) do
					local tBone = skel:Bone(i-1)
					tBone.fHidden = bool
				end
			else
				if (selectedBones ~= 1 and not mouseEvent.ctrlKey) or (not lockHandles and not mouseEvent.ctrlKey) then
					if lockHandles and selectedBones > 1 then
						local bones = {}
						for i=0, skel:CountBones()-1 do
							local tBone = skel:Bone(i)
							table.insert(bones, tBone.fHidden)
							if not tBone.fSelected then
								tBone.fHidden = true
							end
						end

						self.mousePickedID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, false)
						lockMousePickedID = self.mousePickedID 
						boneID = self.mousePickedID 
						self.mouseHoverID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)

						for i, bool in ipairs(bones) do
							local tBone = skel:Bone(i-1)
							tBone.fHidden = bool
						end
					else
						self.mousePickedID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, false)
					end
				end
			end
		end
		
		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 self.multiTransform and self.keepSelection and not self.lockHandles then
			if self.mousePickedID > -1 and selectedBones > 0 then
				local tBone = skel:Bone(self.mousePickedID)
				if not tBone.fSelected then
					self.mousePickedID = -1
					mouseEvent.view:SetCursor(self.mainCursor)
					mouseEvent.view:DrawMe()
					return
				end
			end
		end
		
		if self.multiTransform and self.keepSelection and selectedBones > 1 then
			self.additionHandles = false
		end
		
		if lockHandles and selectedBones >= 1 then
			if not self.showIcons 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 ~= self.mouseHoverID 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
			end
		else
			if self.mouseHoverID > -1 or bone ~= nil then
				local isBoneSelected = false
				if self.multiTransform and self.keepSelection then
					if self.mousePickedID > -1 and self.mousePickedID == self.mouseHoverID then
						isBoneSelected = true
					end
				else
					if (not self.multiTransform and self.keepSelection) or (not self.multiTransform and self.keepSelection) and not self.lockHandles then
						isBoneSelected = true
					elseif not self.keepSelection and not self.lockHandles then
						isBoneSelected = true
					else
						if self.mouseHoverID > -1 then
							local selBone = skel:Bone(self.mouseHoverID)
							if selBone.fSelected then
								isBoneSelected = true
							end
						end
					end
				end

				if isBoneSelected then
					if not self.showIcons then
						if self.multiTransform and self.keepSelection then
							mode = self:TestMousePoint(moho, mouseEvent, self.mousePickedID)
						else
							mode = self:TestMousePoint(moho, mouseEvent, boneID)
						end
						
						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
					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
	self.isMouseMoved = true
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
	
	self:AdjustFollowAndLockBones(moho)
	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
			if (self.multiTransform and self.keepSelection and not self.selBoneIsAncestorSelected) or not(self.multiTransform and self.keepSelection) 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
				
			if self.multiTransform and self.keepSelection then
				for i=1, #self.multiBoneTranslateList do
					if self.multiBoneTranslateList[i] ~= self.secondBoneID then
						local sBone = skel:Bone(self.multiBoneTranslateList[i])
						sBone.fPos:Set(sBone.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 (sBone.fParent >= 0) then
							parent = skel:Bone(sBone.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 = sBone.fPos + boneVec
						local bonePos = sBone.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
							sBone.fAnimPos:SetValue(moho.layerFrame, v)
							if self.bakeAdjacentFrames and not self.multiBoneTranslateBakedList[i] then
								if moho.layerFrame - self.interval > 0 then
									sBone.fAnimPos:SetValue(moho.layerFrame - self.interval, self.multiBoneTranslateSBValuesPList[i])
								end
								if moho.layerFrame + self.interval > 0 then
									sBone.fAnimPos:SetValue(moho.layerFrame + self.interval, self.multiBoneTranslateSBValuesNList[i])
								end
								self.multiBoneTranslateBakedList[i] = true
							end
						end
					end
				end
			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
				if (self.selBones == 1 and self.multiTransform and self.keepSelection) or not self.multiTransform 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
			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
	self:AdjustFollowAndLockBones(moho)
	
	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 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.multiTransform and self.keepSelection then
		for i=1, #self.selectedBonesList do
			if self.selectedBonesList[i] ~= self.secondBoneID then
				local sBone = skel:Bone(self.selectedBonesList[i])
				local center = LM.Vector2:new_local()
				center:Set(0, 0)
				
				sBone.fMovedMatrix:Transform(center)

				local selectedAngleSign = 1.0
				if (not sBone.fFixedAngle) then
					selectedAngleSign = sBone:ParentalFlipFactor()
				end

				local newSelAgle = (sBone.fTempAngle + (angle * selectedAngleSign))

				if not self:IsEqual(newSelAgle, sBone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then
					sBone.fAnimAngle:SetValue(moho.layerFrame, newSelAgle)
					if self.bakeAdjacentFrames and not self.multiBoneAngleBakedList[i] then
						if moho.layerFrame - self.interval > 0 then
							sBone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.multiBoneAngleSBValuesPList[i])
						end
						if moho.layerFrame + self.interval > 0 then
							sBone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.multiBoneAngleSBValuesNList[i])
						end
						self.multiBoneAngleBakedList[i] = true
					end
				end
			end
		end
	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 not (self.multiTransform and self.keepSelection and self.selBones > 1) then
		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
	end

	self:AdjustFollowAndLockBones(moho)
	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
		
		if self.multiTransform and self.keepSelection then
			for i=1, #self.selectedBonesList do
				local sBone = skel:Bone(self.selectedBonesList[i])
				local newSelectedScale = (sBone.fTempScale * scaleFactor) - self.multiBoneScaleDeltaList[i]
				if not self:IsEqual(newSelectedScale, sBone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then
					sBone.fAnimScale:SetValue(moho.layerFrame, newSelectedScale)
					if self.bakeAdjacentFrames and not self.multiBoneScaleBakedList[i] then
						if moho.layerFrame - self.interval > 0 then
							sBone.fAnimScale:SetValue(moho.layerFrame - self.interval, self.multiBoneScaleSBValuesPList[i])
						end
						if moho.layerFrame + self.interval > 0 then
							sBone.fAnimScale:SetValue(moho.layerFrame + self.interval, self.multiBoneScaleSBValuesNList[i])
						end
						self.multiBoneScaleBakedList[i] = true
					end
				end
			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 self.multiTransform and self.keepSelection then
			for i=1, #self.selectedBonesList do
				local sBone = skel:Bone(self.selectedBonesList[i])
				local newSelectedScale = (sBone.fTempScale * secondDelta) - self.multiBoneScaleDeltaList[i]
				if not self:IsEqual(newSelectedScale, sBone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then
					sBone.fAnimScale:SetValue(moho.layerFrame, newSelectedScale)
					if self.bakeAdjacentFrames and not self.multiBoneScaleBakedList[i] then
						if moho.layerFrame - self.interval > 0 then
							sBone.fAnimScale:SetValue(moho.layerFrame - self.interval, self.multiBoneScaleSBValuesPList[i])
						end
						if moho.layerFrame + self.interval > 0 then
							sBone.fAnimScale:SetValue(moho.layerFrame + self.interval, self.multiBoneScaleSBValuesNList[i])
						end
						self.multiBoneScaleBakedList[i] = true
					end
				end
			end
		end
		if self.multiTransform and self.keepSelection and self.selBones == 1 or not (self.multiTransform and self.keepSelection) then
			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
	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 not (self.multiTransform and self.keepSelection and self.selBones > 1) then
		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
	end
	
	self:AdjustFollowAndLockBones(moho)
	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) - self.secondBoneSecondDelta)
		
		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) - self.parentBonesScaleDelta[i])
			if not self:IsEqual(parentBone.fTempAngle, parentBone.fAnimAngle:GetValue(moho.layerFrame), 0.0000001) then
				parentBone.fAnimAngle:SetValue(moho.layerFrame, parentBone.fTempAngle)
			end	
		end	
		if not self:IsEqual(bone.fTempAngle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.0000001) 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.0000001) 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
	
	self:AdjustFollowAndLockBones(moho)
	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.twosMode then
		if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0) then
			return
		end
	end
	
	self.dragging = false
	local skel = moho:Skeleton()
	if skel == nil or frame == 0 then
		return
	end
	
	if self.showIcons or self.showIcons2 then
		return
	end

	if self.lockHandlesSelection and self.isLockHandleMouseMoved then
		return
	end
	self.isLockHandleMouseMoved = false

	if self.multiSelectionUnselectedMovement then
		self.mousePickedID = -1
	end
	self.multiSelectionUnselectedMovement = false

	if not self.isMouseDragging then
		if not self.isMouseMoved or (self.lockHandlesSelection and not (self.multiTransform and self.keepSelection)) then
			if mouseEvent.shiftKey or mouseEvent.altKey then
				skel:SelectNone()
				for i, id in ipairs(self.selectedBonesList) do
					local sBone = skel:Bone(id)
					if sBone then
						sBone.fSelected = true
					end
				end
			end
			
			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
			
			local pickWidth = self.pickWidth
			
			local 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
				id = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance)
			end
			
			if not mouseEvent.shiftKey and not mouseEvent.altKey then
				skel:SelectNone()
			end	
			if id ~= -1 then
				skel:Bone(id).fSelected = not mouseEvent.altKey
			end
			if self.bonesReset then
				skel:SelectNone()
				for i, boneID in ipairs(self.selectedBonesList) do
					local bone = skel:Bone(boneID)
					bone.fSelected = true
				end
			end
			self.bonesReset = false
			return
		end
	end
	self.isMouseMoved = false
	self.lockHandlesSelection = false
	if self.isMouseDragging then
		local v = LM.Vector2:new_local()
		local screenPt = LM.Point:new_local()
		local m = LM.Matrix:new_local()
		
		self.selRect:Normalize()
		moho.layer:GetFullTransform(moho.frame, m, moho.document)
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			local boneMatrix = bone.fMovedMatrix
			for j = 0, 10 do
				v:Set(bone.fLength * j / 10.0, 0)
				boneMatrix:Transform(v)
				m:Transform(v)
				mouseEvent.view:Graphics():WorldToScreen(v, screenPt)
				if (self.selRect:Contains(screenPt)) then
					if (mouseEvent.altKey) then
						bone.fSelected = false
					else
						bone.fSelected = true
					end
					break
				end
			end
		end
		self.isMouseDragging = false
		if self.bonesReset then
			skel:SelectNone()
			for i, boneID in ipairs(self.selectedBonesList) do
				local bone = skel:Bone(boneID)
				bone.fSelected = true
			end
		end
		self.bonesReset = false
		moho:UpdateSelectedChannels()
		return
	end

	if self.isActive == false then
		if self.bonesReset then
			skel:SelectNone()
			for i, boneID in ipairs(self.selectedBonesList) do
				local bone = skel:Bone(boneID)
				bone.fSelected = true
			end
		end
		moho:UpdateSelectedChannels()
		self.bonesReset = false
		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
	
	self.firstBoneID = -1
	self.firstBoneParentID = -1
	self.firstBoneParentIBIK = -1
	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()
	mouseEvent.view:DrawMe()
	moho:UpdateSelectedChannels()
	moho:UpdateUI()
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

	if self.isMouseDragging then
		local g = view:Graphics()
		g:SelectionRect(self.selRect)
		g:Pop()
		return
	end

	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
	
	local colorFollowBones = LM.rgb_color:new_local()
	colorFollowBones.r = self.colorFollowBonesR
	colorFollowBones.g = self.colorFollowBonesG
	colorFollowBones.b = self.colorFollowBonesB
	colorFollowBones.a = self.colorFollowBonesA
		
	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 iconColorBack = LM.rgb_color:new_local()
	iconColorBack.r = 255
	iconColorBack.g = 255
	iconColorBack.b = 255
	iconColorBack.a = 255
	
	local iconColor = LM.rgb_color:new_local()
	iconColor.r = self.iconColorR
	iconColor.g = self.iconColorG
	iconColor.b = self.iconColorB
	iconColor.a = self.iconColorA
	
	local disabledIconColor = LM.rgb_color:new_local()
	disabledIconColor.r = (self.iconColorR + iconColorBack.r) / 2
	disabledIconColor.g = (self.iconColorG + iconColorBack.g) / 2
	disabledIconColor.b = (self.iconColorB + iconColorBack.b) / 2
	disabledIconColor.a = (self.iconColorA + iconColorBack.a) / 2
	
	local iconHowerColor = LM.rgb_color:new_local()
	iconHowerColor.r = (self.iconColorR * 3 + iconColorBack.r) / 4 
	iconHowerColor.g = (self.iconColorG * 3 + iconColorBack.g) / 4
	iconHowerColor.b = (self.iconColorB * 3 + iconColorBack.b) / 4
	iconHowerColor.a = (self.iconColorA * 3 + iconColorBack.a) / 4
	
	local lockAngleColor = LM.rgb_color:new_local()
	lockAngleColor.r = 255
	lockAngleColor.g = 68 
	lockAngleColor.b = 68 
	lockAngleColor.a = 255
	
	local lockPosColor = LM.rgb_color:new_local()
	lockPosColor.r = 255
	lockPosColor.g = 192
	lockPosColor.b = 0  
	lockPosColor.a = 255
	
	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)

	local isFollowBonesSelected = false
	for i=1, #self.followBonesList do
		local followBone = skel:Bone(self.followBonesList[i])
		if followBone.fSelected then
			isFollowBonesSelected = true
			break
		end
	end

	if #self.lockAngleList > 0 then
		g:SetPenWidth(10)
		g:SetColor(255, 241, 229, 255)
		local radius = 14
		
		for b=1, #self.lockAngleList do
			local lockBone = skel:Bone(self.lockAngleList[b])
			if lockBone then
				local lockBoneCenter = LM.Vector2:new_local()
				local lockBoneTip = LM.Vector2:new_local()
				lockBoneCenter:Set(0, 0)
				lockBoneTip:Set(lockBone.fLength / 3, 0)
				lockBone.fMovedMatrix:Transform(lockBoneCenter)
				lockBone.fMovedMatrix:Transform(lockBoneTip)
				if not lockBone:IsZeroLength() then
					g:DrawLine(lockBoneCenter.x, lockBoneCenter.y, lockBoneTip.x, lockBoneTip.y)
				end
			end
		end
		
		g:SetPenWidth(4)
		g:SetColor(lockAngleColor)
		
		for b=1, #self.lockAngleList do
			local lockBone = skel:Bone(self.lockAngleList[b])
			if lockBone then
				local lockBoneCenter = LM.Vector2:new_local()
				local lockBoneTip = LM.Vector2:new_local()
				lockBoneCenter:Set(0, 0)
				lockBoneTip:Set(lockBone.fLength / 3, 0)
				lockBone.fMovedMatrix:Transform(lockBoneCenter)
				lockBone.fMovedMatrix:Transform(lockBoneTip)
				if lockBone:IsZeroLength() then
					g:SetColor(lockAngleColor)
					g:FillCirclePixelRadius(lockBoneCenter, radius)
					g:SetColor(iconColorBack)
					g:FrameCirclePixelRadius(lockBoneCenter, radius)
					g:SetColor(lockAngleColor)
				else
					g:DrawLine(lockBoneCenter.x, lockBoneCenter.y, lockBoneTip.x, lockBoneTip.y)
				end
			end
		end
		g:SetPenWidth(1)
	end
	
	if #self.lockPosList > 0 then
		g:SetPenWidth(10)
		g:SetColor(iconColorBack)
		local radius = 10
		
		for b=1, #self.lockPosList do
			local lockBone = skel:Bone(self.lockPosList[b])
			if lockBone then
				local lockBoneCenter = LM.Vector2:new_local()
				local lockBoneTip = LM.Vector2:new_local()
				lockBoneCenter:Set(lockBone.fLength, 0)
				lockBoneTip:Set(lockBone.fLength / 1.5, 0)
				lockBone.fMovedMatrix:Transform(lockBoneCenter)
				lockBone.fMovedMatrix:Transform(lockBoneTip)
				if not lockBone:IsZeroLength() then
					g:DrawLine(lockBoneCenter.x, lockBoneCenter.y, lockBoneTip.x, lockBoneTip.y)
				end
			end
		end
		
		g:SetPenWidth(4)
		g:SetColor(lockPosColor)
		
		for b=1, #self.lockPosList do
			local lockBone = skel:Bone(self.lockPosList[b])
			if lockBone then
				local lockBoneCenter = LM.Vector2:new_local()
				local lockBoneTip = LM.Vector2:new_local()
				lockBoneCenter:Set(lockBone.fLength, 0)
				lockBoneTip:Set(lockBone.fLength / 1.5, 0)
				lockBone.fMovedMatrix:Transform(lockBoneCenter)
				lockBone.fMovedMatrix:Transform(lockBoneTip)
				if lockBone:IsZeroLength() then
					g:SetColor(lockPosColor)
					g:FrameCirclePixelRadius(lockBoneCenter, radius)
				else
					g:DrawLine(lockBoneCenter.x, lockBoneCenter.y, lockBoneTip.x, lockBoneTip.y)
				end
			end
		end
		g:SetPenWidth(1)
	end

	if not isFollowBonesSelected or self.forceFollowBonesGraphics then
		if #self.followBonesList.id > 0 then
			for b=1, #self.followBonesList.id do
				local isBlocked = false
				if self.dragging then
					if self.followBonesDataList.block then
						isBlocked = self.followBonesDataList.block[b]
					end
				end

				if not isBlocked then
					g:SetPenWidth(2)
					g:SetColor(colorFollowBones)
					for i=1, #self.followBonesList.id[b] do
						local followBone = skel:Bone(self.followBonesList.id[b][i])
						if i + 1 <= #self.followBonesList.id[b] then
							if followBone then
								local nextBone = skel:Bone(self.followBonesList.id[b][i + 1])
								if nextBone then
									local followBoneCenter = LM.Vector2:new_local()
									local nextBoneCenter = LM.Vector2:new_local()
									followBoneCenter:Set(followBone.fLength / 2, 0)
									nextBoneCenter:Set(nextBone.fLength / 2, 0)
									followBone.fMovedMatrix:Transform(followBoneCenter)
									nextBone.fMovedMatrix:Transform(nextBoneCenter)
									g:DrawLine(followBoneCenter.x, followBoneCenter.y, nextBoneCenter.x, nextBoneCenter.y)
								end
							end
						end
					end
					g:SetPenWidth(1)
				end
			end

			for b=1, #self.followBonesList.id do
				local isBlocked = false
				if self.dragging then
					if self.followBonesDataList.block then
						isBlocked = self.followBonesDataList.block[b]
					end
				end
				if not isBlocked then
					g:SetPenWidth(10)
					g:SetColor(196, 235, 255, 255)
					for i=1, #self.followBonesList.id[b] do
						local followBone = skel:Bone(self.followBonesList.id[b][i])
						if followBone then
							local followBoneCenter = LM.Vector2:new_local()
							local followBoneTip = LM.Vector2:new_local()
							followBoneCenter:Set(followBone.fLength / 1.5, 0)
							followBoneTip:Set(followBone.fLength / 3, 0)
							followBone.fMovedMatrix:Transform(followBoneCenter)
							followBone.fMovedMatrix:Transform(followBoneTip)
							g:DrawLine(followBoneCenter.x, followBoneCenter.y, followBoneTip.x, followBoneTip.y)
						end
					end
					g:SetPenWidth(4)
					g:SetColor(colorFollowBones)
					for i=1, #self.followBonesList.id[b] do
						local followBone = skel:Bone(self.followBonesList.id[b][i])
						if followBone then
							local followBoneCenter = LM.Vector2:new_local()
							local followBoneTip = LM.Vector2:new_local()
							followBoneCenter:Set(followBone.fLength / 1.5, 0)
							followBoneTip:Set(followBone.fLength / 3, 0)
							followBone.fMovedMatrix:Transform(followBoneCenter)
							followBone.fMovedMatrix:Transform(followBoneTip)
							g:DrawLine(followBoneCenter.x, followBoneCenter.y, followBoneTip.x, followBoneTip.y)
						end
					end
					if self.dragging then
						g:SetColor(colorHighlightBone)
						g:SetPenWidth(3)
						local markersSize = (0.015) / currentScale / height
						local marker1VecCam = self.followBonesDataList.targetPos[b]
						g:DrawLine(marker1VecCam.x - markersSize, marker1VecCam.y, marker1VecCam.x + markersSize, marker1VecCam.y)
						g:DrawLine(marker1VecCam.x, marker1VecCam.y - markersSize, marker1VecCam.x, marker1VecCam.y + markersSize)
					elseif self.showCross then
						if MR_TweenMachine and MR_TweenMachine.followBonesDataList.targetPos[b] then 
							g:SetColor(colorHighlightBone)
							g:SetPenWidth(3)
							local markersSize = (0.015) / currentScale / height
							local marker1VecCam = MR_TweenMachine.followBonesDataList.targetPos[b]
							g:DrawLine(marker1VecCam.x - markersSize, marker1VecCam.y, marker1VecCam.x + markersSize, marker1VecCam.y)
							g:DrawLine(marker1VecCam.x, marker1VecCam.y - markersSize, marker1VecCam.x, marker1VecCam.y + markersSize)
						end
					end
					g:SetPenWidth(1)
				end
			end
		end
	end
	
	if self.mousePickedID > -1 and not (self.dragging or moho:IsPlaying()) and not self.showIcons 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()
	
	if self.showIcons then
		local m = LM.Matrix:new_local()
		moho.document:GetCameraMatrix(moho.layerFrame, m)
		g:Push()
		currentScale = g:CurrentScale(false)
		height = g:Height() / moho.document:Height()
		height = g:Height() / self.height
		local offset = self.iconsDistance / currentScale / height
		local center = LM.Vector2:new_local()
		center:Set(self.graphicsMenuCenter)
		local radius = self.iconsRadius
		local howerRadius = 1.1
		local shadowOffset = LM.Vector2:new_local()
		shadowOffset:Set(0.005 / currentScale / height, -0.01 / currentScale / height)
		local v = LM.Vector2:new_local()
		local v1 = LM.Vector2:new_local()
		local v2 = LM.Vector2:new_local()
		local tooltipSizeH = 0.35 / currentScale / height
		local tooltipSizeV = 0.05 / currentScale / height
		local tooltipTextOffsetH = 0.033 / currentScale / height
		local tooltipTextOffsetV = 0.011 / currentScale / height
		local tooltipTextSize = 3 / currentScale / height
		
		-- set follow bones icon
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(30)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 1 then
			tooltipSizeH = 0.375 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.033 / currentScale / height
			tooltipTextOffsetV = 0.011 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x - tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x - tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x - tooltipSizeH + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Set follow bones'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		if self.graphicMenuMode == 1 then
			radius = self.iconsRadius * howerRadius
		else
			radius = self.iconsRadius
		end
		
		g:SetColor(0, 0, 0, 75)		
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		if self.graphicMenuMode == 1 then
			g:SetColor(iconHowerColor)
		else
			g:SetColor(iconColor)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		g:SetColor(iconColor)
		local arrowLen = 0.012 / currentScale / height
		local arrowWidth = 0.012 / currentScale / height
		
		local iconCenter = LM.Vector2:new_local()
		local offsetCenter = -0.01 / currentScale / height
		iconCenter:Set(v.x + offsetCenter, v.y)
		g:BeginShape()
		v1:Set(iconCenter.x - arrowLen, iconCenter.y + arrowWidth)
		v2:Set(iconCenter.x + arrowLen, iconCenter.y + arrowWidth)
		v1:Set(self:RotateVector2(moho, v1, v, math.rad(45)))
		v2:Set(self:RotateVector2(moho, v2, v, math.rad(45)))
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x + arrowLen, iconCenter.y + arrowWidth * 2.0)
		v2:Set(self:RotateVector2(moho, v2, v, math.rad(45)))
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x + arrowLen + arrowWidth * 2.0, iconCenter.y)
		v2:Set(self:RotateVector2(moho, v2, v, math.rad(45)))
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x + arrowLen, iconCenter.y - (arrowWidth * 2.0))
		v2:Set(self:RotateVector2(moho, v2, v, math.rad(45)))
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x + arrowLen, iconCenter.y - arrowWidth)
		v2:Set(self:RotateVector2(moho, v2, v, math.rad(45)))
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x-arrowLen, iconCenter.y - arrowWidth )
		v2:Set(self:RotateVector2(moho, v2, v, math.rad(45)))
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x - arrowLen, iconCenter.y + arrowWidth)
		v2:Set(self:RotateVector2(moho, v2, v, math.rad(45)))
		g:AddLine(v1, v2)
		g:EndShape()
		
		-- scale follow bones icon
		if self.graphicMenuMode == 2 then
			radius = self.iconsRadius * howerRadius
		else
			radius = self.iconsRadius
		end
		
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(90)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 2 then
			tooltipSizeH = 0.424 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.033 / currentScale / height
			tooltipTextOffsetV = 0.011 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x - tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x - tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x - tooltipSizeH + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Scale follow bones'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 2 then
			g:SetColor(iconHowerColor)
		else
			g:SetColor(iconColor)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		if self.scaleFollowBones then
			g:SetColor(iconColor)
		else
			g:SetColor(disabledIconColor)
		end
		
		offsetCenter = -0.0025 / currentScale / height
		iconCenter:Set(v.x + offsetCenter, v.y - offsetCenter)
		local boxSize = 0.015 / currentScale / height
		g:SetPenWidth(2)

		v1:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		v2:Set(iconCenter.x + boxSize, iconCenter.y + boxSize)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(iconCenter.x + boxSize, iconCenter.y - boxSize)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y - boxSize)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		offsetCenter = 0.01 / currentScale / height
		iconCenter:Set(v.x + offsetCenter, v.y - offsetCenter)
		local boxSize = 0.008 / currentScale / height
		
		g:SetColor(iconColorBack)
		g:BeginShape()
		v1:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		v2:Set(iconCenter.x + boxSize, iconCenter.y + boxSize)
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x + boxSize, iconCenter.y - boxSize)
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y - boxSize)
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		g:AddLine(v1, v2)
		g:EndShape()
		
		if self.scaleFollowBones then
			g:SetColor(iconColor)
		else
			g:SetColor(disabledIconColor)
		end
		v1:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		v2:Set(iconCenter.x + boxSize, iconCenter.y + boxSize)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(iconCenter.x + boxSize, iconCenter.y - boxSize)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y - boxSize)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		-- lock angle icon
		if self.graphicMenuMode == 3 then
			radius = self.iconsRadius * howerRadius
		else
			radius = self.iconsRadius
		end
		
		g:SetPenWidth(3)
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(-30)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 3 then
			tooltipSizeH = 0.275 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.0735 / currentScale / height
			tooltipTextOffsetV = 0.012 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x + tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x + tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Lock angle'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		shadowOffset:Set(-0.005 / currentScale / height, -0.01 / currentScale / height)
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 3 then
			g:SetColor(iconHowerColor)
		else
			g:SetColor(iconColor)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		g:SetColor(iconColor)
		
		offsetCenter = 0.005 / currentScale / height
		iconCenter:Set(v.x, v.y - offsetCenter)
		local boxSize = 0.015 / currentScale / height
		
		g:BeginShape()
		v1:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		v2:Set(iconCenter.x + boxSize, iconCenter.y + boxSize)
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x + boxSize, iconCenter.y - boxSize)
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y - boxSize)
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		g:AddLine(v1, v2)
		g:EndShape()
		
		g:SetPenWidth(2)
		v1:Set((iconCenter.x - boxSize) - ((iconCenter.x - boxSize) - iconCenter.x)/3, iconCenter.y + boxSize + (0.0025 / currentScale / height))
		v2:Set(v1.x, v1.y + 0.01 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set((iconCenter.x + boxSize) + ((iconCenter.x - boxSize) - iconCenter.x)/3, v2.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(v1.x, iconCenter.y + boxSize + (0.0025 / currentScale / height))
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)

		local symbolWidth = 0.007 / currentScale / height
		local symbolHeight = 0.01 / currentScale / height
		g:SetColor(iconColorBack)
		v1:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolHeight)
		v2:Set(iconCenter.x, iconCenter.y + symbolHeight)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(iconCenter.x + symbolWidth, iconCenter.y - symbolHeight)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(iconCenter.x - symbolWidth / 2, iconCenter.y - symbolHeight / 2)
		v2:Set(iconCenter.x + symbolWidth / 2, iconCenter.y - symbolHeight / 2)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		-- lock pos icon
		if self.graphicMenuMode == 4 then
			radius = self.iconsRadius * howerRadius
		else
			radius = self.iconsRadius
		end
		
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(-90)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 4 then
			tooltipSizeH = 0.318 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.072 / currentScale / height
			tooltipTextOffsetV = 0.012 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x + tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x + tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Lock position'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 4 then
			g:SetColor(iconHowerColor)
		else
			g:SetColor(iconColor)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		g:SetColor(iconColor)
		
		offsetCenter = 0.005 / currentScale / height
		iconCenter:Set(v.x, v.y - offsetCenter)
		local boxSize = 0.015 / currentScale / height
		
		g:BeginShape()
		v1:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		v2:Set(iconCenter.x + boxSize, iconCenter.y + boxSize)
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x + boxSize, iconCenter.y - boxSize)
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y - boxSize)
		g:AddLine(v1, v2)
		v1:Set(v2)
		v2:Set(iconCenter.x - boxSize, iconCenter.y + boxSize)
		g:AddLine(v1, v2)
		g:EndShape()
		
		g:SetPenWidth(2)
		v1:Set((iconCenter.x - boxSize) - ((iconCenter.x - boxSize) - iconCenter.x)/3, iconCenter.y + boxSize + (0.0025 / currentScale / height))
		v2:Set(v1.x, v1.y + 0.01 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set((iconCenter.x + boxSize) + ((iconCenter.x - boxSize) - iconCenter.x)/3, v2.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(v1.x, iconCenter.y + boxSize + (0.0025 / currentScale / height))
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)

		local symbolWidth = 0.007 / currentScale / height
		local symbolHeight = 0.008 / currentScale / height
		g:SetColor(iconColorBack)
		v1:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolHeight)
		v2:Set(iconCenter.x - symbolWidth, iconCenter.y + symbolHeight)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(iconCenter.x + symbolWidth, v2.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(v2.x, v2.y - symbolHeight)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(v2)
		v2:Set(iconCenter.x - symbolWidth, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		-- clear icon
		if self.graphicMenuMode == 5 then
			radius = self.iconsRadius * howerRadius
		else
			radius = self.iconsRadius
		end
		
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(210)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 5 then
			tooltipSizeH = 0.35 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.072 / currentScale / height
			tooltipTextOffsetV = 0.012 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x + tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x + tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Clear selection'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		shadowOffset:Set(-0.005 / currentScale / height, -0.01 / currentScale / height)
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 5 then
			g:SetColor(iconHowerColor)
		else
			g:SetColor(iconColor)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		g:SetColor(iconColor)
		
		offsetCenter = 0.005 / currentScale / height
		iconCenter:Set(v.x, v.y)
		
		local symbolWidth = 0.008 / currentScale / height
		local symbolHeight = 0.008 / currentScale / height
		v1:Set(iconCenter.x - symbolWidth, iconCenter.y + symbolHeight)
		v2:Set(iconCenter.x + symbolWidth, iconCenter.y - symbolHeight)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolHeight)
		v2:Set(iconCenter.x + symbolWidth, iconCenter.y + symbolHeight)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		-- clear all icon
		if self.graphicMenuMode == 6 then
			radius = self.iconsRadius * howerRadius
		else
			radius = self.iconsRadius
		end
		
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(150)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 6 then
			tooltipSizeH = 0.22 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.033 / currentScale / height
			tooltipTextOffsetV = 0.011 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x - tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x - tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x - tooltipSizeH + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Clear all'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		shadowOffset:Set(0.005 / currentScale / height, -0.01 / currentScale / height)
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 6 then
			g:SetColor(iconHowerColor)
		else
			g:SetColor(iconColor)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		g:SetColor(iconColor)
		
		offsetCenter = 0.005 / currentScale / height
		iconCenter:Set(v.x, v.y)
		
		local symbolWidth = 0.015 / currentScale / height
		local symbolHeight = 0.015 / currentScale / height
		v1:Set(iconCenter.x - symbolWidth, iconCenter.y + symbolHeight)
		v2:Set(iconCenter.x + symbolWidth, iconCenter.y - symbolHeight)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		v1:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolHeight)
		v2:Set(iconCenter.x + symbolWidth, iconCenter.y + symbolHeight)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		g:Pop()
	end
	
	if self.showIcons2 then
		local m = LM.Matrix:new_local()
		moho.document:GetCameraMatrix(moho.layerFrame, m)
		g:Push()
		currentScale = g:CurrentScale(false)
		height = g:Height() / moho.document:Height()
		height = g:Height() / self.height
		local offset = self.iconsDistance * 1.05 / currentScale / height
		local center = LM.Vector2:new_local()
		center:Set(self.graphicsMenuCenter)
		local radius = self.iconsRadius
		local radiusMultiplier = 1.1
		local howerRadius = 1.1
		local shadowOffset = LM.Vector2:new_local()
		shadowOffset:Set(0.005 / currentScale / height, -0.01 / currentScale / height)
		local v = LM.Vector2:new_local()
		local v1 = LM.Vector2:new_local()
		local v2 = LM.Vector2:new_local()
		local tooltipSizeH = 0.35 / currentScale / height
		local tooltipSizeV = 0.05 / currentScale / height
		local tooltipTextOffsetH = 0.033 / currentScale / height
		local tooltipTextOffsetV = 0.011 / currentScale / height
		local tooltipTextSize = 3 / currentScale / height
		
		
		-- Multi Transform icon
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(30)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 1 then
			tooltipSizeH = 0.34 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.033 / currentScale / height
			tooltipTextOffsetV = 0.011 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x - tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x - tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x - tooltipSizeH + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Multi transform'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		if self.graphicMenuMode == 1 then
			radius = self.iconsRadius * radiusMultiplier * howerRadius
		else
			radius = self.iconsRadius * radiusMultiplier
		end
		
		local arrowLen = 0.012 / currentScale / height
		local arrowWidth = 0.012 / currentScale / height
		
		local iconCenter = LM.Vector2:new_local()
		iconCenter:Set(v.x - 0.0011 / currentScale / height, v.y + 0.003 / currentScale / height)
		
		g:SetColor(0, 0, 0, 75)		
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		if self.graphicMenuMode == 1 then
			g:SetColor(255, 222, 120, 255)
		else
			g:SetColor(255, 195, 52, 255)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		
		if self.multiTransform and self.keepSelection then
			g:SetColor(iconColor)
		else
			g:SetColor(disabledIconColor)
		end
		
		g:SetPenWidth(2)
		
		v1:Set(iconCenter.x - 0.015 / currentScale / height, iconCenter.y - 0.015 / currentScale / height)
		v2:Set(v1.x, v1.y + 0.022 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x + 0.007 / currentScale / height, v1.y - 0.012 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x + 0.007 / currentScale / height, v1.y + 0.012 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, iconCenter.y - 0.015 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)

		v1:Set(iconCenter.x + 0.012 / currentScale / height, iconCenter.y - 0.015 / currentScale / height)
		v2:Set(v1.x, v1.y + 0.02 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2.x - 0.007 / currentScale / height, v2.y)
		v2:Set(v2.x + 0.007 / currentScale / height, v2.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)

		-- Keep Selection icon
		if self.graphicMenuMode == 2 then
			radius = self.iconsRadius * radiusMultiplier * howerRadius
		else
			radius = self.iconsRadius * radiusMultiplier
		end
		
		
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(90)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 2 then
			tooltipSizeH = 0.35 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.033 / currentScale / height
			tooltipTextOffsetV = 0.011 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x - tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x - tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x - tooltipSizeH + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Keep selection'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 2 then
			g:SetColor(70, 148, 255, 255)
		else
			g:SetColor(14, 116, 255, 255)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		if self.keepSelection then
			g:SetColor(iconColor)
		else
			g:SetColor(disabledIconColor)
		end
		
		iconCenter:Set(v.x + 0.0012 / currentScale / height, v.y + 0.003 / currentScale / height)
		
		g:SetPenWidth(2)

		v1:Set(iconCenter.x - 0.015 / currentScale / height, iconCenter.y - 0.015 / currentScale / height)
		v2:Set(v1.x, v1.y + 0.022 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2.x, iconCenter.y - 0.005 / currentScale / height)
		v2:Set(v1.x + 0.01 / currentScale / height , v1.y + 0.0105 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v1.x, iconCenter.y - 0.005 / currentScale / height)
		v2:Set(v1.x + 0.01 / currentScale / height , v1.y - 0.009 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(iconCenter.x + 0.001 / currentScale / height, iconCenter.y - 0.013 / currentScale / height)
		v2:Set(v1.x  + 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, v1.y + 0.009 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x - 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, v1.y + 0.009 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x + 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		-- lock Handle icon
		if self.graphicMenuMode == 3 then
			radius = self.iconsRadius * radiusMultiplier * howerRadius
		else
			radius = self.iconsRadius * radiusMultiplier
		end
		
		g:SetPenWidth(3)
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(-30)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 3 then
			tooltipSizeH = 0.325 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.0735 / currentScale / height
			tooltipTextOffsetV = 0.012 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x + tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x + tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Lock handles'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		shadowOffset:Set(-0.005 / currentScale / height, -0.01 / currentScale / height)
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 3 then
			g:SetColor(45, 243, 54, 255)
		else
			g:SetColor(19, 223, 29, 255)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		if self.lockHandles then
			g:SetColor(iconColor)
		else
			g:SetColor(disabledIconColor)
		end
		
		iconCenter:Set(v.x - 0.0007 / currentScale / height, v.y + 0.003 / currentScale / height)
		
		g:SetPenWidth(2)
		
		v1:Set(iconCenter.x - 0.0145 / currentScale / height, iconCenter.y + 0.007 / currentScale / height)
		v2:Set(v1.x, iconCenter.y - 0.013 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x + 0.010 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
	
		v1:Set(iconCenter.x + 0.0013 / currentScale / height, iconCenter.y + 0.007 / currentScale / height)
		v2:Set(v1.x, iconCenter.y - 0.015 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2.x, iconCenter.y - 0.0035 / currentScale / height)
		v2:Set(v1.x + 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2.x, iconCenter.y + 0.007 / currentScale / height)
		v2:Set(v1.x, iconCenter.y - 0.015 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		-- Smart Bake icon
		if self.graphicMenuMode == 4 then
			radius = self.iconsRadius * radiusMultiplier * howerRadius
		else
			radius = self.iconsRadius * radiusMultiplier
		end
		
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(-90)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 4 then
			tooltipSizeH = 0.27 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.072 / currentScale / height
			tooltipTextOffsetV = 0.012 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x + tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x + tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Bake Adjacent Frames'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 4 then
			g:SetColor(211, 94, 255, 255)
		else
			g:SetColor(202, 60, 255, 255)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		if self.bakeAdjacentFrames then
			g:SetColor(iconColor)
		else
			g:SetColor(disabledIconColor)
		end
		
		iconCenter:Set(v.x + 0.0008 / currentScale / height, v.y + 0.003 / currentScale / height)
		
		g:SetPenWidth(2)
		
		v1:Set(iconCenter.x - 0.015 / currentScale / height, iconCenter.y - 0.013 / currentScale / height)
		v2:Set(v1.x + 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, v1.y + 0.009 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x - 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, v1.y + 0.009 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x + 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)

		v1:Set(iconCenter.x + 0.0045 / currentScale / height, iconCenter.y - 0.0126 / currentScale / height)
		v2:Set(v1.x, v1.y + 0.020 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2.x, v2.y - 0.001 / currentScale / height)
		v2:Set(v1.x + 0.008 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v2.x + 0.001 / currentScale / height, v2.y - 0.001 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, v1.y - 0.0075 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x - 0.001 / currentScale / height, v1.y - 0.001 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x - 0.010 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2.x + 0.011 / currentScale / height, v2.y)
		v2:Set(v1.x, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v2.x + 0.001 / currentScale / height, v2.y - 0.001 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, v1.y - 0.008 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x - 0.001 / currentScale / height, v1.y - 0.001 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x - 0.010 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		-- Show Path icon
		if self.graphicMenuMode == 5 then
			radius = self.iconsRadius * radiusMultiplier * howerRadius
		else
			radius = self.iconsRadius * radiusMultiplier
		end
		
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(210)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 5 then
			tooltipSizeH = 0.256 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.072 / currentScale / height
			tooltipTextOffsetV = 0.012 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x + tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x + tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Show path'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		shadowOffset:Set(-0.005 / currentScale / height, -0.01 / currentScale / height)
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 5 then
			g:SetColor(86, 225, 255, 255)
		else
			g:SetColor(27, 203, 241, 255)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		if self.showPath then
			g:SetColor(iconColor)
		else
			g:SetColor(disabledIconColor)
		end
		
		iconCenter:Set(v.x + 0.00045 / currentScale / height, v.y + 0.003 / currentScale / height)
		
		g:SetPenWidth(2)
		
		v1:Set(iconCenter.x - 0.015 / currentScale / height, iconCenter.y - 0.013 / currentScale / height)
		v2:Set(v1.x + 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, v1.y + 0.009 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x - 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, v1.y + 0.009 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x + 0.012 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(iconCenter.x + 0.0045 / currentScale / height, iconCenter.y - 0.014 / currentScale / height)
		v2:Set(v1.x, v1.y + 0.021 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2.x, v2.y - 0.001 / currentScale / height)
		v2:Set(v1.x + 0.01 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v2.x + 0.001 / currentScale / height, v2.y - 0.001 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, v1.y - 0.0075 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x - 0.001 / currentScale / height, v1.y - 0.001 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x - 0.010 / currentScale / height, v1.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		-- Twos Mode icon
		if self.graphicMenuMode == 6 then
			radius = self.iconsRadius * radiusMultiplier * howerRadius
		else
			radius = self.iconsRadius * radiusMultiplier
		end
		
		v:Set(center.x, center.y + offset)
		v:Set(self:RotateVector2(moho, v, center, math.rad(150)))
		
		if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 6 then
			tooltipSizeH = 0.275 / currentScale / height
			tooltipSizeV = 0.05 / currentScale / height
			tooltipTextOffsetH = 0.033 / currentScale / height
			tooltipTextOffsetV = 0.011 / currentScale / height
			tooltipTextSize = 3 / currentScale / height
			
			g:SetPenWidth(1)
			g:SetColor(255, 255, 255, 255)	
			g:BeginShape()
			v1:Set(v.x - tooltipSizeH, v.y - tooltipSizeV / 2)
			v2:Set(v.x, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y + tooltipSizeV)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x - tooltipSizeH, v1.y)
			g:AddLine(v1, v2)
			v1:Set(v2)
			v2:Set(v1.x, v1.y -tooltipSizeV)
			g:AddLine(v1, v2)
			g:EndShape()
			
			g:SetColor(0, 0, 0, 255)	
			v1:Set(v.x - tooltipSizeH + tooltipTextOffsetH, v.y - tooltipSizeV / 2 + tooltipTextOffsetV)
			
			HV_Font:DrawLetters(moho, g, self:Localize('Twos mode'), tooltipTextSize, v1.x, v1.y, 0, 0)
		end
		
		g:SetColor(0, 0, 0, 75)		
		shadowOffset:Set(0.005 / currentScale / height, -0.01 / currentScale / height)
		g:FillCirclePixelRadius(v + shadowOffset, radius)
		g:SetColor(iconColorBack)		
		g:FillCirclePixelRadius(v, radius)
		g:SetPenWidth(3)
		
		if self.graphicMenuMode == 6 then
			g:SetColor(255, 100, 100, 255)
		else
			g:SetColor(255, 70, 70, 255)
		end
		
		g:FrameCirclePixelRadius(v, radius)
		if self.twosMode then
			g:SetColor(iconColor)
		else
			g:SetColor(disabledIconColor)
		end
		
		iconCenter:Set(v.x + 0.0018 / currentScale / height, v.y + 0.003 / currentScale / height)
		
		g:SetPenWidth(2)

		v1:Set(iconCenter.x - 0.015 / currentScale / height, iconCenter.y - 0.015 / currentScale / height)
		v2:Set(v1.x, v1.y + 0.02 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2.x - 0.007 / currentScale / height, v2.y)
		v2:Set(v2.x + 0.007 / currentScale / height, v2.y)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(iconCenter.x - 0.002 / currentScale / height, iconCenter.y - 0.015 / currentScale / height)
		v2:Set(v1.x, v1.y + 0.022 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x + 0.007 / currentScale / height, v1.y - 0.012 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x + 0.007 / currentScale / height, v1.y + 0.012 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		v1:Set(v2)
		v2:Set(v1.x, iconCenter.y - 0.015 / currentScale / height)
		g:DrawLine(v1.x, v1.y, v2.x, v2.y)
		
		g:Pop()
	end
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.TWOS_MODE = MOHO.MSG_BASE
MR_PoseTool.KEEP_SELECTION = MOHO.MSG_BASE + 1
MR_PoseTool.MULTI_TRANSFORM = MOHO.MSG_BASE + 2
MR_PoseTool.LOCK_HANDLES = MOHO.MSG_BASE + 3
MR_PoseTool.BAKE_ADJACENT_FRAMES = MOHO.MSG_BASE + 4
MR_PoseTool.INTERVAL_1 = MOHO.MSG_BASE + 5
MR_PoseTool.INTERVAL_2 = MOHO.MSG_BASE + 6
MR_PoseTool.INTERVAL_3 = MOHO.MSG_BASE + 7
MR_PoseTool.INTERVAL_4 = MOHO.MSG_BASE + 8
MR_PoseTool.SHOW_PATH = MOHO.MSG_BASE + 9
MR_PoseTool.RANGE = MOHO.MSG_BASE + 10
MR_PoseTool.RANGE_FRAMES = MOHO.MSG_BASE + 11
MR_PoseTool.FLIP_H = MOHO.MSG_BASE + 12
MR_PoseTool.FLIP_V = MOHO.MSG_BASE + 13

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.twosModeCheckbox = LM.GUI.CheckBox(self:Localize('Twos mode'), self.TWOS_MODE)
    layout:AddChild(self.twosModeCheckbox, LM.GUI.ALIGN_LEFT, 0)
	
	self.keepSelectionCheckbox = LM.GUI.CheckBox(self:Localize('Keep selection'), self.KEEP_SELECTION)
    layout:AddChild(self.keepSelectionCheckbox, LM.GUI.ALIGN_LEFT, 0)
	
	self.multiTransformCheckbox = LM.GUI.CheckBox(self:Localize('Multi transform'), self.MULTI_TRANSFORM)
    layout:AddChild(self.multiTransformCheckbox, 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	
	
	self:ValidateFollowList(moho)
	
	self:ValidateLockList(moho)
	if self.followLockLayerUUID ~= moho.layer:UUID() then
		self.lockAngleList = {}
		self.lockPosList = {}
		self.lockAngleBoneNamesList = {}
		self.lockPosBoneNamesList = {}
		self.followBonesList = {}
		self.followBonesList.id = {}
		self.followBonesList.names  = {}
		self.followBonesList.startBone = {}
		self.followBonesList.endBone = {}
	end
	
	local frame = moho.frame
	
	if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0) and self.twosMode then
		moho.view:SetCursor(MOHO.disabledCursor)
	else
		moho.view:SetCursor(self.mainCursor)
	end

	self.twosModeCheckbox:SetValue(self.twosMode)
	self.keepSelectionCheckbox:SetValue(self.keepSelection)
	self.multiTransformCheckbox:SetValue(self.multiTransform)
	self.multiTransformCheckbox:Enable(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.TWOS_MODE then
        self.twosMode = self.twosModeCheckbox:Value()
	elseif msg == self.KEEP_SELECTION then
        self.keepSelection = self.keepSelectionCheckbox:Value()
		self.multiTransformCheckbox:Enable(self.keepSelection)
	elseif msg == self.MULTI_TRANSFORM then
        self.multiTransform = self.multiTransformCheckbox: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

function MR_PoseTool:AddToFollowBones(moho)
	local skel = moho:Skeleton()
	
	if skel == nil then
		return
	end

	local selectedBonesId = {}
	local selectedBonesNames = {}
	local isValid = true
	
	self:ValidateFollowList(moho)
	
	local selectedBonesList = {}
	
	for i=0, skel:CountBones()-1 do
		local bone = skel:Bone(i)
		if bone.fSelected and not bone:IsZeroLength() then
			table.insert(selectedBonesList, i)
		end
	end
	
	local followBonesChainsList = {}
	local boneParentMap = {}
	local multipleChildrenMap = {}
	local isInGroup = {}
	local selectedBonesSet = {}

	for _, id in ipairs(selectedBonesList) do
		selectedBonesSet[id] = true
	end

	for _, id in ipairs(selectedBonesList) do
		local bone = skel:Bone(id)
		local count = 0
		
		for _, childId in ipairs(selectedBonesList) do
			local childBone = skel:Bone(childId)
			if childBone then
				if childBone.fParent == id then
					count = count + 1
				end
			end
		end
		
		if count > 1 then
			multipleChildrenMap[id] = true
		end
		
		boneParentMap[id] = bone.fParent
	end
		for n, id in ipairs(multipleChildrenMap) do
			local bone = skel:Bone(id)
		end

	local function collectAncestors(boneId, group)
		local parentId = boneParentMap[boneId]
		while parentId and parentId ~= -1 and selectedBonesSet[parentId] and not isInGroup[parentId] do
			if not multipleChildrenMap[parentId] then
				table.insert(group, 1, parentId) 
				isInGroup[parentId] = true
			end
			parentId = boneParentMap[parentId]
		end
	end


	local function addDescendants(boneId, group)
		for _, childId in ipairs(selectedBonesList) do
			if boneParentMap[childId] == boneId and not isInGroup[childId] then
				if not multipleChildrenMap[boneId] then
					table.insert(group, childId)
					isInGroup[childId] = true
					addDescendants(childId, group)
				end
			end
		end
	end


	for _, boneId in ipairs(selectedBonesList) do
		if not isInGroup[boneId] then
			local group = {}

			collectAncestors(boneId, group)

			if not isInGroup[boneId] then
				table.insert(group, boneId)
				isInGroup[boneId] = true

				addDescendants(boneId, group)
			end

			if #group > 0 then
				table.insert(followBonesChainsList, group)
			end
		end
	end
	
	local followBonesChainsNamesList = {}
	
	for i, a in ipairs(followBonesChainsList) do
		local followBonesNamesList = {}
		for n, id in ipairs(followBonesChainsList[i]) do
			local bone = skel:Bone(id)
			table.insert(followBonesNamesList, bone:Name())
		end
		table.insert(followBonesChainsNamesList, followBonesNamesList)
	end
	self:RemoveSelectedBonesFromFollowList(moho)
	for c, a in ipairs(followBonesChainsList) do
		local startBone = followBonesChainsList[c][1]
		local endBone = followBonesChainsList[c][#followBonesChainsList[c]]
		
		table.insert(self.followBonesList.id, followBonesChainsList[c])
		table.insert(self.followBonesList.names, followBonesChainsNamesList[c])
		table.insert(self.followBonesList.startBone, startBone)
		table.insert(self.followBonesList.endBone, endBone)

		for _, id in ipairs(followBonesChainsList[c]) do
			local boneID = id
			local existInList = self:ValueExists(self.lockAngleList, boneID)
			if existInList then
				table.remove(self.lockAngleList, existInList)
				table.remove(self.lockAngleBoneNamesList, existInList)
			end
			existInList = self:ValueExists(self.lockPosList, boneID)
			if existInList then
				table.remove(self.lockPosList, existInList)
				table.remove(self.lockPosBoneNamesList, existInList)
			end
		end
	end
		
	self.followLockLayerUUID = moho.layer:UUID()
	self.forceFollowBonesGraphics = true
end

function MR_PoseTool:AdjustFollowBones(moho, index)
	if not self.followBonesList.id or #self.followBonesList.id < 1 then
		return
	end
	
	local skel = moho:Skeleton()
	
	if skel == nil then
		return
	end
	
	local b = index
	
	if self.followBonesDataList.block[b] then
		return
	end
	
	local startFollowBone = skel:Bone(self.followBonesList.startBone[b])
	local endFollowBone = skel:Bone(self.followBonesList.endBone[b])
	if not startFollowBone or not endFollowBone then
		return
	end
	
	moho.layer:UpdateCurFrame()

	local startBonePos = LM.Vector2:new_local()	
	startBonePos:Set(0, 0)
	
	if moho.frame == 0 then
		startFollowBone.fRestMatrix:Transform(startBonePos)
	else
		startFollowBone.fMovedMatrix:Transform(startBonePos)
	end

	if self.scaleFollowBones then
		local secondCursorDist = self:GetDistance(startBonePos, self.followBonesDataList.targetPos[b])
		local scaleFactor = (secondCursorDist / self.followBonesDataList.distance[b])
		
		for i=1, #self.followBonesList.id[b] do
			local bone = skel:Bone(self.followBonesList.id[b][i])
			local newScale = (bone.fTempScale * scaleFactor) - self.followBonesDataList.scaleDelta[b][i]
			bone.fAnimScale:SetValue(moho.layerFrame, newScale)
		end
		
		if self.bakeAdjacentFrames and not self.followBonesDataList.sBValuesBakedS[b] then
			for i, q in ipairs(self.followBonesList.id[b]) do
				local bone = skel:Bone(q)
				if moho.layerFrame - self.interval > 0 then
					bone.fAnimScale:SetValue(moho.layerFrame - self.interval, self.followBonesDataList.sBValuesP[b][i])
				end
				if moho.layerFrame + self.interval > 0 then
					bone.fAnimScale:SetValue(moho.layerFrame + self.interval, self.followBonesDataList.sBValuesN[b][i])
				end
			end	
			self.followBonesDataList.sBValuesBakedS[b] = true
		end
	end
	local bone = startFollowBone
	local center = LM.Vector2:new_local()

	center:Set(self.followBonesDataList.targetPos[b])
	local angle = self.followBonesDataList.startAngle[b]
	local v1 = self.followBonesDataList.lastVec[b] - center
	local v2 = startBonePos - center
	v2:Rotate(-math.atan2(v1.y, v1.x))
	angle = angle + math.atan2(v2.y, v2.x)
	self.followBonesDataList.startAngle[b] = angle
	self.followBonesDataList.lastVec[b] = startBonePos
	local angleSign = 1.0
	if (not bone.fFixedAngle) then
		angleSign = bone:ParentalFlipFactor()
	end

	local parentAngle = 0

	if startFollowBone.fParent > -1 then
		local parentBone = skel:Bone(startFollowBone.fParent)
		local startParentBonePos = LM.Vector2:new_local()	
		local startParentBoneTipPos = LM.Vector2:new_local()	
		startParentBonePos:Set(0, 0)
		
		if parentBone:IsZeroLength() then
			startParentBoneTipPos:Set(0.1, 0)
		else
			startParentBoneTipPos:Set(parentBone.fLength, 0)
		end
		if moho.frame == 0 then
			parentBone.fRestMatrix:Transform(startParentBonePos)
			parentBone.fRestMatrix:Transform(startParentBoneTipPos)
		else
			parentBone.fMovedMatrix:Transform(startParentBonePos)
			parentBone.fMovedMatrix:Transform(startParentBoneTipPos)
		end
		
		local basePosDelta = startParentBonePos - self.followBonesDataList.lastParentBaseVec[b]
		startParentBonePos = startParentBonePos - basePosDelta
		startParentBoneTipPos = startParentBoneTipPos - basePosDelta
		parentAngle = self.followBonesDataList.parentStartAngle[b]
		local v1 = self.followBonesDataList.lastParentTipVec[b] - startParentBonePos
		local v2 = startParentBoneTipPos - startParentBonePos
		v2:Rotate(-math.atan2(v1.y, v1.x))
		parentAngle = parentAngle + math.atan2(v2.y, v2.x)
		self.followBonesDataList.parentStartAngle[b] = parentAngle
		self.followBonesDataList.lastParentTipVec[b] = startParentBoneTipPos
	end

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

	if not bone.fFixedAngle then
		if bone.fConstraints then
			local min = bone.fAnimAngle:GetValue(0) - self.followBonesDataList.angleDelta[b]
			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.followBonesDataList.bakedA[b] then
			if moho.layerFrame - self.interval > 0 then
				bone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.followBonesDataList.FAngleP[b])
			end
			if moho.layerFrame + self.interval > 0 then
				bone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.followBonesDataList.FAngleN[b])
			end
			self.followBonesDataList.bakedA[b] = true
		end
	end
end

function MR_PoseTool:AdjustLockPos(moho, index)
	if not self.lockPosList or #self.lockPosList < 1 then
		return
	end
	local skel = moho:Skeleton()
	if skel == nil then
		return
	end
	
	local i = index
	
	moho.layer:UpdateCurFrame()

	local bone = skel:Bone(self.lockPosList[i])
	if bone then
		if not bone.fSelected then
			local newPos 
			if bone.fParent >-1 then
				local matrix = LM.Matrix:new_local()
				local bonePos = LM.Vector2:new_local()
				bonePos:Set(self.lockedBonesPos[i])
				if moho.frame == 0 then
					matrix:Set(skel:Bone(bone.fParent).fRestMatrix)
				else
					matrix:Set(skel:Bone(bone.fParent).fMovedMatrix)
				end
				matrix:Invert()
				matrix:Transform(bonePos)
				newPos = bonePos - self.lockedBonesDeltaPos[i]
			else
				newPos = self.lockedBonesPos[i] - self.lockedBonesDeltaPos[i]
			end
			local originalPosVal = bone.fAnimPos:GetValue(moho.layerFrame)
			if not self:IsEqual(newPos.x, originalPosVal.x, 0.000001) or not self:IsEqual(newPos.y, originalPosVal.y, 0.000001) then
				bone.fAnimPos:SetValue(moho.layerFrame, newPos)
				if self.bakeAdjacentFrames and not self.lockPosBaked[i] then
					if moho.layerFrame - self.interval > 0 then
						bone.fAnimPos:SetValue(moho.layerFrame - self.interval, self.lockedBonesSBPosValuesP[i])
					end
					if moho.layerFrame + self.interval > 0 then
						bone.fAnimPos:SetValue(moho.layerFrame + self.interval, self.lockedBonesSBPosValuesN[i])
					end
					self.lockPosBaked[i] = true
				end
			end	
		end
	end
	moho.layer:UpdateCurFrame()
end

function MR_PoseTool:AdjustLockAngles(moho, index)
	if not self.lockAngleList or #self.lockAngleList < 1 then
		return
	end
	
	local skel = moho:Skeleton()
	if skel == nil then
		return
	end
	
	local i = index
	moho.layer:UpdateCurFrame()
	local bone = skel:Bone(self.lockAngleList[i])
	if bone then
		if not bone.fSelected and not bone.fFixedAngle then
			local parentAngle = 0
			if bone.fParent > -1 then
				local parentBone = skel:Bone(bone.fParent)
				local parentBonePos = LM.Vector2:new_local()	
				local parentBoneTipPos = LM.Vector2:new_local()	
				parentBonePos:Set(0, 0)
				
				if parentBone:IsZeroLength() then
					parentBoneTipPos:Set(0.1, 0)
				else
					if bone:IsZeroLength() then
						parentBoneTipPos:Set(0.1, 0)
					else
						parentBoneTipPos:Set(bone.fLength, 0)
					end
				end
				if moho.frame == 0 then
					parentBone.fRestMatrix:Transform(parentBonePos)
					parentBone.fRestMatrix:Transform(parentBoneTipPos)
				else
					parentBone.fMovedMatrix:Transform(parentBonePos)
					parentBone.fMovedMatrix:Transform(parentBoneTipPos)
				end
				local basePosDelta = parentBonePos - self.lockBonesLastParentBaseVec[i]
				parentBonePos = parentBonePos - basePosDelta
				parentBoneTipPos = parentBoneTipPos - basePosDelta
				parentAngle = self.lockBonesParentStartAngle[i]
				local v1 = self.lockBonesLastParentTipVec[i] - parentBonePos
				local v2 = parentBoneTipPos - parentBonePos
				v2:Rotate(-math.atan2(v1.y, v1.x))
				parentAngle = parentAngle + math.atan2(v2.y, v2.x)
				self.lockBonesParentStartAngle[i] = parentAngle
				self.lockBonesLastParentTipVec[i] = parentBoneTipPos
			end
			
			local angleSign = 1.0
			if (not bone.fFixedAngle) then
				angleSign = bone:ParentalFlipFactor()
			end
			
			local newAgle = (bone.fTempAngle - parentAngle * angleSign)
			if not bone.fFixedAngle then
				if bone.fConstraints then
					local min = bone.fAnimAngle:GetValue(0)
					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.lockAngleBaked[i] then
					if moho.layerFrame - self.interval > 0 then
						bone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.lockedBonesSBAngleValuesP[i])
					end
					if moho.layerFrame + self.interval > 0 then
						bone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.lockedBonesSBAngleValuesN[i])
					end
					self.lockAngleBaked[i] = true
				end
			end	
		end
	end
	moho.layer:UpdateCurFrame()
end

function MR_PoseTool:TestMousePointGraphicMenu(moho, mouseEvent)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return
	end
	local v = LM.Vector2:new_local()
	local pt = LM.Point:new_local()
	local m = LM.Matrix:new_local()
	local localV = LM.Vector2:new_local()
	
	local g = mouseEvent.view:Graphics()
	g:Push()

	local height = g:Height() / moho.document:Height()
	height = g:Height() / self.height

	local currentScale = g:CurrentScale(false)
	g:Pop()
	
	local offset = self.iconsDistance / currentScale / height
	local center = LM.Vector2:new_local()
	center:Set(self.graphicsMenuCenter)

	local radius = self.iconsRadius
	local shadowOffset = LM.Vector2:new_local()
	shadowOffset:Set(0.005 / currentScale / height, -0.01 / currentScale / height)
	local v = LM.Vector2:new_local()
	v:Set(center.x, center.y + offset)
	v:Set(self:RotateVector2(moho, v, center, math.rad(30)))

	mouseEvent.view:Graphics():WorldToScreen(v, pt)
	if (math.abs(pt.x - mouseEvent.pt.x) < radius and math.abs(pt.y - mouseEvent.pt.y) < radius) then
		return 1 -- set follow bones icon
	end
	
	v:Set(center.x, center.y + offset)
	v:Set(self:RotateVector2(moho, v, center, math.rad(90)))

	mouseEvent.view:Graphics():WorldToScreen(v, pt)
	if (math.abs(pt.x - mouseEvent.pt.x) < radius and math.abs(pt.y - mouseEvent.pt.y) < radius) then
		return 2 -- scale follow bones icon
	end
	
	v:Set(center.x, center.y + offset)
	v:Set(self:RotateVector2(moho, v, center, math.rad(-30)))

	mouseEvent.view:Graphics():WorldToScreen(v, pt)
	if (math.abs(pt.x - mouseEvent.pt.x) < radius and math.abs(pt.y - mouseEvent.pt.y) < radius) then
		return 3 -- lock angle icon
	end
	
	v:Set(center.x, center.y + offset)
	v:Set(self:RotateVector2(moho, v, center, math.rad(-90)))

	mouseEvent.view:Graphics():WorldToScreen(v, pt)
	if (math.abs(pt.x - mouseEvent.pt.x) < radius and math.abs(pt.y - mouseEvent.pt.y) < radius) then
		return 4 -- lock pos icon
	end
	
	v:Set(center.x, center.y + offset)
	v:Set(self:RotateVector2(moho, v, center, math.rad(210)))

	mouseEvent.view:Graphics():WorldToScreen(v, pt)
	if (math.abs(pt.x - mouseEvent.pt.x) < radius and math.abs(pt.y - mouseEvent.pt.y) < radius) then
		return 5 -- clear pos icon
	end
	
	v:Set(center.x, center.y + offset)
	v:Set(self:RotateVector2(moho, v, center, math.rad(150)))

	mouseEvent.view:Graphics():WorldToScreen(v, pt)
	if (math.abs(pt.x - mouseEvent.pt.x) < radius and math.abs(pt.y - mouseEvent.pt.y) < radius) then
		return 6 -- clear pos icon
	end
	return 0
end

function MR_PoseTool:AddToLockAngleList(moho)
	local skel = moho:Skeleton()
	if not skel then
		return
	end
	
	self:RemoveSelectedBonesFromFollowList(moho)
	
	self:ValidateLockList(moho)
	for i = 0, skel:CountBones()-1 do
		local bone = skel:Bone(i)
		if bone.fSelected then
			local existInList = self:ValueExists(self.lockAngleList, i)
			if not existInList then
				table.insert(self.lockAngleList, i)
				table.insert(self.lockAngleBoneNamesList, bone:Name())
			else
				table.remove(self.lockAngleList, existInList)
				table.remove(self.lockAngleBoneNamesList, existInList)
			end
		end
	end
	self.followLockLayerUUID = moho.layer:UUID()
end

function MR_PoseTool:AddToLockPosList(moho)
	local skel = moho:Skeleton()
	if not skel then
		return
	end
	
	self:RemoveSelectedBonesFromFollowList(moho)
	
	self:ValidateLockList(moho)
	for i = 0, skel:CountBones()-1 do
		local bone = skel:Bone(i)
		if bone.fSelected then
			local existInList = self:ValueExists(self.lockPosList, i)
			if not existInList then
				table.insert(self.lockPosList, i)
				table.insert(self.lockPosBoneNamesList, bone:Name())
			else
				table.remove(self.lockPosList, existInList)
				table.remove(self.lockPosBoneNamesList, existInList)
			end
		end
	end
	self.followLockLayerUUID = moho.layer:UUID()
end

function MR_PoseTool:RemoveFromLockList(moho)
	local skel = moho:Skeleton()
	if not skel then
		return
	end
	self:ValidateLockList(moho)
	for i = 0, skel:CountBones()-1 do
		local bone = skel:Bone(i)
		if bone.fSelected then
			local existInList
			if self.lockAngleList then
				existInList = self:ValueExists(self.lockAngleList, i)
				if existInList then
					table.remove(self.lockAngleList, existInList)
					table.remove(self.lockAngleBoneNamesList, existInList)
				end
			end
			if self.lockPosList then
				existInList = self:ValueExists(self.lockPosList, i)
				if existInList then
					table.remove(self.lockPosList, existInList)
					table.remove(self.lockPosBoneNamesList, existInList)
				end
			end
		end
	end
end

function MR_PoseTool:RemoveFromFollowist(moho)
	local skel = moho:Skeleton()
	if not skel then
		return
	end
	self:ValidateLockList(moho)
	for i = 0, skel:CountBones()-1 do
		local bone = skel:Bone(i)
		if bone.fSelected then
			local existInList
			if self.lockAngleList then
				existInList = self:ValueExists(self.lockAngleList, i)
				if existInList then
					table.remove(self.lockAngleList, existInList)
					table.remove(self.lockAngleBoneNamesList, existInList)
				end
			end
			if self.lockPosList then
				existInList = self:ValueExists(self.lockPosList, i)
				if existInList then
					table.remove(self.lockPosList, existInList)
					table.remove(self.lockPosBoneNamesList, existInList)
				end
			end
		end
	end
end

function MR_PoseTool:SwapTwoArrayKeys(array, key1, key2)
	local keyTmp1 = array[key1]
	local keyTmp2 = array[key2]
	return keyTmp2, keyTmp1
end

function MR_PoseTool:ValidateLockList(moho)
	local skel = moho:Skeleton()
	if not skel then
		return
	end
	
	local removeList = {}
	for b=1, #self.lockAngleList do
		local tBone = skel:Bone(self.lockAngleList[b])
		if tBone then
			if tBone:Name() ~= self.lockAngleBoneNamesList[b] then
				table.insert(removeList, b)
			end
		else
			table.insert(removeList, b)
		end
	end

	if #removeList > 0 then
		table.sort(removeList, function(a, b) return a > b end)
		for i, v in ipairs(removeList) do
			table.remove(self.lockAngleList, v)
			table.remove(self.lockAngleBoneNamesList, v)
		end
	end
	
	removeList = {}
	
	for b=1, #self.lockPosList do
		local tBone = skel:Bone(self.lockPosList[b])
		if tBone then
			if tBone:Name() ~= self.lockPosBoneNamesList[b] then
				table.insert(removeList, b)
			end
		else
			table.insert(removeList, b)
		end
	end

	if #removeList > 0 then
		table.sort(removeList, function(a, b) return a > b end)
		for i, v in ipairs(removeList) do
			table.remove(self.lockPosList, v)
			table.remove(self.lockPosBoneNamesList, v)
		end
	end
end

function MR_PoseTool:ValidateFollowList(moho)
	local skel = moho:Skeleton()
	if not skel then
		return
	end
	local removeList = {}
	for b=1, #self.followBonesList.id do
		for i=1, #self.followBonesList.id[b] do
			local tBone = skel:Bone(self.followBonesList.id[b][i])
			if tBone then
				if tBone:Name() ~= self.followBonesList.names[b][i] or tBone:IsZeroLength() then
					table.insert(removeList, b)
					break
				end
			else
				table.insert(removeList, b)
				break
			end
		end
	end
	
	if #removeList > 0 then
		local function compare(a, b)
			return a > b 
		end
		table.sort(removeList, compare)
		for i, v in ipairs(removeList) do
			table.remove(self.followBonesList.id, v)
			table.remove(self.followBonesList.names, v)
			table.remove(self.followBonesList.startBone, v)
			table.remove(self.followBonesList.endBone, v)
		end
	end
end

function MR_PoseTool:AdjustFollowAndLockBones(moho)
	for i=1, #self.followLockedBonesList.listIndex do
		if self.followLockedBonesList.list[i] == 1 then
			self:AdjustFollowBones(moho, self.followLockedBonesList.listIndex[i])
		elseif self.followLockedBonesList.list[i] == 2 then
			self:AdjustLockAngles(moho, self.followLockedBonesList.listIndex[i])
		elseif self.followLockedBonesList.list[i] == 3 then
			self:AdjustLockPos(moho, self.followLockedBonesList.listIndex[i])
		end
	end
end

function MR_PoseTool:RemoveSelectedBonesFromFollowList(moho)
	local skel = moho:Skeleton()
	if not skel then
		return
	end
	local removeList = {}
	for b=1, #self.followBonesList.id do
		for i=1, #self.followBonesList.id[b] do
			local bone = skel:Bone(self.followBonesList.id[b][i])
			if bone.fSelected then
				table.insert(removeList, b)
				break
			end
		end
	end
	
	if #removeList > 0 then
		local function compare(a, b)
			return a > b 
		end
		table.sort(removeList, compare)
		for i, v in ipairs(removeList) do
			table.remove(self.followBonesList.id, v)
			table.remove(self.followBonesList.names, v)
			table.remove(self.followBonesList.startBone, v)
			table.remove(self.followBonesList.endBone, v)
		end
	end
end

function MR_PoseTool:ValueExists(tbl, value)
    for key, val in pairs(tbl) do
        if val == value then
            return key
        end
    end
    return false
end

function MR_PoseTool:Compare(a, b)
    return a > b
end

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

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

	phrase['Description'] = 'Set up the pose of your character (hold <ctrl/cmd> or <ctrl/cmd> + <shift> to access the quick menu, <alt> for compensation of child bone transformation, <shift> for additional transformation variations)'
	phrase['UILabel'] = 'MR Pose Tool '..self:Version()
	
	phrase['Settings'] = 'Settings'
	phrase['Quick menu tooltips'] = 'Quick menu tooltips'
	phrase['Double-click to reset'] = 'Double-click to reset'
	phrase['Move target parent'] = 'Move target\'s parent'
	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['Twos mode'] = 'Twos mode'
	phrase['Keep selection'] = 'Keep selection'
	phrase['Multi transform'] = 'Multi transform'
	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'
	
	phrase['Set follow bones'] = 'Set follow bones'
	phrase['Scale follow bones'] = 'Scale follow bones'
	phrase['Lock angle'] = 'Lock angle'
	phrase['Lock position'] = 'Lock position'
	phrase['Clear selection'] = 'Clear selection'
	phrase['Clear all'] = 'Clear all'

	return phrase[text]
end

Icon
MR Pose Tool
Listed

Script type: Tool

Uploaded: Aug 14 2023, 06:38

Last modified: Apr 14 2024, 13:51

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