Image
-- **************************************************
ScriptName = "LK_ToggleColorBones"

-- **************************************************
-- General information about this script
-- **************************************************
LK_ToggleColorBones = {}

function LK_ToggleColorBones:Name()
   return "Toggle Color Bones"
end

function LK_ToggleColorBones:Tool()
	return "LK_ToggleColorBones"
end

function LK_ToggleColorBones:Version()
   return "2.1"
end

function LK_ToggleColorBones:Description()
   return "Expose bones by color. Hold <alt> to select bones instead. <shift + #> to show/hide color bones. <alt + shift + #> to add color to selection. Shy bones will always stay hidden. Click to use select bone tool."
end

function LK_ToggleColorBones:Creator()
   return "Lukas Krepel, Frame Order"
end

function LK_ToggleColorBones:UILabel()
   return "Toggle Color Bones"
end

function LK_ToggleColorBones:ColorizeIcon()
   return true
end

function LK_ToggleColorBones:IsEnabled(moho)
	local skel = moho:Skeleton()
	if (skel == nil) then
		return false
	end
	return true
end

function LK_ToggleColorBones:IsRelevant(moho)
	local relevant = true
	local skel = moho:Skeleton()
	if (skel == nil) then
		relevant = false
	end
	if relevant and MohoMode ~= nil then
		relevant = MohoMode.animation
	end
	return relevant
end

-- ***************************************************
-- Forward Mouse functions to Mike's Select Bone tool:
-- ***************************************************
function LK_ToggleColorBones:OnMouseDown(moho, mouseEvent)
	LM_SelectBone:OnMouseDown(moho, mouseEvent)
end

function LK_ToggleColorBones:OnMouseMoved(moho, mouseEvent)
	LM_SelectBone:OnMouseMoved(moho, mouseEvent)
end

function LK_ToggleColorBones:OnMouseUp(moho, mouseEvent)
	LM_SelectBone:OnMouseUp(moho, mouseEvent)
end

function LK_ToggleColorBones:DrawMe(moho, view)
	LM_SelectBone:DrawMe(moho, view)
	FO_Utilities:DrawMeMod(moho, view)
end

-- **************************************************
-- Tool options - create and respond to tool's UI
-- **************************************************

LK_ToggleColorBones.shortcutBoneColor = { "1", "2", "3", "4", "5", "6", "7", "8", "--9", "--10", "--11", "0" }

LK_ToggleColorBones.shortcutBoneColorShift = { "!", "@", "#", "$", "%", "^", "&", "*", "--9", "--10", "--11", ")" }

LK_ToggleColorBones.shortcutRestBoneColor = "9"

LK_ToggleColorBones.shortcutRestBoneColorShift = "("

-- **************************************************
-- Do Layout - Set up the toolbar
-- **************************************************
function LK_ToggleColorBones:DoLayout(moho, layout, msg_base)
	self:InsertLayout(moho, layout, MOHO.MSG_BASE)
end

