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

ScriptName = "AE_Recolor"

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

AE_Recolor = {}

function AE_Recolor:Name()
	return 'Recolor'
end

function AE_Recolor:Version()
	return '1.2'
end

function AE_Recolor:UILabel()
	return 'Recolor'
end

function AE_Recolor:Creator()
	return 'Alexandra Evseeva'
end

function AE_Recolor:Description()
	return 'Change color to color for fill and/or line of any shape in a layer'
end

function AE_Recolor:ColorizeIcon()
	return true
end

-- **************************************************
-- Is Relevant / Is Enabled
-- **************************************************

function AE_Recolor:IsRelevant(moho)
	return true
end

function AE_Recolor:IsEnabled(moho)
	return true
end

-- **************************************************
-- Recurring Values
-- **************************************************

AE_Recolor.ignoreAlpha = true
AE_Recolor.changeFill = true
AE_Recolor.changeLine = true
AE_Recolor.changeLineWidth = true


-- **************************************************
-- Prefs
-- **************************************************

function AE_Recolor:LoadPrefs(prefs)
	self.ignoreAlpha = prefs:GetBool("AE_Recolor.ignoreAlpha", true)
	self.changeFill = prefs:GetBool("AE_Recolor.changeFill", true)
	self.changeLine = prefs:GetBool("AE_Recolor.changeLine", true)
	self.changeLineWidth = prefs:GetBool("AE_Recolor.changeLineWidth", true)	
end

function AE_Recolor:SavePrefs(prefs)
	prefs:SetBool("AE_Recolor.ignoreAlpha", self.ignoreAlpha)
	prefs:SetBool("AE_Recolor.changeFill", self.changeFill)
	prefs:SetBool("AE_Recolor.changeLine", self.changeLine)
	prefs:SetBool("AE_Recolor.changeLineWidth", self.changeLineWidth)	
end

function AE_Recolor:ResetPrefs()
	self.ignoreAlpha = true
	self.changeFill = true
	self.changeLine = true
	self.changeLineWidth = true	
end

-- **************************************************
-- AE_RecolorDialog
-- **************************************************

local AE_RecolorDialog = {}

AE_RecolorDialog.IGNOREALPHACHECK = MOHO.MSG_BASE
AE_RecolorDialog.FILLCHECK = MOHO.MSG_BASE + 1
AE_RecolorDialog.LINECHECK = MOHO.MSG_BASE + 2
AE_RecolorDialog.OLDFILL = MOHO.MSG_BASE + 3
AE_RecolorDialog.NEWFILL = MOHO.MSG_BASE + 4
AE_RecolorDialog.OLDLINE = MOHO.MSG_BASE + 5
AE_RecolorDialog.NEWLINE = MOHO.MSG_BASE + 6
AE_RecolorDialog.POINTCHECK = MOHO.MSG_BASE + 7
AE_RecolorDialog.OLDPOINT = MOHO.MSG_BASE + 8
AE_RecolorDialog.NEWPOINT = MOHO.MSG_BASE + 9
AE_RecolorDialog.LINEWIDTHCHECK = MOHO.MSG_BASE + 10
AE_RecolorDialog.OLDLINEWIDTH = MOHO.MSG_BASE + 11
AE_RecolorDialog.NEWLINEWIDTH = MOHO.MSG_BASE + 12


