-- **************************************************
-- Provide Moho with the name of this script object
-- **************************************************

ScriptName = "SZ_LayerSelectionButtons"

SZ_LayerSelectionButtons = {}

-- **************************************************
-- Settings
-- **************************************************

SZ_LayerSelectionButtons.numberOfButtons = 8
SZ_LayerSelectionButtons.showLayer = true

-- **************************************************
-- General information about this script
-- **************************************************

function SZ_LayerSelectionButtons:Name()
	return self:Localize("name")
end

function SZ_LayerSelectionButtons:Version()
	return "1.0"
end

function SZ_LayerSelectionButtons:Description()
	return self:Localize("description")
end

function SZ_LayerSelectionButtons:Creator()
	return "Stan from 2danimator.ru"
end

function SZ_LayerSelectionButtons:UILabel()
	return self:Localize("label")
end

function SZ_LayerSelectionButtons:ResetPrefs()
	self.resetPrefs = true
end


-- **************************************************
-- Recurring values
-- **************************************************

SZ_LayerSelectionButtons.layerButtons = {}
SZ_LayerSelectionButtons.layerVisibilityCheckBoxes = {}
SZ_LayerSelectionButtons.layerTimelineCheckBoxes = {}
SZ_LayerSelectionButtons.bindingKey = "SZ_LayerSelectionButtons_boundTo_"
SZ_LayerSelectionButtons.boundLayers = {}
SZ_LayerSelectionButtons.resetPrefs = false


-- **************************************************
-- Relevance and Availability
-- **************************************************

function SZ_LayerSelectionButtons:IsRelevant(moho)
	return true
end


function SZ_LayerSelectionButtons:IsEnabled(moho)
	return true
end


-- **************************************************
-- The guts of this script
-- **************************************************


function SZ_LayerSelectionButtons:OnMouseDown(moho, mouseEvent)
	
end



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

SZ_LayerSelectionButtons.SHOW_LAYER = MOHO.MSG_BASE
SZ_LayerSelectionButtons.RESET = MOHO.MSG_BASE + 1
SZ_LayerSelectionButtons.BUTTON_MSG_BASE = MOHO.MSG_BASE + 100
SZ_LayerSelectionButtons.BUTTON_ALT_MSG_BASE = MOHO.MSG_BASE+200
SZ_LayerSelectionButtons.CHECKBOX_VISIBILITY_MSG_BASE = MOHO.MSG_BASE+300
SZ_LayerSelectionButtons.CHECKBOX_TIMELINE_MSG_BASE = MOHO.MSG_BASE+400


function SZ_LayerSelectionButtons:DoLayout(moho, layout)
	for i=1, self.numberOfButtons do
		local button = LM.GUI.Button(self:Localize("emptyButton"), self.BUTTON_MSG_BASE + i)
		button:SetAlternateMessage(self.BUTTON_ALT_MSG_BASE + i)
		self.layerButtons[i] = button
		layout:AddChild(self.layerButtons[i])
		
		local visibilityCheckbox = LM.GUI.CheckBox("", self.CHECKBOX_VISIBILITY_MSG_BASE + i)
		visibilityCheckbox:SetToolTip(self:Localize("layerVisibility"))
		self.layerVisibilityCheckBoxes[i] = visibilityCheckbox
		layout:AddChild(self.layerVisibilityCheckBoxes[i])
	
		layout:AddPadding(-16)
		
		local timelineCheckbox = LM.GUI.CheckBox("", self.CHECKBOX_TIMELINE_MSG_BASE + i)
		timelineCheckbox:SetToolTip(self:Localize("timelineVisibility"))
		self.layerTimelineCheckBoxes[i] = timelineCheckbox
		layout:AddChild(self.layerTimelineCheckBoxes[i])
		
		layout:AddPadding(10)
		
		self:ClearButton(i)
	end
	layout:AddPadding(-26)
	layout:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL, 0)
	layout:AddPadding(0)
	self.showLayerCheckbox = LM.GUI.CheckBox(self:Localize("showLayer"), self.SHOW_LAYER)
	layout:AddChild(self.showLayerCheckbox)
	layout:AddChild(LM.GUI.Button(self:Localize("reset"), self.RESET))