function LK_ToggleColorBones:InsertLayout(moho, layout, msg_base)
	-- *******************	
	-- *** Messages:   ***
	-- *******************
	self.msg_base = msg_base
	self.SHOW_ALL_BONES 					= self.msg_base
	self.TOGGLE_VISIBLE_LAYERS_ONLY	= self.msg_base + 1
	self.NUMERIC_LEGEND 					= self.msg_base + 1
	self.EXPOSE_REST 						= self.msg_base + 2
	self.FLOODSELECT_COLOR_BONES		= self.msg_base + 3
	self.SHOW_SMARTBONE_DIALS			= self.msg_base + 4
	self.SELECT_ROOT_BONES 								= self.msg_base + 5
	self.SHOW_COLOR_BONES				= self.msg_base + 100 -- * (100 = 0 = Plain t/m 111 = 11 = Coral)
	self.EXPOSE_COLOR_BONES				= self.msg_base + 112 -- * (112 = 0 = Plain t/m 123 = 11 = Coral)
	self.SELECT_COLOR_BONES 			= self.msg_base + 124 -- * (124 = 0 = Plain t/m 135 = 11 = Coral)
	self.SELECT_COLOR_BONES_ADD		= self.msg_base + 136 -- * (136 = 0 = Plain t/m 147 = 11 = Coral)

	if moho:CurrentTool() == self:Tool() then
		FO_Utilities.tinyUI = false
	end
	FO_Utilities:Divider(layout, "Show all bones", moho:CurrentTool()==self:Tool())
	self.showAllButton = LM.GUI.ImageButton("ScriptResources/FO_icons/color_All", "Show all bones", true, self.SHOW_ALL_BONES, true)
	layout:AddChild(self.showAllButton)

	FO_Utilities:Divider(layout, "Colored bones")
	self.showColorButtons = {}
	self.skelButtons = {}
	for i = 0, #FO_Utilities.colorNames do
		local colorName = FO_Utilities.colorNames[i]
		local extraDescriptionBit = { "", " or <6>", " or <5>", " or <4>", " or <3>", " or <2>", " or <1>", " or <9>", " or <9>", " or <9>", " or <8>", " or <7>" }
		self.colButton = LM.GUI.ImageButton("ScriptResources/FO_icons/color_"..colorName.."_number", "Show "..colorName.." bones (<alt>"..extraDescriptionBit[i+1].." to expose)", true, self.SHOW_COLOR_BONES + i, false)
		self.colButton:SetAlternateMessage(self.EXPOSE_COLOR_BONES + i)
		table.insert(self.showColorButtons, self.colButton)
		--[[ * Backup, re-enable when we get API access to channel visibility:
		self.showTimelineButton = LM.GUI.ImageButton("ScriptResources/FO_icons/color_timeline_"..colorName, "Show "..colorName.." bones in timeline (<alt> to ***)", true, self.COLOR_TIMELINE + i, false)
		self.showTimelineButton:SetAlternateMessage(self.COLOR_SELECT + i)
		table.insert(self.showTimelineButtons, self.showTimelineButton)
		--]]
	end
	-- * Show Plain bones:
	local buttonColor = 0
	-- layout:PushV(LM.GUI.ALIGN_CENTER, 0)
	--[[ * Backup, re-enable when we get API access to channel visibility:
	table.insert(self.skelButtons, self.showTimelineButtons[1])
	showTimelinePlainButton is a dummy.
	layout:AddPadding(2)
	-- layout:Pop()
	-- ]]
	layout:PushH(LM.GUI.ALIGN_CENTER, 0)
	table.insert(self.skelButtons, self.showColorButtons[1])
	layout:AddChild(self.showColorButtons[1])
	-- * Show color bones:
	local reverse = FO_Utilities.reverseBoneColorButtons
	local start = 2
	local stop = #self.showColorButtons
	local increment = 1
	if reverse then
		start, stop = stop, start
		increment = -1
	end
	for i = start, stop, increment do --todo start/end/incr fixen
		local buttonColor = i - 1
		-- layout:AddPadding(-15)
		-- layout:PushV(LM.GUI.ALIGN_CENTER, 0)
		--[[ * Backup, re-enable when we get API access to channel visibility:
		table.insert(self.skelButtons, self.showTimelineButtons[i])
		layout:AddChild(self.showTimelineButtons[i])
		layout:AddPadding(2)
		--]]
		table.insert(self.skelButtons, self.showColorButtons[i])
		layout:AddChild(self.showColorButtons[i])
		-- layout:Pop()
	end
	layout:Pop()
	-- * Show GUI button:
	FO_Utilities:Divider(layout, "Dials")
	self.showSmartboneDialsButton = LM.GUI.ImageButton("ScriptResources/FO_icons/GUI", "Toggle bone-dials visibility.", true, self.SHOW_SMARTBONE_DIALS, true)
	table.insert(self.skelButtons, self.showSmartboneDialsButton)
	layout:AddChild(self.showSmartboneDialsButton)
	FO_Utilities:Divider(layout, "Select")
	layout:PushH(LM.GUI.ALIGN_CENTER, 2)
	-- * Select Hip Feet button:
	self.selectRootBonesButton = LM.GUI.ImageButton("ScriptResources/FO_icons/SelectHipFeet", "Select root bones.", false, self.SELECT_ROOT_BONES, true)
	table.insert(self.skelButtons, self.selectRootBonesButton)
	layout:AddChild(self.selectRootBonesButton)
	-- * Flood select button:
	self.selectFloodColorBonesButton = LM.GUI.ImageButton("ScriptResources/FO_icons/select_floodcolorbones", "Flood select color bones.", false, self.FLOODSELECT_COLOR_BONES, true)
	layout:AddChild(self.selectFloodColorBonesButton)
	layout:Pop()
	-- * Color Numeric Legend:
	if not FO_Utilities.tinyUI then
		FO_Utilities:Divider(layout, "Keyboard Shortcuts")
		layout:AddChild(LM.GUI.ImageButton("ScriptResources/FO_icons/color_numeric_legend", "Hide / Show Color Bones Shortcuts. Hold <alt> to Expose.", false, self.NUMERIC_LEGEND, false))
	end
