change parameters for multiple bones

Discuss Moho bugs (or suspected bugs) with other users. To report bugs to Smith Micro, please visit support.smithmicro.com

Moderators: Víctor Paredes, Belgarath, slowtiger

Post Reply
User avatar
davoodice2
Posts: 381
Joined: Tue Jun 15, 2021 1:14 pm

change parameters for multiple bones

Post by davoodice2 »

Hi
for example I have some bones with different setting. some of theme have bone angle limit and some other have target bone. now when I select all bones and activate independent angle, all bones settings change and my target bones and angle limit will be set for all or deactivate for all.
normally it must changes current parameter.
خیام اگر ز باده مستی خوش باش
با ماهرخی اگر نشستی خوش باش
چون عاقبت کار جهان نیستی است
انگار که نیستی چو هستی خوش باش
User avatar
SimplSam
Posts: 1048
Joined: Thu Mar 13, 2014 5:09 pm
Location: London, UK
Contact:

Re: change parameters for multiple bones

Post by SimplSam »

Yes it would be better if you could change just the individual parameters without all/most settings being applied to all selected bones.
Last edited by SimplSam on Thu Jul 08, 2021 3:48 am, edited 1 time in total.
Moho 14.1 » Win 11 Pro 64GB » NVIDIA GTX 1080ti 11GB
Moho 14.1 » Mac mini 2012 8GB » macOS 10.15 Catalina
Tube: SimplSam


Sam
User avatar
synthsin75
Posts: 9979
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: change parameters for multiple bones

Post by synthsin75 »

The select bone tool could be modded to only change the attributes that change, but I have no need for that myself.
User avatar
heyvern
Posts: 7035
Joined: Fri Sep 02, 2005 4:49 am

Re: change parameters for multiple bones

Post by heyvern »

Oh wow, yes I have dreamed of a way to do this but for the life of me couldn't figure out how to implement this. The logic hurts my head.
How would the tool "know" which parameter to change on which bone if they are all different?

An example:
You select 10 bones. They all have different angle targets to different bones so you don't want to change those because they are all different.
As an example, let's say you only want to change the angle limit for the selected bones and ignore all the other settings.

The logic is tricky. You would have to make a list of all the bones parameters ALL OF THE PARAMETERS and compare all of each bones parameters to each other to see what is different. Then make another list to compare any changes made in the bone edit window and only apply what changed to each bone leaving the other parameters the same... yikes... head is spinning again. :)
User avatar
SimplSam
Posts: 1048
Joined: Thu Mar 13, 2014 5:09 pm
Location: London, UK
Contact:

Re: change parameters for multiple bones

Post by SimplSam »

synthsin75 wrote: Thu Jul 08, 2021 2:51 am The select bone tool could be modded to only change the attributes that change, but I have no need for that myself.
p.s. Quite embarrassing, but I actually forgot that this was scripted !!!! :oops:
heyvern wrote: Thu Jul 08, 2021 3:32 am ...
The logic is tricky. You would have to make a list of all the bones parameters ALL OF THE PARAMETERS and compare all of each bones parameters ...
I don't think you need to do all that. At the moment the script uses a single change Message DLOG_CHANGE for all input property fields. Instead it could use individual Message & handler logic to set relevant properties.

One thing I am definitely going to change is the Wind enable switch (checkbox) - so that it can auto-enable Bone Dynamics - in a single click. I get irritated having to enable Dynamics and then enable Wind (Lazy me).
Moho 14.1 » Win 11 Pro 64GB » NVIDIA GTX 1080ti 11GB
Moho 14.1 » Mac mini 2012 8GB » macOS 10.15 Catalina
Tube: SimplSam


Sam
User avatar
heyvern
Posts: 7035
Joined: Fri Sep 02, 2005 4:49 am

Re: change parameters for multiple bones

Post by heyvern »