function AE_RecolorDialog:new(moho)
	local d = LM.GUI.SimpleDialog('Recolor', AE_RecolorDialog)
	local l = d:GetLayout()

	d.ignoreAlphaCheckbox = LM.GUI.CheckBox('Ignore alpha', d.IGNOREALPHACHECK)
	l:AddChild(d.ignoreAlphaCheckbox, LM.GUI.ALIGN_LEFT, 0)

	-- fill color
	l:PushH()
		d.fillCheckbox = LM.GUI.CheckBox('Change fill', d.FILLCHECK)
		l:AddChild(d.fillCheckbox, LM.GUI.ALIGN_LEFT, 0)
		d.oldFill = LM.GUI.ColorSwatch(true, d.OLDFILL)
		l:AddChild(d.oldFill)
		d.newFill = LM.GUI.ColorSwatch(true, d.NEWFILL)
		l:AddChild(d.newFill)	
		d.oldFill:SetValue(moho:NewShapeFillColor())
		d.newFill:SetValue(moho:NewShapeFillColor())
	l:Pop()
	-- line color
	l:PushH()
		d.lineCheckbox = LM.GUI.CheckBox('Change line', d.LINECHECK)
		l:AddChild(d.lineCheckbox, LM.GUI.ALIGN_LEFT, 0)
		d.oldLine = LM.GUI.ColorSwatch(true, d.OLDLINE)
		l:AddChild(d.oldLine)
		d.newLine = LM.GUI.ColorSwatch(true, d.NEWLINE)
		l:AddChild(d.newLine)	
		d.oldLine:SetValue(moho:NewShapeLineColor())
		d.newLine:SetValue(moho:NewShapeLineColor())
	l:Pop()
	-- line width
	l:PushH()
		d.lineWidthCheckbox = LM.GUI.CheckBox('Change line width', d.LINEWIDTHCHECK)
		l:AddChild(d.lineWidthCheckbox, LM.GUI.ALIGN_LEFT, 0)
		d.oldLineWidth = LM.GUI.TextControl(100, "1.00", d.OLDLINEWIDTH, LM.GUI.LM_FIELD_FLOAT, "Old width")
		l:AddChild(d.oldLineWidth)
		d.newLineWidth = LM.GUI.TextControl(100, "1.00", d.NEWLINEWIDTH, LM.GUI.LM_FIELD_FLOAT, "New width")
		l:AddChild(d.newLineWidth)	
		d.oldLineWidth:SetValue(moho:NewShapeLineWidth()* moho.document:Height())
		d.newLineWidth:SetValue(moho:NewShapeLineWidth()* moho.document:Height())
	l:Pop()	
	-- point color
	l:PushH()
		d.pointCheckbox = LM.GUI.CheckBox('Change points', d.POINTCHECK)
		l:AddChild(d.pointCheckbox, LM.GUI.ALIGN_LEFT, 0)
		d.oldPoint = LM.GUI.ColorSwatch(true, d.OLDPOINT)
		l:AddChild(d.oldPoint)
		d.newPoint = LM.GUI.ColorSwatch(true, d.NEWPOINT)
		l:AddChild(d.newPoint)	
		--d.oldPoint:SetValue(moho:NewShapeLineColor())
		--d.newPoint:SetValue(moho:NewShapeLineColor())
	l:Pop()	
	return d
end

function AE_RecolorDialog:UpdateWidgets(moho)
	self.ignoreAlphaCheckbox:SetValue(AE_Recolor.ignoreAlpha)
	self.fillCheckbox:SetValue(AE_Recolor.changeFill)
	self.lineCheckbox:SetValue(AE_Recolor.changeLine)
	self.lineWidthCheckbox:SetValue(AE_Recolor.changeLineWidth)
	self.pointCheckbox:SetValue(AE_Recolor.changePoint)
end

function AE_RecolorDialog:OnOK(moho)
	AE_Recolor.ignoreAlpha = self.ignoreAlphaCheckbox:Value()
	AE_Recolor.changeFill = self.fillCheckbox:Value()
	AE_Recolor.changeLine = self.lineCheckbox:Value()
	AE_Recolor.changeLineWidth = self.lineWidthCheckbox:Value()
	AE_Recolor.changePoint = self.pointCheckbox:Value()
	AE_Recolor.oldFill = self.oldFill:Value()
	AE_Recolor.newFill = self.newFill:Value()
	AE_Recolor.oldLine = self.oldLine:Value()
	AE_Recolor.newLine = self.newLine:Value()
	AE_Recolor.oldLineWidth = self.oldLineWidth:Value()
	AE_Recolor.newLineWidth = self.newLineWidth:Value()	
	AE_Recolor.oldPoint = self.oldPoint:Value()
	AE_Recolor.newPoint = self.newPoint:Value()	
end