end

function SZ_LayerSelectionButtons:UpdateWidgets(moho)
	if self.resetPrefs then
		self:Reset(moho)
		self.resetPrefs = false
	end
	
	self.showLayerCheckbox:SetValue(self.showLayer)
	
	local count = 0
	repeat
		local layer = moho.document:LayerByAbsoluteID(count)
		if layer then
			count = count + 1
			local uuid = layer:UUID()
			local scriptData = layer:ScriptData()
			if scriptData:HasKey(self.bindingKey) then
				local buttonNumber = scriptData:GetInt(self.bindingKey)
				-- clear the same key from other layers, to avoid issues when layer is duplicated
				local count2 = count
				repeat
					local layer2 = moho.document:LayerByAbsoluteID(count2)
					if layer2 then
						count2 = count2 + 1
						if layer2 ~= layer then
							local scriptData2 = layer2:ScriptData()
							if scriptData2:HasKey(self.bindingKey) and scriptData2:GetInt(self.bindingKey) == buttonNumber then
								scriptData2:Remove(self.bindingKey)
							end
						end
					end
				until not layer2
				self:BindButtonToLayer(buttonNumber, layer)
			else
				self.boundLayers[uuid] = nil
			end
		end
	until not layer
end

function SZ_LayerSelectionButtons:HandleMessage(moho, view, msg)
	for i = 1, self.numberOfButtons do
		if msg == self.BUTTON_MSG_BASE + i then
			self:SelectBoundLayer(moho, i)
		elseif msg == self.BUTTON_ALT_MSG_BASE + i then
			local uuid = moho.layer:UUID()
			if self.boundLayers[uuid] ~= i then
				if self.boundLayers[uuid] then
					self:ClearButton(self.boundLayers[uuid])
				end
				self:UnbindAllLayersFromButton(moho, i)
				local scriptData = moho.layer:ScriptData()
				scriptData:Set(self.bindingKey, i)
				self:BindButtonToLayer(i, moho.layer)
			end
		elseif msg == self.CHECKBOX_VISIBILITY_MSG_BASE + i then
			self:SetLayerVisibility(moho, i, self.layerVisibilityCheckBoxes[i]:Value())
		elseif msg == self.CHECKBOX_TIMELINE_MSG_BASE + i then
			self:SetLayerTimelineVisibility(moho, i, self.layerTimelineCheckBoxes[i]:Value())
		end
	end		
	if msg == self.RESET then
		self:Reset(moho)
	elseif msg == self.SHOW_LAYER then
		self.showLayer = self.showLayerCheckbox:Value()
	end
end

function SZ_LayerSelectionButtons:UnbindAllLayersFromButton(moho, buttonNumber)
	local count = 0
	repeat
		local layer = moho.document:LayerByAbsoluteID(count)
		if layer then
			count = count + 1
			local scriptData = layer:ScriptData()
			if scriptData:HasKey(self.bindingKey) and scriptData:GetInt(self.bindingKey) == buttonNumber then
				scriptData:Remove(self.bindingKey)
			end
		end
	until not layer	
end

function SZ_LayerSelectionButtons:SetLayerVisibility(moho, buttonNumber, value)
	local count = 0
	repeat
		local layer = moho.document:LayerByAbsoluteID(count)
		if layer then
			count = count + 1
			local scriptData = layer:ScriptData()
			if scriptData:HasKey(self.bindingKey) and scriptData:GetInt(self.bindingKey) == buttonNumber then
				layer:SetVisible(value)
				moho:UpdateUI()
				break
			end
		end
	until not layer
end

function SZ_LayerSelectionButtons:SetLayerTimelineVisibility(moho, buttonNumber, value)
	local count = 0
	repeat
		local layer = moho.document:LayerByAbsoluteID(count)
		if layer then
			count = count + 1
			local scriptData = layer:ScriptData()
			if scriptData:HasKey(self.bindingKey) and scriptData:GetInt(self.bindingKey) == buttonNumber then
				layer:SetShownOnTimeline(value)
				moho:UpdateUI()
				break
			end
		end
	until not layer
end

