-- ************************************************** -- 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 '3.2.1' 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) and not self.skeletonLayersNavigation then return false end if not self.mohoVersion then if MR_Utilities then local v1, v2, v3 = MR_Utilities:GetMohoVersion(moho) self.mohoVersion = v1 end end return true end function MR_PoseTool:IsEnabled(moho) return true end -- ************************************************** -- Recurring Values -- ************************************************** MR_PoseTool.relativeKeyframingScale = true MR_PoseTool.skeletonLayersNavigation = false MR_PoseTool.quickMenuTooltips = true MR_PoseTool.moveTargetParent = false MR_PoseTool.doubleClickToSetKeyframe = true MR_PoseTool.holdToReset = 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.panelSizeShort = false 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.length = {} MR_PoseTool.followBonesList.startBone = {} MR_PoseTool.followBonesList.endBone = {} MR_PoseTool.ikBonesList = {} MR_PoseTool.ikBonesList.id = {} MR_PoseTool.ikBonesList.names = {} MR_PoseTool.ikBonesList.length = {} MR_PoseTool.ikBonesList.startBone = {} MR_PoseTool.ikBonesList.endBone = {} MR_PoseTool.startFollowBone = -1 MR_PoseTool.endFollowBone = -1 MR_PoseTool.boneStretching = false MR_PoseTool.boneStretchingIconStatus = 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.showQuickMenu = 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.multiSelectionUnselectedMovement = false MR_PoseTool.showCross = false MR_PoseTool.ignoreBonesList = {} MR_PoseTool.scriptDataName = 'MR_PoseTool_' MR_PoseTool.bonesDataActive = true MR_PoseTool.bonesDataActiveF = true MR_PoseTool.bonesDataActiveIK = true MR_PoseTool.bonesDataActiveA = true MR_PoseTool.bonesDataActiveP = true MR_PoseTool.selBonesList = {} MR_PoseTool.isBoneHaveAngleKeyList = {} MR_PoseTool.isBoneHaveScaleKeyList = {} MR_PoseTool.clickTime = 0 MR_PoseTool.setKeyframe = false MR_PoseTool.onMMTreshold = false MR_PoseTool.forceBoneTranslationAlt = false MR_PoseTool.forceBoneTranslationShift = false MR_PoseTool.singleFollowBonesMode = false MR_PoseTool.scriptValidated = nil MR_PoseTool.buttonPressed = 0 MR_PoseTool.operationFailes = 0 MR_PoseTool.enableFBExpanded = false MR_PoseTool.ignoreUpdateWidgets = false MR_PoseTool.blockQuickMenu = false -- ************************************************** -- Prefs -- ************************************************** function MR_PoseTool:LoadPrefs(prefs) self.relativeKeyframingScale = prefs:GetBool("MR_PoseTool.relativeKeyframingScale", true) self.skeletonLayersNavigation = prefs:GetBool("MR_PoseTool.skeletonLayersNavigation", false) self.quickMenuTooltips = prefs:GetBool("MR_PoseTool.quickMenuTooltips", true) self.doubleClickToSetKeyframe = prefs:GetBool("MR_PoseTool.doubleClickToSetKeyframe", true) self.holdToReset = prefs:GetBool("MR_PoseTool.holdToReset", 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.panelSizeShort = prefs:GetBool("MR_PoseTool.panelSizeShort", false) 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) end function MR_PoseTool:SavePrefs(prefs) prefs:SetBool("MR_PoseTool.relativeKeyframingScale", self.relativeKeyframingScale) prefs:SetBool("MR_PoseTool.skeletonLayersNavigation", self.skeletonLayersNavigation) prefs:SetBool("MR_PoseTool.quickMenuTooltips", self.quickMenuTooltips) prefs:SetBool("MR_PoseTool.doubleClickToSetKeyframe", self.doubleClickToSetKeyframe) prefs:SetBool("MR_PoseTool.holdToReset", self.holdToReset) 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.panelSizeShort", self.panelSizeShort) 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) end function MR_PoseTool:ResetPrefs() self.relativeKeyframingScale = true self.skeletonLayersNavigation = false self.quickMenuTooltips = true self.doubleClickToSetKeyframe = true self.holdToReset = 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.panelSizeShort = false 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 end function MR_PoseTool:NonDragMouseMove() return true -- Call MouseMoved() even if the mouse button is not down end -- ************************************************** -- MR_PoseToolInfoDialog -- ************************************************** local MR_PoseToolInfoDialog = {} MR_PoseToolInfoDialog.INFO = MOHO.MSG_BASE function MR_PoseToolInfoDialog:new(moho) local d = LM.GUI.SimpleDialog(MR_PoseTool:Localize('UILabel'), MR_PoseToolInfoDialog) local l = d:GetLayout() d.infoButton = LM.GUI.ImageButton('ScriptResources/mr_pose_tool/mr_pose_tool_cheat_sheet', '', false, self.INFO, false) l:AddChild(d.infoButton, LM.GUI.ALIGN_FILL, 0) return d end function MR_PoseToolInfoDialog:UpdateWidgets(moho) end function MR_PoseToolInfoDialog:OnOK(moho) end -- ************************************************** -- Settings Menu -- ************************************************** local MR_PoseToolSettingsDialog = {} MR_PoseToolSettingsDialog.RELATIVE_KEYFRAMING_SCALE = MOHO.MSG_BASE MR_PoseToolSettingsDialog.SKELETON_LAYERS_NAVIGATION = MOHO.MSG_BASE + 1 MR_PoseToolSettingsDialog.QUICK_MENU_TOOLTIPS = MOHO.MSG_BASE + 2 MR_PoseToolSettingsDialog.DOUBLE_CLICK_TO_SET_KEYFRAME = MOHO.MSG_BASE + 3 MR_PoseToolSettingsDialog.HOLD_TO_RESET = MOHO.MSG_BASE + 4 MR_PoseToolSettingsDialog.MOVE_TARGET_PARENT = MOHO.MSG_BASE + 5 MR_PoseToolSettingsDialog.BLOCK_ON_EVEN_FRAMES = MOHO.MSG_BASE + 6 MR_PoseToolSettingsDialog.BLOCK_ON_ODD_FRAMES = MOHO.MSG_BASE + 7 MR_PoseToolSettingsDialog.HIGHLIGHT_BONES = MOHO.MSG_BASE + 8 MR_PoseToolSettingsDialog.HIGHLIGHT_WIDTH = MOHO.MSG_BASE + 9 MR_PoseToolSettingsDialog.HIGHLIGHT_OPACITY = MOHO.MSG_BASE + 10 MR_PoseToolSettingsDialog.USE_HIGHLIGHT_CUSTOM_COLOR = MOHO.MSG_BASE + 11 MR_PoseToolSettingsDialog.HIGHLIGHT_CUSTOM_COLOR = MOHO.MSG_BASE + 12 MR_PoseToolSettingsDialog.ALIGN_HANDLES_ALONG_BONE = MOHO.MSG_BASE + 13 MR_PoseToolSettingsDialog.HANDLES_DISTANCE = MOHO.MSG_BASE + 14 MR_PoseToolSettingsDialog.HANDLES_STROKE_OPACITY = MOHO.MSG_BASE + 15 MR_PoseToolSettingsDialog.HANDLES_FILL_OPACITY = MOHO.MSG_BASE + 16 MR_PoseToolSettingsDialog.USE_CUSTOM_COLORS = MOHO.MSG_BASE + 17 MR_PoseToolSettingsDialog.COLOR_TRANSLATE_STROKE = MOHO.MSG_BASE + 18 MR_PoseToolSettingsDialog.COLOR_TRANSLATE_FILL = MOHO.MSG_BASE + 19 MR_PoseToolSettingsDialog.COLOR_SCALE_STROKE = MOHO.MSG_BASE + 20 MR_PoseToolSettingsDialog.COLOR_SCALE_FILL = MOHO.MSG_BASE + 21 MR_PoseToolSettingsDialog.COLOR_MOVE_JOINT_STROKE = MOHO.MSG_BASE + 22 MR_PoseToolSettingsDialog.COLOR_MOVE_JOINT_FILL = MOHO.MSG_BASE + 23 MR_PoseToolSettingsDialog.COLOR_MANIPULATE_STROKE = MOHO.MSG_BASE + 24 MR_PoseToolSettingsDialog.COLOR_MANIPULATE_FILL = MOHO.MSG_BASE + 25 MR_PoseToolSettingsDialog.RESET_COLOR = MOHO.MSG_BASE + 26 function MR_PoseToolSettingsDialog:new() local d = LM.GUI.SimpleDialog(MR_PoseTool:Localize('UILabel'), MR_PoseToolSettingsDialog) local l = d:GetLayout() d.relativeKeyframingScaleCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Relative keyframing scale'), self.RELATIVE_KEYFRAMING_SCALE) l:AddChild(d.relativeKeyframingScaleCheck, LM.GUI.ALIGN_LEFT, 0) l:AddPadding(-10) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) d.skeletonLayersNavigationCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Skeleton layers navigation'), self.SKELETON_LAYERS_NAVIGATION) l:AddChild(d.skeletonLayersNavigationCheck, LM.GUI.ALIGN_LEFT, 0) l:AddPadding(-10) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) 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) l:AddPadding(-10) d.doubleClickToSetKeyframeCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Double-click to set keyframe'), self.DOUBLE_CLICK_TO_SET_KEYFRAME) l:AddChild(d.doubleClickToSetKeyframeCheck, LM.GUI.ALIGN_LEFT, 0) l:AddPadding(-17) d.holdToResetCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Click and hold to reset'), self.HOLD_TO_RESET) l:AddChild(d.holdToResetCheck, LM.GUI.ALIGN_LEFT, 0) l:AddPadding(-17) 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:AddPadding(-10) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) l:AddPadding(-10) 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) l:AddPadding(-17) 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:AddPadding(-10) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) l:AddPadding(-10) d.highlightBonesCheck = LM.GUI.CheckBox(MR_PoseTool:Localize('Highlight bones'), self.HIGHLIGHT_BONES) l:AddChild(d.highlightBonesCheck, LM.GUI.ALIGN_LEFT, 0) l:AddPadding(-17) 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) l:AddPadding(-10) 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:AddPadding(-10) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) l:AddPadding(-10) 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) l:AddPadding(-10) 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) l:AddPadding(-10) 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) l:AddPadding(-10) 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:AddPadding(-10) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) l:AddPadding(-10) 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.relativeKeyframingScaleCheck:SetValue(MR_PoseTool.relativeKeyframingScale) self.skeletonLayersNavigationCheck:SetValue(MR_PoseTool.skeletonLayersNavigation) self.doubleClickToSetKeyframeCheck:SetValue(MR_PoseTool.doubleClickToSetKeyframe) self.holdToResetCheck:SetValue(MR_PoseTool.holdToReset) 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.relativeKeyframingScale = self.relativeKeyframingScaleCheck:Value() MR_PoseTool.skeletonLayersNavigation = self.skeletonLayersNavigationCheck:Value() MR_PoseTool.doubleClickToSetKeyframe = self.doubleClickToSetKeyframeCheck:Value() MR_PoseTool.holdToReset = self.holdToResetCheck: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.RELATIVE_KEYFRAMING_SCALE then MR_PoseTool.relativeKeyframingScale = self.relativeKeyframingScaleCheck:Value() elseif msg == self.SKELETON_LAYERS_NAVIGATION then MR_PoseTool.skeletonLayersNavigation = self.skeletonLayersNavigationCheck:Value() elseif msg == self.QUICK_MENU_TOOLTIPS then MR_PoseTool.quickMenuTooltips = self.quickMenuTooltipsCheck:Value() elseif msg == self.DOUBLE_CLICK_TO_SET_KEYFRAME then MR_PoseTool.doubleClickToSetKeyframe = self.doubleClickToSetKeyframeCheck:Value() elseif msg == self.HOLD_TO_RESET then MR_PoseTool.holdToReset = self.holdToResetCheck: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 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() MR_PoseTool:GenerateColors(moho) moho.view:DrawMe() helper:delete() end end end -- ************************************************** -- Keyboard/Mouse Control -- ************************************************** function MR_PoseTool:OnMouseDown(moho, mouseEvent) if self.scriptValidated ~= true then return end self.onMMTreshold = true self.clickTime = os.time() self.forceFollowBonesGraphics = false local skel = moho:Skeleton() local layer = moho.layer local frame = moho.frame if self.skeletonLayersNavigation then if skel == nil and frame ~= 0 then if mouseEvent.ctrlKey then layer = mouseEvent.view:PickGlobalLayer(mouseEvent.pt) end self:GoToSkeletonLayer(moho, layer, true) skel = moho:LayerAsBone(layer) end end if skel == nil or frame == 0 then return end self.blockQuickMenu = false local twosModeValid = true if self.twosMode then if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0) then twosModeValid = false end end if self.showQuickMenu then self.graphicMenuMode = self:TestMousePointGraphicMenu(moho, mouseEvent) if self.graphicMenuMode == 0 and self.skeletonLayersNavigation and twosModeValid then local targetLayer = mouseEvent.view:PickGlobalLayer(mouseEvent.pt) self:GoToSkeletonLayer(moho, targetLayer, false) self.blockQuickMenu = true mouseEvent.view:SetCursor(self.mainCursor) end if self.graphicMenuMode == 1 then self.buttonPressed = 1 if not self.singleFollowBonesMode then moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() self:AddToFollowBonesChains(moho) end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 2 then self.buttonPressed = 2 if not self.singleFollowBonesMode then moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() self:AddToIKBonesChains(moho) end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 3 then self.buttonPressed = 3 if not self.singleFollowBonesMode then moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() self:AddToLockAngleList(moho) end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 4 then self.buttonPressed = 4 if not self.singleFollowBonesMode then moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() self:AddToLockPosList(moho) end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 5 then self.buttonPressed = 5 if not self.singleFollowBonesMode then moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() self:RemoveSelectedBonesFromFollowList(moho) self:RemoveSelectedBonesFromIkList(moho) self:RemoveFromLockList(moho) end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 6 then self.buttonPressed = 6 moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() local scriptInfo = moho.layer:ScriptData() self.bonesDataActive = not self.bonesDataActive local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' scriptInfo:Set(bonesDataActiveKey, self.bonesDataActive) mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 7 then self.buttonPressed = 7 moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() local scriptInfo = moho.layer:ScriptData() self.bonesDataActiveF = not self.bonesDataActiveF local bonesDataActiveFKey = self.scriptDataName..'bonesDataActiveF ' scriptInfo:Set(bonesDataActiveFKey, self.bonesDataActiveF) mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 8 then self.buttonPressed = 8 moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() local scriptInfo = moho.layer:ScriptData() self.bonesDataActiveIK = not self.bonesDataActiveIK local bonesDataActiveIKKey = self.scriptDataName..'bonesDataActiveIK ' scriptInfo:Set(bonesDataActiveIKKey, self.bonesDataActiveIK) mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 9 then self.buttonPressed = 9 moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() local scriptInfo = moho.layer:ScriptData() self.bonesDataActiveA = not self.bonesDataActiveA local bonesDataActiveAKey = self.scriptDataName..'bonesDataActiveA ' scriptInfo:Set(bonesDataActiveAKey, self.bonesDataActiveA) mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 10 then self.buttonPressed = 10 moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() local scriptInfo = moho.layer:ScriptData() self.bonesDataActiveP = not self.bonesDataActiveP local bonesDataActivePKey = self.scriptDataName..'bonesDataActiveP ' scriptInfo:Set(bonesDataActivePKey, self.bonesDataActiveP) mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 11 then self.buttonPressed = 11 moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() local scriptInfo = moho.layer:ScriptData() self.boneStretching = not self.boneStretching local scaleFollowBonesKey = self.scriptDataName..'boneStretching ' scriptInfo:Set(scaleFollowBonesKey, self.boneStretching) mouseEvent.view:DrawMe() end return elseif self.showQuickMenu2 then self.graphicMenuMode = self:TestMousePointGraphicMenu(moho, mouseEvent) if self.graphicMenuMode == 0 and self.skeletonLayersNavigation and twosModeValid then local targetLayer = mouseEvent.view:PickGlobalLayer(mouseEvent.pt) self:GoToSkeletonLayer(moho, targetLayer, false) self.blockQuickMenu = true mouseEvent.view:SetCursor(self.mainCursor) end if self.graphicMenuMode == 1 then self.buttonPressed = 1 if not self.singleFollowBonesMode then moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() self:AddToFollowBones(moho) end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 2 then self.buttonPressed = 2 moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() self:ReverseIkDirection(moho) mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 3 then self.buttonPressed = 3 if not self.singleFollowBonesMode then moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() self:SetBoneStretching(moho, false) end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 4 then self.buttonPressed = 4 if not self.singleFollowBonesMode then self:CleanUpBoneStretching(moho) end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 5 then self.buttonPressed = 5 moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() self:CleanUpBonesData(moho.layer) mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 6 then self.buttonPressed = 6 moho.document:PrepUndo(moho.layer, true) moho.document:SetDirty() local scriptInfo = moho.layer:ScriptData() self.singleFollowBonesMode = not self.singleFollowBonesMode local singleFollowBonesModeKey = self.scriptDataName..'singleFollowBonesMode ' scriptInfo:Set(singleFollowBonesModeKey, self.singleFollowBonesMode) mouseEvent.view:DrawMe() end return elseif self.showQuickMenu3 then self.graphicMenuMode = self:TestMousePointGraphicMenu(moho, mouseEvent) if self.graphicMenuMode == 0 and self.skeletonLayersNavigation and twosModeValid then local targetLayer = mouseEvent.view:PickGlobalLayer(mouseEvent.pt) self:GoToSkeletonLayer(moho, targetLayer, false) self.blockQuickMenu = true mouseEvent.view:SetCursor(self.mainCursor) end if self.graphicMenuMode == 1 then self.buttonPressed = 1 if self.keepSelection then self.multiTransform = not self.multiTransform end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 2 then self.buttonPressed = 2 self.keepSelection = not self.keepSelection mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 3 then self.buttonPressed = 3 self.lockHandles = not self.lockHandles mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 4 then self.buttonPressed = 4 if not MOHO.MohoGlobals.EditMultipleKeys then self.bakeAdjacentFrames = not self.bakeAdjacentFrames end mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 5 then self.buttonPressed = 5 self.showPath = not self.showPath mouseEvent.view:DrawMe() elseif self.graphicMenuMode == 6 then self.buttonPressed = 6 self.twosMode = not self.twosMode mouseEvent.view:DrawMe() 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 self.isBoneHaveAngleKeyList = {} self.isBoneHavePosKeyList = {} self.isBoneHaveScaleKeyList = {} 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.selBonesList = {} self.selectedBonesList = {} self.multiBoneTranslateList = {} for i=0, skel:CountBones()-1 do local bone = skel:Bone(i) if bone.fSelected then self.selBonesList[i] = true table.insert(self.selectedBonesList, i) if not skel:IsAncestorSelected(i) then table.insert(self.multiBoneTranslateList, i) end end end end self.setKeyframe = false self.trPathBone = nil self.keepHandles = false self.dragging = true self.lastVec:Set(mouseEvent.vec) self.ignoreBonesList = {} 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 and not (mouseEvent.altKey and mouseEvent.shiftKey and not mouseEvent.ctrlKey) 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 if mouseEvent.altKey and mouseEvent.shiftKey and not mouseEvent.ctrlKey then if self.multiTransform and self.keepSelection then local bonesVisibilityList = {} for i=0, skel:CountBones()-1 do local bone = skel:Bone(i) if not bone.fSelected then bonesVisibilityList[i+1] = bone.fHidden bone.fHidden = true end end id = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, 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 else id = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, false) end else id = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, false) end 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 if id > -1 then self.mode = self:TestMousePoint(moho, mouseEvent, id) else self.mode = self:TestMousePoint(moho, mouseEvent, selBoneID) end if mouseEvent.doubleClick then local doubleclickMode = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance) if doubleclickMode == -1 then local scriptInfo = moho.layer:ScriptData() self.bonesDataActive = not self.bonesDataActive local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' scriptInfo:Set(bonesDataActiveKey, self.bonesDataActive) return end end if self.mode > 1 and mouseHoverID < 0 then id = selBoneID self.mousePickedID = id self.secondBoneID = id end ::multiTransformSelection:: local multiTransformSelection = false if not (mouseEvent.altKey and mouseEvent.shiftKey and not mouseEvent.ctrlKey) then 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 end if id < 0 then return end if MOHO.MohoGlobals.EditMultipleKeys then self:PrepareToEditMultipleKeys(moho) end self.forceBoneTranslationAlt = false self.forceBoneTranslationShift = false if mouseEvent.altKey and mouseEvent.shiftKey and not mouseEvent.ctrlKey then mouseEvent.altKey = false mouseEvent.shiftKey = false self.forceBoneTranslationAlt = true self.forceBoneTranslationShift = true self.mode = 0 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.doubleClickToSetKeyframe then for i=0, skel:CountBones()-1 do local bone = skel:Bone(i) local secondBone = skel:Bone(self.secondBoneID) if secondBone then if secondBone.fSelected == self.selBonesList[self.secondBoneID] then if self.selBonesList[i] then bone.fSelected = true end end end if bone.fSelected then if self.mode == 0 then bone.fAnimPos:AddKey(moho.layerFrame) elseif self.mode == 1 then bone.fAnimAngle:AddKey(moho.layerFrame) elseif self.mode == 2 then bone.fAnimScale:AddKey(moho.layerFrame) end end end self.setKeyframe = true return 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.isBoneHaveAngleKeyList[self.secondBoneID] = secondBone.fAnimAngle:HasKey(moho.layerFrame) self.isBoneHaveScaleKeyList[self.secondBoneID] = secondBone.fAnimScale:HasKey(moho.layerFrame) self.jointChain = false self.firstBoneID = -1 self:PrepareFollowBones(moho) if self.mode == 5 then local bone = skel:Bone(id) bone.fSelected = true self.selID = skel:BoneID(self.trPathBone) self.secondBoneID = id self.isBoneHaveAngleKeyList[self.secondBoneID] = bone.fAnimAngle:HasKey(moho.layerFrame) self.isBoneHaveScaleKeyList[self.secondBoneID] = bone.fAnimScale:HasKey(moho.layerFrame) 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) if id >= 0 then self.ignoreBonesList[id + 1] = true end 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) self.ignoreBonesList[parenBoneID + 1] = true 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) if startBoneID >= 0 then self.ignoreBonesList[startBoneID + 1] = true end local startBonePos = LM.Vector2:new_local() startBonePos:Set(0, 0) startBone.fMovedMatrix:Transform(startBonePos) self.startBonePos:Set(startBonePos) self.startBoneDist = MR_Utilities: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) self.isBoneHaveAngleKeyList[self.firstBoneID] = firstBone.fAnimAngle:HasKey(moho.layerFrame) self.isBoneHaveScaleKeyList[self.firstBoneID] = firstBone.fAnimScale:HasKey(moho.layerFrame) 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 MR_Utilities:Round(secondBone.fPos.y) == 0 and not MR_Utilities: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.secondBoneID >= 0 and self.mode ~= 0 then self.ignoreBonesList[self.secondBoneID + 1] = true end if self.bakeAdjacentFrames then self.boneBakedA = false self.boneBakedP = false self.boneBakedS = false if useFirstBone then if self.firstBoneID >= 0 then self.ignoreBonesList[self.firstBoneID + 1] = true end 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 and self.mode ~= 1 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 MR_Utilities: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 MR_Utilities: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 = MR_Utilities:GetDistance(self.firstBonePos, self.secondBonePos) self.ignoreBonesList[self.firstBoneID + 1] = true end self.secondBoneTipPos:Set(secondTipVec) self.secondBoneDist = MR_Utilities: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() self.isMouseMoved = false end function MR_PoseTool:OnMouseMoved(moho, mouseEvent) if self.scriptValidated ~= true then return end if self.onMMTreshold then self.onMMTreshold = false return end local frame = moho.layerFrame local skel = moho:Skeleton() if skel == nil then if self.skeletonLayersNavigation then local skelLayer = MR_Utilities:FindSkeletonLayer(moho.layer) if (skelLayer or mouseEvent.ctrlKey) and frame ~= 0 then mouseEvent.view:SetCursor(self.sblCursor) else mouseEvent.view:SetCursor(MOHO.disabledCursor) end end return end if 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 not mouseEvent.ctrlKey then self.blockQuickMenu = false end if self.twosMode then if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0)then self.showQuickMenu = false self.showQuickMenu2 = false self.showQuickMenu3 = false self.showQuickMenu4 = false self.showIcons4 = 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.showQuickMenu = false self.showQuickMenu2 = false self.showQuickMenu3 = false self.showIcons4 = false mouseEvent.view:SetCursor(MOHO.disabledCursor) elseif mouseEvent.ctrlKey and self.mouseHoverIDGraphicMenu == -1 then if mouseEvent.shiftKey then self.showQuickMenu3 = true if self.showQuickMenu or self.showQuickMenu2 or self.showQuickMenu3 then self.graphicMenuMode = self:TestMousePointGraphicMenu(moho, mouseEvent) end mouseEvent.view:SetCursor(self.mainCursor) else self.showQuickMenu = false self.showQuickMenu2 = 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.showQuickMenu = false self.showQuickMenu2 = false self.showQuickMenu3 = false local pickWidth = self.pickWidth if not self.blockQuickMenu then if not mouseEvent.ctrlKey then self.mouseHoverIDGraphicMenu = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance) self.showQuickMenu = false self.showQuickMenu2 = false self.showQuickMenu3 = false self.showQuickMenu4 = false elseif mouseEvent.ctrlKey and self.mouseHoverIDGraphicMenu == -1 then if not mouseEvent.shiftKey and not mouseEvent.altKey then self.showQuickMenu = true elseif mouseEvent.altKey and not mouseEvent.shiftKey then self.showQuickMenu2 = true self.showQuickMenu4 = false elseif mouseEvent.shiftKey and not mouseEvent.altKey then self.showQuickMenu3 = true self.showQuickMenu4 = false end end end if self.showQuickMenu or self.showQuickMenu2 or self.showQuickMenu3 then self.graphicMenuMode = self:TestMousePointGraphicMenu(moho, mouseEvent) end if self.graphicMenuMode == 6 then self.showQuickMenu4 = true elseif self.graphicMenuMode >= 1 and self.graphicMenuMode <= 5 then self.showQuickMenu4 = false end self.mouseHoverID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true, pickWidth * self.handlesDistYMultiplier * self.handlesDistance) local forceBoneTranslation = false if mouseEvent.altKey and mouseEvent.shiftKey and not mouseEvent.ctrlKey then forceBoneTranslation = true end if (not self.dragging) then if forceBoneTranslation then mouseEvent.view:SetCursor(MOHO.moveCursor) end 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 if not forceBoneTranslation then mouseEvent.view:SetCursor(self.mainCursor) end 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.showQuickMenu then mode = self:TestMousePoint(moho, mouseEvent, boneID) self.drawMode = mode if self.mouseHoverID > -1 and not forceBoneTranslation 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 if not forceBoneTranslation then mouseEvent.view:SetCursor(self.mainCursor) end 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.showQuickMenu 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) and not forceBoneTranslation 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 if not forceBoneTranslation then mouseEvent.view:SetCursor(self.mainCursor) end end end else if not forceBoneTranslation then mouseEvent.view:SetCursor(self.mainCursor) end end else if not forceBoneTranslation then mouseEvent.view:SetCursor(self.mainCursor) end end end if self.skeletonLayersNavigation and mouseEvent.ctrlKey and (self.showQuickMenu or self.showQuickMenu2 or self.showQuickMenu3) then if self.graphicMenuMode == 0 and not self.blockQuickMenu then mouseEvent.view:SetCursor(self.sblCursor) 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 smartBake = self.bakeAdjacentFrames if MOHO.MohoGlobals.EditMultipleKeys then smartBake = false end local firstBone = skel:Bone(self.firstBoneID) local secondBone = skel:Bone(self.secondBoneID) if smartBake 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 = MR_Utilities: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 = MR_Utilities: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 = MR_Utilities:GetDistance(vectorMousePos, self.firstBonePos) local secondCursorDist = MR_Utilities: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 MR_Utilities:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then bone.fAnimAngle:SetValue(moho.layerFrame, newAgle) bone.fAnimAngle.value = bone.fAngle if smartBake 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 MR_Utilities:IsEqual(newAgle2, bone.fAnimAngle:GetValue(moho.layerFrame), 0.0001) then bone.fAnimAngle:SetValue(moho.layerFrame, newAgle2) bone.fAnimAngle.value = bone.fAngle if smartBake 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 = MR_Utilities: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 smartBake 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 MR_Utilities: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 smartBake = self.bakeAdjacentFrames if MOHO.MohoGlobals.EditMultipleKeys then smartBake = false 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 not mouseEvent.shiftKey then self.forceBoneTranslationShift = false end if not mouseEvent.altKey then self.forceBoneTranslationAlt = false end if mouseEvent.shiftKey and not self.forceBoneTranslationShift 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 MR_Utilities:IsEqual(v.x, bonePos.x, 0.000001) or not MR_Utilities: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 smartBake 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 subBoneVec = LM.Vector2:new_local() local inverseM = LM.Matrix:new_local() local parent = nil subBoneVec:Set(0, 0) if (sBone.fParent >= 0) then parent = skel:Bone(sBone.fParent) parent.fMovedMatrix:Transform(subBoneVec) end subBoneVec = subBoneVec + offset if (parent) then inverseM:Set(parent.fMovedMatrix) inverseM:Invert() inverseM:Transform(subBoneVec) end if mouseEvent.shiftKey and not self.forceBoneTranslationShift then if (math.abs(subBoneVec.x) > math.abs(subBoneVec.y)) then subBoneVec.y = 0 else subBoneVec.x = 0 end end local v = nil v = sBone.fPos + subBoneVec local bonePos = sBone.fAnimPos:GetValue(moho.layerFrame) if not MR_Utilities:IsEqual(v.x, bonePos.x, 0.000001) or not MR_Utilities:IsEqual(v.y, bonePos.y, 0.000001) then sBone.fAnimPos:SetValue(moho.layerFrame, v) if smartBake 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 MR_Utilities:Round(bone.fAnimScale:GetValue(0), 1) == 1) or not self.ignoreZeroScaledBones then if mouseEvent.altKey and bone.fLength > 0 and not self.forceBoneTranslationAlt then if (self.selBones == 1 and self.multiTransform and self.keepSelection) or (self.keepSelection and not self.multiTransform) or (not self.keepSelection) then local vectorMousePos = mouseEvent.vec + self.clickOffset local secondCursorDist = MR_Utilities:GetDistance(vectorMousePos, self.secondBoneTipPos) local secondDelta = (secondCursorDist / self.secondBoneDist) local newScale = (bone.fTempScale * secondDelta) - self.secondBoneSizeDelta if not MR_Utilities:IsEqual(newScale, bone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then bone.fAnimScale:SetValue(moho.layerFrame, newScale) if smartBake 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 MR_Utilities:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then bone.fAnimAngle:SetValue(moho.layerFrame, newAgle) bone.fAnimAngle.value = bone.fAngle end if smartBake 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 MR_Utilities: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 MR_Utilities: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 MR_Utilities: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 smartBake = self.bakeAdjacentFrames if MOHO.MohoGlobals.EditMultipleKeys then smartBake = false 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 MR_Utilities:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then bone.fAnimAngle:SetValue(moho.layerFrame, newAgle) if smartBake 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 MR_Utilities:IsEqual(newSelAgle, sBone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then sBone.fAnimAngle:SetValue(moho.layerFrame, newSelAgle) if smartBake 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 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 smartBake 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 MR_Utilities: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 smartBake = self.bakeAdjacentFrames if MOHO.MohoGlobals.EditMultipleKeys then smartBake = false 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 MR_Utilities:IsEqual(newScale, secondBone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then secondBone.fAnimScale:SetValue(moho.layerFrame, newScale) if smartBake 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 MR_Utilities:IsEqual(newSelectedScale, sBone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then sBone.fAnimScale:SetValue(moho.layerFrame, newSelectedScale) if smartBake 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 = MR_Utilities:GetDistance(vectorMousePos, self.secondBonePos) local secondDelta = (secondCursorDist / self.secondBoneDist) local newScale = (secondBone.fTempScale * secondDelta) - self.secondBoneSizeDelta if not MR_Utilities:IsEqual(newScale, secondBone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then secondBone.fAnimScale:SetValue(moho.layerFrame, newScale) if smartBake 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 MR_Utilities:IsEqual(newSelectedScale, sBone.fAnimScale:GetValue(moho.layerFrame), 0.000001) then sBone.fAnimScale:SetValue(moho.layerFrame, newSelectedScale) if smartBake 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 MR_Utilities:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then bone.fAnimAngle:SetValue(moho.layerFrame, newAgle) if smartBake 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 MR_Utilities:IsEqual(newAngle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then bone.fAnimAngle:SetValue(moho.layerFrame, newAngle) if smartBake 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 smartBake 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 smartBake 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 MR_Utilities: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 smartBake = self.bakeAdjacentFrames if MOHO.MohoGlobals.EditMultipleKeys then smartBake = false end local riggingFrame = 0 local bone = skel:Bone(self.selID) local secondBone = skel:Bone(self.selID) if smartBake 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 smartBake 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 smartBake and not self.boneBakedS then self:BakeFrames(moho, secondBone, nil, false, false, true) self.boneBakedS = true end local newStartBoneDist = MR_Utilities: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 MR_Utilities:IsEqual(parentBone.fTempAngle, parentBone.fAnimAngle:GetValue(moho.layerFrame), 0.0000001) then parentBone.fAnimAngle:SetValue(moho.layerFrame, parentBone.fTempAngle) end end if not MR_Utilities: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 smartBake 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 MR_Utilities:IsEqual(firstBone.fTempAngle, firstBone.fAnimAngle:GetValue(moho.layerFrame), 0.0000001) then firstBone.fAnimAngle:SetValue(moho.layerFrame, firstBone.fTempAngle) end end end end if smartBake 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 smartBake 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) self.buttonPressed = 0 self.operationFailes = 0 if self.scriptValidated ~= true then return end self.ignoreBonesList = {} moho:UpdateBonePointSelection() local frame = moho.frame if self.twosMode then if self.blockOnEvenFrames and frame % 2 == 0 or self.blockOnOddFrames and not (frame % 2 == 0) then moho:UpdateSelectedChannels() moho:UpdateUI() return end end self.dragging = false local skel = moho:Skeleton() if skel == nil or frame == 0 then moho:UpdateSelectedChannels() moho:UpdateUI() return end if self.showQuickMenu or self.showQuickMenu2 or self.showQuickMenu3 then moho:UpdateSelectedChannels() moho:UpdateUI() return end if self.lockHandlesSelection and self.isLockHandleMouseMoved then moho:UpdateSelectedChannels() moho:UpdateUI() return end if self.setKeyframe then moho:UpdateSelectedChannels() moho:UpdateUI() 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 local firstBone = skel:Bone(self.firstBoneID) if self.isBoneHaveAngleKeyList[self.firstBoneID] == false then firstBone.fAnimAngle:DeleteKey(moho.layerFrame) end if self.isBoneHaveScaleKeyList[self.firstBoneID] == false then firstBone.fAnimScale:DeleteKey(moho.layerFrame) end local secondBone = skel:Bone(self.secondBoneID) if self.isBoneHaveAngleKeyList[self.secondBoneID] == false then secondBone.fAnimAngle:DeleteKey(moho.layerFrame) end if self.isBoneHaveScaleKeyList[self.secondBoneID] == false then secondBone.fAnimScale:DeleteKey(moho.layerFrame) end if self.holdToReset then local upTime = os.time() if upTime - self.clickTime >= 2 then if self.selBonesList[self.secondBoneID] 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 = MR_Utilities: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 = MR_Utilities: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 skel:SelectNone() for i, boneID in ipairs(self.selectedBonesList) do local bone = skel:Bone(boneID) bone.fSelected = true end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE_T) moho:UpdateUI() 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 skel:SelectNone() for i, boneID in ipairs(self.selectedBonesList) do local bone = skel:Bone(boneID) bone.fSelected = true end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE) moho:UpdateUI() 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 skel:SelectNone() for i, boneID in ipairs(self.selectedBonesList) do local bone = skel:Bone(boneID) bone.fSelected = true end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE_S) moho:UpdateUI() return end else moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE_S) moho:UpdateUI() return end end end moho:UpdateSelectedChannels() moho:UpdateUI() self:OnMouseMoved(moho, mouseEvent) 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 self.secondBoneID = -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 if MOHO.MohoGlobals.AutoFreezeKeys then for i=0, skel:CountBones()-1 do local bone = skel:Bone(i) if not (bone.fHidden and not bone.fShy) then local frame = moho.layerFrame bone.fAnimAngle:SetValue(frame, bone.fAnimAngle:GetValue(frame)) bone.fAnimPos:SetValue(frame, bone.fAnimPos:GetValue(frame)) bone.fAnimScale:SetValue(frame, bone.fAnimScale:GetValue(frame)) end end end if MOHO.MohoGlobals.EditMultipleKeys then self:EditMultipleKeys(moho) 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 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 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 wireframe = MOHO.hasbit(moho.view:QualityFlags(), MOHO.bit(MOHO.LDQ_WIREFRAME)) if self.bonesDataActive and wireframe and not moho:IsPlaying() then 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 and self.bonesDataActiveA then g:SetPenWidth(10) g:SetColor(255, 241, 229, 255) local radius = 14 for b=1, #self.lockAngleList do local boneId = self.lockAngleList[b] local lockBone = skel:Bone(boneId) if lockBone then if not self.ignoreBonesList[boneId + 1] 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 end g:SetPenWidth(4) g:SetColor(self.lockAngleColor) for b=1, #self.lockAngleList do local boneId = self.lockAngleList[b] local lockBone = skel:Bone(boneId) if lockBone then if not self.ignoreBonesList[boneId + 1] 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(self.lockAngleColor) g:FillCirclePixelRadius(lockBoneCenter, radius) g:SetColor(self.iconColorBack) g:FrameCirclePixelRadius(lockBoneCenter, radius) g:SetColor(self.lockAngleColor) else g:DrawLine(lockBoneCenter.x, lockBoneCenter.y, lockBoneTip.x, lockBoneTip.y) end end end end g:SetPenWidth(1) end if #self.lockPosList > 0 and self.bonesDataActiveP then g:SetPenWidth(10) g:SetColor(self.iconColorBack) local radius = 10 for b=1, #self.lockPosList do local boneId = self.lockPosList[b] local lockBone = skel:Bone(boneId) if lockBone then if not self.ignoreBonesList[boneId + 1] 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 end g:SetPenWidth(4) g:SetColor(self.lockPosColor) for b=1, #self.lockPosList do local boneId = self.lockPosList[b] local lockBone = skel:Bone(boneId) if lockBone then if not self.ignoreBonesList[boneId + 1] 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(self.lockPosColor) g:FrameCirclePixelRadius(lockBoneCenter, radius) else g:DrawLine(lockBoneCenter.x, lockBoneCenter.y, lockBoneTip.x, lockBoneTip.y) end end end end g:SetPenWidth(1) end if not isFollowBonesSelected or self.forceFollowBonesGraphics then if #self.followBonesList.id > 0 and self.bonesDataActiveF then for b=1, #self.followBonesList.id do local isBlocked = false if self.dragging then if self.followBonesDataList.block and self.mode ~= 0 then isBlocked = self.followBonesDataList.block[b] end end if not isBlocked then g:SetPenWidth(2) g:SetColor(self.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 and self.mode ~= 0 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 boneId = self.followBonesList.id[b][i] local followBone = skel:Bone(boneId) if followBone then if not self.ignoreBonesList[boneId + 1] 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 end g:SetPenWidth(4) g:SetColor(self.colorFollowBones) for i=1, #self.followBonesList.id[b] do local boneId = self.followBonesList.id[b][i] local followBone = skel:Bone(boneId) if followBone then if not self.ignoreBonesList[boneId + 1] 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 end if self.dragging then g:SetColor(self.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 self.followBonesDataList.targetPos[b] then g:SetColor(self.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) end end g:SetPenWidth(1) end end end end if #self.ikBonesList.id > 0 and self.bonesDataActiveIK then for b=1, #self.ikBonesList.id do local isBlocked = false if self.dragging then if self.ikBonesDataList.block and self.mode ~= 0 then isBlocked = self.ikBonesDataList.block[b] end end if not isBlocked then g:SetPenWidth(2) g:SetColor(self.colorIkBones) for i=1, #self.ikBonesList.id[b] do local followBone = skel:Bone(self.ikBonesList.id[b][i]) if i + 1 <= #self.ikBonesList.id[b] then if followBone then local nextBone = skel:Bone(self.ikBonesList.id[b][i + 1]) if nextBone then local ikBoneCenter = LM.Vector2:new_local() local nextBoneCenter = LM.Vector2:new_local() ikBoneCenter:Set(followBone.fLength / 2, 0) nextBoneCenter:Set(nextBone.fLength / 2, 0) followBone.fMovedMatrix:Transform(ikBoneCenter) nextBone.fMovedMatrix:Transform(nextBoneCenter) g:DrawLine(ikBoneCenter.x, ikBoneCenter.y, nextBoneCenter.x, nextBoneCenter.y) end end end end g:SetPenWidth(1) end end for b=1, #self.ikBonesList.id do local isBlocked = false if self.dragging then if self.ikBonesDataList.block and self.mode ~= 0 then isBlocked = self.ikBonesDataList.block[b] end end if not isBlocked then g:SetPenWidth(10) g:SetColor(196, 235, 255, 255) for i=1, #self.ikBonesList.id[b] do local boneId = self.ikBonesList.id[b][i] local followBone = skel:Bone(boneId) if followBone then if not self.ignoreBonesList[boneId + 1] then local ikBoneCenter = LM.Vector2:new_local() local followBoneTip = LM.Vector2:new_local() ikBoneCenter:Set(followBone.fLength / 1.5, 0) followBoneTip:Set(followBone.fLength / 3, 0) followBone.fMovedMatrix:Transform(ikBoneCenter) followBone.fMovedMatrix:Transform(followBoneTip) g:DrawLine(ikBoneCenter.x, ikBoneCenter.y, followBoneTip.x, followBoneTip.y) end end end g:SetPenWidth(4) g:SetColor(self.colorIkBones) for i=1, #self.ikBonesList.id[b] do local boneId = self.ikBonesList.id[b][i] local followBone = skel:Bone(boneId) if followBone then if not self.ignoreBonesList[boneId + 1] then local ikBoneCenter = LM.Vector2:new_local() local followBoneTip = LM.Vector2:new_local() ikBoneCenter:Set(followBone.fLength / 1.5, 0) followBoneTip:Set(followBone.fLength / 3, 0) followBone.fMovedMatrix:Transform(ikBoneCenter) followBone.fMovedMatrix:Transform(followBoneTip) g:DrawLine(ikBoneCenter.x, ikBoneCenter.y, followBoneTip.x, followBoneTip.y) end end end if self.dragging then g:SetColor(self.colorHighlightBone) g:SetPenWidth(3) local markersSize = (0.015) / currentScale / height local marker1VecCam = self.ikBonesDataList.endBoneTipPos[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 self.ikBonesDataList.endBoneTipPos[b] then g:SetColor(self.colorHighlightBone) g:SetPenWidth(3) local markersSize = (0.015) / currentScale / height local marker1VecCam = self.ikBonesDataList.endBoneTipPos[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.showQuickMenu 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(MR_Utilities:RotateVector2(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(MR_Utilities:RotateVector2(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 MR_Utilities:GetDistance(globalBoneCenterPos, boneHandlePos) * currentScale * height < 0.065 then alignHandlesAdaptation = true end v:Set(bone.fLength * self.handlesDist, 0) bone.fMovedMatrix:Transform(v) local distanceValue = MR_Utilities: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 = MR_Utilities: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(self.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(MR_Utilities:RotateVector2(offset, boneCenterPos, angle)) else v:Set(MR_Utilities:RotateVector2(offset, v, angle)) end end if self.drawMode == 2 then if isPin then g:SetColor(self.colorScaleFillHL) else g:SetColor(self.colorScaleFillHL) end markerR = self.markerR + hlDelta else if isPin then g:SetColor(self.colorScaleFill) else g:SetColor(self.colorScaleFill) end markerR = self.markerR end if bone.fLength == 0 and self.keepHandles then markerR = markerR * 3 end if (self.ignoreZeroScaledBones and MR_Utilities:Round(bone.fAnimScale:GetValue(0), 1) == 1) or not self.ignoreZeroScaledBones then g:FillCirclePixelRadius(v, markerR) g:SetColor(self.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(MR_Utilities:RotateVector2(offset, v, newAngle)) if self.drawMode == 4 then g:SetColor(self.colorManipulateFillHL) markerR = self.markerR + hlDelta else g:SetColor(self.colorManipulateFill) markerR = self.markerR end g:FillCirclePixelRadius(v, markerR) g:SetColor(self.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(MR_Utilities:RotateVector2(offset, boneCenterPos, newAngle)) else v:Set(MR_Utilities:RotateVector2(offset, v, newAngle)) end end if self.drawMode == 0 or self.drawMode == 5 then g:SetColor(self.colorTranslateFillHL) markerR = self.markerR + hlDelta else g:SetColor(self.colorTranslateFill) markerR = self.markerR end g:FillCirclePixelRadius(v, markerR) g:SetColor(self.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(MR_Utilities:RotateVector2(offset, v, newAngle)) if self.drawMode == 3 then g:SetColor(self.colorMoveJointFillHL) markerR = self.markerR + hlDelta else g:SetColor(self.colorMoveJointFill) markerR = self.markerR end g:FillCirclePixelRadius(v, markerR) g:SetColor(self.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.showQuickMenu then self:DrawQuickMenu_1(moho, g) elseif self.showQuickMenu2 then self:DrawQuickMenu_2(moho, g) elseif self.showQuickMenu3 then self:DrawQuickMenu_3(moho, g) end if self.showQuickMenu and self.showQuickMenu4 and self.bonesDataActive then self:DrawQuickMenu_4(moho, g) end end -- ************************************************** -- Tool Panel Layout -- ************************************************** MR_PoseTool.TOGGLE_PANEL = MOHO.MSG_BASE MR_PoseTool.TWOS_MODE = MOHO.MSG_BASE + 1 MR_PoseTool.KEEP_SELECTION = MOHO.MSG_BASE + 2 MR_PoseTool.MULTI_TRANSFORM = MOHO.MSG_BASE + 3 MR_PoseTool.LOCK_HANDLES = MOHO.MSG_BASE + 4 MR_PoseTool.BAKE_ADJACENT_FRAMES = MOHO.MSG_BASE + 5 MR_PoseTool.INTERVAL_1 = MOHO.MSG_BASE + 6 MR_PoseTool.INTERVAL_2 = MOHO.MSG_BASE + 7 MR_PoseTool.INTERVAL_3 = MOHO.MSG_BASE + 8 MR_PoseTool.INTERVAL_4 = MOHO.MSG_BASE + 9 MR_PoseTool.INTERVAL_5 = MOHO.MSG_BASE + 10 MR_PoseTool.INTERVAL_6 = MOHO.MSG_BASE + 11 MR_PoseTool.SHOW_PATH = MOHO.MSG_BASE + 12 MR_PoseTool.RANGE = MOHO.MSG_BASE + 13 MR_PoseTool.RANGE_FRAMES = MOHO.MSG_BASE + 14 MR_PoseTool.FLIP_H = MOHO.MSG_BASE + 15 MR_PoseTool.FLIP_V = MOHO.MSG_BASE + 16 MR_PoseTool.RESET_A = MOHO.MSG_BASE + 17 MR_PoseTool.RESET_T = MOHO.MSG_BASE + 18 MR_PoseTool.RESET_S = MOHO.MSG_BASE + 19 MR_PoseTool.CHANGE_R = MOHO.MSG_BASE + 20 MR_PoseTool.CHANGE_T_X = MOHO.MSG_BASE + 21 MR_PoseTool.CHANGE_T_Y = MOHO.MSG_BASE + 22 MR_PoseTool.CHANGE_S = MOHO.MSG_BASE + 23 MR_PoseTool.INFO = MOHO.MSG_BASE + 24 MR_PoseTool.COPY_LINK = MOHO.MSG_BASE + 25 MR_PoseTool.SHOW_MORE_INFO = MOHO.MSG_BASE + 26 function MR_PoseTool:DoLayout(moho, layout) if self.scriptValidated == nil then self:ValidateScriptFiles(moho) end if self.scriptValidated ~= true then self.alertText = LM.GUI.DynamicText('Some script files are missing. Please download the script using the \"Download for Install Script\" button and install all script files.') layout:AddChild(self.alertText, LM.GUI.ALIGN_LEFT, 0) self.copyLinkButton = LM.GUI.ShortButton(self:Localize('Copy link to clipboard'), self.COPY_LINK) layout:AddChild(self.copyLinkButton, LM.GUI.ALIGN_FILL, 0) self.showMoreInfoButton = LM.GUI.ShortButton(self:Localize('Show more info'), self.SHOW_MORE_INFO) layout:AddChild(self.showMoreInfoButton, LM.GUI.ALIGN_FILL, 0) return end 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) self.togglePanelCheckbox = LM.GUI.ImageButton('ScriptResources/mr_pose_tool/mr_toggle_panel', self:Localize('Toggle panel'), true, self.TOGGLE_PANEL, false) layout:AddChild(self.togglePanelCheckbox, LM.GUI.ALIGN_FILL, 0) if not self.panelSizeShort then self.resetText = LM.GUI.DynamicText(self:Localize('Reset:')) layout:AddChild(self.resetText, LM.GUI.ALIGN_LEFT, 0) self.resetAButton = LM.GUI.ImageButton('ScriptResources/mr_pose_tool/mr_rotate', self:Localize('A'), false, self.RESET_A, false) self.resetAButton:SetToolTip(self:Localize('Reset angle')) layout:AddChild(self.resetAButton, LM.GUI.ALIGN_FILL, 0) self.resetPButton = LM.GUI.ImageButton('ScriptResources/mr_pose_tool/mr_translate', self:Localize('T'), false, self.RESET_T, false) self.resetPButton:SetToolTip(self:Localize('Reset translation')) layout:AddChild(self.resetPButton, LM.GUI.ALIGN_FILL, 0) self.resetSButton = LM.GUI.ImageButton('ScriptResources/mr_pose_tool/mr_scale', self:Localize('S'), false, self.RESET_S, false) self.resetSButton:SetToolTip(self:Localize('Reset scale')) layout:AddChild(self.resetSButton, LM.GUI.ALIGN_FILL, 0) else self.resetAButton = LM.GUI.ImageButton('ScriptResources/mr_pose_tool/mr_rotate', self:Localize('A'), false, self.RESET_A, false) self.resetAButton:SetToolTip(self:Localize('Reset angle')) layout:AddChild(self.resetAButton, LM.GUI.ALIGN_FILL, 0) self.angleInput = LM.GUI.TextControl(0, "000.000", self.CHANGE_R, LM.GUI.FIELD_FLOAT, '') self.angleInput:SetWheelInc(0.01) layout:AddChild(self.angleInput) self.resetPButton = LM.GUI.ImageButton('ScriptResources/mr_pose_tool/mr_translate', self:Localize('T'), false, self.RESET_T, false) self.resetPButton:SetToolTip(self:Localize('Reset translation')) layout:AddChild(self.resetPButton, LM.GUI.ALIGN_FILL, 0) self.translationInputX = LM.GUI.TextControl(0, "00.000", self.CHANGE_T_X, LM.GUI.FIELD_FLOAT, self:Localize('X')) self.translationInputX:SetWheelInc(0.1) layout:AddChild(self.translationInputX) self.translationInputY = LM.GUI.TextControl(0, "00.000", self.CHANGE_T_Y, LM.GUI.FIELD_FLOAT, self:Localize('Y')) self.translationInputY:SetWheelInc(0.1) layout:AddChild(self.translationInputY) self.resetSButton = LM.GUI.ImageButton('ScriptResources/mr_pose_tool/mr_scale', self:Localize('S'), false, self.RESET_S, false) self.resetSButton:SetToolTip(self:Localize('Reset scale')) layout:AddChild(self.resetSButton, LM.GUI.ALIGN_FILL, 0) self.scaleInput = LM.GUI.TextControl(0, "00.000", self.CHANGE_S, LM.GUI.FIELD_FLOAT, '') self.scaleInput:SetWheelInc(0.1) layout:AddChild(self.scaleInput) end 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.intervalMenu:AddItemAlphabetically(MOHO.Localize("5=5"), 0, self.INTERVAL_5) self.intervalMenu:AddItemAlphabetically(MOHO.Localize("6=6"), 0, self.INTERVAL_6) 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) self.endFlipButton = LM.GUI.ImageButton("ScriptResources/flip_bone_h", self:Localize('End flip'), false, self.FLIP_H, true) layout:AddChild(self.endFlipButton ) self.sideFlipButton = LM.GUI.ImageButton("ScriptResources/flip_bone_v", self:Localize('Side flip'), false, self.FLIP_V, true) layout:AddChild(self.sideFlipButton) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) self.infoButton = LM.GUI.ImageButton('ScriptResources/mr_pose_tool/mr_info', self:Localize('A'), false, self.INFO, false) self.infoButton:SetToolTip(self:Localize('Info')) layout:AddChild(self.infoButton, LM.GUI.ALIGN_FILL, 0) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) layout:AddChild(LM.GUI.StaticText('v'..self:Version())) end function MR_PoseTool:UpdateWidgets(moho) if not self.colorsGenerated then self:GenerateColors(moho) end if self.scriptValidated ~= true then return end 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 if self.sblCursor == nil then self.sblCursor = LM.GUI.Cursor(moho:UserContentDir()..'/Scripts/ScriptResources/mr_pose_tool/mr_select_bone_layer', 1, 1) end if not self.settingsPopup then return end local skel = moho:Skeleton() local layer = moho.layer if self.skeletonLayersNavigation then if self.ignoreUpdateWidgets then return end end self.togglePanelCheckbox:SetValue(self.panelSizeShort) if skel ~= nil and frame ~= 0 then self:LoadBonesData(layer) self:ValidateFollowList(moho) self:ValidateIkList(moho) self:ValidateLockList(moho) if #self.followBonesList.id > 0 or #self.ikBonesList.id > 0 or #self.lockPosList > 0 or #self.lockAngleList > 0 then local scriptInfo = layer:ScriptData() local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' if scriptInfo:HasKey(bonesDataActiveKey) then self.bonesDataActive = scriptInfo:GetBool(bonesDataActiveKey) else self.bonesDataActive = true end local bonesDataActiveFKey = self.scriptDataName..'bonesDataActiveF ' if scriptInfo:HasKey(bonesDataActiveFKey) then self.bonesDataActiveF = scriptInfo:GetBool(bonesDataActiveFKey) else self.bonesDataActiveF = true end local bonesDataActiveIKKey = self.scriptDataName..'bonesDataActiveIK ' if scriptInfo:HasKey(bonesDataActiveIKKey) then self.bonesDataActiveIK = scriptInfo:GetBool(bonesDataActiveIKKey) else self.bonesDataActiveIK = true end local bonesDataActiveAKey = self.scriptDataName..'bonesDataActiveA ' if scriptInfo:HasKey(bonesDataActiveAKey) then self.bonesDataActiveA = scriptInfo:GetBool(bonesDataActiveAKey) else self.bonesDataActiveA = true end local bonesDataActivePKey = self.scriptDataName..'bonesDataActiveP ' if scriptInfo:HasKey(bonesDataActivePKey) then self.bonesDataActiveP = scriptInfo:GetBool(bonesDataActivePKey) else self.bonesDataActiveP = true end local singleFollowBonesModeKey = self.scriptDataName..'singleFollowBonesMode ' if scriptInfo:HasKey(singleFollowBonesModeKey) then self.singleFollowBonesMode = scriptInfo:GetBool(singleFollowBonesModeKey) else self.singleFollowBonesMode = true end local scaleFollowBonesKey = self.scriptDataName..'boneStretching ' if scriptInfo:HasKey(scaleFollowBonesKey) then self.boneStretching = scriptInfo:GetBool(scaleFollowBonesKey) else self.boneStretching = true end if #self.followBonesList.id > 0 or #self.ikBonesList.id > 0 then self:SetBoneStretching(moho, true) end else self.bonesDataActive = true local scriptInfo = layer:ScriptData() local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' scriptInfo:Set(bonesDataActiveKey, true) local singleFollowBonesModeKey = self.scriptDataName..'singleFollowBonesMode ' scriptInfo:Set(singleFollowBonesModeKey, false) self.singleFollowBonesMode = false self.boneStretchingIconStatus = false end 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) self.bakeAdjacentFramesCheckbox:Enable(not MOHO.MohoGlobals.EditMultipleKeys) if self.panelSizeShort then self.togglePanelCheckbox:SetToolTip(self:Localize('Show compact panel')) if skel and self.angleInput ~= nil then local selID = skel:SelectedBoneID() local selBones = moho:CountSelectedBones(true) if selBones > 0 then local selCount = 0 local angle = 0 for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected) then selCount = selCount + 1 angle = angle + bone.fAngle end end self.angleInput:SetValue(math.deg(angle) / selCount) else self.angleInput:SetValue("") end if (selID >= 0) then local bone = skel:Bone(selID) self.translationInputX:SetValue(bone.fPos.x) self.translationInputY:SetValue(bone.fPos.y) else self.translationInputX:SetValue("") self.translationInputY:SetValue("") end if selBones > 0 then local selCount = 0 local scale = 0 for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected) then selCount = selCount + 1 scale = scale + bone.fScale end end self.scaleInput:SetValue(scale / selCount) else self.scaleInput:SetValue("") end else self.angleInput:SetValue("") self.translationInputX:SetValue("") self.translationInputY:SetValue("") self.scaleInput:SetValue("") end else self.togglePanelCheckbox:SetToolTip(self:Localize('Show full panel')) end if self.interval < 1 or self.interval > 6 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) self.intervalMenu:SetChecked(self.INTERVAL_5, false) self.intervalMenu:SetChecked(self.INTERVAL_6, 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) elseif (self.interval == 5) then self.intervalMenu:SetChecked(self.INTERVAL_5, true) elseif (self.interval == 6) then self.intervalMenu:SetChecked(self.INTERVAL_6, 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.TOGGLE_PANEL then self.panelSizeShort = self.togglePanelCheckbox:Value() local drawingToolsNonZero = MOHO.MohoGlobals.DisableDrawingToolsNonZero if not drawingToolsNonZero then MOHO.MohoGlobals.DisableDrawingToolsNonZero = true end local frame = moho.frame local curLayer = moho.layer if moho.layer:LayerType() ~= MOHO.LT_BONE and moho.layer:LayerType() ~= MOHO.LT_VECTOR then local count = 0 repeat local layer = moho.document:LayerByAbsoluteID(count) if layer then count = count + 1 if layer:LayerType() == MOHO.LT_BONE or layer:LayerType() == MOHO.LT_BONE then moho:SetSelLayer(layer) break end end until not layer end if frame == 0 then moho:SetCurFrame(1) moho:SetSelLayer(curLayer) moho:SetCurFrame(0) elseif frame ~= 0 then moho:SetCurFrame(0) moho:SetSelLayer(curLayer) moho:SetCurFrame(frame) end if not drawingToolsNonZero then MOHO.MohoGlobals.DisableDrawingToolsNonZero = drawingToolsNonZero end elseif 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 if MOHO.MohoGlobals.EditMultipleKeys then self.bakeAdjacentFramesCheckbox:SetValue(self.bakeAdjacentFrames) self:UpdateWidgets(moho) else self.bakeAdjacentFrames = self.bakeAdjacentFramesCheckbox:Value() self.intervalPopup:Enable(self.bakeAdjacentFrames) end elseif (msg >= self.INTERVAL_1 and msg <= self.INTERVAL_6) 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 elseif (msg == self.INTERVAL_5) then int = 5 elseif (msg == self.INTERVAL_6) then int = 6 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) elseif (msg == self.RESET_A) then local skel = moho:Skeleton() if skel then if MOHO.MohoGlobals.EditMultipleKeys then self:PrepareToEditMultipleKeys(moho) end if (moho:CountSelectedBones(true) > 0) then 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 bone.fAnimAngle:SetValue(moho.layerFrame, bone.fAnimAngle:GetValue(0)) end end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE) self:UpdateWidgets(moho) end if MOHO.MohoGlobals.EditMultipleKeys then self:EditMultipleKeys(moho) moho.layer:UpdateCurFrame() moho:UpdateSelectedChannels() end end elseif (msg == self.RESET_T) then local skel = moho:Skeleton() if skel then if MOHO.MohoGlobals.EditMultipleKeys then self:PrepareToEditMultipleKeys(moho) end if (moho:CountSelectedBones(true) > 0) then 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 bone.fAnimPos:SetValue(moho.layerFrame, bone.fAnimPos:GetValue(0)) end end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE_T) self:UpdateWidgets(moho) end if MOHO.MohoGlobals.EditMultipleKeys then self:EditMultipleKeys(moho) moho.layer:UpdateCurFrame() moho:UpdateSelectedChannels() end end elseif (msg == self.RESET_S) then local skel = moho:Skeleton() if skel then if MOHO.MohoGlobals.EditMultipleKeys then self:PrepareToEditMultipleKeys(moho) end if (moho:CountSelectedBones(true) > 0) then 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 bone.fAnimScale:SetValue(moho.layerFrame, bone.fAnimScale:GetValue(0)) end end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE_S) self:UpdateWidgets(moho) end if MOHO.MohoGlobals.EditMultipleKeys then self:EditMultipleKeys(moho) moho.layer:UpdateCurFrame() moho:UpdateSelectedChannels() end end elseif (msg == self.CHANGE_R) then local skel = moho:Skeleton() if skel then if MOHO.MohoGlobals.EditMultipleKeys then self:PrepareToEditMultipleKeys(moho) end if (moho:CountSelectedBones(true) > 0) then 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 bone.fAngle = math.rad(self.angleInput:FloatValue()) bone.fAnimAngle:SetValue(moho.layerFrame, bone.fAngle) end end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE) else self.angleInput:SetValue('') end if MOHO.MohoGlobals.EditMultipleKeys then self:EditMultipleKeys(moho) moho.layer:UpdateCurFrame() moho:UpdateSelectedChannels() end else self.angleInput:SetValue('') end elseif (msg == self.CHANGE_T_X) then local skel = moho:Skeleton() if skel then if MOHO.MohoGlobals.EditMultipleKeys then self:PrepareToEditMultipleKeys(moho) end if (moho:CountSelectedBones(true) > 0) then 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 bone.fPos.x = self.translationInputX:FloatValue() bone.fAnimPos:SetValue(moho.layerFrame, bone.fPos) end end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE_T) else self.translationInputX:SetValue('') end if MOHO.MohoGlobals.EditMultipleKeys then self:EditMultipleKeys(moho) moho.layer:UpdateCurFrame() moho:UpdateSelectedChannels() end else self.translationInputX:SetValue('') end elseif (msg == self.CHANGE_T_Y) then local skel = moho:Skeleton() if skel then if MOHO.MohoGlobals.EditMultipleKeys then self:PrepareToEditMultipleKeys(moho) end if (moho:CountSelectedBones(true) > 0) then 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 bone.fPos.y = self.translationInputY:FloatValue() bone.fAnimPos:SetValue(moho.layerFrame, bone.fPos) end end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE_T) else self.translationInputY:SetValue('') end if MOHO.MohoGlobals.EditMultipleKeys then self:EditMultipleKeys(moho) moho.layer:UpdateCurFrame() moho:UpdateSelectedChannels() end else self.translationInputY:SetValue('') end elseif (msg == self.CHANGE_S) then local skel = moho:Skeleton() if skel then if MOHO.MohoGlobals.EditMultipleKeys then self:PrepareToEditMultipleKeys(moho) end if (moho:CountSelectedBones(true) > 0) then 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 bone.fScale = self.scaleInput:FloatValue() bone.fAnimScale:SetValue(moho.layerFrame, bone.fScale) end end moho.layer:UpdateCurFrame() moho:NewKeyframe(CHANNEL_BONE_S) else self.scaleInput:SetValue('') end if MOHO.MohoGlobals.EditMultipleKeys then self:EditMultipleKeys(moho) moho.layer:UpdateCurFrame() moho:UpdateSelectedChannels() end else self.scaleInput:SetValue('') end elseif (msg == self.INFO) then local poseToolInfoDlog = MR_PoseToolInfoDialog:new(moho) poseToolInfoDlog = MR_PoseToolInfoDialog:new(moho) if poseToolInfoDlog then poseToolInfoDlog:DoModal() end elseif (msg == self.COPY_LINK) then local linkText = self:Localize('Script link') moho:CopyText(linkText) elseif (msg == self.SHOW_MORE_INFO) then self:ValidateScriptFiles(moho) 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 MR_Utilities:Round(secondBone.fPos.y) == 0 and not MR_Utilities: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(MR_Utilities:RotateVector2(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(MR_Utilities:RotateVector2(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 MR_Utilities:GetDistance(globalBoneCenterPos, boneHandlePos) * currentScale * height < 0.065 then alignHandlesAdaptation = true end v:Set(bone.fLength * self.handlesDist, 0) bone.fMovedMatrix:Transform(v) local distanceValue = MR_Utilities: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 = MR_Utilities: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(MR_Utilities:RotateVector2(offset, boneCenterPos, newAngle)) else v:Set(MR_Utilities:RotateVector2(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(MR_Utilities:RotateVector2(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(MR_Utilities:RotateVector2(offset, boneCenterPos, newAngle)) else v:Set(MR_Utilities:RotateVector2(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 MR_Utilities: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(MR_Utilities:RotateVector2(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:AddToFollowBonesChains(moho) local skel = moho:Skeleton() if skel == nil then return end local selectedBonesId = {} local selectedBonesNames = {} local isValid = true local scriptInfo = moho.layer:ScriptData() self.bonesDataActive = true local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' scriptInfo:Set(bonesDataActiveKey, self.bonesDataActive) self.bonesDataActiveF = true local bonesDataActiveFKey = self.scriptDataName..'bonesDataActiveF ' scriptInfo:Set(bonesDataActiveFKey, self.bonesDataActiveF) self:LoadBonesData(moho.layer) self:ValidateFollowList(moho) self:ValidateIkList(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) self:RemoveSelectedBonesFromIkList(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) table.insert(self.followBonesList.stretching, false) for _, id in ipairs(followBonesChainsList[c]) do local boneID = id local existInList = MR_Utilities:ValueExists(self.lockAngleList, boneID) if existInList then table.remove(self.lockAngleList, existInList) table.remove(self.lockAngleBoneNamesList, existInList) end existInList = MR_Utilities:ValueExists(self.lockPosList, boneID) if existInList then table.remove(self.lockPosList, existInList) table.remove(self.lockPosBoneNamesList, existInList) end end end self:SaveBonesData(moho.layer) end function MR_PoseTool:AddToIKBonesChains(moho) local skel = moho:Skeleton() if skel == nil then return end local selectedBonesId = {} local selectedBonesNames = {} local isValid = true local scriptInfo = moho.layer:ScriptData() self.bonesDataActive = true local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' scriptInfo:Set(bonesDataActiveKey, self.bonesDataActive) self:LoadBonesData(moho.layer) self:ValidateIkList(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 ikBonesChainsList = {} 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(ikBonesChainsList, group) end end end local ikBonesChainsNamesList = {} for i, a in ipairs(ikBonesChainsList) do local ikBonesNamesList = {} for n, id in ipairs(ikBonesChainsList[i]) do local bone = skel:Bone(id) table.insert(ikBonesNamesList, bone:Name()) end table.insert(ikBonesChainsNamesList, ikBonesNamesList) end local areNewIK = false for c, a in ipairs(ikBonesChainsList) do local startBone = ikBonesChainsList[c][1] local endBone = ikBonesChainsList[c][#ikBonesChainsList[c]] local isStartBoneTargeted = skel:TargetOfBoneChain(startBone, moho.layerFrame) local isEndBoneTargeted = skel:TargetOfBoneChain(endBone, moho.layerFrame) local sBone = skel:Bone(startBone) local eBone = skel:Bone(endBone) if #ikBonesChainsList[c] == 2 and isStartBoneTargeted == -1 and isEndBoneTargeted == -1 and not sBone.fFixedAngle and not eBone.fFixedAngle and not sBone.fIgnoredByIK and not eBone.fIgnoredByIK then areNewIK = true local existInList local removeList = {} for i, id in ipairs(self.ikBonesList.id) do existInList = MR_Utilities:ValueExists(self.ikBonesList.id[i], startBone) if not existInList then existInList = MR_Utilities:ValueExists(self.ikBonesList.id[i], endBone) end if existInList then existInList = i table.insert(removeList, existInList) end end if #removeList > 0 then table.sort(removeList, function(a, b) return MR_Utilities:Compare(a, b) end) for i, v in ipairs(removeList) do table.remove(self.ikBonesList.id, v) table.remove(self.ikBonesList.names, v) table.remove(self.ikBonesList.startBone, v) table.remove(self.ikBonesList.endBone, v) table.remove(self.ikBonesList.stretching, v) end end removeList = {} existInList = nil for i, id in ipairs(self.followBonesList.id) do existInList = MR_Utilities:ValueExists(self.followBonesList.id[i], startBone) if not existInList then existInList = MR_Utilities:ValueExists(self.followBonesList.id[i], endBone) end if existInList then existInList = i table.insert(removeList, existInList) end end if #removeList > 0 then table.sort(removeList, function(a, b) return MR_Utilities:Compare(a, b) end) 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) table.remove(self.followBonesList.stretching, v) end end end end for c, a in ipairs(ikBonesChainsList) do local startBone = ikBonesChainsList[c][1] local endBone = ikBonesChainsList[c][#ikBonesChainsList[c]] local isStartBoneTargeted = skel:TargetOfBoneChain(startBone, moho.layerFrame) local isEndBoneTargeted = skel:TargetOfBoneChain(endBone, moho.layerFrame) local sBone = skel:Bone(startBone) local eBone = skel:Bone(endBone) if #ikBonesChainsList[c] == 2 and isStartBoneTargeted == -1 and isEndBoneTargeted == -1 and not sBone.fFixedAngle and not eBone.fFixedAngle and not sBone.fIgnoredByIK and not eBone.fIgnoredByIK then table.insert(self.ikBonesList.id, ikBonesChainsList[c]) table.insert(self.ikBonesList.names, ikBonesChainsNamesList[c]) table.insert(self.ikBonesList.startBone, startBone) table.insert(self.ikBonesList.endBone, endBone) table.insert(self.ikBonesList.stretching, false) for _, id in ipairs(ikBonesChainsList[c]) do local boneID = id local existInList = MR_Utilities:ValueExists(self.lockAngleList, boneID) if existInList then table.remove(self.lockAngleList, existInList) table.remove(self.lockAngleBoneNamesList, existInList) end existInList = MR_Utilities:ValueExists(self.lockPosList, boneID) if existInList then table.remove(self.lockPosList, existInList) table.remove(self.lockPosBoneNamesList, existInList) end end end end if not areNewIK and moho:CountSelectedBones() > 0 then self.operationFailes = 2 moho.view:DrawMe() else self.bonesDataActiveIK = true local bonesDataActiveIKKey = self.scriptDataName..'bonesDataActiveIK ' scriptInfo:Set(bonesDataActiveIKKey, self.bonesDataActiveIK) end self:SaveBonesData(moho.layer) end function MR_PoseTool:AddToFollowBones(moho) local skel = moho:Skeleton() if skel == nil then return end local scriptInfo = moho.layer:ScriptData() self.bonesDataActive = true local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' scriptInfo:Set(bonesDataActiveKey, self.bonesDataActive) self.bonesDataActiveF = true local bonesDataActiveFKey = self.scriptDataName..'bonesDataActiveF ' scriptInfo:Set(bonesDataActiveFKey, self.bonesDataActiveF) self:LoadBonesData(moho.layer) self:ValidateFollowList(moho) self:RemoveSelectedBonesFromFollowList(moho) self:RemoveSelectedBonesFromIkList(moho) for i=0, skel:CountBones()-1 do local bone = skel:Bone(i) if bone.fSelected and not bone:IsZeroLength() then local followBonesIdList = {} table.insert(followBonesIdList, i) table.insert(self.followBonesList.id, followBonesIdList) local followBonesNameList = {} table.insert(followBonesNameList, bone:Name()) table.insert(self.followBonesList.names, followBonesNameList) table.insert(self.followBonesList.startBone, i) table.insert(self.followBonesList.endBone, i) table.insert(self.followBonesList.stretching, false) for _, id in ipairs(followBonesIdList) do local boneID = id local existInList = MR_Utilities:ValueExists(self.lockAngleList, boneID) if existInList then table.remove(self.lockAngleList, existInList) table.remove(self.lockAngleBoneNamesList, existInList) end existInList = MR_Utilities:ValueExists(self.lockPosList, boneID) if existInList then table.remove(self.lockPosList, existInList) table.remove(self.lockPosBoneNamesList, existInList) end end end end self.forceFollowBonesGraphics = true self:SaveBonesData(moho.layer) end function MR_PoseTool:AdjustFollowBones(moho, index) if not self.followBonesList.id or #self.followBonesList.id < 1 then return end local b = index local endFollowBoneId = self.followBonesList.endBone[b] if self.ignoreBonesList[endFollowBoneId + 1] == true then return end local skel = moho:Skeleton() if skel == nil then return end if self.followBonesDataList.block[b] and self.mode ~= 0 then return end local smartBake = self.bakeAdjacentFrames if MOHO.MohoGlobals.EditMultipleKeys then smartBake = false 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 skel:UpdateBoneMatrix() 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.boneStretching and self.followBonesList.stretching[b] then local secondCursorDist = MR_Utilities: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 smartBake 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 MR_Utilities:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then bone.fAnimAngle:SetValue(moho.layerFrame, newAgle) if smartBake 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:AdjustIkBones(moho, index) if not self.ikBonesList.id or #self.ikBonesList.id < 1 then return end local b = index local endIkBoneId = self.ikBonesList.endBone[b] if self.ignoreBonesList[endIkBoneId + 1] == true and not self.ikBonesList.reverseList[b] then return end local smartBake = self.bakeAdjacentFrames if MOHO.MohoGlobals.EditMultipleKeys then smartBake = false end local skel = moho:Skeleton() if skel == nil then return end if self.ikBonesDataList.block[b] and self.mode ~= 0 and not self.ikBonesList.reverseList[b] then return end local startIkBone = skel:Bone(self.ikBonesList.startBone[b]) local endIkBone = skel:Bone(self.ikBonesList.endBone[b]) if not startIkBone or not endIkBone then return end if self.boneStretching and self.ikBonesDataList.needKey[b] and self.ikBonesList.stretching[b] then startIkBone.fAnimScale:SetValue(moho.layerFrame, endIkBone.fTempScale - self.ikBonesDataList.startBoneScaleDelta[b]) endIkBone.fAnimScale:SetValue(moho.layerFrame, endIkBone.fTempScale - self.ikBonesDataList.endBoneScaleDelta[b]) end skel:UpdateBoneMatrix() moho.layer:UpdateCurFrame() local base1 = LM.Vector2:new_local() local tip1 = LM.Vector2:new_local() local base2 = LM.Vector2:new_local() local tip2 = LM.Vector2:new_local() base1:Set(0, 0) tip1:Set(startIkBone.fLength, 0) base2:Set(0, 0) tip2:Set(endIkBone.fLength, 0) if moho.frame == 0 then startIkBone.fRestMatrix:Transform(base1) startIkBone.fRestMatrix:Transform(tip1) endIkBone.fRestMatrix:Transform(base2) endIkBone.fRestMatrix:Transform(tip2) else startIkBone.fMovedMatrix:Transform(base1) startIkBone.fMovedMatrix:Transform(tip1) endIkBone.fMovedMatrix:Transform(base2) endIkBone.fMovedMatrix:Transform(tip2) end local length1 = self.ikBonesDataList.startBoneLength[b] local length2 = self.ikBonesDataList.endtBoneLength[b] local target = self.ikBonesDataList.endBoneTipPos[b] local distBase1ToTarget = MR_Utilities:GetDistance(base1, target) local newBase2 = LM.Vector2:new_local() local newTip2 = LM.Vector2:new_local() if distBase1ToTarget > (length1 + length2) then self.ikBonesDataList.needKey[b] = true local directionAngle = MR_Utilities:GetAngle(base1, target) if self.boneStretching and self.ikBonesList.stretching[b] then local newBoneDistDelta = distBase1ToTarget / (length1 + length2) newBase2:Set(base1.x + length1 * newBoneDistDelta * math.cos(directionAngle), base1.y + length1 * newBoneDistDelta * math.sin(directionAngle)) newTip2:Set(target) else newBase2:Set(base1.x + length1 * math.cos(directionAngle), base1.y + length1 * math.sin(directionAngle)) newTip2:Set(newBase2.x + length2 * (target.x - newBase2.x) / MR_Utilities:GetDistance(newBase2, target), newBase2.y + length2 * (target.y - newBase2.y) / MR_Utilities:GetDistance(newBase2, target)) end else local aV = length1 local bV = length2 local cV = distBase1ToTarget local cosAngle = (aV^2 + cV^2 - bV^2) / (2 * aV * cV) local angle = math.acos(cosAngle) local directionAngle = MR_Utilities:GetAngle(base1, target) local newTip1 = LM.Vector2:new_local() if self.ikBonesList.reverseList[b] then if self.ikBonesDataList.initialDirection[b] > 0 then newTip1:Set(base1.x + length1 * math.cos(directionAngle + angle), base1.y + length1 * math.sin(directionAngle + angle)) else newTip1:Set(base1.x + length1 * math.cos(directionAngle - angle), base1.y + length1 * math.sin(directionAngle - angle)) end else if self.ikBonesDataList.initialDirection[b] < 0 then newTip1:Set(base1.x + length1 * math.cos(directionAngle + angle), base1.y + length1 * math.sin(directionAngle + angle)) else newTip1:Set(base1.x + length1 * math.cos(directionAngle - angle), base1.y + length1 * math.sin(directionAngle - angle)) end end newBase2 = newTip1 newTip2:Set(newBase2.x + length2 * math.cos(MR_Utilities:GetAngle(newBase2, target)), newBase2.y + length2 * math.sin(MR_Utilities:GetAngle(newBase2, target))) if newBase2.x ~= newBase2.x or newBase2.y ~= newBase2.y then local directionAngle = MR_Utilities:GetAngle(target, base1) newBase2:Set(target.x + length1 * math.cos(directionAngle), target.y + length1 * math.sin(directionAngle)) local distNewBase2ToTarget = MR_Utilities:GetDistance(newBase2, target) newTip2:Set(newBase2.x + length2 * (target.x - newBase2.x) / distNewBase2ToTarget, newBase2.y + length2 * (target.y - newBase2.y) / distNewBase2ToTarget) end end skel:IKAngleSolver(self.ikBonesList.startBone[b], newBase2) local startBoneNewAngle = startIkBone.fAngle - self.ikBonesDataList.startAngleDelta[b] if not startIkBone.fFixedAngle then if startIkBone.fConstraints then local min = startIkBone.fAnimAngle:GetValue(0) - self.ikBonesDataList.startAngleDelta[b] local max = min + startIkBone.fMaxConstraint min = min + startIkBone.fMinConstraint startBoneNewAngle = LM.Clamp(startBoneNewAngle, min, max) end end if not MR_Utilities:IsEqual(startBoneNewAngle, startIkBone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then startIkBone.fAnimAngle:SetValue(moho.layerFrame, startBoneNewAngle) startIkBone.fAnimAngle.value = startIkBone.fAngle if smartBake and not self.ikBonesDataList.startBoneBakedA[b] then if moho.layerFrame - self.interval > 0 then startIkBone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.ikBonesDataList.startBoneFAngleP[b]) end if moho.layerFrame + self.interval > 0 then startIkBone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.ikBonesDataList.startBoneFAngleN[b]) end self.ikBonesDataList.startBoneBakedA[b] = true end end if self.boneStretching and self.ikBonesDataList.needKey[b] and self.ikBonesList.stretching[b] then local newBoneDistDelta = distBase1ToTarget / (length1 + length2) if distBase1ToTarget <= (length1 + length2) then newBoneDistDelta = 1 end local startBoneNewScale = (startIkBone.fTempScale * newBoneDistDelta) - self.ikBonesDataList.startBoneScaleDelta[b] local endBoneNewScale = (endIkBone.fTempScale * newBoneDistDelta) - self.ikBonesDataList.endBoneScaleDelta[b] startIkBone.fAnimScale:SetValue(moho.layerFrame, startBoneNewScale) endIkBone.fAnimScale:SetValue(moho.layerFrame, endBoneNewScale) skel:UpdateBoneMatrix() moho.layer:UpdateCurFrame() end skel:IKAngleSolver(self.ikBonesList.endBone[b], newTip2, 1, false, true) local endBoneNewAngle = endIkBone.fAngle - self.ikBonesDataList.endAngleDelta[b] if not endIkBone.fFixedAngle then if endIkBone.fConstraints then local min = endIkBone.fAnimAngle:GetValue(0) - self.ikBonesDataList.endAngleDelta[b] local max = min + endIkBone.fMaxConstraint min = min + endIkBone.fMinConstraint endBoneNewAngle = LM.Clamp(endBoneNewAngle, min, max) end end if not MR_Utilities:IsEqual(endBoneNewAngle, endIkBone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then endIkBone.fAnimAngle:SetValue(moho.layerFrame, endBoneNewAngle) endIkBone.fAnimAngle.value = endIkBone.fAngle if smartBake and not self.ikBonesDataList.endBoneBakedA[b] then if moho.layerFrame - self.interval > 0 then endIkBone.fAnimAngle:SetValue(moho.layerFrame - self.interval, self.ikBonesDataList.endBoneFAngleP[b]) end if moho.layerFrame + self.interval > 0 then endIkBone.fAnimAngle:SetValue(moho.layerFrame + self.interval, self.ikBonesDataList.endBoneFAngleN[b]) end self.ikBonesDataList.endBoneBakedA[b] = true end end if self.boneStretching and self.ikBonesDataList.needKey[b] and self.ikBonesList.stretching[b] then if smartBake and not self.ikBonesDataList.startBoneBakedS[b] then if moho.layerFrame - self.interval > 0 then startIkBone.fAnimScale:SetValue(moho.layerFrame - self.interval, self.ikBonesDataList.startBoneFScaleP[b]) end if moho.layerFrame + self.interval > 0 then startIkBone.fAnimScale:SetValue(moho.layerFrame + self.interval, self.ikBonesDataList.startBoneFScaleN[b]) end self.ikBonesDataList.startBoneBakedS[b] = true end if smartBake and not self.ikBonesDataList.endBoneBakedS[b] then if moho.layerFrame - self.interval > 0 then endIkBone.fAnimScale:SetValue(moho.layerFrame - self.interval, self.ikBonesDataList.endBoneFScaleP[b]) end if moho.layerFrame + self.interval > 0 then endIkBone.fAnimScale:SetValue(moho.layerFrame + self.interval, self.ikBonesDataList.endBoneFScaleN[b]) end self.ikBonesDataList.startBoneBakedS[b] = true end end end function MR_PoseTool:AdjustLockPos(moho, index) if not self.lockPosList or #self.lockPosList < 1 then return end local i = index local lockPosId = self.lockPosList[i] if self.ignoreBonesList[lockPosId + 1] == true then return end local skel = moho:Skeleton() if skel == nil then return end local smartBake = self.bakeAdjacentFrames if MOHO.MohoGlobals.EditMultipleKeys then smartBake = false end 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 MR_Utilities:IsEqual(newPos.x, originalPosVal.x, 0.000001) or not MR_Utilities:IsEqual(newPos.y, originalPosVal.y, 0.000001) then bone.fAnimPos:SetValue(moho.layerFrame, newPos) if smartBake 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 end function MR_PoseTool:AdjustLockAngles(moho, index) if not self.lockAngleList or #self.lockAngleList < 1 then return end local i = index local lockAngleId = self.lockAngleList[i] if self.ignoreBonesList[lockAngleId + 1] == true then return end local skel = moho:Skeleton() if skel == nil then return end local smartBake = self.bakeAdjacentFrames if MOHO.MohoGlobals.EditMultipleKeys then smartBake = false end 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 MR_Utilities:IsEqual(newAgle, bone.fAnimAngle:GetValue(moho.layerFrame), 0.000001) then bone.fAnimAngle:SetValue(moho.layerFrame, newAgle) if smartBake 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 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(MR_Utilities:RotateVector2(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(MR_Utilities:RotateVector2(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(MR_Utilities:RotateVector2(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(MR_Utilities:RotateVector2(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(MR_Utilities:RotateVector2(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(MR_Utilities:RotateVector2(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 if self.showQuickMenu and self.showQuickMenu4 and self.bonesDataActive then local iconCenter = LM.Vector2:new_local() center:Set(self.graphicsMenuCenter) center:Set(center.x, center.y - 0.15 / currentScale / height) local buttonsWidth = 0.05 / currentScale / height v:Set(center.x - buttonsWidth - buttonsWidth, center.y) radius = 12 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 7 -- F end v:Set(center.x - buttonsWidth, center.y) radius = 12 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 8 -- IK end v:Set(center.x, center.y) radius = 12 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 9 -- A end v:Set(center.x + buttonsWidth, center.y) radius = 12 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 10 -- P end v:Set(center.x + buttonsWidth * 2, center.y) radius = 12 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 11 -- S end if self.skeletonLayersNavigation then v:Set(center) local radiusX = 120 local radiusY = 50 mouseEvent.view:Graphics():WorldToScreen(v, pt) if (math.abs(pt.x - mouseEvent.pt.x) < radiusX and math.abs(pt.y - mouseEvent.pt.y) < radiusY) then return 100 -- Block skeleton pick end end end if self.skeletonLayersNavigation then center:Set(self.graphicsMenuCenter) v:Set(center) radius = 110 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 100 -- Block skeleton pick end end return 0 end function MR_PoseTool:AddToLockAngleList(moho) local skel = moho:Skeleton() if not skel then return end local scriptInfo = moho.layer:ScriptData() self.bonesDataActive = true local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' scriptInfo:Set(bonesDataActiveKey, self.bonesDataActive) self.bonesDataActiveA = true local bonesDataActiveAKey = self.scriptDataName..'bonesDataActiveA ' scriptInfo:Set(bonesDataActiveAKey, self.bonesDataActiveA) self:LoadBonesData(moho.layer) self:RemoveSelectedBonesFromFollowList(moho) self:RemoveSelectedBonesFromIkList(moho) self:ValidateLockList(moho) for i = 0, skel:CountBones()-1 do local bone = skel:Bone(i) if bone.fSelected then local existInList = MR_Utilities: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:SaveBonesData(moho.layer) end function MR_PoseTool:AddToLockPosList(moho) local skel = moho:Skeleton() if not skel then return end local scriptInfo = moho.layer:ScriptData() self.bonesDataActive = true local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' scriptInfo:Set(bonesDataActiveKey, self.bonesDataActive) self.bonesDataActiveP = true local bonesDataActivePKey = self.scriptDataName..'bonesDataActiveP ' scriptInfo:Set(bonesDataActivePKey, self.bonesDataActiveP) self:LoadBonesData(moho.layer) self:RemoveSelectedBonesFromFollowList(moho) self:RemoveSelectedBonesFromIkList(moho) self:ValidateLockList(moho) for i = 0, skel:CountBones()-1 do local bone = skel:Bone(i) if bone.fSelected then local existInList = MR_Utilities: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:SaveBonesData(moho.layer) end function MR_PoseTool:RemoveFromLockList(moho) local skel = moho:Skeleton() if not skel then return end self:LoadBonesData(moho.layer) 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 = MR_Utilities:ValueExists(self.lockAngleList, i) if existInList then table.remove(self.lockAngleList, existInList) table.remove(self.lockAngleBoneNamesList, existInList) end end if self.lockPosList then existInList = MR_Utilities:ValueExists(self.lockPosList, i) if existInList then table.remove(self.lockPosList, existInList) table.remove(self.lockPosBoneNamesList, existInList) end end end end self:SaveBonesData(moho.layer) end function MR_PoseTool:RemoveFromFollowList(moho) local skel = moho:Skeleton() if not skel then return end self:LoadBonesData(moho.layer) 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 = MR_Utilities:ValueExists(self.lockAngleList, i) if existInList then table.remove(self.lockAngleList, existInList) table.remove(self.lockAngleBoneNamesList, existInList) end end if self.lockPosList then existInList = MR_Utilities:ValueExists(self.lockPosList, i) if existInList then table.remove(self.lockPosList, existInList) table.remove(self.lockPosBoneNamesList, existInList) end end end end self:SaveBonesData(moho.layer) 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 if self.followBonesList.stretching[b] == nil then self.followBonesList.stretching[b] = false end 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 table.sort(removeList, function(a, b) return MR_Utilities:Compare(a, b) end) for i, v in ipairs(removeList) do table.remove(self.followBonesList.id, v) table.remove(self.followBonesList.names, v) table.remove(self.followBonesList.length, v) table.remove(self.followBonesList.startBone, v) table.remove(self.followBonesList.endBone, v) table.remove(self.followBonesList.stretching, v) end end end function MR_PoseTool:ValidateIkList(moho) local skel = moho:Skeleton() if not skel then return end local removeList = {} for b=1, #self.ikBonesList.id do for i=1, #self.ikBonesList.id[b] do if self.ikBonesList.stretching[b] == nil then self.ikBonesList.stretching[b] = false end local tBone = skel:Bone(self.ikBonesList.id[b][i]) if tBone then if tBone:Name() ~= self.ikBonesList.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 table.sort(removeList, function(a, b) return MR_Utilities:Compare(a, b) end) for i, v in ipairs(removeList) do table.remove(self.ikBonesList.id, v) table.remove(self.ikBonesList.names, v) table.remove(self.ikBonesList.length, v) table.remove(self.ikBonesList.startBone, v) table.remove(self.ikBonesList.endBone, v) table.remove(self.ikBonesList.stretching, v) end end end function MR_PoseTool:AdjustFollowAndLockBones(moho) if self.bonesDataActive then 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]) elseif self.followLockedBonesList.list[i] == 4 then self:AdjustIkBones(moho, self.followLockedBonesList.listIndex[i]) end end end end function MR_PoseTool:RemoveSelectedBonesFromFollowList(moho) local skel = moho:Skeleton() if not skel then return end self:LoadBonesData(moho.layer) local removeList = {} for b=1, #self.followBonesList.id do if self.followBonesList.stretching[b] == nil then self.followBonesList.stretching[b] = false end 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 table.sort(removeList, function(a, b) return MR_Utilities:Compare(a, b) end) 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) table.remove(self.followBonesList.stretching, v) end end self:SaveBonesData(moho.layer) end function MR_PoseTool:RemoveSelectedBonesFromIkList(moho) local skel = moho:Skeleton() if not skel then return end self:LoadBonesData(moho.layer) local removeList = {} for b=1, #self.ikBonesList.id do if self.ikBonesList.stretching[b] == nil then self.ikBonesList.stretching[b] = false end for i=1, #self.ikBonesList.id[b] do local bone = skel:Bone(self.ikBonesList.id[b][i]) if bone.fSelected then table.insert(removeList, b) break end end end if #removeList > 0 then table.sort(removeList, function(a, b) return MR_Utilities:Compare(a, b) end) for i, v in ipairs(removeList) do table.remove(self.ikBonesList.id, v) table.remove(self.ikBonesList.names, v) table.remove(self.ikBonesList.startBone, v) table.remove(self.ikBonesList.endBone, v) table.remove(self.ikBonesList.stretching, v) end end self:SaveBonesData(moho.layer) end function MR_PoseTool:LoadBonesData(layer) self.followBonesList = {} self.followBonesList.id = {} self.followBonesList.names = {} self.followBonesList.length = {} self.followBonesList.startBone = {} self.followBonesList.endBone = {} self.followBonesList.stretching = {} local scriptInfo = layer:ScriptData() local followBonesLengthKey = self.scriptDataName..'followBones_length ' if scriptInfo:HasKey(followBonesLengthKey) then local keyValue = scriptInfo:GetString(followBonesLengthKey) MR_Utilities:StringToTable(keyValue, self.followBonesList.length, 'n') end local idList = {} local followBonesIdKey = self.scriptDataName..'followBones_id ' if scriptInfo:HasKey(followBonesIdKey) then local keyValue = scriptInfo:GetString(followBonesIdKey) MR_Utilities:StringToTable(keyValue, idList, 'n') end if self.singleFollowBonesMode then for i, v in pairs(idList) do local group = {} table.insert(group, v) self.followBonesList.id[i] = group self.followBonesList.startBone[i] = v self.followBonesList.endBone[i] = v end else MR_Utilities:DistributeValuesToTables(self.followBonesList.id, idList, self.followBonesList.length) end local namesList = {} local followBonesNamesKey = self.scriptDataName..'followBones_names ' if scriptInfo:HasKey(followBonesNamesKey) then local keyValue = scriptInfo:GetString(followBonesNamesKey) MR_Utilities:StringToTable(keyValue, namesList, 's') end if self.singleFollowBonesMode then for i, v in pairs(namesList) do local group = {} table.insert(group, v) self.followBonesList.names[i] = group end else MR_Utilities:DistributeValuesToTables(self.followBonesList.names, namesList, self.followBonesList.length) end if not self.singleFollowBonesMode then local followBonesStartBoneKey = self.scriptDataName..'followBones_startBone ' if scriptInfo:HasKey(followBonesStartBoneKey) then local keyValue = scriptInfo:GetString(followBonesStartBoneKey) MR_Utilities:StringToTable(keyValue, self.followBonesList.startBone, 'n') end end if not self.singleFollowBonesMode then local followBonesEndBoneKey = self.scriptDataName..'followBones_endBone ' if scriptInfo:HasKey(followBonesEndBoneKey) then local keyValue = scriptInfo:GetString(followBonesEndBoneKey) MR_Utilities:StringToTable(keyValue, self.followBonesList.endBone, 'n') end end if not self.singleFollowBonesMode then local followBonesStretchingBoneKey = self.scriptDataName..'followBones_stretching ' if scriptInfo:HasKey(followBonesStretchingBoneKey) then local keyValue = scriptInfo:GetString(followBonesStretchingBoneKey) MR_Utilities:StringToTable(keyValue, self.followBonesList.stretching, 'b') end else local idList = {} local idOutList = {} local idSretchingList = {} local followBonesStretchingBoneKey = self.scriptDataName..'followBones_stretching ' if scriptInfo:HasKey(followBonesStretchingBoneKey) then local keyValue = scriptInfo:GetString(followBonesStretchingBoneKey) MR_Utilities:StringToTable(keyValue, idSretchingList, 'b') end local followBonesIdKey = self.scriptDataName..'followBones_id ' if scriptInfo:HasKey(followBonesIdKey) then local keyValue = scriptInfo:GetString(followBonesIdKey) MR_Utilities:StringToTable(keyValue, idList, 'n') end MR_Utilities:DistributeValuesToTables(idOutList, idList, self.followBonesList.length) for i=1, #idOutList do for b=1, #idOutList[i] do table.insert(self.followBonesList.stretching, idSretchingList[i]) end end end self.ikBonesList = {} self.ikBonesList.id = {} self.ikBonesList.names = {} self.ikBonesList.length = {} self.ikBonesList.startBone = {} self.ikBonesList.endBone = {} self.ikBonesList.stretching = {} local ikBonesLengthKey = self.scriptDataName..'ikBones_length ' if scriptInfo:HasKey(ikBonesLengthKey) then local keyValue = scriptInfo:GetString(ikBonesLengthKey) MR_Utilities:StringToTable(keyValue, self.ikBonesList.length, 'n') end idList = {} local ikBonesIdKey = self.scriptDataName..'ikBones_id ' if scriptInfo:HasKey(ikBonesIdKey) then local keyValue = scriptInfo:GetString(ikBonesIdKey) MR_Utilities:StringToTable(keyValue, idList, 'n') end MR_Utilities:DistributeValuesToTables(self.ikBonesList.id, idList, self.ikBonesList.length) local namesList = {} local ikBonesNamesKey = self.scriptDataName..'ikBones_names ' if scriptInfo:HasKey(ikBonesNamesKey) then local keyValue = scriptInfo:GetString(ikBonesNamesKey) MR_Utilities:StringToTable(keyValue, namesList, 's') end MR_Utilities:DistributeValuesToTables(self.ikBonesList.names, namesList, self.ikBonesList.length) local ikBonesStartBoneKey = self.scriptDataName..'ikBones_startBone ' if scriptInfo:HasKey(ikBonesStartBoneKey) then local keyValue = scriptInfo:GetString(ikBonesStartBoneKey) MR_Utilities:StringToTable(keyValue, self.ikBonesList.startBone, 'n') end local ikBonesEndBoneKey = self.scriptDataName..'ikBones_endBone ' if scriptInfo:HasKey(ikBonesEndBoneKey) then local keyValue = scriptInfo:GetString(ikBonesEndBoneKey) MR_Utilities:StringToTable(keyValue, self.ikBonesList.endBone, 'n') end local ikBonesStretchingBoneKey = self.scriptDataName..'ikBones_stretching ' if scriptInfo:HasKey(ikBonesStretchingBoneKey) then local keyValue = scriptInfo:GetString(ikBonesStretchingBoneKey) MR_Utilities:StringToTable(keyValue, self.ikBonesList.stretching, 'b') end self.lockAngleList = {} self.lockAngleBoneNamesList = {} local lockAngleListKey = self.scriptDataName..'lockAngleList ' if scriptInfo:HasKey(lockAngleListKey) then local keyValue = scriptInfo:GetString(lockAngleListKey) MR_Utilities:StringToTable(keyValue, self.lockAngleList, 'n') end local lockAngleBoneNamesListKey = self.scriptDataName..'lockAngleBoneNamesList ' if scriptInfo:HasKey(lockAngleBoneNamesListKey) then local keyValue = scriptInfo:GetString(lockAngleBoneNamesListKey) MR_Utilities:StringToTable(keyValue, self.lockAngleBoneNamesList, 's') end self.lockPosList = {} self.lockPosBoneNamesList = {} local lockPosListKey = self.scriptDataName..'lockPosList ' if scriptInfo:HasKey(lockPosListKey) then local keyValue = scriptInfo:GetString(lockPosListKey) MR_Utilities:StringToTable(keyValue, self.lockPosList, 'n') end local lockPosBoneNamesListKey = self.scriptDataName..'lockPosBoneNamesList ' if scriptInfo:HasKey(lockPosBoneNamesListKey) then local keyValue = scriptInfo:GetString(lockPosBoneNamesListKey) MR_Utilities:StringToTable(keyValue, self.lockPosBoneNamesList, 's') end end function MR_PoseTool:SaveBonesData(layer) local scriptInfo = layer:ScriptData() local keyValue = '' local tblLength = '' local followBonesIdKey = self.scriptDataName..'followBones_id ' local followBonesLengthKey = self.scriptDataName..'followBones_length ' for i, tbl in ipairs(self.followBonesList.id) do keyValue = keyValue..MR_Utilities:TableToString(tbl) local length = tostring(#tbl) tblLength = tblLength..#length..' '..length..',' end scriptInfo:Set(followBonesIdKey, keyValue) scriptInfo:Set(followBonesLengthKey, tblLength) keyValue = '' local followBonesNamesKey = self.scriptDataName..'followBones_names ' for i, tbl in ipairs(self.followBonesList.names) do keyValue = keyValue..MR_Utilities:TableToString(tbl) end scriptInfo:Set(followBonesNamesKey, keyValue) local followBonesStartBoneKey = self.scriptDataName..'followBones_startBone ' keyValue = MR_Utilities:TableToString(self.followBonesList.startBone) scriptInfo:Set(followBonesStartBoneKey, keyValue) local followBonesEndBoneKey = self.scriptDataName..'followBones_endBone ' keyValue = MR_Utilities:TableToString(self.followBonesList.endBone) scriptInfo:Set(followBonesEndBoneKey, keyValue) local followBonesStretchingBoneKey = self.scriptDataName..'followBones_stretching ' keyValue = MR_Utilities:TableToString(self.followBonesList.stretching) scriptInfo:Set(followBonesStretchingBoneKey, keyValue) keyValue = '' tblLength = '' local ikBonesIdKey = self.scriptDataName..'ikBones_id ' local ikBonesLengthKey = self.scriptDataName..'ikBones_length ' for i, tbl in ipairs(self.ikBonesList.id) do keyValue = keyValue..MR_Utilities:TableToString(tbl) local length = tostring(#tbl) tblLength = tblLength..#length..' '..length..',' end scriptInfo:Set(ikBonesIdKey, keyValue) scriptInfo:Set(ikBonesLengthKey, tblLength) keyValue = '' local ikBonesNamesKey = self.scriptDataName..'ikBones_names ' for i, tbl in ipairs(self.ikBonesList.names) do keyValue = keyValue..MR_Utilities:TableToString(tbl) end scriptInfo:Set(ikBonesNamesKey, keyValue) local ikBonesStartBoneKey = self.scriptDataName..'ikBones_startBone ' keyValue = MR_Utilities:TableToString(self.ikBonesList.startBone) scriptInfo:Set(ikBonesStartBoneKey, keyValue) local ikBonesEndBoneKey = self.scriptDataName..'ikBones_endBone ' keyValue = MR_Utilities:TableToString(self.ikBonesList.endBone) scriptInfo:Set(ikBonesEndBoneKey, keyValue) local ikBonesStretchingBoneKey = self.scriptDataName..'ikBones_stretching ' keyValue = MR_Utilities:TableToString(self.ikBonesList.stretching) scriptInfo:Set(ikBonesStretchingBoneKey, keyValue) local lockAngleListKey = self.scriptDataName..'lockAngleList ' keyValue = MR_Utilities:TableToString(self.lockAngleList) scriptInfo:Set(lockAngleListKey, keyValue) local lockAngleBoneNamesListKey = self.scriptDataName..'lockAngleBoneNamesList ' keyValue = MR_Utilities:TableToString(self.lockAngleBoneNamesList) scriptInfo:Set(lockAngleBoneNamesListKey, keyValue) local lockPosListKey = self.scriptDataName..'lockPosList ' keyValue = MR_Utilities:TableToString(self.lockPosList) scriptInfo:Set(lockPosListKey, keyValue) local lockPosBoneNamesListKey = self.scriptDataName..'lockPosBoneNamesList ' keyValue = MR_Utilities:TableToString(self.lockPosBoneNamesList) scriptInfo:Set(lockPosBoneNamesListKey, keyValue) end function MR_PoseTool:CleanUpBonesData(layer) local scriptInfo = layer:ScriptData() local followBonesIdKey = self.scriptDataName..'followBones_id ' scriptInfo:Remove(followBonesIdKey) local followBonesLengthKey = self.scriptDataName..'followBones_length ' scriptInfo:Remove(followBonesLengthKey) local followBonesNamesKey = self.scriptDataName..'followBones_names ' scriptInfo:Remove(followBonesNamesKey) local followBonesStartBoneKey = self.scriptDataName..'followBones_startBone ' scriptInfo:Remove(followBonesStartBoneKey) local followBonesEndBoneKey = self.scriptDataName..'followBones_endBone ' scriptInfo:Remove(followBonesEndBoneKey) local followBonesStretchingBoneKey = self.scriptDataName..'followBones_stretching ' scriptInfo:Remove(followBonesStretchingBoneKey) local ikBonesIdKey = self.scriptDataName..'ikBones_id ' scriptInfo:Remove(ikBonesIdKey) local ikBonesLengthKey = self.scriptDataName..'ikBones_length ' scriptInfo:Remove(ikBonesLengthKey) local ikBonesNamesKey = self.scriptDataName..'ikBones_names ' scriptInfo:Remove(ikBonesNamesKey) local ikBonesStartBoneKey = self.scriptDataName..'ikBones_startBone ' scriptInfo:Remove(ikBonesStartBoneKey) local ikBonesEndBoneKey = self.scriptDataName..'ikBones_endBone ' scriptInfo:Remove(ikBonesEndBoneKey) local ikBonesStretchingBoneKey = self.scriptDataName..'ikBones_stretching ' scriptInfo:Remove(ikBonesStretchingBoneKey) local lockAngleListKey = self.scriptDataName..'lockAngleList ' scriptInfo:Remove(lockAngleListKey) local lockAngleBoneNamesListKey = self.scriptDataName..'lockAngleBoneNamesList ' scriptInfo:Remove(lockAngleBoneNamesListKey) local lockPosListKey = self.scriptDataName..'lockPosList ' scriptInfo:Remove(lockPosListKey) local lockPosBoneNamesListKey = self.scriptDataName..'lockPosBoneNamesList ' scriptInfo:Remove(lockPosBoneNamesListKey) local bonesDataActiveKey = self.scriptDataName..'bonesDataActive ' scriptInfo:Remove(bonesDataActiveKey) self.lockAngleList = {} self.lockPosList = {} self.lockAngleBoneNamesList = {} self.lockPosBoneNamesList = {} self.followBonesList = {} self.followBonesList.id = {} self.followBonesList.names = {} self.followBonesList.length = {} self.followBonesList.startBone = {} self.followBonesList.endBone = {} self.ikBonesList = {} self.ikBonesList.id = {} self.ikBonesList.names = {} self.ikBonesList.length = {} self.ikBonesList.startBone = {} self.ikBonesList.endBone = {} self.bonesDataActive = true end function MR_PoseTool:CleanUpBoneStretching(moho) self:ValidateFollowList(moho) self:ValidateIkList(moho) for i=1, #self.followBonesList.id do self.followBonesList.stretching[i] = false end for i=1, #self.ikBonesList.id do self.ikBonesList.stretching[i] = false end self:SaveBonesData(moho.layer) end function MR_PoseTool:ValidateScriptFiles(moho) local utilities = true local font = true local utilitiesVersion = 1 local mr_mb_cursor local mr_mj_cursor local mr_select_bone_layer local mr_pose_tool_cursor local mr_pose_tool local mr_rotate local mr_scale local mr_translate local mr_toggle_panel local mr_pose_tool_cheat_sheet local mr_info if not MR_Utilities then utilities = false else utilitiesVersion = tonumber(MR_Utilities:Version()) end if not HV_Font then font = false end local isWindows = (os.getenv("OS") == "Windows_NT") local mohoPath = moho:UserContentDir() local testPath = mohoPath:sub(1, -10) local isPathCorrect = testPath:find("[/\\]") ~= nil if mohoPath:find("[^A-Za-z%s%p%d]") ~= nil then isPathCorrect = false end if not isPathCorrect then if not utilities then alertText = 'The file mr_utilities.lua is missing at '..mohoPath..'\\Scripts\\Utility\\' if not isWindows then alertText = 'The file mr_utilities.lua is missing at '..mohoPath..'/Scripts/Utility/' end local alert = LM.GUI.Alert(LM.GUI.ALERT_WARNING, alertTitleText, alertText.."\n".."\n"..howToFixText.."\n".."\n", linkText, 'Copy link to clipboard', 'Close') self.scriptValidated = false if alert == 0 then moho:CopyText(linkText) end self.scriptValidated = false return end if utilitiesVersion < 1.2 then if not isWindows then alertText = 'The version of mr_utilities.lua is '..utilitiesVersion..'. Version 1.2 or higher required.'.."\n"..'The file mr_utilities.lua is located at '..mohoPath..'/Scripts/Utility/' end local alert = LM.GUI.Alert(LM.GUI.ALERT_WARNING, alertTitleText, alertText.."\n".."\n"..howToFixText.."\n".."\n", linkText, 'Copy link to clipboard', 'Close') self.scriptValidated = false if alert == 0 then moho:CopyText(linkText) end self.scriptValidated = false return end self.scriptValidated = true return end local filePath = mohoPath..'\\Scripts\\ScriptResources\\mr_pose_tool\\' if not isWindows then filePath = mohoPath..'/Scripts/ScriptResources/mr_pose_tool/' end if utilities then if isWindows then mr_pose_tool_cursor = MR_Utilities:FileExists(mohoPath..'\\Scripts\\Tool\\mr_pose_tool_cursor.png') mr_pose_tool = MR_Utilities:FileExists(mohoPath..'\\Scripts\\Tool\\mr_pose_tool.png') mr_mb_cursor = MR_Utilities:FileExists(filePath..'mr_mb_cursor.png') mr_mj_cursor = MR_Utilities:FileExists(filePath..'mr_mj_cursor.png') mr_select_bone_layer = MR_Utilities:FileExists(filePath..'mr_select_bone_layer.png') mr_rotate = MR_Utilities:FileExists(filePath..'mr_rotate.png') mr_scale = MR_Utilities:FileExists(filePath..'mr_scale.png') mr_translate = MR_Utilities:FileExists(filePath..'mr_translate.png') mr_toggle_panel = MR_Utilities:FileExists(filePath..'mr_toggle_panel.png') mr_pose_tool_cheat_sheet = MR_Utilities:FileExists(filePath..'mr_pose_tool_cheat_sheet.png') mr_info = MR_Utilities:FileExists(filePath..'mr_info.png') else mr_pose_tool_cursor = MR_Utilities:FileExists(mohoPath..'/Scripts/Tool/mr_pose_tool_cursor.png') mr_pose_tool = MR_Utilities:FileExists(mohoPath..'/Scripts/Tool/mr_pose_tool.png') mr_mb_cursor = MR_Utilities:FileExists(filePath..'mr_mb_cursor.png') mr_mj_cursor = MR_Utilities:FileExists(filePath..'mr_mj_cursor.png') mr_select_bone_layer = MR_Utilities:FileExists(filePath..'mr_select_bone_layer.png') mr_rotate = MR_Utilities:FileExists(filePath..'mr_rotate.png') mr_scale = MR_Utilities:FileExists(filePath..'mr_scale.png') mr_translate = MR_Utilities:FileExists(filePath..'mr_translate.png') mr_toggle_panel = MR_Utilities:FileExists(filePath..'mr_toggle_panel.png') mr_pose_tool_cheat_sheet = MR_Utilities:FileExists(filePath..'mr_pose_tool_cheat_sheet.png') mr_info = MR_Utilities:FileExists(filePath..'mr_info.png') end end if utilities and font and utilitiesVersion >= 1.1 and mr_mb_cursor and mr_mj_cursor and mr_select_bone_layer and mr_rotate and mr_scale and mr_translate and mr_toggle_panel and mr_pose_tool_cheat_sheet and mr_info and mr_pose_tool_cursor and mr_pose_tool then self.scriptValidated = true else local alertTitleText = 'Some script files are missing' local alertText = '' local howToFixText = 'Please download the script using the \"Download for Install Script\" button and install all script files.' local linkText = self:Localize('Script link') if not utilities then alertText = 'The file mr_utilities.lua is missing at '..mohoPath..'\\Scripts\\Utility\\' if not isWindows then alertText = 'The file mr_utilities.lua is missing at '..mohoPath..'/Scripts/Utility/' end local alert = LM.GUI.Alert(LM.GUI.ALERT_WARNING, alertTitleText, alertText.."\n".."\n"..howToFixText.."\n".."\n", linkText, 'Copy link to clipboard', 'Close') self.scriptValidated = false if alert == 0 then moho:CopyText(linkText) end self.scriptValidated = false return end if utilitiesVersion < 1.1 then if not isWindows then alertText = 'The version of mr_utilities.lua is '..utilitiesVersion..'. Version 1.1 or higher required.'.."\n"..'The file mr_utilities.lua is located at '..mohoPath..'/Scripts/Utility/' end local alert = LM.GUI.Alert(LM.GUI.ALERT_WARNING, alertTitleText, alertText.."\n".."\n"..howToFixText.."\n".."\n", linkText, 'Copy link to clipboard', 'Close') self.scriptValidated = false if alert == 0 then moho:CopyText(linkText) end self.scriptValidated = false return end if isWindows then if not font then alertText = 'The file hv_font.lua is missing at '..mohoPath..'\\Scripts\\Utility\\'.."\n" end if not mr_pose_tool then alertText = alertText..'The file mr_pose_tool.png is missing at '..mohoPath..'\\Scripts\\Tool\\'.."\n" end if not mr_pose_tool_cursor then alertText = alertText..'The file mr_pose_tool_cursor.png is missing at '..mohoPath..'\\Scripts\\Tool\\'.."\n" end else if not font then alertText = 'The file hv_font.lua is missing at '..mohoPath..'/Scripts/Utility/'.."\n" end if not mr_pose_tool then alertText = alertText..'The file mr_pose_tool.png is missing at '..mohoPath..'/Scripts/Tool/'.."\n" end if not mr_pose_tool_cursor then alertText = alertText..'The file mr_pose_tool_cursor.png is missing at '..mohoPath..'/Scripts/Tool/'.."\n" end end if not mr_mb_cursor then alertText = alertText..'The file mr_mb_cursor.png is missing at '..filePath.."\n" end if not mr_mj_cursor then alertText = alertText..'The file mr_mj_cursor.png is missing at '..filePath.."\n" end if not mr_select_bone_layer then alertText = alertText..'The file mr_select_bone_layer.png is missing at '..filePath.."\n" end if not mr_rotate then alertText = alertText..'The file mr_rotate.png is missing at '..filePath.."\n" end if not mr_scale then alertText = alertText..'The file mr_scale.png is missing at '..filePath.."\n" end if not mr_translate then alertText = alertText..'The file mr_translate.png is missing at '..filePath.."\n" end if not mr_toggle_panel then alertText = alertText..'The file mr_toggle_panel.png is missing at '..filePath.."\n" end if not mr_pose_tool_cheat_sheet then alertText = alertText..'The file mr_pose_tool_cheat_sheet.png is missing at '..filePath.."\n" end if not mr_info then alertText = alertText..'The file mr_info.png is missing at '..filePath.."\n" end alertText = alertText.."\n" local alert = LM.GUI.Alert(LM.GUI.ALERT_WARNING, alertTitleText, alertText..howToFixText, linkText, 'Copy link to clipboard', 'Close') self.scriptValidated = false if alert == 0 then moho:CopyText(linkText) end self.scriptValidated = false return end end function MR_PoseTool:ReverseIkDirection(moho) local skel = moho:Skeleton() if skel == nil then return end self:PrepareFollowBones(moho) self.ikBonesList.reverseList = {} for i=0, skel:CountBones()-1 do local bone = skel:Bone(i) if bone.fSelected and not bone:IsZeroLength() then for b=1, #self.ikBonesList.id do if self.ikBonesList.startBone[b] == i or self.ikBonesList.endBone[b] == i then self.ikBonesList.reverseList[b] = true end end end end self:AdjustFollowAndLockBones(moho) skel:UpdateBoneMatrix() moho.layer:UpdateCurFrame() end function MR_PoseTool:PrepareFollowBones(moho) if self.bonesDataActive then local skel = moho:Skeleton() if skel == nil then return end self.ikBonesList.reverseList = {} if #self.lockAngleList > 0 and self.bonesDataActiveA then self:ValidateLockList(moho) 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 and self.bonesDataActiveP 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 and self.bonesDataActiveF then self:ValidateFollowList(moho) 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.secondBoneID < 0 then if fBone.fSelected then block = true end else if self.followBonesList.id[b][i] == self.secondBoneID then block = true end 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] = MR_Utilities: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 if #self.ikBonesList.id > 0 and self.bonesDataActiveIK then self:ValidateIkList(moho) self.ikBonesDataList = {} self.ikBonesDataList.initialDirection = {} self.ikBonesDataList.startBoneLength = {} self.ikBonesDataList.endtBoneLength = {} self.ikBonesDataList.endBoneTipPos = {} self.ikBonesDataList.startAngleDelta = {} self.ikBonesDataList.endAngleDelta = {} self.ikBonesDataList.startBoneBakedA = {} self.ikBonesDataList.startBoneFAngleP = {} self.ikBonesDataList.startBoneFAngleN = {} self.ikBonesDataList.endBoneBakedA = {} self.ikBonesDataList.endBoneFAngleP = {} self.ikBonesDataList.endBoneFAngleN = {} self.ikBonesDataList.startBoneBakedS = {} self.ikBonesDataList.startBoneFScaleP = {} self.ikBonesDataList.startBoneFScaleN = {} self.ikBonesDataList.endBoneBakedS = {} self.ikBonesDataList.endBoneFScaleP = {} self.ikBonesDataList.endBoneFScaleN = {} self.ikBonesDataList.startBoneScaleDelta = {} self.ikBonesDataList.endBoneScaleDelta = {} self.ikBonesDataList.needKey = {} self.ikBonesDataList.block = {} for b=1, #self.ikBonesList.id do local startIkBone = skel:Bone(self.ikBonesList.startBone[b]) local endIkBone = skel:Bone(self.ikBonesList.endBone[b]) if startIkBone and endIkBone then local endBoneTipPos = LM.Vector2:new_local() local startBoneTipPos = LM.Vector2:new_local() local startBoneBasePos = LM.Vector2:new_local() local endBoneBasePos = LM.Vector2:new_local() local valuesPLis = {} local valuesNLis = {} local scaleDeltaList = {} local block = false for i=1, #self.ikBonesList.id[b] do local fBone = skel:Bone(self.ikBonesList.id[b][i]) if fBone then if self.secondBoneID < 0 then if fBone.fSelected then block = true end else if self.ikBonesList.id[b][i] == self.secondBoneID then block = true end end end end self.ikBonesDataList.block[b] = block startBoneBasePos:Set(0, 0) if (startIkBone:IsZeroLength()) then endBoneTipPos:Set(0.1, 0) else endBoneTipPos:Set(endIkBone.fLength, 0) end startBoneTipPos:Set(startIkBone.fLength, 0) endBoneBasePos:Set(0, 0) if moho.frame == 0 then startIkBone.fRestMatrix:Transform(startBoneBasePos) endIkBone.fRestMatrix:Transform(endBoneTipPos) startIkBone.fRestMatrix:Transform(startBoneTipPos) endIkBone.fRestMatrix:Transform(endBoneBasePos) else startIkBone.fMovedMatrix:Transform(startBoneBasePos) endIkBone.fMovedMatrix:Transform(endBoneTipPos) startIkBone.fMovedMatrix:Transform(startBoneTipPos) endIkBone.fMovedMatrix:Transform(endBoneBasePos) end self.ikBonesDataList.initialDirection[b] = MR_Utilities:GetDirection(startBoneBasePos, endBoneBasePos, endBoneTipPos) self.ikBonesDataList.endBoneTipPos[b] = endBoneTipPos self.ikBonesDataList.startBoneLength[b] = MR_Utilities:GetDistance(startBoneBasePos, endBoneBasePos) self.ikBonesDataList.endtBoneLength[b] = MR_Utilities:GetDistance(endBoneBasePos, endBoneTipPos) self.ikBonesDataList.needKey[b] = false startIkBone.fTempAngle = startIkBone.fAnimAngle:GetValue(moho.layerFrame) endIkBone.fTempAngle = startIkBone.fAnimAngle:GetValue(moho.layerFrame) local ikStartBoneActualAngle = startIkBone.fAngle local ikEndBoneActualAngle = endIkBone.fAngle self.ikBonesDataList.startAngleDelta[b] = ikStartBoneActualAngle - startIkBone.fAnimAngle:GetValue(moho.layerFrame) self.ikBonesDataList.endAngleDelta[b] = ikEndBoneActualAngle - endIkBone.fAnimAngle:GetValue(moho.layerFrame) self.ikBonesDataList.startBoneBakedA[b] = false self.ikBonesDataList.startBoneFAngleP[b] = startIkBone.fAnimAngle:GetValue(moho.layerFrame - self.interval) self.ikBonesDataList.startBoneFAngleN[b] = startIkBone.fAnimAngle:GetValue(moho.layerFrame + self.interval) self.ikBonesDataList.endBoneBakedA[b] = false self.ikBonesDataList.endBoneFAngleP[b] = endIkBone.fAnimAngle:GetValue(moho.layerFrame - self.interval) self.ikBonesDataList.endBoneFAngleN[b] = endIkBone.fAnimAngle:GetValue(moho.layerFrame + self.interval) if self.boneStretching and self.ikBonesList.stretching[b] then self.ikBonesDataList.startBoneBakedS[b] = false self.ikBonesDataList.startBoneFScaleP[b] = startIkBone.fAnimScale:GetValue(moho.layerFrame - self.interval) self.ikBonesDataList.startBoneFScaleN[b] = startIkBone.fAnimScale:GetValue(moho.layerFrame + self.interval) self.ikBonesDataList.endBoneBakedS[b] = false self.ikBonesDataList.endBoneFScaleP[b] = endIkBone.fAnimScale:GetValue(moho.layerFrame - self.interval) self.ikBonesDataList.endBoneFScaleN[b] = endIkBone.fAnimScale:GetValue(moho.layerFrame + self.interval) startIkBone.fTempScale = startIkBone.fScale endIkBone.fTempScale = endIkBone.fScale self.ikBonesDataList.startBoneScaleDelta[b] = startIkBone.fScale - startIkBone.fAnimScale:GetValue(moho.layerFrame) self.ikBonesDataList.endBoneScaleDelta[b] = endIkBone.fScale - endIkBone.fAnimScale:GetValue(moho.layerFrame) end end end end self.followLockedBonesList = {} self.followLockedBonesList.id = {} self.followLockedBonesList.listIndex = {} self.followLockedBonesList.list = {} -- 1 follow, 2 lock angle, 3 lock pos if self.bonesDataActiveF then 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 end if self.bonesDataActiveA then 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 end if self.bonesDataActiveP then 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 end if self.bonesDataActiveIK then for b=1, #self.ikBonesList.id do table.insert(self.followLockedBonesList.id, self.ikBonesList.id[b][1]) table.insert(self.followLockedBonesList.listIndex, b) table.insert(self.followLockedBonesList.list, 4) end 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] = MR_Utilities:SwapTwoArrayKeys(self.followLockedBonesList.id, i, a) self.followLockedBonesList.listIndex[i], self.followLockedBonesList.listIndex[a] = MR_Utilities:SwapTwoArrayKeys(self.followLockedBonesList.listIndex, i, a) self.followLockedBonesList.list[i], self.followLockedBonesList.list[a] = MR_Utilities: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] = MR_Utilities:SwapTwoArrayKeys(self.followLockedBonesList.id, i, b) self.followLockedBonesList.listIndex[i], self.followLockedBonesList.listIndex[b] = MR_Utilities:SwapTwoArrayKeys(self.followLockedBonesList.listIndex, i, b) self.followLockedBonesList.list[i], self.followLockedBonesList.list[b] = MR_Utilities: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 end end function MR_PoseTool:GenerateColors(moho) local vc1 = LM.ColorVector:new_local() local vc2 = LM.ColorVector:new_local() 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 if self.useCustomColors then self.colorTranslateStroke = LM.rgb_color:new_local() self.colorTranslateStroke.r = self.colorStrokeTranslateHandleR self.colorTranslateStroke.g = self.colorStrokeTranslateHandleG self.colorTranslateStroke.b = self.colorStrokeTranslateHandleB self.colorTranslateStroke.a = 255 * self.handleStrokeOpacity self.colorTranslateFill = LM.rgb_color:new_local() self.colorTranslateFill.r = self.colorFillTranslateHandleR self.colorTranslateFill.g = self.colorFillTranslateHandleG self.colorTranslateFill.b = self.colorFillTranslateHandleB self.colorTranslateFill.a = 255 * self.handleFillOpacity self.colorTranslateFillHL = LM.rgb_color:new_local() self.colorTranslateFillHL.r = ((self.colorTranslateFill.r * 3) + whiteColor.r) / 4 self.colorTranslateFillHL.g = ((self.colorTranslateFill.g * 3) + whiteColor.g) / 4 self.colorTranslateFillHL.b = ((self.colorTranslateFill.b * 3) + whiteColor.b) / 4 self.colorTranslateFillHL.a = 255 * self.handleFillOpacity self.colorScaleStroke = LM.rgb_color:new_local() self.colorScaleStroke.r = self.colorStrokeScaleHandleR self.colorScaleStroke.g = self.colorStrokeScaleHandleG self.colorScaleStroke.b = self.colorStrokeScaleHandleB self.colorScaleStroke.a = 255 * self.handleStrokeOpacity self.colorScaleFill = LM.rgb_color:new_local() self.colorScaleFill.r = self.colorFillScaleHandleR self.colorScaleFill.g = self.colorFillScaleHandleG self.colorScaleFill.b = self.colorFillScaleHandleB self.colorScaleFill.a = 255 * self.handleFillOpacity self.colorScaleFillHL = LM.rgb_color:new_local() self.colorScaleFillHL.r = ((self.colorScaleFill.r * 3) + whiteColor.r) / 4 self.colorScaleFillHL.g = ((self.colorScaleFill.g * 3) + whiteColor.g) / 4 self.colorScaleFillHL.b = ((self.colorScaleFill.b * 3) + whiteColor.b) / 4 self.colorScaleFillHL.a = 255 * self.handleFillOpacity self.colorMoveJointStroke = LM.rgb_color:new_local() self.colorMoveJointStroke.r = self.colorStrokeMoveJointHandleR self.colorMoveJointStroke.g = self.colorStrokeMoveJointHandleG self.colorMoveJointStroke.b = self.colorStrokeMoveJointHandleB self.colorMoveJointStroke.a = 255 * self.handleStrokeOpacity self.colorMoveJointFill = LM.rgb_color:new_local() self.colorMoveJointFill.r = self.colorFillMoveJointHandleR self.colorMoveJointFill.g = self.colorFillMoveJointHandleG self.colorMoveJointFill.b = self.colorFillMoveJointHandleB self.colorMoveJointFill.a = 255 * self.handleFillOpacity self.colorMoveJointFillHL = LM.rgb_color:new_local() self.colorMoveJointFillHL.r = ((self.colorMoveJointFill.r * 3) + whiteColor.r) / 4 self.colorMoveJointFillHL.g = ((self.colorMoveJointFill.g * 3) + whiteColor.g) / 4 self.colorMoveJointFillHL.b = ((self.colorMoveJointFill.b * 3) + whiteColor.b) / 4 self.colorMoveJointFillHL.a = 255 * self.handleFillOpacity self.colorManipulateStroke = LM.rgb_color:new_local() self.colorManipulateStroke.r = self.colorStrokeManipulateHandleR self.colorManipulateStroke.g = self.colorStrokeManipulateHandleG self.colorManipulateStroke.b = self.colorStrokeManipulateHandleB self.colorManipulateStroke.a = 255 * self.handleStrokeOpacity self.colorManipulateFill = LM.rgb_color:new_local() self.colorManipulateFill.r = self.colorFillManipulateHandleR self.colorManipulateFill.g = self.colorFillManipulateHandleG self.colorManipulateFill.b = self.colorFillManipulateHandleB self.colorManipulateFill.a = 255 * self.handleFillOpacity self.colorManipulateFillHL = LM.rgb_color:new_local() self.colorManipulateFillHL.r = ((self.colorManipulateFill.r * 3) + whiteColor.r) / 4 self.colorManipulateFillHL.g = ((self.colorManipulateFill.g * 3) + whiteColor.g) / 4 self.colorManipulateFillHL.b = ((self.colorManipulateFill.b * 3) + whiteColor.b) / 4 self.colorManipulateFillHL.a = 255 * self.handleFillOpacity else self.colorTranslateStroke = LM.rgb_color:new_local() self.colorTranslateStroke.r = MOHO.MohoGlobals.SelCol.r self.colorTranslateStroke.g = MOHO.MohoGlobals.SelCol.g self.colorTranslateStroke.b = MOHO.MohoGlobals.SelCol.b self.colorTranslateStroke.a = 255 * self.handleStrokeOpacity self.colorTranslateFill = LM.rgb_color:new_local() self.colorTranslateFill.r = fillCol.r self.colorTranslateFill.g = fillCol.g self.colorTranslateFill.b = fillCol.b self.colorTranslateFill.a = 255 * self.handleFillOpacity self.colorTranslateFillHL = LM.rgb_color:new_local() self.colorTranslateFillHL.r = ((self.colorTranslateFill.r * 3) + whiteColor.r) / 4 self.colorTranslateFillHL.g = ((self.colorTranslateFill.g * 3) + whiteColor.g) / 4 self.colorTranslateFillHL.b = ((self.colorTranslateFill.b * 3) + whiteColor.b) / 4 self.colorTranslateFillHL.a = 255 * self.handleFillOpacity self.colorScaleStroke = LM.rgb_color:new_local() self.colorScaleStroke.r = MOHO.MohoGlobals.SelCol.r self.colorScaleStroke.g = MOHO.MohoGlobals.SelCol.g self.colorScaleStroke.b = MOHO.MohoGlobals.SelCol.b self.colorScaleStroke.a = 255 * self.handleStrokeOpacity self.colorScaleFill = LM.rgb_color:new_local() self.colorScaleFill.r = fillCol.r self.colorScaleFill.g = fillCol.g self.colorScaleFill.b = fillCol.b self.colorScaleFill.a = 255 * self.handleFillOpacity self.colorScaleFillHL = LM.rgb_color:new_local() self.colorScaleFillHL.r = ((self.colorScaleFill.r * 3) + whiteColor.r) / 4 self.colorScaleFillHL.g = ((self.colorScaleFill.g * 3) + whiteColor.g) / 4 self.colorScaleFillHL.b = ((self.colorScaleFill.b * 3) + whiteColor.b) / 4 self.colorScaleFillHL.a = 255 * self.handleFillOpacity self.colorMoveJointFill = LM.rgb_color:new_local() self.colorMoveJointFill.r = 255 self.colorMoveJointFill.g = 189 self.colorMoveJointFill.b = 46 self.colorMoveJointFill.a = 255 * self.handleFillOpacity self.colorMoveJointStroke = LM.rgb_color:new_local() self.colorMoveJointStroke.r = (self.colorMoveJointFill.r + (MOHO.MohoGlobals.SelCol.r * 2)) / 3 self.colorMoveJointStroke.g = (self.colorMoveJointFill.g + (MOHO.MohoGlobals.SelCol.g * 2)) / 3 self.colorMoveJointStroke.b = (self.colorMoveJointFill.b + (MOHO.MohoGlobals.SelCol.b * 2)) / 3 self.colorMoveJointStroke.a = 255 * self.handleStrokeOpacity self.colorMoveJointFillHL = LM.rgb_color:new_local() self.colorMoveJointFillHL.r = ((self.colorMoveJointFill.r * 3) + whiteColor.r) / 4 self.colorMoveJointFillHL.g = ((self.colorMoveJointFill.g * 3) + whiteColor.g) / 4 self.colorMoveJointFillHL.b = ((self.colorMoveJointFill.b * 3) + whiteColor.b) / 4 self.colorMoveJointFillHL.a = 255 * self.handleFillOpacity self.colorManipulateFill = LM.rgb_color:new_local() self.colorManipulateFill.r = 255 self.colorManipulateFill.g = 189 self.colorManipulateFill.b = 46 self.colorManipulateFill.a = 255 * self.handleFillOpacity self.colorManipulateStroke = LM.rgb_color:new_local() self.colorManipulateStroke.r = (self.colorManipulateFill.r + (MOHO.MohoGlobals.SelCol.r * 2)) / 3 self.colorManipulateStroke.g = (self.colorManipulateFill.g + (MOHO.MohoGlobals.SelCol.g * 2)) / 3 self.colorManipulateStroke.b = (self.colorManipulateFill.b + (MOHO.MohoGlobals.SelCol.b * 2)) / 3 self.colorManipulateStroke.a = 255 * self.handleStrokeOpacity self.colorManipulateFillHL = LM.rgb_color:new_local() self.colorManipulateFillHL.r = ((self.colorManipulateFill.r * 3) + whiteColor.r) / 4 self.colorManipulateFillHL.g = ((self.colorManipulateFill.g * 3) + whiteColor.g) / 4 self.colorManipulateFillHL.b = ((self.colorManipulateFill.b * 3) + whiteColor.b) / 4 self.colorManipulateFillHL.a = 255 * self.handleFillOpacity end self.colorHighlightBone = LM.rgb_color:new_local() if self.useHighlightCustomColor then self.colorHighlightBone.r = self.highlightCustomColorR self.colorHighlightBone.g = self.highlightCustomColorG self.colorHighlightBone.b = self.highlightCustomColorB self.colorHighlightBone.a = 255 * self.highlightOpacity else self.colorHighlightBone.r = MOHO.MohoGlobals.SelCol.r self.colorHighlightBone.g = MOHO.MohoGlobals.SelCol.g self.colorHighlightBone.b = MOHO.MohoGlobals.SelCol.b self.colorHighlightBone.a = 255 * self.highlightOpacity end self.colorsGenerated = true self.colorFollowBones = LM.rgb_color:new_local() self.colorFollowBones.r = self.colorFollowBonesR self.colorFollowBones.g = self.colorFollowBonesG self.colorFollowBones.b = self.colorFollowBonesB self.colorFollowBones.a = self.colorFollowBonesA self.colorIkBones = LM.rgb_color:new_local() self.colorIkBones.r = 146 self.colorIkBones.g = 31 self.colorIkBones.b = 131 self.colorIkBones.a = 255 self.lockAngleColor = LM.rgb_color:new_local() self.lockAngleColor.r = 255 self.lockAngleColor.g = 68 self.lockAngleColor.b = 68 self.lockAngleColor.a = 255 self.lockPosColor = LM.rgb_color:new_local() self.lockPosColor.r = 255 self.lockPosColor.g = 192 self.lockPosColor.b = 0 self.lockPosColor.a = 255 self.iconColorBack = LM.rgb_color:new_local() self.iconColorBack.r = 255 self.iconColorBack.g = 255 self.iconColorBack.b = 255 self.iconColorBack.a = 255 self.iconColor = LM.rgb_color:new_local() self.iconColor.r = self.iconColorR self.iconColor.g = self.iconColorG self.iconColor.b = self.iconColorB self.iconColor.a = self.iconColorA self.disabledIconColor = LM.rgb_color:new_local() self.disabledIconColor.r = (self.iconColorR + self.iconColorBack.r) / 2 self.disabledIconColor.g = (self.iconColorG + self.iconColorBack.g) / 2 self.disabledIconColor.b = (self.iconColorB + self.iconColorBack.b) / 2 self.disabledIconColor.a = (self.iconColorA + self.iconColorBack.a) / 2 self.iconHowerColor = LM.rgb_color:new_local() self.iconHowerColor.r = (self.iconColorR * 3 + self.iconColorBack.r) / 4 self.iconHowerColor.g = (self.iconColorG * 3 + self.iconColorBack.g) / 4 self.iconHowerColor.b = (self.iconColorB * 3 + self.iconColorBack.b) / 4 self.iconHowerColor.a = (self.iconColorA * 3 + self.iconColorBack.a) / 4 end function MR_PoseTool:DrawQuickMenu_1(moho, g) local m = LM.Matrix:new_local() moho.document:GetCameraMatrix(moho.layerFrame, m) g:Push() local currentScale = g:CurrentScale(false) local 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 g:SetSmoothing(true) -- set follow bones icon v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(v, center, math.rad(30))) if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 1 then tooltipSizeH = 0.518 / 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 chains'), tooltipTextSize, v1.x, v1.y, 0, 0) end if self.graphicMenuMode == 1 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 1 then radius = self.iconsRadius / (howerRadius / 1.1) end g:SetColor(0, 0, 0, 75) g:FillCirclePixelRadius(v + shadowOffset, radius) g:SetColor(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 1 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.iconColor) if self.singleFollowBonesMode then g:SetColor(self.disabledIconColor) end 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(MR_Utilities:RotateVector2(v1, v, math.rad(45))) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x + arrowLen, iconCenter.y + arrowWidth * 2.0) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x + arrowLen + arrowWidth * 2.0, iconCenter.y) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x + arrowLen, iconCenter.y - (arrowWidth * 2.0)) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x + arrowLen, iconCenter.y - arrowWidth) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x-arrowLen, iconCenter.y - arrowWidth ) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x - arrowLen, iconCenter.y + arrowWidth) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) g:EndShape() -- Set IK bones if self.graphicMenuMode == 2 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 2 then radius = self.iconsRadius / (howerRadius / 1.1) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(v, center, math.rad(90))) if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 2 then tooltipSizeH = 0.316 / 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 IK bones'), tooltipTextSize, v1.x, v1.y, 0, 0) end g:SetColor(0, 0, 0, 75) g:FillCirclePixelRadius(v + shadowOffset, radius) if self.graphicMenuMode == 2 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) if self.boneStretching then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end g:SetColor(self.iconColorBack) if self.operationFailes == 2 then g:SetColor(255, 57, 57, 255) end g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 2 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end if self.operationFailes == 2 then g:SetColor(115, 3, 3, 255) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.iconColor) if self.singleFollowBonesMode then g:SetColor(self.disabledIconColor) end offsetCenter = 0.002 / currentScale / height iconCenter:Set(v.x + offsetCenter, v.y) local symbolWidth = 0.015 / currentScale / height local symbolHeight = 0.015 / currentScale / height v1:Set(iconCenter.x - symbolWidth, iconCenter.y + symbolHeight) v2:Set(v1.x, iconCenter.y - symbolHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set((iconCenter.x - symbolWidth) + symbolHeight / 1.2, iconCenter.y + symbolHeight) v2:Set(v1.x, iconCenter.y - symbolHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, iconCenter.y) v2:Set(v2.x + symbolWidth, iconCenter.y + symbolHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(((iconCenter.x - symbolWidth) + symbolHeight / 1.2), iconCenter.y) v2:Set(v1.x + symbolWidth, iconCenter.y - symbolHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- lock angle if self.graphicMenuMode == 3 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 3 then radius = self.iconsRadius / (howerRadius / 1.1) end g:SetPenWidth(3) v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(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(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 3 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.iconColor) if self.singleFollowBonesMode then g:SetColor(self.disabledIconColor) end 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(self.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 if self.graphicMenuMode == 4 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 4 then radius = self.iconsRadius / (howerRadius / 1.1) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(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(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 4 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.iconColor) if self.singleFollowBonesMode then g:SetColor(self.disabledIconColor) end 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(self.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 if self.buttonPressed == 5 then radius = self.iconsRadius / (howerRadius / 1.1) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(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(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 5 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.iconColor) if self.singleFollowBonesMode then g:SetColor(self.disabledIconColor) end 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) -- enable icon local iconRadius = self.iconsRadius if self.graphicMenuMode == 6 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 6 then radius = self.iconsRadius / (howerRadius / 1.1) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(v, center, math.rad(150))) if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 6 then tooltipSizeH = 0.19 / 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('Enable'), 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(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 6 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) if self.bonesDataActive then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end iconCenter:Set(v.x, v.y) g:FrameCirclePixelRadius(v, iconRadius * 0.55) g:SetColor(self.iconColorBack) offsetCenter = 0.014 / currentScale / height iconCenter:Set(v.x, v.y + offsetCenter) local boxSize = 0.008 / 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() if self.bonesDataActive then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end local symbolHeight = 0.008 / currentScale / height v1:Set(iconCenter.x, iconCenter.y - symbolHeight) v2:Set(iconCenter.x, iconCenter.y + symbolHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) g:Pop() end function MR_PoseTool:DrawQuickMenu_2(moho, g) local m = LM.Matrix:new_local() moho.document:GetCameraMatrix(moho.layerFrame, m) g:Push() local currentScale = g:CurrentScale(false) local 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 g:SetSmoothing(true) -- set single follow bones icon v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(v, center, math.rad(30))) if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 1 then tooltipSizeH = 0.506 / 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 single follow bones'), tooltipTextSize, v1.x, v1.y, 0, 0) end if self.graphicMenuMode == 1 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 1 then radius = self.iconsRadius / (howerRadius / 1.1) end g:SetColor(0, 0, 0, 75) g:FillCirclePixelRadius(v + shadowOffset, radius) g:SetColor(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 1 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.iconColor) if self.singleFollowBonesMode then g:SetColor(self.disabledIconColor) end 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(MR_Utilities:RotateVector2(v1, v, math.rad(45))) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x + arrowLen, iconCenter.y + arrowWidth * 2.0) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x + arrowLen + arrowWidth * 2.0, iconCenter.y) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x + arrowLen, iconCenter.y - (arrowWidth * 2.0)) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x + arrowLen, iconCenter.y - arrowWidth) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x-arrowLen, iconCenter.y - arrowWidth ) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) v1:Set(v2) v2:Set(iconCenter.x - arrowLen, iconCenter.y + arrowWidth) v2:Set(MR_Utilities:RotateVector2(v2, v, math.rad(45))) g:AddLine(v1, v2) g:EndShape() g:SetColor(self.iconColorBack) local offsetLine = 0.003 / currentScale / height v1:Set(iconCenter.x - offsetLine * 3, iconCenter.y + offsetLine * 0.6) v2:Set(iconCenter.x + offsetLine * 4, iconCenter.y - offsetLine * 6) local markersSize = (0.004) / currentScale / height g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- reverse IK direction icon if self.graphicMenuMode == 2 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 2 then radius = self.iconsRadius / (howerRadius / 1.1) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(v, center, math.rad(90))) if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 2 then tooltipSizeH = 0.46 / 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('Reverse IK direction'), tooltipTextSize, v1.x, v1.y, 0, 0) end g:SetColor(0, 0, 0, 75) g:FillCirclePixelRadius(v + shadowOffset, radius) g:SetColor(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 2 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) if self.bonesDataActive and #self.ikBonesList.id > 0 then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end offsetCenter = 0.002 / currentScale / height iconCenter:Set(v.x - offsetCenter, v.y - offsetCenter) local symbolWidth = 0.013 / currentScale / height local offsetS = 1.3 v1:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolWidth) v2:Set(iconCenter.x + symbolWidth, iconCenter.y - symbolWidth * offsetS) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x - symbolWidth * offsetS, iconCenter.y + symbolWidth) v2:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolWidth) g:DrawLine(v1.x, v1.y, v2.x, v2.y) iconCenter:Set(v.x + offsetCenter, v.y + offsetCenter) v1:Set(iconCenter.x + symbolWidth * offsetS, iconCenter.y - symbolWidth) v2:Set(iconCenter.x + symbolWidth, iconCenter.y + symbolWidth) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x + symbolWidth, iconCenter.y + symbolWidth) v2:Set(iconCenter.x - symbolWidth, iconCenter.y + symbolWidth * offsetS) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- set stretch bones icon if self.graphicMenuMode == 3 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 3 then radius = self.iconsRadius / (howerRadius / 1.1) end g:SetPenWidth(3) v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(v, center, math.rad(-30))) if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 3 then tooltipSizeH = 0.44 / 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('Set bone stretching'), 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(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 3 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.iconColor) g:SetColor(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 3 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) if self.boneStretchingIconStatus then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end if self.singleFollowBonesMode then g:SetColor(self.disabledIconColor) end offsetCenter = 0.0 / currentScale / height iconCenter:Set(v.x + offsetCenter, v.y) local symbolWidth = 0.015 / currentScale / height local symbolHeight = 0.015 / currentScale / height v1:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolHeight) v2:Set(v1.x, v1.y + symbolHeight * 0.8) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolHeight) v2:Set(v1.x + symbolHeight * 0.8, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x + symbolWidth, iconCenter.y + symbolHeight) v2:Set(v1.x, v1.y - symbolHeight * 0.8) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x + symbolWidth, iconCenter.y + symbolHeight) v2:Set(v1.x - symbolHeight * 0.8, v1.y) 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) -- turn off scale for all bones if self.graphicMenuMode == 4 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 4 then radius = self.iconsRadius / (howerRadius / 1.1) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(v, center, math.rad(-90))) if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 4 then tooltipSizeH = 0.537 / 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 all bone stretching'), tooltipTextSize, v1.x, v1.y, 0, 0) end g:SetColor(0, 0, 0, 75) g:FillCirclePixelRadius(v + shadowOffset, radius) g:SetColor(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 4 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.iconColor) g:SetColor(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 4 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.iconColor) if self.singleFollowBonesMode then g:SetColor(self.disabledIconColor) end offsetCenter = 0.0045 / currentScale / height iconCenter:Set(v.x - offsetCenter, v.y + offsetCenter) local symbolWidth = 0.015 / currentScale / height local symbolHeight = 0.015 / currentScale / height v1:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolHeight) v2:Set(v1.x, v1.y + symbolHeight * 0.8) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x - symbolWidth, iconCenter.y - symbolHeight) v2:Set(v1.x + symbolHeight * 0.8, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x + symbolWidth, iconCenter.y + symbolHeight) v2:Set(v1.x, v1.y - symbolHeight * 0.8) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x + symbolWidth, iconCenter.y + symbolHeight) v2:Set(v1.x - symbolHeight * 0.8, v1.y) 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:SetPenWidth(2) offsetCenter = 0.009 / currentScale / height iconCenter:Set(v.x + offsetCenter, v.y - offsetCenter) local symbolWidth = 0.006 / currentScale / height local symbolHeight = 0.006 / 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:SetPenWidth(3) -- clear all icon if self.graphicMenuMode == 5 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 5 then radius = self.iconsRadius / (howerRadius / 1.1) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(v, center, math.rad(210))) if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 5 then tooltipSizeH = 0.22 / 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 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(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 5 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) g:SetColor(self.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) -- single bone mode icon local iconRadius = self.iconsRadius if self.graphicMenuMode == 6 then radius = self.iconsRadius * howerRadius else radius = self.iconsRadius end if self.buttonPressed == 6 then radius = self.iconsRadius / (howerRadius / 1.1) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(v, center, math.rad(150))) if self.quickMenuTooltips and HV_Font and self.graphicMenuMode == 6 then tooltipSizeH = 0.396 / 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('Single bone 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(self.iconColorBack) g:FillCirclePixelRadius(v, radius) g:SetPenWidth(3) if self.graphicMenuMode == 6 then g:SetColor(self.iconHowerColor) else g:SetColor(self.iconColor) end g:FrameCirclePixelRadius(v, radius) if self.singleFollowBonesMode then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end 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, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - symbolHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(iconCenter.x + symbolWidth, v2.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - symbolHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(iconCenter.x - symbolWidth, v2.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) g:Pop() end function MR_PoseTool:DrawQuickMenu_3(moho, g) 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 g:SetSmoothing(true) -- Multi Transform icon v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(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 if self.buttonPressed == 1 then radius = self.iconsRadius * radiusMultiplier / (howerRadius / 1.15) 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(self.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(self.iconColor) else g:SetColor(self.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 if self.buttonPressed == 2 then radius = self.iconsRadius * radiusMultiplier / (howerRadius / 1.15) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(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(self.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(self.iconColor) else g:SetColor(self.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 if self.buttonPressed == 3 then radius = self.iconsRadius * radiusMultiplier / (howerRadius / 1.15) end g:SetPenWidth(3) v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(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(self.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(self.iconColor) else g:SetColor(self.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 if self.buttonPressed == 4 then radius = self.iconsRadius * radiusMultiplier / (howerRadius / 1.15) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(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(self.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(self.iconColor) else g:SetColor(self.disabledIconColor) end if MOHO.MohoGlobals.EditMultipleKeys then g:SetColor(self.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 if self.buttonPressed == 5 then radius = self.iconsRadius * radiusMultiplier / (howerRadius / 1.15) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(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(self.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(self.iconColor) else g:SetColor(self.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 if self.buttonPressed == 6 then radius = self.iconsRadius * radiusMultiplier / (howerRadius / 1.15) end v:Set(center.x, center.y + offset) v:Set(MR_Utilities:RotateVector2(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(self.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(self.iconColor) else g:SetColor(self.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 function MR_PoseTool:DrawQuickMenu_4(moho, g) local m = LM.Matrix:new_local() moho.document:GetCameraMatrix(moho.layerFrame, m) g:Push() local currentScale = g:CurrentScale(false) local 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) center:Set(center.x, center.y - 0.15 / currentScale / height) local shadowCenter = LM.Vector2:new_local() shadowCenter:Set(self.graphicsMenuCenter) shadowCenter:Set(center.x, center.y - 0.008 / currentScale / height) local buttonsWidth = 0.05 / currentScale / height local buttonsHeight = 0.05 / currentScale / height local buttonHeight local buttonsRound = 0.02 / currentScale / height 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 local symbolWidth = 0.015 / currentScale / height local symbolHeight = 0.015 / currentScale / height local offsetVec local iconCenter = LM.Vector2:new_local() local tempVec = LM.Vector2:new_local() g:SetSmoothing(true) -- shadow v:Set(shadowCenter.x - buttonsWidth - buttonsWidth / 2, shadowCenter.y) local cornerCenter = LM.Vector2:new_local() g:SetPenWidth(1) g:SetColor(0, 0, 0, 75) g:BeginShape() v1:Set(v.x, v.y - buttonsHeight / 2) v2:Set(v1.x - buttonsWidth + buttonsRound / 1, v1.y) g:AddLine(v1, v2) v1:Set(v.x - buttonsWidth + buttonsRound / 1, v.y - buttonsHeight / 2) v2:Set(v1.x, v1.y + buttonsRound / 1) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y + buttonsHeight - buttonsRound * 2) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x + buttonsRound, v1.y) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v.x + buttonsWidth * 4 - buttonsRound, v2.y) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - buttonsRound / 1) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - buttonsHeight + buttonsRound * 2) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x - buttonsRound, v1.y) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v.x, v2.y) g:AddLine(v1, v2) g:EndShape() -- button 1 if self.graphicMenuMode == 7 then buttonHeight = buttonsHeight * howerRadius else buttonHeight = buttonsHeight end if self.buttonPressed == 7 then buttonHeight = buttonsHeight / (howerRadius * 0.8) end -- fill v:Set(center.x - buttonsWidth - buttonsWidth / 2, center.y) local cornerCenter = LM.Vector2:new_local() g:SetPenWidth(1) g:SetColor(self.iconColorBack) g:BeginShape() v1:Set(v.x, v.y - buttonHeight / 2) v2:Set(v1.x - buttonsWidth + buttonsRound / 1, v1.y) g:AddLine(v1, v2) v1:Set(v.x - buttonsWidth + buttonsRound / 1, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonsRound / 1) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y + buttonHeight - buttonsRound * 2) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x + buttonsRound, v1.y) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v.x, v2.y) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v.x, v2.y - buttonHeight) g:AddLine(v1, v2) g:EndShape() -- stroke local cornerCenter = LM.Vector2:new_local() g:SetPenWidth(3) g:SetColor(self.iconColor) v1:Set(v.x, v.y - buttonHeight / 2) v2:Set(v1.x - buttonsWidth + buttonsRound / 1, v1.y) g:AddLine(v1, v2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v.x - buttonsWidth + buttonsRound / 1, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonsRound / 1) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y + buttonHeight - buttonsRound * 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x + buttonsRound, v1.y) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(-22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v.x, v2.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v.x, v2.y - buttonHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- symbol if self.bonesDataActiveF then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end iconCenter:Set(v.x - buttonsWidth / 2, v.y) g:SetPenWidth(2) symbolWidth = 0.015 / currentScale / height symbolHeight = 0.028 / currentScale / height offsetVec = 0.0009 / currentScale / height iconCenter:Set(iconCenter.x - symbolWidth / 2 + offsetVec * 2, iconCenter.y - offsetVec) v1:Set(iconCenter.x, iconCenter.y - symbolHeight / 2) v2:Set(v1.x, iconCenter.y + symbolHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x + symbolWidth, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y - symbolHeight / 2.5) v2:Set(v1.x - symbolWidth, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- button 2 if self.graphicMenuMode == 8 then buttonHeight = buttonsHeight * howerRadius else buttonHeight = buttonsHeight end if self.buttonPressed == 8 then buttonHeight = buttonsHeight / (howerRadius * 0.8) end -- fill 2 v:Set(center.x - buttonsWidth / 2, center.y) g:SetPenWidth(1) g:SetColor(self.iconColorBack) g:BeginShape() v1:Set(v.x - buttonsWidth, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonHeight) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x + buttonsWidth, v1.y) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - buttonHeight) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v.x - buttonsWidth, v.y - buttonHeight / 2) g:AddLine(v1, v2) g:EndShape() -- Stroke 2 g:SetPenWidth(3) g:SetColor(self.iconColor) v1:Set(v.x - buttonsWidth, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x + buttonsWidth, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - buttonHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v.x - buttonsWidth, v.y - buttonHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- symbol 2 if self.bonesDataActiveIK then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end g:SetPenWidth(2) offsetVec = 0.0315 / currentScale / height symbolWidth = 0.015 / currentScale / height symbolHeight = 0.028 / currentScale / height iconCenter:Set(v.x - buttonsWidth / 2, v.y ) iconCenter:Set(iconCenter.x - symbolWidth / 2 + offsetVec * 0.15, iconCenter.y) v1:Set(iconCenter.x - offsetVec * 0.3, iconCenter.y - symbolHeight / 2) v2:Set(v1.x, iconCenter.y + symbolHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x, iconCenter.y - symbolHeight / 2) v2:Set(v1.x, iconCenter.y + symbolHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y - symbolHeight / 2) tempVec:Set(v1) v2:Set(v1.x + symbolWidth, v1.y + symbolHeight / 2 - offsetVec * 0.04) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(tempVec) v2:Set(v1.x + symbolWidth, v1.y - symbolHeight / 2 + offsetVec * 0.04) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- button 3 if self.graphicMenuMode == 9 then buttonHeight = buttonsHeight * howerRadius else buttonHeight = buttonsHeight end if self.buttonPressed == 9 then buttonHeight = buttonsHeight / (howerRadius * 0.8) end -- fill 3 v:Set(center.x - buttonsWidth / 2, center.y) g:SetPenWidth(1) g:SetColor(self.iconColorBack) g:BeginShape() v1:Set(v.x + buttonsWidth, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonHeight) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x - buttonsWidth, v1.y) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - buttonHeight) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v.x + buttonsWidth, v.y - buttonHeight / 2) g:AddLine(v1, v2) g:EndShape() -- stroke 3 g:SetPenWidth(3) g:SetColor(self.iconColor) v1:Set(v.x + buttonsWidth, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x - buttonsWidth, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - buttonHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v.x + buttonsWidth, v.y - buttonHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- symbol 3 if self.bonesDataActiveA then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end g:SetPenWidth(2) symbolWidth = 0.02 / currentScale / height symbolHeight = 0.028 / currentScale / height iconCenter:Set(v.x + buttonsWidth / 2, v.y ) iconCenter:Set(iconCenter.x - symbolWidth / 2, iconCenter.y) v1:Set(iconCenter.x, iconCenter.y - symbolHeight / 2) v2:Set(v1.x + symbolWidth / 2, iconCenter.y + symbolHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x + symbolWidth / 2, iconCenter.y - symbolHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(iconCenter.x + symbolWidth / 4 , iconCenter.y - symbolHeight * 0.1) v2:Set(v1.x + symbolWidth / 2, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- button 4 if self.graphicMenuMode == 10 then buttonHeight = buttonsHeight * howerRadius else buttonHeight = buttonsHeight end if self.buttonPressed == 10 then buttonHeight = buttonsHeight / (howerRadius * 0.8) end -- fill 4 v:Set(center.x + buttonsWidth - buttonsWidth / 2, center.y) g:SetPenWidth(1) g:SetColor(self.iconColorBack) g:BeginShape() v1:Set(v.x + buttonsWidth, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonHeight) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x - buttonsWidth, v1.y) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - buttonHeight) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v.x + buttonsWidth, v.y - buttonHeight / 2) g:AddLine(v1, v2) g:EndShape() -- stroke 4 g:SetPenWidth(3) g:SetColor(self.iconColor) v1:Set(v.x + buttonsWidth, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x - buttonsWidth, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y - buttonHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v.x + buttonsWidth, v.y - buttonHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- symbol 4 if self.bonesDataActiveP then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end iconCenter:Set(v.x + buttonsWidth / 2, v.y ) g:SetPenWidth(2) symbolWidth = 0.015 / currentScale / height symbolHeight = 0.028 / currentScale / height offsetVec = 0.0009 / currentScale / height iconCenter:Set(iconCenter.x - symbolWidth / 2 + offsetVec * 2, iconCenter.y - offsetVec) v1:Set(iconCenter.x, iconCenter.y - symbolHeight / 2) v2:Set(v1.x, iconCenter.y + symbolHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x + symbolWidth, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y - symbolHeight / 2.5) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x - symbolWidth, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- button 5 if self.graphicMenuMode == 11 then buttonHeight = buttonsHeight * howerRadius else buttonHeight = buttonsHeight end if self.buttonPressed == 11 then buttonHeight = buttonsHeight / (howerRadius * 0.8) end -- fill 5 v:Set(center.x + buttonsWidth * 2 - buttonsWidth / 2, center.y) local cornerCenter = LM.Vector2:new_local() g:SetPenWidth(1) g:SetColor(self.iconColorBack) g:BeginShape() v1:Set(v.x, v.y - buttonHeight / 2) v2:Set(v1.x + buttonsWidth - buttonsRound / 1, v1.y) g:AddLine(v1, v2) v1:Set(v.x + buttonsWidth - buttonsRound / 1, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonsRound / 1) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y + buttonHeight - buttonsRound * 2) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v1.x - buttonsRound, v1.y) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v.x, v2.y) g:AddLine(v1, v2) v1:Set(v2.x, v2.y) v2:Set(v.x, v2.y - buttonHeight) g:AddLine(v1, v2) g:EndShape() -- stroke 5 local cornerCenter = LM.Vector2:new_local() g:SetPenWidth(3) g:SetColor(self.iconColor) v1:Set(v.x, v.y - buttonHeight / 2) v2:Set(v1.x + buttonsWidth - buttonsRound / 1, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v.x + buttonsWidth - buttonsRound / 1, v.y - buttonHeight / 2) v2:Set(v1.x, v1.y + buttonsRound / 1) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y + buttonHeight - buttonsRound * 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x - buttonsRound, v1.y) cornerCenter:Set(v2) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x, v2.y) v2:Set(MR_Utilities:RotateVector2(v1, cornerCenter, math.rad(22.5))) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v.x, v2.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v.x, v2.y - buttonHeight) g:DrawLine(v1.x, v1.y, v2.x, v2.y) -- symbol 5 if self.boneStretching then g:SetColor(self.iconColor) else g:SetColor(self.disabledIconColor) end iconCenter:Set(v.x + buttonsWidth / 2, v.y ) g:SetPenWidth(2) symbolWidth = 0.015 / currentScale / height symbolHeight = 0.028 / currentScale / height offsetVec = 0.0009 / currentScale / height iconCenter:Set(iconCenter.x - symbolWidth / 2, iconCenter.y) v1:Set(iconCenter.x, iconCenter.y - symbolHeight / 2) v2:Set(v1.x + symbolWidth, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y + symbolHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v2.x - symbolWidth, v2.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x, v1.y + symbolHeight / 2) g:DrawLine(v1.x, v1.y, v2.x, v2.y) v1:Set(v2.x, v2.y) v2:Set(v1.x + symbolWidth, v1.y) g:DrawLine(v1.x, v1.y, v2.x, v2.y) end function MR_PoseTool:SetBoneStretching(moho, scan) local skel = moho:Skeleton() if skel == nil then return end if not scan then self:ValidateFollowList(moho) self:ValidateIkList(moho) end local boneStretching = false for i=1, #self.followBonesList.id do for b=1, #self.followBonesList.id[i] do local bone = skel:Bone(self.followBonesList.id[i][b]) if bone.fSelected then if scan then if self.followBonesList.stretching[i] then boneStretching = true break end else self.followBonesList.stretching[i] = not self.boneStretchingIconStatus break end end end end for i=1, #self.ikBonesList.id do for b=1, #self.ikBonesList.id[i] do local bone = skel:Bone(self.ikBonesList.id[i][b]) if bone.fSelected then if scan then if self.ikBonesList.stretching[i] then boneStretching = true break end else self.ikBonesList.stretching[i] = not self.boneStretchingIconStatus break end end end end if scan then self.boneStretchingIconStatus = boneStretching else self:SaveBonesData(moho.layer) end end function MR_PoseTool:PrepareToEditMultipleKeys(moho) local skel = moho:Skeleton() if skel == nil then return end local frame = moho.layerFrame self.bonesKeysAngleList = {} self.bonesKeysPosList = {} self.bonesKeysScaleList = {} for i=0, skel:CountBones()-1 do local bone = skel:Bone(i) self.bonesKeysAngleList[i] = bone.fAnimAngle:GetValue(frame) local posChannel = bone.fAnimPos if posChannel:AreDimensionsSplit() then local channelPosX = posChannel:DimensionChannel(0) local channelPosY = posChannel:DimensionChannel(1) self.bonesKeysPosList[i] = LM.Vector2:new_local() self.bonesKeysPosList[i]:Set(channelPosX:GetValue(frame), channelPosY:GetValue(frame)) else self.bonesKeysPosList[i] = posChannel:GetValue(frame) end self.bonesKeysScaleList[i] = bone.fAnimScale:GetValue(frame) end end function MR_PoseTool:EditMultipleKeys(moho, mode) local skel = moho:Skeleton() if skel == nil or frame == 0 then end local frame = moho.layerFrame for i=0, skel:CountBones()-1 do local bone = skel:Bone(i) local angleDelta = bone.fAnimAngle:GetValue(frame) - self.bonesKeysAngleList[i] if angleDelta ~= 0 then self:AddDeltaToValChannel(moho, bone.fAnimAngle, angleDelta) end local posDelta = LM.Vector2:new_local() local boneChannelPos = bone.fAnimPos if boneChannelPos:AreDimensionsSplit() then local channelPosX = boneChannelPos:DimensionChannel(0) local channelPosY = boneChannelPos:DimensionChannel(1) posDelta:Set(channelPosX:GetValue(frame) - self.bonesKeysPosList[i].x, channelPosY:GetValue(frame) - self.bonesKeysPosList[i].y) if posDelta.x ~= 0 or posDelta.y ~= 0 then self:AddDeltaToValChannel(moho, channelPosX, posDelta.x) self:AddDeltaToValChannel(moho, channelPosY, posDelta.y) end else posDelta:Set(bone.fAnimPos:GetValue(frame)) posDelta:Set(posDelta.x - self.bonesKeysPosList[i].x, posDelta.y - self.bonesKeysPosList[i].y) if posDelta.x ~= 0 or posDelta.y ~= 0 then self:AddDeltaToVec2Channel(moho, bone.fAnimPos, posDelta) end end local scaleDelta = bone.fAnimScale:GetValue(frame) - self.bonesKeysScaleList[i] if scaleDelta ~= 0 then if self.relativeKeyframingScale then local deltaPercentage = ((bone.fAnimScale:GetValue(frame) - self.bonesKeysScaleList[i]) / self.bonesKeysScaleList[i]) * 100 local currentFrame = moho.layerFrame local channel = bone.fAnimScale for keyID = 0, channel:CountKeys() - 1 do local keyFrame = channel:GetKeyWhen(keyID) if (keyFrame > 0 and keyFrame ~= currentFrame and channel:IsKeySelectedByID(keyID)) then local delta = (deltaPercentage / 100) * bone.fAnimScale:GetValue(keyFrame) local newVal = channel:GetValue(keyFrame) + delta channel:SetValue(keyFrame, newVal) end end else self:AddDeltaToValChannel(moho, bone.fAnimScale, scaleDelta) end end end end function MR_PoseTool:AddDeltaToValChannel(moho, channel, delta) local currentFrame = moho.layerFrame for keyID = 0, channel:CountKeys() - 1 do local keyFrame = channel:GetKeyWhen(keyID) if (keyFrame > 0 and keyFrame ~= currentFrame and channel:IsKeySelectedByID(keyID)) then local newVal = channel:GetValue(keyFrame) + delta channel:SetValue(keyFrame, newVal) end end end function MR_PoseTool:AddDeltaToVec2Channel(moho, channel, delta) local currentFrame = moho.layerFrame for keyID = 0, channel:CountKeys() - 1 do local keyFrame = channel:GetKeyWhen(keyID) if (keyFrame > 0 and keyFrame ~= currentFrame and channel:IsKeySelectedByID(keyID)) then local newVec2 = LM.Vector2:new_local() newVec2:Set(channel:GetValue(keyFrame)) newVec2:Set(newVec2.x + delta.x, newVec2.y + delta.y) channel:SetValue(keyFrame, newVec2) end end end function MR_PoseTool:GoToSkeletonLayer(moho, layer, updateToolPanel) if layer then if layer:LayerType() ~= MOHO.LT_BONE then local skelLayer = MR_Utilities:FindSkeletonLayer(layer) if skelLayer then moho:SetSelLayer(skelLayer) moho:ShowLayerInLayersPalette(skelLayer) if updateToolPanel then local drawingToolsNonZero = MOHO.MohoGlobals.DisableDrawingToolsNonZero if not drawingToolsNonZero then MOHO.MohoGlobals.DisableDrawingToolsNonZero = true end local frame = moho.frame self.ignoreUpdateWidgets = true if frame == 0 then moho:SetCurFrame(1) moho:SetCurFrame(0) elseif frame ~= 0 then moho:SetCurFrame(0) moho:SetCurFrame(frame) end if not drawingToolsNonZero then MOHO.MohoGlobals.DisableDrawingToolsNonZero = drawingToolsNonZero end end moho.view:DrawMe() moho.layer:UpdateCurFrame() moho:UpdateUI() end end self.ignoreUpdateWidgets = false end 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['Relative keyframing scale'] = 'Relative keyframing scale in %' phrase['RK blend smoothness:'] = 'RK blend smoothness:' phrase['RK blend in:'] = 'RK blend in:' phrase['out:'] = 'out:' phrase['Skeleton layers navigation'] = 'Skeleton layers navigation' phrase['Double-click to set keyframe'] = 'Double-click to set keyframe' phrase['Click and hold to reset'] = 'Click and hold 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['Toggle panel'] = 'Toggle panel' phrase['Panel size tolltip'] = '' phrase['Show compact panel'] = 'Show compact panel' phrase['Show full panel'] = 'Show full panel' 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['Reset:'] = 'Reset:' phrase['A'] = 'A' phrase['Reset angle'] = 'Reset angle' phrase['T'] = 'T' phrase['Reset translation'] = 'Reset translation' phrase['S'] = 'S' phrase['Reset scale'] = 'Reset scale' phrase['X'] = 'X' phrase['Y'] = 'Y' phrase['Set follow bones chains'] = 'Set follow bones chains' phrase['Set single follow bones'] = 'Set single follow bones' phrase['Set IK bones'] = 'Set IK bones' phrase['Clear all bone stretching'] = 'Clear all bone stretching' phrase['Set bone stretching'] = 'Set bone stretching ' phrase['Lock angle'] = 'Lock angle' phrase['Lock position'] = 'Lock position' phrase['Clear selection'] = 'Clear selection' phrase['Clear all'] = 'Clear all' phrase['Enable'] = 'Enable' phrase['Single bone mode'] = 'Single bone mode' phrase['Reverse IK direction'] = 'Reverse IK direction' phrase['Info'] = 'Info' phrase['Copy link to clipboard'] = 'Copy link to clipboard' phrase['Show more info'] = 'Show more info' phrase['Script link'] = 'https://mohoscripts.com/script/mr_pose_tool' return phrase[text] end
MR Pose Tool
Listed
Author: eugenebabich
View Script
Script type: Tool
Uploaded: Aug 14 2023, 06:38
Last modified: Jul 31 2024, 18:34
Script Version: 3.2.1
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.
Update 1.2
Change List:
1. Improved Lock Handles mode, now there's no need to deselect the current bone to select another.
2. Enhanced Align Handles Along Bone mode, now the handles do not overlap each other when the bone on the screen is small in size. This works only when all four handles are active.
3. Added the ability to customize the color and transparency of the handles.
4. Added Highlight Bones option which draws a line along the bone under the cursor, making it easier to identify which bone you will select when you click.
5. Added Double-click to Reset option, allowing you to disable this feature if it interferes.
Update 1.3
Change List:
1. Added an option that allows blocking the script on even or odd frames. This is convenient if you work in twos, so as not to create keys outside the interval.
MR Pose Tool 2.0
1. Ability to select multiple bones at once.
2. Ability to transform multiple bones at once.
3. Quick access menu to options and functions of the tool.
4. Follow bone, Lock angle, and Lock Pos features, which allow you to find the pose faster by controlling only individual body parts of the character, while maintaining the position of other parts.
5. Added Twos mode option to the panel and in the quick menu.
6. In Lock handles mode, only handles for selected bones are displayed. Previously, this only worked with one bone.
7. The Keep selection option now retains selection only if there has been bone transformation. Meaning, now you can select bones without turning off this option.
Update 2.1
Change List:
1. All information about Follow bones and Lock bones is now stored in the character layer. This allows you to switch freely between characters without needing to reassign bones each time.
2. Added the ability to enable and disable Follow bones and Lock bones for quick access without the need to constantly reassign bones. This can be done via the quick menu or by double-clicking outside the bones.
3. Pressing Ctrl + Alt in the quick menu brings up additional options. For example, you can add individual bones as Follow bones instead of chains of bones.
4. Bug fixes.
Update 2.1.6
Change List:
1. Bug fixes.
MR Pose Tool 3.0
1. The Inverse Kinematic Bones.
2. New Bone Stretching option for Follow Bones and IK Bones that can be assigned separately to different bone chains.
3. Reverse IK Direction button for flipping elbows and knees.
4. All settings for the IK Bones, Follow Bones, and Lock Bones are now stored on the character itself, so it works as part of the rig.
5. The IK Bones, Follow Bones, and Lock Bones can be turned on or off at any moment using the quick menu or by double-clicking outside the bones. Each type of bone can be disabled individually.
6. MR Tween Machine 2.4 supports MR Pose Tool 3 and can use IK Bones, Follow Bones, and Lock Bones.
7. The Set Single Follow Bones button allows you to set them without grouping them into chains.
8. The Single Bone Mode provides an ability to turn on and off the Follow Bones chains without constant re-adjustments.
Please note that when this option is turned on some menu buttons will be disabled. Don't forget to turn it off if you need those buttons.
9. The tool panel now has buttons to reset bones to their default values. Also, the panel can be expanded to provide access to the text fields for the position, angle, and scale of the bones.
10. Holding Alt + Shift allows you to move bones without clicking on their handles.
11. Added an algorithm to verify if all of the tool’s files are available. If the script is installed incorrectly it will let you know what files are missing and what needs to be done to fix it.
12. Added the Info button, which allows you to quickly see the list of all shortcuts of the tool.
Update 3.1.6
Change List:
1. Added support for Relative Keyframing and bug fixes. Please note that when the Relative Keyframing option is enabled, the Smart Bake function becomes unavailable.
2. Added the Skeleton layers navigation option.
Update 3.2
Change List:
1. Relative Keyframing now supports all types of bone transformations.
2. Added option to use percentage values for bone scaling in Relative Keyframing.
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: 3933
MR Pose Tool
Listed
Author: eugenebabich
View Script
Script type: Tool
Uploaded: Aug 14 2023, 06:38
Last modified: Jul 31 2024, 18:34
Script Version: 3.2.1
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.
Update 1.2
Change List:
1. Improved Lock Handles mode, now there's no need to deselect the current bone to select another.
2. Enhanced Align Handles Along Bone mode, now the handles do not overlap each other when the bone on the screen is small in size. This works only when all four handles are active.
3. Added the ability to customize the color and transparency of the handles.
4. Added Highlight Bones option which draws a line along the bone under the cursor, making it easier to identify which bone you will select when you click.
5. Added Double-click to Reset option, allowing you to disable this feature if it interferes.
Update 1.3
Change List:
1. Added an option that allows blocking the script on even or odd frames. This is convenient if you work in twos, so as not to create keys outside the interval.
MR Pose Tool 2.0
1. Ability to select multiple bones at once.
2. Ability to transform multiple bones at once.
3. Quick access menu to options and functions of the tool.
4. Follow bone, Lock angle, and Lock Pos features, which allow you to find the pose faster by controlling only individual body parts of the character, while maintaining the position of other parts.
5. Added Twos mode option to the panel and in the quick menu.
6. In Lock handles mode, only handles for selected bones are displayed. Previously, this only worked with one bone.
7. The Keep selection option now retains selection only if there has been bone transformation. Meaning, now you can select bones without turning off this option.
Update 2.1
Change List:
1. All information about Follow bones and Lock bones is now stored in the character layer. This allows you to switch freely between characters without needing to reassign bones each time.
2. Added the ability to enable and disable Follow bones and Lock bones for quick access without the need to constantly reassign bones. This can be done via the quick menu or by double-clicking outside the bones.
3. Pressing Ctrl + Alt in the quick menu brings up additional options. For example, you can add individual bones as Follow bones instead of chains of bones.
4. Bug fixes.
Update 2.1.6
Change List:
1. Bug fixes.
MR Pose Tool 3.0
1. The Inverse Kinematic Bones.
2. New Bone Stretching option for Follow Bones and IK Bones that can be assigned separately to different bone chains.
3. Reverse IK Direction button for flipping elbows and knees.
4. All settings for the IK Bones, Follow Bones, and Lock Bones are now stored on the character itself, so it works as part of the rig.
5. The IK Bones, Follow Bones, and Lock Bones can be turned on or off at any moment using the quick menu or by double-clicking outside the bones. Each type of bone can be disabled individually.
6. MR Tween Machine 2.4 supports MR Pose Tool 3 and can use IK Bones, Follow Bones, and Lock Bones.
7. The Set Single Follow Bones button allows you to set them without grouping them into chains.
8. The Single Bone Mode provides an ability to turn on and off the Follow Bones chains without constant re-adjustments.
Please note that when this option is turned on some menu buttons will be disabled. Don't forget to turn it off if you need those buttons.
9. The tool panel now has buttons to reset bones to their default values. Also, the panel can be expanded to provide access to the text fields for the position, angle, and scale of the bones.
10. Holding Alt + Shift allows you to move bones without clicking on their handles.
11. Added an algorithm to verify if all of the tool’s files are available. If the script is installed incorrectly it will let you know what files are missing and what needs to be done to fix it.
12. Added the Info button, which allows you to quickly see the list of all shortcuts of the tool.
Update 3.1.6
Change List:
1. Added support for Relative Keyframing and bug fixes. Please note that when the Relative Keyframing option is enabled, the Smart Bake function becomes unavailable.
2. Added the Skeleton layers navigation option.
Update 3.2
Change List:
1. Relative Keyframing now supports all types of bone transformations.
2. Added option to use percentage values for bone scaling in Relative Keyframing.
To work correctly the lower bone (the shin or the forearm) must not have any Y-axis translation.
Update 1.2
Change List:
1. Improved Lock Handles mode, now there's no need to deselect the current bone to select another.
2. Enhanced Align Handles Along Bone mode, now the handles do not overlap each other when the bone on the screen is small in size. This works only when all four handles are active.
3. Added the ability to customize the color and transparency of the handles.
4. Added Highlight Bones option which draws a line along the bone under the cursor, making it easier to identify which bone you will select when you click.
5. Added Double-click to Reset option, allowing you to disable this feature if it interferes.
Update 1.3
Change List:
1. Added an option that allows blocking the script on even or odd frames. This is convenient if you work in twos, so as not to create keys outside the interval.
MR Pose Tool 2.0
1. Ability to select multiple bones at once.
2. Ability to transform multiple bones at once.
3. Quick access menu to options and functions of the tool.
4. Follow bone, Lock angle, and Lock Pos features, which allow you to find the pose faster by controlling only individual body parts of the character, while maintaining the position of other parts.
5. Added Twos mode option to the panel and in the quick menu.
6. In Lock handles mode, only handles for selected bones are displayed. Previously, this only worked with one bone.
7. The Keep selection option now retains selection only if there has been bone transformation. Meaning, now you can select bones without turning off this option.
Update 2.1
Change List:
1. All information about Follow bones and Lock bones is now stored in the character layer. This allows you to switch freely between characters without needing to reassign bones each time.
2. Added the ability to enable and disable Follow bones and Lock bones for quick access without the need to constantly reassign bones. This can be done via the quick menu or by double-clicking outside the bones.
3. Pressing Ctrl + Alt in the quick menu brings up additional options. For example, you can add individual bones as Follow bones instead of chains of bones.
4. Bug fixes.
Update 2.1.6
Change List:
1. Bug fixes.
MR Pose Tool 3.0
1. The Inverse Kinematic Bones.
2. New Bone Stretching option for Follow Bones and IK Bones that can be assigned separately to different bone chains.
3. Reverse IK Direction button for flipping elbows and knees.
4. All settings for the IK Bones, Follow Bones, and Lock Bones are now stored on the character itself, so it works as part of the rig.
5. The IK Bones, Follow Bones, and Lock Bones can be turned on or off at any moment using the quick menu or by double-clicking outside the bones. Each type of bone can be disabled individually.
6. MR Tween Machine 2.4 supports MR Pose Tool 3 and can use IK Bones, Follow Bones, and Lock Bones.
7. The Set Single Follow Bones button allows you to set them without grouping them into chains.
8. The Single Bone Mode provides an ability to turn on and off the Follow Bones chains without constant re-adjustments.
Please note that when this option is turned on some menu buttons will be disabled. Don't forget to turn it off if you need those buttons.
9. The tool panel now has buttons to reset bones to their default values. Also, the panel can be expanded to provide access to the text fields for the position, angle, and scale of the bones.
10. Holding Alt + Shift allows you to move bones without clicking on their handles.
11. Added an algorithm to verify if all of the tool’s files are available. If the script is installed incorrectly it will let you know what files are missing and what needs to be done to fix it.
12. Added the Info button, which allows you to quickly see the list of all shortcuts of the tool.
Update 3.1.6
Change List:
1. Added support for Relative Keyframing and bug fixes. Please note that when the Relative Keyframing option is enabled, the Smart Bake function becomes unavailable.
2. Added the Skeleton layers navigation option.
Update 3.2
Change List:
1. Relative Keyframing now supports all types of bone transformations.
2. Added option to use percentage values for bone scaling in Relative Keyframing.
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: 3933