-- ************************************************** -- 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
MR Pose Tool
Listed
Author: eugenebabich
View Script
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
MR Pose Tool
Listed
Author: eugenebabich
View Script
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.
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