function SZ_LayerSelectionButtons:SelectBoundLayer(moho, buttonNumber)
	local count = 0
	repeat
		local layer = moho.document:LayerByAbsoluteID(count)
		if layer then
			count = count + 1
			local scriptData = layer:ScriptData()
			if scriptData:HasKey(self.bindingKey) and scriptData:GetInt(self.bindingKey) == buttonNumber then
				moho:SetSelLayer(layer, false, true)
				-- These are the methods I tried, and none of them updates the tool panel:
					-- moho:UpdateUI()				
					-- moho.view:DrawMe()
					-- moho.view:RefreshView()
					-- layer:UpdateCurFrame(true)
					-- MOHO.Redraw()
					-- moho:UpdateSelectedChannels()
					-- moho:UpdateBonePointSelection()
				-- That's why we have to do some dark magic here instead:
				local sacrificialLayer = moho:CreateNewLayer(MOHO.LT_UNKNOWN)
				moho:DeleteLayer(sacrificialLayer)
				
				if self.showLayer then
					moho:ShowLayerInLayersPalette(layer)
				end
				break
			end
		end
	until not layer
end

function SZ_LayerSelectionButtons:ClearButton(buttonNumber)
	self.layerButtons[buttonNumber]:SetLabel(self:Localize("emptyButton"), false)
	self.layerVisibilityCheckBoxes[buttonNumber]:SetValue(false);
	self.layerVisibilityCheckBoxes[buttonNumber]:Enable(false);
	self.layerTimelineCheckBoxes[buttonNumber]:SetValue(false);
	self.layerTimelineCheckBoxes[buttonNumber]:Enable(false);
end

function SZ_LayerSelectionButtons:BindButtonToLayer(buttonNumber, layer)
	self.boundLayers[layer:UUID()] = buttonNumber
	self.layerButtons[buttonNumber]:SetLabel(layer:Name(), false)
	self.layerVisibilityCheckBoxes[buttonNumber]:Enable(true)
	self.layerVisibilityCheckBoxes[buttonNumber]:SetValue(layer:IsVisible())
	self.layerTimelineCheckBoxes[buttonNumber]:Enable(true)
	self.layerTimelineCheckBoxes[buttonNumber]:SetValue(layer:IsShownOnTimeline())
end

function SZ_LayerSelectionButtons:Reset(moho)
	self.boundLayers = {}
	local count = 0
	repeat
		local layer = moho.document:LayerByAbsoluteID(count)
		if layer then
			count = count + 1
			local scriptData = layer:ScriptData()
			if scriptData:HasKey(self.bindingKey) then
				scriptData:Remove(self.bindingKey)
			end
		end
	until not layer
	for i=1, self.numberOfButtons do
		self:ClearButton(i)
	end
end

-- Tool localization

function SZ_LayerSelectionButtons:Localize(text)
	local fileWord = MOHO.Localize("/Menus/File/File=File")
	
	local phrase = {}
	
	phrase["name"] = "Layer Selection Buttons"
	phrase["description"] = "Select a layer by pressing a button. Alt+click a button to assign to the current layer."
	phrase["label"] = "Layer Selection Buttons"
	phrase["emptyButton"] = "        —        "
	phrase["reset"] = "Reset"
	phrase["layerVisibility"] = "Layer Visibility"
	phrase["timelineVisibility"] = "Timeline Visibility"
	phrase["showLayer"] = "Show layer"
		
	if fileWord == "Файл" then
		phrase["name"] = "Кнопки выбора слоев"
		phrase["description"] = "Выбирает слой по клику на кнопку. Чтобы назначить текущий слой на кнопку, кликните на нее удерживая Alt."
		phrase["label"] = "Кнопки выбора слоев"
		phrase["reset"] = "Сбросить"
		phrase["layerVisibility"] = "Видимость слоя"
		phrase["timelineVisibility"] = "Видимость в таймлайне"
		phrase["showLayer"] = "Показать слой"
	end
	
	return phrase[text];
end

Icon
Layer Selection Buttons
Listed

Author: Stan View Script
Script type: Tool

Uploaded: Jan 10 2021, 19:18

Allows you to assign any layer in the project to a button for quick selection and visibility control.


See also: Bone Selection Buttons tool.
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: 170