-- ************************************************** -- Provide Moho with the name of this script object -- ************************************************** ScriptName = "MR_TransformRigTool" -- ************************************************** -- General information about this script -- ************************************************** MR_TransformRigTool = {} function MR_TransformRigTool:Name() return self:Localize('UILabel') end function MR_TransformRigTool:Version() return '1.2.5' end function MR_TransformRigTool:UILabel() return self:Localize('UILabel') end function MR_TransformRigTool:Creator() return 'Eugene Babich' end function MR_TransformRigTool:Description() return self:Localize('Description') end -- ************************************************** -- Is Relevant / Is Enabled -- ************************************************** function MR_TransformRigTool:IsRelevant(moho) local v1, v2, v3 = MR_Utilities:GetMohoVersion(moho) self.mohoVersion = v1 self.isVitruvianBonesAvaible = true self.isBones1353 = true if not v3 then v3 = 0 end if v1 < 13 then self.isVitruvianBonesAvaible = false self.isBones1353 = false elseif v1 == 13 then if v2 < 5 then self.isVitruvianBonesAvaible = false self.isBones1353 = false elseif v3 < 3 then self.isBones1353 = false end end return true end function MR_TransformRigTool:IsEnabled(moho) return true end function MR_TransformRigTool:SupportsGPUMode(moho) return false end -- ************************************************** -- Keyboard/Mouse Control -- ************************************************** function MR_TransformRigTool:LoadPrefs(prefs) self.considerNewParentRotation = prefs:GetBool('MR_TransformRigTool.considerNewParentRotation', false) self.considerOldParentRotation = prefs:GetBool('MR_TransformRigTool.considerOldParentRotation', false) self.centerId = prefs:GetInt("MR_TransformRigTool.centerId", 0) self.selectBonesBt = prefs:GetBool("MR_TransformRigTool.selectBonesBt", true) self.translateBt = prefs:GetBool("MR_TransformRigTool.translateBt", false) self.scaleBt = prefs:GetBool("MR_TransformRigTool.scaleBt", false) self.rotateBt = prefs:GetBool("MR_TransformRigTool.rotateBt", false) self.transformBones = prefs:GetBool("MR_TransformRigTool.transformBones", false) self.transformPoints = prefs:GetBool("MR_TransformRigTool.transformPoints", true) self.autoSelect = prefs:GetBool("MR_TransformRigTool.autoSelect", false) self.ignoreRefLayers = prefs:GetBool("MR_TransformRigTool.ignoreRefLayers", true) self.transformOrigin = prefs:GetBool("MR_TransformRigTool.transformOrigin", true) self.transformVitruvianBones = prefs:GetBool("MR_TransformRigTool.transformVitruvianBones", true) self.transformTargetBones = prefs:GetBool("MR_TransformRigTool.transformTargetBones", true) self.adjustStrokeWidth = prefs:GetBool("MR_TransformRigTool.adjustStrokeWidth", false) self.transformImageLayers = prefs:GetBool("MR_TransformRigTool.transformImageLayers", false) self.transformInfo = prefs:GetBool("MR_TransformRigTool.transformInfo", true) self.followPathAdaptation = prefs:GetBool("MR_TransformRigTool.followPathAdaptation", false) self.transformPatchLayers = prefs:GetBool("MR_TransformRigTool.transformPatchLayers", true) self.useGlobalFlip = prefs:GetBool("MR_TransformRigTool.useGlobalFlip", false) self.adaptiveScaleAndRotation = prefs:GetBool("MR_TransformRigTool.adaptiveScaleAndRotation", false) self.useLineWidthInsteadStrokeWidth = prefs:GetBool("MR_TransformRigTool.useLineWidthInsteadStrokeWidth", false) self.liveUpdatingReferences = prefs:GetBool("MR_TransformRigTool.liveUpdatingReferences", true) self.duplicatedBodypartSuffix = prefs:GetString("MR_TransformRigTool.duplicatedBodypartSuffix", ' Dup') self.directionMode = prefs:GetBool("MR_TransformRigTool.directionMode", true) self.rDirection = prefs:GetBool("MR_TransformRigTool.rDirection", true) self.lDirection = prefs:GetBool("MR_TransformRigTool.lDirection", false) self.customMode = prefs:GetBool("MR_TransformRigTool.customMode", false) self.suffixMode = prefs:GetBool("MR_TransformRigTool.suffixMode", false) self.customModeInput1 = prefs:GetString("MR_TransformRigTool.customModeInput1", 'Front') self.customModeInput2 = prefs:GetString("MR_TransformRigTool.customModeInput2", 'Back') self.counterDelimiter = prefs:GetString("MR_TransformRigTool.counterDelimiter", ' ') self.directionSmartbone = prefs:GetBool("MR_TransformRigTool.directionSmartbone", true) self.renameSmartbone = prefs:GetBool("MR_TransformRigTool.renameSmartbone", false) self.swapNames = prefs:GetBool("MR_TransformRigTool.swapNames", true) end function MR_TransformRigTool:SavePrefs(prefs) prefs:SetBool('MR_TransformRigTool.considerNewParentRotation', self.considerNewParentRotation) prefs:SetBool('MR_TransformRigTool.considerOldParentRotation', self.considerOldParentRotation) prefs:SetInt("MR_TransformRigTool.centerId", self.centerId) prefs:SetBool("MR_TransformRigTool.selectBonesBt", self.selectBonesBt) prefs:SetBool("MR_TransformRigTool.translateBt", self.translateBt) prefs:SetBool("MR_TransformRigTool.scaleBt", self.scaleBt) prefs:SetBool("MR_TransformRigTool.rotateBt", self.rotateBt) prefs:SetBool("MR_TransformRigTool.transformBones", self.transformBones) prefs:SetBool("MR_TransformRigTool.transformPoints", self.transformPoints) prefs:SetBool("MR_TransformRigTool.autoSelect", self.autoSelect) prefs:SetBool("MR_TransformRigTool.ignoreRefLayers", self.ignoreRefLayers) prefs:SetBool("MR_TransformRigTool.transformOrigin", self.transformOrigin) prefs:SetBool("MR_TransformRigTool.transformVitruvianBones", self.transformVitruvianBones) prefs:SetBool("MR_TransformRigTool.transformTargetBones", self.transformTargetBones) prefs:SetBool("MR_TransformRigTool.adjustStrokeWidth", self.adjustStrokeWidth) prefs:SetBool("MR_TransformRigTool.transformImageLayers", self.transformImageLayers) prefs:SetBool("MR_TransformRigTool.transformInfo", self.transformInfo) prefs:SetBool("MR_TransformRigTool.followPathAdaptation", self.followPathAdaptation) prefs:SetBool("MR_TransformRigTool.transformPatchLayers", self.transformPatchLayers) prefs:SetBool("MR_TransformRigTool.useGlobalFlip", self.useGlobalFlip) prefs:SetBool("MR_TransformRigTool.adaptiveScaleAndRotation", self.adaptiveScaleAndRotation) prefs:SetBool("MR_TransformRigTool.useLineWidthInsteadStrokeWidth", self.useLineWidthInsteadStrokeWidth) prefs:SetBool("MR_TransformRigTool.liveUpdatingReferences", self.liveUpdatingReferences) prefs:SetString("MR_TransformRigTool.duplicatedBodypartSuffix", self.duplicatedBodypartSuffix) prefs:SetBool("MR_TransformRigTool.directionMode", self.directionMode) prefs:SetBool("MR_TransformRigTool.rDirection", self.rDirection) prefs:SetBool("MR_TransformRigTool.lDirection", self.lDirection) prefs:SetBool("MR_TransformRigTool.customMode", self.customMode) prefs:SetBool("MR_TransformRigTool.suffixMode", self.suffixMode) prefs:SetString("MR_TransformRigTool.customModeInput1", self.customModeInput1) prefs:SetString("MR_TransformRigTool.customModeInput2", self.customModeInput2) prefs:SetString("MR_TransformRigTool.counterDelimiter", self.counterDelimiter) prefs:SetBool("MR_TransformRigTool.directionSmartbone", self.directionSmartbone) prefs:SetBool("MR_TransformRigTool.renameSmartbone", self.renameSmartbone) prefs:SetBool("MR_TransformRigTool.swapNames", self.swapNames) end function MR_TransformRigTool:ResetPrefs() MR_TransformRigTool.considerNewParentRotation = false MR_TransformRigTool.considerOldParentRotation = false self.centerId = 0 self.selectBonesBt = true self.translateBt = false self.scaleBt = false self.rotateBt = false self.transformBones = false self.transformPoints = true self.autoSelect = false self.ignoreRefLayers = true self.transformOrigin = true self.transformVitruvianBones = true self.transformTargetBones = true self.adjustStrokeWidth = false self.transformImageLayers = false self.transformInfo = true self.followPathAdaptation = false self.transformPatchLayers = true self.useGlobalFlip = false self.adaptiveScaleAndRotation = false self.useLineWidthInsteadStrokeWidth = false self.liveUpdatingReferences = true self.duplicatedBodypartSuffix = ' Dup' self.directionMode = true self.rDirection = true self.lDirection = false self.customMode = false self.suffixMode = false self.customModeInput1 = 'Front' self.customModeInput2 = 'Back' self.counterDelimiter = ' ' self.directionSmartbone = true self.renameSmartbone = false self.swapNames = true end -- ************************************************** -- Recurring Values -- ************************************************** MR_TransformRigTool.considerNewParentRotation = false MR_TransformRigTool.considerOldParentRotation = false MR_TransformRigTool.boneList = {} MR_TransformRigTool.boneRefList = {} MR_TransformRigTool.boneOrigPosList = {} MR_TransformRigTool.boneOrigGlobalPosList = {} MR_TransformRigTool.boneAngleList = {} MR_TransformRigTool.boneAngleExtraList = {} MR_TransformRigTool.boneAngleOffsetList = {} MR_TransformRigTool.boneParentAngleList = {} MR_TransformRigTool.boneParentList = {} MR_TransformRigTool.boneParentMatrixList = {} MR_TransformRigTool.boneLayerId = nil MR_TransformRigTool.status = '' MR_TransformRigTool.fixedBonesList = {} MR_TransformRigTool.fixedActionsList = {} MR_TransformRigTool.totalBones = 0 MR_TransformRigTool.refKey = 1 MR_TransformRigTool.offset = LM.Vector2:new_local() MR_TransformRigTool.centerVec = LM.Vector2:new_local() MR_TransformRigTool.scaling = LM.Vector2:new_local() MR_TransformRigTool.centerId = 0 MR_TransformRigTool.transformType = 0 MR_TransformRigTool.selectBonesBt = true MR_TransformRigTool.translateBt = false MR_TransformRigTool.scaleBt = false MR_TransformRigTool.rotateBt = false MR_TransformRigTool.transformBones = false MR_TransformRigTool.transformPoints = true MR_TransformRigTool.lastScaleX = 1.0 MR_TransformRigTool.lastScaleY = 1.0 MR_TransformRigTool.isFlip = false MR_TransformRigTool.bMin = LM.Vector2:new_local() MR_TransformRigTool.bMax = LM.Vector2:new_local() MR_TransformRigTool.isSkel = false MR_TransformRigTool.autoSelect = false MR_TransformRigTool.transformOrigin = true MR_TransformRigTool.adjustStrokeWidth = false MR_TransformRigTool.startAngle = 0 MR_TransformRigTool.lastVec = LM.Vector2:new_local() MR_TransformRigTool.lastAngle = 0 MR_TransformRigTool.mainSkelSelectedBones = 0 MR_TransformRigTool.lastTransformMode = 0 -- 0=non, 1=transform, 2=scale, 3=scale.x, 4=scale.y, 5=rotate MR_TransformRigTool.lastCenter = LM.Vector2:new_local() MR_TransformRigTool.lastCenterId = LM.Vector2:new_local() MR_TransformRigTool.lastTranslate = LM.Vector2:new_local() MR_TransformRigTool.lastScaling = LM.Vector2:new_local() MR_TransformRigTool.lastScaling:Set(1, 1) MR_TransformRigTool.lastRotate = 0 MR_TransformRigTool.showTransformInfo = false MR_TransformRigTool.mousePos = LM.Vector2:new_local() MR_TransformRigTool.transformInfoText = '' MR_TransformRigTool.ignoreRefLayers = true MR_TransformRigTool.transformImageLayers = false MR_TransformRigTool.refLayersList = {} MR_TransformRigTool.drawingVec = LM.Vector2:new_local() MR_TransformRigTool.drawingStartVec = LM.Vector2:new_local() MR_TransformRigTool.transformCenter = LM.Vector2:new_local() MR_TransformRigTool.blockTransformation = false MR_TransformRigTool.transformVitruvianBones = true MR_TransformRigTool.transformTargetBones = true MR_TransformRigTool.protectLayerTransformation = false MR_TransformRigTool.transformInfo = true MR_TransformRigTool.followPathAdaptation = false MR_TransformRigTool.transformPatchLayers = true MR_TransformRigTool.useGlobalFlip = false MR_TransformRigTool.adaptiveScaleAndRotation = false MR_TransformRigTool.useLineWidthInsteadStrokeWidth = false MR_TransformRigTool.liveUpdatingReferences = true MR_TransformRigTool.newSmartBoneName = '' MR_TransformRigTool.duplicatedBodypartSuffix = ' Dup' MR_TransformRigTool.duplicateActionsMode = 1 -- 1 = to self skeleton, 2 = to another skeleton MR_TransformRigTool.vectorLayersToStrokeChange = {} MR_TransformRigTool.vectorLayersToChange = {} MR_TransformRigTool.vectorLayersToChange.layer = {} MR_TransformRigTool.vectorLayersToChange.parentalFlip = {} MR_TransformRigTool.vectorLayersToChange.layersPosition = {} MR_TransformRigTool.vectorLayersToChange.origin = {} MR_TransformRigTool.vectorLayersToChange.transformOriginsOffset = {} MR_TransformRigTool.followPathGroupsToChange = {} MR_TransformRigTool.followPathGroupsToChange.group = {} MR_TransformRigTool.followPathGroupsToChange.origin = {} MR_TransformRigTool.followPathGroupsToChange.angle = {} MR_TransformRigTool.followPathGroupsToChange.parentalFlip = {} MR_TransformRigTool.followPathGroupsToChange.transform = {} MR_TransformRigTool.followPathGroupsToChange.layersPosition = {} MR_TransformRigTool.groupsToChange = {} MR_TransformRigTool.groupsToChange.group = {} MR_TransformRigTool.patchLayersToChange = {} MR_TransformRigTool.patchLayersToChange.layer = {} MR_TransformRigTool.imageLayersToChange = {} MR_TransformRigTool.imageLayersToChange.layer = {} MR_TransformRigTool.imageLayersToChange.origin = {} MR_TransformRigTool.imageLayersToChange.scale = {} MR_TransformRigTool.imageLayersToChange.position = {} MR_TransformRigTool.imageLayersToChange.angle = {} MR_TransformRigTool.imageLayersToChange.positionOffset = {} MR_TransformRigTool.imageLayersToChange.parentalFlip = {} MR_TransformRigTool.childBonesList = {} MR_TransformRigTool.curvesList = {} MR_TransformRigTool.fPoses = {} MR_TransformRigTool.selList = {} MR_TransformRigTool.refLayersList = {} MR_TransformRigTool.bonesList = {} MR_TransformRigTool.templayersList = {} MR_TransformRigTool.targetBonesList = {} MR_TransformRigTool.areBonesUnlinked = false MR_TransformRigTool.bonesLinkList = {} MR_TransformRigTool.bonesLinkList.bone = {} MR_TransformRigTool.bonesLinkList.parentBone = {} MR_TransformRigTool.smartbonesList = {} MR_TransformRigTool.smartbonesList.originalName = {} MR_TransformRigTool.smartbonesList.newName = {} MR_TransformRigTool.smartbonesList.mode = {} MR_TransformRigTool.smartbonesList.originalAngle = {} MR_TransformRigTool.targetSkelBonesNamesList = {} MR_TransformRigTool.transformedTargetBonesList = {} MR_TransformRigTool.isVitruvianBonesAvaible = true MR_TransformRigTool.isBones1354 = true MR_TransformRigTool.directionMode = true MR_TransformRigTool.rDirection = true MR_TransformRigTool.lDirection = false MR_TransformRigTool.customMode = false MR_TransformRigTool.customModeInput1 = 'Front' MR_TransformRigTool.customModeInput2 = 'Back' MR_TransformRigTool.suffixMode = false MR_TransformRigTool.directionSmartbone = true MR_TransformRigTool.rDirectionSmartbone = true MR_TransformRigTool.lDirectionSmartbone = false MR_TransformRigTool.renameSmartbone = false MR_TransformRigTool.swapNames = true MR_TransformRigTool.fixActionsButton = true MR_TransformRigTool.counterDelimiter = ' ' -- ************************************************** -- MR_SettingsDialog -- ************************************************** local MR_ActionsDialog = {} MR_ActionsDialog.dynamicNumberText = {} MR_ActionsDialog.dynamicSymbolText = {} MR_ActionsDialog.actionInput = {} MR_ActionsDialog.asActionRadioButton = {} MR_ActionsDialog.asSmartboneRadioButton = {} MR_ActionsDialog.removeRadioButton = {} MR_ActionsDialog.edited = '*' MR_ActionsDialog.notEdited = ' ' MR_ActionsDialog.chekNamesMode = false MR_ActionsDialog.editedStatus = {} MR_ActionsDialog.CHANGE = MOHO.MSG_BASE MR_ActionsDialog.SET_R = MOHO.MSG_BASE + 1 MR_ActionsDialog.SET_R_ALT = MOHO.MSG_BASE + 2 MR_ActionsDialog.SET_L = MOHO.MSG_BASE + 3 MR_ActionsDialog.SET_L_ALT = MOHO.MSG_BASE + 4 MR_ActionsDialog.CHECK_NAMES = MOHO.MSG_BASE + 5 MR_ActionsDialog.CHECK_NAMES_ALT = MOHO.MSG_BASE + 6 MR_ActionsDialog.RESTORE_NAMES = MOHO.MSG_BASE + 7 MR_ActionsDialog.AUTO_MODE = MOHO.MSG_BASE + 8 MR_ActionsDialog.AUTO_MODE_ALT = MOHO.MSG_BASE + 9 MR_ActionsDialog.M1 = MOHO.MSG_BASE + 10 MR_ActionsDialog.M3 = MOHO.MSG_BASE + 11 MR_ActionsDialog.CHANGE_TEXT = MOHO.MSG_BASE + 12 MR_ActionsDialog.REPLACE_TEXT = MOHO.MSG_BASE + 13 MR_ActionsDialog.REPLACE_TEXT_ALT = MOHO.MSG_BASE + 14 function MR_ActionsDialog:new(moho) local d = LM.GUI.SimpleDialog(MR_TransformRigTool:Localize('UILabel'), MR_ActionsDialog) local l = d:GetLayout() local fileWord = MOHO.Localize("/Menus/File/File=File") d.dynamicHeaderText = LM.GUI.DynamicText(MR_TransformRigTool:Localize('Smartbones Manager'), 0) l:AddChild(d.dynamicHeaderText, LM.GUI.ALIGN_CENTER, 0) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) l:PushH() local totalActions = #MR_TransformRigTool.smartbonesList.originalName for i = 1, totalActions do d.editedStatus[i] = d.notEdited if totalActions > 60 then if i == 1 then l:PushV() elseif i == 26 then l:Pop() l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) l:PushV() elseif i == 51 or i == 76 then l:Pop() l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) l:PushV() elseif i == 101 then l:Pop() end if i <= 100 then l:PushH() local numberText if i < 10 then numberText = ' '..i else numberText = ''..i end local dynamicTxt = LM.GUI.DynamicText(numberText, 0) d.dynamicNumberText[i] = dynamicTxt l:AddChild(d.dynamicNumberText[i], LM.GUI.ALIGN_LEFT, 0) local symbolText = d.editedStatus[i] local dynamicSymbolTxt = LM.GUI.DynamicText(symbolText, 0) d.dynamicSymbolText[i] = dynamicSymbolTxt l:AddChild(d.dynamicSymbolText[i], LM.GUI.ALIGN_LEFT, 0) textInput = LM.GUI.TextControl(150, ' ', d.CHANGE, LM.GUI.FIELD_TEXT, '') d.actionInput[i] = textInput d.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('Smartbone name does not changed')) l:AddChild(d.actionInput[i], LM.GUI.ALIGN_LEFT, 0) l:AddPadding(1) local asActionRB = LM.GUI.RadioButton(MR_TransformRigTool:Localize('As Action'), d.CHANGE) d.asActionRadioButton[i] = asActionRB d.asActionRadioButton[i]:SetToolTip(MR_TransformRigTool:Localize('Duplicate only action')) l:AddChild(d.asActionRadioButton[i], LM.GUI.ALIGN_LEFT, 0) local asSmartboneRB = LM.GUI.RadioButton(MR_TransformRigTool:Localize('As Smartbone'), d.CHANGE) d.asSmartboneRadioButton[i] = asSmartboneRB d.asSmartboneRadioButton[i]:SetToolTip(MR_TransformRigTool:Localize('Duplicate smartbone')) l:AddChild(d.asSmartboneRadioButton[i], LM.GUI.ALIGN_LEFT, 0) local removeRB = LM.GUI.RadioButton(MR_TransformRigTool:Localize('Remove'), d.CHANGE) d.removeRadioButton[i] = removeRB d.removeRadioButton[i]:SetToolTip(MR_TransformRigTool:Localize('Do not duplicate action')) l:AddChild(d.removeRadioButton[i], LM.GUI.ALIGN_LEFT, 0) l:Pop() end if i == totalActions then l:Pop() end else if i == 1 then l:PushV() elseif i == 16 then l:Pop() l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) l:PushV() elseif i == 31 or i == 46 then l:Pop() l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) l:PushV() elseif i == 61 then l:Pop() end if i <= 60 then l:PushH() local numberText if i < 10 then numberText = ' '..i else numberText = ''..i end local dynamicTxt = LM.GUI.DynamicText(numberText, 0) d.dynamicNumberText[i] = dynamicTxt l:AddChild(d.dynamicNumberText[i], LM.GUI.ALIGN_LEFT, 0) local symbolText = d.editedStatus[i] local dynamicSymbolTxt = LM.GUI.DynamicText(symbolText, 0) d.dynamicSymbolText[i] = dynamicSymbolTxt l:AddChild(d.dynamicSymbolText[i], LM.GUI.ALIGN_LEFT, 0) textInput = LM.GUI.TextControl(150, ' ', d.CHANGE, LM.GUI.FIELD_TEXT, '') d.actionInput[i] = textInput d.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('Smartbone name does not changed')) l:AddChild(d.actionInput[i], LM.GUI.ALIGN_LEFT, 0) l:AddPadding(1) local asActionRB = LM.GUI.RadioButton(MR_TransformRigTool:Localize('As Action'), d.CHANGE) d.asActionRadioButton[i] = asActionRB d.asActionRadioButton[i]:SetToolTip(MR_TransformRigTool:Localize('Duplicate only action')) l:AddChild(d.asActionRadioButton[i], LM.GUI.ALIGN_LEFT, 0) local asSmartboneRB = LM.GUI.RadioButton(MR_TransformRigTool:Localize('As Smartbone'), d.CHANGE) d.asSmartboneRadioButton[i] = asSmartboneRB d.asSmartboneRadioButton[i]:SetToolTip(MR_TransformRigTool:Localize('Duplicate smartbone')) l:AddChild(d.asSmartboneRadioButton[i], LM.GUI.ALIGN_LEFT, 0) local removeRB = LM.GUI.RadioButton(MR_TransformRigTool:Localize('Remove'), d.CHANGE) d.removeRadioButton[i] = removeRB d.removeRadioButton[i]:SetToolTip(MR_TransformRigTool:Localize('Do not duplicate action')) l:AddChild(d.removeRadioButton[i], LM.GUI.ALIGN_LEFT, 0) l:Pop() end if i == totalActions then l:Pop() end end end l:Pop() l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) l:PushH() d.RButton = LM.GUI.Button(MR_TransformRigTool:Localize('Set R'), d.SET_R) d.RButton:SetAlternateMessage(d.SET_R_ALT) d.RButton:SetToolTip(MR_TransformRigTool:Localize('R to L Tooltip')) l:AddChild(d.RButton, LM.GUI.ALIGN_LEFT, 0) d.LButton = LM.GUI.Button(MR_TransformRigTool:Localize('Set L'), d.SET_L) d.LButton:SetAlternateMessage(d.SET_L_ALT) d.LButton:SetToolTip(MR_TransformRigTool:Localize('L to R Tooltip')) l:AddChild(d.LButton, LM.GUI.ALIGN_LEFT, 0) d.autoModeButton = LM.GUI.Button(MR_TransformRigTool:Localize('Auto Mode'), d.AUTO_MODE) d.autoModeButton:SetToolTip(MR_TransformRigTool:Localize('Suggest Tooltip')) d.autoModeButton:SetAlternateMessage(d.AUTO_MODE_ALT) l:AddChild(d.autoModeButton, LM.GUI.ALIGN_LEFT, 0) d.m1Button = LM.GUI.Button(' * ', d.M1) d.m1Button:SetToolTip(MR_TransformRigTool:Localize('Duplicate Actions Tooltip')) l:AddChild(d.m1Button, LM.GUI.ALIGN_LEFT, 0) if fileWord == "Файл" then l:AddPadding(3) else l:AddPadding(14) end d.m3Button = LM.GUI.Button(' - ', d.M3) d.m3Button:SetToolTip(MR_TransformRigTool:Localize('Remove Actions Tooltip')) l:AddChild(d.m3Button, LM.GUI.ALIGN_LEFT, 0) l:Pop() l:PushH() d.replaceTextInput1 = LM.GUI.TextControl(100, ' ', d.CHANGE_TEXT, LM.GUI.FIELD_TEXT, '') d.replaceTextInput1:SetToolTip(MR_TransformRigTool:Localize('Replace Text 1 Tooltip')) l:AddChild(d.replaceTextInput1, LM.GUI.ALIGN_LEFT, 0) d.replaceTextInput2 = LM.GUI.TextControl(100, ' ', d.CHANGE_TEXT, LM.GUI.FIELD_TEXT, '') d.replaceTextInput2:SetToolTip(MR_TransformRigTool:Localize('Replace Text 2 Tooltip')) l:AddChild(d.replaceTextInput2, LM.GUI.ALIGN_LEFT, 0) d.replaceTextButton = LM.GUI.Button(MR_TransformRigTool:Localize('Replace Text'), d.REPLACE_TEXT) d.replaceTextButton:SetToolTip(MR_TransformRigTool:Localize('Replace Text Button Tooltip')) d.replaceTextButton:SetAlternateMessage(d.REPLACE_TEXT_ALT) l:AddChild(d.replaceTextButton, LM.GUI.ALIGN_LEFT, 0) l:Pop() l:PushH() d.checkNamesButton = LM.GUI.Button(MR_TransformRigTool:Localize('Check Names'), d.CHECK_NAMES) d.checkNamesButton:SetToolTip(MR_TransformRigTool:Localize('Check Names Tooltip')) d.checkNamesButton:SetAlternateMessage(d.CHECK_NAMES_ALT) l:AddChild(d.checkNamesButton, LM.GUI.ALIGN_LEFT, 0) l:AddPadding(2) d.restoreNamesButton = LM.GUI.Button(MR_TransformRigTool:Localize('Reset Names'), d.RESTORE_NAMES) d.restoreNamesButton:SetToolTip(MR_TransformRigTool:Localize('Reset Names Tooltip')) l:AddChild(d.restoreNamesButton, LM.GUI.ALIGN_LEFT, 0) l:Pop() return d end function MR_ActionsDialog:UpdateWidgets(moho) for i = 1, #MR_TransformRigTool.smartbonesList.originalName do if i <= 100 then self.actionInput[i]:SetValue(MR_TransformRigTool.smartbonesList.originalName[i]) self.asActionRadioButton[i]:SetValue(false) self.asSmartboneRadioButton[i]:SetValue(true) self.removeRadioButton[i]:SetValue(false) end end self.replaceTextInput1:SetValue(MR_TransformRigTool.customModeInput1) self.replaceTextInput2:SetValue(MR_TransformRigTool.customModeInput2) end function MR_ActionsDialog:OnOK(moho) for i = 1, #MR_TransformRigTool.smartbonesList.originalName do if i <= 100 then MR_TransformRigTool.smartbonesList.newName[i] = self.actionInput[i]:Value() if self.asActionRadioButton[i]:Value() then MR_TransformRigTool.smartbonesList.mode[i] = 1 elseif self.asSmartboneRadioButton[i]:Value() then MR_TransformRigTool.smartbonesList.mode[i] = 2 elseif self.removeRadioButton[i]:Value() then MR_TransformRigTool.smartbonesList.mode[i] = 3 end end end end function MR_ActionsDialog:CheckNameStatus() for i = 1, #self.actionInput do if i <= 100 then local newName = self.actionInput[i]:Value() if newName ~= MR_TransformRigTool.smartbonesList.originalName[i] then self.editedStatus[i] = self.edited self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('Smartbone name is changed')) else self.editedStatus[i] = self.notEdited self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('Smartbone name does not changed')) end self.dynamicSymbolText[i]:SetValue(self.editedStatus[i]) end end end function MR_ActionsDialog:HandleMessage(msg) if msg == self.CHANGE then self:CheckNameStatus() elseif msg == self.SET_R then for i = 1, #self.actionInput do if i <= 100 then local newName = self.actionInput[i]:Value() newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'L', 'R') newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'l', 'r') self.actionInput[i]:SetValue(newName) end end self:CheckNameStatus() elseif msg == self.SET_R_ALT then for i = 1, #self.actionInput do if i <= 100 then local newName = self.actionInput[i]:Value() local tempText1 = 'TEMPTEXT1' local tempText2 = 'TEMPTEXT2' newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'L', tempText1) newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'R', tempText2) newName = MR_TransformRigTool:ChangeNameString(moho, newName, tempText1, 'R') newName = MR_TransformRigTool:ChangeNameString(moho, newName, tempText2, 'L') newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'l', string.lower(tempText1)) newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'r', string.lower(tempText2)) newName = MR_TransformRigTool:ChangeNameString(moho, newName, string.lower(tempText1), 'r') newName = MR_TransformRigTool:ChangeNameString(moho, newName, string.lower(tempText2), 'l') self.actionInput[i]:SetValue(newName) end end self:CheckNameStatus() elseif msg == self.SET_L then for i = 1, #self.actionInput do if i <= 100 then local newName = self.actionInput[i]:Value() newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'R', 'L') newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'r', 'l') self.actionInput[i]:SetValue(newName) end end self:CheckNameStatus() elseif msg == self.SET_L_ALT then for i = 1, #self.actionInput do if i <= 100 then local newName = self.actionInput[i]:Value() local tempText1 = 'TEMPTEXT1' local tempText2 = 'TEMPTEXT2' newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'R', tempText1) newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'L', tempText2) newName = MR_TransformRigTool:ChangeNameString(moho, newName, tempText1, 'L') newName = MR_TransformRigTool:ChangeNameString(moho, newName, tempText2, 'R') newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'r', string.lower(tempText1)) newName = MR_TransformRigTool:ChangeNameString(moho, newName, 'l', string.lower(tempText2)) newName = MR_TransformRigTool:ChangeNameString(moho, newName, string.lower(tempText1), 'l') newName = MR_TransformRigTool:ChangeNameString(moho, newName, string.lower(tempText2), 'r') self.actionInput[i]:SetValue(newName) end end self:CheckNameStatus() elseif msg == self.AUTO_MODE then for i = 1, #MR_TransformRigTool.smartbonesList.originalName do if i <= 100 then local newName1 = MR_TransformRigTool.smartbonesList.originalName[i] local newName2 = MR_TransformRigTool.smartbonesList.originalName[i] newName1 = MR_TransformRigTool:ChangeNameString(moho, newName1, 'L', 'R') newName1 = MR_TransformRigTool:ChangeNameString(moho, newName1, 'l', 'r') newName2 = MR_TransformRigTool:ChangeNameString(moho, newName2, 'R', 'L') newName2 = MR_TransformRigTool:ChangeNameString(moho, newName2, 'r', 'l') if newName1 ~= MR_TransformRigTool.smartbonesList.originalName[i] or newName2 ~= MR_TransformRigTool.smartbonesList.originalName[i] then self.asSmartboneRadioButton[i]:SetValue(true) else self.asActionRadioButton[i]:SetValue(true) end end end self:CheckNameStatus() elseif msg == self.AUTO_MODE_ALT then for i = 1, #self.asSmartboneRadioButton do if i <= 100 then self.asSmartboneRadioButton[i]:SetValue(true) end end elseif msg == self.CHECK_NAMES then if self.chekNamesMode then for i = 1, #self.actionInput do if i <= 100 then self.actionInput[i]:Enable(true) end end self.chekNamesMode = false self:CheckNameStatus() return end self:CheckNameStatus() for i = 1, #self.actionInput do if i <= 100 then if self.actionInput[i]:Value() ~= MR_TransformRigTool.smartbonesList.newName[i] then self.chekNamesMode = true for b = 1, #MR_TransformRigTool.targetSkelBonesNamesList do local boneName = MR_TransformRigTool.targetSkelBonesNamesList[b] if MR_TransformRigTool.duplicateActionsMode == 1 then if self.asActionRadioButton[i]:Value() then self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('This smartbone name is not used')) self.actionInput[i]:Enable(false) elseif self.asSmartboneRadioButton[i]:Value() then if self.actionInput[i]:Value() == boneName then self.actionInput[i]:Enable(true) self.dynamicSymbolText[i]:SetValue('×') self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('This smartbone name is used')) break else self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('This smartbone name is not used')) self.actionInput[i]:Enable(false) end elseif self.removeRadioButton[i]:Value() then self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('This smartbone name is not used')) self.actionInput[i]:Enable(false) end elseif MR_TransformRigTool.duplicateActionsMode == 2 then if self.asActionRadioButton[i]:Value() then self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('This smartbone name is not used')) self.actionInput[i]:Enable(false) elseif self.asSmartboneRadioButton[i]:Value() then if self.actionInput[i]:Value() == boneName then self.actionInput[i]:Enable(true) self.dynamicSymbolText[i]:SetValue('×') self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('This smartbone name is used')) break else self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('This smartbone name is not used')) self.actionInput[i]:Enable(false) end elseif self.removeRadioButton[i]:Value() then self.actionInput[i]:SetToolTip(MR_TransformRigTool:Localize('This smartbone name is not used')) self.actionInput[i]:Enable(false) end end end end end end elseif msg == self.CHECK_NAMES_ALT then for i = 1, #self.actionInput do if i <= 100 then self.actionInput[i]:Enable(true) end end self:CheckNameStatus() elseif msg == self.RESTORE_NAMES then for i = 1, #self.actionInput do if i <= 100 then self.actionInput[i]:SetValue(MR_TransformRigTool.smartbonesList.originalName[i]) self.actionInput[i]:Enable(true) end end self:CheckNameStatus() elseif msg == self.M1 then for i = 1, #self.asActionRadioButton do if i <= 100 then self.asActionRadioButton[i]:SetValue(true) end end elseif msg == self.M3 then for i = 1, #self.asActionRadioButton do if i <= 100 then self.removeRadioButton[i]:SetValue(true) end end elseif msg == self.REPLACE_TEXT then local text1 = self.replaceTextInput1:Value() local text2 = self.replaceTextInput2:Value() for i = 1, #self.actionInput do if i <= 100 then local newName = self.actionInput[i]:Value() newName = MR_TransformRigTool:ChangeNameString(moho, newName, text1, text2) newName = MR_TransformRigTool:ChangeNameString(moho, newName, string.lower(text1), string.lower(text2)) self.actionInput[i]:SetValue(newName) end end self:CheckNameStatus() elseif msg == self.REPLACE_TEXT_ALT then local text1 = self.replaceTextInput1:Value() local text2 = self.replaceTextInput2:Value() self.replaceTextInput1:SetValue(text2) self.replaceTextInput2:SetValue(text1) end end local MR_DuplicateBodypartDialog = {} MR_DuplicateBodypartDialog.DIRECTION_MODE = MOHO.MSG_BASE MR_DuplicateBodypartDialog.SWAP_MODE = MOHO.MSG_BASE + 1 MR_DuplicateBodypartDialog.R_TO_L = MOHO.MSG_BASE + 2 MR_DuplicateBodypartDialog.L_TO_R = MOHO.MSG_BASE + 3 MR_DuplicateBodypartDialog.CUSTOM_MODE = MOHO.MSG_BASE + 4 MR_DuplicateBodypartDialog.CUTOM_INPUT_1 = MOHO.MSG_BASE + 5 MR_DuplicateBodypartDialog.CUTOM_INPUT_2 = MOHO.MSG_BASE + 6 MR_DuplicateBodypartDialog.SUFFIX_MODE = MOHO.MSG_BASE + 7 MR_DuplicateBodypartDialog.SUFFIX = MOHO.MSG_BASE + 8 MR_DuplicateBodypartDialog.REVERSE = MOHO.MSG_BASE + 9 function MR_DuplicateBodypartDialog:new(moho) local d = LM.GUI.SimpleDialog(MR_TransformRigTool:Localize('UILabel'), MR_DuplicateBodypartDialog) local l = d:GetLayout() d.pleaseChoseHowToRenameBonesAndActionsText = LM.GUI.DynamicText(MR_TransformRigTool:Localize('Please chose how to rename bones and actions:'), 0) l:AddChild(d.pleaseChoseHowToRenameBonesAndActionsText, LM.GUI.ALIGN_LEFT, 0) d.swapCheck = LM.GUI.CheckBox(MR_TransformRigTool:Localize('Swap Mode'), d.SWAP_MODE) d.swapCheck:SetToolTip(MR_TransformRigTool:Localize('Swap Mode Tooltip')) l:AddChild(d.swapCheck, LM.GUI.ALIGN_LEFT, 0) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) local fileWord = MOHO.Localize("/Menus/File/File=File") l:PushH() d.directionModeRadioButton = LM.GUI.RadioButton(MR_TransformRigTool:Localize('Direction Mode'), d.DIRECTION_MODE) d.directionModeRadioButton:SetToolTip(MR_TransformRigTool:Localize('Direction Mode Tooltip')) l:AddChild(d.directionModeRadioButton, LM.GUI.ALIGN_LEFT, 0) if fileWord == "Файл" then l:AddPadding(25) else l:AddPadding(54) end l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) d.rToLCheck = LM.GUI.CheckBox('R ➞ L', d.R_TO_L) d.rToLCheck:SetToolTip(MR_TransformRigTool:Localize('R to L Tooltip')) l:AddChild(d.rToLCheck, LM.GUI.ALIGN_LEFT, 0) l:AddPadding(84) d.lToRCheck = LM.GUI.CheckBox('L ➞ R', d.L_TO_R) d.lToRCheck:SetToolTip(MR_TransformRigTool:Localize('L to R Tooltip')) l:AddChild(d.lToRCheck, LM.GUI.ALIGN_LEFT, 0) l:Pop() l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) l:PushH() d.customModeRadioButton = LM.GUI.RadioButton(MR_TransformRigTool:Localize('Custom Mode'), d.CUSTOM_MODE) d.customModeRadioButton:SetToolTip(MR_TransformRigTool:Localize('Custom Mode Tooltip')) l:AddChild(d.customModeRadioButton, LM.GUI.ALIGN_LEFT, 0) if fileWord == "Файл" then l:AddPadding(22) else l:AddPadding(7) end l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) d.customInput1 = LM.GUI.TextControl(100, '', d.CUTOM_INPUT_1, LM.GUI.FIELD_TEXT, '') d.customInput1:SetToolTip(MR_TransformRigTool:Localize('Replace Text 1 Tooltip')) l:AddChild(d.customInput1, LM.GUI.ALIGN_LEFT, 0) d.reversrButton = LM.GUI.Button('↔', d.REVERSE) d.reversrButton:SetToolTip(MR_TransformRigTool:Localize('Reverse Tooltip')) l:AddChild(d.reversrButton, LM.GUI.ALIGN_LEFT, 0) d.customInput2 = LM.GUI.TextControl(100, '', d.CUTOM_INPUT_2, LM.GUI.FIELD_TEXT, '') d.customInput2:SetToolTip(MR_TransformRigTool:Localize('Replace Text 2 Tooltip')) l:AddChild(d.customInput2, LM.GUI.ALIGN_LEFT, 0) l:Pop() l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) l:PushH() d.suffixModeRadioButton = LM.GUI.RadioButton(MR_TransformRigTool:Localize('Suffix Mode'), d.SUFFIX_MODE) d.suffixModeRadioButton:SetToolTip(MR_TransformRigTool:Localize('Suffix Mode Tooltip')) l:AddChild(d.suffixModeRadioButton, LM.GUI.ALIGN_LEFT, 0) if fileWord == "Файл" then l:AddPadding(1) else l:AddPadding(55) end l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) d.suffixInput = LM.GUI.TextControl(100, '', d.SUFFIX, LM.GUI.FIELD_TEXT, MR_TransformRigTool:Localize('')) d.suffixInput:SetToolTip(MR_TransformRigTool:Localize('Suffix Tooltip')) l:AddChild(d.suffixInput, LM.GUI.ALIGN_LEFT, 0) l:Pop() return d end function MR_DuplicateBodypartDialog:UpdateWidgets() self.swapCheck:SetValue(MR_TransformRigTool.swapNames) self.directionModeRadioButton:SetValue(MR_TransformRigTool.directionMode) self.rToLCheck:SetValue(MR_TransformRigTool.rDirection) self.lToRCheck:SetValue(MR_TransformRigTool.lDirection) self.customModeRadioButton:SetValue(MR_TransformRigTool.customMode) self.customInput1:SetValue(MR_TransformRigTool.customModeInput1) self.customInput2:SetValue(MR_TransformRigTool.customModeInput2) self.suffixModeRadioButton:SetValue(MR_TransformRigTool.suffixMode) self.suffixInput:SetValue(MR_TransformRigTool.duplicatedBodypartSuffix) self.rToLCheck:Enable(MR_TransformRigTool.directionMode) self.lToRCheck:Enable(MR_TransformRigTool.directionMode) self.customInput1:Enable(MR_TransformRigTool.customMode) self.customInput2:Enable(MR_TransformRigTool.customMode) self.suffixInput:Enable(MR_TransformRigTool.suffixMode) self.reversrButton:Enable(MR_TransformRigTool.customMode) end function MR_DuplicateBodypartDialog:OnOK() MR_TransformRigTool.swapNames = self.swapCheck:Value() MR_TransformRigTool.directionMode = self.directionModeRadioButton:Value() MR_TransformRigTool.rDirection = self.rToLCheck:Value() MR_TransformRigTool.lDirection = self.lToRCheck:Value() MR_TransformRigTool.customMode = self.customModeRadioButton:Value() MR_TransformRigTool.customModeInput1 = self.customInput1:Value() MR_TransformRigTool.customModeInput2 = self.customInput2:Value() MR_TransformRigTool.suffixMode = self.suffixModeRadioButton:Value() if self.suffixInput:Value() ~= '' then MR_TransformRigTool.duplicatedBodypartSuffix = self.suffixInput:Value() else MR_TransformRigTool.duplicatedBodypartSuffix = ' ' end end function MR_DuplicateBodypartDialog:HandleMessage(msg) if msg == self.SWAP_MODE then elseif msg == self.DIRECTION_MODE then self.directionModeRadioButton:SetValue(true) self.customModeRadioButton:SetValue(false) self.suffixModeRadioButton:SetValue(false) self.rToLCheck:Enable(true) self.lToRCheck:Enable(true) self.customInput1:Enable(false) self.customInput2:Enable(false) self.suffixInput:Enable(false) self.reversrButton:Enable(false) elseif msg == self.R_TO_L then self.rToLCheck:SetValue(true) self.lToRCheck:SetValue(false) elseif msg == self.L_TO_R then self.rToLCheck:SetValue(false) self.lToRCheck:SetValue(true) elseif msg == self.CUSTOM_MODE then self.directionModeRadioButton:SetValue(false) self.customModeRadioButton:SetValue(true) self.suffixModeRadioButton:SetValue(false) self.rToLCheck:Enable(false) self.lToRCheck:Enable(false) self.customInput1:Enable(true) self.customInput2:Enable(true) self.suffixInput:Enable(false) self.reversrButton:Enable(true) elseif msg == self.CUTOM_INPUT_1 then elseif msg == self.CUTOM_INPUT_2 then elseif msg == self.REVERSE then local text1 = self.customInput1:Value() local text2 = self.customInput2:Value() self.customInput1:SetValue(text2) self.customInput2:SetValue(text1) elseif msg == self.SUFFIX_MODE then self.directionModeRadioButton:SetValue(false) self.customModeRadioButton:SetValue(false) self.suffixModeRadioButton:SetValue(true) self.rToLCheck:Enable(false) self.lToRCheck:Enable(false) self.customInput1:Enable(false) self.customInput2:Enable(false) self.suffixInput:Enable(true) self.reversrButton:Enable(false) elseif msg == self.SUFFIX then end end local MR_RenameSmartBoneDialog = {} MR_RenameSmartBoneDialog.DIRECTION_MODE = MOHO.MSG_BASE MR_RenameSmartBoneDialog.RENAME_SMARTBONE = MOHO.MSG_BASE + 1 MR_RenameSmartBoneDialog.R_TO_L = MOHO.MSG_BASE + 2 MR_RenameSmartBoneDialog.L_TO_R = MOHO.MSG_BASE + 3 function MR_RenameSmartBoneDialog:new(moho, name) MR_TransformRigTool.newSmartBoneName = name local d = LM.GUI.SimpleDialog(MR_TransformRigTool:Localize('UILabel'), MR_RenameSmartBoneDialog) local l = d:GetLayout() local fileWord = MOHO.Localize("/Menus/File/File=File") d.pleaseChoseHowToRenameSmartboneText = LM.GUI.DynamicText(MR_TransformRigTool:Localize('Please chose how to rename smartbone:'), 0) l:AddChild(d.pleaseChoseHowToRenameSmartboneText, LM.GUI.ALIGN_LEFT, 0) l:PushH() d.directionModeRadioButton = LM.GUI.RadioButton(MR_TransformRigTool:Localize('Direction Mode'), d.DIRECTION_MODE) d.directionModeRadioButton:SetToolTip(MR_TransformRigTool:Localize('Direction Mode Tooltip')) l:AddChild(d.directionModeRadioButton, LM.GUI.ALIGN_LEFT, 0) if fileWord == "Файл" then l:AddPadding(1) else l:AddPadding(34) end l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) d.rToLCheck = LM.GUI.CheckBox('R ➞ L', d.R_TO_L) d.rToLCheck:SetToolTip(MR_TransformRigTool:Localize('R to L Tooltip')) l:AddChild(d.rToLCheck, LM.GUI.ALIGN_LEFT, 0) l:AddPadding(30) d.lToRCheck = LM.GUI.CheckBox('L ➞ R', d.L_TO_R) d.lToRCheck:SetToolTip(MR_TransformRigTool:Localize('L to R Tooltip')) l:AddChild(d.lToRCheck, LM.GUI.ALIGN_LEFT, 0) l:Pop() l:PushH() d.renameSmartboneRadioButton = LM.GUI.RadioButton(MR_TransformRigTool:Localize('Rename Smartbone'), d.RENAME_SMARTBONE) d.renameSmartboneRadioButton:SetToolTip(MR_TransformRigTool:Localize('Rename Smartbone Tooltip')) l:AddChild(d.renameSmartboneRadioButton, LM.GUI.ALIGN_LEFT, 0) if fileWord == "Файл" then l:AddPadding(21) else l:AddPadding(1) end l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) d.textInput = LM.GUI.TextControl(150, name) d.textInput:SetToolTip(MR_TransformRigTool:Localize('New Smartbone Name Tooltip')) l:AddChild(d.textInput, LM.GUI.ALIGN_LEFT) l:Pop() return d end function MR_RenameSmartBoneDialog:UpdateWidgets() self.directionModeRadioButton:SetValue(MR_TransformRigTool.directionSmartbone) self.rToLCheck:SetValue(MR_TransformRigTool.rDirectionSmartbone) self.lToRCheck:SetValue(MR_TransformRigTool.lDirectionSmartbone) self.renameSmartboneRadioButton:SetValue(MR_TransformRigTool.renameSmartbone) self.rToLCheck:Enable(MR_TransformRigTool.directionSmartbone) self.lToRCheck:Enable(MR_TransformRigTool.directionSmartbone) self.textInput:Enable(MR_TransformRigTool.renameSmartbone) end function MR_RenameSmartBoneDialog:OnOK() if self.textInput:Value() ~= '' then MR_TransformRigTool.newSmartBoneName = self.textInput:Value() end MR_TransformRigTool.directionSmartbone = self.directionModeRadioButton:Value() MR_TransformRigTool.rDirectionSmartbone = self.rToLCheck:Value() MR_TransformRigTool.lDirectionSmartbone = self.lToRCheck:Value() MR_TransformRigTool.renameSmartbone = self.renameSmartboneRadioButton:Value() end function MR_RenameSmartBoneDialog:HandleMessage(msg) if msg == self.DIRECTION_MODE then self.directionModeRadioButton:SetValue(true) self.renameSmartboneRadioButton:SetValue(false) self.rToLCheck:Enable(true) self.lToRCheck:Enable(true) self.textInput:Enable(false) elseif msg == self.R_TO_L then self.rToLCheck:SetValue(true) self.lToRCheck:SetValue(false) elseif msg == self.L_TO_R then self.rToLCheck:SetValue(false) self.lToRCheck:SetValue(true) elseif msg == self.RENAME_SMARTBONE then self.directionModeRadioButton:SetValue(false) self.renameSmartboneRadioButton:SetValue(true) self.rToLCheck:Enable(false) self.lToRCheck:Enable(false) self.textInput:Enable(true) end end local MR_SettingsDialog = {} MR_SettingsDialog.SHOW_TRANSFORM_INFO = MOHO.MSG_BASE MR_SettingsDialog.USE_GLOBAL_FLIP = MOHO.MSG_BASE + 1 MR_SettingsDialog.ADAPTIVE_SCALE_AND_ROTATION = MOHO.MSG_BASE + 2 MR_SettingsDialog.USE_LINE_WIDTH = MOHO.MSG_BASE + 3 MR_SettingsDialog.LIVE_UPDATING_REFERENCES = MOHO.MSG_BASE + 4 MR_SettingsDialog.DUPLICATED_BODYPART_SUFFIX = MOHO.MSG_BASE + 5 MR_SettingsDialog.COUNTER_DELIMITER = MOHO.MSG_BASE + 6 MR_SettingsDialog.CONSIDER_NEW_PARENT_ROTATION = MOHO.MSG_BASE + 7 MR_SettingsDialog.CONSIDER_OLD_PARENT_ROTATION = MOHO.MSG_BASE + 8 function MR_SettingsDialog:new() local d = LM.GUI.SimpleDialog(MR_TransformRigTool:Localize('UILabel'), MR_SettingsDialog) local l = d:GetLayout() d.statusText = LM.GUI.DynamicText(MR_TransformRigTool:Localize('Live transformation settings:'), 0) l:AddChild(d.statusText, LM.GUI.ALIGN_LEFT, 0) if HV_Font then d.showTransformInfoCheck = LM.GUI.CheckBox(MR_TransformRigTool:Localize('Show Transform Info'), self.SHOW_TRANSFORM_INFO) l:AddChild(d.showTransformInfoCheck, LM.GUI.ALIGN_LEFT, 0) end d.useGlobalFlipCheck = LM.GUI.CheckBox(MR_TransformRigTool:Localize('Use Global Flip'), self.USE_GLOBAL_FLIP) l:AddChild(d.useGlobalFlipCheck, LM.GUI.ALIGN_LEFT, 0) d.adaptiveScaleAndRotationCheck = LM.GUI.CheckBox(MR_TransformRigTool:Localize('Adaptive scale and rotation'), self.ADAPTIVE_SCALE_AND_ROTATION) l:AddChild(d.adaptiveScaleAndRotationCheck, LM.GUI.ALIGN_LEFT, 0) d.useLineWidthInsteadStrokeWidthCheck = LM.GUI.CheckBox(MR_TransformRigTool:Localize('Use Line Width'), self.USE_LINE_WIDTH) l:AddChild(d.useLineWidthInsteadStrokeWidthCheck, LM.GUI.ALIGN_LEFT, 0) d.liveUpdatingReferencesCheck = LM.GUI.CheckBox(MR_TransformRigTool:Localize('Live updating references'), self.LIVE_UPDATING_REFERENCES) l:AddChild(d.liveUpdatingReferencesCheck, LM.GUI.ALIGN_LEFT, 0) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) d.statusText2 = LM.GUI.DynamicText(MR_TransformRigTool:Localize('Duplicate bodypart settings:'), 0) l:AddChild(d.statusText2, LM.GUI.ALIGN_LEFT, 0) d.duplicatedBodypartSuffixInput = LM.GUI.TextControl(75, '', self.ADAPTIVE_SCALE_AND_ROTATION, LM.GUI.FIELD_TEXT, MR_TransformRigTool:Localize('Duplicated names suffix')) l:AddChild(d.duplicatedBodypartSuffixInput, LM.GUI.ALIGN_LEFT, 0) d.counterDelimiterInput = LM.GUI.TextControl(51, '', self.COUNTER_DELIMITER, LM.GUI.FIELD_TEXT, MR_TransformRigTool:Localize('Counter delimiter')) l:AddChild(d.counterDelimiterInput, LM.GUI.ALIGN_LEFT, 0) l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL) d.statusText3 = LM.GUI.DynamicText(MR_TransformRigTool:Localize('Advanced mode settings:'), 0) l:AddChild(d.statusText3, LM.GUI.ALIGN_LEFT, 0) d.considerNewParentRotationCheckbox = LM.GUI.CheckBox(MR_TransformRigTool:Localize('Consider new parent rotation'), d.CONSIDER_NEW_PARENT_ROTATION) l:AddChild(d.considerNewParentRotationCheckbox, LM.GUI.ALIGN_LEFT, 0) d.considerOldParentRotationCheckbox = LM.GUI.CheckBox(MR_TransformRigTool:Localize('Consider old parent rotation'), d.CONSIDER_OLD_PARENT_ROTATION) l:AddChild(d.considerOldParentRotationCheckbox, LM.GUI.ALIGN_LEFT, 0) return d end function MR_SettingsDialog:UpdateWidgets(moho) if HV_Font then self.showTransformInfoCheck:SetValue(MR_TransformRigTool.transformInfo) end self.useGlobalFlipCheck:SetValue(MR_TransformRigTool.useGlobalFlip) self.adaptiveScaleAndRotationCheck:SetValue(MR_TransformRigTool.adaptiveScaleAndRotation) self.useLineWidthInsteadStrokeWidthCheck:SetValue(MR_TransformRigTool.useLineWidthInsteadStrokeWidth) self.liveUpdatingReferencesCheck:SetValue(MR_TransformRigTool.liveUpdatingReferences) self.duplicatedBodypartSuffixInput:SetValue(MR_TransformRigTool.duplicatedBodypartSuffix) self.counterDelimiterInput:SetValue(MR_TransformRigTool.counterDelimiter) self.considerNewParentRotationCheckbox:SetValue(MR_TransformRigTool.considerNewParentRotation) self.considerOldParentRotationCheckbox:SetValue(MR_TransformRigTool.considerOldParentRotation) end function MR_SettingsDialog:OnOK(moho) if HV_Font then MR_TransformRigTool.transformInfo = self.showTransformInfoCheck:Value() end MR_TransformRigTool.useGlobalFlip = self.useGlobalFlipCheck:Value() MR_TransformRigTool.adaptiveScaleAndRotation = self.adaptiveScaleAndRotationCheck:Value() MR_TransformRigTool.useLineWidthInsteadStrokeWidth = self.useLineWidthInsteadStrokeWidthCheck:Value() MR_TransformRigTool.liveUpdatingReferences = self.liveUpdatingReferencesCheck:Value() if self.duplicatedBodypartSuffixInput:Value() ~= '' then MR_TransformRigTool.duplicatedBodypartSuffix = self.duplicatedBodypartSuffixInput:Value() else MR_TransformRigTool.duplicatedBodypartSuffix = ' ' end MR_TransformRigTool.counterDelimiter = self.counterDelimiterInput:Value() MR_TransformRigTool.considerNewParentRotation = self.considerNewParentRotationCheckbox:Value() MR_TransformRigTool.considerOldParentRotation = self.considerOldParentRotationCheckbox:Value() end function MR_SettingsDialog:HandleMessage(msg) if msg == self.SHOW_TRANSFORM_INFO then if HV_Font then MR_TransformRigTool.transformInfo = self.showTransformInfoCheck:Value() end elseif msg == self.USE_GLOBAL_FLIP then MR_TransformRigTool.useGlobalFlip = self.useGlobalFlipCheck:Value() elseif msg == self.ADAPTIVE_SCALE_AND_ROTATION then MR_TransformRigTool.adaptiveScaleAndRotation = self.adaptiveScaleAndRotationCheck:Value() elseif msg == self.USE_LINE_WIDTH then MR_TransformRigTool.useLineWidthInsteadStrokeWidth = self.useLineWidthInsteadStrokeWidthCheck:Value() elseif msg == self.LIVE_UPDATING_REFERENCES then MR_TransformRigTool.liveUpdatingReferences = self.liveUpdatingReferencesCheck:Value() elseif msg == self.DUPLICATED_BODYPART_SUFFIX then MR_TransformRigTool.duplicatedBodypartSuffix = duplicatedBodypartSuffixInput:Value() elseif msg == self.COUNTER_DELIMITER then MR_TransformRigTool.counterDelimiter = self.counterDelimiterInput:Value() elseif msg == self.CONSIDER_NEW_PARENT_ROTATION then self.considerNewParentRotation = self.considerNewParentRotationCheckbox:Value() elseif msg == self.CONSIDER_OLD_PARENT_ROTATION then self.considerOldParentRotation = self.considerOldParentRotationCheckbox:Value() end end -- ************************************************** -- editLestTransformDialog -- ************************************************** local MR_EditLastTransformDialog = {} MR_EditLastTransformDialog.X = MOHO.MSG_BASE MR_EditLastTransformDialog.Y = MOHO.MSG_BASE + 1 MR_EditLastTransformDialog.ANGLE = MOHO.MSG_BASE + 2 MR_EditLastTransformDialog.APPLY = MOHO.MSG_BASE + 3 MR_EditLastTransformDialog.APPLY_ALT = MOHO.MSG_BASE + 4 function MR_EditLastTransformDialog:new() local d = LM.GUI.SimpleDialog(MR_TransformRigTool:Localize('UILabel'), MR_EditLastTransformDialog) local l = d:GetLayout() d.xInput = LM.GUI.TextControl(0, '0.0000', d.X, LM.GUI.FIELD_FLOAT, MR_TransformRigTool:Localize('X')) d.xInput:SetWheelInc(0.01) l:AddChild(d.xInput, LM.GUI.ALIGN_LEFT, 0) d.yInput = LM.GUI.TextControl(0, '0.0000', d.Y, LM.GUI.FIELD_FLOAT, MR_TransformRigTool:Localize('Y')) d.yInput:SetWheelInc(0.1) l:AddChild(d.yInput, LM.GUI.ALIGN_LEFT, 0) d.angleInput = LM.GUI.TextControl(0, '0.0000', d.ANGLE, LM.GUI.FIELD_FLOAT, MR_TransformRigTool:Localize('Angle')) d.angleInput:SetWheelInc(1) l:AddChild(d.angleInput, LM.GUI.ALIGN_LEFT, 0) d.applyButton = LM.GUI.Button(MR_TransformRigTool:Localize('Apply'), d.APPLY) d.applyButton:SetAlternateMessage(d.APPLY_ALT) l:AddChild(d.applyButton, LM.GUI.ALIGN_LEFT, 0) return d end function MR_EditLastTransformDialog:UpdateWidgets(moho) if MR_TransformRigTool.translateBt then self.xInput:SetValue(MR_TransformRigTool.lastTranslate.x or 0) self.yInput:SetValue(MR_TransformRigTool.lastTranslate.y or 0) self.xInput:Enable(true) self.yInput:Enable(true) self.angleInput:Enable(false) self.angleInput:SetValue('') elseif MR_TransformRigTool.scaleBt then self.xInput:SetValue(MR_TransformRigTool.lastScaling.x or 1) self.yInput:SetValue(MR_TransformRigTool.lastScaling.y or 1) self.angleInput:SetValue(math.deg(MR_TransformRigTool.lastAngle) or 0) self.xInput:Enable(true) self.yInput:Enable(true) self.angleInput:Enable(false) self.angleInput:SetValue('') elseif MR_TransformRigTool.rotateBt then local angle = MR_TransformRigTool.lastAngle or 0 self.angleInput:SetValue(math.deg(angle)) self.xInput:SetValue('') self.yInput:SetValue('') self.xInput:Enable(false) self.yInput:Enable(false) self.angleInput:Enable(true) end end function MR_EditLastTransformDialog:OnOK(moho) end function MR_EditLastTransformDialog:HandleMessage(msg) if msg == self.X then elseif msg == self.Y then elseif msg == self.ANGLE then elseif msg == self.APPLY then if MR_TransformRigTool.translateBt then MR_TransformRigTool.lastTranslate:Set(self.xInput:FloatValue(), self.yInput:FloatValue()) self.xInput:SetValue(MR_TransformRigTool.lastTranslate.x) self.yInput:SetValue(MR_TransformRigTool.lastTranslate.y) MR_TransformRigTool.lastTransformMode = 1 MR_TransformRigTool.repeatLastTransformationButton:SetToolTip(MR_TransformRigTool:Localize('Apply Custom Translate')) elseif MR_TransformRigTool.scaleBt then MR_TransformRigTool.lastScaling:Set(self.xInput:FloatValue(), self.yInput:FloatValue()) self.xInput:SetValue(MR_TransformRigTool.lastScaling.x) self.yInput:SetValue(MR_TransformRigTool.lastScaling.y) MR_TransformRigTool.lastTransformMode = 2 MR_TransformRigTool.updateCenterButton:Enable(true) MR_TransformRigTool.repeatLastTransformationButton:SetToolTip(MR_TransformRigTool:Localize('Apply Custom Scale')) elseif MR_TransformRigTool.rotateBt then MR_TransformRigTool.lastAngle = math.rad(self.angleInput:FloatValue()) self.angleInput:SetValue(math.deg(MR_TransformRigTool.lastAngle)) MR_TransformRigTool.lastTransformMode = 5 MR_TransformRigTool.updateCenterButton:Enable(true) MR_TransformRigTool.repeatLastTransformationButton:SetToolTip(MR_TransformRigTool:Localize('Apply Custom Rotation')) end MR_TransformRigTool.repeatLastTransformationButton:Enable(true) MR_TransformRigTool.lastCenterId = MR_TransformRigTool.centerId elseif msg == self.APPLY_ALT then self.yInput:SetValue(self.xInput:FloatValue()) end end -- ************************************************** -- Tool Panel Layout -- ************************************************** MR_TransformRigTool.ADVANCED_MODE = MOHO.MSG_BASE MR_TransformRigTool.FIX_ACTIONS = MOHO.MSG_BASE + 1 MR_TransformRigTool.CLEAR = MOHO.MSG_BASE + 2 MR_TransformRigTool.CUSTOM_CENTER = MOHO.MSG_BASE + 3 MR_TransformRigTool.SELECTED_BONE = MOHO.MSG_BASE + 4 MR_TransformRigTool.SET_FROM_SELECTION = MOHO.MSG_BASE + 5 MR_TransformRigTool.SET_FROM_SELECTION_ALT = MOHO.MSG_BASE + 6 MR_TransformRigTool.DUPLICATE_BODYPART = MOHO.MSG_BASE + 7 MR_TransformRigTool.COPY_BODYPART = MOHO.MSG_BASE + 8 MR_TransformRigTool.FLIP_H = MOHO.MSG_BASE + 9 MR_TransformRigTool.FLIP_H_ALT = MOHO.MSG_BASE + 10 MR_TransformRigTool.FLIP_V = MOHO.MSG_BASE + 11 MR_TransformRigTool.FLIP_V_ALT = MOHO.MSG_BASE + 12 MR_TransformRigTool.DUPLICATE_AND_FLIP_SMARTBONE = MOHO.MSG_BASE + 13 MR_TransformRigTool.DUPLICATE_AND_FLIP_SMARTBONE_ALT = MOHO.MSG_BASE + 14 MR_TransformRigTool.RECONNECT_BONES = MOHO.MSG_BASE + 15 MR_TransformRigTool.RECONNECT_BONES_ALT = MOHO.MSG_BASE + 16 MR_TransformRigTool.SELECT_ALL_POINTS = MOHO.MSG_BASE + 17 MR_TransformRigTool.DESELECT_ALL_POINTS = MOHO.MSG_BASE + 18 MR_TransformRigTool.CHECK_FOR_SPLIT_DIMENSIONS = MOHO.MSG_BASE + 19 MR_TransformRigTool.IGNORE_REF = MOHO.MSG_BASE + 20 MR_TransformRigTool.TRANSFORM_POINTS = MOHO.MSG_BASE + 21 MR_TransformRigTool.AUTO_SELECT_POINTS = MOHO.MSG_BASE + 22 MR_TransformRigTool.ADJUST_STROKE_WIDTH = MOHO.MSG_BASE + 23 MR_TransformRigTool.FOLLOW_PATH_ADAPTATION = MOHO.MSG_BASE + 24 MR_TransformRigTool.FOLLOW_PATH_ADAPTATION_ALT = MOHO.MSG_BASE + 25 MR_TransformRigTool.TRANSFORM_BONES = MOHO.MSG_BASE + 26 MR_TransformRigTool.TRANSFORM_VITRUVIAN_BONES = MOHO.MSG_BASE + 27 MR_TransformRigTool.TRANSFORM_TARGET_BONES = MOHO.MSG_BASE + 28 MR_TransformRigTool.TRANSFORM_PATCH_LAYERS = MOHO.MSG_BASE + 29 MR_TransformRigTool.TRANSFORM_IMAGE_LAYERS = MOHO.MSG_BASE + 30 MR_TransformRigTool.TRANSFORM_ORIGIN = MOHO.MSG_BASE + 31 MR_TransformRigTool.SELECT_BONE = MOHO.MSG_BASE + 32 MR_TransformRigTool.TRANSLATE_BONE = MOHO.MSG_BASE + 33 MR_TransformRigTool.ROTATE_BONE = MOHO.MSG_BASE + 34 MR_TransformRigTool.SCALE_BONE = MOHO.MSG_BASE + 35 MR_TransformRigTool.UPDATE_CENTER = MOHO.MSG_BASE + 36 MR_TransformRigTool.UPDATE_CENTER_ALT = MOHO.MSG_BASE + 37 MR_TransformRigTool.REPEAT_TRANSFORMATION = MOHO.MSG_BASE + 38 MR_TransformRigTool.ALT_REPEAT = MOHO.MSG_BASE + 39 function MR_TransformRigTool:DoLayout(moho, layout) local fileWord = MOHO.Localize("/Menus/File/File=File") layout:AddPadding(2) self.dlog = MR_SettingsDialog:new() self.settingsPopup = LM.GUI.PopupDialog(self:Localize('Settings'), false, 0) self.settingsPopup:SetDialog(self.dlog) layout:AddChild(self.settingsPopup, LM.GUI.ALIGN_LEFT, 0) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) self.advancedModeButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_advanced_mode', self:Localize('Advanced Mode'), false, self.ADVANCED_MODE, false) layout:AddChild(self.advancedModeButton, LM.GUI.ALIGN_LEFT, 0) self.fixActionsButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_ok', self:Localize('Finalize'), false, self.FIX_ACTIONS, false) layout:AddChild(self.fixActionsButton, LM.GUI.ALIGN_LEFT, 0) self.clearButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_cancel', self:Localize('Clear'), false, self.CLEAR, false) layout:AddChild(self.clearButton, LM.GUI.ALIGN_LEFT, 0) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) self.centerMenu = LM.GUI.Menu('Center') self.centerMenu:AddItem(self:Localize("Custom Center"), 0, self.CUSTOM_CENTER) self.centerMenu:AddItem(self:Localize("Selected Bone"), 0, self.SELECTED_BONE) if fileWord == "Файл" then self.centerPopup = LM.GUI.PopupMenu(140, true) else self.centerPopup = LM.GUI.PopupMenu(120, true) end self.centerPopup:SetMenu(self.centerMenu) layout:AddChild(self.centerPopup) self.setFromSelectionButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_select_center', self:Localize('Set From Selection'), false, self.SET_FROM_SELECTION, false) self.setFromSelectionButton:SetAlternateMessage(self.SET_FROM_SELECTION_ALT) layout:AddChild(self.setFromSelectionButton, LM.GUI.ALIGN_LEFT, 0) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) layout:AddPadding(3) self.duplicateBodypartButton = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_duplicate_bodypart", self:Localize('Duplicate Bodypart'), false, self.DUPLICATE_BODYPART, false) layout:AddChild(self.duplicateBodypartButton, LM.GUI.ALIGN_LEFT, 0) self.copyBodypartButton = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_copy_to_another_skeleton", self:Localize('Copy Bodypart'), false, self.COPY_BODYPART, false) layout:AddChild(self.copyBodypartButton, LM.GUI.ALIGN_LEFT, 0) self.flipH = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_flip_points_h", self:Localize('Flip Horizontally'), false, self.FLIP_H, false) self.flipH:SetAlternateMessage(self.FLIP_H_ALT) layout:AddChild(self.flipH, LM.GUI.ALIGN_LEFT, 0) self.flipV = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_flip_points_v", self:Localize('Flip Vertically'), false, self.FLIP_V, false) self.flipV:SetAlternateMessage(self.FLIP_V_ALT) layout:AddChild(self.flipV, LM.GUI.ALIGN_LEFT, 0) self.duplicateAndFlipSmarboneButton = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_duplicate_and_flip_smarbone", self:Localize('Duplicate And Flip Smarbone'), false, self.DUPLICATE_AND_FLIP_SMARTBONE, false) self.duplicateAndFlipSmarboneButton:SetAlternateMessage(self.DUPLICATE_AND_FLIP_SMARTBONE_ALT) layout:AddChild(self.duplicateAndFlipSmarboneButton, LM.GUI.ALIGN_LEFT, 0) self.reconnectBonesButton = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_reconnect_bones", self:Localize('Reconnect Bones'), true, self.RECONNECT_BONES, false) self.reconnectBonesButton:SetAlternateMessage(self.RECONNECT_BONES_ALT) layout:AddChild(self.reconnectBonesButton, LM.GUI.ALIGN_LEFT, 0) self.selectAllPointsButton = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_select_all_points", self:Localize('Select All Points'), false, self.SELECT_ALL_POINTS, false) self.selectAllPointsButton:SetAlternateMessage(self.DESELECT_ALL_POINTS) layout:AddChild(self.selectAllPointsButton, LM.GUI.ALIGN_LEFT, 0) self.checkForSplitDimensionsButton = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_split_dimensions", self:Localize('Check For Split Dimensions'), false, self.CHECK_FOR_SPLIT_DIMENSIONS, false) layout:AddChild(self.checkForSplitDimensionsButton, LM.GUI.ALIGN_LEFT, 0) layout:AddPadding(1) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) layout:AddPadding(1) self.ignoreRefCheck = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_ignore_ref', self:Localize('Ignore References'), true, self.IGNORE_REF, false) layout:AddChild(self.ignoreRefCheck, LM.GUI.ALIGN_LEFT, 0) self.transformPointsCheck = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_transform_points', self:Localize('Transform Points'), true, self.TRANSFORM_POINTS, false) layout:AddChild(self.transformPointsCheck, LM.GUI.ALIGN_LEFT, 0) self.autoSelectCheck = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_auto_select_all_points", self:Localize('Auto Select All Points'), true, self.AUTO_SELECT_POINTS, false) layout:AddChild(self.autoSelectCheck, LM.GUI.ALIGN_LEFT, 0) self.adjustStrokeWidthCheck = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_stroke_width", self:Localize("Adjust Stroke Width"), true, self.ADJUST_STROKE_WIDTH, false) layout:AddChild(self.adjustStrokeWidthCheck, LM.GUI.ALIGN_LEFT, 0) self.followPathAdaptationCheck = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_follow_path", self:Localize("Follow Path Rig Adaptation"), true, self.FOLLOW_PATH_ADAPTATION, false) self.followPathAdaptationCheck:SetAlternateMessage(self.FOLLOW_PATH_ADAPTATION_ALT) layout:AddChild(self.followPathAdaptationCheck, LM.GUI.ALIGN_LEFT, 0) self.transformBonesCheck = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_selected_bone', self:Localize('Transform Bones'), true, self.TRANSFORM_BONES, false) layout:AddChild(self.transformBonesCheck, LM.GUI.ALIGN_LEFT, 0) if self.isVitruvianBonesAvaible then self.transformVitruvianBonesButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_vitruvian_bones', self:Localize('Transform Vitruvian Bones'), true, self.TRANSFORM_VITRUVIAN_BONES, false) layout:AddChild(self.transformVitruvianBonesButton, LM.GUI.ALIGN_LEFT, 0) end self.transformTargetBonesButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_target_bones', self:Localize('Transform Target Bones'), true, self.TRANSFORM_TARGET_BONES, false) layout:AddChild(self.transformTargetBonesButton, LM.GUI.ALIGN_LEFT, 0) self.transformPatchLayerCheck = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_transform_patch', self:Localize('Transform Patch Layers'), true, self.TRANSFORM_PATCH_LAYERS, false) layout:AddChild(self.transformPatchLayerCheck, LM.GUI.ALIGN_LEFT, 0) self.transformImageLayersCheck = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_image_layer', self:Localize('Transform Image Layers'), true, self.TRANSFORM_IMAGE_LAYERS, false) layout:AddChild(self.transformImageLayersCheck, LM.GUI.ALIGN_LEFT, 0) self.transformOriginButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_origin', self:Localize('Transform Origins'), true, self.TRANSFORM_ORIGIN, false) layout:AddChild(self.transformOriginButton, LM.GUI.ALIGN_LEFT, 0) layout:AddPadding(1) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) layout:AddPadding(1) self.selectBonesButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_select', self:Localize('Select Bone'), true, self.SELECT_BONE, false) layout:AddChild(self.selectBonesButton, LM.GUI.ALIGN_LEFT, 0) self.translateButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_translate', self:Localize('Translate'), true, self.TRANSLATE_BONE, false) layout:AddChild(self.translateButton, LM.GUI.ALIGN_LEFT, 0) self.rotateButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_rotate', self:Localize('Rotate'), true, self.ROTATE_BONE, false) layout:AddChild(self.rotateButton, LM.GUI.ALIGN_LEFT, 0) self.scaleButton = LM.GUI.ImageButton('ScriptResources/mr_transform_rig_tool/mr_scale', self:Localize('Scale'), true, self.SCALE_BONE, false) layout:AddChild(self.scaleButton, LM.GUI.ALIGN_LEFT, 0) layout:AddPadding(3) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) self.updateCenterButton = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_update_center", self:Localize('Update Center'), false, self.UPDATE_CENTER, false) self.updateCenterButton:SetAlternateMessage(self.UPDATE_CENTER_ALT) layout:AddChild(self.updateCenterButton, LM.GUI.ALIGN_LEFT, 0) self.repeatLastTransformationButton = LM.GUI.ImageButton("ScriptResources/mr_transform_rig_tool/mr_apply_transformation",self:Localize('Repeat Transformation'), false, self.REPEAT_TRANSFORMATION, false) self.repeatLastTransformationButton:SetAlternateMessage(self.ALT_REPEAT) layout:AddChild(self.repeatLastTransformationButton, LM.GUI.ALIGN_LEFT, 0) self.dlog = MR_EditLastTransformDialog:new() self.editLastTransformPopup = LM.GUI.PopupDialog(self:Localize('Edit Last Transform'), false, 0) self.editLastTransformPopup:SetDialog(self.dlog) layout:AddChild(self.editLastTransformPopup, LM.GUI.ALIGN_LEFT, 0) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) layout:AddChild(LM.GUI.StaticText('v'..self:Version())) layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL) self.statusText = LM.GUI.DynamicText(self:Localize('Status:'), 500) layout:AddChild(self.statusText, LM.GUI.ALIGN_LEFT, 0) end function MR_TransformRigTool:HandleMessage(moho, view, msg) if msg == self.ADVANCED_MODE then self:GetBoneTransformation(moho) elseif msg == self.FIX_ACTIONS then self:ApplyBoneTransformation(moho) elseif msg == self.CLEAR then self:Cancel(moho) elseif (msg >= self.CUSTOM_CENTER and msg <= self.SELECTED_BONE) then local center = 0 if (msg == self.CUSTOM_CENTER) then center = 0 elseif (msg == self.SELECTED_BONE) then center = 1 end self.centerId = center self:UpdateWidgets(moho) elseif msg == self.SET_FROM_SELECTION then self:SetFromSelection(moho) elseif msg == self.SET_FROM_SELECTION_ALT then self:SetCenterFromBone(moho) elseif msg == self.DUPLICATE_BODYPART then self:DuplicateBodypart(moho, true) elseif msg == self.COPY_BODYPART then self:CopyBodypart(moho, true) elseif msg == self.FLIP_H then if not AE_Utilities then local ans = LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Missing Utilites'), self:Localize('Missing Utilites Info'), "", 'Ok', '', '', '') return end self:Flip(moho, true, false) elseif msg == self.FLIP_H_ALT then if not AE_Utilities then local ans = LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Missing Utilites'), self:Localize('Missing Utilites Info'), "", 'Ok', '', '', '') return end self:Flip(moho, true, true) elseif msg == self.FLIP_V then if not AE_Utilities then local ans = LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Missing Utilites'), self:Localize('Missing Utilites Info'), "", 'Ok', '', '', '') return end self:Flip(moho, false, false) elseif msg == self.FLIP_V_ALT then if not AE_Utilities then local ans = LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Missing Utilites'), self:Localize('Missing Utilites Info'), "", 'Ok', '', '', '') return end self:Flip(moho, false, true) elseif msg == self.DUPLICATE_AND_FLIP_SMARTBONE then self:DuplicateAndFlipSmarbone(moho) elseif msg == self.DUPLICATE_AND_FLIP_SMARTBONE_ALT then self:DuplicateAndFlipSmarbone(moho) self:FindSkeletonLayer(moho) self:FlipBoneChain(moho, true, false) elseif (msg == self.RECONNECT_BONES) then moho.document:SetDirty() moho.document:PrepUndo(self.skelLayer) self:RelinkBones(moho) self.areBonesUnlinked = false self.reconnectBonesButton:SetValue(self.areBonesUnlinked) elseif (msg == self.RECONNECT_BONES_ALT) then moho.document:SetDirty() moho.document:PrepUndo(self.skelLayer) self:AddBonesToList(moho) self:UnlinkBones(moho) self.areBonesUnlinked = true self.reconnectBonesButton:SetValue(self.areBonesUnlinked) elseif (msg == self.SELECT_ALL_POINTS) then moho.document:PrepUndo(self.skelLayer) moho.document:SetDirty() local autoSelect = self.autoSelect local transformPoints = self.transformPoints self.autoSelect = true self.transformPoints = true self:ScanLayers(moho) self.autoSelect = autoSelect self.transformPoints = transformPoints moho:UpdateUI() elseif (msg == self.DESELECT_ALL_POINTS) then moho.document:PrepUndo(self.skelLayer) moho.document:SetDirty() local autoSelect = self.autoSelect local transformPoints = self.transformPoints self.autoSelect = false self.transformPoints = true self:ScanLayers(moho) for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() if not self.autoSelect then mesh:DeselectPoints() end end self.autoSelect = autoSelect self.transformPoints = transformPoints moho:UpdateUI() elseif msg == self.CHECK_FOR_SPLIT_DIMENSIONS then self:CheckForSplitDimensions(moho) elseif msg == self.IGNORE_REF then self.ignoreRefLayers = self.ignoreRefCheck:Value() elseif msg == self.TRANSFORM_POINTS then self.transformPoints = self.transformPointsCheck:Value() self:UpdateWidgets(moho) elseif msg == self.AUTO_SELECT_POINTS then self.autoSelect = self.autoSelectCheck:Value() self:UpdateWidgets(moho) elseif msg == self.ADJUST_STROKE_WIDTH then self.adjustStrokeWidth = self.adjustStrokeWidthCheck:Value() elseif msg == self.FOLLOW_PATH_ADAPTATION then self.followPathAdaptation = self.followPathAdaptationCheck:Value() elseif msg == self.FOLLOW_PATH_ADAPTATION_ALT then moho.document:PrepUndo() moho.document:SetDirty() moho.layer:SetName(moho.layer:Name()) moho:UpdateUI() elseif msg == self.TRANSFORM_BONES then self.transformBones = self.transformBonesCheck:Value() self:UpdateWidgets(moho) elseif msg == self.TRANSFORM_VITRUVIAN_BONES then self.transformVitruvianBones = self.transformVitruvianBonesButton:Value() elseif msg == self.TRANSFORM_TARGET_BONES then self.transformTargetBones = self.transformTargetBonesButton:Value() elseif msg == self.TRANSFORM_PATCH_LAYERS then self.transformPatchLayers = self.transformPatchLayerCheck:Value() elseif msg == self.TRANSFORM_IMAGE_LAYERS then self.transformImageLayers = self.transformImageLayersCheck:Value() elseif msg == self.TRANSFORM_ORIGIN then self.transformOrigin = self.transformOriginButton:Value() elseif msg == self.SELECT_BONE then self.selectBonesBt = true self.translateBt = false self.scaleBt = false self.rotateBt = false self:UpdateWidgets(moho) elseif msg == self.TRANSLATE_BONE then self.selectBonesBt = false self.translateBt = true self.scaleBt = false self.rotateBt = false self:UpdateWidgets(moho) elseif msg == self.SCALE_BONE then self.selectBonesBt = false self.translateBt = false self.scaleBt = true self.rotateBt = false self:UpdateWidgets(moho) elseif msg == self.ROTATE_BONE then self.selectBonesBt = false self.translateBt = false self.scaleBt = false self.rotateBt = true self:UpdateWidgets(moho) elseif msg == self.UPDATE_CENTER then self:UpdateLastCenter(moho) elseif msg == self.UPDATE_CENTER_ALT then self.centerVec:Set(MR_Utilities:GetGlobalPos(moho, moho.layer, moho.layer:Origin(), false)) self.lastCenter:Set(self.centerVec) elseif msg == self.REPEAT_TRANSFORMATION then self.transformedTargetBonesList = {} if not AE_Utilities then local ans = LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Missing Utilites'), self:Localize('Missing Utilites Info'), "", 'Ok', '', '', '') return end self:ScanLayers(moho) self.skel = self:FindSkeleton(moho) if self.skel == nil then return end local skel = self.skel self.mainSkelSelectedBones = self:CountSelectedBones(moho, skel) if self.transformPoints then self:CollectPointsTempPos(moho) end for m in pairs(self.fixedActionsList) do self.fixedActionsList[m] = nil end if (self.vectorLayersToChange.layer[1] == nil) and self.imageLayersToChange.layer[1] == nil then if self.patchLayersToChange.layer[1] == nil then if (self.transformBones and self.mainSkelSelectedBones ~= 1) or not self.transformBones then self.status = self:Localize('No layers selected for active mode.') self:UpdateWidgets(moho) return end end end if (self.transformBones and self.mainSkelSelectedBones ~= 1) or (self.centerId == 1 and self.mainSkelSelectedBones ~= 1) then self.status = self:Localize('You need to select one bone in this mode.') self:UpdateWidgets(moho) return end local isMarker = self:CheckMarker(moho) if not self:RepeatTransformation(moho, false) then return end if self.transformBones and self.mainSkelSelectedBones == 1 then if self.transformVitruvianBones and moho.frame == 0 and self.isVitruvianBonesAvaible and not isMarker then if self.lastTransformMode == 1 then -- translate self:TranslateVitruvianBones(moho, false) elseif self.lastTransformMode == 2 then -- scale self:ScaleVitruvianBones(moho, false) elseif self.lastTransformMode == 5 then -- rotate self:RotateVitruvianBones(moho, false) end end if self.transformTargetBones and not isMarker then if self.lastTransformMode == 1 then -- translate self:TransformTargetBones(moho, false) elseif self.lastTransformMode == 2 then -- scale self:TransformTargetBones(moho, false) elseif self.lastTransformMode == 5 then -- rotate self:TransformTargetBones(moho, false) end end end local totalActions = #self.fixedActionsList local actionsStr = self:Localize(' actions were updated.') if totalActions == 1 then actionsStr = self:Localize(' action was updated.') end if totalActions > 0 then self.status = totalActions.. actionsStr else self.status = self:Localize('Actions did not need to be updated') end if self.transformPoints then self:RefreshCachedLayers(moho) end moho:NewKeyframe(CHANNEL_POINT) moho:UpdateUI() moho.view:DrawMe() elseif msg == self.ALT_REPEAT then self.transformedTargetBonesList = {} if not AE_Utilities then local ans = LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Missing Utilites'), self:Localize('Missing Utilites Info'), "", 'Ok', '', '', '') return end self:ScanLayers(moho) self.skel = self:FindSkeleton(moho) if self.skel == nil then return end local skel = self.skel self.mainSkelSelectedBones = self:CountSelectedBones(moho, skel) if self.transformPoints then self:CollectPointsTempPos(moho) end for m in pairs(self.fixedActionsList) do self.fixedActionsList[m] = nil end if (self.vectorLayersToChange.layer[1] == nil) and self.imageLayersToChange.layer[1] == nil then if self.patchLayersToChange.layer[1] == nil then if (self.transformBones and self.mainSkelSelectedBones ~= 1) or not self.transformBones then self.status = self:Localize('No layers selected for active mode.') self:UpdateWidgets(moho) return end end end if (self.transformBones and self.mainSkelSelectedBones ~= 1) or (self.centerId == 1 and self.mainSkelSelectedBones ~= 1) then self.status = self:Localize('You need to select one bone in this mode.') self:UpdateWidgets(moho) return end local isMarker = self:CheckMarker(moho) if not self:RepeatTransformation(moho, true) then return end if self.transformBones and self.mainSkelSelectedBones == 1 then if self.transformVitruvianBones and moho.frame == 0 and self.isVitruvianBonesAvaible and not isMarker then if self.lastTransformMode == 1 then -- translate self:TranslateVitruvianBones(moho, true) elseif self.lastTransformMode == 2 then -- scale self:ScaleVitruvianBones(moho, true) elseif self.lastTransformMode == 5 then -- rotate self:RotateVitruvianBones(moho, true) end end if self.transformTargetBones and not isMarker then if self.lastTransformMode == 1 then -- translate self:TransformTargetBones(moho, true) elseif self.lastTransformMode == 2 then -- scale self:TransformTargetBones(moho, true) elseif self.lastTransformMode == 5 then -- rotate self:TransformTargetBones(moho, true) end end end local totalActions = #self.fixedActionsList local actionsStr = self:Localize(' actions were updated.') if totalActions == 1 then actionsStr = self:Localize(' action was updated.') end if totalActions > 0 then self.status = totalActions.. actionsStr else self.status = self:Localize('Actions did not need to be updated') end if self.transformPoints then self:RefreshCachedLayers(moho) end moho:NewKeyframe(CHANNEL_POINT) moho:UpdateUI() moho.view:DrawMe() end end function MR_TransformRigTool:UpdateWidgets(moho) if self.mainCursor == nil then self.mainCursor = LM.GUI.Cursor("ScriptResources/mr_transform_rig_tool/mr_cursor", 1, 1) end local skel = self:FindSkeleton(moho) self:FindSkeletonLayer(moho) self.skel = skel local isMarker = self:CheckMarker(moho) local curLayerId = moho.layer:UUID() if self.boneLayerId ~= curLayerId or not isMarker then self.fixActionsButton:Enable(false) else self.fixActionsButton:Enable(true) end if moho.frame ~= 0 then self.advancedModeButton:Enable(false) else self.advancedModeButton:Enable(true) end if isMarker then self.clearButton:Enable(true) self.advancedModeButton:Enable(false) self.scaleButton:Enable(false) self.checkForSplitDimensionsButton:Enable(false) if self.scaleBt then self.scaleBt = false self.selectBonesBt = true end else self.clearButton:Enable(false) self.scaleButton:Enable(true) end if moho.layer:LayerType() ~= MOHO.LT_BONE or moho.document:CurrentDocAction() ~= "" then self.advancedModeButton:Enable(false) self.fixActionsButton:Enable(false) end if self.centerId == 0 then self.centerMenu:SetChecked(self.CUSTOM_CENTER, true) self.centerMenu:SetChecked(self.SELECTED_BONE, false) elseif (self.centerId == 1) then self.centerMenu:SetChecked(self.CUSTOM_CENTER, false) self.centerMenu:SetChecked(self.SELECTED_BONE, true) end self.centerPopup:Redraw() self.reconnectBonesButton:SetValue(self.areBonesUnlinked) self.ignoreRefCheck:SetValue(self.ignoreRefLayers) self.transformPointsCheck:SetValue(self.transformPoints) self.autoSelectCheck:SetValue(self.autoSelect) self.autoSelectCheck:Enable(self.transformPoints) self.adjustStrokeWidthCheck:SetValue(self.adjustStrokeWidth) self.adjustStrokeWidthCheck:Enable(self.transformPoints) self.followPathAdaptationCheck:SetValue(self.followPathAdaptation) self.followPathAdaptationCheck:Enable(self.transformPoints) self.transformBonesCheck:SetValue(self.transformBones) self.transformBonesCheck:Enable(true) if self.isVitruvianBonesAvaible then self.transformVitruvianBonesButton:SetValue(self.transformVitruvianBones) self.transformVitruvianBonesButton:Enable(self.transformBones and not isMarker) end self.transformTargetBonesButton:SetValue(self.transformTargetBones) self.transformTargetBonesButton:Enable(self.transformBones and not isMarker) self.transformPatchLayerCheck:SetValue(self.transformPatchLayers) self.transformImageLayersCheck:SetValue(self.transformImageLayers) self.transformOriginButton:SetValue(self.transformOrigin) self.selectBonesButton:SetValue(self.selectBonesBt) self.translateButton:SetValue(self.translateBt) self.scaleButton:SetValue(self.scaleBt) self.rotateButton:SetValue(self.rotateBt) if self.isSkel and moho.frame == 0 then if (self.selectBonesBt) then moho.view:SetCursor(self.mainCursor) self.editLastTransformPopup:Enable(false) elseif (self.translateBt) then moho.view:SetCursor(MOHO.moveCursor) self.editLastTransformPopup:Enable(true) elseif (self.scaleBt) then moho.view:SetCursor(MOHO.scaleCursor) self.editLastTransformPopup:Enable(true) elseif (self.rotateBt) then moho.view:SetCursor(MOHO.rotateCursor) self.editLastTransformPopup:Enable(true) end else moho.view:SetCursor(MOHO.disabledCursor) self.editLastTransformPopup:Enable(false) end if moho.frame ~= 0 then moho.view:SetCursor(MOHO.disabledCursor) end if self.lastTransformMode == 0 then self.repeatLastTransformationButton:Enable(false) elseif self.lastTransformMode == 1 and self.translateBt then self.repeatLastTransformationButton:SetToolTip(self:Localize('Repeat Translate')) self.updateCenterButton:Enable(true) self.repeatLastTransformationButton:Enable(true) elseif self.lastTransformMode == 2 and self.scaleBt then self.repeatLastTransformationButton:SetToolTip(self:Localize('Repeat Scale')) self.updateCenterButton:Enable(true) self.repeatLastTransformationButton:Enable(true) elseif self.lastTransformMode >= 3 and self.lastTransformMode <= 4 and self.scaleBt then self.repeatLastTransformationButton:SetToolTip(self:Localize('Repeat Scale')) self.updateCenterButton:Enable(true) self.repeatLastTransformationButton:Enable(true) elseif self.lastTransformMode == 5 and self.rotateBt then self.repeatLastTransformationButton:SetToolTip(self:Localize('Repeat Rotate')) self.updateCenterButton:Enable(true) self.repeatLastTransformationButton:Enable(true) else self.repeatLastTransformationButton:Enable(false) end if moho.frame == 0 and moho.layer:CurrentAction() == '' then self.duplicateBodypartButton:Enable(not isMarker) self.copyBodypartButton:Enable(not isMarker) self.flipH:Enable(not isMarker) self.flipV:Enable(not isMarker) self.duplicateAndFlipSmarboneButton:Enable(not isMarker) self.selectAllPointsButton:Enable(not isMarker) self.editLastTransformPopup:Enable(not self.selectBonesBt) if self.centerId == 0 then self.setFromSelectionButton:Enable(true) else self.setFromSelectionButton:Enable(false) end else self.centerPopup:Enable(false) self.setFromSelectionButton:Enable(false) self.duplicateBodypartButton:Enable(false) self.copyBodypartButton:Enable(false) self.flipH:Enable(false) self.flipV:Enable(false) self.duplicateAndFlipSmarboneButton:Enable(false) self.reconnectBonesButton:Enable(false) self.selectAllPointsButton:Enable(false) self.checkForSplitDimensionsButton:Enable(false) self.selectBonesButton:Enable(false) self.translateButton:Enable(false) self.rotateButton:Enable(false) self.scaleButton:Enable(false) self.updateCenterButton:Enable(false) self.repeatLastTransformationButton:Enable(false) self.editLastTransformPopup:Enable(false) end self.statusText:SetValue(self.status) end function MR_TransformRigTool:Cancel(moho) moho.document:PrepUndo(moho.layer) moho.document:SetDirty() local markerChannels = moho.layer.fTimelineMarkers local framesToDel = {} local isNeedUpdate = false if markerChannels:Duration() > 0 then for i=1, markerChannels:CountKeys()-1 do local markerTime = markerChannels:GetKeyWhen(i) local markerText = markerChannels:GetValue(markerTime) if markerText == 'Do not delete or edit!' then self.refKey = markerTime table.insert(framesToDel, markerTime) isNeedUpdate = true end end for y in pairs(framesToDel) do markerChannels:DeleteKey(framesToDel[y]) self:ClearFrame(moho, framesToDel[y]) if framesToDel[y] > 1 then self:ClearFrame(moho, framesToDel[y]-1) end end self.status = self:Localize('Collected data cleared.') self:UpdateWidgets(moho) if isNeedUpdate then self:HardUpdate(moho) end end end function MR_TransformRigTool:CheckMarker(moho) local found = false local markerChannels if self.skelLayer then markerChannels = self.skelLayer.fTimelineMarkers else markerChannels = moho.layer.fTimelineMarkers end if markerChannels:Duration() > 0 then for i=1, markerChannels:CountKeys()-1 do local markerTime = markerChannels:GetKeyWhen(i) local markerText = markerChannels:GetValue(markerTime) if markerText == 'Do not delete or edit!' then found = true break end end end return found end function MR_TransformRigTool:FindLastKey(moho) local lastKey = 0 local skel = moho:Skeleton() for i=0, skel:CountBones()-1 do local myBone = skel:Bone(i) local channelAngle = myBone.fAnimAngle local channelPos = myBone.fAnimPos local channelScale = myBone.fAnimScale if channelAngle:Duration() > lastKey then lastKey = channelAngle:Duration() end if channelPos:Duration() > lastKey then lastKey = channelPos:Duration() end if channelScale:Duration() > lastKey then lastKey = channelScale:Duration() end end return lastKey end function MR_TransformRigTool:RejoinDimensionsInSelectedBones(moho) local skel = moho:Skeleton() local isAllowRejoin = false local isSuccessful = true local isIgnoreMainLine = false for i=0, skel:CountBones()-1 do local myBone = skel:Bone(i) if myBone.fSelected then for act=0, myBone.fAnimPos:CountActions()-1 do local actName = myBone.fAnimPos:ActionName(act) local isSmartBone = moho.layer:IsSmartBoneAction(actName) if isSmartBone then local actionChannel = moho:ChannelAsAnimVec2(myBone.fAnimPos:Action(act)) if actionChannel then if actionChannel:AreDimensionsSplit() then if not isAllowRejoin then local ans = LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Channels with separated dimensions were found.'), self:Localize('You can Rejoin Dimensions to continue or cancel operation.'), "", self:Localize('Rejoin Dimensions'), self:Localize('Cancel'),"") if ans == 0 then isAllowRejoin = true elseif ans == 1 then isSuccessful = false return isSuccessful end end if isAllowRejoin then actionChannel:SplitDimensions(false) end end end end end end end return isSuccessful end function MR_TransformRigTool:GetBoneTransformation(moho) for k in pairs(self.boneList) do self.boneList[k] = nil self.boneOrigPosList[k] = nil self.boneOrigGlobalPosList[k] = nil self.boneAngleList[k] = nil self.boneAngleExtraList[k] = nil self.boneAngleOffsetList[k] = nil self.boneParentAngleList[k] = nil self.boneParentList[k] = nil self.boneParentMatrixList[k] = nil end for k in pairs(self.boneRefList) do self.boneRefList[k] = nil end local skel = moho:Skeleton() self.totalBones = 0 local bonesFound = moho:CountSelectedBones(true) if bonesFound > 0 then moho.document:PrepUndo(moho.layer) moho.document:SetDirty() local curLayerId = moho.layer:UUID() if self.boneLayerId ~= curLayerId then self.refKey = 1 end local markerChannels = moho.layer.fTimelineMarkers local framesToDel = {} local isNeedUpdate = false if markerChannels:Duration() > 0 then for i=1, markerChannels:CountKeys()-1 do local markerTime = markerChannels:GetKeyWhen(i) local markerText = markerChannels:GetValue(markerTime) if markerText == 'Do not delete or edit!' then self.refKey = markerTime table.insert(framesToDel, markerTime) isNeedUpdate = true end end for y in pairs(framesToDel) do markerChannels:DeleteKey(framesToDel[y]) self:ClearFrame(moho, framesToDel[y]) if framesToDel[y] > 1 then self:ClearFrame(moho, framesToDel[y]-1) end end if isNeedUpdate then self:HardUpdate(moho) end end local lastFrame = self:FindLastKey(moho) if lastFrame >= 1 then self.refKey = lastFrame + 2 else self.refKey = 1 end for i=0, skel:CountBones()-1 do table.insert(self.boneRefList,i) end if self.refKey > 1 then self:SetKey(moho, self.refKey -1, self.refKey -1) end self:SetKey(moho, self.refKey, 0) local keyInterp = MOHO.InterpSetting:new_local() keyInterp.tags = 1 moho.layer.fTimelineMarkers:SetValue(self.refKey,'Do not delete or edit!') moho.layer.fTimelineMarkers:SetKeyInterp(self.refKey, keyInterp) end local isSuccessful = self:RejoinDimensionsInSelectedBones(moho) if not isSuccessful then self.status = self:Localize('Canceled.') self:UpdateWidgets(moho) self:ClearFrame(moho, self.refKey) if self.refKey > 1 then self:ClearFrame(moho, self.refKey-1) end self:HardUpdate(moho) return end for i=0, skel:CountBones()-1 do local myBone = skel:Bone(i) self.totalBones = self.totalBones + 1 if myBone.fSelected then table.insert(self.boneList, i) local parentBone = skel:Bone(myBone.fParent) if myBone.fParent >= 0 then local parentMatrix = LM.Matrix:new_local() parentMatrix:Set(parentBone.fRestMatrix) table.insert(self.boneParentList, myBone.fParent) table.insert(self.boneParentMatrixList, parentMatrix) else local emtyMatrix = LM.Matrix:new_local() emtyMatrix:Identity() table.insert(self.boneParentMatrixList, emtyMatrix) table.insert(self.boneParentList, -1) end local bonePos = LM.Vector2:new_local() bonePos = myBone.fAnimPos:GetValue(0) local boneAngle = myBone.fAnimAngle:GetValue(0) local boneAngleExtra = myBone.fAnimAngle:GetValue(self.refKey) table.insert(self.boneOrigPosList, myBone.fAnimPos:GetValue(0)) local boneParentAngle = 0 if myBone.fParent >= 0 then boneParentAngle = parentBone.fAnimAngle:GetValue(0) parentBone.fRestMatrix:Transform(bonePos) end table.insert(self.boneOrigGlobalPosList, bonePos) table.insert(self.boneAngleList, boneAngle) table.insert(self.boneAngleExtraList, boneAngleExtra) table.insert(self.boneParentAngleList, boneParentAngle) end end local layerName = moho.layer:Name() if bonesFound > 0 then self.boneLayerId = moho.layer:UUID() if bonesFound == 1 then self.status = self:Localize('Original transformation collected for 1 bone on layer ') .. layerName..'.' else self.status = self:Localize('Original transformation collected for ') .. bonesFound.. self:Localize(' bones on layer ') .. layerName..'.' end else self.boneLayerId = nil self.status = self:Localize('No bones was selected. Please select bones first.') end moho.view:DrawMe() moho:UpdateUI() moho.layer:UpdateCurFrame() self:UpdateWidgets(moho) end function MR_TransformRigTool:ApplyBoneTransformation(moho) self:UpdateWidgets(moho) for q in pairs(self.fixedBonesList) do self.fixedBonesList[q] = nil end for m in pairs(self.fixedActionsList) do self.fixedActionsList[m] = nil end self.fixedBones = 0 self.fixedActions = 0 local curFrame = moho.frame local skel = moho:Skeleton() if (skel == nil) then return elseif (self.boneList[1] == nil) then return end for b in pairs(self.boneList) do local bone = skel:Bone(self.boneList[b]) if bone == nil then self.status = self:Localize('Correction was canceled.') self:UpdateWidgets(moho) moho.document:PrepUndo(moho.layer) moho.document:SetDirty() self:ClearFrame(moho, self.refKey) if self.refKey > 1 then self:ClearFrame(moho, self.refKey-1) end local markerChannels = moho.layer.fTimelineMarkers markerChannels:DeleteKey(self.refKey) self:HardUpdate(moho) return LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Some bones are missing. The skeleton structure was changed.'), "", "", self:Localize('EXIT')) end end local totalCurBones = 0 for i=0, skel:CountBones()-1 do totalCurBones = totalCurBones + 1 local myBone = skel:Bone(i) local channelAngle = myBone.fAnimAngle local channelPos = myBone.fAnimPos local channelScale = myBone.fAnimScale local isRefKeysOk = true local isPosChannelSplit = channelPos:AreDimensionsSplit() if isPosChannelSplit then local subChannel1 = channelPos:DimensionChannel(0) local subChannel2 = channelPos:DimensionChannel(1) if not subChannel1:HasKey(self.refKey) or not subChannel2:HasKey(self.refKey) then isRefKeysOk = false end elseif not channelPos:HasKey(self.refKey) then isRefKeysOk = false end if not channelAngle:HasKey(self.refKey) or not channelScale:HasKey(self.refKey) then isRefKeysOk = false end if not isRefKeysOk and self.boneRefList[i + 1] ~= nil then self.status = self:Localize('Correction was canceled.') self:UpdateWidgets(moho) moho.document:PrepUndo(moho.layer) moho.document:SetDirty() self:ClearFrame(moho, self.refKey) if self.refKey > 1 then self:ClearFrame(moho, self.refKey-1) end local markerChannels = moho.layer.fTimelineMarkers markerChannels:DeleteKey(self.refKey) self:HardUpdate(moho) return LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Some reference keys are missing. Please do not remove or edit any reference keys.'), "", "", self:Localize('EXIT')) end end if totalCurBones < self.totalBones then self.status = self:Localize('Correction was canceled.') self:UpdateWidgets(moho) moho.document:PrepUndo(moho.layer) moho.document:SetDirty() self:ClearFrame(moho, self.refKey) if self.refKey > 1 then self:ClearFrame(moho, self.refKey-1) end local markerChannels = moho.layer.fTimelineMarkers markerChannels:DeleteKey(self.refKey) self:HardUpdate(moho) return LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('The original number of bones is different.'), "", "", self:Localize('EXIT')) end local isChanges = false for r in pairs(self.boneList) do local myBone = skel:Bone(self.boneList[r]) local extraBoneAngle = self.boneAngleExtraList[r] local extraBoneAngleTmp = myBone.fAnimAngle:GetValue(self.refKey) if myBone.fParent > -1 then local origParentMatrix = LM.Matrix:new_local() origParentMatrix:Set(self.boneParentMatrixList[r]) extraBoneAngle = self:GetGlobalBoneAngle(moho, origParentMatrix, extraBoneAngle, 0, false) extraBoneAngleTmp = self:GetGlobalBoneAngle(moho, origParentMatrix, extraBoneAngleTmp, self.refKey, false) end local reparentOffset = extraBoneAngle - extraBoneAngleTmp table.insert(self.boneAngleOffsetList, reparentOffset) end repeat isChanges = false for y in pairs(self.boneList) do local myBone = skel:Bone(self.boneList[y]) if myBone.fParent > -1 then local newParentId = myBone.fParent for t in pairs(self.boneList) do if newParentId == self.boneList[t] then if y < t then isChanges = true local key2 = self.boneList[t] self.boneList[y], self.boneList[t] = MR_Utilities:SwapTwoArrayKeys(self.boneList, y, t) self.boneOrigPosList[y], self.boneOrigPosList[t] = MR_Utilities:SwapTwoArrayKeys(self.boneOrigPosList, y, t) self.boneOrigGlobalPosList[y], self.boneOrigGlobalPosList[t] = MR_Utilities:SwapTwoArrayKeys(self.boneOrigGlobalPosList, y, t) self.boneAngleList[y], self.boneAngleList[t] = MR_Utilities:SwapTwoArrayKeys(self.boneAngleList, y, t) self.boneAngleExtraList[y], self.boneAngleExtraList[t] = MR_Utilities:SwapTwoArrayKeys(self.boneAngleExtraList, y, t) self.boneAngleOffsetList[y], self.boneAngleOffsetList[t] = MR_Utilities:SwapTwoArrayKeys(self.boneAngleOffsetList, y, t) self.boneParentAngleList[y], self.boneParentAngleList[t] = MR_Utilities:SwapTwoArrayKeys(self.boneParentAngleList, y, t) self.boneParentList[y], self.boneParentList[t] = MR_Utilities:SwapTwoArrayKeys(self.boneParentList, y, t) self.boneParentMatrixList[y], self.boneParentMatrixList[t] = MR_Utilities:SwapTwoArrayKeys(self.boneParentMatrixList, y, t) break end else local nextBone = skel:Bone(newParentId) repeat local prevBone = nextBone for g in pairs(self.boneList) do if prevBone.fParent == self.boneList[g] then if y < g then isChanges = true local key2 = self.boneList[g] self.boneList[y], self.boneList[g] = MR_Utilities:SwapTwoArrayKeys(self.boneList, y, g) self.boneOrigPosList[y], self.boneOrigPosList[g] = MR_Utilities:SwapTwoArrayKeys(self.boneOrigPosList, y, g) self.boneOrigGlobalPosList[y], self.boneOrigGlobalPosList[g] = MR_Utilities:SwapTwoArrayKeys(self.boneOrigGlobalPosList, y, g) self.boneAngleList[y], self.boneAngleList[g] = MR_Utilities:SwapTwoArrayKeys(self.boneAngleList, y, g) self.boneAngleExtraList[y], self.boneAngleExtraList[g] = MR_Utilities:SwapTwoArrayKeys(self.boneAngleExtraList, y, g) self.boneAngleOffsetList[y], self.boneAngleOffsetList[g] = MR_Utilities:SwapTwoArrayKeys(self.boneAngleOffsetList, y, g) self.boneParentAngleList[y], self.boneParentAngleList[g] = MR_Utilities:SwapTwoArrayKeys(self.boneParentAngleList, y, g) self.boneParentList[y], self.boneParentList[g] = MR_Utilities:SwapTwoArrayKeys(self.boneParentList, y, g) self.boneParentMatrixList[y], self.boneParentMatrixList[g] = MR_Utilities:SwapTwoArrayKeys(self.boneParentMatrixList, y, g) end end end if nextBone.fParent > -1 then nextBone = skel:Bone(nextBone.fParent) end until nextBone == prevBone end end end end until isChanges == false moho.document:PrepUndo(moho.layer) moho.document:SetDirty() for i in pairs(self.boneList) do local myBone = skel:Bone(self.boneList[i]) for act=0, moho.layer:CountActions()-1 do local actName = moho.layer:ActionName(act) local actionChannel = myBone.fAnimAngle:ActionByName(actName) local found = false local isSmartBone = moho.layer:IsSmartBoneAction(actName) if actionChannel and actionChannel:Duration()>0 and isSmartBone then self:ScanAction(moho, skel, myBone, actName, i) found = true end if found == false and isSmartBone then actionChannel = myBone.fAnimPos:ActionByName(actName) if actionChannel and actionChannel:Duration()>0 then self:ScanAction(moho, skel, myBone, actName, i) found = true end end if found == true then self.fixedActions = self.fixedActions + 1 end end end moho.layer:ActivateAction(nil) self:ClearFrame(moho, self.refKey) local markerChannels = moho.layer.fTimelineMarkers markerChannels:DeleteKey(self.refKey) if self.refKey > 1 then self:ClearFrame(moho, self.refKey-1) end local totalBones = #self.fixedBonesList local totalActions = #self.fixedActionsList local actionsStr = self:Localize(' actions.') local bonesStr = self:Localize(' bones were') if totalBones == 1 then bonesStr = self:Localize(' bone was') end if totalActions == 1 then actionsStr = self:Localize(' action.') end self.status = self:Localize('Correction completed! ')..totalBones.. bonesStr..self:Localize(' fixed in ').. totalActions.. actionsStr if totalBones == 0 or totalActions == 0 then self.status = self:Localize('Could not find any actions that need to be fixed.') end self:UpdateWidgets(moho) moho:SetCurFrame(curFrame) self:HardUpdate(moho) end function MR_TransformRigTool:HardUpdate(moho) moho:SetCurFrame(1) moho:SetCurFrame(0) moho:UpdateSelectedChannels() moho:UpdateUI() moho.layer:UpdateCurFrame() end function MR_TransformRigTool:ClearFrame(moho, frame) local skel = moho:Skeleton() for i=0, skel:CountBones()-1 do local myBone = skel:Bone(i) myBone.fAnimPos:DeleteKey(frame) myBone.fAnimAngle:DeleteKey(frame) myBone.fAnimScale:DeleteKey(frame) end end function MR_TransformRigTool:SetKey(moho, frame, valueFromFrame) local keyInterp = MOHO.InterpSetting:new_local() keyInterp.tags = 1 local skel = moho:Skeleton() for i=0, skel:CountBones()-1 do local myBone = skel:Bone(i) local channelPos = myBone.fAnimPos local pos = channelPos:GetValue(valueFromFrame) local angle = myBone.fAnimAngle:GetValue(valueFromFrame) local scale = myBone.fAnimScale:GetValue(valueFromFrame) local isPosChannelSplit = channelPos:AreDimensionsSplit() if isPosChannelSplit then local subChannel1 = channelPos:DimensionChannel(0) local subChannel2 = channelPos:DimensionChannel(1) if subChannel1 then subChannel1:SetValue(frame, pos.x) subChannel1:SetKeyInterp(frame, keyInterp) end if subChannel2 then subChannel2:SetValue(frame, pos.y) subChannel2:SetKeyInterp(frame, keyInterp) end else myBone.fAnimPos:SetValue(frame, pos) myBone.fAnimPos:SetKeyInterp(frame, keyInterp) end myBone.fAnimAngle:SetValue(frame, angle) myBone.fAnimAngle:SetKeyInterp(frame, keyInterp) if valueFromFrame == 0 then myBone.fAnimScale:SetValue(frame, 1) myBone.fAnimScale:SetKeyInterp(frame, keyInterp) else myBone.fAnimScale:SetValue(frame, scale) myBone.fAnimScale:SetKeyInterp(frame, keyInterp) end end end function MR_TransformRigTool:ScanAction(moho, skel, bone, actionName, boneNum) moho.layer:ActivateAction(actionName) local actionChannelPos = bone.fAnimPos:ActionByName(actionName) local actionChannelAngle = bone.fAnimAngle:ActionByName(actionName) for i=1, actionChannelPos:CountKeys()-1 do local keyTime = actionChannelPos:GetKeyWhen(i) if keyTime > 0 then self:ApplyPosition(moho, skel, bone, keyTime, boneNum, actionName) end end for i=1, actionChannelAngle:CountKeys()-1 do local keyTime = actionChannelAngle:GetKeyWhen(i) if keyTime > 0 then self:ApplyAngle(moho, skel, bone, keyTime, boneNum, actionName) end end end function MR_TransformRigTool:ApplyPosition(moho, skel, bone, frame, boneNum, actionName) moho:SetCurFrame(frame) local myBone = bone local parentBone = myBone.fParent local oldParentBone = self.boneParentList[boneNum] local localOrigBonePos = LM.Vector2:new_local() localOrigBonePos:Set(self.boneOrigPosList[boneNum]) local origBoneGlobalPos = LM.Vector2:new_local() origBoneGlobalPos:Set(self.boneOrigGlobalPosList[boneNum]) local bonePosFrameZero = LM.Vector2:new_local() local oldMatrix = LM.Matrix:new_local() oldMatrix:Set(self.boneParentMatrixList[boneNum]) local parent = skel:Bone(parentBone) local parentOffset = LM.Vector2:new_local() local parentOffsetZero = LM.Vector2:new_local() parentOffset:Set(0,0) parentOffsetZero:Set(0,0) if parent ~= nil then parent.fMovedMatrix:Transform(parentOffset) parent.fRestMatrix:Transform(parentOffsetZero) end parentOffset = parentOffsetZero - parentOffset bonePosFrameZero:Set(myBone.fAnimPos:GetValue(0)) local oldParent = skel:Bone(oldParentBone) if parent ~= nil then parent.fRestMatrix:Transform(bonePosFrameZero) end local bonePos = LM.Vector2:new_local() bonePos:Set(myBone.fAnimPos:GetValue(frame)) local bonePosDifFrameZero = LM.Vector2:new_local() bonePosDifFrameZero = origBoneGlobalPos - bonePosFrameZero local localBonePosFrameZero = LM.Vector2:new_local() localBonePosFrameZero:Set(myBone.fAnimPos:GetValue(0)) oldMatrix:Transform(bonePos) bonePos = bonePos - bonePosDifFrameZero - parentOffset if parent ~= nil then local inverseM = LM.Matrix:new_local() inverseM:Set(parent.fMovedMatrix) inverseM:Invert() inverseM:Transform(bonePos) end if localOrigBonePos.x ~= localBonePosFrameZero.x or localOrigBonePos.y ~= localBonePosFrameZero.y or oldParentBone ~= parentBone then myBone.fAnimPos:SetValue(frame, bonePos) self:CollectLog(myBone:Name(), actionName) end end function MR_TransformRigTool:CollectLog(boneName, actionName) local isBoneNew = true local isActionNew = true if boneName ~= nil then for z in pairs(self.fixedBonesList) do if self.fixedBonesList[z] == boneName then isBoneNew = false break end end if isBoneNew then table.insert(self.fixedBonesList, boneName) end end if actionName ~= '' and actionName ~= nil then for a in pairs(self.fixedActionsList) do if self.fixedActionsList[a] == actionName then isActionNew = false break end end if isActionNew then table.insert(self.fixedActionsList, actionName) end end end function MR_TransformRigTool:GetGlobalBoneAngle(moho, matrix, boneAngle, frame, round) local v1 = LM.Vector2:new_local() local v2 = LM.Vector2:new_local() v1:Set(0,0) v2:Set(1,0) local newAngle = 0 local invMatrix = LM.Matrix:new_local() invMatrix:Set(matrix) invMatrix:Invert() invMatrix:Transform(v1) invMatrix:Transform(v2) v2 = v2-v1 newAngle = math.atan2(v2.y, v2.x) if round == true then while newAngle > 2 * math.pi do newAngle = newAngle - 2 * math.pi end while newAngle < - 2 * math.pi do newAngle = newAngle + 2 * math.pi end end newAngle = boneAngle - newAngle return newAngle end function MR_TransformRigTool:ApplyAngle(moho, skel, bone, frame, boneNum, actionName) moho:SetCurFrame(frame) local myBone = bone local oldBoneAngle = self.boneAngleList[boneNum] local newBoneAngle = myBone.fAnimAngle:GetValue(frame) local newBoneAngleFrameZero = myBone.fAnimAngle:GetValue(0) local newParentBoneId = myBone.fParent local oldParentBoneId = self.boneParentList[boneNum] local boneAngleDifFrameZero = 0 local parentAngleOffset = 0 local oldParentAngleOffset = 0 if oldBoneAngle ~= newBoneAngleFrameZero and oldParentBoneId == newParentBoneId then local oldParentBone = skel:Bone(oldParentBoneId) boneAngleDifFrameZero = oldBoneAngle - newBoneAngleFrameZero newBoneAngle = (newBoneAngle - boneAngleDifFrameZero) + self.boneAngleOffsetList[boneNum] self:CollectLog(myBone:Name(), actionName) elseif oldBoneAngle ~= newBoneAngleFrameZero and oldParentBoneId ~= newParentBoneId and oldParentBoneId >= 0 then local oldParentBone = skel:Bone(oldParentBoneId) local oldMatrix = LM.Matrix:new_local() oldMatrix = oldParentBone.fMovedMatrix if newParentBoneId > -1 then local parentBone = skel:Bone(newParentBoneId) if self.considerNewParentRotation then local parentAngleZero = parentBone.fAnimAngle:GetValue(0) local parentAngle = parentBone.fAnimAngle:GetValue(frame) if parentBone.fParent > -1 then local grandPaBone = skel:Bone(parentBone.fParent) parentAngleZero = self:GetGlobalBoneAngle(moho, grandPaBone.fRestMatrix, parentAngleZero, 0, false) parentAngle = self:GetGlobalBoneAngle(moho, grandPaBone.fMovedMatrix, parentAngle, frame, false) end parentAngleOffset = parentAngleZero - parentAngle end end oldBoneAngle = oldBoneAngle - self.boneAngleOffsetList[boneNum] if oldParentBoneId > -1 then local oldParentBone = skel:Bone(oldParentBoneId) if self.considerOldParentRotation then local oldParentAngleZero = oldParentBone.fAnimAngle:GetValue(0) local oldParentAngle = oldParentBone.fAnimAngle:GetValue(frame) if oldParentBone.fParent > -1 then local oldGandPaBone = skel:Bone(oldParentBone.fParent) oldParentAngleZero = self:GetGlobalBoneAngle(moho, oldGandPaBone.fRestMatrix, oldParentAngleZero, 0, false) oldParentAngle = self:GetGlobalBoneAngle(moho, oldGandPaBone.fMovedMatrix, oldParentAngle, frame, false) end oldParentAngleOffset = oldParentAngleZero - oldParentAngle end end boneAngleDifFrameZero = oldBoneAngle - newBoneAngleFrameZero newBoneAngle = (newBoneAngle - boneAngleDifFrameZero) + parentAngleOffset - oldParentAngleOffset self:CollectLog(myBone:Name(), actionName) elseif newParentBoneId > -1 and oldParentBoneId < 0 then local parentBone = skel:Bone(newParentBoneId) local newMatrix = LM.Matrix:new_local() newMatrix = parentBone.fMovedMatrix if self.considerNewParentRotation then local parentAngleZero = parentBone.fAnimAngle:GetValue(0) local parentAngle = parentBone.fAnimAngle:GetValue(frame) if parentBone.fParent > -1 then local grandPaBone = skel:Bone(parentBone.fParent) parentAngleZero = self:GetGlobalBoneAngle(moho, grandPaBone.fRestMatrix, parentAngleZero, 0, false) parentAngle = self:GetGlobalBoneAngle(moho, grandPaBone.fMovedMatrix, parentAngle, frame, false) end parentAngleOffset = parentAngleZero - parentAngle end newBoneAngleFrameZero = newBoneAngleFrameZero + self.boneAngleOffsetList[boneNum] boneAngleDifFrameZero = oldBoneAngle - newBoneAngleFrameZero newBoneAngle = (newBoneAngle - boneAngleDifFrameZero) + parentAngleOffset self:CollectLog(myBone:Name(), actionName) end myBone.fAnimAngle:SetValue(frame,newBoneAngle) end function MR_TransformRigTool:DrawMe(moho, view) if not self.isSkel or moho.frame ~= 0 then return end local g = view:Graphics() local min = LM.Vector2:new_local() local max = LM.Vector2:new_local() local matrix = LM.Matrix:new_local() local centerVec = LM.Vector2:new_local() local v = LM.Vector2:new_local() local vc1 = LM.ColorVector:new_local() local vc2 = LM.ColorVector:new_local() local vc3 = LM.ColorVector:new_local() vc1:Set(MOHO.MohoGlobals.SelCol) local blackColorRGB = LM.rgb_color:new_local() blackColorRGB.r = 0 blackColorRGB.g = 0 blackColorRGB.b = 0 blackColorRGB.a = 255 vc2:Set(MOHO.MohoGlobals.BackCol) vc3:Set(blackColorRGB) local selCol = vc1:AsColorStruct() vc1 = (vc1 + vc2) / 2 local col = vc1:AsColorStruct() local blackCol = vc3:AsColorStruct() local cursorOffset1 = LM.Vector2:new_local() cursorOffset1:Set(0.08,0.02) moho.document:GetCameraMatrix(moho.frame, matrix) if (self.centerVec == nil) then self.centerVec = LM.Vector2:new_local() local center = LM.Vector2:new_local() center:Set(0,0) self.centerVec:Set(center) end centerVec:Set(self.centerVec) g:Push() g:ApplyMatrix(matrix) if moho.layer:ControllingSkeleton() ~= nil and moho.frame == 0 then if not self.skel or not self.skelLayer or not self.skelLayer:IsLayerValid(moho.layer) then self.skel = self:FindSkeleton(moho) self:FindSkeletonLayer(moho) end local layer = moho.layer if layer:IsGroupType() or layer:LayerType() == MOHO.LT_PATCH then local ok = true if layer:LayerType() ~= MOHO.LT_GROUP and layer:LayerType() ~= MOHO.LT_PATCH then if moho:LayerAsBone(layer) ~= nil then local skel = moho:LayerAsBone(layer):Skeleton() if skel:CountBones() > 0 then ok = false end end end if ok then if self.skel:SelectedBoneID() >= 0 then for i=0, self.skel:CountBones() -1 do local bone = self.skel:Bone(i) if bone.fSelected then g:SetColor(selCol) g:SetSmoothing(true) if bone.fLength ~= 0 then g:SetPenWidth(2) local boneStartPos = LM.Vector2:new_local() local boneLeftPos = LM.Vector2:new_local() local boneRightPos = LM.Vector2:new_local() local boneEndPos = LM.Vector2:new_local() boneLeftPos:Set(bone.fLength * 0.075, bone.fLength * 0.075) boneRightPos:Set(bone.fLength * 0.075, -bone.fLength * 0.075) boneEndPos:Set(bone.fLength, 0) local selBoneMatrix = LM.Matrix:new_local() selBoneMatrix:Set(bone.fRestMatrix) selBoneMatrix:Transform(boneStartPos) selBoneMatrix:Transform(boneEndPos) selBoneMatrix:Transform(boneLeftPos) selBoneMatrix:Transform(boneRightPos) local skelLayerMatrix = LM.Matrix:new_local() self.skelLayer:GetFullTransform(0, skelLayerMatrix, nil) skelLayerMatrix:Transform(boneStartPos) skelLayerMatrix:Transform(boneEndPos) skelLayerMatrix:Transform(boneLeftPos) skelLayerMatrix:Transform(boneRightPos) if self.isBones1353 then g:SetPenWidth(6) g:DrawLine(boneStartPos.x, boneStartPos.y, boneEndPos.x, boneEndPos.y) else g:DrawLine(boneStartPos.x, boneStartPos.y, boneLeftPos.x, boneLeftPos.y) g:DrawLine(boneLeftPos.x, boneLeftPos.y, boneEndPos.x, boneEndPos.y) g:DrawLine(boneStartPos.x, boneStartPos.y, boneRightPos.x, boneRightPos.y) g:DrawLine(boneRightPos.x, boneRightPos.y, boneEndPos.x, boneEndPos.y) end else g:SetPenWidth(4) local boneStartPos = LM.Vector2:new_local() boneStartPos:Set(self:GetGlobalBonePos(moho, bone)) local secondPos = LM.Vector2:new_local() secondPos:Set(1,0) local selBoneMatrix = LM.Matrix:new_local() selBoneMatrix:Set(bone.fRestMatrix) selBoneMatrix:Transform(secondPos) local skelLayerMatrix = LM.Matrix:new_local() self.skelLayer:GetFullTransform(0, skelLayerMatrix, nil) skelLayerMatrix:Transform(secondPos) local dist = MR_Utilities:GetDistance(boneStartPos, secondPos) if self.isBones1353 then g:FrameCircle(boneStartPos, (bone:DisplayWidth(1) * 0.0015) /g:CurrentScale(false)) else g:FrameCircle(boneStartPos, 0.05 * dist) end end end end end end end end local lineSize = 0.03 if self.showTransformInfo and self.transformInfo and HV_Font then g:SetPenWidth(1) g:SetColor(blackCol) g:SetSmoothing(true) HV_Font:DrawLetters(moho, g, self.transformInfoText, 2.5/g:CurrentScale(false), self.mousePos.x + (cursorOffset1.x/g:CurrentScale(false)), self.mousePos.y + (cursorOffset1.y/g:CurrentScale(false)),2,2) end if self.centerId == 0 then g:SetPenWidth(2) g:SetColor(col) g:SetSmoothing(true) g:DrawLine(centerVec.x - lineSize, centerVec.y, centerVec.x + lineSize, centerVec.y) g:DrawLine(centerVec.x, centerVec.y - lineSize, centerVec.x, centerVec.y + lineSize) end g:Pop() end function MR_TransformRigTool:OnMouseDown(moho, mouseEvent) if not AE_Utilities then local ans = LM.GUI.Alert(LM.GUI.ALERT_WARNING, self:Localize('Missing Utilites'), self:Localize('Missing Utilites Info'), "", 'Ok', '', '', '') self.blockTransformation = true return end local skel = self:FindSkeleton(moho) if skel == nil or moho.frame ~= 0 then self.status = self:Localize('Could not find a Rig.') return end self.skel = skel self:FindSkeletonLayer(moho) self.blockTransformation = false local m = LM.Matrix:new_local() moho.layer:GetFullTransform(moho.frame, m, nil) if (mouseEvent.ctrlKey and mouseEvent.altKey) then local StartVec = LM.Vector2:new_local() StartVec:Set(mouseEvent.drawingStartVec) m:Transform(StartVec) self.centerVec:Set(StartVec) self.blockTransformation = true return end if self.selectBonesBt then local id = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, self.skelLayer, true) if (self.selectBonesBt) then if not mouseEvent.shiftKey and not mouseEvent.ctrlKey then skel:SelectNone() end if mouseEvent.ctrlKey then if id ~= -1 then skel:Bone(id).fSelected = false end else if id ~= -1 then skel:Bone(id).fSelected = true end end self.blockTransformation = true return end else if mouseEvent.altKey and not mouseEvent.ctrlKey then local id = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, self.skelLayer, true) skel:SelectNone() if id ~= -1 then skel:Bone(id).fSelected = true end self.blockTransformation = true return end end self.mainSkelSelectedBones = self:CountSelectedBones(moho, skel) self:ScanLayers(moho) self.status = ' ' if (self.vectorLayersToChange.layer[1] == nil) and self.imageLayersToChange.layer[1] == nil then if self.patchLayersToChange.layer[1] == nil then if (self.transformBones and self.mainSkelSelectedBones ~= 1) or not self.transformBones then self.status = self:Localize('No layers selected for active mode.') self:UpdateWidgets(moho) self.blockTransformation = true return end end end if (self.transformBones and self.mainSkelSelectedBones ~= 1) or (self.centerId == 1 and self.mainSkelSelectedBones ~= 1) then self.status = self:Localize('You need to select one bone in this mode.') self:UpdateWidgets(moho) self.blockTransformation = true return end self.isFlip = false self.lastScaleX = 1 self.lastScaleY = 1 if self.mainSkelSelectedBones == 1 then self.selectedMainBone = skel:Bone(skel:SelectedBoneID()) self.selectedMainBone.fTempPos = self.selectedMainBone.fAnimPos:GetValue(0) self.selectedMainBone.fTempAngle = self.selectedMainBone.fAnimAngle:GetValue(0) end if self.ignoreRefLayers then self:ScanGroupForReferences(moho, self.skelLayer) end moho.document:PrepUndo(self.skelLayer) moho.document:SetDirty() if self.transformPoints then self:CollectPointsTempPos(moho) end self.startAngle = 0 local m = LM.Matrix:new_local() moho.document:GetCameraMatrix(moho.frame, m) self.lastVec:Set(mouseEvent.view:Point2Vec(mouseEvent.pt, m)) self.offset:Set(0,0) if self.transformBones and self.mainSkelSelectedBones == 1 and self.scaleBt then local startBone = self.selectedMainBone startBone.fTempLength = startBone.fLength for l, b in ipairs(self.childBonesList) do self.childBonesList[l] = nil end for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if bone.fParent == skel:BoneID(startBone) then bone.fTempLength = bone.fLength bone.fTempPos = bone.fPos table.insert(self.childBonesList, bone) self:ScanBonesRecursion(moho, bone) end end end if self.transformImageLayers and (self.scaleBt or self.rotateBt) then local bone = skel:Bone(skel:SelectedBoneID()) for i, id in ipairs(self.imageLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) local vec = LM.Vector2:new_local() vec:Set(self.centerVec) local center = LM.Vector2:new_local() if self.centerId == 0 then -- custom center center:Set(self.centerVec) elseif self.centerId == 1 then -- selected bone center:Set(self:GetGlobalBonePos(moho, bone)) end center = MR_Utilities:GetLocalPos(moho, layer, center, false) -- use global pos self:SetOrigin(moho, layer, center) end end if self.centerId == 0 then -- custom center self.transformCenter:Set(self.centerVec) elseif self.centerId == 1 then -- selected bone local bone = skel:Bone(skel:SelectedBoneID()) self.transformCenter:Set(self:GetGlobalBonePos(moho, bone, true)) end if self.rotateBt and self.followPathAdaptation then for i, id in ipairs(self.followPathGroupsToChange.group) do local group = moho.document:LayerByAbsoluteID(id) local vec = LM.Vector2:new_local() vec:Set(self.centerVec) local center = LM.Vector2:new_local() center:Set(self.transformCenter) center:Set(MR_Utilities:GetLocalPos(moho, group, center, false)) self:SetOrigin(moho, group, center) end end end function MR_TransformRigTool:OnMouseMoved(moho, mouseEvent) if self.selectBonesBt then self.lastTransformMode = 0 elseif self.translateBt then self:OnMouseMoved_T(moho, mouseEvent) self.transformType = 1 elseif self.scaleBt then self:OnMouseMoved_S(moho, mouseEvent) self.transformType = 2 elseif self.rotateBt then self:OnMouseMoved_R(moho, mouseEvent) self.transformType = 3 end end function MR_TransformRigTool:OnMouseMoved_T(moho, mouseEvent) if self.blockTransformation then return end local skel = self.skel if skel == nil or moho.frame ~= 0 then return end local mouseStartVec = LM.Vector2:new_local() local mouseVec = LM.Vector2:new_local() local m = LM.Matrix:new_local() moho.document:GetCameraMatrix(moho.frame, m) mouseStartVec:Set(mouseEvent.view:Point2Vec(mouseEvent.startPt, m)) mouseVec:Set(mouseEvent.view:Point2Vec(mouseEvent.pt, m)) local offset = mouseVec - mouseStartVec if (mouseEvent.shiftKey) then if (math.abs(mouseVec.x - mouseStartVec.x) > math.abs(mouseVec.y - mouseStartVec.y)) then offset.y = 0 else offset.x = 0 end end self.offset:Set(offset) if self.transformPoints then for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() local localOffset = LM.Vector2:new_local() local zeroOffset = LM.Vector2:new_local() localOffset:Set(offset) localOffset:Set(MR_Utilities:GetLocalPos(moho, layer, localOffset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, layer, zeroOffset, false)) localOffset:Set(localOffset - zeroOffset) mesh:TranslatePoints(localOffset) moho:AddPointKeyframe(0, layer) -- Fix Onion Skin end end if self.transformBones and self.mainSkelSelectedBones == 1 then local localOffset = LM.Vector2:new_local() local zeroOffset = LM.Vector2:new_local() zeroOffset:Set(0, 0) localOffset:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, offset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, zeroOffset, false)) localOffset:Set(localOffset - zeroOffset) local myBone = self.selectedMainBone if myBone.fParent >= 0 then local bonePos = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() bonePos:Set(myBone.fTempPos) local parentBone = skel:Bone(myBone.fAnimParent:GetValue(0)) local parentMatrix = parentBone.fRestMatrix parentMatrix:Transform(bonePos) newPos:Set(bonePos + localOffset) local invertedMatrix = LM.Matrix:new_local() invertedMatrix:Set(parentMatrix) invertedMatrix:Invert() invertedMatrix:Transform(newPos) myBone.fAnimPos:SetValue(moho.frame, newPos) else myBone.fAnimPos:SetValue(0, myBone.fTempPos + localOffset) end end self.showTransformInfo = true self.mousePos:Set(MR_Utilities:GetGlobalPos(moho, moho.layer, mouseEvent.drawingVec, false)) self.transformInfoText = 'x '..MR_Utilities:Round(offset.x, 2)..' y '..MR_Utilities:Round(offset.y, 2) if self.ignoreRefLayers and self.liveUpdatingReferences then for k, layer in ipairs(self.refLayersList) do layer:MarkReferenceOutdated() end end if self.transformImageLayers then for i, id in ipairs(self.imageLayersToChange.layer) do local imagelayer = moho.document:LayerByAbsoluteID(id) local localOffset = LM.Vector2:new_local() local zeroOffset = LM.Vector2:new_local() localOffset:Set(offset) if imagelayer:Parent() then localOffset:Set(MR_Utilities:GetLocalPos(moho, imagelayer:Parent(), localOffset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, imagelayer:Parent(), zeroOffset, false)) localOffset:Set(localOffset - zeroOffset) end local vec = LM.Vector3:new_local() vec:Set(self.imageLayersToChange.position[i]) vec.x = vec.x + localOffset.x vec.y = vec.y + localOffset.y imagelayer.fTranslation:SetValue(0, vec) end end moho:NewKeyframe(CHANNEL_LAYER_T) moho.document:DepthSort() self.lastTransformMode = 1 self.lastTranslate:Set(offset) mouseEvent.view:DrawMe() end function MR_TransformRigTool:OnMouseMoved_S(moho, mouseEvent) if self.blockTransformation then return end local skel = self.skel if skel == nil or moho.frame ~= 0 then return end local bone = skel:Bone(skel:SelectedBoneID()) local bonePos = LM.Vector2:new_local() local center = LM.Vector2:new_local() center:Set(self.transformCenter) local scaling = LM.Vector2:new_local() scaling:Set(1, 1) local v1 = LM.Vector2:new_local() local v2 = LM.Vector2:new_local() local m = LM.Matrix:new_local() moho.document:GetCameraMatrix(moho.frame, m) v1:Set(mouseEvent.view:Point2Vec(mouseEvent.startPt, m)) v2:Set(mouseEvent.view:Point2Vec(mouseEvent.pt, m)) v1 = v1 - center v2 = v2 - center scaling.x = v2.x / v1.x scaling.y = v2.y / v1.y self.lastTransformMode = 2 self.lastCenter:Set(center) self.scaling = scaling if (mouseEvent.shiftKey and not self.transformBones) or (mouseEvent.shiftKey and self.centerId == 0) and not self.transformBones then scaling.y = 1 self.scalingMode = 2 -- h self.lastTransformMode = 3 elseif (mouseEvent.ctrlKey and not self.transformBones) or (mouseEvent.ctrlKey and self.centerId == 0) and not self.transformBones then scaling.x = 1 self.scalingMode = 3 -- v self.lastTransformMode = 4 else scaling.x = (scaling.x + scaling.y) / 2 scaling.y = scaling.x self.scalingMode = 1 -- uniform self.scaling = scaling end local flip = false if (scaling.x * self.lastScaleX < -0.0001) then if (scaling.y * self.lastScaleY > 0.0001) then flip = true self.isFlip = not self.isFlip end elseif (scaling.y * self.lastScaleY < -0.0001) then if (scaling.x * self.lastScaleX > 0.0001) then flip = true self.isFlip = not self.isFlip end end if (flip) then self.lastScaleX = scaling.x self.lastScaleY = scaling.y end if self.transformPoints then for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() local localCenter = LM.Vector2:new_local() localCenter:Set(center) localCenter = MR_Utilities:GetLocalPos(moho, layer, localCenter, false) -- use global pos mesh:ScalePoints(scaling.x, scaling.y, localCenter) moho:AddPointKeyframe(0, layer) -- Fix Onion Skin if flip then for i = 0, mesh:CountPoints() - 1 do local pt = mesh:Point(i) pt:FlipControlHandles(0) end end end end if self.transformImageLayers then for i, id in ipairs(self.imageLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) local vec = LM.Vector3:new_local() vec:Set(self.imageLayersToChange.scale[i]) if self.scalingMode == 1 then vec.x = vec.x * scaling.x vec.y = vec.y * scaling.x vec.z = vec.z * scaling.x elseif self.scalingMode == 2 then vec.x = vec.x * scaling.x elseif self.scalingMode == 3 then vec.y = vec.y * scaling.y end layer.fScale:SetValue(0, vec) end end moho:NewKeyframe(CHANNEL_LAYER_S) moho.document:DepthSort() if self.ignoreRefLayers and self.liveUpdatingReferences then for k, layer in ipairs(self.refLayersList) do layer:MarkReferenceOutdated() end end if self.transformBones and scaling.x == scaling.y and self.mainSkelSelectedBones == 1 then if self.centerId == 0 then local startBonePos = LM.Vector2:new_local() local centerVec = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local dif = LM.Vector2:new_local() if bone.fParent < 0 then startBonePos:Set(bone.fTempPos) centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) dif:Set(startBonePos - centerVec) newPos:Set((dif * scaling.x) + centerVec) else local parentBoneMatrix = LM.Matrix:new_local() local parentBone = skel:Bone(bone.fParent) startBonePos:Set(bone.fTempPos) parentBoneMatrix = parentBone.fRestMatrix parentBoneMatrix:Transform(startBonePos) centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) dif:Set(startBonePos - centerVec) newPos:Set((dif * scaling.x) + centerVec) parentBoneMatrix:Invert() parentBoneMatrix:Transform(newPos) end bone.fAnimPos:SetValue(0, newPos) end self:ScaleBones(moho, 1, scaling) end self.showTransformInfo = true self.mousePos:Set(MR_Utilities:GetGlobalPos(moho, moho.layer, mouseEvent.drawingVec, false)) if self.lastTransformMode == 2 then self.transformInfoText = LM.Round(scaling.x * 100) elseif self.lastTransformMode == 3 then self.transformInfoText = 'x '..LM.Round(scaling.x * 100) elseif self.lastTransformMode == 4 then self.transformInfoText = 'y '..LM.Round(scaling.y * 100) end self.lastScaling:Set(scaling) mouseEvent.view:DrawMe() end function MR_TransformRigTool:OnMouseMoved_R(moho, mouseEvent) if self.blockTransformation then return end local skel = self.skel if skel == nil or moho.frame ~= 0 then return end local bone = skel:Bone(skel:SelectedBoneID()) local bonePos = LM.Vector2:new_local() local center = LM.Vector2:new_local() center:Set(self.transformCenter) self.lastCenter:Set(center) local m = LM.Matrix:new_local() moho.document:GetCameraMatrix(moho.frame, m) local mousePos = mouseEvent.view:Point2Vec(mouseEvent.pt, m) 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 if (mouseEvent.shiftKey) then angle = angle / math.rad(45) angle = math.rad(45) * LM.Round(angle) end if self.transformPoints then for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() local localCenter = LM.Vector2:new_local() localCenter:Set(center) localCenter = MR_Utilities:GetLocalPos(moho, layer, localCenter, false) -- use global local localAngle = angle if self.vectorLayersToChange.parentalFlip[k] then localAngle = -localAngle end mesh:RotatePoints(localAngle, localCenter) moho:AddPointKeyframe(0, layer) -- Fix Onion Skin end end self.lastVec:Set(mousePos) self.lastAngle = angle if self.transformImageLayers then for i, id in ipairs(self.imageLayersToChange.layer) do local imageLayer = moho.document:LayerByAbsoluteID(id) local isLayerinFollowPathGroup = false if self.followPathAdaptation then for i, groupId in ipairs(self.followPathGroupsToChange.group) do if imageLayer:Parent() then local parentLayerID = moho.document:LayerAbsoluteID(imageLayer:Parent()) if parentLayerID == groupId then isLayerinFollowPathGroup = true end end end end if not isLayerinFollowPathGroup then local imageAngle = self.imageLayersToChange.angle[i] local localAngle = self.lastAngle if self.imageLayersToChange.parentalFlip[i] then localAngle = -localAngle end imageAngle = imageAngle + localAngle imageLayer.fRotationZ:SetValue(0, imageAngle) end end end if self.followPathAdaptation then for i, id in ipairs(self.followPathGroupsToChange.group) do local group = moho.document:LayerByAbsoluteID(id) if self.followPathGroupsToChange.transform[i] then local groupAngle = self.followPathGroupsToChange.angle[i] local localAngle = self.lastAngle if self.followPathGroupsToChange.parentalFlip[i] then localAngle = -localAngle end groupAngle = groupAngle + localAngle group.fRotationZ:SetValue(0, groupAngle) end end end -- moho:NewKeyframe(CHANNEL_LAYER_ROT_Z) moho.document:DepthSort() if self.transformBones and self.mainSkelSelectedBones == 1 then local bone = self.selectedMainBone local startBonePos = LM.Vector2:new_local() local centerVec = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local dif = LM.Vector2:new_local() startBonePos:Set(bone.fTempPos) centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) if bone.fParent < 0 then dif:Set(startBonePos - centerVec) local px = dif.x * math.cos(angle) - dif.y * math.sin(angle) local py = dif.x * math.sin(angle) + dif.y * math.cos(angle) newPos:Set(px + centerVec.x, py + centerVec.y) else local parentBoneMatrix = LM.Matrix:new_local() local parentBone = skel:Bone(bone.fParent) parentBoneMatrix = parentBone.fRestMatrix parentBoneMatrix:Transform(startBonePos) dif:Set(startBonePos - centerVec) local px = dif.x * math.cos(angle) - dif.y * math.sin(angle) local py = dif.x * math.sin(angle) + dif.y * math.cos(angle) newPos:Set(px + centerVec.x, py + centerVec.y) parentBoneMatrix:Invert() parentBoneMatrix:Transform(newPos) end bone.fAnimPos:SetValue(0, newPos) bone.fAnimAngle:SetValue(0, bone.fTempAngle + self.lastAngle) end self.showTransformInfo = true self.mousePos:Set(MR_Utilities:GetGlobalPos(moho, self.skelLayer, self.lastVec, false)) self.transformInfoText = LM.Round(180 * self.lastAngle/math.pi) if self.ignoreRefLayers and self.liveUpdatingReferences then for k, layer in ipairs(self.refLayersList) do layer:MarkReferenceOutdated() end end mouseEvent.view:DrawMe() self.lastTransformMode = 5 end function MR_TransformRigTool:OnMouseUp(moho, mouseEvent) if self.blockTransformation then self.blockTransformation = false return end local skel = self.skel self.showTransformInfo = false local curLayer = moho.layer if skel == nil or moho.frame ~= 0 then return end for m in pairs(self.fixedActionsList) do self.fixedActionsList[m] = nil end self.transformedTargetBonesList = {} self.lastScaling:Set(self.scaling) self.lastCenterId = self.centerId local isMarker = self:CheckMarker(moho) if moho.frame == 0 and self.transformType == 1 then -- translate if self.transformPoints then self:TranslatePointsInActions(moho, self.offset) end if self.transformBones and self.mainSkelSelectedBones == 1 then if self.transformTargetBones and not isMarker then self:TransformTargetBones(moho, false) end if self.transformVitruvianBones and self.isVitruvianBonesAvaible and not isMarker then self:TranslateVitruvianBones(moho, false) end if not isMarker then local bone = skel:Bone(skel:SelectedBoneID()) self:TranslateBoneInActions(moho, bone, self.offset) end end if self.transformOrigin then self:TranslateOrigins(moho, self.offset) end if self.followPathAdaptation then for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) if self.vectorLayersToChange.transformOriginsOffset[k] then local newOriginPos = LM.Vector2:new_local() local origin = LM.Vector2:new_local() origin:Set(self.vectorLayersToChange.origin[k]) local newOffset = LM.Vector2:new_local() newOffset:Set(self.offset) local zeroOffset = LM.Vector2:new_local() newOffset:Set(MR_Utilities:GetLocalPos(moho, layer, newOffset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, layer, zeroOffset, false)) newOffset:Set(newOffset - zeroOffset) newOriginPos:Set(origin + newOffset) self:SetOrigin(moho, layer, newOriginPos) layer.fTranslation:SetValue(0, self.vectorLayersToChange.layersPosition[k]) end end for k, id in ipairs(self.followPathGroupsToChange.group) do local layer = moho.document:LayerByAbsoluteID(id) if self.followPathGroupsToChange.transform[k] then local newOriginPos = LM.Vector2:new_local() local origin = self.followPathGroupsToChange.origin[k] local newOffset = LM.Vector2:new_local() newOffset:Set(self.offset) local zeroOffset = LM.Vector2:new_local() newOffset:Set(MR_Utilities:GetLocalPos(moho, layer, newOffset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, layer, zeroOffset, false)) newOffset:Set(newOffset - zeroOffset) newOriginPos:Set(origin + newOffset) self:SetOrigin(moho, layer, newOriginPos) layer.fTranslation:SetValue(0, self.followPathGroupsToChange.layersPosition[k]) end end end if self.transformImageLayers then self:TranslateImagesInActions(moho, self.offset, 0) end if self.transformPatchLayers then for i, id in ipairs(self.patchLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) self:TranslateLayer(moho, layer, self.offset) end end end if moho.frame == 0 and self.transformType == 2 then -- scale local bone = skel:Bone(skel:SelectedBoneID()) local ok = true if self.centerId == 1 and skel:SelectedBoneID() == -1 then ok = false elseif self.scaling.x == 1 and self.scaling.y == 1 then ok = false end if self.transformBones and self.mainSkelSelectedBones ~= 1 then ok = false end if ok then if self.transformPoints then if self.adjustStrokeWidth and self.lastTransformMode == 2 then self:AdjustStrokesWidth(moho, self.scaling.x) end self:ScalePointsInActions(moho, self.lastCenter, self.scaling) end if self.transformBones and self.mainSkelSelectedBones == 1 then if self.transformBones and self.scaling.x == self.scaling.y then if not isMarker then if self.adaptiveScaleAndRotation then self:CorrectScalingOffsetInActions(moho, bone, self.lastCenter, self.scaling) else local startBonePos = LM.Vector2:new_local() local centerVec = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local dif = LM.Vector2:new_local() local offset = LM.Vector2:new_local() startBonePos:Set(bone.fTempPos) if bone.fParent < 0 then centerVec:Set(self.lastCenter) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) dif:Set(startBonePos - centerVec) newPos:Set((dif * self.scaling.x) + centerVec) else local parentBoneMatrix = LM.Matrix:new_local() local parentBone = skel:Bone(bone.fParent) parentBoneMatrix = parentBone.fRestMatrix parentBoneMatrix:Transform(startBonePos) centerVec:Set(self.lastCenter) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) dif:Set(startBonePos - centerVec) newPos:Set((dif * self.scaling.x) + centerVec) end offset:Set(MR_Utilities:GetGlobalPos(moho, self.skelLayer, newPos, false) - MR_Utilities:GetGlobalPos(moho, self.skelLayer, startBonePos, false)) self:TranslateBoneInActions(moho, bone, offset) end self:ScaleBonesInActions(moho, self.lastCenter, self.scaling) end end if self.transformVitruvianBones and self.isVitruvianBonesAvaible and not isMarker then self:ScaleVitruvianBones(moho, false) end if self.transformTargetBones and not isMarker then self:TransformTargetBones(moho, false) end end if self.transformOrigin then self:ScaleOrigins(moho, self.lastCenter, self.scaling) end if self.followPathAdaptation then for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) if self.vectorLayersToChange.transformOriginsOffset[k] then local centerVec = LM.Vector2:new_local() centerVec:Set(self.lastCenter) centerVec = MR_Utilities:GetLocalPos(moho, layer, centerVec, false) --use global pos local dif = LM.Vector2:new_local() local newOriginPos = LM.Vector2:new_local() local origin = self.vectorLayersToChange.origin[k] dif:Set(origin - centerVec) newOriginPos:Set((dif * self.scaling.x) + centerVec) self:SetOrigin(moho, layer, newOriginPos) layer.fTranslation:SetValue(0, self.vectorLayersToChange.layersPosition[k]) end end for k, id in ipairs(self.followPathGroupsToChange.group) do local layer = moho.document:LayerByAbsoluteID(id) if self.followPathGroupsToChange.transform[k] then local centerVec = LM.Vector2:new_local() centerVec:Set(self.lastCenter) centerVec = MR_Utilities:GetLocalPos(moho, layer, centerVec, false) --use global pos local dif = LM.Vector2:new_local() local newOriginPos = LM.Vector2:new_local() local origin = self.followPathGroupsToChange.origin[k] dif:Set(origin - centerVec) newOriginPos:Set((dif * self.scaling.x) + centerVec) self:SetOrigin(moho, layer, newOriginPos) layer.fTranslation:SetValue(0, self.followPathGroupsToChange.layersPosition[k]) end end end if self.transformImageLayers then for i, id in ipairs(self.imageLayersToChange.layer) do local imagelayer = moho.document:LayerByAbsoluteID(id) self:SetOrigin(moho, imagelayer, self.imageLayersToChange.origin[i]) local posDif = LM.Vector3:new_local() posDif:Set(imagelayer.fTranslation:GetValue(0) - self.imageLayersToChange.position[i]) for actionID = 0, imagelayer.fTranslation:CountActions() - 1 do local action = moho:ChannelAsAnimVec3(imagelayer.fTranslation:Action(actionID)) local actionName = imagelayer.fTranslation:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local newPos = LM.Vector3:new_local() local layerTranslation = action:GetValue(actionFrame) newPos:Set(layerTranslation + posDif) action:SetValue(actionFrame, newPos) if layerTranslation ~= newPos then self:CollectLog(nil, actionName) end end end end end end self:ScaleImagesInActions(moho, self.lastCenter, self.scaling) end if self.transformPatchLayers then for i, id in ipairs(self.patchLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) self:ScaleLayer(moho, layer, self.lastCenter, self.scaling) end end else self.status = self:Localize('Only one bone should be selected.') end end if moho.frame == 0 and self.transformType == 3 then -- rotate local bone = skel:Bone(skel:SelectedBoneID()) local ok = true if self.centerId == 1 and skel:SelectedBoneID() == -1 then ok = false end if ok then local bonePos = LM.Vector2:new_local() local center = LM.Vector2:new_local() if self.centerId == 0 then -- custom center center:Set(self.centerVec) elseif self.centerId == 1 then -- selected bone bonePos:Set(self:GetGlobalBonePos(moho, bone)) center:Set(bonePos) end if self.transformPoints then self:RotatePointsInActions(moho, center, self.lastAngle) end if self.transformOrigin then self:RotateOrigins(moho, self.lastCenter, self.lastAngle) end if self.transformBones and self.mainSkelSelectedBones == 1 then if self.transformVitruvianBones and self.isVitruvianBonesAvaible and not isMarker then self:RotateVitruvianBones(moho, false) end if self.transformTargetBones and not isMarker then self:TransformTargetBones(moho, false) end if not isMarker then if self.adaptiveScaleAndRotation then self:CorrectRotatingOffsetInActions(moho, bone, center, self.lastAngle) else local startBonePos = LM.Vector2:new_local() local centerVec = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local dif = LM.Vector2:new_local() local offset = LM.Vector2:new_local() local angle = self.lastAngle startBonePos:Set(bone.fTempPos) centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) if bone.fParent < 0 then dif:Set(startBonePos - centerVec) local px = dif.x * math.cos(angle) - dif.y * math.sin(angle) local py = dif.x * math.sin(angle) + dif.y * math.cos(angle) newPos:Set(px + centerVec.x, py + centerVec.y) else local parentBoneMatrix = LM.Matrix:new_local() local parentBone = skel:Bone(bone.fParent) parentBoneMatrix = parentBone.fRestMatrix parentBoneMatrix:Transform(startBonePos) dif:Set(startBonePos - centerVec) local px = dif.x * math.cos(angle) - dif.y * math.sin(angle) local py = dif.x * math.sin(angle) + dif.y * math.cos(angle) newPos:Set(px + centerVec.x, py + centerVec.y) end offset:Set(MR_Utilities:GetGlobalPos(moho, self.skelLayer, newPos, false) - MR_Utilities:GetGlobalPos(moho, self.skelLayer, startBonePos, false)) self:TranslateBoneInActions(moho, bone, offset) end self:RotateBoneInActions(moho, bone, self.lastAngle) end end if self.transformImageLayers then for i, id in ipairs(self.imageLayersToChange.layer) do local imagelayer = moho.document:LayerByAbsoluteID(id) self:SetOrigin(moho, imagelayer, self.imageLayersToChange.origin[i]) local posDif = LM.Vector3:new_local() posDif:Set(imagelayer.fTranslation:GetValue(0) - self.imageLayersToChange.position[i]) for actionID = 0, imagelayer.fTranslation:CountActions() - 1 do local action = moho:ChannelAsAnimVec3(imagelayer.fTranslation:Action(actionID)) local actionName = imagelayer.fTranslation:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local newPos = LM.Vector3:new_local() local layerTranslation = action:GetValue(actionFrame) newPos:Set(layerTranslation + posDif) action:SetValue(actionFrame, newPos) if layerTranslation ~= newPos then self:CollectLog(nil, actionName) end end end end end end self:RotateImagesInActions(moho, self.lastCenter, self.lastAngle) end if self.followPathAdaptation then for i, id in ipairs(self.followPathGroupsToChange.group) do local group = moho.document:LayerByAbsoluteID(id) self:SetOrigin(moho, group, self.followPathGroupsToChange.origin[i]) end end if self.transformPatchLayers then for i, id in ipairs(self.patchLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) self:RotateLayer(moho, layer, center, self.lastAngle) end end end end if self.transformPoints then self:RefreshCachedLayers(moho) end if self.ignoreRefLayers then for k, layer in ipairs(self.refLayersList) do layer:MarkReferenceOutdated() end end local totalActions = #self.fixedActionsList local actionsStr = self:Localize(' actions were updated.') if totalActions == 1 then actionsStr = self:Localize(' action was updated.') end if totalActions > 0 then self.status = totalActions.. actionsStr else self.status = self:Localize('Actions did not need to be updated') end self.scaling:Set(1,1) self.transformType = 0 self.isFlip = false moho:NewKeyframe(CHANNEL_POINT) moho:UpdateUI() moho.view:DrawMe() end function MR_TransformRigTool:ScanLayers(moho, alt) if self.adjustStrokeWidth then for k in pairs(self.vectorLayersToStrokeChange) do self.vectorLayersToStrokeChange[k] = nil end end for k in pairs(self.vectorLayersToChange.layer) do self.vectorLayersToChange.layer[k] = nil self.vectorLayersToChange.parentalFlip[k] = nil self.vectorLayersToChange.layersPosition[k] = nil self.vectorLayersToChange.origin[k] = nil self.vectorLayersToChange.transformOriginsOffset[k] = nil end for k in pairs(self.groupsToChange.group) do self.groupsToChange.group[k] = nil end for k in pairs(self.followPathGroupsToChange.group) do self.followPathGroupsToChange.group[k] = nil self.followPathGroupsToChange.origin[k] = nil self.followPathGroupsToChange.angle[k] = nil self.followPathGroupsToChange.parentalFlip[k] = nil self.followPathGroupsToChange.transform[k] = nil self.followPathGroupsToChange.layersPosition[k] = nil end for k in pairs(self.patchLayersToChange.layer) do self.patchLayersToChange.layer[k] = nil end for k in pairs(self.imageLayersToChange.layer) do self.imageLayersToChange.layer[k] = nil self.imageLayersToChange.origin[k] = nil self.imageLayersToChange.scale[k] = nil self.imageLayersToChange.position[k] = nil self.imageLayersToChange.angle[k] = nil self.imageLayersToChange.parentalFlip[k] = nil end local count = 0 repeat local layer = moho.document:LayerByAbsoluteID(count) if layer then count = count + 1 if layer:IsAncestorSelected() or layer:SecondarySelection() or layer == moho.layer then local isLayerInSkel = false if layer:ControllingSkeleton() then if layer:ControllingSkeleton() == self.skel then if layer:LayerType() == MOHO.LT_BONE then local layerSkel = moho:LayerAsBone(layer):Skeleton() if layerSkel:CountBones() < 1 then isLayerInSkel = true end else isLayerInSkel = true end end else if layer:LayerType() == MOHO.LT_BONE then local layerSkel = moho:LayerAsBone(layer):Skeleton() if layerSkel then if layerSkel == self.skel then isLayerInSkel = true end end else local parentGroup = layer:Parent() if parentGroup ~= nil then local targetGroup = parentGroup repeat if targetGroup:LayerType() == MOHO.LT_BONE then local layerSkel = moho:LayerAsBone(targetGroup):Skeleton() if targetGroup == self.skel then isLayerInSkel = true break else break end else if targetGroup:ControllingSkeleton() then local targetSkel = targetGroup:ControllingSkeleton() if targetSkel ~= nil then if targetSkel == self.skel then isLayerInSkel = true break else break end end end end targetGroup = targetGroup:Parent() until targetGroup == nil end end end if isLayerInSkel then if self.transformImageLayers then if moho:LayerAsImage(layer) then if not self.ignoreRefLayers or (self.ignoreRefLayers and not layer:IsReferencedLayer()) then table.insert(self.imageLayersToChange.layer, moho.document:LayerAbsoluteID(layer)) local scale = LM.Vector3:new_local() local translation = LM.Vector3:new_local() scale:Set(layer.fScale.value) translation:Set(layer.fTranslation.value) local angle = layer.fRotationZ.value table.insert(self.imageLayersToChange.origin, layer:Origin()) table.insert(self.imageLayersToChange.scale, scale) table.insert(self.imageLayersToChange.position, translation) table.insert(self.imageLayersToChange.angle, angle) if self.rotateBt then table.insert(self.imageLayersToChange.parentalFlip, self:CheckLayerParentalFlip(moho, layer)) end end end end if moho:LayerAsVector(layer) and self.transformPoints then if not self.ignoreRefLayers or (self.ignoreRefLayers and not layer:IsReferencedLayer()) then local isLayerOk = true local transformOffset = false if (self.followPathAdaptation and self.rotateBt) or (self.followPathAdaptation and alt) then if layer:GetFollowingLayer() then if layer:Parent() then local layerParent = layer:Parent() if layerParent ~= self.skelLayer then local isGroupNew = true local layerParentID = moho.document:LayerAbsoluteID(layerParent) for _, groupID in pairs(self.followPathGroupsToChange.group) do if groupID == layerParentID then isGroupNew = false end end if isGroupNew then table.insert(self.followPathGroupsToChange.group, layerParentID) table.insert(self.followPathGroupsToChange.origin, layerParent:Origin()) table.insert(self.followPathGroupsToChange.transform, true) table.insert(self.followPathGroupsToChange.layersPosition, layerParent.fTranslation:GetValue(0)) table.insert(self.followPathGroupsToChange.angle, layerParent.fRotationZ:GetValue(0)) table.insert(self.followPathGroupsToChange.parentalFlip, self:CheckLayerParentalFlip(moho, layerParent)) end else local isLayerOk = false end else local isLayerOk = false end end elseif self.followPathAdaptation and (self.translateBt or self.scaleBt) then if layer:GetFollowingLayer() then local mesh = moho:LayerAsVector(layer):Mesh() if mesh:CountPoints() > 1 then local point = mesh:Point(0) local followLayer = layer:GetFollowingLayer() local followCurve = layer:GetFollowingCurve() local followValue = layer.fFollowing.value local matrix = LM.Matrix:new_local() layer:GetFullTransform(0, matrix, nil) local curPos = point.fAnimPos:GetValue(0) local newPos = LM.Vector2:new_local() newPos:Set(curPos) matrix:Transform(curPos) layer:SetFollowingCurve(followLayer, followCurve, followValue, true) layer:GetFullTransform(0, matrix, nil) matrix:Transform(newPos) if MR_Utilities:Round(curPos.x, 5) == MR_Utilities:Round(newPos.x, 5) and MR_Utilities:Round(curPos.y, 5) == MR_Utilities:Round(newPos.y, 5) then else layer:SetFollowingCurve(followLayer, followCurve, followValue, false) transformOffset = true end end end end if self.adjustStrokeWidth then table.insert(self.vectorLayersToStrokeChange, moho.document:LayerAbsoluteID(layer)) end if isLayerOk then local mesh = moho:LayerAsVector(layer):Mesh() if self.autoSelect then mesh:SelectAll() end if (mesh:CountPoints() > 1 and mesh ~= nil) then table.insert(self.vectorLayersToChange.layer, moho.document:LayerAbsoluteID(layer)) if self.followPathAdaptation then table.insert(self.vectorLayersToChange.layersPosition, layer.fTranslation:GetValue(0)) table.insert(self.vectorLayersToChange.transformOriginsOffset, transformOffset) end table.insert(self.vectorLayersToChange.origin, layer:Origin()) if self.rotateBt then table.insert(self.vectorLayersToChange.parentalFlip, self:CheckLayerParentalFlip(moho, layer, true)) end end end end end if layer:IsGroupType() then if layer:GetFollowingLayer() and self.followPathAdaptation then local isGroupNew = true local layerID = moho.document:LayerAbsoluteID(layer) for _, groupID in pairs(self.followPathGroupsToChange.group) do if groupID == layerID then isGroupNew = false end end if isGroupNew then table.insert(self.followPathGroupsToChange.group, layerID) table.insert(self.followPathGroupsToChange.origin, layer:Origin()) if self.translateBt or self.scaleBt then table.insert(self.followPathGroupsToChange.transform, true) else table.insert(self.followPathGroupsToChange.transform, false) end table.insert(self.followPathGroupsToChange.layersPosition, layer.fTranslation:GetValue(0)) table.insert(self.followPathGroupsToChange.angle, layer.fRotationZ:GetValue(0)) if self.rotateBt then table.insert(self.followPathGroupsToChange.parentalFlip, self:CheckLayerParentalFlip(moho, layer)) end end else table.insert(self.groupsToChange.group, moho.document:LayerAbsoluteID(layer)) end end if layer:LayerType() == MOHO.LT_PATCH and self.transformPatchLayers then table.insert(self.patchLayersToChange.layer, moho.document:LayerAbsoluteID(layer)) end end end end until not layer if self.followPathAdaptation then if self.rotateBt or alt then local isChanges = false repeat ::start_loop_groups:: isChanges = false for k, id in pairs(self.followPathGroupsToChange.group) do local layer = moho.document:LayerByAbsoluteID(id) for i, targetId in pairs(self.followPathGroupsToChange.group) do local targetLayer = moho:LayerAsGroup(moho.document:LayerByAbsoluteID(targetId)) if targetLayer:IsLayerValid(layer) then table.remove(self.followPathGroupsToChange.group, k) table.remove(self.followPathGroupsToChange.origin, k) table.remove(self.followPathGroupsToChange.angle, k) table.remove(self.followPathGroupsToChange.layersPosition, k) if self.rotateBt then table.remove(self.followPathGroupsToChange.parentalFlip, k) end table.remove(self.followPathGroupsToChange.transform, k) isChanges = true goto start_loop_groups end end end until not isChange repeat ::start_loop_vector_layers:: isChanges = false for k, id in pairs(self.vectorLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) for i, targetId in pairs(self.followPathGroupsToChange.group) do local targetLayer = moho:LayerAsGroup(moho.document:LayerByAbsoluteID(targetId)) if targetLayer:IsLayerValid(layer) then table.remove(self.vectorLayersToChange.layer, k) table.remove(self.vectorLayersToChange.layersPosition, k) table.remove(self.vectorLayersToChange.origin, k) table.remove(self.vectorLayersToChange.transformOriginsOffset, k) if self.rotateBt then table.remove(self.vectorLayersToChange.parentalFlip, k) end isChanges = true goto start_loop_vector_layers end end end until not isChange end end end function MR_TransformRigTool:FlipPoints(moho, direction, center, alt) local skel = self.skel if skel == nil or moho.frame ~= 0 then return end if self.mainSkelSelectedBones ~= 1 and self.centerId == 1 then return end if (self.vectorLayersToChange.layer[1] == nil) then return end self:FindSkeletonLayer(moho) if self.ignoreRefLayers then self:ScanGroupForReferences(moho, self.skelLayer) end for i, l in ipairs(self.curvesList) do self.curvesList[i] = nil end for i, l in ipairs(self.fPoses) do self.fPoses[i] = nil end for i, l in ipairs(self.selList) do self.selList[i] = nil end local bone = skel:Bone(skel:SelectedBoneID()) local bonePos = LM.Vector2:new_local() for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) if self.followPathAdaptation then for i, groupId in ipairs(self.followPathGroupsToChange.group) do if layer:Parent() then local parentLayerID = moho.document:LayerAbsoluteID(layer:Parent()) if parentLayerID == groupId then goto continue_to_next_layer end end end end local centerVec = LM.Vector2:new_local() centerVec:Set(center) local mesh = layer:Mesh() centerVec = MR_Utilities:GetLocalPos(moho, layer, centerVec, false) -- use global pos if self.autoSelect then mesh:SelectAll() end local localDirection = direction local skelMatrix = LM.Matrix:new_local() if alt and not self.useGlobalFlip then if self.lastSkelLayer ~= nil then self.lastSkelLayer:GetFullTransform(0, skelMatrix, nil) end elseif self.useGlobalFlip or not alt then self.skelLayer:GetFullTransform(0, skelMatrix, nil) end local layerMatrix = LM.Matrix:new_local() layer:GetFullTransform(0, layerMatrix, nil) local invertedLayerMatrix = LM.Matrix:new_local() invertedLayerMatrix:Set(layerMatrix) invertedLayerMatrix:Invert() local invertedSkelMatrix = LM.Matrix:new_local() invertedSkelMatrix:Set(skelMatrix) invertedSkelMatrix:Invert() for i = 0, mesh:CountPoints() - 1 do local pt = mesh:Point(i) if (pt.fSelected) then local dif = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local pointPos = LM.Vector2:new_local() local localCener = LM.Vector2:new_local() localCener:Set(center) pointPos:Set(pt.fAnimPos:GetValue(0)) layerMatrix:Transform(pointPos) if not self.useGlobalFlip then invertedSkelMatrix:Transform(localCener) invertedSkelMatrix:Transform(pointPos) end if direction then dif:Set(localCener.x - pointPos.x, 0) newPos:Set(localCener.x + dif.x, pointPos.y) else dif:Set(0, localCener.y - pointPos.y) newPos:Set(pointPos.x, localCener.y + dif.y) end if not self.useGlobalFlip then skelMatrix:Transform(newPos) end invertedLayerMatrix:Transform(newPos) pt.fAnimPos:SetValue(0, newPos) pt:FlipControlHandles(0) for actionID = 0, pt.fAnimPos:CountActions() - 1 do local action = moho:ChannelAsAnimVec2(pt.fAnimPos:Action(actionID)) local actionName = pt.fAnimPos:ActionName(actionID) if action ~= nil then layer:ActivateAction(actionName) for keyID = 0, action:CountKeys() - 1 do local posFrame = action:GetKeyWhen(keyID) if (posFrame > 0) then if alt or self.useGlobalFlip then local pointPos = LM.Vector2:new_local() local originalPos = LM.Vector2:new_local() local localCener = LM.Vector2:new_local() localCener:Set(center) pointPos:Set(action:GetValue(posFrame)) originalPos:Set(pointPos) layerMatrix:Transform(pointPos) if alt and not self.useGlobalFlip then invertedSkelMatrix:Transform(localCener) invertedSkelMatrix:Transform(pointPos) end if localDirection then dif:Set(localCener.x - pointPos.x, 0) newPos:Set(localCener.x + dif.x, pointPos.y) else dif:Set(0, localCener.y - pointPos.y) newPos:Set(pointPos.x, localCener.y + dif.y) end if alt and not self.useGlobalFlip then skelMatrix:Transform(newPos) end invertedLayerMatrix:Transform(newPos) else if localDirection then dif:Set(centerVec.x - action:GetValue(posFrame).x, 0) newPos:Set(centerVec.x + dif.x, action:GetValue(posFrame).y) else dif:Set(0, centerVec.y - action:GetValue(posFrame).y) newPos:Set(pt.fAnimPos:GetValue(posFrame).x, centerVec.y + dif.y) end end action:SetValue(posFrame, newPos) if originalPos ~= newPos then self:CollectLog(nil, actionName) end end end end end end end self:FlipControlHandlesInActions(moho, layer) if self.transformOrigin then local dif = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local originGlobal = MR_Utilities:GetGlobalPos(moho, layer, layer:Origin(), false) if direction then dif:Set(center.x - originGlobal.x, 0) newPos:Set(center.x + dif.x, originGlobal.y) else dif:Set(0, center.y - originGlobal.y) newPos:Set(originGlobal.x, center.y + dif.y ) end newPos = MR_Utilities:GetLocalPos(moho, layer, newPos, false) self:SetOrigin(moho, layer, newPos) end ::continue_to_next_layer:: end end function MR_TransformRigTool:FlipControlHandlesInActions(moho, layer) local mesh = layer:Mesh() if mesh == nil then return end for j = 0, mesh:CountPoints() - 1 do local point = mesh:Point(j) if point.fSelected then for c = 0, point:CountCurves() - 1 do local curve, where = point:Curve(c, -1) local offsetChannel1 = AE_Utilities:GetOffsetChannel(moho, layer, curve, where, false) for actionID = 0, offsetChannel1:CountActions() - 1 do local offsetActionChannel1 = offsetChannel1:Action(actionID) local actionName = offsetChannel1:ActionName(actionID) for keyID = 0, offsetActionChannel1:CountKeys() - 1 do local channelFrame = offsetActionChannel1:GetKeyWhen(keyID) if (channelFrame > 0) then layer:ActivateAction(actionName) curve:SetOffset(where, -curve:GetOffset(where, channelFrame, true), channelFrame, true) curve:SetOffset(where, -curve:GetOffset(where, channelFrame, false), channelFrame, false) self:CollectLog(nil, actionName) end end end layer:ActivateAction(nil) end end end end function MR_TransformRigTool:GetGlobalBonePos(moho, bone, rest) local skel = self.skel if skel == nil then return end local selBonePos = LM.Vector2:new_local() selBonePos:Set(bone.fAnimPos:GetValue(moho.frame)) if bone.fParent >-1 then local selBoneParentMatrix = LM.Matrix:new_local() if rest then selBoneParentMatrix:Set(skel:Bone(bone.fParent).fRestMatrix) else selBoneParentMatrix:Set(skel:Bone(bone.fParent).fMovedMatrix) end selBoneParentMatrix:Transform(selBonePos) end local skelLayerMatrix = LM.Matrix:new_local() self.skelLayer:GetFullTransform(moho.frame, skelLayerMatrix, nil) skelLayerMatrix:Transform(selBonePos) return selBonePos end function MR_TransformRigTool:GetLocalBonePos(moho, layer, globalPos, bone) local skel = self.skel local localPos = LM.Vector2:new_local() localPos:Set(globalPos) local selLayer = layer local selLayerMatrix = LM.Matrix:new_local() selLayer:GetFullTransform(0, selLayerMatrix, nil) selLayerMatrix:Invert() selLayerMatrix:Transform(localPos) if bone.fParent >-1 then local selBoneParentMatrix = LM.Matrix:new_local() selBoneParentMatrix:Set(skel:Bone(bone.fParent).fMovedMatrix) selBoneParentMatrix:Invert() selBoneParentMatrix:Transform(localPos) end return localPos end function MR_TransformRigTool:SetFromSelection(moho) self:ScanLayers(moho) self:ScanMeshBounds(moho) self:SelectedMeshBounds(moho, moho.layer, 0, view) end function MR_TransformRigTool:ScanMeshBounds(moho) local min = LM.Vector2:new_local() local max = LM.Vector2:new_local() min:Set(10000,10000) max:Set(-10000,-10000) if self.layersFound == 1 and moho.document:LayerByAbsoluteID(self.vectorLayersToChange.layer[1]) ~= moho.layer then self.bMin:Set(0,0) self.bMax:Set(0,0) return end for k, id in ipairs(self.vectorLayersToChange.layer) do local vectorLayer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = vectorLayer:Mesh() local minB = LM.Vector2:new_local() local maxB = LM.Vector2:new_local() local testBbox = mesh:SelectedBounds(minB, maxB) local m = LM.Matrix:new_local() local rightUp = LM.Vector2:new_local() local rightDown = LM.Vector2:new_local() local leftUp = LM.Vector2:new_local() local leftDown = LM.Vector2:new_local() local allVectors = {} rightUp:Set(maxB.x, maxB.y) rightDown:Set(maxB.x, minB.y) leftUp:Set(minB.x, maxB.y) leftDown:Set(minB.x, minB.y) vectorLayer:GetFullTransform(0, m, nil) m:Transform(rightUp) m:Transform(rightDown) m:Transform(leftUp) m:Transform(leftDown) table.insert(allVectors, rightUp) table.insert(allVectors, rightDown) table.insert(allVectors, leftUp) table.insert(allVectors, leftDown) for k, vec in ipairs(allVectors) do if vec.x < min.x then min.x = vec.x end if vec.x > max.x then max.x = vec.x end if vec.y < min.y then min.y = vec.y end if vec.y > max.y then max.y = vec.y end end end self.bMin = min self.bMax = max end function MR_TransformRigTool:SelectedMeshBounds(moho, layer, frame, view) local bbox = LM.BBox:new_local() local min = LM.Vector2:new_local() local max = LM.Vector2:new_local() min:Set(self.bMin) max:Set(self.bMax) bbox.fMin:Set(min.x, min.y, 0) bbox.fMax:Set(max.x, max.y, 0) local xLen = bbox.fMax.x - bbox.fMin.x local yLen = bbox.fMax.y - bbox.fMin.y if (xLen < yLen / 10.0) then local center = (bbox.fMin.x + bbox.fMax.x) / 2.0 bbox.fMin.x = center - yLen / 10.0 bbox.fMax.x = center + yLen / 10.0 elseif (yLen < xLen / 10.0) then local center = (bbox.fMin.y + bbox.fMax.y) / 2.0 bbox.fMin.y = center - xLen / 10.0 bbox.fMax.y = center + xLen / 10.0 end local minLength = 150 local m = LM.Matrix:new_local() local v = LM.Vector2:new_local() local pt1 = LM.Point:new_local() local pt2 = LM.Point:new_local() layer:GetFullTransform(frame, m, moho.document) v:Set(bbox.fMin.x, bbox.fMin.y) if (self.layersFound == 1) then m:Transform(v) end moho.view:Graphics():WorldToScreen(v, pt1) v:Set(bbox.fMax.x, bbox.fMax.y) if (self.layersFound == 1) then m:Transform(v) end moho.view:Graphics():WorldToScreen(v, pt2) pt1 = pt2 - pt1 local length = math.sqrt(pt1.x * pt1.x + pt1.y * pt1.y) if (length < minLength) then center = (bbox.fMin + bbox.fMax) / 2.0 v = bbox.fMax - center bbox.fMax = center + v * (minLength / length) / 2.0 v = bbox.fMin - center bbox.fMin = center + v * (minLength / length) / 2.0 end bbox:Normalize() self.centerVec:Set(bbox:Center2D()) end function MR_TransformRigTool:ScanGroupForReferences(moho, group) for i, l in ipairs(self.refLayersList) do self.refLayersList[i] = nil end local count = 0 repeat local layer = moho.document:LayerByAbsoluteID(count) if layer then count = count + 1 if group:IsLayerValid(layer) then if moho:LayerAsVector(layer) and layer:IsReferencedLayer() then table.insert(self.refLayersList, layer) end end end until not layer end function MR_TransformRigTool:UpdateRefereceLayersInGroup(moho, group) local groupLayer = moho:LayerAsGroup(group) if groupLayer then for i=0, groupLayer:CountLayers()-1 do local layer = groupLayer:Layer(i) if moho:LayerAsVector(layer) and layer:IsReferencedLayer() then layer:MarkReferenceOutdated() elseif layer:IsGroupType() then self:UpdateRefereceLayersInGroup(moho, layer) end end end end function MR_TransformRigTool:ScaleBones(moho, mode, scaleFactor) local skel = self.skel if mode == 1 then -- hierarchy local startBone = skel:Bone(skel:SelectedBoneID()) startBone.fLength = startBone.fTempLength * scaleFactor.x for i, a in pairs(self.childBonesList) do local bone = a local newPos = LM.Vector2:new_local() newPos:Set(bone.fTempPos.x * scaleFactor.x, bone.fTempPos.y * scaleFactor.x) bone.fLength = bone.fTempLength * scaleFactor.x bone.fAnimPos:SetValue(0, newPos) end end end function MR_TransformRigTool:ScanBonesRecursion(moho, bone) local skel = self.skel local startBone = bone for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if bone.fParent == skel:BoneID(startBone) then bone.fTempLength = bone.fLength bone.fTempPos = bone.fPos table.insert(self.childBonesList, bone) self:ScanBonesRecursion(moho, bone) end end end function MR_TransformRigTool:SetCenterFromBone(moho) self.skel = self:FindSkeleton(moho) if self.skel == nil then return end local skel = self.skel local selectedBones = self:CountSelectedBones(moho, skel) if selectedBones ~= 1 then return end local startBone = skel:Bone(skel:SelectedBoneID()) local boneCenter = LM.Vector2:new_local() boneCenter:Set(self:GetGlobalBonePos(moho, startBone)) self.centerVec:Set(boneCenter) end function MR_TransformRigTool:RepeatTransformation(moho, alt, vBones) local vBones = vBones or false if self.lastTransformMode == 0 then return false end self.skel = self:FindSkeleton(moho) if self.skel == nil then return false end local skel = self.skel self.mainSkelSelectedBones = self:CountSelectedBones(moho, skel) if self.transformBones and self.mainSkelSelectedBones ~= 1 then return false end self:FindSkeletonLayer(moho) local isMarker = self:CheckMarker(moho) if self.ignoreRefLayers then self:ScanGroupForReferences(moho, self.skelLayer) end local isStartBoneParent local startBone if self.transformBones then isStartBoneParent = false if self.mainSkelSelectedBones > 0 then startBone = self.skel:Bone(self.skel:SelectedBoneID()) if startBone.fParent < 0 then isStartBoneParent = false else isStartBoneParent = true end end end if self.lastTransformMode == 1 then -- translate if not vBones then moho.document:PrepUndo(self.skelLayer) moho.document:SetDirty() end local offset = LM.Vector2:new_local() offset:Set(self.lastTranslate) if alt then offset:Set(-offset.x, -offset.y) end local bone = startBone if not vBones then if self.transformPoints then for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() local localOffset = LM.Vector2:new_local() local zeroOffset = LM.Vector2:new_local() localOffset:Set(offset) localOffset:Set(MR_Utilities:GetLocalPos(moho, layer, localOffset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, layer, zeroOffset, false)) localOffset:Set(localOffset - zeroOffset) mesh:TranslatePoints(localOffset) moho:AddPointKeyframe(0, layer) end self:TranslatePointsInActions(moho, offset) end if self.transformOrigin and not vBones then self:TranslateOrigins(moho, offset) end if self.transformImageLayers then for i, id in ipairs(self.imageLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) self:TranslateLayer(moho, layer, offset) end end if self.transformPatchLayers then for i, id in ipairs(self.patchLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) self:TranslateLayer(moho, layer, self.offset) end end end if self.transformBones and self.mainSkelSelectedBones == 1 then local localOffset = LM.Vector2:new_local() local zeroOffset = LM.Vector2:new_local() zeroOffset:Set(0, 0) localOffset:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, offset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, zeroOffset, false)) localOffset:Set(localOffset - zeroOffset) if bone.fParent >= 0 then local bonePos = LM.Vector2:new_local() bonePos:Set(bone.fAnimPos:GetValue(0)) local parentBone = skel:Bone(bone.fAnimParent:GetValue(0)) local parentMatrix = parentBone.fRestMatrix parentMatrix:Transform(bonePos) bonePos:Set(bonePos + localOffset) local invertedMatrix = LM.Matrix:new_local() invertedMatrix:Set(parentMatrix) invertedMatrix:Invert() local newPos = LM.Vector2:new_local() newPos:Set(bonePos) invertedMatrix:Transform(newPos) bone.fAnimPos:SetValue(0, newPos) else bone.fAnimPos:SetValue(0, bone.fAnimPos:GetValue(0) + localOffset) end if not isMarker then self:TranslateBoneInActions(moho, bone, offset) end end elseif self.lastTransformMode >= 2 and self.lastTransformMode <= 4 then -- scale if not vBones then moho.document:PrepUndo(self.skelLayer) moho.document:SetDirty() end local skel = self.skel local scaling = LM.Vector2:new_local() scaling:Set(self.lastScaling) if self.transformBones and scaling.x ~= scaling.y then self.status = self:Localize('Non uniform scaling not supported for bones.') self:UpdateWidgets(moho) return false end if alt then local scalePercentageX = 100 / (1 / scaling.x) local scalePercentageY = 100 / (1 / scaling.y) scaling:Set(1/((1/100) * scalePercentageX), 1/((1/100) * scalePercentageY)) end if scaling.x == scaling.y then self.scalingMode = 1 elseif scaling.x ~= 1 and scaling.y == 1 then self.scalingMode = 2 elseif scaling.x == 1 and scaling.y ~= 1 then self.scalingMode = 3 elseif scaling.x ~= scaling.y and scaling.x ~= 1 and scaling.y ~= 1 then self.scalingMode = 4 end if self.mainSkelSelectedBones > 1 and self.centerId == 1 then return false end local boneCenter = LM.Vector2:new_local() if self.centerId == 1 and startBone then boneCenter:Set(self:GetGlobalBonePos(moho, startBone, true)) end if self.transformBones and self.mainSkelSelectedBones == 1 then if self.lastTransformMode == 2 and scaling.x == scaling.y then -- scale local startBonePos = LM.Vector2:new_local() local centerVec = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local newPosInLayer = LM.Vector2:new_local() local dif = LM.Vector2:new_local() startBone.fTempLength = startBone.fLength if startBone.fParent < 0 then startBonePos:Set(startBone.fAnimPos:GetValue(0)) centerVec:Set(self.lastCenter) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) dif:Set(startBonePos - centerVec) newPos:Set((dif * scaling.x) + centerVec) newPosInLayer:Set(newPos) else local parentBoneMatrix = LM.Matrix:new_local() local parentBone = skel:Bone(startBone.fParent) startBonePos:Set(startBone.fAnimPos:GetValue(0)) parentBoneMatrix = parentBone.fMovedMatrix parentBoneMatrix:Transform(startBonePos) centerVec:Set(self.lastCenter) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) dif:Set(startBonePos - centerVec) newPos:Set((dif * scaling.x) + centerVec) newPosInLayer:Set(newPos) parentBoneMatrix:Invert() parentBoneMatrix:Transform(newPos) end startBone.fAnimPos:SetValue(0, newPos) if not isMarker then if self.adaptiveScaleAndRotation then self:CorrectScalingOffsetInActions(moho, startBone, self.lastCenter, scaling) else local offset = LM.Vector2:new_local() MR_Utilities:Set(MR_Utilities:GetGlobalPos(moho, self.skelLayer, newPosInLayer, false) - MR_Utilities:GetGlobalPos(moho, self.skelLayer, startBonePos, false)) self:TranslateBoneInActions(moho, startBone, offset) end end for i, l in ipairs(self.childBonesList) do self.childBonesList[i] = nil end for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if bone.fParent == skel:BoneID(startBone) then bone.fTempLength = bone.fLength bone.fTempPos = bone.fPos table.insert(self.childBonesList, bone) self:ScanBonesRecursion(moho, bone) end end if self.transformBones and scaling.x == scaling.y and self.mainSkelSelectedBones == 1 then self:ScaleBones(moho, 1, scaling) end if isStartBoneParent then self:ScaleBonesInActions(moho, boneCenter, scaling) else self:ScaleBonesInActions(moho, self.lastCenter, scaling) end end end if not vBones then if self.transformPoints then for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() local localCenter = LM.Vector2:new_local() localCenter:Set(self.lastCenter) localCenter:Set(MR_Utilities:GetLocalPos(moho, layer, localCenter, false)) -- use global pos mesh:ScalePoints(scaling.x, scaling.y, localCenter) if self.isFlip then for i = 0, mesh:CountPoints() - 1 do local pt = mesh:Point(i) pt:FlipControlHandles(0) end end moho:AddPointKeyframe(0, layer) end self:ScalePointsInActions(moho, self.lastCenter, scaling) if self.adjustStrokeWidth and scaling.x == scaling.y then self:AdjustStrokesWidth(moho, scaling.x) end end if self.transformOrigin then self:ScaleOrigins(moho, self.lastCenter, scaling) end if self.transformImageLayers then for i, id in ipairs(self.imageLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) local localCenter = LM.Vector2:new_local() localCenter:Set(self.lastCenter) self:ScaleLayer(moho, layer, localCenter, scaling) end end if self.transformPatchLayers then for i, id in ipairs(self.patchLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) local localCenter = LM.Vector2:new_local() localCenter:Set(self.lastCenter) self:ScaleLayer(moho, layer, localCenter, scaling) end end end elseif self.lastTransformMode == 5 then -- rotate if not vBones then moho.document:PrepUndo(self.skelLayer) moho.document:SetDirty() end local skel = self.skel local angle = self.lastAngle local center = LM.Vector2:new_local() center:Set(self.lastCenter) if alt then angle = -angle end if self.mainSkelSelectedBones > 1 and self.centerId == 1 then return end if not vBones then if self.transformPoints then for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() local localAngle = angle if layer:GetFollowingLayer() == nil and self.followPathAdaptation or not self.followPathAdaptation then if self.vectorLayersToChange.parentalFlip[k] then localAngle = -localAngle end local localCenter = LM.Vector2:new_local() localCenter:Set(center) localCenter:Set(MR_Utilities:GetLocalPos(moho, layer, localCenter, false)) -- use global pos mesh:RotatePoints(localAngle, localCenter) moho:AddPointKeyframe(0, layer) end end self:RotatePointsInActions(moho, center, angle) end if self.transformOrigin then self:RotateOrigins(moho, center, angle) end if self.transformImageLayers then for i, id in ipairs(self.imageLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) self:RotateLayer(moho, layer, center, angle) end end if self.transformPatchLayers then for i, id in ipairs(self.patchLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) self:RotateLayer(moho, layer, center, angle) end end end if self.transformBones and startBone then if self:CheckLayerParentalFlip(moho, self.skelLayer, true) then angle = -angle end startBone.fAnimAngle:SetValue(0, startBone.fAnimAngle:GetValue(0) + angle) local startBonePos = LM.Vector2:new_local() local centerVec = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local newPosInLayer = LM.Vector2:new_local() local dif = LM.Vector2:new_local() startBonePos:Set(startBone.fAnimPos:GetValue(0)) centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) if startBone.fParent < 0 then dif:Set(startBonePos - centerVec) local px = dif.x * math.cos(angle) - dif.y * math.sin(angle) local py = dif.x * math.sin(angle) + dif.y * math.cos(angle) newPos:Set(px + centerVec.x, py + centerVec.y) newPosInLayer:Set(newPos) else local parentBoneMatrix = LM.Matrix:new_local() local parentBone = skel:Bone(startBone.fParent) parentBoneMatrix = parentBone.fRestMatrix parentBoneMatrix:Transform(startBonePos) dif:Set(startBonePos - centerVec) local px = dif.x * math.cos(angle) - dif.y * math.sin(angle) local py = dif.x * math.sin(angle) + dif.y * math.cos(angle) newPos:Set(px + centerVec.x, py + centerVec.y) newPosInLayer:Set(newPos) parentBoneMatrix:Invert() parentBoneMatrix:Transform(newPos) end startBone.fAnimPos:SetValue(0, newPos) if not isMarker then if self.adaptiveScaleAndRotation then self:CorrectRotatingOffsetInActions(moho, startBone, self.lastCenter, angle) else local offset = LM.Vector2:new_local() offset:Set(MR_Utilities:GetGlobalPos(moho, self.skelLayer, newPosInLayer, false) - MR_Utilities:GetGlobalPos(moho, self.skelLayer, startBonePos, false)) self:TranslateBoneInActions(moho, startBone, offset) end self:RotateBoneInActions(moho, startBone, angle) end end end if self.ignoreRefLayers then for k, layer in ipairs(self.refLayersList) do layer:MarkReferenceOutdated() end end return true end function MR_TransformRigTool:RotatePointsInActions(moho, center, angle) for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local localAngle = angle if layer:GetFollowingLayer() == nil and self.followPathAdaptation or not self.followPathAdaptation then if self.vectorLayersToChange.parentalFlip[k] then localAngle = -localAngle end local mesh = layer:Mesh() local centerVec = LM.Vector2:new_local() centerVec:Set(center) centerVec = MR_Utilities:GetLocalPos(moho, layer, centerVec, false) --use local m = LM.Matrix:new_local() local mInverted = LM.Matrix:new_local() layer:GetFullTransform(moho.frame, m, nil) mInverted:Set(m) mInverted:Invert() for i = 0, mesh:CountPoints() - 1 do local pt = mesh:Point(i) if pt.fSelected then for actionID = 0, pt.fAnimPos:CountActions() - 1 do local action = moho:ChannelAsAnimVec2(pt.fAnimPos:Action(actionID)) local actionName = pt.fAnimPos:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local posFrame = action:GetKeyWhen(keyID) if (posFrame > 0) then local dif = LM.Vector2:new_local() local originalPos = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local pointPos = action:GetValue(posFrame) originalPos:Set(pointPos) dif:Set(pointPos - centerVec) local px = dif.x * math.cos(localAngle) - dif.y * math.sin(localAngle) local py = dif.x * math.sin(localAngle) + dif.y * math.cos(localAngle) newPos:Set(px + centerVec.x, py + centerVec.y) action:SetValue(posFrame, newPos) if originalPos ~= newPos then self:CollectLog(nil, actionName) end end end end end end end if self.isFlip then self:FlipControlHandlesInActions(moho, layer) end end end end function MR_TransformRigTool:TranslatePointsInActions(moho, offset) for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() local localOffset = LM.Vector2:new_local() local zeroOffset = LM.Vector2:new_local() localOffset:Set(offset) localOffset:Set(MR_Utilities:GetLocalPos(moho, layer, localOffset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, layer, zeroOffset, false)) localOffset:Set(localOffset - zeroOffset) for i = 0, mesh:CountPoints() - 1 do local pt = mesh:Point(i) if pt.fSelected then for actionID = 0, pt.fAnimPos:CountActions() - 1 do local action = moho:ChannelAsAnimVec2(pt.fAnimPos:Action(actionID)) local actionName = pt.fAnimPos:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local posFrame = action:GetKeyWhen(keyID) if (posFrame > 0) then local originalPos = action:GetValue(posFrame) local newPos = originalPos + localOffset action:SetValue(posFrame, newPos) if originalPos ~= newPos then self:CollectLog(nil, actionName) end end end end end end end end end function MR_TransformRigTool:ScalePointsInActions(moho, centerScale, scaleValue) for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() local centerVec = LM.Vector2:new_local() centerVec:Set(centerScale) centerVec = MR_Utilities:GetLocalPos(moho, layer, centerVec, false) --use global pos for i = 0, mesh:CountPoints() - 1 do local pt = mesh:Point(i) if pt.fSelected then for actionID = 0, pt.fAnimPos:CountActions() - 1 do local action = moho:ChannelAsAnimVec2(pt.fAnimPos:Action(actionID)) local actionName = pt.fAnimPos:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local posFrame = action:GetKeyWhen(keyID) if (posFrame > 0) then local dif = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local originalPos = LM.Vector2:new_local() local pointPos = action:GetValue(posFrame) originalPos:Set(pointPos) dif:Set(pointPos - centerVec) if self.scalingMode == 1 then -- uniform newPos:Set((dif * scaleValue.x) + centerVec) elseif self.scalingMode == 2 then -- h newPos:Set((dif.x * scaleValue.x) + centerVec.x, pointPos.y ) elseif self.scalingMode == 3 then -- v newPos:Set(pointPos.x,(dif.y * scaleValue.y) + centerVec.y) elseif self.scalingMode == 4 then newPos:Set((dif.x * scaleValue.x) + centerVec.x, (dif.y * scaleValue.y) + centerVec.y) end action:SetValue(posFrame, newPos) if originalPos ~= newPos then self:CollectLog(nil, actionName) end end end end end end end if self.isFlip then self:FlipControlHandlesInActions(moho, layer) end end end function MR_TransformRigTool:ScaleBonesInActions(moho, centerScale, scaleValue) local skel = self.skel if 1 == 1 then -- hierarchy local startBone = skel:Bone(skel:SelectedBoneID()) local centerVec = LM.Vector2:new_local() centerVec:Set(centerScale) centerVec = MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false) --use global pos for i, a in pairs(self.childBonesList) do local bone = a for actionID = 0, bone.fAnimPos:CountActions() - 1 do local action = moho:ChannelAsAnimVec2(bone.fAnimPos:Action(actionID)) local actionName = bone.fAnimPos:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local posFrame = action:GetKeyWhen(keyID) if (posFrame > 0) then local newPos = LM.Vector2:new_local() local bonePos = action:GetValue(posFrame) newPos:Set(bonePos.x * scaleValue.x, bonePos.y * scaleValue.x) action:SetValue(posFrame, newPos) if bonePos ~= newPos then self:CollectLog(nil, actionName) end end end end end end end end function MR_TransformRigTool:UpdateLastCenter(moho) if self.centerId == 0 then self.lastCenter = self.centerVec elseif self.centerId == 1 then self.skel = self:FindSkeleton(moho) if self.skel == nil then return end local selectedBones = self:CountSelectedBones(moho, self.skel) if selectedBones == 1 then local boneCenter = LM.Vector2:new_local() local startBone = self.skel:Bone(self.skel:SelectedBoneID()) boneCenter:Set(self:GetGlobalBonePos(moho, startBone)) self.lastCenter:Set(boneCenter) end end end function MR_TransformRigTool:FindSkeletonLayer(moho) local skelLayer = nil if moho:Skeleton() and moho:Skeleton():CountBones() > 0 then skelLayer = moho.layer elseif moho.layer:ControllingBoneLayer() then skelLayer = moho.layer:ControllingBoneLayer() end if skelLayer == nil then local targetSkelLayer = nil local parentGroup = moho.layer:Parent() if parentGroup ~= nil then local targetGroup = parentGroup repeat if targetGroup:ControllingBoneLayer() then targetSkelLayer = targetGroup:ControllingBoneLayer() if targetSkelLayer ~= nil then skelLayer = targetSkelLayer break end end targetGroup = targetGroup:Parent() until targetGroup == nil end end self.skelLayer = skelLayer end function MR_TransformRigTool:FindSkeleton(moho) self.isSkel = true local skel = moho:Skeleton() if skel ~= nil and skel:CountBones() < 1 then skel = moho.layer:ControllingSkeleton() elseif (not moho:LayerAsBone(moho.layer)) then skel = moho.layer:ControllingSkeleton() end if skel == nil then local targetSkel = nil local parentGroup = moho.layer:Parent() if parentGroup ~= nil then local targetGroup = parentGroup repeat if targetGroup:ControllingSkeleton() then targetSkel = targetGroup:ControllingSkeleton() if targetSkel ~= nil then if targetSkel:CountBones() >0 then skel = targetSkel self.isSkel = true return skel end end end targetGroup = targetGroup:Parent() until targetGroup == nil self.isSkel = false end else self.isSkel = true return skel end end function MR_TransformRigTool:CountSelectedBones(moho, skeleton) if not skeleton then return 0 end local selectedBones = 0 for b=0, skeleton:CountBones() -1 do local myBone = skeleton:Bone(b) if myBone.fSelected then selectedBones = selectedBones +1 end end return selectedBones end function MR_TransformRigTool:CollectPointsTempPos(moho) for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() mesh:PrepMovePoints() if layer:AncestorSwitchLayer() then for i = 0, mesh:CountPoints() - 1 do local pt = mesh:Point(i) if pt.fSelected then pt.fTempPos = pt.fAnimPos:GetValue(0) end end end end end function MR_TransformRigTool:FlipBoneChain(moho, direction, smartBone, alt) local skel = self.skel if self.skel == nil then return end local startBone = skel:Bone(skel:SelectedBoneID()) for i, l in ipairs(self.childBonesList) do self.childBonesList[i] = nil end self:ScanBonesRecursion(moho, startBone) for i, a in pairs(self.childBonesList) do local bone = a bone.fTempAngle = bone.fAnimAngle:GetValue(0) end ---------- collect angle info ---------- for i, a in pairs(self.childBonesList) do local bone = a bone.fTempAngle = bone.fAnimAngle:GetValue(0) end for i, l in ipairs(self.bonesList) do self.bonesList[i] = nil end for i, a in pairs(self.childBonesList) do local bone = a local actionsList = {} for actionID = 0, bone.fAnimAngle:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVal(bone.fAnimAngle:Action(actionID)) local actionKeysList = {} local actionKeysDeltaList = {} for keyID = 0, actionChannel:CountKeys() - 1 do local posFrame = actionChannel:GetKeyWhen(keyID) table.insert(actionKeysList, actionChannel:GetValue(posFrame)) end table.insert(actionsList, actionKeysList) end table.insert(self.bonesList, actionsList) end -------------------------------------------------- startBone.fTempAngle = startBone.fAnimAngle:GetValue(0) skel:FlipBone(skel:BoneID(startBone), false) startBone.fMinConstraint, startBone.fMaxConstraint = -startBone.fMaxConstraint, -startBone.fMinConstraint local skelMatrix = LM.Matrix:new_local() self.skelLayer:GetFullTransform(0, skelMatrix, nil) local lastSkelMatrix = LM.Matrix:new_local() local invertedLastSkelMatrix = LM.Matrix:new_local() if self.lastSkelLayer ~= nil then self.lastSkelLayer:GetFullTransform(0, lastSkelMatrix, nil) invertedLastSkelMatrix:Set(lastSkelMatrix) invertedLastSkelMatrix:Invert() end local invertedSkelMatrix = LM.Matrix:new_local() invertedSkelMatrix:Set(skelMatrix) invertedSkelMatrix:Invert() if startBone.fParent < 0 then if alt or self.useGlobalFlip then local boneMatrix = startBone.fMovedMatrix local invertedBoneMatrix = LM.Matrix:new_local() invertedBoneMatrix:Set(boneMatrix) invertedBoneMatrix:Invert() local v1 = LM.Vector2:new_local() local v2 = LM.Vector2:new_local() v1:Set(startBone.fAnimPos:GetValue(0)) if (startBone:IsZeroLength()) then v2:Set(0.1, 0) else v2:Set(startBone.fLength, 0) end boneMatrix:Transform(v2) skelMatrix:Transform(v1) skelMatrix:Transform(v2) if alt and not self.useGlobalFlip then invertedLastSkelMatrix:Transform(v1) invertedLastSkelMatrix:Transform(v2) end if direction then v2:Set(v1.x + (v1.x - v2.x),v2.y) else v2:Set(v2.x, v1.y + (v1.y - v2.y)) end if alt and not self.useGlobalFlip then lastSkelMatrix:Transform(v1) lastSkelMatrix:Transform(v2) end invertedSkelMatrix:Transform(v1) invertedSkelMatrix:Transform(v2) local newAngle = 0 v2 = v2 - v1 newAngle = math.atan2(v2.y, v2.x) while newAngle > math.rad(360) do newAngle = newAngle - math.rad(360) end while newAngle < - math.rad(360) do newAngle = newAngle + math.rad(360) end startBone.fAnimAngle:SetValue(0, newAngle) else if direction then startBone.fAnimAngle:SetValue(0, math.rad(180) - startBone.fAnimAngle:GetValue(0)) else startBone.fAnimAngle:SetValue(0, -startBone.fAnimAngle:GetValue(0)) end end else local parent = skel:Bone(startBone.fParent) local parentMatrix = parent.fMovedMatrix local invMatrix = LM.Matrix:new_local() invMatrix:Set(parentMatrix) invMatrix:Invert() local v1 = LM.Vector2:new_local() local v2 = LM.Vector2:new_local() v1:Set(startBone.fAnimPos:GetValue(0)) if (startBone:IsZeroLength()) then v2:Set(0.1, 0) else v2:Set(startBone.fLength, 0) end parentMatrix:Transform(v1) startBone.fMovedMatrix:Transform(v2) if alt and not self.useGlobalFlip then skelMatrix:Transform(v1) skelMatrix:Transform(v2) invertedLastSkelMatrix:Transform(v1) invertedLastSkelMatrix:Transform(v2) elseif self.useGlobalFlip then skelMatrix:Transform(v1) skelMatrix:Transform(v2) end if direction then v2:Set(v1.x + (v1.x - v2.x),v2.y) else v2:Set(v2.x, v1.y + (v1.y - v2.y)) end if alt and not self.useGlobalFlip then lastSkelMatrix:Transform(v1) lastSkelMatrix:Transform(v2) invertedSkelMatrix:Transform(v1) invertedSkelMatrix:Transform(v2) elseif self.useGlobalFlip then invertedSkelMatrix:Transform(v1) invertedSkelMatrix:Transform(v2) end invMatrix:Transform(v1) invMatrix:Transform(v2) local newAngle = 0 v2 = v2 - v1 newAngle = math.atan2(v2.y, v2.x) while newAngle > math.rad(360) do newAngle = newAngle - math.rad(360) end while newAngle < - math.rad(360) do newAngle = newAngle + math.rad(360) end startBone.fAnimAngle:SetValue(0, newAngle) end ---------- correct start bone angle in actions ---------- for actionID = 0, startBone.fAnimAngle:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVal(startBone.fAnimAngle:Action(actionID)) local actionName = startBone.fAnimAngle:ActionName(actionID) for keyID = 0, actionChannel:CountKeys() - 1 do local keyFrame = actionChannel:GetKeyWhen(keyID) if (keyFrame > 0) then local newAngle = 0 local originalValue = actionChannel:GetValue(0) if startBone.fParent < 0 and not (alt or self.useGlobalFlip) then if direction then newAngle = math.rad(180) - actionChannel:GetValue(keyFrame) else newAngle = -actionChannel:GetValue(keyFrame) end else local angleDelta = startBone.fTempAngle - originalValue local startValue = actionChannel:GetValue(keyFrame) local angleDif = 0 if direction then angleDif = originalValue - startValue + angleDelta else angleDif = (originalValue - startValue) + angleDelta end newAngle = originalValue + angleDif end actionChannel:SetValue(keyFrame, newAngle) if originalValue ~= newAngle then self:CollectLog(nil, actionName) end end end end for i, a in pairs(self.childBonesList) do local bone = a if bone.fParent ~= skel:BoneID(startBone) then local newPos = LM.Vector2:new_local() newPos:Set(bone.fAnimPos:GetValue(0)) newPos:Set(newPos.x, -newPos.y) bone.fAnimPos:SetValue(0, newPos) end bone.fMinConstraint, bone.fMaxConstraint = -bone.fMaxConstraint, -bone.fMinConstraint for actionID = 0, bone.fAnimPos:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVec2(bone.fAnimPos:Action(actionID)) local actionName = bone.fAnimPos:ActionName(actionID) for keyID = 0, actionChannel:CountKeys() - 1 do local posFrame = actionChannel:GetKeyWhen(keyID) if (posFrame > 0) then local newPos = LM.Vector2:new_local() local originalPos = LM.Vector2:new_local() originalPos:Set(actionChannel:GetValue(posFrame)) newPos:Set(originalPos) newPos:Set(newPos.x, -newPos.y) actionChannel:SetValue(posFrame, newPos) if originalPos ~= newPos then self:CollectLog(nil, actionName) end end end end local maxValue = 0 for aID = 0, bone.fAnimAngle:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVal(bone.fAnimAngle:Action(aID)) local actionName = bone.fAnimAngle:ActionName(aID) local startValue = actionChannel:GetValue(0) local origZeoro = self.bonesList[i][aID + 1][1] local origStartValue = bone.fTempAngle local oldStartValue = 0 oldStartValue = math.rad(360) - startValue for keyID = 0, actionChannel:CountKeys() - 1 do local posFrame = actionChannel:GetKeyWhen(keyID) if (posFrame > 0) then local oldValue = actionChannel:GetValue(posFrame) local oldDelta = oldValue - oldStartValue local newValue = startValue - ((oldValue + (startValue - origZeoro)) - startValue) actionChannel:SetValue(posFrame, newValue) if oldValue ~= newValue then self:CollectLog(nil, actionName) end end end end end ---------- correct start bone position in actions ---------- for actionID = 0, startBone.fAnimPos:CountActions() - 1 do moho:SetCurFrame(0) local actionChannel = moho:ChannelAsAnimVec2(startBone.fAnimPos:Action(actionID)) local actionName = startBone.fAnimPos:ActionName(actionID) local startPos = LM.Vector2:new_local() startPos:Set(startBone.fAnimPos:GetValue(0)) local globalStartPos = LM.Vector2:new_local() globalStartPos:Set(startPos) if startBone.fParent > -1 then skel:Bone(startBone.fParent).fMovedMatrix:Transform(globalStartPos) end local lastSkelMatrix = LM.Matrix:new_local() local skelMatrix = LM.Matrix:new_local() self.skelLayer:GetFullTransform(0, skelMatrix, nil) local invertedSkelMatrix = LM.Matrix:new_local() invertedSkelMatrix:Set(skelMatrix) invertedSkelMatrix:Invert() if self.lastSkelLayer ~= nil then self.lastSkelLayer:GetFullTransform(0, lastSkelMatrix, nil) end local invertedLastSkelMatrix = LM.Matrix:new_local() invertedLastSkelMatrix:Set(lastSkelMatrix) invertedLastSkelMatrix:Invert() if alt and not self.useGlobalFlip then skelMatrix:Transform(startPos) skelMatrix:Transform(globalStartPos) invertedLastSkelMatrix:Transform(startPos) invertedLastSkelMatrix:Transform(globalStartPos) elseif self.useGlobalFlip then skelMatrix:Transform(startPos) skelMatrix:Transform(globalStartPos) end for keyID = 0, actionChannel:CountKeys() - 1 do local posFrame = actionChannel:GetKeyWhen(keyID) if (posFrame > 0) then if startBone.fParent < 0 then if alt or self.useGlobalFlip then self.skelLayer:ActivateAction(actionName) moho:SetCurFrame(posFrame) local newPos = LM.Vector2:new_local() local curPos = LM.Vector2:new_local() local difPos = LM.Vector2:new_local() local originalPos = LM.Vector2:new_local() curPos:Set(actionChannel:GetValue(posFrame)) originalPos:Set(curPos) if alt and not self.useGlobalFlip then skelMatrix:Transform(curPos) invertedLastSkelMatrix:Transform(curPos) elseif self.useGlobalFlip then skelMatrix:Transform(curPos) end difPos:Set(startPos - curPos) newPos:Set(startPos + difPos) if direction then newPos:Set(newPos.x, curPos.y) else newPos:Set(curPos.x, newPos.y) end if alt and not self.useGlobalFlip then lastSkelMatrix:Transform(newPos) invertedSkelMatrix:Transform(newPos) elseif self.useGlobalFlip then invertedSkelMatrix:Transform(newPos) end actionChannel:SetValue(posFrame, newPos) else local newPos = LM.Vector2:new_local() local difPos = LM.Vector2:new_local() newPos:Set(actionChannel:GetValue(posFrame)) difPos:Set(startPos - newPos) if direction then newPos:Set(startPos.x + difPos.x, newPos.y) else newPos:Set(newPos.x, startPos.y + difPos.y) end actionChannel:SetValue(posFrame, newPos) if originalPos ~= newPos then self:CollectLog(nil, actionName) end end else self.skelLayer:ActivateAction(actionName) moho:SetCurFrame(posFrame) local newPos = LM.Vector2:new_local() local globalCurPos = LM.Vector2:new_local() local difPos = LM.Vector2:new_local() local originalPos = LM.Vector2:new_local() local parentBoneMatrix = LM.Matrix:new_local() parentBoneMatrix:Set(skel:Bone(startBone.fParent).fMovedMatrix) originalPos:Set(actionChannel:GetValue(posFrame)) globalCurPos:Set(originalPos) parentBoneMatrix:Transform(globalCurPos) if alt and not self.useGlobalFlip then skelMatrix:Transform(globalCurPos) invertedLastSkelMatrix:Transform(globalCurPos) elseif self.useGlobalFlip then skelMatrix:Transform(globalCurPos) end difPos:Set(globalStartPos - globalCurPos) newPos:Set(globalStartPos + difPos) if direction then newPos:Set(newPos.x, globalCurPos.y) else newPos:Set(globalCurPos.x, newPos.y) end if alt and not self.useGlobalFlip then lastSkelMatrix:Transform(newPos) invertedSkelMatrix:Transform(newPos) elseif self.useGlobalFlip then invertedSkelMatrix:Transform(newPos) end parentBoneMatrix:Invert() parentBoneMatrix:Transform(newPos) actionChannel:SetValue(posFrame, newPos) if originalPos ~= newPos then self:CollectLog(nil, actionName) end end end end self.skelLayer:ActivateAction(nil) moho:SetCurFrame(0) end end function MR_TransformRigTool:IsLayerFlipped(moho, layer, direction) local isFlipped = false if direction then isFlipped = layer.fFlipH.value else isFlipped = layer.fFlipV.value end local parentGroup = layer:Parent() if parentGroup ~= nil then local targetGroup = parentGroup repeat if direction then if targetGroup.fFlipH.value then isFlipped = not isFlipped end else if targetGroup.fFlipV.value then isFlipped = not isFlipped end end targetGroup = targetGroup:Parent() until targetGroup == nil end return isFlipped end function MR_TransformRigTool:SetOrigin(moho, layer, pos) local matrix = LM.Matrix:new_local() local beforeVec = LM.Vector3:new_local() local afterVec = LM.Vector3:new_local() layer:GetLayerTransform(0, matrix, nil) matrix:Transform(beforeVec) layer:SetOrigin(pos) layer:GetLayerTransform(moho.frame, matrix, nil) matrix:Transform(afterVec) local returnVec = beforeVec - afterVec if returnVec:Mag() > 0.000001 then layer.fTranslation:SetValue(0, layer.fTranslation:GetValue(0) + returnVec) moho:NewKeyframe(CHANNEL_LAYER_T) end moho.document:DepthSort() end function MR_TransformRigTool:FindSmartbones(moho, skel, targetSkel, mainBone, ignoreGroup) local actionsList = {} local count = 0 for a in pairs(self.targetSkelBonesNamesList) do self.targetSkelBonesNamesList[a] = nil end for i = 0, targetSkel:CountBones()-1 do local bone = targetSkel:Bone(i) table.insert(self.targetSkelBonesNamesList, bone:Name()) end repeat local layer = moho.document:LayerByAbsoluteID(count) count = count + 1 if layer then local isOk = true if ignoreGroup then if moho:LayerAsGroup(ignoreGroup):IsLayerValid(layer) or layer == ignoreGroup then isOk = false end end if (layer:IsAncestorSelected() or layer:SecondarySelection()) and isOk then for a=0, layer:CountActions()-1 do local actionName = layer:ActionName(a) if layer:ActionDuration(actionName) > 0 then local isActionNew = true for u, action in pairs(actionsList) do if action == actionName then isActionNew = false end end if isActionNew then table.insert(actionsList, actionName) end end end end end until not layer for i = 0, skel:CountBones()-1 do local bone = skel:Bone(i) if bone.fSelected then for actionID = 0, bone.fAnimPos:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVec2(bone.fAnimPos:Action(actionID)) local actionName = bone.fAnimPos:ActionName(actionID) if actionChannel ~= nil then if actionChannel:Duration() > 0 then local isActionNew = true for u, action in pairs(actionsList) do if action == actionName then isActionNew = false end end if isActionNew then table.insert(actionsList, actionName) end end end end for actionID = 0, bone.fAnimAngle:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVal(bone.fAnimAngle:Action(actionID)) local actionName = bone.fAnimAngle:ActionName(actionID) if actionChannel ~= nil then if actionChannel:Duration() > 0 then local isActionNew = true for u, action in pairs(actionsList) do if action == actionName then isActionNew = false end end if isActionNew then table.insert(actionsList, actionName) end end end end for actionID = 0, bone.fAnimScale:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVal(bone.fAnimScale:Action(actionID)) local actionName = bone.fAnimScale:ActionName(actionID) if actionChannel ~= nil then if actionChannel:Duration() > 0 then local isActionNew = true for u, action in pairs(actionsList) do if action == actionName then isActionNew = false end end if isActionNew then table.insert(actionsList, actionName) end end end end for actionID = 0, bone.fFlipH:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimBool(bone.fFlipH:Action(actionID)) local actionName = bone.fFlipH:ActionName(actionID) if actionChannel ~= nil then if actionChannel:Duration() > 0 then local isActionNew = true for u, action in pairs(actionsList) do if action == actionName then isActionNew = false end end if isActionNew then table.insert(actionsList, actionName) end end end end for actionID = 0, bone.fFlipV:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimBool(bone.fFlipV:Action(actionID)) local actionName = bone.fFlipV:ActionName(actionID) if actionChannel ~= nil then if actionChannel:Duration() > 0 then local isActionNew = true for u, action in pairs(actionsList) do if action == actionName then isActionNew = false end end if isActionNew then table.insert(actionsList, actionName) end end end end end end for a in pairs(self.smartbonesList.originalName) do self.smartbonesList[a] = nil self.smartbonesList.originalName[a] = nil self.smartbonesList.newName[a] = nil self.smartbonesList.mode[a] = nil self.smartbonesList.originalAngle[a] = nil end for a in pairs(MR_ActionsDialog.actionInput) do MR_ActionsDialog.dynamicNumberText[a] = nil MR_ActionsDialog.dynamicSymbolText[a] = nil MR_ActionsDialog.actionInput[a] = nil MR_ActionsDialog.asActionRadioButton[a] = nil MR_ActionsDialog.asSmartboneRadioButton[a] = nil MR_ActionsDialog.removeRadioButton[a] = nil end for u, action in pairs(actionsList) do for i = 0, skel:CountBones()-1 do local bone = skel:Bone(i) if action == bone:Name() and not skel:IsAncestorSelected(i) and not bone.fSelected then table.insert(self.smartbonesList.originalName, action) table.insert(self.smartbonesList.originalAngle, bone.fAnimAngle:GetValue(0)) break end end end if #self.smartbonesList.originalName >= 1 then local dlog = MR_ActionsDialog:new(moho) if (dlog:DoModal() == LM.GUI.MSG_CANCEL) then return false end end return true end function MR_TransformRigTool:DuplicateBodypart(moho, alt) local mainSkel = self:FindSkeleton(moho) self:FindSkeletonLayer(moho) local skelLayer = self.skelLayer if not mainSkel or not skelLayer then return end for l = 0, moho.document:CountSelectedLayers()-1 do local layer = moho.document:GetSelectedLayer(l) if layer == skelLayer then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Duplicate bodypart alert 1'), self:Localize('Duplicate bodypart alert 2'), "", 'OK') return end end local isAnotherSkelSelected = false local extraSkelCounter = 0 for l = 0, moho.document:CountSelectedLayers()-1 do local layer = moho.document:GetSelectedLayer(l) if layer == skelLayer then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Duplicate bodypart alert 1'), self:Localize('Duplicate bodypart alert 2'), "", 'OK') return elseif layer:IsBoneType() and not moho:LayerAsGroup(skelLayer):IsLayerValid(layer) then isAnotherSkelSelected = true extraSkelCounter = extraSkelCounter + 1 end end if extraSkelCounter > 0 then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Duplicate bodypart alert 1'), self:Localize('Duplicate bodypart alert 2'), "", 'OK') return end self.mainSkelSelectedBones = self:CountSelectedBones(moho, mainSkel) if self.mainSkelSelectedBones ~= 1 then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Duplicate bodypart alert 1'), self:Localize('Duplicate bodypart alert 2'), "", 'OK') return end local topLayer = moho.document:Layer(moho.document:CountLayers()-1) local isDirectionRight = true local direction1 local direction2 local needToRename = true local dlog = MR_DuplicateBodypartDialog:new(moho) if (dlog:DoModal() == LM.GUI.MSG_CANCEL) then return false end if self.directionMode then if self.rDirection then isDirectionRight = true direction1 = 'R' direction2 = 'L' else isDirectionRight = false direction1 = 'L' direction2 = 'R' end elseif self.customMode then direction1 = self.customModeInput1 direction2 = self.customModeInput2 elseif self.suffixMode then needToRename = false end moho.document:SetDirty() moho.document:PrepUndo(nil) local currentLayer = moho.layer local duplicatedLayersList = {} duplicatedLayersList.originalLayers = {} duplicatedLayersList.duplicatedLayers = {} for l = 0, moho.document:CountSelectedLayers()-1 do local originalLayer = moho.document:GetSelectedLayer(l) if not originalLayer:IsAncestorSelected() then table.insert(duplicatedLayersList.originalLayers, originalLayer) end end local selectedBoneId = mainSkel:SelectedBoneID() local selectedBone = mainSkel:Bone(selectedBoneId) local originalVitruvianGroup = nil local mainBones = {} if self.transformTargetBones then self:FindTargetBones(moho, selectedBone, true) end if self.isVitruvianBonesAvaible then if mainSkel:IsBoneInAGroup(selectedBoneId) and self.transformVitruvianBones then originalVitruvianGroup = mainSkel:GroupForBone(selectedBoneId, false) for i=0, originalVitruvianGroup:CountBones()-1 do local bone = originalVitruvianGroup:Bone(i) bone.fSelected = true table.insert(mainBones, bone) if self.transformTargetBones then self:FindTargetBones(moho, bone, false) end end else table.insert(mainBones, selectedBone) end end if self.transformTargetBones then for n, targetBone in ipairs(self.targetBonesList) do targetBone.fSelected = true end end for i=0, mainSkel:CountBones()-1 do local bone = mainSkel:Bone(i) if mainSkel:IsAncestorSelected(i) then bone.fSelected = true end end if alt then self.duplicateActionsMode = 1 if not self:FindSmartbones(moho, mainSkel, mainSkel, selectedBone, nil) then mainSkel:SelectNone() selectedBone.fSelected = true return end for i = 1, #MR_TransformRigTool.smartbonesList.originalName do if MR_TransformRigTool.smartbonesList.mode[i] == 2 then local bone = mainSkel:BoneByName(MR_TransformRigTool.smartbonesList.originalName[i]) bone.fSelected = true end end end moho:SetSelLayer(skelLayer) local originalTotalBonesNum = mainSkel:CountBones() local oiginalBonesList = {} local duplicatedBonesListID = {} for i=0, mainSkel:CountBones()-1 do local bone = mainSkel:Bone(i) if bone.fSelected then table.insert(oiginalBonesList, bone) end end local isMainBonePin = false if selectedBone.fLength == 0 then isMainBonePin = true selectedBone.fLength = 0.1 end moho:Copy() if isMainBonePin then selectedBone.fLength = 0 end moho:SetSelLayer(topLayer) local tempSkelLayer = moho:CreateNewLayer(MOHO.LT_BONE, false) local tempSkel = moho:LayerAsBone(tempSkelLayer):Skeleton() tempSkelLayer:SetName('Temp Layer') moho:Paste() for i = 1, #MR_TransformRigTool.smartbonesList.originalName do local sBone = tempSkel:BoneByName(MR_TransformRigTool.smartbonesList.originalName[i]) if sBone then local angleDelta = sBone.fAnimAngle:GetValue(0) - MR_TransformRigTool.smartbonesList.originalAngle[i] for aID = 0, sBone.fAnimAngle:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVal(sBone.fAnimAngle:Action(aID)) local actionName = sBone.fAnimAngle:ActionName(aID) for keyID = 0, actionChannel:CountKeys() - 1 do local actionFrame = actionChannel:GetKeyWhen(keyID) if (actionFrame > 0) then local value = actionChannel:GetValue(actionFrame) local newValue = value + angleDelta actionChannel:SetValue(actionFrame, newValue) end end end end end for o, origBone in ipairs(oiginalBonesList) do for i =0, tempSkel:CountBones()-1 do local bone = tempSkel:Bone(i) if isMainBonePin then if selectedBone:Name() == bone:Name() then bone.fLength = 0 end end if origBone:Name() == bone:Name() then table.insert(duplicatedBonesListID, i) break end end end local allOriginalLayersList = {} local allDuplicatedLayersList = {} local duplicatSufix = self.duplicatedBodypartSuffix for k, origLayer in ipairs(duplicatedLayersList.originalLayers) do if origLayer:IsGroupType() then local tempList = self:ScanLayersReccursion(moho, origLayer) for t, templayer in ipairs(tempList) do table.insert(allOriginalLayersList, templayer) end else table.insert(allOriginalLayersList, origLayer) end local dupLayer = moho.document:DuplicateLayer(origLayer) if dupLayer:IsGroupType() then local tempList = self:ScanLayersReccursion(moho, dupLayer) for t, templayer in ipairs(tempList) do table.insert(allDuplicatedLayersList, templayer) end else table.insert(allDuplicatedLayersList, dupLayer) end local newDuplicatedLayerName = origLayer:Name() if needToRename then if self.swapNames then local tempText1 = 'TEMPTEXT1' local tempText2 = 'TEMPTEXT2' newDuplicatedLayerName = self:ChangeNameString(moho, origLayer:Name(), direction1, tempText1) newDuplicatedLayerName = self:ChangeNameString(moho, newDuplicatedLayerName, direction2, tempText2) newDuplicatedLayerName = self:ChangeNameString(moho, newDuplicatedLayerName, string.lower(direction1), string.lower(tempText1)) newDuplicatedLayerName = self:ChangeNameString(moho, newDuplicatedLayerName, string.lower(direction2), string.lower(tempText2)) newDuplicatedLayerName = self:ChangeNameString(moho, newDuplicatedLayerName, tempText1, direction2) newDuplicatedLayerName = self:ChangeNameString(moho, newDuplicatedLayerName, tempText2, direction1) newDuplicatedLayerName = self:ChangeNameString(moho, newDuplicatedLayerName, string.lower(tempText1), string.lower(direction2)) newDuplicatedLayerName = self:ChangeNameString(moho, newDuplicatedLayerName, string.lower(tempText2), string.lower(direction1)) else newDuplicatedLayerName = self:ChangeNameString(moho, origLayer:Name(), direction1, direction2) newDuplicatedLayerName = self:ChangeNameString(moho, newDuplicatedLayerName, string.lower(direction1), string.lower(direction2)) end end local isNameOk = true local targetName = newDuplicatedLayerName local counter = '' local sufix = '' repeat isNameOk = true for i=0, skelLayer:CountLayers()-1 do local layer = skelLayer:Layer(i) if targetName..sufix..counter == layer:Name() then isNameOk = false if counter == '' and sufix ~= '' then counter = 0 end if sufix == '' then sufix = duplicatSufix elseif counter >= 0 then sufix = duplicatSufix..self.counterDelimiter end if counter ~= '' then counter = counter + 1 end break end end newDuplicatedLayerName = targetName..sufix..counter until isNameOk dupLayer:SetName(newDuplicatedLayerName) moho:SetSelLayer(dupLayer) if needToRename then if dupLayer:IsGroupType() then local count = 0 repeat local subLayer = moho.document:LayerByAbsoluteID(count) if subLayer then count = count + 1 if moho:LayerAsGroup(dupLayer):IsLayerValid(subLayer) then if self.swapNames then local tempText1 = 'TEMPTEXT1' local tempText2 = 'TEMPTEXT2' local newName = subLayer:Name() newName = self:ChangeNameString(moho, newName, direction1, tempText1) newName = self:ChangeNameString(moho, newName, direction2, tempText2) newName = self:ChangeNameString(moho, newName, string.lower(direction1), string.lower(tempText1)) newName = self:ChangeNameString(moho, newName, string.lower(direction2), string.lower(tempText2)) newName = self:ChangeNameString(moho, newName, tempText1, direction2) newName = self:ChangeNameString(moho, newName, tempText2, direction1) newName = self:ChangeNameString(moho, newName, string.lower(tempText1), string.lower(direction2)) newName = self:ChangeNameString(moho, newName, string.lower(tempText2), string.lower(direction1)) subLayer:SetName(newName) else subLayer:SetName(self:ChangeNameString(moho, subLayer:Name(), direction1, direction2)) subLayer:SetName(self:ChangeNameString(moho, subLayer:Name(), string.lower(direction1), string.lower(direction2))) end end end until not subLayer end end table.insert(duplicatedLayersList.duplicatedLayers, dupLayer) moho:PlaceLayerInGroup(dupLayer, moho:LayerAsGroup(tempSkelLayer), true, false) end moho:SetSelLayer(tempSkelLayer) local duplicatedBonesNamesList = {} duplicatedBonesNamesList.original = {} duplicatedBonesNamesList.new = {} for i = 0, tempSkel:CountBones()-1 do local bone = tempSkel:Bone(i) local isBoneInSBList = false local newNameFromList = bone:Name() if alt then for p = 1, #self.smartbonesList.originalName do if bone:Name() == self.smartbonesList.originalName[p] and self.smartbonesList.mode[p] == 2 then isBoneInSBList = true newNameFromList = self.smartbonesList.newName[p] end end end table.insert(duplicatedBonesNamesList.original, bone:Name()) local newBoneName = bone:Name() if isBoneInSBList and alt then newBoneName = newNameFromList elseif needToRename then if self.swapNames then local tempText1 = 'TEMPTEXT1' local tempText2 = 'TEMPTEXT2' newBoneName = self:ChangeNameString(moho, bone:Name(), direction1, tempText1) newBoneName = self:ChangeNameString(moho, newBoneName, direction2, tempText2) newBoneName = self:ChangeNameString(moho, newBoneName, tempText1, direction2) newBoneName = self:ChangeNameString(moho, newBoneName, tempText2, direction1) newBoneName = self:ChangeNameString(moho, newBoneName, string.lower(direction1), string.lower(tempText1)) newBoneName = self:ChangeNameString(moho, newBoneName, string.lower(direction2), string.lower(tempText2)) newBoneName = self:ChangeNameString(moho, newBoneName, string.lower(tempText1), string.lower(direction2)) newBoneName = self:ChangeNameString(moho, newBoneName, string.lower(tempText2), string.lower(direction1)) else newBoneName = self:ChangeNameString(moho, bone:Name(), direction1, direction2) newBoneName = self:ChangeNameString(moho, newBoneName, string.lower(direction1)) end end local targetName = newBoneName local counter = '' local isNameOk = true local sufix = '' repeat isNameOk = true for i = 0, mainSkel:CountBones()-1 do local mainSkelBone = mainSkel:Bone(i) if targetName..sufix..counter == mainSkelBone:Name() then isNameOk = false if counter == '' and sufix ~= '' then counter = 0 end if sufix == '' then sufix = duplicatSufix elseif counter >= 0 then sufix = duplicatSufix..self.counterDelimiter end if counter ~= '' then counter = counter + 1 end break end end newBoneName = targetName..sufix..counter until isNameOk bone:SetName(newBoneName) table.insert(duplicatedBonesNamesList.new, newBoneName) end if self.swapNames then self:CleanUpActions(moho, tempSkelLayer, false, isDirectionRight, needToRename, duplicatedBonesNamesList.original) else self:CleanUpActions(moho, tempSkelLayer, true, isDirectionRight, needToRename, duplicatedBonesNamesList.original) end local actionNames = {} for k, layer in ipairs(allDuplicatedLayersList) do if needToRename then if layer:IsBoneType() then local layerSkel = moho:LayerAsBone(layer):Skeleton() if layerSkel ~= tempSkel then for i =0, layerSkel:CountBones()-1 do local bone = layerSkel:Bone(i) if self.swapNames then local tempText1 = 'TEMPTEXT1' local tempText2 = 'TEMPTEXT2' local newName = bone:Name() newName = self:ChangeNameString(moho, newName, direction1, tempText1) newName = self:ChangeNameString(moho, newName, direction2, tempText2) newName = self:ChangeNameString(moho, newName, tempText1, direction2) newName = self:ChangeNameString(moho, newName, tempText2, direction1) newName = self:ChangeNameString(moho, newName, string.lower(direction1), string.lower(tempText1)) newName = self:ChangeNameString(moho, newName, string.lower(direction2), string.lower(tempText2)) newName = self:ChangeNameString(moho, newName, string.lower(tempText1), string.lower(direction2)) newName = self:ChangeNameString(moho, newName, string.lower(tempText2), string.lower(direction1)) bone:SetName(newName) else bone:SetName(self:ChangeNameString(moho, bone:Name(), direction1, direction2)) bone:SetName(self:ChangeNameString(moho, bone:Name(), string.lower(direction1), string.lower(direction2))) end end end end end for n, orLayer in ipairs(allOriginalLayersList) do if self.mohoVersion >= 14 then if layer:GetWarpLayer() == orLayer then layer:SetWarpLayer(allDuplicatedLayersList[n]) end else if layer:GetDistortionMeshLayer() == orLayer then layer:SetDistortionMeshLayer(allDuplicatedLayersList[n]) end end end local layerActionNames = {} for i=0, layer:CountActions()-1 do local actionName = layer:ActionName(i) table.insert(layerActionNames, actionName) end table.insert(actionNames, layerActionNames) end if alt then for p = 1, #self.smartbonesList.originalName do tempSkelLayer:ActivateAction(self.smartbonesList.originalName[p]) end tempSkelLayer:ActivateAction(nil) end local actionsToRemoveList = {} for i=0, tempSkelLayer:CountActions()-1 do local actionName = tempSkelLayer:ActionName(i) local isActionHasBone = false local newBoneName = '' local newName = actionName for o, boneName in pairs(duplicatedBonesNamesList.original) do if actionName == boneName then isActionHasBone = true newBoneName = duplicatedBonesNamesList.new[o] break elseif actionName == boneName..' 2' and skelLayer:IsSmartBoneAction(actionName) then local isActionDouble = false for i = 0, mainSkel:CountBones()-1 do local boneName = mainSkel:Bone(i):Name() if boneName == actionName then isActionDouble = false end end if not isActionDouble then isActionHasBone = true newBoneName = duplicatedBonesNamesList.new[o]..' 2' break end end end local isActionNeedToRemove = false if alt then for p = 1, #self.smartbonesList.originalName do if actionName == self.smartbonesList.originalName[p]..' 2' and self.smartbonesList.mode[p] == 1 then newName = self.smartbonesList.newName[p] elseif actionName == self.smartbonesList.originalName[p]..' 2' and self.smartbonesList.mode[p] == 3 then isActionNeedToRemove = true end end for p = 1, #self.smartbonesList.originalName do if actionName == self.smartbonesList.originalName[p] and self.smartbonesList.mode[p] == 1 then newName = self.smartbonesList.newName[p] elseif actionName == self.smartbonesList.originalName[p] and self.smartbonesList.mode[p] == 3 then isActionNeedToRemove = true end end end if not isActionNeedToRemove then if isActionHasBone then newName = newBoneName end if newName ~= actionName then tempSkelLayer:RenameAction(actionName, newName) end else local isActionNew = true for u, action in pairs(actionsToRemoveList) do if action == actionName then isActionNew = false end end if isActionNew then table.insert(actionsToRemoveList, actionName) end end end if alt then if #actionsToRemoveList > 0 then local count = 0 repeat local layer = moho.document:LayerByAbsoluteID(count) count = count + 1 if layer then if tempSkelLayer:IsLayerValid(layer) or layer == tempSkelLayer then for _,name in ipairs(actionsToRemoveList) do layer:DeleteAction(name) end end end until not layer end end for k = 1, #allDuplicatedLayersList do for i = 1, #actionNames[k] do local actionName = actionNames[k][i] local isActionHasBone = false local newBoneName = '' local newName = actionName for o, boneName in pairs(duplicatedBonesNamesList.original) do if actionName == boneName then isActionHasBone = true newBoneName = duplicatedBonesNamesList.new[o] break end end if isActionHasBone then newName = newBoneName else if needToRename then if self.swapNames then local tempText1 = 'TEMPTEXT1' local tempText2 = 'TEMPTEXT2' newName = self:ChangeNameString(moho, actionName, direction1, tempText1) newName = self:ChangeNameString(moho, newName, direction2, tempText2) newName = self:ChangeNameString(moho, newName, string.lower(direction1), string.lower(tempText1)) newName = self:ChangeNameString(moho, newName, string.lower(direction2), string.lower(tempText2)) newName = self:ChangeNameString(moho, newName, tempText1, direction2) newName = self:ChangeNameString(moho, newName, tempText2, direction1) newName = self:ChangeNameString(moho, newName, string.lower(tempText1), string.lower(direction2)) newName = self:ChangeNameString(moho, newName, string.lower(tempText2), string.lower(direction1)) else newName = self:ChangeNameString(moho, actionName, direction1, direction2) newName = self:ChangeNameString(moho, newName, string.lower(direction1), string.lower(direction2)) end end end if newName ~= actionName then allDuplicatedLayersList[k]:RenameAction(actionName, newName) end end end if originalVitruvianGroup and needToRename then for g=0, tempSkel:CountGroups()-1 do local group = tempSkel:Group(g) local newName if self.swapNames then local tempText1 = 'TEMPTEXT1' local tempText2 = 'TEMPTEXT2' newName = self:ChangeNameString(moho, group:Name(), direction1, tempText1) newName = self:ChangeNameString(moho, newName, direction2, tempText2) newName = self:ChangeNameString(moho, newName, string.lower(direction1), string.lower(tempText1)) newName = self:ChangeNameString(moho, newName, string.lower(direction2), string.lower(tempText2)) newName = self:ChangeNameString(moho, newName, tempText1, direction2) newName = self:ChangeNameString(moho, newName, tempText2, direction1) newName = self:ChangeNameString(moho, newName, string.lower(tempText1), string.lower(direction2)) newName = self:ChangeNameString(moho, newName, string.lower(tempText2), string.lower(direction1)) else newName = self:ChangeNameString(moho, group:Name(), direction1, direction2) end if group:Name() ~= newName then group:SetName(newName) end end end tempSkel:SelectAll() moho:Copy() moho:SetSelLayer(skelLayer) mainSkel:SelectNone() moho:Paste() local allDuplicatedLayers = {} for k, dupLayer in ipairs(duplicatedLayersList.duplicatedLayers) do moho:PlaceLayerInGroup(dupLayer, moho:LayerAsGroup(skelLayer), true, false) if dupLayer:IsGroupType() then local count = 0 repeat local layer = moho.document:LayerByAbsoluteID(count) count = count + 1 if layer then if moho:LayerAsGroup(dupLayer):IsLayerValid(layer) then table.insert(allDuplicatedLayers, layer) elseif layer == dupLayer then table.insert(allDuplicatedLayers, layer) end end until not layer else table.insert(allDuplicatedLayers, dupLayer) end end for k, dupLayer in ipairs(allDuplicatedLayers) do if dupLayer:ControllingSkeleton() == mainSkel then if moho:LayerAsVector(dupLayer) then local mesh = moho:LayerAsVector(dupLayer):Mesh() for i=0, mesh:CountPoints()-1 do local point = mesh:Point(i) for b = 1, #oiginalBonesList do local bone = oiginalBonesList[b] if point.fParent >= 0 and point.fParent == mainSkel:BoneID(bone) then local newBoneID = duplicatedBonesListID[b] + originalTotalBonesNum point.fParent = newBoneID break end end end end local bonesInFlexiBoneSubset = {} for u = 1, #oiginalBonesList do local bone = oiginalBonesList[u] if dupLayer:IsIncludedInFlexiBoneSubset(mainSkel:BoneID(bone)) then local newBoneID = duplicatedBonesListID[u] + originalTotalBonesNum table.insert(bonesInFlexiBoneSubset, newBoneID) -- break end end for u = 1, #oiginalBonesList do local bone = oiginalBonesList[u] if dupLayer:LayerParentBone() == mainSkel:BoneID(bone) then local newBoneID = duplicatedBonesListID[u] + originalTotalBonesNum dupLayer:SetLayerParentBone(newBoneID) break end end dupLayer:ClearFlexiBoneSubset() for s, boneId in ipairs(bonesInFlexiBoneSubset) do dupLayer:AddToFlexiBoneSubset(boneId) end end end for b = 1, #oiginalBonesList do local bone = oiginalBonesList[b] for k, mainBone in ipairs(mainBones) do if mainBone == bone then local duplicatedMainBone = mainSkel:Bone(duplicatedBonesListID[b] + originalTotalBonesNum) duplicatedMainBone.fParent = mainBone.fParent duplicatedMainBone.fAnimParent:SetValue(0, mainBone.fParent) duplicatedMainBone.fAnimPos:SetValue(0, mainBone.fAnimPos:GetValue(0)) duplicatedMainBone.fAnimAngle:SetValue(0, mainBone.fAnimAngle:GetValue(0)) end end if selectedBone == bone then local duplicatedMainBone = mainSkel:Bone(duplicatedBonesListID[b] + originalTotalBonesNum) mainSkel:SelectNone() duplicatedMainBone.fSelected = true end end if self.transformTargetBones then for i = originalTotalBonesNum, mainSkel:CountBones() - 1 do local bone = mainSkel:Bone(i) for actionID = 0, bone.fTargetBone:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVal(bone.fTargetBone:Action(actionID)) if actionChannel ~= nil then for keyID = 0, actionChannel:CountKeys() - 1 do local actionFrame = actionChannel:GetKeyWhen(keyID) if (actionFrame > 0) then local targetId = actionChannel:GetValue(actionFrame) for t = 1, #oiginalBonesList do local targetBoneCandidat = oiginalBonesList[t] if mainSkel:Bone(targetId) == targetBoneCandidat then local newTargetBoneID = duplicatedBonesListID[t] + originalTotalBonesNum actionChannel:SetValue(actionFrame, newTargetBoneID) local pastedTargetBone = mainSkel:Bone(newTargetBoneID) break end end end end end end end end for d=0, tempSkel:CountBones()-1 do tempSkel:DeleteBone(0) end local actionsToRemove = {} for i=0, tempSkelLayer:CountActions()-1 do local actionName = tempSkelLayer:ActionName(i) table.insert(actionsToRemove, actionName) end for l, action in ipairs(actionsToRemove) do tempSkelLayer:DeleteAction(action) end moho:DeleteLayer(tempSkelLayer) moho:SetSelLayer(duplicatedLayersList.duplicatedLayers[1]) for i, layer in ipairs(duplicatedLayersList.duplicatedLayers) do layer:SetSecondarySelection(true) end moho:SetCurFrame(1) moho:SetCurFrame(0) moho.view:DrawMe() moho:UpdateUI() moho.layer:UpdateCurFrame() end function MR_TransformRigTool:CopyBodypart(moho, alt) local mainSkel = self:FindSkeleton(moho) self:FindSkeletonLayer(moho) local skelLayer = self.skelLayer if not mainSkel or not skelLayer then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Copy bodypart alert 1'), self:Localize('Copy bodypart alert 2'), "", 'OK') return end local isAnotherSkelSelected = false local skelLayerToCopy local extraSkelCounter = 0 for l = 0, moho.document:CountSelectedLayers()-1 do local layer = moho.document:GetSelectedLayer(l) if layer == skelLayer then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Copy bodypart alert 1'), self:Localize('Copy bodypart alert 2'), "", 'OK') return elseif layer:IsBoneType() and not moho:LayerAsGroup(skelLayer):IsLayerValid(layer) then isAnotherSkelSelected = true skelLayerToCopy = layer extraSkelCounter = extraSkelCounter + 1 end end if skelLayerToCopy == nil or extraSkelCounter ~= 1 then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Copy bodypart alert 1'), self:Localize('Copy bodypart alert 2'), "", 'OK') return end local skelToCopy = moho:LayerAsBone(skelLayerToCopy):Skeleton() self.mainSkelSelectedBones = self:CountSelectedBones(moho, mainSkel) if self.mainSkelSelectedBones ~= 1 or not isAnotherSkelSelected then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Copy bodypart alert 1'), self:Localize('Copy bodypart alert 2'), "", 'OK') return end local topLayer = moho.document:Layer(moho.document:CountLayers()-1) moho.document:SetDirty() moho.document:PrepUndo('', nil) local currentLayer = moho.layer local duplicatedLayersList = {} duplicatedLayersList.originalLayers = {} duplicatedLayersList.duplicatedLayers = {} for l = 0, moho.document:CountSelectedLayers()-1 do local originalLayer = moho.document:GetSelectedLayer(l) if originalLayer ~= skelLayerToCopy and not originalLayer:IsAncestorSelected() then table.insert(duplicatedLayersList.originalLayers, originalLayer) end end local selectedBoneId = mainSkel:SelectedBoneID() local selectedBone = mainSkel:Bone(selectedBoneId) local originalVitruvianGroup = nil local mainBones = {} if self.transformTargetBones then self:FindTargetBones(moho, selectedBone, true) end selectedBone.fTempPos = selectedBone.fAnimPos:GetValue(0) selectedBone.fTempAngle = selectedBone.fAnimAngle:GetValue(0) if self.isVitruvianBonesAvaible then if mainSkel:IsBoneInAGroup(selectedBoneId) and self.transformVitruvianBones then originalVitruvianGroup = mainSkel:GroupForBone(selectedBoneId, false) for i=0, originalVitruvianGroup:CountBones()-1 do local bone = originalVitruvianGroup:Bone(i) bone.fSelected = true table.insert(mainBones, bone) if self.transformTargetBones then self:FindTargetBones(moho, bone, false) end end else table.insert(mainBones, selectedBone) end end if self.transformTargetBones then for n, targetBone in ipairs(self.targetBonesList) do targetBone.fSelected = true end end local hiddenBonesList = {} for i=0, mainSkel:CountBones()-1 do local bone = mainSkel:Bone(i) if mainSkel:IsAncestorSelected(i) then if bone.fHidden then bone.fHidden = false table.insert(hiddenBonesList, bone) end bone.fSelected = true end end if alt then self.duplicateActionsMode = 2 if not self:FindSmartbones(moho, mainSkel, skelToCopy, selectedBone, skelLayerToCopy) then mainSkel:SelectNone() selectedBone.fSelected = true return end for i = 1, #MR_TransformRigTool.smartbonesList.originalName do if MR_TransformRigTool.smartbonesList.mode[i] == 2 then local bone = mainSkel:BoneByName(MR_TransformRigTool.smartbonesList.originalName[i]) bone.fSelected = true end end end moho:SetSelLayer(skelLayer) local originalTotalBonesNum = skelToCopy:CountBones() local oiginalBonesList = {} local duplicatedBonesListID = {} for i=0, mainSkel:CountBones()-1 do local bone = mainSkel:Bone(i) if bone.fSelected then table.insert(oiginalBonesList, bone) end end local isMainBonePin = false if selectedBone.fLength == 0 then isMainBonePin = true selectedBone.fLength = 0.1 end moho:Copy() if isMainBonePin then selectedBone.fLength = 0 end moho:SetSelLayer(topLayer) local tempSkelLayer = moho:CreateNewLayer(MOHO.LT_BONE, false) local tempSkel = moho:LayerAsBone(tempSkelLayer):Skeleton() tempSkelLayer:SetName('Temp Layer') moho:Paste() for o, origBone in ipairs(oiginalBonesList) do for i =0, tempSkel:CountBones()-1 do local bone = tempSkel:Bone(i) if isMainBonePin then if selectedBone:Name() == bone:Name() then bone.fLength = 0 end end if origBone:Name() == bone:Name() then table.insert(duplicatedBonesListID, i) break end end end local allOriginalLayersList = {} local allDuplicatedLayersList = {} local duplicatSufix = self.duplicatedBodypartSuffix for k, origLayer in ipairs(duplicatedLayersList.originalLayers) do if origLayer:IsGroupType() then local tempList = self:ScanLayersReccursion(moho, origLayer) for t, templayer in ipairs(tempList) do table.insert(allOriginalLayersList, templayer) end else table.insert(allOriginalLayersList, origLayer) end local dupLayer = moho.document:DuplicateLayer(origLayer) if dupLayer:IsGroupType() then local tempList = self:ScanLayersReccursion(moho, dupLayer) for t, templayer in ipairs(tempList) do table.insert(allDuplicatedLayersList, templayer) end else table.insert(allDuplicatedLayersList, dupLayer) end local newDuplicatedLayerName = origLayer:Name() local isNameOk = true local targetName = newDuplicatedLayerName local counter = '' local sufix = '' repeat isNameOk = true for i=0, skelLayerToCopy:CountLayers()-1 do local layer = skelLayerToCopy:Layer(i) if targetName..sufix..counter == layer:Name() then isNameOk = false if counter == '' and sufix ~= '' then counter = 0 end if sufix == '' then sufix = duplicatSufix elseif counter >= 0 then sufix = duplicatSufix..self.counterDelimiter end if counter ~= '' then counter = counter + 1 end break end end newDuplicatedLayerName = targetName..sufix..counter until isNameOk dupLayer:SetName(newDuplicatedLayerName) moho:SetSelLayer(dupLayer) table.insert(duplicatedLayersList.duplicatedLayers, dupLayer) moho:PlaceLayerInGroup(dupLayer, moho:LayerAsGroup(tempSkelLayer), true, false) end moho:SetSelLayer(tempSkelLayer) for s=0, tempSkel:CountBones()-1 do local bone = tempSkel:Bone(s) if bone.fParent < 0 then local originalBone = mainSkel:BoneByName(bone:Name()) local deltaAngle = bone.fAnimAngle:GetValue(0) - originalBone.fAnimAngle:GetValue(0) for act = 0, tempSkelLayer:CountActions()-1 do local actionName = tempSkelLayer:ActionName(act) local actionChannelPos = bone.fAnimPos:ActionByName(actionName) if actionChannelPos and actionChannelPos:Duration() > 0 then for i = 1, actionChannelPos:CountKeys()-1 do local keyTime = actionChannelPos:GetKeyWhen(i) if keyTime > 0 then tempSkelLayer:ActivateAction(actionName) moho:SetCurFrame(keyTime) local parentOffsetZero = LM.Vector2:new_local() local bonePosFrameZero = LM.Vector2:new_local() bonePosFrameZero:Set(bone.fAnimPos:GetValue(0)) local oldMatrix = LM.Matrix:new_local() oldMatrix:Identity() local bonePos = LM.Vector2:new_local() bonePos:Set(bone.fAnimPos:GetValue(keyTime)) local origBoneGlobalPos = LM.Vector2:new_local() origBoneGlobalPos:Set(originalBone.fAnimPos:GetValue(0)) if originalBone.fParent >= 0 then local originalParent = mainSkel:Bone(originalBone.fParent) oldMatrix:Set(originalParent.fRestMatrix) originalParent.fRestMatrix:Transform(origBoneGlobalPos) oldMatrix:Transform(bonePos) end local bonePosDifFrameZero = LM.Vector2:new_local() bonePosDifFrameZero = origBoneGlobalPos - bonePosFrameZero local localBonePosFrameZero = LM.Vector2:new_local() localBonePosFrameZero:Set(bone.fAnimPos:GetValue(0)) bonePos = bonePos - bonePosDifFrameZero bone.fAnimPos:SetValue(keyTime, bonePos) tempSkelLayer:ActivateAction(nil) end end end end for act = 0, bone.fAnimAngle:CountActions()-1 do local actionChannelAngle = moho:ChannelAsAnimVal(bone.fAnimAngle:Action(act)) if actionChannelAngle and actionChannelAngle:Duration() > 0 then for i=1, actionChannelAngle:CountKeys()-1 do local keyTime = actionChannelAngle:GetKeyWhen(i) if keyTime > 0 then actionChannelAngle:SetValue(keyTime, actionChannelAngle:GetValue(keyTime) + deltaAngle) end end end end end end self:CleanUpActions(moho, tempSkelLayer, false, false, true) local actionNames = {} for k, layer in ipairs(allDuplicatedLayersList) do for n, orLayer in ipairs(allOriginalLayersList) do if self.mohoVersion >= 14 then if layer:GetWarpLayer() == orLayer then layer:SetWarpLayer(allDuplicatedLayersList[n]) end else if layer:GetDistortionMeshLayer() == orLayer then layer:SetDistortionMeshLayer(allDuplicatedLayersList[n]) end end end local layerActionNames = {} for i=0, layer:CountActions()-1 do local actionName = layer:ActionName(i) table.insert(layerActionNames, actionName) end table.insert(actionNames, layerActionNames) end for b, bone in ipairs(hiddenBonesList) do bone.fHidden = true tempSkel:BoneByName(bone:Name()).fHidden = true end local duplicatedBonesNamesList = {} duplicatedBonesNamesList.original = {} duplicatedBonesNamesList.new = {} for s=0, tempSkel:CountBones()-1 do local bone = tempSkel:Bone(s) local isBoneInSBList = false local newNameFromList = bone:Name() if alt then for p = 1, #self.smartbonesList.originalName do if bone:Name() == self.smartbonesList.originalName[p] and self.smartbonesList.mode[p] == 2 then isBoneInSBList = true newNameFromList = self.smartbonesList.newName[p] end end end table.insert(duplicatedBonesNamesList.original, bone:Name()) local newBoneName = bone:Name() if isBoneInSBList and alt then newBoneName = newNameFromList end local targetName = newBoneName local counter = '' local isNameOk = true local sufix = '' repeat isNameOk = true for i = 0, skelToCopy:CountBones()-1 do local mainSkelBone = skelToCopy:Bone(i) if targetName..sufix..counter == mainSkelBone:Name() then isNameOk = false if counter == '' and sufix ~= '' then counter = 0 end if sufix == '' then sufix = duplicatSufix..' ' end if counter ~= '' then counter = counter + 1 end break end end newBoneName = targetName..sufix..counter until isNameOk bone:SetName(newBoneName) table.insert(duplicatedBonesNamesList.new, newBoneName) end if alt then for p = 1, #self.smartbonesList.originalName do tempSkelLayer:ActivateAction(self.smartbonesList.originalName[p]) end tempSkelLayer:ActivateAction(nil) end local actionsToRemoveList = {} for i=0, tempSkelLayer:CountActions()-1 do local actionName = tempSkelLayer:ActionName(i) local isActionHasBone = false local newBoneName = '' local newName = actionName for o, boneName in pairs(duplicatedBonesNamesList.original) do if actionName == boneName then isActionHasBone = true newBoneName = duplicatedBonesNamesList.new[o] break elseif actionName == boneName..' 2' and skelLayer:IsSmartBoneAction(actionName) then local isActionDouble = false for i = 0, mainSkel:CountBones()-1 do local boneName = mainSkel:Bone(i):Name() if boneName == actionName then isActionDouble = true end end if not isActionDouble then isActionHasBone = true newBoneName = duplicatedBonesNamesList.new[o]..' 2' break end end end local isActionNeedToRemove = false if alt then for p = 1, #self.smartbonesList.originalName do if actionName == self.smartbonesList.originalName[p]..' 2' and self.smartbonesList.mode[p] == 1 then newName = self.smartbonesList.newName[p]..' 2' elseif actionName == self.smartbonesList.originalName[p]..' 2' and self.smartbonesList.mode[p] == 3 then isActionNeedToRemove = true end end for p = 1, #self.smartbonesList.originalName do if actionName == self.smartbonesList.originalName[p] and self.smartbonesList.mode[p] == 1 then newName = self.smartbonesList.newName[p] elseif actionName == self.smartbonesList.originalName[p] and self.smartbonesList.mode[p] == 3 then isActionNeedToRemove = true end end end if not isActionNeedToRemove then if isActionHasBone then newName = newBoneName end if newName ~= actionName then tempSkelLayer:RenameAction(actionName, newName) end else local isActionNew = true for u, action in pairs(actionsToRemoveList) do if action == actionName then isActionNew = false end end if isActionNew then table.insert(actionsToRemoveList, actionName) end end end if alt then if #actionsToRemoveList > 0 then local count = 0 repeat local layer = moho.document:LayerByAbsoluteID(count) count = count + 1 if layer then if tempSkelLayer:IsLayerValid(layer) or layer == tempSkelLayer then for _,name in ipairs(actionsToRemoveList) do layer:DeleteAction(name) end end end until not layer end end for k = 1, #allDuplicatedLayersList do for i = 1, #actionNames[k] do local actionName = actionNames[k][i] local isActionHasBone = false local newBoneName = '' local newName = actionName for o, boneName in pairs(duplicatedBonesNamesList.original) do if actionName == boneName then isActionHasBone = true newBoneName = duplicatedBonesNamesList.new[o] break end end if isActionHasBone then newName = newBoneName end if newName ~= actionName then allDuplicatedLayersList[k]:RenameAction(actionName, newName) end end end tempSkel:SelectAll() moho:Copy() moho:SetSelLayer(skelLayerToCopy) skelToCopy:SelectNone() moho:Paste() local allDuplicatedLayers = {} for k, dupLayer in ipairs(duplicatedLayersList.duplicatedLayers) do moho:PlaceLayerInGroup(dupLayer, moho:LayerAsGroup(skelLayerToCopy), true, false) if dupLayer:IsGroupType() then local count = 0 repeat local layer = moho.document:LayerByAbsoluteID(count) count = count + 1 if layer then if moho:LayerAsGroup(dupLayer):IsLayerValid(layer) then table.insert(allDuplicatedLayers, layer) elseif layer == dupLayer then table.insert(allDuplicatedLayers, layer) end end until not layer else table.insert(allDuplicatedLayers, dupLayer) end end for k, dupLayer in ipairs(allDuplicatedLayers) do if dupLayer:ControllingSkeleton() == skelToCopy then if moho:LayerAsVector(dupLayer) then local mesh = moho:LayerAsVector(dupLayer):Mesh() for i=0, mesh:CountPoints()-1 do local point = mesh:Point(i) for b = 1, #oiginalBonesList do local bone = oiginalBonesList[b] if point.fParent >= 0 and point.fParent == mainSkel:BoneID(bone) then local newBoneID = duplicatedBonesListID[b] + originalTotalBonesNum point.fParent = newBoneID break end end end end local bonesInFlexiBoneSubset = {} for u = 1, #oiginalBonesList do local bone = oiginalBonesList[u] if dupLayer:IsIncludedInFlexiBoneSubset(mainSkel:BoneID(bone)) then local newBoneID = duplicatedBonesListID[u] + originalTotalBonesNum table.insert(bonesInFlexiBoneSubset, newBoneID) -- break end end for u = 1, #oiginalBonesList do local bone = oiginalBonesList[u] if dupLayer:LayerParentBone() == mainSkel:BoneID(bone) then local newBoneID = duplicatedBonesListID[u] + originalTotalBonesNum dupLayer:SetLayerParentBone(newBoneID) break end end dupLayer:ClearFlexiBoneSubset() for s, boneId in ipairs(bonesInFlexiBoneSubset) do dupLayer:AddToFlexiBoneSubset(boneId) end end end for b = 1, #oiginalBonesList do local bone = oiginalBonesList[b] if selectedBone == bone then local duplicatedMainBone = skelToCopy:Bone(duplicatedBonesListID[b] + originalTotalBonesNum) skelToCopy:SelectNone() duplicatedMainBone.fSelected = true end end if self.transformTargetBones then for i = originalTotalBonesNum, skelToCopy:CountBones() - 1 do local bone = skelToCopy:Bone(i) for actionID = 0, bone.fTargetBone:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVal(bone.fTargetBone:Action(actionID)) if actionChannel ~= nil then for keyID = 0, actionChannel:CountKeys() - 1 do local actionFrame = actionChannel:GetKeyWhen(keyID) if (actionFrame > 0) then local targetId = actionChannel:GetValue(actionFrame) for t = 1, #oiginalBonesList do local targetBoneCandidat = oiginalBonesList[t] if mainSkel:Bone(targetId) == targetBoneCandidat then local newTargetBoneID = duplicatedBonesListID[t] + originalTotalBonesNum actionChannel:SetValue(actionFrame, newTargetBoneID) local pastedTargetBone = skelToCopy:Bone(newTargetBoneID) break end end end end end end end end for d=0, tempSkel:CountBones()-1 do tempSkel:DeleteBone(0) end local actionsToRemove = {} for i=0, tempSkelLayer:CountActions()-1 do local actionName = tempSkelLayer:ActionName(i) table.insert(actionsToRemove, actionName) end for l, action in ipairs(actionsToRemove) do tempSkelLayer:DeleteAction(action) end mainSkel:SelectNone() selectedBone.fSelected = true moho:DeleteLayer(tempSkelLayer) moho:SetSelLayer(duplicatedLayersList.duplicatedLayers[1]) for i, layer in ipairs(duplicatedLayersList.duplicatedLayers) do layer:SetSecondarySelection(true) end moho:SetCurFrame(1) moho:SetCurFrame(0) moho.view:DrawMe() moho:UpdateUI() moho.layer:UpdateCurFrame() end function MR_TransformRigTool:ChangeNameString(moho, name, t1, t2, viceVersa) if not name then return end local viceVersa = viceVersa or false local text1 = t1 or 'R' local text2 = t2 or 'L' local layerName = name if string.gsub(layerName, "% "..text1.." ", " "..text2.." ") ~= layerName then layerName = string.gsub(layerName, "% "..text1.." ", " "..text2.." ") elseif string.gsub(layerName, "% "..text2.." ", " "..text1.." ") ~= layerName and viceVersa then layerName = string.gsub(layerName, "% "..text2.." ", " "..text1.." ") end if string.gsub(layerName, "%_"..text1.."_", "_"..text2.."_") ~= layerName then layerName = string.gsub(layerName, "%_"..text1.."_", "_"..text2.."_") elseif string.gsub(layerName, "%_"..text2.."_", "_"..text1.."_") ~= layerName and viceVersa then layerName = string.gsub(layerName, "%_"..text2.."_", "_"..text1.."_") end if string.gsub(layerName, "% "..text1.."_", " "..text2.."_") ~= layerName then layerName = string.gsub(layerName, "% "..text1.."_", " "..text2.."_") elseif string.gsub(layerName, "% "..text2.."_", " "..text1.."_") ~= layerName and viceVersa then layerName = string.gsub(layerName, "% "..text2.."_", " "..text1.."_") end if string.gsub(layerName, "%_"..text1.." ", "_"..text2.." ") ~= layerName then layerName = string.gsub(layerName, "%_"..text1.." ", "_"..text2.." ") elseif string.gsub(layerName, "%_"..text2.." ", "_"..text1.." ") ~= layerName and viceVersa then layerName =string.gsub(layerName, "%_"..text2.." ", "_"..text1.." ") end if string.sub(layerName, layerName:len() - text1:len()) == " "..text1 then layerName = string.sub(layerName, 0, -text1:len()-2).." "..text2 elseif string.sub(layerName, layerName:len() - text2:len()) == " "..text2 and viceVersa then layerName = string.sub(layerName, 0, -text2:len()-2).." "..text1 end if string.sub(layerName, layerName:len() - text1:len()) == "_"..text1 then layerName = string.sub(layerName, 0, -text1:len()-2).."_"..text2 elseif string.sub(layerName, layerName:len() - text2:len()) == "_"..text2 and viceVersa then layerName = string.sub(layerName, 0, -text2:len()-2).."_"..text1 end if string.sub(layerName, 0, text1:len()+1) == text1.." " then layerName = text2.." "..string.sub(layerName, text1:len() + 2, layerName:len()) elseif string.sub(layerName, 0, text2:len() + 1) == text2.." " and viceVersa then layerName = text1.." "..string.sub(layerName, text2:len() + 2, layerName:len()) end if string.sub(layerName, 0, text1:len() + 1) == text1.."_" then layerName = text2.."_"..string.sub(layerName, text1:len() + 2, layerName:len()) elseif string.sub(layerName, 0, text2:len() + 1) == text2.."_" and viceVersa then layerName = text1.."_"..string.sub(layerName, text2:len() + 2, layerName:len()) end return layerName end function MR_TransformRigTool:CleanUpActions(moho, group, clenupDirection, direction, considerDirection, bonesNamesList) local count = 0 local direction1 local direction2 if self.directionMode then if direction then direction1 = 'R' direction2 = 'L' else direction1 = 'L' direction2 = 'R' end elseif self.customMode then direction1 = self.customModeInput1 direction2 = self.customModeInput2 elseif self.suffixMode then direction1 = '' direction2 = '' end repeat local layer = moho.document:LayerByAbsoluteID(count) count = count + 1 if layer then local actionsToRemove = {} if group:IsLayerValid(layer) or layer == group then for a=0, layer:CountActions()-1 do local actionName = layer:ActionName(a) if layer:ActionDuration(actionName) < 1 then table.insert(actionsToRemove, actionName) elseif self:ChangeNameString(moho, actionName, direction2, direction1) ~= actionName and clenupDirection and considerDirection then table.insert(actionsToRemove, actionName) elseif self:ChangeNameString(moho, actionName, string.lower(direction2), string.lower(direction1)) ~= actionName and clenupDirectionthen and considerDirection then table.insert(actionsToRemove, actionName) end end if #actionsToRemove > 0 then for _,name in ipairs(actionsToRemove) do if bonesNamesList ~= nil then local isActionHasBone = false for o, boneName in pairs(bonesNamesList) do if name == boneName then isActionHasBone = true break end end if not isActionHasBone then layer:DeleteAction(name) end else layer:DeleteAction(name) end end end end end until not layer end function MR_TransformRigTool:CollectLayersFromGroup(moho, group, insertSelf) local layerList = {} local count = 0 repeat local layer = moho.document:LayerByAbsoluteID(count) count = count + 1 if layer then if group:IsLayerValid(layer) then table.insert(layerList, layer) elseif layer == group and insertSelf then table.insert(layerList, layer) end end until not layer return layerList end function MR_TransformRigTool:CollectLayersFromSelectedGroups(moho, insertSelf) local layerList = {} local count = 0 repeat local layer = moho.document:LayerByAbsoluteID(count) count = count + 1 if layer then if layer:IsAncestorSelected() then table.insert(layerList, layer) elseif layer:SecondarySelection() and insertSelf then table.insert(layerList, layer) end end until not layer return layerList end function MR_TransformRigTool:ScanLayersReccursion(moho, group) for i, l in ipairs(self.templayersList) do self.templayersList[i] = nil end if group:IsGroupType() then table.insert(self.templayersList, group) self:ScanGroupReccursion(moho, group) end return self.templayersList end function MR_TransformRigTool:ScanGroupReccursion(moho, group) local groupLayer = moho:LayerAsGroup(group) for i=0, groupLayer:CountLayers()-1 do local layer = group:Layer(i) if layer:IsGroupType() then table.insert(self.templayersList, layer) self:ScanGroupReccursion(moho, layer) -- recursion else table.insert(self.templayersList, layer) end end end function MR_TransformRigTool:TranslateOrigins(moho, offset) for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local layerScale = LM.Vector3:new_local() layerScale:Set(layer.fScale.value) if (layerScale.x == 1 and layerScale.y == 1 and layerScale.z == 1 and layer.fRotationZ.value == 0) or not self.protectLayerTransformation then if not self:CheckLayerParentalFlip(moho, layer) then local newOriginPos = LM.Vector2:new_local() local origin = layer:Origin() local newOffset = LM.Vector2:new_local() newOffset:Set(offset) local zeroOffset = LM.Vector2:new_local() newOffset:Set(MR_Utilities:GetLocalPos(moho, layer, newOffset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, layer, zeroOffset, false)) newOffset:Set(newOffset - zeroOffset) newOriginPos:Set(origin + newOffset) self:SetOrigin(moho, layer, newOriginPos) end end end for k, id in ipairs(self.groupsToChange.group) do local layer = moho.document:LayerByAbsoluteID(id) local layerScale = LM.Vector3:new_local() layerScale:Set(layer.fScale.value) if (layerScale.x == 1 and layerScale.y == 1 and layerScale.z == 1 and layer.fRotationZ.value == 0) or not self.protectLayerTransformation then if not self:CheckLayerParentalFlip(moho, layer) then local newOriginPos = LM.Vector2:new_local() local origin = layer:Origin() local newOffset = LM.Vector2:new_local() newOffset:Set(offset) local zeroOffset = LM.Vector2:new_local() newOffset:Set(MR_Utilities:GetLocalPos(moho, layer, newOffset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, layer, zeroOffset, false)) newOffset:Set(newOffset - zeroOffset) newOriginPos:Set(origin + newOffset) self:SetOrigin(moho, layer, newOriginPos) end end end end function MR_TransformRigTool:ScaleOrigins(moho, center, scaling) for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local layerScale = LM.Vector3:new_local() local layerAngle = layer.fRotationZ.value layerScale:Set(layer.fScale.value) if (layerScale.x == 1 and layerScale.y == 1 and layerScale.z == 1 and layer.fRotationZ.value == 0) or not self.protectLayerTransformation then local centerVec = LM.Vector2:new_local() centerVec:Set(center) centerVec = MR_Utilities:GetLocalPos(moho, layer, centerVec, false) --use global pos local dif = LM.Vector2:new_local() local newOriginPos = LM.Vector2:new_local() local origin = layer:Origin() dif:Set(origin - centerVec) newOriginPos:Set((dif * scaling.x) + centerVec) self:SetOrigin(moho, layer, newOriginPos) end end for k, id in ipairs(self.groupsToChange.group) do local layer = moho.document:LayerByAbsoluteID(id) local layerScale = LM.Vector3:new_local() layerScale:Set(layer.fScale.value) if (layerScale.x == 1 and layerScale.y == 1 and layerScale.z == 1 and layer.fRotationZ.value == 0) or not self.protectLayerTransformation then local centerVec = LM.Vector2:new_local() centerVec:Set(self.lastCenter) centerVec = MR_Utilities:GetLocalPos(moho, layer, centerVec, false) --use global pos local dif = LM.Vector2:new_local() local newOriginPos = LM.Vector2:new_local() local origin = layer:Origin() dif:Set(origin - centerVec) newOriginPos:Set((dif * scaling.x) + centerVec) self:SetOrigin(moho, layer, newOriginPos) end end end function MR_TransformRigTool:RotateOrigins(moho, center, angle) for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) if layer:GetFollowingLayer() == nil and self.followPathAdaptation or not self.followPathAdaptation then local layerScale = LM.Vector3:new_local() layerScale:Set(layer.fScale.value) local localAngle = angle if self:CheckLayerParentalFlip(moho, layer, true) then localAngle = -localAngle end if (layerScale.x == 1 and layerScale.y == 1 and layerScale.z == 1 and layer.fRotationZ.value == 0) or not self.protectLayerTransformation then local centerVec = LM.Vector2:new_local() centerVec:Set(center) centerVec = MR_Utilities:GetLocalPos(moho, layer, centerVec, false) --use global pos local dif = LM.Vector2:new_local() local newOriginPos = LM.Vector2:new_local() local origin = layer:Origin() dif:Set(origin - centerVec) local px = dif.x * math.cos(localAngle) - dif.y * math.sin(localAngle) local py = dif.x * math.sin(localAngle) + dif.y * math.cos(localAngle) newOriginPos:Set(px + centerVec.x, py + centerVec.y) self:SetOrigin(moho, layer, newOriginPos) end end end for k, id in ipairs(self.groupsToChange.group) do local layer = moho.document:LayerByAbsoluteID(id) local layerScale = LM.Vector3:new_local() layerScale:Set(layer.fScale.value) local localAngle = angle if self:CheckLayerParentalFlip(moho, layer, true) then localAngle = -localAngle end if (layerScale.x == 1 and layerScale.y == 1 and layerScale.z == 1 and layer.fRotationZ.value == 0) or not self.protectLayerTransformation then local centerVec = LM.Vector2:new_local() centerVec:Set(center) centerVec = MR_Utilities:GetLocalPos(moho, layer, centerVec, false) --use global pos local dif = LM.Vector2:new_local() local newOriginPos = LM.Vector2:new_local() local origin = layer:Origin() dif:Set(origin - centerVec) local px = dif.x * math.cos(angle) - dif.y * math.sin(angle) local py = dif.x * math.sin(angle) + dif.y * math.cos(angle) newOriginPos:Set(px + centerVec.x, py + centerVec.y) self:SetOrigin(moho, layer, newOriginPos) end end end function MR_TransformRigTool:DuplicateAndFlipSmarbone(moho) local mainSkel = self:FindSkeleton(moho) self:FindSkeletonLayer(moho) local skelLayer = self.skelLayer if not mainSkel or not skelLayer then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Duplicate smartbone alert 1'), '', "", 'OK') return end self.mainSkelSelectedBones = self:CountSelectedBones(moho, mainSkel) if self.mainSkelSelectedBones ~= 1 then local infoAlert = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('Duplicate smartbone alert 1'), self:Localize('Duplicate smartbone alert 2'), "", 'OK') return end local topLayer = moho.document:Layer(moho.document:CountLayers()-1) local isDirectionRight = true local direction1 local direction2 moho:SetSelLayer(skelLayer) local selectedBoneId = mainSkel:SelectedBoneID() local selectedBone = mainSkel:Bone(selectedBoneId) local selectedBoneName = selectedBone:Name() local customName = false local dlog = MR_RenameSmartBoneDialog:new(moho, selectedBoneName) if (dlog:DoModal() == LM.GUI.MSG_CANCEL) then return end if self.directionSmartbone then if self.rDirectionSmartbone then isDirectionRight = true direction1 = 'R' direction2 = 'L' elseif self.lDirectionSmartbone then isDirectionRight = false direction1 = 'L' direction2 = 'R' end elseif self.renameSmartbone then customName = true end moho.document:SetDirty() moho.document:PrepUndo(nil) local currentLayer = moho.layer moho:Copy() moho:SetSelLayer(topLayer) local tempSkelLayer = moho:CreateNewLayer(MOHO.LT_BONE, false) local tempSkel = moho:LayerAsBone(tempSkelLayer):Skeleton() tempSkelLayer:SetName('Temp Layer') moho:SetSelLayer(tempSkelLayer) moho:Paste() local tempDuplicatedBone = tempSkel:Bone(0) local newBoneName = '' if customName then newBoneName = self.newSmartBoneName else newBoneName = self:ChangeNameString(moho, tempDuplicatedBone:Name(), direction1, direction2) newBoneName = self:ChangeNameString(moho, newBoneName, string.lower(direction1), string.lower(direction2)) end local duplicatSufix = self.duplicatedBodypartSuffix local targetName = newBoneName local counter = '' local isNameOk = true local sufix = '' repeat isNameOk = true for i = 0, mainSkel:CountBones()-1 do local mainSkelBone = mainSkel:Bone(i) if targetName..sufix..counter == mainSkelBone:Name() then isNameOk = false if counter == '' and sufix ~= '' then counter = 0 end if sufix == '' then sufix = duplicatSufix elseif counter >= 0 then sufix = duplicatSufix..self.counterDelimiter end if counter ~= '' then counter = counter + 1 end break end end newBoneName = targetName..sufix..counter until isNameOk tempDuplicatedBone:SetName(newBoneName) self:CleanUpActions(moho, tempSkelLayer, true, isDirectionRight, nil) local actionNames = {} for i=0, tempSkelLayer:CountActions()-1 do local actionName = tempSkelLayer:ActionName(i) if selectedBoneName == actionName then if newBoneName ~= actionName then tempSkelLayer:RenameAction(actionName, newBoneName) break end end end for i=0, tempSkelLayer:CountActions()-1 do local actionName = tempSkelLayer:ActionName(i) if selectedBoneName..' 2' == actionName then if newBoneName..' 2' ~= actionName then tempSkelLayer:RenameAction(actionName, newBoneName..' 2') break end end end moho:Copy() moho:SetSelLayer(skelLayer) mainSkel:SelectNone() moho:Paste() local duplicatedBone = mainSkel:Bone(mainSkel:CountBones()-1) duplicatedBone.fParent = selectedBone.fParent duplicatedBone.fAnimParent:SetValue(0, selectedBone.fParent) duplicatedBone.fAnimPos:SetValue(0, selectedBone.fAnimPos:GetValue(0)) duplicatedBone.fAnimAngle:SetValue(0, selectedBone.fAnimAngle:GetValue(0)) mainSkel:SelectNone() duplicatedBone.fSelected = true for d=0, tempSkel:CountBones()-1 do tempSkel:DeleteBone(0) end local actionsToRemove = {} for i=0, tempSkelLayer:CountActions()-1 do local actionName = tempSkelLayer:ActionName(i) table.insert(actionsToRemove, actionName) end for l, action in ipairs(actionsToRemove) do tempSkelLayer:DeleteAction(action) end moho:DeleteLayer(tempSkelLayer) moho:SetSelLayer(currentLayer) moho:SetCurFrame(1) moho:SetCurFrame(0) moho.view:DrawMe() moho:UpdateUI() moho.layer:UpdateCurFrame() end function MR_TransformRigTool:ScaleVector2(moho, vector2, center, scaling) local centerVec = LM.Vector2:new_local() centerVec:Set(center) local dif = LM.Vector2:new_local() local newVector2 = LM.Vector2:new_local() dif:Set(vector2 - centerVec) newVector2:Set((dif * scaling.x) + centerVec) return newVector2 end function MR_TransformRigTool:Flip(moho, direction, alt) self.skel = self:FindSkeleton(moho) local skel = self.skel self.mainSkelSelectedBones = self:CountSelectedBones(moho, skel) self:ScanLayers(moho, true) if (self.vectorLayersToChange.layer[1] == nil) and self.imageLayersToChange.layer[1] == nil then if self.patchLayersToChange.layer[1] == nil then if (self.transformBones and self.mainSkelSelectedBones ~= 1) or not self.transformBones then self.status = self:Localize('No layers selected for active mode.') self:UpdateWidgets(moho) self.blockTransformation = true return end end end if (self.transformBones and self.mainSkelSelectedBones ~= 1) or (self.centerId == 1 and self.mainSkelSelectedBones ~= 1) then self.status = self:Localize('You need to select one bone in this mode.') self:UpdateWidgets(moho) self.blockTransformation = true return end for m in pairs(self.fixedActionsList) do self.fixedActionsList[m] = nil end self.selectedMainBone = skel:Bone(skel:SelectedBoneID()) moho.document:SetDirty() moho.document:PrepUndo(self.skelLayer) if self.centerId == 1 and self.mainSkelSelectedBones ~= 1 then self.status = self:Localize('You need to select one bone in this mode.') self:UpdateWidgets(moho) return end self:FindSkeletonLayer(moho) if not alt then self.lastSkelLayer = self.skelLayer end if self.lastSkelLayer == nil then self.status = self:Localize('No last flip to repeat') self:UpdateWidgets(moho) return end local center = LM.Vector2:new_local() local bone = skel:Bone(skel:SelectedBoneID()) if self.centerId == 0 then -- custom center center:Set(self.centerVec) elseif self.centerId == 1 then -- selected bone local bonePos = LM.Vector2:new_local() bonePos:Set(self:GetGlobalBonePos(moho, bone)) center:Set(bonePos) end if alt and self.lastFlipCenter ~= nil then center:Set(self.lastFlipCenter) end if self.transformPoints then self:FlipPoints(moho, direction, center, alt) end ---------- Flip groups origin ---------- if self.transformOrigin then for k, id in ipairs(self.groupsToChange.group) do local group = moho:LayerAsGroup(moho.document:LayerByAbsoluteID(id)) local centerVec = LM.Vector2:new_local() centerVec:Set(center) local dif = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local origin = MR_Utilities:GetGlobalPos(moho, group, group:Origin(), false) if direction then dif:Set(centerVec.x - origin.x, 0) newPos:Set(centerVec.x + dif.x, origin.y) else dif:Set(0, centerVec.y - origin.y) newPos:Set(origin.x, centerVec.y + dif.y ) end newPos = MR_Utilities:GetLocalPos(moho, group, newPos, false) self:SetOrigin(moho, group, newPos) end end if self.ignoreRefLayers then for k, layer in ipairs(self.refLayersList) do layer:MarkReferenceOutdated() end end if self.transformBones and self.mainSkelSelectedBones == 1 then self:FlipBoneChain(moho, direction, false, alt) if self.mainSkelSelectedBones == 1 then local centerVec = LM.Vector2:new_local() centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) local bone = skel:Bone(skel:SelectedBoneID()) local dif = LM.Vector2:new_local() local bonePos = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local globalOffset = LM.Vector2:new_local() local parentBoneMatrix = LM.Matrix:new_local() local lastSkelMatrix = LM.Matrix:new_local() local skelMatrix = LM.Matrix:new_local() local invertedSkelMatrix = LM.Matrix:new_local() self.skelLayer:GetFullTransform(0, skelMatrix, nil) invertedSkelMatrix:Set(skelMatrix) invertedSkelMatrix:Invert() if self.lastSkelLayer ~= nil then self.lastSkelLayer:GetFullTransform(0, lastSkelMatrix, nil) end local invertedLastSkelMatrix = LM.Matrix:new_local() invertedLastSkelMatrix:Set(lastSkelMatrix) invertedLastSkelMatrix:Invert() bonePos:Set(bone.fAnimPos:GetValue(0)) if bone.fParent > -1 then parentBoneMatrix:Set(skel:Bone(bone.fParent).fMovedMatrix) parentBoneMatrix:Transform(bonePos) end if alt and not self.useGlobalFlip then skelMatrix:Transform(bonePos) invertedLastSkelMatrix:Transform(bonePos) centerVec:Set(center) invertedLastSkelMatrix:Transform(centerVec) elseif self.useGlobalFlip then skelMatrix:Transform(bonePos) centerVec:Set(center) end if direction then dif:Set(centerVec.x - bonePos.x, 0) newPos:Set(centerVec.x + dif.x, bonePos.y) else dif:Set(0, centerVec.y - bonePos.y) newPos:Set(bonePos.x, centerVec.y + dif.y ) end if alt and not self.useGlobalFlip then lastSkelMatrix:Transform(newPos) invertedSkelMatrix:Transform(newPos) elseif self.useGlobalFlip then invertedSkelMatrix:Transform(newPos) end globalOffset:Set(MR_Utilities:GetGlobalPos(moho, self.skelLayer, newPos, false) - self:GetGlobalBonePos(moho, bone)) if bone.fParent > -1 then parentBoneMatrix:Invert() parentBoneMatrix:Transform(newPos) end bone.fAnimPos:SetValue(0, newPos) self:TranslateBoneInActions(moho, bone, globalOffset) end if self.transformTargetBones and self.mainSkelSelectedBones == 1 then local selectedBone = skel:Bone(skel:SelectedBoneID()) self:FindTargetBones(moho, selectedBone, true) end if self.transformVitruvianBones and self.mainSkelSelectedBones == 1 and self.isVitruvianBonesAvaible then local selectedBoneId = skel:SelectedBoneID() local selectedBone = skel:Bone(skel:SelectedBoneID()) local centerVec = LM.Vector2:new_local() centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) if skel:IsBoneInAGroup(selectedBoneId) then local vitruvianGroup = skel:GroupForBone(selectedBoneId, false) for i=0, vitruvianGroup:CountBones()-1 do local bone = vitruvianGroup:Bone(i) if skel:BoneID(bone) ~= selectedBoneId then skel:SelectNone() bone.fSelected = true self:FlipBoneChain(moho, direction, false) local dif = LM.Vector2:new_local() local bonePos = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local globalOffset = LM.Vector2:new_local() local parentBoneMatrix = LM.Matrix:new_local() local lastSkelMatrix = LM.Matrix:new_local() local skelMatrix = LM.Matrix:new_local() local invertedSkelMatrix = LM.Matrix:new_local() self.skelLayer:GetFullTransform(0, skelMatrix, nil) invertedSkelMatrix:Set(skelMatrix) invertedSkelMatrix:Invert() if self.lastSkelLayer ~= nil then self.lastSkelLayer:GetFullTransform(0, lastSkelMatrix, nil) end local invertedLastSkelMatrix = LM.Matrix:new_local() invertedLastSkelMatrix:Set(lastSkelMatrix) invertedLastSkelMatrix:Invert() bonePos:Set(bone.fAnimPos:GetValue(0)) if bone.fParent > -1 then parentBoneMatrix:Set(skel:Bone(bone.fParent).fMovedMatrix) parentBoneMatrix:Transform(bonePos) end if alt and not self.useGlobalFlip then skelMatrix:Transform(bonePos) invertedLastSkelMatrix:Transform(bonePos) centerVec:Set(center) invertedLastSkelMatrix:Transform(centerVec) elseif self.useGlobalFlip then skelMatrix:Transform(bonePos) centerVec:Set(center) end if direction then dif:Set(centerVec.x - bonePos.x, 0) newPos:Set(centerVec.x + dif.x, bonePos.y) else dif:Set(0, centerVec.y - bonePos.y) newPos:Set(bonePos.x, centerVec.y + dif.y ) end if alt and not self.useGlobalFlip then lastSkelMatrix:Transform(newPos) invertedSkelMatrix:Transform(newPos) elseif self.useGlobalFlip then invertedSkelMatrix:Transform(newPos) end globalOffset:Set(MR_Utilities:GetGlobalPos(moho, self.skelLayer, newPos, false) - self:GetGlobalBonePos(moho, bone)) if bone.fParent > -1 then parentBoneMatrix:Invert() parentBoneMatrix:Transform(newPos) end bone.fAnimPos:SetValue(0, newPos) self:TranslateBoneInActions(moho, bone, globalOffset) if self.transformTargetBones and self.mainSkelSelectedBones == 1 then local selectedBone = skel:Bone(skel:SelectedBoneID()) self:FindTargetBones(moho, bone, false) end end end skel:SelectNone() selectedBone.fSelected = true end end if self.transformTargetBones and self.mainSkelSelectedBones == 1 then self:FlipTargetBones(moho, center, direction, alt) end end if self.transformImageLayers then for i, id in ipairs(self.imageLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) local isLayerinFollowPathGroup = false if self.followPathAdaptation then for i, groupId in ipairs(self.followPathGroupsToChange.group) do if layer:Parent() then local parentLayerID = moho.document:LayerAbsoluteID(layer:Parent()) if parentLayerID == groupId then isLayerinFollowPathGroup = true end end end end if not isLayerinFollowPathGroup then self:FlipLayer(moho, layer, center, direction, alt) end end end if self.followPathAdaptation then for i, id in ipairs(self.followPathGroupsToChange.group) do local group = moho.document:LayerByAbsoluteID(id) if self.followPathGroupsToChange.transform[i] then self:FlipLayer(moho, group, center, direction, alt) end end end if self.transformPatchLayers then for i, id in ipairs(self.patchLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) self:FlipLayer(moho, layer, center, direction, alt) end end local totalActions = #self.fixedActionsList local actionsStr = self:Localize(' actions were updated.') if totalActions == 1 then actionsStr = self:Localize(' action was updated.') end if totalActions > 0 then self.status = totalActions.. actionsStr else self.status = self:Localize('Actions did not need to be updated') end if self.transformPoints then self:RefreshCachedLayers(moho) end self.lastFlipCenter = LM.Vector2:new_local() self.lastFlipCenter:Set(center) moho:UpdateUI() moho.layer:UpdateCurFrame() moho:SetCurFrame(1) moho:SetCurFrame(0) end function MR_TransformRigTool:AdjustStrokesWidth(moho, scaling) for k, id in ipairs(self.vectorLayersToStrokeChange) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() if mesh == nil then return end if self.useLineWidthInsteadStrokeWidth then for i = 0, mesh:CountPoints() - 1 do local point = mesh:Point(i) local newValue = point.fWidth:GetValue(0) * scaling point.fWidth:SetValue(0, newValue) for actionID = 0, point.fWidth:CountActions() - 1 do local action = moho:ChannelAsAnimVal(point.fWidth:Action(actionID)) local actionName = point.fWidth:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local newValue = action:GetValue(actionFrame) * scaling action:SetValue(actionFrame, newValue) self:CollectLog(nil, actionName) end end end end end else for i = 0, mesh:CountShapes() - 1 do local shape = mesh:Shape(i) if (shape ~= nil) then local lineWidth = shape.fMyStyle.fLineWidth * moho.document:Height() shape.fMyStyle.fLineWidth = LM.Clamp((lineWidth * scaling), 0.25, 256) / moho.document:Height() end end end end if self.ignoreRefLayers and not self.useLineWidthInsteadStrokeWidth then for k, layer in ipairs(self.refLayersList) do local layerRef = MOHO.MohoLayerRef:new_local() layer:GetLayerRefInfo(layerRef) local layerUUID = layerRef.fLayerUUID:Buffer() local origLayer = MR_Utilities:FindLayerByUUID(moho, layerUUID) if origLayer then if origLayer:IsAncestorSelected() or origLayer:SecondarySelection() or origLayer == moho.layer then local mesh = layer:Mesh() if mesh == nil then return end for i = 0, mesh:CountShapes() - 1 do local shape = mesh:Shape(i) if (shape ~= nil) then local lineWidth = shape.fMyStyle.fLineWidth * moho.document:Height() shape.fMyStyle.fLineWidth = LM.Clamp((lineWidth * scaling), 0.25, 256) / moho.document:Height() end end end end end end end function MR_TransformRigTool:ScaleImagesInActions(moho, center, scaleValue) for k, id in ipairs(self.imageLayersToChange.layer) do local imagelayer = moho.document:LayerByAbsoluteID(id) for actionID = 0, imagelayer.fScale:CountActions() - 1 do local action = moho:ChannelAsAnimVec3(imagelayer.fScale:Action(actionID)) local actionName = imagelayer.fScale:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local newScale = LM.Vector3:new_local() local layerScale = action:GetValue(actionFrame) if self.scalingMode == 1 then -- uniform newScale:Set(layerScale * scaleValue.x) elseif self.scalingMode == 2 then -- h newScale:Set(layerScale.x * scaleValue.x, layerScale.y, layerScale.z) elseif self.scalingMode == 3 then -- v newScale:Set(layerScale.x, layerScale.y * scaleValue.y, layerScale.z) end action:SetValue(actionFrame, newScale) if layerScale ~= newScale then self:CollectLog(nil, actionName) end end end end end end end function MR_TransformRigTool:RotateImagesInActions(moho, center, angleValue) for k, id in ipairs(self.imageLayersToChange.layer) do local imagelayer = moho.document:LayerByAbsoluteID(id) local localAngle = angleValue if self.imageLayersToChange.parentalFlip[k] then localAngle = -localAngle end for actionID = 0, imagelayer.fRotationZ:CountActions() - 1 do local action = moho:ChannelAsAnimVal(imagelayer.fRotationZ:Action(actionID)) local actionName = imagelayer.fRotationZ:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local layerAngle = action:GetValue(actionFrame) local newAngle = layerAngle + localAngle action:SetValue(actionFrame, newAngle) if layerAngle ~= newAngle then self:CollectLog(nil, actionName) end end end end end end end function MR_TransformRigTool:TranslateImagesInActions(moho, offset, mode, center) for k, id in ipairs(self.imageLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) local localOffset = LM.Vector2:new_local() local zeroOffset = LM.Vector2:new_local() if mode == 0 then localOffset:Set(offset) if layer:Parent() then localOffset:Set(MR_Utilities:GetLocalPos(moho, layer:Parent(), offset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, layer:Parent(), zeroOffset, false)) localOffset:Set(localOffset - zeroOffset) end end for actionID = 0, layer.fTranslation:CountActions() - 1 do local action = moho:ChannelAsAnimVec3(layer.fTranslation:Action(actionID)) local actionName = layer.fTranslation:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local newPos = LM.Vector3:new_local() local layerTranslation = action:GetValue(actionFrame) if mode == 0 then newPos:Set(layerTranslation.x + localOffset.x, layerTranslation.y + localOffset.y, layerTranslation.z) elseif mode == 1 then newPos:Set(layerTranslation + (action:GetValue(0) - self.imageLayersToChange.position[k])) end action:SetValue(actionFrame, newPos) if layerTranslation ~= newPos then self:CollectLog(nil, actionName) end end end end end end end function MR_TransformRigTool:FlipTargetBones(moho, center, direction, alt) local skel = self.skel local selectedBone = skel:Bone(skel:SelectedBoneID()) local centerVec = LM.Vector2:new_local() centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) for n, targetBone in ipairs(self.targetBonesList) do if targetBone ~= self.selectedMainBone then skel:SelectNone() targetBone.fSelected = true self:FlipBoneChain(moho, direction, true) local dif = LM.Vector2:new_local() local bonePos = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local globalOffset = LM.Vector2:new_local() local parentBoneMatrix = LM.Matrix:new_local() local lastSkelMatrix = LM.Matrix:new_local() local skelMatrix = LM.Matrix:new_local() local invertedSkelMatrix = LM.Matrix:new_local() self.skelLayer:GetFullTransform(0, skelMatrix, nil) invertedSkelMatrix:Set(skelMatrix) invertedSkelMatrix:Invert() if self.lastSkelLayer ~= nil then self.lastSkelLayer:GetFullTransform(0, lastSkelMatrix, nil) end local invertedLastSkelMatrix = LM.Matrix:new_local() invertedLastSkelMatrix:Set(lastSkelMatrix) invertedLastSkelMatrix:Invert() bonePos:Set(targetBone.fAnimPos:GetValue(0)) if targetBone.fParent > -1 then parentBoneMatrix:Set(skel:Bone(targetBone.fParent).fMovedMatrix) parentBoneMatrix:Transform(bonePos) end if alt and not self.useGlobalFlip then skelMatrix:Transform(bonePos) invertedLastSkelMatrix:Transform(bonePos) centerVec:Set(center) invertedLastSkelMatrix:Transform(centerVec) elseif self.useGlobalFlip then skelMatrix:Transform(bonePos) centerVec:Set(center) end if direction then dif:Set(centerVec.x - bonePos.x, 0) newPos:Set(centerVec.x + dif.x, bonePos.y) else dif:Set(0, centerVec.y - bonePos.y) newPos:Set(bonePos.x, centerVec.y + dif.y ) end if alt and not self.useGlobalFlip then lastSkelMatrix:Transform(newPos) invertedSkelMatrix:Transform(newPos) elseif self.useGlobalFlip then invertedSkelMatrix:Transform(newPos) end globalOffset:Set(MR_Utilities:GetGlobalPos(moho, self.skelLayer, newPos, false) - self:GetGlobalBonePos(moho, targetBone)) if targetBone.fParent > -1 then parentBoneMatrix:Invert() parentBoneMatrix:Transform(newPos) end targetBone.fAnimPos:SetValue(0, newPos) self:TranslateBoneInActions(moho, targetBone, globalOffset) end end skel:SelectNone() selectedBone.fSelected = true end function MR_TransformRigTool:TransformTargetBones(moho, alt) local skel = self.skel local selectedBone = skel:Bone(skel:SelectedBoneID()) self:FindTargetBones(moho, selectedBone, true) for n, targetBone in ipairs(self.targetBonesList) do local isBoneNotTransformed = true for t, tBone in ipairs(self.transformedTargetBonesList) do if targetBone:Name() == tBone then isBoneNotTransformed = false break end end if targetBone ~= self.selectedMainBone and isBoneNotTransformed then skel:SelectNone() targetBone.fSelected = true self:RepeatTransformation(moho, alt, true) table.insert(self.transformedTargetBonesList, targetBone:Name()) end end skel:SelectNone() selectedBone.fSelected = true end function MR_TransformRigTool:TranslateVitruvianBones(moho, alt) local skel = self.skel local selectedBoneId = skel:SelectedBoneID() local selectedBone = skel:Bone(selectedBoneId) if skel:IsBoneInAGroup(selectedBoneId) then local vitruvianGroup = skel:GroupForBone(selectedBoneId, false) local vitruvianGroupStatus = vitruvianGroup.fEnabled vitruvianGroup.fEnabled = false for i=0, vitruvianGroup:CountBones()-1 do local bone = vitruvianGroup:Bone(i) if skel:BoneID(bone) ~= selectedBoneId then skel:SelectNone() bone.fSelected = true self:RepeatTransformation(moho, alt, true) if self.transformTargetBones then self:TransformTargetBones(moho, alt) end end end vitruvianGroup.fEnabled = vitruvianGroupStatus skel:SelectNone() selectedBone.fSelected = true end end function MR_TransformRigTool:ScaleVitruvianBones(moho, alt) local skel = self.skel local selectedBoneId = skel:SelectedBoneID() local selectedBone = skel:Bone(selectedBoneId) local scaling = LM.Vector2:new_local() scaling:Set(self.lastScaling) if alt then local scalePercentageX = 100 / (1 / scaling.x) local scalePercentageY = 100 / (1 / scaling.y) scaling:Set(1/((1/100) * scalePercentageX), 1/((1/100) * scalePercentageY)) end if skel:IsBoneInAGroup(selectedBoneId) then local vitruvianGroup = skel:GroupForBone(selectedBoneId, false) local vitruvianGroupStatus = vitruvianGroup.fEnabled vitruvianGroup.fEnabled = false for i=0, vitruvianGroup:CountBones()-1 do local bone = vitruvianGroup:Bone(i) if skel:BoneID(bone) ~= selectedBoneId then skel:SelectNone() bone.fSelected = true self:RepeatTransformation(moho, alt, true) if self.transformTargetBones then self:TransformTargetBones(moho, alt) end end end vitruvianGroup.fEnabled = vitruvianGroupStatus skel:SelectNone() selectedBone.fSelected = true end end function MR_TransformRigTool:RotateVitruvianBones(moho, alt) local skel = self.skel local angle = self.lastAngle if alt then angle = -angle end local selectedBoneId = skel:SelectedBoneID() local selectedBone = skel:Bone(selectedBoneId) if skel:IsBoneInAGroup(selectedBoneId) then local vitruvianGroup = skel:GroupForBone(selectedBoneId, false) local vitruvianGroupStatus = vitruvianGroup.fEnabled vitruvianGroup.fEnabled = false for i=0, vitruvianGroup:CountBones()-1 do local bone = vitruvianGroup:Bone(i) if skel:BoneID(bone) ~= selectedBoneId then skel:SelectNone() bone.fSelected = true self:RepeatTransformation(moho, alt, true) if self.transformTargetBones then self:TransformTargetBones(moho, alt) end end end vitruvianGroup.fEnabled = vitruvianGroupStatus skel:SelectNone() selectedBone.fSelected = true end end function MR_TransformRigTool:CheckLayerParentalFlip(moho, layer, selfCheck) local targetLayer if selfCheck then targetLayer = layer else if layer:Parent() then targetLayer = layer:Parent() else targetLayer = layer end end local flipFactor = false repeat local flipH = targetLayer.fFlipH.value local flipV = targetLayer.fFlipV.value if ((flipH and not flipV) or (flipV and not flipH)) then flipFactor = not flipFactor end targetLayer = targetLayer:Parent() until targetLayer == nil return flipFactor end function MR_TransformRigTool:TranslateBoneInActions(moho, bone, offset) local skel = self.skel local localOffset = LM.Vector2:new_local() local zeroOffset = LM.Vector2:new_local() zeroOffset:Set(0, 0) localOffset:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, offset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, zeroOffset, false)) localOffset:Set(localOffset - zeroOffset) for actionID = 0, bone.fAnimPos:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVec2(bone.fAnimPos:Action(actionID)) local actionName = bone.fAnimPos:ActionName(actionID) if actionChannel ~= nil then for keyID = 0, actionChannel:CountKeys() - 1 do local actionFrame = actionChannel:GetKeyWhen(keyID) if (actionFrame > 0) then if bone.fParent >= 0 then self.skelLayer:ActivateAction(actionName) moho:SetCurFrame(actionFrame) local bonePos = LM.Vector2:new_local() local originalPos = LM.Vector2:new_local() bonePos:Set(actionChannel:GetValue(actionFrame)) originalPos:Set(bonePos) local parentBone = skel:Bone(bone.fAnimParent:GetValue(0)) local parentMatrix = parentBone.fMovedMatrix parentMatrix:Transform(bonePos) bonePos:Set(bonePos + localOffset) local invertedMatrix = LM.Matrix:new_local() invertedMatrix:Set(parentMatrix) invertedMatrix:Invert() local newPos = LM.Vector2:new_local() newPos:Set(bonePos) invertedMatrix:Transform(newPos) actionChannel:SetValue(actionFrame, newPos) if originalPos ~= newPos then self:CollectLog(nil, actionName) end else actionChannel:SetValue(actionFrame, actionChannel:GetValue(actionFrame) + localOffset) end end end self.skelLayer:ActivateAction(nil) moho:SetCurFrame(0) end end end function MR_TransformRigTool:FindTargetBones(moho, bone, startNewList) local skel = self.skel local boneId = skel:BoneID(bone) if startNewList then for i, l in ipairs(self.targetBonesList) do self.targetBonesList[i] = nil end end for i = 0, skel:CountBones() - 1 do if skel:IsBoneParent(i, boneId) or i == boneId then local childBone = skel:Bone(i) for b = 0, skel:CountBones() - 1 do local isTargetFound = false local targetBoneCandidat = skel:Bone(b) if targetBoneCandidat.fParent == -1 then if childBone.fTargetBone.value == b then isTargetFound = true else for actionID = 0, childBone.fTargetBone:CountActions() - 1 do local actionChannel = moho:ChannelAsAnimVal(childBone.fTargetBone:Action(actionID)) if actionChannel ~= nil then for keyID = 0, actionChannel:CountKeys() - 1 do local actionFrame = actionChannel:GetKeyWhen(keyID) if (actionFrame > 0) then if actionChannel:GetValue(actionFrame) == b then isTargetFound = true break end end end end end end if isTargetFound then local isBoneNotInList = true for k, tBone in pairs(self.targetBonesList) do if tBone == targetBoneCandidat then isBoneNotInList = false break end end if isBoneNotInList then table.insert(self.targetBonesList, targetBoneCandidat) break end end end end end end end function MR_TransformRigTool:RotateBoneInActions(moho, bone, angle) for actionID = 0, bone.fAnimAngle:CountActions() - 1 do local action = moho:ChannelAsAnimVal(bone.fAnimAngle:Action(actionID)) local actionName = bone.fAnimAngle:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local originalVal = action:GetValue(actionFrame) action:SetValue(actionFrame, action:GetValue(actionFrame) + angle) if originalVal ~= originalVal + angle then self:CollectLog(nil, actionName) end end end end end end function MR_TransformRigTool:AskForRejoinDemensions(moho) local isRejoint = false local ans = LM.GUI.Alert(LM.GUI.ALERT_QUESTION, self:Localize('Channels with separated dimensions were found.'), self:Localize('Do You want to rejoin dimensions?'), "", self:Localize('Rejoin Dimensions'), self:Localize('Cancel'),"") if ans == 0 then isRejoint = true end return isRejoint end function MR_TransformRigTool:SplitChannel(moho, channel, isAllowRejoin) if not isAllowRejoin then isAllowRejoin = self:AskForRejoinDemensions(moho) if not isAllowRejoin then return false else channel:SplitDimensions(false) return true end else channel:SplitDimensions(false) return true end end function MR_TransformRigTool:CheckForSplitDimensions(moho) self.skel = self:FindSkeleton(moho) if self.skel == nil then return end moho.document:PrepUndo(self.skelLayer) moho.document:SetDirty() self:ScanLayers(moho) local isAllowRejoin = false local skel = self.skel self:FindSkeletonLayer(moho) if self.transformBones then for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if bone.fAnimPos:AreDimensionsSplit() then isAllowRejoin = self:SplitChannel(moho, bone.fAnimPos, isAllowRejoin) if not isAllowRejoin then return end end for act=0, bone.fAnimPos:CountActions()-1 do local actName = bone.fAnimPos:ActionName(act) local isSmartBone = self.skelLayer:IsSmartBoneAction(actName) if isSmartBone then local actionChannel = moho:ChannelAsAnimVec2(bone.fAnimPos:Action(act)) if actionChannel:AreDimensionsSplit() then isAllowRejoin = self:SplitChannel(moho, actionChannel, isAllowRejoin) if not isAllowRejoin then return end end end end end end if self.transformPoints then for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho:LayerAsVector(moho.document:LayerByAbsoluteID(id)) local mesh = layer:Mesh() for i = 0, mesh:CountPoints()-1 do local point = mesh:Point(i) if point.fAnimPos:AreDimensionsSplit() then isAllowRejoin = self:SplitChannel(moho, point.fAnimPos, isAllowRejoin) if not isAllowRejoin then return end end for act=0, point.fAnimPos:CountActions()-1 do local actName = point.fAnimPos:ActionName(act) local isSmartBone = self.skelLayer:IsSmartBoneAction(actName) if isSmartBone then local actionChannel = moho:ChannelAsAnimVec2(point.fAnimPos:Action(act)) if actionChannel:AreDimensionsSplit() then isAllowRejoin = self:SplitChannel(moho, actionChannel, isAllowRejoin) if not isAllowRejoin then return end end end end end end end if self.transformImageLayers then for k, id in ipairs(self.imageLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) if layer.fTranslation:AreDimensionsSplit() then isAllowRejoin = self:SplitChannel(moho, layer.fTranslation, isAllowRejoin) if not isAllowRejoin then return end end if layer.fScale:AreDimensionsSplit() then isAllowRejoin = self:SplitChannel(moho, layer.fScale, isAllowRejoin) if not isAllowRejoin then return end end for act=0, layer.fTranslation:CountActions()-1 do local actName = layer.fTranslation:ActionName(act) local isSmartBone = self.skelLayer:IsSmartBoneAction(actName) if isSmartBone then local actionChannel = moho:ChannelAsAnimVec3(layer.fTranslation:Action(act)) if actionChannel:AreDimensionsSplit() then isAllowRejoin = self:SplitChannel(moho, actionChannel, isAllowRejoin) if not isAllowRejoin then return end end end end for act=0, layer.fScale:CountActions()-1 do local actName = layer.fScale:ActionName(act) local isSmartBone = self.skelLayer:IsSmartBoneAction(actName) if isSmartBone then local actionChannel = moho:ChannelAsAnimVec3(layer.fScale:Action(act)) if actionChannel:AreDimensionsSplit() then isAllowRejoin = self:SplitChannel(moho, actionChannel, isAllowRejoin) if not isAllowRejoin then return end end end end end end if not isAllowRejoin then local ans = LM.GUI.Alert(LM.GUI.ALERT_INFO, self:Localize('No channels with separated dimensions were found.'), "", "", "OK", "","") end moho:UpdateUI() end function MR_TransformRigTool:AddBonesToList(moho) local skel = moho:Skeleton() for i, b in pairs(self.bonesLinkList.bone) do self.bonesLinkList[i] = nil self.bonesLinkList.bone[i] = nil self.bonesLinkList.parentBone[i] = nil end local selectedBones = {} for i = 0, moho:CountBones()-1 do local bone = skel:Bone(i) if bone.fSelected then table.insert(selectedBones, i) if bone.fParent > -1 then table.insert(self.bonesLinkList.bone, i) table.insert(self.bonesLinkList.parentBone, bone.fParent) end end end for k, selectedBone in ipairs(selectedBones) do for i = 0, moho:CountBones()-1 do local bone = skel:Bone(i) if bone.fParent == selectedBone then table.insert(self.bonesLinkList.bone, i) table.insert(self.bonesLinkList.parentBone, selectedBone) end end end end function MR_TransformRigTool:UnlinkBones(moho) for i, boneID in ipairs(self.bonesLinkList.bone) do self:ReparentBones(moho, boneID, -1) end end function MR_TransformRigTool:RelinkBones(moho) local skel = moho:Skeleton() for i, boneID in ipairs(self.bonesLinkList.bone) do local skel = moho:Skeleton() local bone = skel:Bone(boneID) local parentBone = skel:Bone(self.bonesLinkList.parentBone[i]) if bone ~= nil and parentBone ~= nil then self:ReparentBones(moho, boneID, self.bonesLinkList.parentBone[i]) end end for i, b in pairs(self.bonesLinkList.bone) do self.bonesLinkList[i] = nil self.bonesLinkList.bone[i] = nil self.bonesLinkList.parentBone[i] = nil end end function MR_TransformRigTool:ReparentBones(moho, boneID, parentBoneID) local skel = moho:Skeleton() local bone = skel:Bone(boneID) if (parentBoneID ~= -1 and skel:Bone(parentBoneID) == nil) or bone == nil then return end local v1 = LM.Vector2:new_local() local v2 = LM.Vector2:new_local() v1:Set(0, 0) if (bone:IsZeroLength()) then v2:Set(0.1, 0) else v2:Set(bone.fLength, 0) end bone.fMovedMatrix:Transform(v1) bone.fMovedMatrix:Transform(v2) if parentBoneID >= 0 then local invMatrix = LM.Matrix:new_local() local parent = skel:Bone(parentBoneID) invMatrix:Set(parent.fMovedMatrix) invMatrix:Invert() invMatrix:Transform(v1) invMatrix:Transform(v2) end bone.fAnimPos:SetValue(0, v1) v2 = v2 - v1 local angle = math.atan2(v2.y, v2.x) while angle > 2 * math.pi do angle = angle - 2 * math.pi end while angle < 0 do angle = angle + 2 * math.pi end if (bone.fFixedAngle) then bone.fAnimAngle:SetValue(0, angle) else local angleDiff = angle - bone.fAnimAngle:GetValue(0) bone.fAnimAngle:SetValue(0, angle) for keyID = 0, bone.fAnimAngle:CountKeys() - 1 do local angleFrame = bone.fAnimAngle:GetKeyWhen(keyID) if (angleFrame > 0) then local newAngle = bone.fAnimAngle:GetValue(angleFrame) + angleDiff bone.fAnimAngle:SetValue(angleFrame, newAngle) end end for actionID = 0, bone.fAnimAngle:CountActions() - 1 do local action = moho:ChannelAsAnimVal(bone.fAnimAngle:Action(actionID)) for keyID = 0, action:CountKeys() - 1 do local angleFrame = action:GetKeyWhen(keyID) if (angleFrame > 0) then local newAngle = action:GetValue(angleFrame) + angleDiff action:SetValue(angleFrame, newAngle) end end end end if (bone.fAnimParent:CountKeys() < 2) then bone.fAnimParent:SetValue(0, bone.fParent) end bone.fParent = parentBoneID bone.fAnimParent:SetValue(0, parentBoneID) end function MR_TransformRigTool:TranslateLayer(moho, layer, offset) local localOffset = LM.Vector2:new_local() local zeroOffset = LM.Vector2:new_local() localOffset:Set(offset) if layer:Parent() then localOffset:Set(MR_Utilities:GetLocalPos(moho, layer:Parent(), localOffset, false)) zeroOffset:Set(MR_Utilities:GetLocalPos(moho, layer:Parent(), zeroOffset, false)) localOffset:Set(localOffset - zeroOffset) end local vec = LM.Vector3:new_local() vec:Set(layer.fTranslation.value) vec.x = vec.x + localOffset.x vec.y = vec.y + localOffset.y layer.fTranslation:SetValue(0, vec) for actionID = 0, layer.fTranslation:CountActions() - 1 do local action = moho:ChannelAsAnimVec3(layer.fTranslation:Action(actionID)) local actionName = layer.fTranslation:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local newPos = LM.Vector3:new_local() local layerTranslation = action:GetValue(actionFrame) newPos:Set(layerTranslation.x + localOffset.x, layerTranslation.y + localOffset.y, layerTranslation.z) action:SetValue(actionFrame, newPos) if layerTranslation ~= newPos then self:CollectLog(nil, actionName) end end end end end end function MR_TransformRigTool:ScaleLayer(moho, layer, center, scaling) local curOrigin = LM.Vector2:new_local() local posDif = LM.Vector3:new_local() local curPos = LM.Vector3:new_local() curPos:Set(layer.fTranslation:GetValue(0)) curOrigin:Set(layer:Origin()) local centerVec = LM.Vector2:new_local() centerVec = MR_Utilities:GetLocalPos(moho, layer, center, false) -- use global pos self:SetOrigin(moho, layer, centerVec) local vec = LM.Vector3:new_local() vec:Set(layer.fScale.value) if self.scalingMode == 1 then vec.x = vec.x * scaling.x vec.y = vec.y * scaling.x vec.z = vec.z * scaling.x elseif self.scalingMode == 2 then vec.x = vec.x * scaling.x elseif self.scalingMode == 3 then vec.y = vec.y * scaling.y end layer.fScale:SetValue(0, vec) self:SetOrigin(moho, layer, curOrigin) posDif:Set(layer.fTranslation:GetValue(0) - curPos) for actionID = 0, layer.fTranslation:CountActions() - 1 do local action = moho:ChannelAsAnimVec3(layer.fTranslation:Action(actionID)) local actionName = layer.fTranslation:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local newPos = LM.Vector3:new_local() local layerTranslation = action:GetValue(actionFrame) newPos:Set(layerTranslation + posDif) action:SetValue(actionFrame, newPos) if layerTranslation ~= newPos then self:CollectLog(nil, actionName) end end end end end for actionID = 0, layer.fScale:CountActions() - 1 do local action = moho:ChannelAsAnimVec3(layer.fScale:Action(actionID)) local actionName = layer.fScale:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local newScale = LM.Vector3:new_local() local layerScale = action:GetValue(actionFrame) if self.scalingMode == 1 then -- uniform newScale:Set(layerScale * scaling.x) elseif self.scalingMode == 2 then -- h newScale:Set(layerScale.x * scaling.x, layerScale.y, layerScale.z) elseif self.scalingMode == 3 then -- v newScale:Set(layerScale.x, layerScale.y * scaling.y, layerScale.z) end action:SetValue(actionFrame, newScale) if layerScale ~= newScale then self:CollectLog(nil, actionName) end end end end end end function MR_TransformRigTool:RotateLayer(moho, layer, center, angle) local curOrigin = LM.Vector2:new_local() curOrigin:Set(layer:Origin()) local curPos = LM.Vector3:new_local() local posDif = LM.Vector3:new_local() curPos:Set(layer.fTranslation:GetValue(0)) local centerVec = LM.Vector2:new_local() centerVec = MR_Utilities:GetLocalPos(moho, layer, center, false) -- use global pos self:SetOrigin(moho, layer, centerVec) local layerAngle = layer.fRotationZ:GetValue(0) local localAngle = angle if self:CheckLayerParentalFlip(moho, layer, true) then localAngle = -localAngle end layerAngle = layerAngle + localAngle layer.fRotationZ:SetValue(0, layerAngle) self:SetOrigin(moho, layer, curOrigin) posDif:Set(layer.fTranslation:GetValue(0) - curPos) for actionID = 0, layer.fTranslation:CountActions() - 1 do local action = moho:ChannelAsAnimVec3(layer.fTranslation:Action(actionID)) local actionName = layer.fTranslation:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local newPos = LM.Vector3:new_local() local layerTranslation = action:GetValue(actionFrame) newPos:Set(layerTranslation + posDif) action:SetValue(actionFrame, newPos) if layerTranslation ~= newPos then self:CollectLog(nil, actionName) end end end end end for actionID = 0, layer.fRotationZ:CountActions() - 1 do local action = moho:ChannelAsAnimVal(layer.fRotationZ:Action(actionID)) local actionName = layer.fRotationZ:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local actionFrame = action:GetKeyWhen(keyID) if (actionFrame > 0) then local layerAngle = action:GetValue(actionFrame) local newAngle = layerAngle + localAngle action:SetValue(actionFrame, newAngle) if layerAngle ~= newAngle then self:CollectLog(nil, actionName) end end end end end end function MR_TransformRigTool:FlipLayer(moho, layer, center, direction, lastFlip) local curOrigin = LM.Vector2:new_local() local localCenter = LM.Vector2:new_local() localCenter:Set(center) curOrigin:Set(layer:Origin()) local skelMatrix = LM.Matrix:new_local() if lastFlip and not self.useGlobalFlip then if self.lastSkelLayer ~= nil then self.lastSkelLayer:GetFullTransform(0, skelMatrix, nil) end end localCenter = MR_Utilities:GetLocalPos(moho, layer, center, false) -- use global pos self:SetOrigin(moho, layer, localCenter) if direction then layer.fFlipH:SetValue(0, not layer.fFlipH.value) else layer.fFlipV:SetValue(0, not layer.fFlipV.value) end local parenOffset = 0 if layer:Parent() then local parentLayerMatrix = LM.Matrix:new_local() local parentLayer = layer:Parent() parentLayer:GetFullTransform(0, parentLayerMatrix, nil) if lastFlip and not self.useGlobalFlip then elseif not self.useGlobalFlip then self.skelLayer:GetFullTransform(0, skelMatrix, nil) end local v1 = LM.Vector2:new_local() local v2 = LM.Vector2:new_local() v1:Set(parentLayer:Origin()) v2:Set(v1.x - 0.1, v1.y) parentLayerMatrix:Transform(v1) parentLayerMatrix:Transform(v2) if not self.useGlobalFlip then skelMatrix:Invert() skelMatrix:Transform(v1) skelMatrix:Transform(v2) end if direction then v2:Set(v1.x + (v1.x - v2.x),v2.y) else v2:Set(v2.x, v1.y + (v1.y - v2.y)) end local newAngle = 0 v2 = v2 - v1 newAngle = math.atan2(v2.y, v2.x) while newAngle > math.rad(360) do newAngle = newAngle - math.rad(360) end while newAngle < - math.rad(360) do newAngle = newAngle + math.rad(360) end parenOffset = newAngle end if self:CheckLayerParentalFlip(moho, layer, false) then parenOffset = -(parenOffset * 2) else parenOffset = parenOffset * 2 end layer.fRotationZ:SetValue(0, -(layer.fRotationZ:GetValue(0)) + parenOffset) self:SetOrigin(moho, layer, curOrigin) end function MR_TransformRigTool:CorrectScalingOffsetInActions(moho, bone, center, scaling) local skel = self.skel for actionID = 0, bone.fAnimPos:CountActions() - 1 do local action = moho:ChannelAsAnimVec2(bone.fAnimPos:Action(actionID)) local actionName = bone.fAnimPos:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local posFrame = action:GetKeyWhen(keyID) if (posFrame > 0) then local startBonePos = LM.Vector2:new_local() local originalBonePos = LM.Vector2:new_local() local centerVec = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local dif = LM.Vector2:new_local() startBonePos:Set(action:GetValue(posFrame)) originalBonePos:Set(startBonePos) if bone.fParent < 0 then centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) dif:Set(startBonePos - centerVec) newPos:Set((dif * scaling.x) + centerVec) else self.skelLayer:ActivateAction(actionName) moho:SetCurFrame(posFrame) local parentBoneMatrix = LM.Matrix:new_local() local parentBone = skel:Bone(bone.fParent) parentBoneMatrix = parentBone.fMovedMatrix parentBoneMatrix:Transform(startBonePos) centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) dif:Set(startBonePos - centerVec) parentBoneMatrix:Invert() newPos:Set((dif * scaling.x) + centerVec) parentBoneMatrix:Transform(newPos) end action:SetValue(posFrame, newPos) if originalBonePos ~= newPos then self:CollectLog(nil, actionName) end self.skelLayer:ActivateAction(nil) end end end end moho:SetCurFrame(0) end function MR_TransformRigTool:CorrectRotatingOffsetInActions(moho, bone, center, angle) local skel = self.skel for actionID = 0, bone.fAnimPos:CountActions() - 1 do local action = moho:ChannelAsAnimVec2(bone.fAnimPos:Action(actionID)) local actionName = bone.fAnimPos:ActionName(actionID) if action ~= nil then for keyID = 0, action:CountKeys() - 1 do local posFrame = action:GetKeyWhen(keyID) if (posFrame > 0) then local startBonePos = LM.Vector2:new_local() local originalBonePos = LM.Vector2:new_local() local centerVec = LM.Vector2:new_local() local newPos = LM.Vector2:new_local() local dif = LM.Vector2:new_local() startBonePos:Set(action:GetValue(posFrame)) originalBonePos:Set(startBonePos) centerVec:Set(center) centerVec:Set(MR_Utilities:GetLocalPos(moho, self.skelLayer, centerVec, false)) if bone.fParent < 0 then dif:Set(startBonePos - centerVec) local px = dif.x * math.cos(angle) - dif.y * math.sin(angle) local py = dif.x * math.sin(angle) + dif.y * math.cos(angle) newPos:Set(px + centerVec.x, py + centerVec.y) else self.skelLayer:ActivateAction(actionName) moho:SetCurFrame(posFrame) local parentBoneMatrix = LM.Matrix:new_local() local parentBone = skel:Bone(bone.fParent) parentBoneMatrix = parentBone.fMovedMatrix parentBoneMatrix:Transform(startBonePos) dif:Set(startBonePos - centerVec) local px = dif.x * math.cos(angle) - dif.y * math.sin(angle) local py = dif.x * math.sin(angle) + dif.y * math.cos(angle) newPos:Set(px + centerVec.x, py + centerVec.y) parentBoneMatrix:Invert() parentBoneMatrix:Transform(newPos) end action:SetValue(posFrame, newPos) if originalBonePos ~= newPos then self:CollectLog(nil, actionName) end self.skelLayer:ActivateAction(nil) end end end end moho:SetCurFrame(0) end function MR_TransformRigTool:RefreshCachedLayers(moho) for k, id in ipairs(self.vectorLayersToChange.layer) do local layer = moho.document:LayerByAbsoluteID(id) layer:FreeCachedImage() end end -- ************************************************** -- Localization -- ************************************************** function MR_TransformRigTool:Localize(text) local phrase = {} phrase['Description'] = 'Transformation, duplication and copying body parts. Ctrl+Alt+Click for setting Custom Center.' phrase['UILabel'] = 'Transform Rig Tool '..self:Version() phrase['Advanced Mode'] = 'Advanced Mode' phrase['Finalize'] = 'Apply and leave advanced mode' phrase['Clear'] = 'Cancel and leave advanced mode' phrase['Settings'] = 'Settings' phrase['Live transformation settings:'] = 'Live transformation settings:' phrase['Show Transform Info'] = 'Show transformation info' phrase['Use Global Flip'] = 'Use global flip' phrase['Adaptive scale and rotation'] = 'Adaptive scale and rotation' phrase['Use Line Width'] = 'Use Line Width' phrase['Live updating references'] = 'Live updating references' phrase['Duplicate bodypart settings:'] = 'Duplicate bodypart settings:' phrase['Duplicated names suffix'] = 'Names suffix' phrase['Advanced mode settings:'] = 'Advanced mode settings:' phrase['Consider new parent rotation'] = 'Consider new parent rotation' phrase['Consider old parent rotation'] = 'Consider old parent rotation' phrase['Custom Center'] = 'Custom Center' phrase['Selected Bone'] = 'Selected Bone' phrase['Set From Selection'] = 'Set to selection center (Alt+Click to set to the selected bone position)' phrase['Duplicate Bodypart'] = 'Duplicate Bodypart' phrase['Copy Bodypart'] = 'Copy Bodypart' phrase['Flip Horizontally'] = 'Flip Horizontally (Alt+Click to copy the previous flip)' phrase['Flip Vertically'] = 'Flip Vertically (Alt+Click to copy the previous flip)' phrase['Duplicate And Flip Smarbone'] = 'Duplicate Smarbone (Alt+Click to duplicate and flip)' phrase['Reconnect Bones'] = 'Preserve Bones Parenting (Alt+Click to unlink, then Click to relink)' phrase['Select All Points'] = 'Select All Points (Alt+Click - deselect points)' phrase['Check For Split Dimensions'] = 'Check For Split Dimensions' phrase['Ignore References'] = 'Ignore Reference Layers' phrase['Transform Points'] = 'Transform Points' phrase['Auto Select All Points'] = 'Auto Select All Points' phrase['Adjust Stroke Width'] = 'Adjust Stroke Width' phrase['Follow Path Rig Adaptation'] = 'Follow Path Rig Adaptation' phrase['Transform Bones'] = 'Transform Bones' phrase['Transform Vitruvian Bones'] = 'Transform Vitruvian Bones' phrase['Transform Target Bones'] = 'Transform Target Bones' phrase['Transform Patch Layers'] = 'Transform Patch Layers' phrase['Transform Image Layers'] = 'Transform Image Layers' phrase['Transform Origins'] = 'Transform Layer Origin' phrase['Select Bone'] = 'Select Bone' phrase['Translate'] = 'Translate' phrase['Rotate'] = 'Rotate' phrase['Scale'] = 'Scale' phrase['Update Center'] = 'Update Center For Repeat Last Transformation (Alt+Click to set the center to layer\'s origin)' phrase['Repeat Transformation'] = 'Repeat Last Transformation' phrase['Repeat Translate'] = 'Repeat Last Translation. (Alt+Click to translate in the opposite direction)' phrase['Repeat Rotate'] = 'Repeat Last Rotation. (Alt+Click to rotate in the opposite direction)' phrase['Repeat Scale'] = 'Repeat Last Scaling. (Alt+Click to scale in the opposite direction)' phrase['Edit Last Transform'] = 'Edit' phrase['X'] = 'X' phrase['Y'] = 'Y' phrase['Angle'] = 'A' phrase['Apply'] = 'Apply' phrase['Collected data cleared.'] = 'Advanced mode info cleared.' phrase['Canceled.'] = 'Canceled.' phrase['Original transformation collected for 1 bone on layer '] = 'Collected info for 1 bone on layer ' phrase['Original transformation collected for '] = 'Collected info for ' phrase[' bones on layer '] = ' bones in layer ' phrase['No bones was selected. Please select bones first.'] = 'No bones were selected. Please select some bones first.' phrase['Correction was canceled.'] = 'Operation was canceled.' phrase['Correction completed! '] = 'Completed! ' phrase[' fixed in '] = ' updated in ' phrase[' actions.'] = ' actions.' phrase[' bones were'] = ' bones were' phrase[' bone was'] = ' bone was' phrase[' action.'] = ' action.' phrase[' actions were updated.'] = ' actions were updated.' phrase[' action was updated.'] = ' action was updated.' phrase['Could not find any actions that need to be fixed.'] = 'No actions to update.' phrase['Actions did not need to be updated'] = 'No updates for actions needed.' phrase['Could not find a Rig.'] = 'Could not find a Rig.' phrase['You need to select one bone in this mode.'] = 'You need to select one bone in this mode.' phrase['Only one bone should be selected.'] = 'Only one bone should be selected.' phrase['No layers selected for active mode.'] = 'No layers selected for active mode.' phrase['Non uniform scaling not supported for bones.'] = 'Non-uniform scaling is not supported for bones.' phrase['Channels with separated dimensions were found.'] = 'Channels with separated dimensions were found.' phrase['You can Rejoin Dimensions to continue or cancel operation.'] = 'You can Rejoin Dimensions to continue or cancel operation.' phrase['Rejoin Dimensions'] = 'Rejoin Dimensions' phrase['Cancel'] = 'Cancel' phrase['Some bones are missing. The skeleton structure was changed.'] = 'Some bones are missing. The skeleton structure was changed.' phrase['EXIT'] = 'EXIT' phrase['Some reference keys are missing. Please do not remove or edit any reference keys.'] = 'Some reference keys are missing. Please do not remove or edit any reference keys.' phrase['The original number of bones is different.'] = 'The original number of bones is different.' phrase['Is smartbone is right?'] = 'Is smartbone is right?' phrase['If smartbone is right all R sufixes will be renamed to L'] = 'If smartbone is right all R sufixes will be renamed to L' phrase['Right'] = 'Right' phrase['Left'] = 'Left' phrase['Enter New Name'] = 'Enter New Name' phrase['Duplicate bodypart alert 1'] = 'Please select one bone and some nested layers.' phrase['Duplicate bodypart alert 2'] = 'The skeleton layer must not be selected.' phrase['Copy bodypart alert 1'] = '1. Select target skeleton.' phrase['Copy bodypart alert 2'] = '2. Select layers in the source skeleton and a bone.' phrase['Do You want to rejoin dimensions?'] = 'Would you like to rejoin dimensions?' phrase['No channels with separated dimensions were found.'] = 'No channels with separated dimensions were found.' phrase['No last flip to repeat'] = 'There is no previous flip to repeat.' phrase['As Action'] = '*' phrase['As Smartbone'] = '+' phrase['Remove'] = '-' phrase['Set R'] = '➞ R' phrase['Set L'] = '➞ L' phrase['Check Names'] = ' Check Names ' phrase['Reset Names'] = ' Reset Names ' phrase['Auto Mode'] = ' Suggest ' phrase['Duplicate only action'] = 'Duplicate only action' phrase['Duplicate smartbone'] = 'Duplicate action and smartbone' phrase['Do not duplicate action'] = 'Do not duplicate action' phrase['Smartbone name does not changed'] = 'Name is not changed' phrase['Smartbone name is changed'] = 'Name is changed' phrase['This smartbone name is used'] = 'This name is already used' phrase['This smartbone name is not used'] = 'This name is not used' phrase['Smartbones Manager'] = 'Smartbones Manager' phrase['Missing Utilites'] = 'AE_Utilities is not installed.' phrase['Missing Utilites Info'] = 'AE_Utilities.lua is required for this tool. Please install the utilities file.' phrase['Please chose how to rename bones and actions:'] = 'Please chose how to rename bones and actions:' phrase['Direction Mode'] = 'Side Mode' phrase['Custom Mode'] = 'Replacement Mode' phrase['Suffix Mode'] = 'Add Suffix' phrase['Replace Text'] = 'Replace Text' phrase['Counter delimiter'] = 'Counter delimiter' phrase['Please chose how to rename smartbone:'] = 'Please chose how to rename smartbone:' phrase['Rename Smartbone'] = 'Enter New Name' phrase['Duplicate smartbone alert 1'] = 'Please select a single smartbone' phrase['Apply Custom Translate'] = 'Apply Custom Translation. (Alt+Click to translate in the opposite direction)' phrase['Apply Custom Scale'] = 'Apply Custom Scaling. (Alt+Click to scale in the opposite direction)' phrase['Apply Custom Rotation'] = 'Apply Custom Rotation. (Alt+Click to rotate in the opposite direction)' phrase['Suggest Tooltip'] = 'Apply suggested settings (Alt+Click to reset)' phrase['Duplicate Actions Tooltip'] = 'Set all to Duplicate Only Action' phrase['Remove Actions Tooltip'] = 'Set all to Do Not Duplicate Action' phrase['Replace Text 1 Tooltip'] = 'Text to find' phrase['Replace Text 2 Tooltip'] = 'Text to replace with' phrase['Replace Text Button Tooltip'] = 'Find and replace in all action names (Alt+Click to swap)' phrase['Check Names Tooltip'] = 'Check if names are available' phrase['Reset Names Tooltip'] = 'Revert all names back to originals' phrase['Direction Mode Tooltip'] = 'The names will be changed based on their side' phrase['R to L Tooltip'] = 'Replace all R with L (Alt+Click to swap)' phrase['L to R Tooltip'] = 'Replace all L with R (Alt+Click to swap)' phrase['Custom Mode Tooltip'] = 'The names will be changed by Find And Replace' phrase['Reverse Tooltip'] = 'Swap Find and Replace' phrase['Suffix Mode Tooltip'] = 'The suffix will be added for duplicated names' phrase['Suffix Tooltip'] = 'The suffix to add' phrase['Rename Smartbone Tooltip'] = 'Rename the smartbone and its corresponding action' phrase['Swap Mode'] = 'Swap Text' phrase['Swap Mode Tooltip'] = 'Swap text instead of replacing' local fileWord = MOHO.Localize("/Menus/File/File=File") if fileWord == "Файл" then phrase['Description'] = 'Трансфомация, дублирование и перенос частей рига. Ctrl+Alt+Click для назначения Свободного Центра.' phrase['UILabel'] = 'Transform Rig Tool 1.2' phrase['Advanced Mode'] = 'Продвинутый режим' phrase['Finalize'] = 'Применить и покинуть продвинутый режим' phrase['Clear'] = 'Отменить и покинуть продвинутый режим' phrase['Settings'] = 'Настройки' phrase['Live transformation settings:'] = 'Трансформация в реальном времени:' phrase['Show Transform Info'] = 'Показывать значения при трансформации' phrase['Use Global Flip'] = 'Глобальное отражение' phrase['Adaptive scale and rotation'] = 'Адаптивные масштаб и вращение' phrase['Use Line Width'] = 'Изменять толщину точек для контура' phrase['Live updating references'] = 'Обновлеять референсы в реальном времени' phrase['Duplicate bodypart settings:'] = 'Настройки дублирования частей рига:' phrase['Duplicated names suffix'] = 'Суффикс для занятых имён' phrase['Advanced mode settings:'] = 'Настройки продвинутого режима:' phrase['Consider new parent rotation'] = 'Учитывать вращение нового родителя' phrase['Consider old parent rotation'] = 'Учитывать вращение старого родителя' phrase['Custom Center'] = 'Свободный Центр' phrase['Selected Bone'] = 'Выделенная кость' phrase['Set From Selection'] = 'Установить в центр выделенного обьекта (Alt+Click - установить в основание выделенной кости)' phrase['Duplicate Bodypart'] = 'Дублировать часть рига' phrase['Copy Bodypart'] = 'Скопировать часть рига в другой скелет' phrase['Flip Horizontally'] = 'Отразить горизонтально (Alt+Click - Повторить с учётом предыдущего отражения)' phrase['Flip Vertically'] = 'Отразить вертикально (Alt+Click - Повторить с учётом предыдущего отражения)' phrase['Duplicate And Flip Smarbone'] = 'Дублировать смартбоун (Alt+Click - дублировать и отразить)' phrase['Reconnect Bones'] = 'Запомнить дочерние связи костей. (Alt+Click - отвязать, Click - привязать обратно)' phrase['Select All Points'] = 'Выделить все точки (Alt+Click - снять выделение)' phrase['Check For Split Dimensions'] = 'Проверить наличие разделённых каналов' phrase['Ignore References'] = 'Игнорировать слои-референсы' phrase['Transform Points'] = 'Трансформировать точки' phrase['Auto Select All Points'] = 'Авто-выделение точек' phrase['Adjust Stroke Width'] = 'Изменять ширину контура под масштаб' phrase['Follow Path Rig Adaptation'] = 'Деформировать под риги с движением по кривой' phrase['Transform Bones'] = 'Трансформировать кости' phrase['Transform Vitruvian Bones'] = 'Трансформировать Витрувианские кости' phrase['Transform Target Bones'] = 'Трансформировать целевые кости' phrase['Transform Patch Layers'] = 'Трансформировать слои-заплатки' phrase['Transform Image Layers'] = 'Трансформировать растровые слои' phrase['Transform Origins'] = 'Трансформировать центр слоя' phrase['Select Bone'] = 'Выделить кость' phrase['Translate'] = 'Перемещать' phrase['Rotate'] = 'Вращать' phrase['Scale'] = 'Масштабировать' phrase['Update Center'] = 'Обновить центр для повторение трансформации (Alt+Click - назначить центр из центра слоя)' phrase['Repeat Transformation'] = 'Повторить последнюю трансформацию' phrase['Repeat Translate'] = 'Повторить последние перемещение. (Alt+Click - в обратном направлении)' phrase['Repeat Rotate'] = 'Повторить последнее вращение. (Alt+Click - в обратном направлении)' phrase['Repeat Scale'] = 'Повторить последнее масштабирование. (Alt+Click - в обратном направлении)' phrase['Edit Last Transform'] = 'Редактировать' phrase['X'] = 'X' phrase['Y'] = 'Y' phrase['Angle'] = 'A' phrase['Apply'] = 'Применить' phrase['Collected data cleared.'] = 'Информация продвинутого режима очищена.' phrase['Canceled.'] = 'Отменено.' phrase['Original transformation collected for 1 bone on layer '] = 'Проанализирована 1 кость в слое ' phrase['Original transformation collected for '] = 'Проанализированы ' phrase[' bones on layer '] = ' кости(-ей) в слое ' phrase['No bones was selected. Please select bones first.'] = 'Нет выделенных костей. Выделите какие-нибудь кости.' phrase['Correction was canceled.'] = 'Операция отменена.' phrase['Correction completed! '] = 'Завершено! ' phrase[' fixed in '] = ' обновлено в ' phrase[' actions.'] = ' действиях.' phrase[' bones were'] = ' кости были' phrase[' bone was'] = ' кость была' phrase[' action.'] = ' действие.' phrase[' actions were updated.'] = ' действий(-ия) были обновлены.' phrase[' action was updated.'] = ' действие обновлено.' phrase['Could not find any actions that need to be fixed.'] = 'Нет действий для обновления.' phrase['Actions did not need to be updated'] = 'Действия в обновлениях не нуждаются.' phrase['Could not find a Rig.'] = 'Риг не найден.' phrase['You need to select one bone in this mode.'] = 'Выделите только 1 кость в этом режиме.' phrase['Only one bone should be selected.'] = 'Только 1 кость должна быть выделина.' phrase['No layers selected for active mode.'] = 'Нет выделенных слоёв для этого режима.' phrase['Non uniform scaling not supported for bones.'] = 'Неравномерное масштабирование не работает с костями.' phrase['Channels with separated dimensions were found.'] = 'Найдены разделённые каналы.' phrase['You can Rejoin Dimensions to continue or cancel operation.'] = 'Объедините каналы или отмените операцию.' phrase['Rejoin Dimensions'] = 'Объединить каналы' phrase['Cancel'] = 'Отмена' phrase['Some bones are missing. The skeleton structure was changed.'] = 'Некоторые кости отсутствуют. Структура скелета была изменена.' phrase['EXIT'] = 'Выход' phrase['Some reference keys are missing. Please do not remove or edit any reference keys.'] = 'Некоторые рефенсные ключи отсутствуют. Не удаляйте и не редактируйте их.' phrase['The original number of bones is different.'] = 'Изначальное количество костей отличается.' phrase['Is smartbone is right?'] = 'Is smartbone is right?' phrase['If smartbone is right all R sufixes will be renamed to L'] = 'If smartbone is right all R sufixes will be renamed to L' phrase['Right'] = 'Right' phrase['Left'] = 'Left' phrase['Enter New Name'] = 'Enter New Name' phrase['Duplicate bodypart alert 1'] = 'Выделите одну кость и слои внутри скелета.' phrase['Duplicate bodypart alert 2'] = 'Сам слой скелета не должен быть выделенным.' phrase['Copy bodypart alert 1'] = '1. Выделите скелет КУДА копировать.' phrase['Copy bodypart alert 2'] = '2. Выделите слои в скелете ОТКУДА копировать и одну кость.' phrase['Do You want to rejoin dimensions?'] = 'Соединить каналы?' phrase['No channels with separated dimensions were found.'] = 'Разъединённые каналы не найдены.' phrase['No last flip to repeat'] = 'Ничего не отражалось, чтобы повторить.' phrase['As Action'] = '*' phrase['As Smartbone'] = '+' phrase['Remove'] = '-' phrase['Set R'] = '➞ R' phrase['Set L'] = '➞ L' phrase['Check Names'] = ' Проверить имена ' phrase['Reset Names'] = ' Сбросить имена ' phrase['Auto Mode'] = 'Рекомендовать' phrase['Duplicate only action'] = 'Дублировать только действие' phrase['Duplicate smartbone'] = 'Дублировать действие и смартбоун' phrase['Do not duplicate action'] = 'Не дублировать действие' phrase['Smartbone name does not changed'] = 'Имя не изменено' phrase['Smartbone name is changed'] = 'Имя изменено' phrase['This smartbone name is used'] = 'Это имя занято' phrase['This smartbone name is not used'] = 'Это имя свободно' phrase['Smartbones Manager'] = 'Менеджер смартбоунов' phrase['Missing Utilites'] = 'AE_Utilities не установлены.' phrase['Missing Utilites Info'] = 'AE_Utilities.lua необходим для этого инструмента. Пожалуйста, установите этот файл.' phrase['Please chose how to rename bones and actions:'] = 'Выберите способ переименования костей и действий:' phrase['Direction Mode'] = 'Режим сторон' phrase['Custom Mode'] = 'Режим замены' phrase['Suffix Mode'] = 'Добавить суффикс' phrase['Replace Text'] = 'Заменить текст' phrase['Counter delimiter'] = 'Разделитель счетчика' phrase['Please chose how to rename smartbone:'] = 'Выберите способ переименования смартбоуна:' phrase['Rename Smartbone'] = 'Новое имя' phrase['Duplicate smartbone alert 1'] = 'Выделите один смартбоун' phrase['Apply Custom Translate'] = 'Применить пользовательское смещение. (Alt+Click - в обратном направлении)' phrase['Apply Custom Scale'] = 'Применить пользовательское масштабирование. (Alt+Click - в обратном направлении)' phrase['Apply Custom Rotation'] = 'Применить пользовательское вращение. (Alt+Click - в обратном направлении)' phrase['Suggest Tooltip'] = 'Применить рекомендованые настройки (Alt+Click - сбросить)' phrase['Duplicate Actions Tooltip'] = 'Включить всем \'Дублировать только действие\'' phrase['Remove Actions Tooltip'] = 'Включить всем \'Не дублировать действие\'' phrase['Replace Text 1 Tooltip'] = 'Что найти' phrase['Replace Text 2 Tooltip'] = 'На что заменить' phrase['Replace Text Button Tooltip'] = 'Найти и заменить во всех именах действий (Alt+Click - поменять местами)' phrase['Check Names Tooltip'] = 'Проверить, не заняты ли имена' phrase['Reset Names Tooltip'] = 'Вернуть все имена в исходный вид' phrase['Direction Mode Tooltip'] = 'Имена будут изменены основываясь на стороне' phrase['R to L Tooltip'] = 'Заменить все R на L (Alt+Click - поменять местами)' phrase['L to R Tooltip'] = 'Заменить все L на R (Alt+Click - поменять местами)' phrase['Custom Mode Tooltip'] = 'Имена будут изменены путём поиска и замены' phrase['Reverse Tooltip'] = 'Поменять местами строки поиска и замены' phrase['Suffix Mode Tooltip'] = 'Добавить суффикс к совпадающим именам' phrase['Suffix Tooltip'] = 'Текст суффикса' phrase['Rename Smartbone Tooltip'] = 'Переименовать смартбоун и его действие' phrase['New Smartbone Name Tooltip'] = 'Новое имя для смартбоуна' phrase['Swap Mode'] = 'Менять местами текст' phrase['Swap Mode Tooltip'] = 'Менять местами текст вместо замены' end return phrase[text] end
MR Transform Rig Tool
Listed
Author: eugenebabich
View Script
Script type: Tool
Uploaded: May 30 2022, 06:38
Last modified: May 05 2024, 06:48
Script Version: 1.2.5
This tool allows you to transform parts of the rig without breaking its actions.
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: 2731
MR Transform Rig Tool
Listed
Author: eugenebabich
View Script
Script type: Tool
Uploaded: May 30 2022, 06:38
Last modified: May 05 2024, 06:48
Script Version: 1.2.5
This tool allows you to transform parts of the rig without breaking its actions.
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: 2731