Great idea. I just did that myself. Have to disable wind before I can disable dynamics, but that's a much rarer task.
Code: Select all
-- **************************************************
-- Provide Moho with the name of this script object
-- **************************************************
ScriptName = "LM_SelectBone"
-- **************************************************
-- General information about this script
-- **************************************************
LM_SelectBone = {}
LM_SelectBone.BASE_STR = 2285
function LM_SelectBone:Name()
return "Select Bone"
end
function LM_SelectBone:Version()
return "6.0"
end
function LM_SelectBone:Description()
return MOHO.Localize("/Scripts/Tool/SelectBone/Description=Click to select a bone (hold <shift> or <ctrl/cmd> to select more than one bone)")
end
function LM_SelectBone:Creator()
return "Lost Marble LLC, modded by J.Wesley Fowler (synthsin75)"
end
function LM_SelectBone:UILabel()
return(MOHO.Localize("/Scripts/Tool/SelectBone/SelectBone=Select Bone"))
end
function LM_SelectBone:LoadPrefs(prefs)
self.lassoMode = prefs:GetBool("LM_SelectBone.lassoMode", false)
end
function LM_SelectBone:SavePrefs(prefs)
prefs:SetBool("LM_SelectBone.lassoMode", self.lassoMode)
end
function LM_SelectBone:ResetPrefs()
self.lassoMode = false
end
-- **************************************************
-- Recurring values
-- **************************************************
LM_SelectBone.selBoneID = -1
LM_SelectBone.selRect = LM.Rect:new_local()
LM_SelectBone.previousX = 0
LM_SelectBone.previousY = 0
LM_SelectBone.isMouseDragging = false
-- **************************************************
-- The guts of this script
-- **************************************************
function LM_SelectBone:ShouldUseParentSkeleton(moho)
if (not moho.layer:IsBoneType()) then
return true
end
return false
end
function LM_SelectBone:IsEnabled(moho)
local skel = moho:Skeleton()
if (skel == nil) then
if (self:ShouldUseParentSkeleton(moho)) then
skel = moho:ParentSkeleton()
end
if (skel == nil) then
return false
end
end
return true
end
function LM_SelectBone:IsRelevant(moho)
local skel = moho:Skeleton()
if (skel == nil) then
if (self:ShouldUseParentSkeleton(moho)) then
skel = moho:ParentSkeleton()
end
if (skel == nil) then
return false
end
end
return true
end
function LM_SelectBone:OnMouseDown(moho, mouseEvent)
self.isMouseDragging = true
self.selRect.left = -10
self.selRect.top = -10
self.selRect.right = -5
self.selRect.bottom = -5
-- Try to select a bone by clicking on it
self:Select(moho, mouseEvent.pt, mouseEvent.vec, mouseEvent.view, mouseEvent.shiftKey, mouseEvent.ctrlKey)
-- If no bone was selected, start dragging out a marquee selection
local lassoMode = false
self.ctrlKeySelection = false
if (self.lassoMode) then
if (not(mouseEvent.ctrlKey)) then
lassoMode = true
else
self.ctrlKeySelection = true
end
else
if (mouseEvent.ctrlKey) then
lassoMode = true
self.ctrlKeySelection = true
end
end
mouseEvent.view:DrawMe()
if (self.selBoneID == -1) then
if (lassoMode) then
self.lassoList = { { mouseEvent.startPt.x, mouseEvent.startPt.y } }
self.previousX = mouseEvent.startPt.x
self.previousY = mouseEvent.startPt.y
else
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)
end
end
end
function LM_SelectBone:OnMouseMoved(moho, mouseEvent)
--self:Select(moho, mouseEvent.pt, mouseEvent.vec, mouseEvent.view, mouseEvent.shiftKey, mouseEvent.ctrlKey)
if (self.selBoneID >= 0) then
return
end
local lassoMode = false
if (self.lassoMode) then
if (not(self.ctrlKeySelection)) then
lassoMode = true
end
else
if (self.ctrlKeySelection) then
lassoMode = true
end
end
if (lassoMode) then
local g = mouseEvent.view:Graphics()
g:SetSmoothing(true)
g:Push()
local m = g:CurrentTransform()
m:Invert()
g:ApplyMatrix(m)
g:SetColor(MOHO.MohoGlobals.SelCol)
g:MoveTo(self.previousX, self.previousY)
g:LineTo(mouseEvent.pt.x, mouseEvent.pt.y)
g:Pop()
g:SetSmoothing(false)
mouseEvent.view:RefreshView()
table.insert(self.lassoList, { mouseEvent.pt.x, mouseEvent.pt.y })
self.previousX = mouseEvent.pt.x
self.previousY = mouseEvent.pt.y
else
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()
end
mouseEvent.view:DrawMe()
end
function LM_SelectBone:OnMouseUp(moho, mouseEvent)
if (self.selBoneID >= 0) then
return
end
self.isMouseDragging = false
local lassoMode = false
if (self.lassoMode) then
if (not(self.ctrlKeySelection)) then
lassoMode = true
end
else
if (self.ctrlKeySelection) then
lassoMode = true
end
end
if (lassoMode) then
-- draw the finalized lasso outline
local g = mouseEvent.view:Graphics()
g:SetSmoothing(true)
g:Push()
local m = g:CurrentTransform()
m:Invert()
g:ApplyMatrix(m)
g:SetColor(MOHO.MohoGlobals.SelCol)
g:MoveTo(self.previousX, self.previousY)
g:LineTo(mouseEvent.startPt.x, mouseEvent.startPt.y)
g:Pop()
g:SetSmoothing(false)
mouseEvent.view:RefreshView()
LM.Snooze(100)
end
-- 1 - Draw the selection shape, either a lasso or a rectangle
local end1 = LM.Vector2:new_local()
local end2 = LM.Vector2:new_local()
local g = mouseEvent.view:Graphics()
g:Clear(0, 0, 0, 0)
g:Push()
local m = g:CurrentTransform()
m:Invert()
g:ApplyMatrix(m)
g:SetColor(255, 255, 255, 255)
g:BeginShape()
if (lassoMode) then
for i = 1, #self.lassoList - 1 do
end1:Set(self.lassoList[i][1], self.lassoList[i][2])
end2:Set(self.lassoList[i + 1][1], self.lassoList[i + 1][2])
g:AddLine(end1, end2)
end
end1:Set(self.lassoList[#self.lassoList][1], self.lassoList[#self.lassoList][2])
end2:Set(self.lassoList[1][1], self.lassoList[1][2])
g:AddLine(end1, end2)
else
end1:Set(mouseEvent.startPt.x, mouseEvent.startPt.y)
end2:Set(mouseEvent.pt.x, mouseEvent.startPt.y)
g:AddLine(end1, end2)
end1:Set(end2.x, end2.y)
end2:Set(mouseEvent.pt.x, mouseEvent.pt.y)
g:AddLine(end1, end2)
end1:Set(end2.x, end2.y)
end2:Set(mouseEvent.startPt.x, mouseEvent.pt.y)
g:AddLine(end1, end2)
end1:Set(end2.x, end2.y)
end2:Set(mouseEvent.startPt.x, mouseEvent.startPt.y)
g:AddLine(end1, end2)
end
g:EndShape()
g:Pop()
-- test code to view the lasso's shape
--mouseEvent.view:RefreshView()
--LM.Snooze(1000)
-- 2 - Do hit testing on the selection shape
local v = LM.Vector2:new_local()
local screenPt = LM.Point:new_local()
local m = LM.Matrix:new_local()
local parentSkeleton = false
local skel = moho:Skeleton()
moho.layer:GetFullTransform(moho.frame, m, moho.document)
if (skel == nil) then
if (self:ShouldUseParentSkeleton(moho)) then
skel = moho:ParentSkeleton()
parentSkeleton = true
moho.layer:ControllingBoneLayer():GetFullTransform(moho.frame, m, moho.document)
end
end
if (skel ~= nil) then
for i = 0, skel:CountBones() - 1 do
local bone = skel:Bone(i)
if ((not bone.fHidden) and bone:IsGroupVisible()) then
local boneMatrix = bone.fMovedMatrix
if (moho.frame == 0) then
boneMatrix = bone.fRestMatrix
end
for j = 0, 10 do
v:Set(bone.fLength * j / 10.0, 0)
boneMatrix:Transform(v)
m:Transform(v)
g:WorldToScreen(v, screenPt)
if (g:IsFullWhite(screenPt)) then
if (mouseEvent.shiftKey) then
bone.fSelected = not bone.fSelected
else
bone.fSelected = true
end
break
end
end
end
end
end
self.lassoList = nil
mouseEvent.view:DrawMe()
moho:UpdateSelectedChannels()
end
function LM_SelectBone:Select(moho, mousePt, mouseVec, mouseView, shiftSelect, ctrlSelect)
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
if (id >= 0) then
skel:Bone(id).fSelected = true
end
elseif (ctrlSelect) then
if (id >= 0) then
skel:Bone(id).fSelected = not skel:Bone(id).fSelected
end
else
for i = 0, skel:CountBones() - 1 do
skel:Bone(i).fSelected = (i == id)
end
end
moho:UpdateBonePointSelection()
mouseView:DrawMe()
moho:UpdateSelectedChannels()
end
function LM_SelectBone:OnKeyDown(moho, keyEvent)
local skel = moho:Skeleton()
if (skel == nil) then
if (self:ShouldUseParentSkeleton(moho)) then
skel = moho:ParentSkeleton()
end
if (skel == nil) then
return
end
end
if (keyEvent.keyCode == LM.GUI.KEY_UP and not keyEvent.ctrlKey) then
for i = 0, skel:CountBones() - 1 do
if (skel:Bone(i).fSelected) then
local pID = skel:Bone(i).fParent
if (pID >= 0) then
skel:Bone(i).fSelected = false
skel:Bone(pID).fSelected = true
end
break
end
end
moho:UpdateBonePointSelection()
keyEvent.view:DrawMe()
moho:UpdateSelectedChannels()
elseif (keyEvent.keyCode == LM.GUI.KEY_DOWN and not keyEvent.ctrlKey) then
for i = 0, skel:CountBones() - 1 do
if (skel:Bone(i).fSelected) then
local childID = -1
if (skel:CountBoneChildren(i) == 1) then
childID = skel:GetFirstChildBone(i)
end
if (childID >= 0) then
skel:Bone(i).fSelected = false
skel:Bone(childID).fSelected = true
end
break
end
end
moho:UpdateBonePointSelection()
keyEvent.view:DrawMe()
moho:UpdateSelectedChannels()
elseif ((keyEvent.keyCode == LM.GUI.KEY_DELETE) or (keyEvent.keyCode == LM.GUI.KEY_BACKSPACE)) then
if (moho.layer:IsBoneType() and (moho.layerFrame == 0 or not moho:DisableDrawingTools())) then
local boneLayer = moho:LayerAsGroup(moho.layer)
moho.document:PrepUndo(moho.layer, false)
moho.document:SetDirty()
keepTrying = true
while keepTrying do
keepTrying = false
for i = 0, skel:CountBones() - 1 do
if (skel:Bone(i).fSelected) then
for j = 0, boneLayer:CountLayers() - 1 do
boneLayer:Layer(j):DeleteParentBone(i)
end
skel:DeleteBone(i)
keepTrying = true
break
end
end
end
moho:SetCurFrame(moho.frame) -- trigger an update of all the bones in case they're undergoing a preview with the manipulate bones tool or something
keyEvent.view:DrawMe()
end
end
end
function LM_SelectBone:DrawMe(moho, view)
if (self.isMouseDragging) then
local g = view:Graphics()
local lassoMode = false
if (self.lassoMode) then
if (not(self.ctrlKeySelection)) then
lassoMode = true
end
else
if (self.ctrlKeySelection) then
lassoMode = true
end
end
if (lassoMode and self.lassoList) then
g:SetSmoothing(true)
g:Push()
local m = g:CurrentTransform()
m:Invert()
g:ApplyMatrix(m)
g:SetColor(MOHO.MohoGlobals.SelCol)
g:MoveTo(self.lassoList[1][1], self.lassoList[1][2])
for i = 2, #self.lassoList do
g:LineTo(self.lassoList[i][1], self.lassoList[i][2])
end
g:Pop()
g:SetSmoothing(false)
else
g:SelectionRect(self.selRect)
end
end
end
-- **************************************************
-- Bone constraints dialog
-- **************************************************
local LM_SelectBoneDialog = {}
function LM_SelectBoneDialog:new()
local d = LM.GUI.SimpleDialog(MOHO.Localize("/Scripts/Tool/SelectBone/BoneConstraints=Bone Constraints"), LM_SelectBoneDialog)
local l = d:GetLayout()
l:PushV(LM.GUI.ALIGN_LEFT, 0)
d.angleConstraints = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/AngleConstraints=Angle constraints:"), LM_SelectBone.DLOG_CHANGE)
l:AddChild(d.angleConstraints, LM.GUI.ALIGN_LEFT)
l:PushH()
l:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/SelectBone/MinMaxDegrees=Min/max (degrees)")))
d.minAngle = LM.GUI.TextControl(0, "0000.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_FLOAT)
d.minAngle:SetWheelInc(5)
l:AddChild(d.minAngle)
d.maxAngle = LM.GUI.TextControl(0, "0000.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_FLOAT)
d.maxAngle:SetWheelInc(5)
l:AddChild(d.maxAngle)
l:Pop()
if (MOHO.IsMohoPro()) then
l:AddPadding()
d.fixedAngle = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/IndependentAngle=Independent angle"), LM_SelectBone.DLOG_CHANGE)
l:AddChild(d.fixedAngle, LM.GUI.ALIGN_LEFT)
l:AddPadding()
l:PushH(LM.GUI.ALIGN_LEFT)
l:PushV(LM.GUI.ALIGN_LEFT)
d.squashScaling = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/SquashAndStretchScaling=Squash and stretch scaling"), LM_SelectBone.DLOG_CHANGE)
l:AddChild(d.squashScaling, LM.GUI.ALIGN_LEFT)
l:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/SelectBone/MaximumIKStretching=Maximum IK stretching")), LM.GUI.ALIGN_LEFT)
l:Pop()
l:PushV(LM.GUI.ALIGN_LEFT)
d.maxStretchScaling = LM.GUI.TextControl(0, "0000.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_UFLOAT)
d.maxStretchScaling:SetWheelInc(0.1)
l:AddChild(d.maxStretchScaling, LM.GUI.ALIGN_LEFT)
d.maxAutoScaling = LM.GUI.TextControl(0, "0000.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_UFLOAT)
d.maxAutoScaling:SetWheelInc(0.1)
l:AddChild(d.maxAutoScaling, LM.GUI.ALIGN_LEFT)
l:Pop()
l:Pop()
l:AddPadding()
d.arcSolver = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/ArcIKSolver=Arc IK solver"), LM_SelectBone.DLOG_CHANGE)
l:AddChild(d.arcSolver, LM.GUI.ALIGN_LEFT)
d.ignoredByIK = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/IgnoredByInverseKinematics=Ignored by inverse kinematics"), LM_SelectBone.DLOG_CHANGE)
l:AddChild(d.ignoredByIK, LM.GUI.ALIGN_LEFT)
l:AddPadding()
l:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/SelectBone/Target=Target:")), LM.GUI.ALIGN_LEFT)
l:PushH()
d.targetMenu = LM.GUI.Menu(MOHO.Localize("/Scripts/Tool/SelectBone/SelectBone=Select Bone"))
d.targetPopup = LM.GUI.PopupMenu(128, true)
d.targetPopup:SetMenu(d.targetMenu)
l:AddChild(d.targetPopup)
l:Pop()
end
l:AddPadding()
l:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/SelectBone/AngleControlBone=Angle control bone:")), LM.GUI.ALIGN_LEFT)
l:PushH()
d.acMenu = LM.GUI.Menu(MOHO.Localize("/Scripts/Tool/SelectBone/SelectBone=Select Bone"))
d.acPopup = LM.GUI.PopupMenu(128, true)
d.acPopup:SetMenu(d.acMenu)
l:AddChild(d.acPopup)
d.angleControl = LM.GUI.TextControl(0, "00.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_FLOAT)
l:AddChild(d.angleControl)
l:Pop()
l:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/SelectBone/PositionControlBone=Position control bone:")), LM.GUI.ALIGN_LEFT)
l:PushH()
d.pcMenu = LM.GUI.Menu(MOHO.Localize("/Scripts/Tool/SelectBone/SelectBone=Select Bone"))
d.pcPopup = LM.GUI.PopupMenu(128, true)
d.pcPopup:SetMenu(d.pcMenu)
l:AddChild(d.pcPopup)
d.posControlX = LM.GUI.TextControl(0, "00.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_FLOAT)
l:AddChild(d.posControlX)
d.posControlY = LM.GUI.TextControl(0, "00.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_FLOAT)
l:AddChild(d.posControlY)
l:Pop()
l:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/SelectBone/ScaleControlBone=Scale control bone:")), LM.GUI.ALIGN_LEFT)
l:PushH()
d.scMenu = LM.GUI.Menu(MOHO.Localize("/Scripts/Tool/SelectBone/SelectBone=Select Bone"))
d.scPopup = LM.GUI.PopupMenu(128, true)
d.scPopup:SetMenu(d.scMenu)
l:AddChild(d.scPopup)
d.scaleControl = LM.GUI.TextControl(0, "00.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_FLOAT)
l:AddChild(d.scaleControl)
l:Pop()
d.boneDynamics = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/BoneDynamics=Bone dynamics:"), LM_SelectBone.DLOG_CHANGE)
l:AddChild(d.boneDynamics, LM.GUI.ALIGN_LEFT)
l:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/SelectBone/TorqueSpringDampingForce=Torque force / Spring force / Damping force")), LM.GUI.ALIGN_LEFT)
l:PushH()
d.torque = LM.GUI.TextControl(0, "00.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_UFLOAT)
d.torque:SetWheelInc(0.1)
l:AddChild(d.torque)
d.spring = LM.GUI.TextControl(0, "00.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_UFLOAT)
d.spring:SetWheelInc(0.1)
l:AddChild(d.spring)
d.damping = LM.GUI.TextControl(0, "00.0000", LM_SelectBone.DLOG_CHANGE, LM.GUI.FIELD_UFLOAT)
d.damping:SetWheelInc(0.1)
l:AddChild(d.damping)
d.windDynamics = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/Wind=Wind"), LM_SelectBone.DLOG_CHANGE)
l:AddChild(d.windDynamics)
l:Pop()
l:PushH(LM.GUI.ALIGN_RIGHT, 0)
l:AddChild(LM.GUI.Button(MOHO.Localize("/Scripts/Tool/SelectBone/Close=Close"), LM.GUI.MSG_CANCEL))
l:Pop()
l:Pop()
return d
end
function LM_SelectBoneDialog:UpdateWidgets(moho)
if (self.document and self.layer and self.skel and self.bone) then
self.angleConstraints:Enable(true)
if (MOHO.IsMohoPro()) then
self.targetPopup:Enable(true)
end
self.acPopup:Enable(true)
self.pcPopup:Enable(true)
self.scPopup:Enable(true)
self.boneDynamics:Enable(true)
self.angleConstraints:SetValue(self.bone.fConstraints)
self.minAngle:SetValue(math.deg(self.bone.fMinConstraint))
self.maxAngle:SetValue(math.deg(self.bone.fMaxConstraint))
self.minAngle:Enable(self.bone.fConstraints)
self.maxAngle:Enable(self.bone.fConstraints)
local id = self.skel:BoneID(self.bone)
if (MOHO.IsMohoPro()) then
self.fixedAngle:Enable(true)
self.fixedAngle:SetValue(self.bone.fFixedAngle)
self.squashScaling:Enable(true)
self.squashScaling:SetValue(self.bone.fScalingMode == 2)
self.maxStretchScaling:Enable(self.bone.fScalingMode == 2)
self.maxStretchScaling:SetValue(self.bone.fSquashStretchScaling)
self.maxAutoScaling:Enable(true)
self.maxAutoScaling:SetValue(self.bone.fMaxAutoScaling)
self.arcSolver:Enable(true)
self.arcSolver:SetValue(self.bone:IsArcSolverEnabled())
self.ignoredByIK:Enable(true)
self.ignoredByIK:SetValue(self.bone.fIgnoredByIK)
MOHO.BuildBoneChoiceMenu(self.targetMenu, self.skel, LM_SelectBone.SELECTCONTROL, id)
if (self.skel:TargetOfBone(id, self.layerFrame) < 0) then
self.targetMenu:SetChecked(LM_SelectBone.SELECTCONTROL, true)
else
self.targetMenu:SetChecked(LM_SelectBone.SELECTCONTROL + 1 + self.skel:TargetOfBone(id, self.layerFrame), true)
end
self.targetPopup:Redraw()
end
MOHO.BuildBoneChoiceMenu(self.acMenu, self.skel, LM_SelectBone.SELECTCONTROL, id)
if (self.bone.fAngleControlParent < 0) then
self.acMenu:SetChecked(LM_SelectBone.SELECTCONTROL, true)
else
self.acMenu:SetChecked(LM_SelectBone.SELECTCONTROL + 1 + self.bone.fAngleControlParent, true)
end
self.acPopup:Redraw()
MOHO.BuildBoneChoiceMenu(self.pcMenu, self.skel, LM_SelectBone.SELECTCONTROL, id)
if (self.bone.fPosControlParent < 0) then
self.pcMenu:SetChecked(LM_SelectBone.SELECTCONTROL, true)
else
self.pcMenu:SetChecked(LM_SelectBone.SELECTCONTROL + 1 + self.bone.fPosControlParent, true)
end
self.pcPopup:Redraw()
MOHO.BuildBoneChoiceMenu(self.scMenu, self.skel, LM_SelectBone.SELECTCONTROL, id)
if (self.bone.fScaleControlParent < 0) then
self.scMenu:SetChecked(LM_SelectBone.SELECTCONTROL, true)
else
self.scMenu:SetChecked(LM_SelectBone.SELECTCONTROL + 1 + self.bone.fScaleControlParent, true)
end
self.scPopup:Redraw()
self.angleControl:Enable(self.bone.fAngleControlParent >= 0)
self.posControlX:Enable(self.bone.fPosControlParent >= 0)
self.posControlY:Enable(self.bone.fPosControlParent >= 0)
self.scaleControl:Enable(self.bone.fScaleControlParent >= 0)
self.angleControl:SetValue(self.bone.fAngleControlScale)
self.posControlX:SetValue(self.bone.fPosControlScale.x)
self.posControlY:SetValue(self.bone.fPosControlScale.y)
self.scaleControl:SetValue(self.bone.fScaleControlScale)
self.boneDynamics:SetValue(self.bone.fBoneDynamics.value)
self.windDynamics:SetValue(self.bone.fWindDynamics)
self.torque:SetValue(self.bone.fTorqueForce)
self.spring:SetValue(self.bone.fSpringForce)
self.damping:SetValue(self.bone.fDampingForce)
--[syn] self.windDynamics:Enable(self.bone.fBoneDynamics.value)
--[[syn]] self.windDynamics:Enable(true)
self.torque:Enable(self.bone.fBoneDynamics.value)
self.spring:Enable(self.bone.fBoneDynamics.value)
self.damping:Enable(self.bone.fBoneDynamics.value)
else
self.angleConstraints:Enable(false)
self.minAngle:Enable(false)
self.maxAngle:Enable(false)
if (MOHO.IsMohoPro()) then
self.fixedAngle:Enable(false)
self.squashScaling:Enable(false)
self.maxStretchScaling:Enable(false)
self.maxAutoScaling:Enable(false)
self.arcSolver:Enable(false)
self.ignoredByIK:Enable(false)
self.targetPopup:Enable(false)
end
self.acPopup:Enable(false)
self.angleControl:Enable(false)
self.pcPopup:Enable(false)
self.posControlX:Enable(false)
self.posControlY:Enable(false)
self.scPopup:Enable(false)
self.scaleControl:Enable(false)
self.boneDynamics:Enable(false)
self.windDynamics:Enable(false)
self.torque:Enable(false)
self.spring:Enable(false)
self.damping:Enable(false)
end
end
function LM_SelectBoneDialog:OnOK()
self:HandleMessage(LM_SelectBone.DLOG_CHANGE) -- send this final message in case the user is in the middle of editing some value
end
function LM_SelectBoneDialog:HandleMessage(msg)
if (not (self.document and self.layer and self.skel and self.bone)) then
return
end
if (msg == LM_SelectBone.DLOG_CHANGE) then
self.document:PrepUndo(self.layer, true)
self.document:SetDirty()
for i = 0, self.skel:CountBones() - 1 do
local bone = self.skel:Bone(i)
if (bone.fSelected) then
bone.fConstraints = self.angleConstraints:Value()
bone.fMinConstraint = math.rad(self.minAngle:FloatValue())
bone.fMaxConstraint = math.rad(self.maxAngle:FloatValue())
if (self.minAngle:IsEnabled() ~= bone.fConstraints) then
self.minAngle:Enable(bone.fConstraints)
self.maxAngle:Enable(bone.fConstraints)
end
if (MOHO.IsMohoPro()) then
bone.fFixedAngle = self.fixedAngle:Value()
if (self.squashScaling:Value()) then
bone.fScalingMode = 2
else
bone.fScalingMode = 0
end
bone.fSquashStretchScaling = self.maxStretchScaling:FloatValue()
if (bone.fSquashStretchScaling < 0.01) then
bone.fSquashStretchScaling = 0.01
self.maxStretchScaling:SetValue(bone.fSquashStretchScaling)
end
if (bone.fSquashStretchScaling > 100.0) then
bone.fSquashStretchScaling = 100.0
self.maxStretchScaling:SetValue(bone.fSquashStretchScaling)
end
self.maxStretchScaling:Enable(self.bone.fScalingMode == 2)
bone.fMaxAutoScaling = self.maxAutoScaling:FloatValue()
if (bone.fMaxAutoScaling < 0.999999) then
bone.fMaxAutoScaling = 1.0
self.maxAutoScaling:SetValue(bone.fMaxAutoScaling)
end
bone:EnableArcSolver(self.arcSolver:Value())
bone.fIgnoredByIK = self.ignoredByIK:Value()
end
bone.fAngleControlScale = self.angleControl:FloatValue()
bone.fPosControlScale.x = self.posControlX:FloatValue()
bone.fPosControlScale.y = self.posControlY:FloatValue()
bone.fScaleControlScale = self.scaleControl:FloatValue()
--syn\/
if (self.windDynamics:Value()) then
self.boneDynamics:SetValue(true)
end
--syn/\
if (bone.fBoneDynamics.value ~= self.boneDynamics:Value()) then
bone.fBoneDynamics.value = self.boneDynamics:Value()
bone.fBoneDynamics:StoreValue()
self.layer:UpdateCurFrame(true)
MOHO.NewKeyframe(CHANNEL_BONE_DYNAMICS)
MOHO.NewKeyframe(CHANNEL_BONE_SEL_DYNAMICS)
end
if (bone.fWindDynamics ~= self.windDynamics:Value()) then
bone.fWindDynamics = self.windDynamics:Value()
local updateDynamicsValues = false
if (bone.fWindDynamics) then
if (math.abs(bone.fTorqueForce - 2.0) < 0.001 and math.abs(bone.fSpringForce - 2.0) < 0.001 and math.abs(bone.fDampingForce - 1.0) < 0.001) then
updateDynamicsValues = true
bone.fTorqueForce = 0.0
bone.fSpringForce = 1.0
bone.fDampingForce = 1.0
end
else
if (math.abs(bone.fTorqueForce - 0.0) < 0.001 and math.abs(bone.fSpringForce - 1.0) < 0.001 and math.abs(bone.fDampingForce - 1.0) < 0.001) then
updateDynamicsValues = true
bone.fTorqueForce = 2.0
bone.fSpringForce = 2.0
bone.fDampingForce = 1.0
end
end
if (updateDynamicsValues) then
self.torque:SetValue(bone.fTorqueForce)
self.spring:SetValue(bone.fSpringForce)
self.damping:SetValue(bone.fDampingForce)
end
else
bone.fTorqueForce = self.torque:FloatValue()
bone.fSpringForce = self.spring:FloatValue()
bone.fDampingForce = self.damping:FloatValue()
end
if (self.torque:IsEnabled() ~= bone.fBoneDynamics.value) then
--[syn] self.windDynamics:Enable(bone.fBoneDynamics.value)
self.torque:Enable(bone.fBoneDynamics.value)
self.spring:Enable(bone.fBoneDynamics.value)
self.damping:Enable(bone.fBoneDynamics.value)
end
end
end
self.layer:UpdateCurFrame()
MOHO.Redraw()
elseif (msg >= LM_SelectBone.SELECTCONTROL and msg <= LM_SelectBone.SELECTCONTROL + 1000) then
self.document:PrepUndo(self.layer, true)
self.document:SetDirty()
for i = 0, self.skel:CountBones() - 1 do
local bone = self.skel:Bone(i)
if (bone.fSelected) then
local ctrlID = -1
if (MOHO.IsMohoPro()) then
ctrlID = self.targetMenu:FirstCheckedMsg() - (LM_SelectBone.SELECTCONTROL + 1)
if (ctrlID ~= self.skel:BoneID(bone) and ctrlID ~= bone.fTargetBone:GetValue(self.layerFrame)) then
bone.fTargetBone:SetValue(self.layerFrame, ctrlID)
MOHO.NewKeyframe(CHANNEL_BONE_TARGET)
MOHO.NewKeyframe(CHANNEL_BONE_SEL_TARGET)
end
end
ctrlID = self.acMenu:FirstCheckedMsg() - (LM_SelectBone.SELECTCONTROL + 1)
if (ctrlID ~= self.skel:BoneID(bone)) then
bone.fAngleControlParent = ctrlID
end
ctrlID = self.pcMenu:FirstCheckedMsg() - (LM_SelectBone.SELECTCONTROL + 1)
if (ctrlID ~= self.skel:BoneID(bone)) then
bone.fPosControlParent = ctrlID
end
ctrlID = self.scMenu:FirstCheckedMsg() - (LM_SelectBone.SELECTCONTROL + 1)
if (ctrlID ~= self.skel:BoneID(bone)) then
bone.fScaleControlParent = ctrlID
end
self.angleControl:Enable(bone.fAngleControlParent >= 0)
self.posControlX:Enable(bone.fPosControlParent >= 0)
self.posControlY:Enable(bone.fPosControlParent >= 0)
self.scaleControl:Enable(bone.fScaleControlParent >= 0)
end
end
self.layer:UpdateCurFrame()
MOHO.Redraw()
end
end
-- **************************************************
-- Tool options - create and respond to tool's UI
-- **************************************************
LM_SelectBone.CHANGE = MOHO.MSG_BASE
LM_SelectBone.DLOG_BEGIN = MOHO.MSG_BASE + 1
LM_SelectBone.DLOG_CHANGE = MOHO.MSG_BASE + 2
LM_SelectBone.LOCK = MOHO.MSG_BASE + 3
LM_SelectBone.LASSO = MOHO.MSG_BASE + 4
LM_SelectBone.LABEL = MOHO.MSG_BASE + 5
LM_SelectBone.SHY = MOHO.MSG_BASE + 6
LM_SelectBone.COL_PLAIN = MOHO.MSG_BASE + 7
LM_SelectBone.COL_RED = MOHO.MSG_BASE + 8
LM_SelectBone.COL_ORANGE = MOHO.MSG_BASE + 9
LM_SelectBone.COL_YELLOW = MOHO.MSG_BASE + 10
LM_SelectBone.COL_GREEN = MOHO.MSG_BASE + 11
LM_SelectBone.COL_BLUE = MOHO.MSG_BASE + 12
LM_SelectBone.COL_PURPLE = MOHO.MSG_BASE + 13
LM_SelectBone.COL_TAN = MOHO.MSG_BASE + 14
LM_SelectBone.COL_PINK = MOHO.MSG_BASE + 15
LM_SelectBone.COL_TURQUOISE = MOHO.MSG_BASE + 16
LM_SelectBone.COL_CADETBLUE = MOHO.MSG_BASE + 17
LM_SelectBone.COL_CORAL = MOHO.MSG_BASE + 18
LM_SelectBone.FLIP_H = MOHO.MSG_BASE + 19
LM_SelectBone.FLIP_V = MOHO.MSG_BASE + 20
LM_SelectBone.DUMMY = MOHO.MSG_BASE + 21
LM_SelectBone.SELECTITEM = MOHO.MSG_BASE + 22
LM_SelectBone.SELECTCONTROL = MOHO.MSG_BASE + 300
function LM_SelectBone:DoLayout(moho, layout)
self.menu = LM.GUI.Menu(MOHO.Localize("/Scripts/Tool/SelectBone/SelectBone=Select Bone"))
self.dlog = LM_SelectBoneDialog:new()
self.popup = LM.GUI.PopupDialog(MOHO.Localize("/Scripts/Tool/SelectBone/ConeConstraints=Bone Constraints"), true, self.DLOG_BEGIN)
self.popup:SetDialog(self.dlog)
layout:AddChild(self.popup)
self.popup = LM.GUI.PopupMenu(120, false)
self.popup:SetMenu(self.menu)
layout:AddChild(self.popup)
self.boneName = LM.GUI.TextControl(0, "Room For a Long Name", self.CHANGE, LM.GUI.FIELD_TEXT)
self.boneName:SetValue("")
layout:AddChild(self.boneName)
self.lockBone = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/LockBone=Lock bone"), self.LOCK)
layout:AddChild(self.lockBone)
self.lassoCheck = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/LassoMode=Lasso mode"), self.LASSO)
layout:AddChild(self.lassoCheck)
layout:AddChild(LM.GUI.StaticText(MOHO.Localize("/Scripts/Tool/SelectBone/Color=Color:")))
self.colorMenu = LM.GUI.Menu(MOHO.Localize("/Scripts/Tool/SelectBone/BoneColor=BoneColor"))
self.colorMenu:AddItem(MOHO.Localize("/Scripts/Tool/SelectBone/Purple=Purple"), 0, self.COL_PURPLE)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/Blue=Blue"), 0, self.COL_BLUE)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/Green=Green"), 0, self.COL_GREEN)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/Yellow=Yellow"), 0, self.COL_YELLOW)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/Orange=Orange"), 0, self.COL_ORANGE)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/Red=Red"), 0, self.COL_RED)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/Tan=Tan"), 0, self.COL_TAN)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/Pink=Pink"), 0, self.COL_PINK)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/Turquoise=Turquoise"), 0, self.COL_TURQUOISE)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/CadetBlue=Cadet Blue"), 0, self.COL_CADETBLUE)
self.colorMenu:AddItemAlphabetically(MOHO.Localize("/Scripts/Tool/SelectBone/Coral=Coral"), 0, self.COL_CORAL)
self.colorMenu:InsertItem(0, "", 0, 0)
self.colorMenu:InsertItem(0, MOHO.Localize("/Scripts/Tool/SelectBone/Plain=Plain"), 0, self.COL_PLAIN)
self.colorPopup = LM.GUI.PopupMenu(120, true)
self.colorPopup:SetMenu(self.colorMenu)
layout:AddChild(self.colorPopup)
if (MOHO.IsMohoPro()) then
self.labelCheck = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/ShowLabel=Show label"), self.LABEL)
layout:AddChild(self.labelCheck)
self.shyCheck = LM.GUI.CheckBox(MOHO.Localize("/Scripts/Tool/SelectBone/ShyBone=Shy bone"), self.SHY)
layout:AddChild(self.shyCheck)
else
self.labelCheck = nil
self.shyCheck = nil
end
if (MOHO.IsMohoPro()) then
layout:AddChild(LM.GUI.ImageButton("ScriptResources/flip_bone_h", MOHO.Localize("/Scripts/Tool/SelectBone/EndFlip=End Flip"), false, self.FLIP_H, true))
layout:AddChild(LM.GUI.ImageButton("ScriptResources/flip_bone_v", MOHO.Localize("/Scripts/Tool/SelectBone/SideFlip=Side Flip"), false, self.FLIP_V, true))
end
end
function LM_SelectBone: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()
MOHO.BuildBoneMenu(self.menu, skel, self.SELECTITEM, self.DUMMY)
if (selID >= 0) then
local bone = skel:Bone(selID)
self.boneName:SetValue(bone:Name())
self.popup:Enable(true)
self.dlog.bone = bone
self.lockBone:Enable(bone.fParent >= 0)
self.lockBone:SetValue(bone.fIKLock.value)
if (self.labelCheck ~= nil) then
self.labelCheck:Enable(true)
end
if (self.shyCheck ~= nil) then
self.shyCheck:Enable(true)
end
else
self.boneName:SetValue("")
self.popup:Enable(false)
self.dlog.bone = nil
self.lockBone:Enable(false)
self.lockBone:SetValue(false)
if (self.labelCheck ~= nil) then
self.labelCheck:Enable(false)
end
if (self.shyCheck ~= nil) then
self.shyCheck:Enable(false)
end
end
self.lassoCheck:SetValue(self.lassoMode)
self.colorMenu:UncheckAll()
self.colorMenu:SetChecked(self.COL_PLAIN, true)
if (self.labelCheck ~= nil) then
self.labelCheck:SetValue(false)
end
if (self.shyCheck ~= nil) then
self.shyCheck:SetValue(false)
end
for i = 0, skel:CountBones() - 1 do
local bone = skel:Bone(i)
if (bone.fSelected) then
local tags = bone:Tags()
if (tags == 0) then
else
self.colorMenu:UncheckAll()
end
if (tags == 1) then
self.colorMenu:SetChecked(self.COL_RED, true)
elseif (tags == 2) then
self.colorMenu:SetChecked(self.COL_ORANGE, true)
elseif (tags == 3) then
self.colorMenu:SetChecked(self.COL_YELLOW, true)
elseif (tags == 4) then
self.colorMenu:SetChecked(self.COL_GREEN, true)
elseif (tags == 5) then
self.colorMenu:SetChecked(self.COL_BLUE, true)
elseif (tags == 6) then
self.colorMenu:SetChecked(self.COL_PURPLE, true)
elseif (tags == 7) then
self.colorMenu:SetChecked(self.COL_TAN, true)
elseif (tags == 8) then
self.colorMenu:SetChecked(self.COL_PINK, true)
elseif (tags == 9) then
self.colorMenu:SetChecked(self.COL_TURQUOISE, true)
elseif (tags == 10) then
self.colorMenu:SetChecked(self.COL_CADETBLUE, true)
elseif (tags == 11) then
self.colorMenu:SetChecked(self.COL_CORAL, true)
end
if (self.labelCheck ~= nil) then
if (bone:IsLabelShowing()) then
self.labelCheck:SetValue(true)
end
end
if (self.shyCheck ~= nil) then
if (bone.fShy) then
self.shyCheck:SetValue(true)
end
end
break
end
end
self.colorPopup:Enable(skel:SelectedBoneID() >= 0)
self.colorPopup:Redraw()
self.dlog.document = moho.document
self.dlog.layer = moho.layer
self.dlog.layerFrame = moho.layerFrame
self.dlog.skel = skel
self.dlog:UpdateWidgets(moho)
end
function LM_SelectBone: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
if (msg == self.CHANGE) 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.LOCK) then
if (skel:SelectedBoneID() >= 0) then
local lockChange = false
moho.document:PrepUndo(layer, true)
moho.document:SetDirty()
for i = 0, skel:CountBones() - 1 do
local bone = skel:Bone(i)
if (bone.fSelected and bone.fParent >= 0) then
if (self.lockBone:Value()) then
skel:LockBone(i, moho.layerFrame)
else
skel:UnlockBone(i, moho.layerFrame)
end
lockChange = true
end
end
moho.layer:UpdateCurFrame(true)
if (lockChange) then
moho:NewKeyframe(CHANNEL_BONE)
moho:NewKeyframe(CHANNEL_BONE_LOCK)
end
end
elseif (msg == self.LASSO) then
self.lassoMode = self.lassoCheck:Value()
elseif (msg >= self.COL_PLAIN and msg <= self.COL_CORAL) then
local tag = 0
if (msg == self.COL_RED) then
tag = 1
elseif (msg == self.COL_ORANGE) then
tag = 2
elseif (msg == self.COL_YELLOW) then
tag = 3
elseif (msg == self.COL_GREEN) then
tag = 4
elseif (msg == self.COL_BLUE) then
tag = 5
elseif (msg == self.COL_PURPLE) then
tag = 6
elseif (msg == self.COL_TAN) then
tag = 7
elseif (msg == self.COL_PINK) then
tag = 8
elseif (msg == self.COL_TURQUOISE) then
tag = 9
elseif (msg == self.COL_CADETBLUE) then
tag = 10
elseif (msg == self.COL_CORAL) then
tag = 11
end
local selBoneCount = 0
for i = 0, skel:CountBones() - 1 do
local bone = skel:Bone(i)
if (bone.fSelected) then
selBoneCount = selBoneCount + 1
end
end
if (selBoneCount > 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:SetTags(tag)
end
end
moho.layer:UpdateCurFrame(true)
end
moho:UpdateUI()
elseif (msg == self.LABEL) then
if (self.labelCheck ~= nil) then
if (skel:SelectedBoneID() >= 0) then
moho.document:PrepUndo(layer, true)
moho.document:SetDirty()
if (self.labelCheck:Value()) then
-- if bone labels are not showing, then turn them on now
layer:SetQualityFlags(MOHO.setbit(layer:QualityFlags(), MOHO.LDQ_LABELS))
view:SetQualityFlags(MOHO.setbit(view:QualityFlags(), MOHO.LDQ_LABELS))
end
for i = 0, skel:CountBones() - 1 do
local bone = skel:Bone(i)
if (bone.fSelected) then
bone:ShowLabel(self.labelCheck:Value())
end
end
end
end
elseif (msg == self.SHY) then
if (self.shyCheck ~= nil) 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.fShy = self.shyCheck:Value()
bone.fHidden = bone.fShy
end
end
end
end
elseif (msg == self.FLIP_H) then
LM_TransformBone:FlipBones(moho, skel, true)
elseif (msg == self.FLIP_V) then
LM_TransformBone:FlipBones(moho, skel, false)
elseif (msg == self.DLOG_BEGIN) then
self.dlog.document = moho.document
self.dlog.layer = layer
self.dlog.layerFrame = moho.layerFrame
self.dlog.skel = skel
if (skel:SelectedBoneID() >= 0) then
self.dlog.bone = skel:Bone(skel:SelectedBoneID())
else
self.dlog.bone = nil
end
elseif (msg == self.DLOG_CHANGE) then
-- Nothing really happens here - it is a message that came from the popup dialog.
-- However, the important thing is that this message then flows back into the Moho app, forcing a redraw.
elseif (msg >= self.SELECTITEM and msg < self.SELECTCONTROL) then
for i = 0, skel:CountBones() - 1 do
skel:Bone(i).fSelected = (i == msg - self.SELECTITEM)
end
moho:UpdateBonePointSelection()
moho:UpdateUI()
end
end
Most up to date is in my signature.