-- ************************************************** -- Provide Moho with the name of this script object -- ************************************************** ScriptName = "AM_Bone_Constraints_Helper" -- ************************************************** -- General information about this script -- ************************************************** AM_Bone_Constraints_Helper = {} function AM_Bone_Constraints_Helper:Name() return self:Localize('UILabel') end function AM_Bone_Constraints_Helper:Version() return '1.0' end function AM_Bone_Constraints_Helper:UILabel() return self:Localize('UILabel') end function AM_Bone_Constraints_Helper:Creator() return 'Aleksei Maletin' end function AM_Bone_Constraints_Helper:Description() return MOHO.Localize("/Scripts/Tool/Autorig/Description=Click to select a new bone (hold <shift> to select a angle control bone , <alt> to select a position control bone , <ctrl/cmd> to select a scale control bone ). Angle = GREEN arrow , Scale = RED arrow , Position = BLUE arrow") end function AM_Bone_Constraints_Helper:ColorizeIcon() return false end -- ************************************************** -- Is Relevant / Is Enabled -- ************************************************** function AM_Bone_Constraints_Helper:ShouldUseParentSkeleton(moho) if (not moho.layer:IsBoneType()) then return true end return false end function AM_Bone_Constraints_Helper:IsRelevant(moho) local skel = moho:Skeleton() if skel then return true else return false end end function AM_Bone_Constraints_Helper:IsEnabled(moho) local skel = moho:Skeleton() if skel then return true else return false end end -- ************************************************** -- Recurring Values -- ************************************************** AM_Bone_Constraints_Helper.bonename = '' AM_Bone_Constraints_Helper.angleControl = 0 AM_Bone_Constraints_Helper.posControlX = 0 AM_Bone_Constraints_Helper.posControlY = 0 AM_Bone_Constraints_Helper.scaleControl = 0 AM_Bone_Constraints_Helper.enableArrows = true AM_Bone_Constraints_Helper.selRect = LM.Rect:new_local() AM_Bone_Constraints_Helper.selBoneID = -1 -- ************************************************** -- Keyboard/Mouse Control -- ************************************************** function AM_Bone_Constraints_Helper:Select(moho, mousePt, mouseVec, mouseView, shiftSelect, ctrlSelect, altSelect) self.selBoneID = -1 local parentSkeleton = false local skel = moho:Skeleton() if (skel == nil) then if (self:ShouldUseParentSkeleton(moho)) then skel = moho:ParentSkeleton() parentSkeleton = true end if (skel == nil) then return end end local id = -1 if (parentSkeleton) then id = mouseView:PickBone(mousePt, mouseVec, moho.layer:ControllingBoneLayer(), true) else id = mouseView:PickBone(mousePt, mouseVec, moho.layer, true) end self.selBoneID = id if (shiftSelect) then elseif (ctrlSelect) then elseif (altSelect) then else for i = 0, skel:CountBones() - 1 do skel:Bone(i).fSelected = (i == id) end end moho:UpdateBonePointSelection() mouseView:DrawMe() moho:UpdateSelectedChannels() end function AM_Bone_Constraints_Helper:OnMouseDown(moho, mouseEvent) local skel = moho:Skeleton() local parentID = mouseEvent.view:PickBone(mouseEvent.pt, mouseEvent.vec, moho.layer, true) self.isMouseDragging = true self.selRect.left = mouseEvent.startPt.x self.selRect.top = mouseEvent.startPt.y self.selRect.right = mouseEvent.pt.x self.selRect.bottom = mouseEvent.pt.y mouseEvent.view:Graphics():SelectionRect(self.selRect) mouseEvent.view:DrawMe() -- Try to select a bone by clicking on it self:Select(moho, mouseEvent.pt, mouseEvent.vec, mouseEvent.view, mouseEvent.shiftKey, mouseEvent.ctrlKey, mouseEvent.altKey) if (mouseEvent.ctrlKey) then moho.document:SetDirty() moho.document:PrepUndo(nil) self.controlKeyPressed = true for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected and i ~= parentID and parentID ~= bone.fScaleControlParent) then bone.fScaleControlParent = parentID end end moho.layer:UpdateCurFrame() end if (mouseEvent.altKey) then moho.document:SetDirty() moho.document:PrepUndo(nil) for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected and i ~= parentID and parentID ~= bone.fPosControlParent) then bone.fPosControlParent = parentID end end moho.layer:UpdateCurFrame() end if (mouseEvent.shiftKey) then moho.document:SetDirty() moho.document:PrepUndo(nil) for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected and i ~= parentID and parentID ~= bone.fAngleControlParent) then bone.fAngleControlParent = parentID end end moho.layer:UpdateCurFrame() end end function AM_Bone_Constraints_Helper:OnMouseMoved(moho, mouseEvent) local mesh = moho:DrawingMesh() local skel = moho:Skeleton() if moho.layer:LayerType() == MOHO.LT_VECTOR then if (mesh == nil) then return end else if (skel == nil) then return end end mouseEvent.view:Graphics():SelectionRect(self.selRect) self.selRect.right = mouseEvent.pt.x self.selRect.bottom = mouseEvent.pt.y mouseEvent.view:Graphics():SelectionRect(self.selRect) mouseEvent.view:RefreshView() mouseEvent.view:DrawMe() end function AM_Bone_Constraints_Helper:OnMouseUp(moho, mouseEvent) local mesh = moho:DrawingMesh() local skel = moho:Skeleton() if moho.layer:LayerType() == MOHO.LT_VECTOR then if (mesh == nil) then return end else if (skel == nil) then return end end local mouseDist = math.abs(mouseEvent.pt.x - mouseEvent.startPt.x) + math.abs(mouseEvent.pt.y - mouseEvent.startPt.y) self.isMouseDragging = false local v = LM.Vector2:new_local() local screenPt = LM.Point:new_local() local m = LM.Matrix:new_local() self.selRect:Normalize() moho.drawingLayer:GetFullTransform(moho.frame, m, moho.document) if skel then for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) local boneMatrix = bone.fMovedMatrix for j = 0, 10 do v:Set(bone.fLength * j / 10.0, 0) boneMatrix:Transform(v) m:Transform(v) mouseEvent.view:Graphics():WorldToScreen(v, screenPt) if (self.selRect:Contains(screenPt)) then bone.fSelected = true --self:Select(moho, mouseEvent.pt, mouseEvent.vec, mouseEvent.view, mouseEvent.shiftKey, mouseEvent.ctrlKey, mouseEvent.altKey) break end end end end moho:UpdateSelectedChannels() end function AM_Bone_Constraints_Helper:OnKeyDown(moho, keyEvent) end function AM_Bone_Constraints_Helper:OnKeyUp(moho, keyEvent) end function AM_Bone_Constraints_Helper:DrawAngleControlArrows(moho, view) if self.enableArrows then local skel = moho:Skeleton() if (skel == nil) then return end local g = view:Graphics() local matrix = LM.Matrix:new_local() local bonePt = LM.Vector2:new_local() local parentPt = LM.Vector2:new_local() local arrowPt1 = LM.Vector2:new_local() local arrowPt2 = LM.Vector2:new_local() moho.layer:GetFullTransform(moho.frame, matrix, moho.document) g:Push() g:ApplyMatrix(matrix) g:SetSmoothing(true) for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fAngleControlParent >= 0) then local parentBone = skel:Bone(bone.fAngleControlParent) bonePt:Set(bone.fLength / 2, 0) bone.fMovedMatrix:Transform(bonePt) parentPt:Set(parentBone.fLength / 2, 0) parentBone.fMovedMatrix:Transform(parentPt) local v = parentPt - bonePt local mag = v:Mag() local f = mag if (f > 0.2) then f = 0.2 end arrowPt1:Set(mag - f / 4, -f / 16) arrowPt2:Set(mag - f / 4, f / 16) f = math.atan2(v.y, v.x) arrowPt1:Rotate(f) arrowPt2:Rotate(f) arrowPt1.x = arrowPt1.x + bonePt.x arrowPt1.y = arrowPt1.y + bonePt.y arrowPt2.x = arrowPt2.x + bonePt.x arrowPt2.y = arrowPt2.y + bonePt.y if (bone.fSelected) then g:SetColor(0, 255, 0, 255) else g:SetColor(50, 200, 50, 255) end g:DrawLine(bonePt.x, bonePt.y, parentPt.x, parentPt.y) g:BeginShape() g:AddLine(parentPt, arrowPt1) g:AddLine(arrowPt1, arrowPt2) g:AddLine(arrowPt2, parentPt) g:EndShape() end end g:Pop() end end function AM_Bone_Constraints_Helper:DrawPosControlArrows(moho, view) if self.enableArrows then local skel = moho:Skeleton() if (skel == nil) then return end local g = view:Graphics() local matrix = LM.Matrix:new_local() local bonePt = LM.Vector2:new_local() local parentPt = LM.Vector2:new_local() local arrowPt1 = LM.Vector2:new_local() local arrowPt2 = LM.Vector2:new_local() moho.layer:GetFullTransform(moho.frame, matrix, moho.document) g:Push() g:ApplyMatrix(matrix) g:SetSmoothing(true) for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fPosControlParent >= 0) then local parentBone = skel:Bone(bone.fPosControlParent) bonePt:Set(bone.fLength / 2, 0) bone.fMovedMatrix:Transform(bonePt) parentPt:Set(parentBone.fLength / 2, 0) parentBone.fMovedMatrix:Transform(parentPt) local v = parentPt - bonePt local mag = v:Mag() local f = mag if (f > 0.2) then f = 0.2 end arrowPt1:Set(mag - f / 4, -f / 16) arrowPt2:Set(mag - f / 4, f / 16) f = math.atan2(v.y, v.x) arrowPt1:Rotate(f) arrowPt2:Rotate(f) arrowPt1.x = arrowPt1.x + bonePt.x arrowPt1.y = arrowPt1.y + bonePt.y arrowPt2.x = arrowPt2.x + bonePt.x arrowPt2.y = arrowPt2.y + bonePt.y if (bone.fSelected) then g:SetColor(0, 0, 255, 255) else g:SetColor(50, 50, 200, 255) end g:DrawLine(bonePt.x, bonePt.y, parentPt.x, parentPt.y) g:BeginShape() g:AddLine(parentPt, arrowPt1) g:AddLine(arrowPt1, arrowPt2) g:AddLine(arrowPt2, parentPt) g:EndShape() end end g:Pop() end end function AM_Bone_Constraints_Helper:DrawScaleControlArrows(moho, view) if self.enableArrows then local skel = moho:Skeleton() if (skel == nil) then return end local g = view:Graphics() local matrix = LM.Matrix:new_local() local bonePt = LM.Vector2:new_local() local parentPt = LM.Vector2:new_local() local arrowPt1 = LM.Vector2:new_local() local arrowPt2 = LM.Vector2:new_local() moho.layer:GetFullTransform(moho.frame, matrix, moho.document) g:Push() g:ApplyMatrix(matrix) g:SetSmoothing(true) for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fScaleControlParent >= 0) then local parentBone = skel:Bone(bone.fScaleControlParent) if parentBone then bonePt:Set(bone.fLength / 2, 0) bone.fMovedMatrix:Transform(bonePt) parentPt:Set(parentBone.fLength / 2, 0) parentBone.fMovedMatrix:Transform(parentPt) local v = parentPt - bonePt local mag = v:Mag() local f = mag if (f > 0.2) then f = 0.2 end arrowPt1:Set(mag - f / 4, -f / 16) arrowPt2:Set(mag - f / 4, f / 16) f = math.atan2(v.y, v.x) arrowPt1:Rotate(f) arrowPt2:Rotate(f) arrowPt1.x = arrowPt1.x + bonePt.x arrowPt1.y = arrowPt1.y + bonePt.y arrowPt2.x = arrowPt2.x + bonePt.x arrowPt2.y = arrowPt2.y + bonePt.y if (bone.fSelected) then g:SetColor(255, 0, 0, 255) else g:SetColor(200, 50, 50, 255) end g:DrawLine(bonePt.x, bonePt.y, parentPt.x, parentPt.y) g:BeginShape() g:AddLine(parentPt, arrowPt1) g:AddLine(arrowPt1, arrowPt2) g:AddLine(arrowPt2, parentPt) g:EndShape() end end end g:Pop() end end function AM_Bone_Constraints_Helper:DrawMe(moho, view) if self.enableArrows then self:DrawAngleControlArrows(moho, view) self:DrawScaleControlArrows(moho, view) self:DrawPosControlArrows(moho, view) end if self.isMouseDragging then local g = view:Graphics() g:SelectionRect(self.selRect) end -- Draw bezier handles if AE_Utilities then if (self.showBezierHandles and self.useCurvature) then local mesh = moho:DrawingMesh() if (mesh == nil) then return end local g = view:Graphics() local layerMatrix = LM.Matrix:new_local() moho.drawingLayer:GetFullTransform(moho.frame, layerMatrix, moho.document) g:Push() g:ApplyMatrix(layerMatrix) g:SetSmoothing(true) local meshLayer = moho:LayerAsVector(moho.drawingLayer) if (moho:CountSelectedPoints() > 0) then meshLayer:DrawHandles(moho.document, g, true) else meshLayer:DrawHandles(moho.document, g, false) end g:Pop() end end end -- ************************************************** -- Tool Panel Layout -- ************************************************** AM_Bone_Constraints_Helper.BONENAME = MOHO.MSG_BASE AM_Bone_Constraints_Helper.ANGLECONTROL = MOHO.MSG_BASE + 1 AM_Bone_Constraints_Helper.POSCONTROLX = MOHO.MSG_BASE + 2 AM_Bone_Constraints_Helper.POSCONTROLY = MOHO.MSG_BASE + 3 AM_Bone_Constraints_Helper.SCALECONTROL = MOHO.MSG_BASE + 4 AM_Bone_Constraints_Helper.DUMMY = MOHO.MSG_BASE + 5 AM_Bone_Constraints_Helper.SELECTITEM = MOHO.MSG_BASE + 7 AM_Bone_Constraints_Helper.SELECTCONTROL = MOHO.MSG_BASE + 6 function AM_Bone_Constraints_Helper:DoLayout(moho, layout) self.menu = LM.GUI.Menu(self:Localize('Select Bone')) self.menu_popup = LM.GUI.PopupMenu(120, false) self.menu_popup:SetMenu(self.menu) layout:AddChild(self.menu_popup) self.boneName = LM.GUI.TextControl(0, ' ', self.BONENAME, LM.GUI.FIELD_TEXT) layout:AddChild(self.boneName) self.boneName:SetValue("") self.angleControlBoneText = LM.GUI.DynamicText(self:Localize('Angle control:'), 0) layout:AddChild(self.angleControlBoneText, LM.GUI.ALIGN_LEFT, 0) self.angleControlInput = LM.GUI.TextControl(0, '00.0000', self.ANGLECONTROL, LM.GUI.FIELD_FLOAT, self:Localize('')) layout:AddChild(self.angleControlInput, LM.GUI.ALIGN_LEFT, 0) self.positionControlBoneText = LM.GUI.DynamicText(self:Localize('Position control:'), 0) layout:AddChild(self.positionControlBoneText, LM.GUI.ALIGN_LEFT, 0) self.posControlXInput = LM.GUI.TextControl(0, '00.000', self.POSCONTROLX, LM.GUI.FIELD_FLOAT, self:Localize('X')) layout:AddChild(self.posControlXInput, LM.GUI.ALIGN_LEFT, 0) self.posControlYInput = LM.GUI.TextControl(0, '00.000', self.POSCONTROLY, LM.GUI.FIELD_FLOAT, self:Localize('Y')) layout:AddChild(self.posControlYInput, LM.GUI.ALIGN_LEFT, 0) self.scaleControlBoneText = LM.GUI.DynamicText(self:Localize('Scale control:'), 0) layout:AddChild(self.scaleControlBoneText, LM.GUI.ALIGN_LEFT, 0) self.scaleControlInput = LM.GUI.TextControl(0, '00.0000', self.SCALECONTROL, LM.GUI.FIELD_FLOAT, self:Localize('')) layout:AddChild(self.scaleControlInput, LM.GUI.ALIGN_LEFT, 0) end function AM_Bone_Constraints_Helper:UpdateWidgets(moho) local skel = moho:Skeleton() if (skel == nil) then if (self:ShouldUseParentSkeleton(moho)) then skel = moho:ParentSkeleton() end if (skel == nil) then return end end local selID = skel:SelectedBoneID() local bone = skel:Bone(selID) MOHO.BuildBoneMenu(self.menu, skel, self.SELECTITEM, self.DUMMY) if (selID >= 0) then local bone = skel:Bone(selID) self.boneName:SetValue(bone:Name()) else self.boneName:SetValue("") end if bone then if bone.fAngleControlParent >= 0 then self.angleControlInput:Enable(true) else self.angleControlInput:Enable(false) end if bone.fScaleControlParent >= 0 then self.scaleControlInput:Enable(true) else self.scaleControlInput:Enable(false) end if bone.fPosControlParent >=0 then self.posControlXInput:Enable(true) self.posControlYInput:Enable(true) else self.posControlXInput:Enable(false) self.posControlYInput:Enable(false) end AM_Bone_Constraints_Helper.angleControlInput:SetValue(bone.fAngleControlScale) AM_Bone_Constraints_Helper.posControlXInput:SetValue(bone.fPosControlScale.x) AM_Bone_Constraints_Helper.posControlYInput:SetValue(bone.fPosControlScale.y) AM_Bone_Constraints_Helper.scaleControlInput:SetValue(bone.fScaleControlScale) else self.angleControlInput:Enable(false) self.scaleControlInput:Enable(false) self.posControlXInput:Enable(false) self.posControlYInput:Enable(false) AM_Bone_Constraints_Helper.angleControlInput:SetValue('00.0000') AM_Bone_Constraints_Helper.posControlXInput:SetValue('00.0000') AM_Bone_Constraints_Helper.posControlYInput:SetValue('00.0000') AM_Bone_Constraints_Helper.scaleControlInput:SetValue('00.0000') end end function AM_Bone_Constraints_Helper:HandleMessage(moho, view, msg) local skel = moho:Skeleton() local layer = moho.layer if (skel == nil) then if (self:ShouldUseParentSkeleton(moho)) then skel = moho:ParentSkeleton() end if (skel == nil) then return end layer = moho.layer:ControllingBoneLayer() end local selID = skel:SelectedBoneID() local bone = skel:Bone(selID) if msg == self.BONENAME then if (skel:SelectedBoneID() >= 0) then moho.document:PrepUndo(layer, true) moho.document:SetDirty() for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected) then bone:SetName(self.boneName:Value()) skel:MakeBoneNameUnique(i) end end moho:UpdateUI() end elseif msg == self.ANGLECONTROL then if (skel:SelectedBoneID() >= 0) then moho.document:PrepUndo(layer, true) moho.document:SetDirty() for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected) then bone.fAngleControlScale = self.angleControlInput:Value() end end moho:UpdateUI() end elseif msg == self.POSCONTROLX then if (skel:SelectedBoneID() >= 0) then moho.document:PrepUndo(layer, true) moho.document:SetDirty() for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected) then bone.fPosControlScale.x = self.posControlXInput:Value() end end moho:UpdateUI() end elseif msg == self.POSCONTROLY then if (skel:SelectedBoneID() >= 0) then moho.document:PrepUndo(layer, true) moho.document:SetDirty() for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected) then bone.fPosControlScale.y = self.posControlYInput:Value() end end moho:UpdateUI() end elseif msg == self.SCALECONTROL then if (skel:SelectedBoneID() >= 0) then moho.document:PrepUndo(layer, true) moho.document:SetDirty() for i = 0, skel:CountBones() - 1 do local bone = skel:Bone(i) if (bone.fSelected) then bone.fScaleControlScale = self.scaleControlInput:Value() end end moho:UpdateUI() end elseif (msg >= self.SELECTITEM) then for i = 0, skel:CountBones() - 1 do skel:Bone(i).fSelected = (i == msg - self.SELECTITEM) end moho:UpdateUI() else end end -- ************************************************** -- Localization -- ************************************************** function AM_Bone_Constraints_Helper:Localize(text) local phrase = {} phrase['Description'] = '' phrase['UILabel'] = 'Bone Constraints Helper' phrase['Select Bone'] = 'Select Bone' phrase['Angle control:'] = 'Angle control:' phrase['<None>'] = '<None>' phrase['Position control:'] = 'Position control:' phrase['<None>'] = '<None>' phrase['X'] = 'X' phrase['Y'] = 'Y' phrase['Scale control:'] = 'Scale control:' phrase['<None>'] = '<None>' local fileWord = MOHO.Localize("/Menus/File/File=File") if fileWord == "Файл" then phrase['Description'] = '' phrase['UILabel'] = 'Bone Constraints Helper' phrase['Select Bone'] = 'Select Bone' phrase['Angle control:'] = 'Angle control:' phrase['<None>'] = '<None>' phrase['Position control:'] = 'Position control:' phrase['<None>'] = '<None>' phrase['X'] = 'X' phrase['Y'] = 'Y' phrase['Scale control:'] = 'Scale control:' phrase['<None>'] = '<None>' end return phrase[text] end
Bone Constraints Helper
Listed
Author: Danfield
View Script
Script type: Tool
Uploaded: Jan 20 2022, 11:07
Last modified: Jan 20 2022, 11:12
Handy tool for working with bone constraints
Click to select a bone. With a bone selected, Shift+Click to set the Angle Control bone, Ctrl+Click to set the Scale Control bone, Alt+Click to set the Position Control bone.
The script also shows you the constraints as color-coded arrows. The green arrow is Angle, the red one is Scale, and the blue one is Position.
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: 1008
Bone Constraints Helper
Listed
Author: Danfield
View Script
Script type: Tool
Uploaded: Jan 20 2022, 11:07
Last modified: Jan 20 2022, 11:12
Handy tool for working with bone constraints
Click to select a bone. With a bone selected, Shift+Click to set the Angle Control bone, Ctrl+Click to set the Scale Control bone, Alt+Click to set the Position Control bone.
The script also shows you the constraints as color-coded arrows. The green arrow is Angle, the red one is Scale, and the blue one is Position.
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: 1008