Oh wow, okay must look at that. So the bone dialog just sets everything to be updated and instead you could simply evaluate ONLY things THAT CHANGED. Cool beans, yes will look at that next chance I get.

p.s. I am just now getting the hang of the changes in the scripting interface since the last time I did any massive scripting. YIKES! OUCH! It HURTS! :D
Is there an updated reference? There use to be a text file with all the scripting references for the current version. It was a bare minimum, some sort of exported text didn't have explanations or anything just basic list of stuff. Couldn't find anything like that with 13.5.
User avatar
synthsin75
Posts: 9979
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: change parameters for multiple bones

Post by synthsin75 »

SimplSam wrote: Thu Jul 08, 2021 4:15 am One thing I am definitely going to change is the Wind enable switch (checkbox) - so that it can auto-enable Bone Dynamics - in a single click. I get irritated having to enable Dynamics and then enable Wind (Lazy me).
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
heyvern wrote: Thu Jul 08, 2021 5:35 am Is there an updated reference?
Most up to date is in my signature.
User avatar
davoodice2
Posts: 381
Joined: Tue Jun 15, 2021 1:14 pm

Re: change parameters for multiple bones

Post by davoodice2 »

synthsin75 wrote: Thu Jul 08, 2021 6:03 am
SimplSam wrote: Thu Jul 08, 2021 4:15 am One thing I am definitely going to change is the Wind enable switch (checkbox) - so that it can auto-enable Bone Dynamics - in a single click. I get irritated having to enable Dynamics and then enable Wind (Lazy me).
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
heyvern wrote: Thu Jul 08, 2021 5:35 am Is there an updated reference?
Most up to date is in my signature.
THAT WORKED.BIG THANKS.
خیام اگر ز باده مستی خوش باش
با ماهرخی اگر نشستی خوش باش
چون عاقبت کار جهان نیستی است
انگار که نیستی چو هستی خوش باش
User avatar
davoodice2
Posts: 381
Joined: Tue Jun 15, 2021 1:14 pm

Re: change parameters for multiple bones

Post by davoodice2 »

UPDATE:
mod bone select tool works at frame 0 only.
when press close button in bone select options box, moho makes change to all bone settings. i want just close window. :( :(
خیام اگر ز باده مستی خوش باش
با ماهرخی اگر نشستی خوش باش
چون عاقبت کار جهان نیستی است
انگار که نیستی چو هستی خوش باش
User avatar
synthsin75
Posts: 9979
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: change parameters for multiple bones

Post by synthsin75 »

That mod was only to allow enabling wind directly, not changing individual settings of multiple selected bones.
Sorry if that confused you.

Like I said earlier, since I have no need for that myself, I'd have to charge to write it.
User avatar
davoodice2
Posts: 381
Joined: Tue Jun 15, 2021 1:14 pm

Re: change parameters for multiple bones

Post by davoodice2 »

synthsin75 wrote: Wed Jul 14, 2021 10:30 pm That mod was only to allow enabling wind directly, not changing individual settings of multiple selected bones.
Sorry if that confused you.

Like I said earlier, since I have no need for that myself, I'd have to charge to write it.
Thnks.if you wish please write a new tool in your free time if its possible.
خیام اگر ز باده مستی خوش باش
با ماهرخی اگر نشستی خوش باش
چون عاقبت کار جهان نیستی است
انگار که نیستی چو هستی خوش باش
User avatar
synthsin75
Posts: 9979
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: change parameters for multiple bones

Post by synthsin75 »

davoodice2 wrote: Thu Jul 15, 2021 7:30 am
synthsin75 wrote: Wed Jul 14, 2021 10:30 pm That mod was only to allow enabling wind directly, not changing individual settings of multiple selected bones.
Sorry if that confused you.

Like I said earlier, since I have no need for that myself, I'd have to charge to write it.
Thnks.if you wish please write a new tool in your free time if its possible.
No, I just said I don't need such a tool. Why on earth would I waste my free time writing it?
Post Reply