function AE_RecolorDialog:HandleMessage(msg)
	if msg == self.IGNOREALPHACHECK then
		--print('Message IGNOREALPHACHECK received')
	elseif msg == self.FILLCHECK then
		--print('Message FILLCHECK received')
		self.oldFill:Enable(self.fillCheckbox:Value())
		self.newFill:Enable(self.fillCheckbox:Value())
	elseif msg == self.LINECHECK then
		--print('Message LINECHECK received')
		self.oldLine:Enable(self.lineCheckbox:Value())
		self.newLine:Enable(self.lineCheckbox:Value())
	elseif msg == self.LINEWIDTHCHECK then
		--print('Message LINECHECK received')
		self.oldLineWidth:Enable(self.lineWidthCheckbox:Value())
		self.newLineWidth:Enable(self.lineWidthCheckbox:Value())		
	elseif msg == self.POINTCHECK then
		--print('Message LINECHECK received')
		self.oldPoint:Enable(self.pointCheckbox:Value())
		self.newPoint:Enable(self.pointCheckbox:Value())	
	
	else
		
	end
end


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

function AE_Recolor:Run(moho)
	local dlog = AE_RecolorDialog:new(moho)
	if (dlog:DoModal() == LM.GUI.MSG_CANCEL) then
		return
	end
	
	moho.document:SetDirty()
	moho.document:PrepUndo(nil)
	
	-- iterate all child layers, processing vector ones
	for i, layer in AE_Utilities:IterateAllLayers(moho) do
		if moho:LayerAsVector(layer) and (layer:IsAncestorSelected() or layer:SecondarySelection()) then
			local mesh = moho:LayerAsVector(layer):Mesh()
			-- iterate all shapes in a mesh
			for s = 0, mesh:CountShapes()-1 do
				local shape = mesh:Shape(s)
				-- get and process line and/or fill with self:Recolor_channel
				if self.changeFill then
					local fillChannel = shape.fMyStyle.fFillCol
					self:Recolor_channel(moho, fillChannel, self.oldFill, self.newFill)
				end
				if self.changeLine then
					local lineChannel = shape.fMyStyle.fLineCol
					self:Recolor_channel(moho, lineChannel, self.oldLine, self.newLine)
				end
				if self.changeLineWidth then
					--print(shape.fMyStyle.fLineWidth*1000, " ", self.oldLineWidth)
					if math.abs(shape.fMyStyle.fLineWidth * moho.document:Height() - self.oldLineWidth) < 0.1 then
						shape.fMyStyle.fLineWidth = self.newLineWidth/moho.document:Height()
					end
				end				
			end
			if self.changePoint then
				for p = 0, mesh:CountPoints() -1 do
					local nextPoint = mesh:Point(p)
					if nextPoint.fColored then
						self:Recolor_channel(moho, nextPoint.fColor, self.oldPoint, self.newPoint)
					end
				end
			end
		end
	end	
end

function AE_Recolor:Recolor_channel(moho, channel, oldColor, newColor)
	local newColorVector = LM.ColorVector:new_local()
	newColorVector:Set(newColor)
	-- iterate all main timeline keys
	for k = 0, channel:CountKeys() - 1 do
		local colorVector = channel:GetValueByID(k)
		if self:EqualColors(colorVector, oldColor) then
			if self.ignoreAlpha then
				newColorVector.a = colorVector.a
			end
			channel:SetValueByID(k, newColorVector)
		end
	end
	-- iterate all timelines (actions)
	for a = 0, channel:CountActions() - 1 do
		local actionChannel = moho:ChannelAsAnimColor(channel:Action(a))
		-- iterate all keys for each timeline checking color with or without alpha	
		for k = 1, actionChannel:CountKeys() - 1 do
			local colorVector = actionChannel:GetValueByID(k)
			if self:EqualColors(colorVector, oldColor) then
				if self.ignoreAlpha then
					newColorVector.a = colorVector.a
				end
				actionChannel:SetValueByID(k, newColorVector)
			end
		end		
	end

end

function AE_Recolor:EqualColors(colorVector, rgb)
	-- compare r, g, b and alpha if it is not ignored
	local oldRGB = colorVector:AsColorStruct()
	if oldRGB.r ~= rgb.r then return false end
	if oldRGB.g ~= rgb.g then return false end
	if oldRGB.b ~= rgb.b then return false end
	if self.ignoreAlpha then return true end
	if oldRGB.a ~= rgb.a then return false end
	return true
end

Recolor
Listed

Script type: Button/Menu

Uploaded: Apr 24 2021, 13:03

Change shape color over all child layers, actions and animation

Installation Options:

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: 164