end

-- **************************************************
-- Update Widgets
-- **************************************************
function LK_ToggleColorBones:UpdateWidgets(moho)
	local skel = moho:Skeleton()
	if skel ~= nil then
		local visibleBones = {}
		local hiddenBones = {}
		local visibleDials = {}
		local hiddenDials = {}
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			local boneColor = bone:Tags()
			if not bone.fShy then
				if bone.fHidden then
					table.insert(hiddenBones, boneColor)
				elseif not bone.fHidden then
					table.insert(visibleBones, boneColor)
				end
				-- * Dials
				if bone.fConstraints and bone:IsLabelShowing() then
					if bone.fHidden then
						table.insert(hiddenDials, boneColor)
					elseif not bone.fHidden then
						table.insert(visibleDials, boneColor)
					end
				end
			end
		end
		for i, button in ipairs(self.showColorButtons) do
			local buttonColor = i-1
			if table.contains(hiddenBones, buttonColor) then
				button:SetValue(false)
			elseif table.contains(visibleBones, buttonColor) then
				button:SetValue(true)
			else
				button:Enable(false)
				button:SetValue(false)
			end
		end
		if table.contains(hiddenBones, 0) or table.contains(hiddenBones, 1) or table.contains(hiddenBones, 2) or table.contains(hiddenBones, 3) or table.contains(hiddenBones, 4) or table.contains(hiddenBones, 5) or table.contains(hiddenBones, 6) or  table.contains(hiddenBones, 7) or table.contains(hiddenBones, 8) or table.contains(hiddenBones, 9) or table.contains(hiddenBones, 10) or table.contains(hiddenBones, 11) then
			self.showAllButton:SetValue(false)
		elseif table.contains(visibleBones, 0) or table.contains(visibleBones, 1) or table.contains(visibleBones, 2) or table.contains(visibleBones, 3) or table.contains(visibleBones, 4) or table.contains(visibleBones, 5) or table.contains(visibleBones, 6) or table.contains(visibleBones, 7) or table.contains(visibleBones, 8) or table.contains(visibleBones, 9) or table.contains(visibleBones, 10) or table.contains(visibleBones, 11) then
			self.showAllButton:SetValue(true)
		else
			self.showAllButton:Enable(false)
			self.showAllButton:SetValue(false)
		end
		if #hiddenDials > 0 then
			self.showSmartboneDialsButton:Enable(true)
			self.showSmartboneDialsButton:SetValue(false)
			self.hiddenDials = true
		elseif #visibleDials > 0 and #hiddenDials == 0 then
			self.showSmartboneDialsButton:Enable(true)
			self.showSmartboneDialsButton:SetValue(true)
			self.hiddenDials = false
		else
			self.showSmartboneDialsButton:Enable(false)
			self.showSmartboneDialsButton:SetValue(false)
		end
	else
		-- * Disable buttons:
		for i, button in ipairs(self.showColorButtons) do
			local buttonColor = i-1
			button:Enable(false)
			button:SetValue(false)
		end
		self.showSmartboneDialsButton:Enable(false)
		self.selectRootBonesButton:Enable(false)
		self.selectFloodColorBonesButton:Enable(false)
	end
end

-- **************************************************
-- Handle Messages
-- **************************************************
function LK_ToggleColorBones:HandleMessage(moho, view, msg)
	local skel = moho:Skeleton()
	if	(msg == self.SELECT_ROOT_BONES) then
		skel:SelectNone()
		local rootBones = FO_Utilities:RootBones(skel)
		for i = 1, #rootBones do
			rootBones[i].fSelected = true
		end
	elseif msg == self.SHOW_SMARTBONE_DIALS then
		for i = 0, skel:CountBones()-1 do
			local bone = skel:Bone(i)
			if not bone.fShy and bone.fConstraints and bone:IsLabelShowing() then
				bone.fHidden = not self.hiddenDials
			end
		end
	elseif msg == self.FLOODSELECT_COLOR_BONES then
		local boneColors = {}
		for i = 0, skel:CountBones() - 1 do -- Rondje 1 -- Zo komen ze er wel dubbel in...
			local bone = skel:Bone(i)
			if (bone.fSelected) then
				local boneColor = bone:Tags() 
				table.insert(boneColors, boneColor)
			end
		end
		for i = 0, skel:CountBones() - 1 do -- Rondje 2 -- Zo ga je wel onnodig veel bones af...
			local bone = skel:Bone(i)
			boneColor = bone:Tags() 
			for i = 0, (#boneColors) do
				if boneColors[i] == boneColor then
					bone.fSelected = true
				end
			end
		end
	elseif msg >= self.SHOW_COLOR_BONES and msg <= self.SHOW_COLOR_BONES + 11 then
		local buttonColor = (msg - self.SHOW_COLOR_BONES)
		local action = moho.document:GetSelectedLayer(i):CurrentAction()
		local layer = moho.document:GetSelectedLayer(i)
		local doHide = true
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			local boneColor = bone:Tags()
			if boneColor == buttonColor and bone.fHidden and not bone.fShy then
				doHide = false
				break
			end
		end
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			local boneColor = bone:Tags() 
			if boneColor == buttonColor and not bone.fShy then
				bone.fHidden = doHide
			elseif boneColor == buttonColor and bone.fShy and layer:IsSmartBoneAction(action) and boneColor ~= 1 then
				bone.fHidden = doHide
			end
		end
	elseif msg == self.SHOW_ALL_BONES then
		local action = moho.document:GetSelectedLayer(i):CurrentAction()
		local layer = moho.document:GetSelectedLayer(i)
		local button = self.showAllButton
		button:SetValue(not(button:Value()))
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			if not bone.fShy then
				bone.fHidden = button:Value()
			elseif bone.fShy and layer:IsSmartBoneAction(action) and boneColor ~= 1 then
				bone.fHidden = button:Value()
			end
		end
	elseif msg >= self.SELECT_COLOR_BONES and msg <= self.SELECT_COLOR_BONES + 11 then
		local buttonColor = msg - self.SELECT_COLOR_BONES
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			local boneColor = bone:Tags()
			if boneColor == buttonColor and not bone.fShy then
				bone.fSelected = true
			else
				bone.fSelected = false
			end
		end
	elseif msg >= self.SELECT_COLOR_BONES_ADD and msg <= self.SELECT_COLOR_BONES_ADD + 11 then
		local buttonColor = msg - self.SELECT_COLOR_BONES_ADD
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			local boneColor = bone:Tags()
			if boneColor == buttonColor and not bone.fShy then
				bone.fSelected = true
			end
		end
	elseif msg >= self.EXPOSE_COLOR_BONES and msg <= self.EXPOSE_COLOR_BONES + 11 then
		-- * Expose color (and toggle back):
		local buttonColor = (msg - self.EXPOSE_COLOR_BONES)
		FO_Utilities:ToggleExposeColorBones(moho.layer, skel, buttonColor)
	elseif msg == self.SHOW_REST_COLORS then
		local action = moho.document:GetSelectedLayer(i):CurrentAction()
		local layer = moho.document:GetSelectedLayer(i)
		local button = self.showRestButton
		button:SetValue(not(button:Value()))
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			local boneColor = bone:Tags() 
			if (boneColor > 6 or boneColor == 0) and not bone.fShy then -- Grey bone + any of the new colors -- HELP misschien niet grey meenemen?
				bone.fHidden = button:Value()
			elseif (boneColor > 6 or boneColor == 0) and bone.fShy and layer:IsSmartBoneAction(action) and boneColor ~= 1 then
				bone.fHidden = button:Value()
			end
		end
	elseif msg == self.NUMERIC_LEGEND then
		local msg = {	
							"i",
							"<#> (1, 2, 3, 4, 5, 6, 7, 8, 9) / <Click numeric buttons> = Expose bones of a color.",
							"Keyboard modifiers:",
							"<Alt + #> / <Alt + click button> = Select bones of a color.",
							"<Shift + #> = Show/Hide bones of a color.",
							"<Alt + Shift #> = Add bones of a color to current selection.",
							"",
							"Note:",
							"(Exposing bones while they are already exposed will show all bones)",
							"(0 = All bones)",
							"(9 = Cadet Blue + Cyan + Coral)",
							"(This tool ignores shy bones)",
							"(<alt + 0> doesn't work, because it's taken by Moho's 'Toggle Seconary Windows' function)",
							"(Bones with visible bone-label and min/max angle constraints are considered 'Dials' and can be toggled with the Dials-button)"
						}
		FO_Utilities:Alert(msg)
	--[[ * BACKUP:
	elseif msg >= self.COLOR_TIMELINE and msg <= self.COLOR_TIMELINE + 11 then
		local buttonColor = (msg - self.COLOR_TIMELINE) -- + 1?
		local button = self.showTimelineButtons[buttonColor + 1]
		button:SetValue(not(button:Value()))
		--if (button:Value()) then
		for i = 0, skel:CountBones() - 1 do
			local bone = skel:Bone(i)
			local boneColor = bone:Tags() 
			if boneColor == buttonColor then
				if (button:Value()) then
					bone:SetTags(0) -- No Colour
				else
					bone:SetTags(buttonColor)
				end
			end
		end--]]
	end
	moho:UpdateSelectedChannels() -- ?
	moho.layer:UpdateCurFrame() -- ?
	MOHO.Redraw()
	moho:UpdateUI()
end

function LK_ToggleColorBones:OnKeyDown(moho, keyEvent)
	if moho:Skeleton() == nil then
		return
	end
	-- ***********************************
	-- *** Numeric keys 1 t/m 6 and 0. ***
	-- ***********************************
	for i = 1, #self.shortcutBoneColor - 1 do
		if self.shortcutBoneColor[i] == keyEvent.key then
			if not keyEvent.altKey then
				self:HandleMessage(moho, keyEvent.view, self.EXPOSE_COLOR_BONES + i) -- * NO MODIFIERS
			else
				self:HandleMessage(moho, i, self.SELECT_COLOR_BONES + i) -- * ALT
			end
		end
	end
	-- ************************************************************
	-- *** SHIFT VARIANT Numeric keys 1 '!' t/m 6 '^' and 0 ')' ***
	-- ************************************************************
	for i = 1, #self.shortcutBoneColorShift - 1 do
		if self.shortcutBoneColorShift[i] == keyEvent.key then
			if keyEvent.altKey then
				self:HandleMessage(moho, keyEvent.view, self.SELECT_COLOR_BONES_ADD + i) -- * SHIFT + ALT
				return
			else
				self:HandleMessage(moho, keyEvent.view, self.SHOW_COLOR_BONES + i) -- * SHIFT
				return
			end
		end
	end
	
	if keyEvent.key == self.shortcutRestBoneColor then
		local doShowFirst = nil
		if keyEvent.altKey then
			doShowFirst = self.showAllButton:Value()
			self.showAllButton:SetValue(not doShowFirst)
			self:HandleMessage(moho, keyEvent.view, self.SHOW_ALL_BONES)
		end
		if doShowFirst == nil or doShowFirst then
			local rest = { 7, 8 , 9 }
			for i = 1, #rest do
				local color = rest[i]
				local button = self.showColorButtons[color + 1]
				button:SetValue(not button:Value())
				self:HandleMessage(moho, keyEvent.view, self.SHOW_COLOR_BONES + color)
			end
		end
	end
	if keyEvent.key == self.shortcutBoneColor[#self.shortcutBoneColor] then
		if keyEvent.altKey then
			self:HandleMessage(moho, keyEvent.view, self.EXPOSE_COLOR_BONES + 0)
		else
			self.showAllButton:SetValue(not self.showAllButton:Value())
			self:HandleMessage(moho, keyEvent.view, self.SHOW_ALL_BONES)
		end
	end
	if keyEvent.key == self.shortcutRestBoneColor then
		self:HandleMessage(moho, keyEvent.view, self.EXPOSE_REST)
	end
	moho:UpdateUI()
end

Icon
Toggle Color Bones
Listed

Author: Lukas View Script
Script type: Tool

Uploaded: Jul 04 2022, 04:36

Last modified: May 16 2023, 04:58

Toggle Color Bones visibility
Image
Changelog:
- v2.0 New version
- v2.1 Toolbar fixes and FO_Utilities compatibility
This script, and all other scripts on this site are distributed as free software under the GNU General Public License 3.0 or later.
Downloads count: 436