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

ScriptName = "SZ_RecolorLayer"

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

SZ_RecolorLayer = {}

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

function SZ_RecolorLayer:Version()
	return "3.1"
end

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

function SZ_RecolorLayer:Creator()
	return "Stan aka Vodka"
end

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

-- Tool localization

function SZ_RecolorLayer:Localize(text)
	local fileWord = MOHO.Localize("/Menus/File/File=File")
	
	local phrase = {}
	
	phrase["name"] = "Recolor Layer"
	phrase["description"] = "Recolors all shapes in a single vector layer or the entire document."
	phrase["label"] = "Recolor Layer"
		
	if fileWord == "Файл" then
		phrase["name"] = "Перекраска слоя"
		phrase["description"] = "Recolors all shapes in a single vector layer or the entire document."
		phrase["label"] = "Перекраска слоя"		
	end
	
	return phrase[text];
end


-- **************************************************
-- Recurring values
-- **************************************************
SZ_RecolorLayer.useFill = true
SZ_RecolorLayer.fillOption = 55
SZ_RecolorLayer.useFillColor = false

SZ_RecolorLayer.fillColor = LM.rgb_color:new_local()

SZ_RecolorLayer.changeFillColor = false
SZ_RecolorLayer.fillColorFrom = LM.rgb_color:new_local()

SZ_RecolorLayer.fillColorTo = LM.rgb_color:new_local()
SZ_RecolorLayer.fillColorTo.r = 255
SZ_RecolorLayer.fillColorTo.g = 255
SZ_RecolorLayer.fillColorTo.b = 255
SZ_RecolorLayer.fillColorTo.a = 255
SZ_RecolorLayer.fillTolerance = 0

SZ_RecolorLayer.useStroke = true
SZ_RecolorLayer.strokeOption = 52
SZ_RecolorLayer.useStrokeColor = false
SZ_RecolorLayer.strokeColor = LM.rgb_color:new_local()

SZ_RecolorLayer.useStrokeWidth = false
SZ_RecolorLayer.strokeWidth = 1

SZ_RecolorLayer.changeStrokeColor = false
SZ_RecolorLayer.strokeColorFrom = LM.rgb_color:new_local()
SZ_RecolorLayer.strokeColorTo = LM.rgb_color:new_local()
SZ_RecolorLayer.strokeColorTo.r = 0
SZ_RecolorLayer.strokeColorTo.g = 0
SZ_RecolorLayer.strokeColorTo.b = 0
SZ_RecolorLayer.strokeColorTo.a = 255
SZ_RecolorLayer.strokeTolerance = 0

SZ_RecolorLayer.useRandomLineWidth = false
SZ_RecolorLayer.randomLineWidthMin = 75
SZ_RecolorLayer.randomLineWidthMax = 140

SZ_RecolorLayer.createNoisyKeyframe = false
SZ_RecolorLayer.amplitudeMin = 0.1
SZ_RecolorLayer.amplitudeMax = 0.5
SZ_RecolorLayer.scaleMin = 0
SZ_RecolorLayer.scaleMax = 1.75

SZ_RecolorLayer.useRoundCaps = false
SZ_RecolorLayer.roundCaps = true

SZ_RecolorLayer.forAllLayers = false
SZ_RecolorLayer.createKeyframe = false

SZ_RecolorLayer.layersToRecolor = {}

-- **************************************************
-- UI dialog
-- **************************************************

local SZ_RecolorLayerDialog = {}

function SZ_RecolorLayerDialog:new(moho)
	local d = LM.GUI.SimpleDialog(self:Localize("title"), SZ_RecolorLayerDialog)
	local l = d:GetLayout()

	d.moho = moho
	
	l:PushH()
		l:PushV()
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.useFill = LM.GUI.CheckBox(self:Localize("use_fill"), 1)
				l:AddChild(d.useFill)
			l:Pop()
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.fillON = LM.GUI.RadioButton(self:Localize("turn_all_on"), 53)
				l:AddChild(d.fillON)
				d.fillOFF = LM.GUI.RadioButton(self:Localize("turn_all_off"), 54)
				l:AddChild(d.fillOFF)
				d.fillLeave = LM.GUI.RadioButton(self:Localize("leave_as_is"), 55)
				l:AddChild(d.fillLeave)
			l:Pop()
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.useFillColor = LM.GUI.CheckBox(self:Localize("paint_all_fills"))
				l:AddChild(d.useFillColor)
				d.fillColor = LM.GUI.ColorSwatch(true)
				l:AddChild(d.fillColor)
			l:Pop()
			l:PushH()
				d.changeFillColor = LM.GUI.CheckBox(self:Localize("change_only_fills"), 57)
				l:AddChild(d.changeFillColor)
			l:Pop()
			l:PushH()
				d.fillFrom = LM.GUI.DynamicText(self:Localize("from"))
				l:AddChild(d.fillFrom)
				d.fillColorFrom = LM.GUI.ColorSwatch(true)
				l:AddPadding(-18)
				l:AddChild(d.fillColorFrom)
				d.fillPM = LM.GUI.DynamicText("+/-")
				l:AddChild(d.fillPM)
				d.fillTolerance = LM.GUI.TextControl(0, "000", 0, LM.GUI.FIELD_INT)
				l:AddChild(d.fillTolerance)
				d.fillTo = LM.GUI.DynamicText(self:Localize("to"))
				l:AddChild(d.fillTo)
				d.fillColorTo = LM.GUI.ColorSwatch(true)
				l:AddPadding(-18)
				l:AddChild(d.fillColorTo)
			l:Pop()
		l:Pop()
		l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
		l:PushV()
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.useStroke = LM.GUI.CheckBox(self:Localize("use_stroke"), 1)
				l:AddChild(d.useStroke)
			l:Pop()
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.strokeON = LM.GUI.RadioButton(self:Localize("turn_all_on"), 50)
				l:AddChild(d.strokeON)
				d.strokeOFF = LM.GUI.RadioButton(self:Localize("turn_all_off"), 51)
				l:AddChild(d.strokeOFF)
				d.strokeLeave = LM.GUI.RadioButton(self:Localize("leave_as_is"), 52)
				l:AddChild(d.strokeLeave)
			l:Pop()			
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.useStrokeWidth = LM.GUI.CheckBox(self:Localize("set_stroke_width"), 58)
				l:AddChild(d.useStrokeWidth)
				d.strokeWidth = LM.GUI.TextControl(0, "0000", 0, LM.GUI.FIELD_UFLOAT)
				l:AddChild(d.strokeWidth)
			l:Pop()
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.useStrokeColor = LM.GUI.CheckBox(self:Localize("paint_all_strokes"))
				l:AddChild(d.useStrokeColor)
				d.strokeColor = LM.GUI.ColorSwatch(true)
				l:AddChild(d.strokeColor)
			l:Pop()
			l:PushH()
				d.changeStrokeColor = LM.GUI.CheckBox(self:Localize("change_only_strokes"), 56)
				l:AddChild(d.changeStrokeColor)
			l:Pop()
			l:PushH()
				d.strokeFrom = LM.GUI.DynamicText(self:Localize("from"))
				l:AddChild(d.strokeFrom)
				d.strokeColorFrom = LM.GUI.ColorSwatch(true)
				l:AddPadding(-18)
				l:AddChild(d.strokeColorFrom)
				d.strokePM = LM.GUI.DynamicText("+/-")
				l:AddChild(d.strokePM)
				d.strokeTolerance = LM.GUI.TextControl(0, "000", 0, LM.GUI.FIELD_INT)
				l:AddChild(d.strokeTolerance)
				d.strokeTo = LM.GUI.DynamicText(self:Localize("to"))
				l:AddChild(d.strokeTo)
				d.strokeColorTo = LM.GUI.ColorSwatch(true)
				l:AddPadding(-18)
				l:AddChild(d.strokeColorTo)
			l:Pop()
		l:Pop()
		l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
		l:PushV()	
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.useRandomLineWidth = LM.GUI.CheckBox(self:Localize("use_random_line_width"), 1)
				l:AddChild(d.useRandomLineWidth)
			l:Pop()
			l:PushH(LM.GUI.ALIGN_RIGHT)
				d.randomLineWidthMinText = LM.GUI.DynamicText(self:Localize("min"), 0)
				l:AddChild(d.randomLineWidthMinText)
				d.randomLineWidthMin = LM.GUI.TextControl(0, "0000", 0, LM.GUI.FIELD_UFLOAT)
				l:AddPadding(-16)
				l:AddChild(d.randomLineWidthMin)
				d.randomLineWidthMaxText = LM.GUI.DynamicText(self:Localize("max"), 0)
				l:AddChild(d.randomLineWidthMaxText)
				d.randomLineWidthMax = LM.GUI.TextControl(0, "0000", 0, LM.GUI.FIELD_UFLOAT)
				l:AddPadding(-16)
				l:AddChild(d.randomLineWidthMax)
			l:Pop()
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.createNoisyKeyframe = LM.GUI.CheckBox(self:Localize("create_noisy_keyframe"), 1)
				l:AddChild(d.createNoisyKeyframe)
			l:Pop()
			l:PushH(LM.GUI.ALIGN_RIGHT)
				d.amplitudeText = LM.GUI.DynamicText(self:Localize("amplitude"))
				l:AddChild(d.amplitudeText)
				d.amplitudeMinText = LM.GUI.DynamicText(self:Localize("min"))
				l:AddChild(d.amplitudeMinText)
				d.amplitudeMin = LM.GUI.TextControl(0, "0000", 0, LM.GUI.FIELD_UFLOAT)
				l:AddPadding(-16)
				l:AddChild(d.amplitudeMin)
				d.amplitudeMaxText = LM.GUI.DynamicText(self:Localize("max"))
				l:AddChild(d.amplitudeMaxText)
				d.amplitudeMax = LM.GUI.TextControl(0, "0000", 0, LM.GUI.FIELD_UFLOAT)
				l:AddPadding(-16)
				l:AddChild(d.amplitudeMax)
			l:Pop()
			l:PushH(LM.GUI.ALIGN_RIGHT)
				d.scaleText = LM.GUI.DynamicText(self:Localize("scale"))
				l:AddChild(d.scaleText)
				d.scaleMinText = LM.GUI.DynamicText(self:Localize("min"))
				l:AddChild(d.scaleMinText)
				d.scaleMin = LM.GUI.TextControl(0, "0000", 0, LM.GUI.FIELD_UFLOAT)
				l:AddPadding(-16)
				l:AddChild(d.scaleMin)
				d.scaleMaxText = LM.GUI.DynamicText(self:Localize("max"))
				l:AddChild(d.scaleMaxText)
				d.scaleMax = LM.GUI.TextControl(0, "0000", 0, LM.GUI.FIELD_UFLOAT)
				l:AddPadding(-16)
				l:AddChild(d.scaleMax)
			l:Pop()
		l:Pop()
		l:AddChild(LM.GUI.Divider(true), LM.GUI.ALIGN_FILL)
		l:PushV()
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.useRoundCaps = LM.GUI.CheckBox(self:Localize("use_round_caps"), 1)
				l:AddChild(d.useRoundCaps)
			l:Pop()
			l:PushV(LM.GUI.ALIGN_LEFT)
				l:PushH(LM.GUI.ALIGN_LEFT)
					l:AddPadding(30)
					l:PushV(LM.GUI.ALIGN_LEFT)
						d.roundCaps = LM.GUI.RadioButton(self:Localize("round_caps"), 59)
						l:AddChild(d.roundCaps, LM.GUI.ALIGN_LEFT)
						d.dontRoundCaps = LM.GUI.RadioButton(self:Localize("dont_round_caps"), 60)
						l:AddChild(d.dontRoundCaps, LM.GUI.ALIGN_LEFT)
					l:Pop()
				l:Pop()
			l:Pop()
			l:AddPadding()
			l:AddChild(LM.GUI.Divider(false), LM.GUI.ALIGN_FILL)
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.forAllLayers = LM.GUI.CheckBox(self:Localize("for_all_layers"))
				l:AddChild(d.forAllLayers)
			l:Pop()
			l:PushH(LM.GUI.ALIGN_LEFT)
				d.createKeyframe = LM.GUI.CheckBox(self:Localize("create_keyframe"))
				l:AddChild(d.createKeyframe)
			l:Pop()
		l:Pop()
	l:Pop()
	local shape = moho:NewShapeProperties()
	local strokeRGBA = shape.fMyStyle.fLineCol.value
	local fillRGBA = shape.fMyStyle.fFillCol.value
	SZ_RecolorLayer.strokeColor = strokeRGBA
	SZ_RecolorLayer.strokeColorFrom = strokeRGBA
	SZ_RecolorLayer.fillColor = fillRGBA
	SZ_RecolorLayer.fillColorFrom = fillRGBA
	d.strokeColor:SetValue(SZ_RecolorLayer.strokeColorFrom)
	d.strokeColorFrom:SetValue(SZ_RecolorLayer.strokeColorFrom)
	d.fillColor:SetValue(SZ_RecolorLayer.fillColorFrom)
	d.fillColorFrom:SetValue(SZ_RecolorLayer.fillColorFrom)
	return d
end

function SZ_RecolorLayerDialog:SetStrokeFillOption(opt)
	if opt == 50 then
		self.strokeON:SetValue(true)		
	elseif opt == 51 then
		self.strokeOFF:SetValue(true)
	elseif opt == 52 then
		self.strokeLeave:SetValue(true)
	elseif opt == 53 then
		self.fillON:SetValue(true)
	elseif opt == 54 then
		self.fillOFF:SetValue(true)
	elseif opt == 55 then
		self.fillLeave:SetValue(true)
	end
end

function SZ_RecolorLayerDialog:UpdateWidgets()
	self.useStroke:SetValue(SZ_RecolorLayer.useStroke)
	self:SetStrokeFillOption(SZ_RecolorLayer.strokeOption)
	self:SetStrokeFillOption(SZ_RecolorLayer.fillOption)
	
	self.changeFillColor:SetValue(SZ_RecolorLayer.changeFillColor)
	self.fillColorFrom:SetValue(SZ_RecolorLayer.fillColorFrom)
	self.fillColorTo:SetValue(SZ_RecolorLayer.fillColorTo)
	self.fillTolerance:SetValue(SZ_RecolorLayer.fillTolerance)
	
	self.useStrokeWidth:SetValue(SZ_RecolorLayer.useStrokeWidth)
	self.strokeWidth:SetValue(SZ_RecolorLayer.strokeWidth)
	
	self.changeStrokeColor:SetValue(SZ_RecolorLayer.changeStrokeColor)
	self.strokeColorFrom:SetValue(SZ_RecolorLayer.strokeColorFrom)
	self.strokeColorTo:SetValue(SZ_RecolorLayer.strokeColorTo)
	self.strokeTolerance:SetValue(SZ_RecolorLayer.strokeTolerance)
	
	self.useRandomLineWidth:SetValue(SZ_RecolorLayer.useRandomLineWidth)
	self.randomLineWidthMin:SetValue(SZ_RecolorLayer.randomLineWidthMin)
	self.randomLineWidthMax:SetValue(SZ_RecolorLayer.randomLineWidthMax)
	
	self.createNoisyKeyframe:SetValue(SZ_RecolorLayer.createNoisyKeyframe)
	self.amplitudeMin:SetValue(SZ_RecolorLayer.amplitudeMin)
	self.amplitudeMax:SetValue(SZ_RecolorLayer.amplitudeMax)
	self.scaleMin:SetValue(SZ_RecolorLayer.scaleMin)
	self.scaleMax:SetValue(SZ_RecolorLayer.scaleMax)
	
	self.useStrokeColor:SetValue(SZ_RecolorLayer.useStrokeColor)
	self.strokeColor:SetValue(SZ_RecolorLayer.strokeColor)
	
	self.useFill:SetValue(SZ_RecolorLayer.useFill)
	self.useFillColor:SetValue(SZ_RecolorLayer.useFillColor)
	self.fillColor:SetValue(SZ_RecolorLayer.fillColor)
	
	self.useRoundCaps:SetValue(SZ_RecolorLayer.useRoundCaps)
	-- self.roundCaps:SetValue(SZ_RecolorLayer.roundCaps)
	if(SZ_RecolorLayer.roundCaps) then
		self.roundCaps:SetValue(true)
	else
		self.dontRoundCaps:SetValue(true)
	end
	
	self.forAllLayers:SetValue(SZ_RecolorLayer.forAllLayers)
	self.createKeyframe:SetValue(SZ_RecolorLayer.createKeyframe)
	
	if self.changeFillColor:Value() == false then
		self.fillFrom:Enable(false)
		self.fillColorFrom:Enable(false)
		self.fillPM:Enable(false)
		self.fillTolerance:Enable(false)
		self.fillTo:Enable(false)
		self.fillColorTo:Enable(false)
	end
	
	if self.changeStrokeColor:Value() == false then
		self.strokeFrom:Enable(false)
		self.strokeColorFrom:Enable(false)
		self.strokePM:Enable(false)
		self.strokeTolerance:Enable(false)
		self.strokeTo:Enable(false)
		self.strokeColorTo:Enable(false)
	end
	
	if self.useStrokeWidth:Value() == false then
		self.strokeWidth:Enable(false)
	end
	
	self:HandleMessage(1)
end

function SZ_RecolorLayerDialog:OnOK()
	SZ_RecolorLayer.useStroke = self.useStroke:Value()		
	SZ_RecolorLayer.useStrokeWidth = self.useStrokeWidth:Value()
	SZ_RecolorLayer.strokeWidth = self.strokeWidth:FloatValue()
	
	SZ_RecolorLayer.changeFillColor = self.changeFillColor:Value()
	SZ_RecolorLayer.fillColorFrom = self.fillColorFrom:Value()
	SZ_RecolorLayer.fillColorTo = self.fillColorTo:Value()
	SZ_RecolorLayer.fillTolerance = self.fillTolerance:IntValue()
	
	SZ_RecolorLayer.changeStrokeColor = self.changeStrokeColor:Value()
	SZ_RecolorLayer.strokeColorFrom = self.strokeColorFrom:Value()
	SZ_RecolorLayer.strokeColorTo = self.strokeColorTo:Value()
	SZ_RecolorLayer.strokeTolerance = self.strokeTolerance:IntValue()
	
	SZ_RecolorLayer.useRandomLineWidth = self.useRandomLineWidth:Value()
	SZ_RecolorLayer.randomLineWidthMin = self.randomLineWidthMin:IntValue()
	SZ_RecolorLayer.randomLineWidthMax = self.randomLineWidthMax:IntValue()
	
	SZ_RecolorLayer.createNoisyKeyframe = self.createNoisyKeyframe:Value()
	SZ_RecolorLayer.amplitudeMin = self.amplitudeMin:FloatValue()
	SZ_RecolorLayer.amplitudeMax = self.amplitudeMax:FloatValue()
	SZ_RecolorLayer.scaleMin = self.scaleMin:FloatValue()
	SZ_RecolorLayer.scaleMax = self.scaleMax:FloatValue()
	
	SZ_RecolorLayer.useStrokeColor = self.useStrokeColor:Value()
	SZ_RecolorLayer.strokeColor = self.strokeColor:Value()
	
	SZ_RecolorLayer.useFill = self.useFill:Value()
	SZ_RecolorLayer.useFillColor = self.useFillColor:Value()
	SZ_RecolorLayer.fillColor = self.fillColor:Value()
	
	SZ_RecolorLayer.useRoundCaps = self.useRoundCaps:Value()
	SZ_RecolorLayer.roundCaps = self.roundCaps:Value()
	
	SZ_RecolorLayer.forAllLayers = self.forAllLayers:Value()
	SZ_RecolorLayer.createKeyframe = self.createKeyframe:Value()
end

function SZ_RecolorLayerDialog:HandleMessage(msg)
	if msg>=50 and msg<=52 then
		SZ_RecolorLayer.strokeOption = msg
	elseif msg>=53 and msg<=55 then
		SZ_RecolorLayer.fillOption = msg
	elseif msg==57 then
		if (self.changeFillColor:Value() == true) then
			self.fillFrom:Enable(true)
			self.fillColorFrom:Enable(true)
			self.fillPM:Enable(true)
			self.fillTolerance:Enable(true)
			self.fillTo:Enable(true)
			self.fillColorTo:Enable(true)
		else
			self.fillFrom:Enable(false)
			self.fillColorFrom:Enable(false)
			self.fillPM:Enable(false)
			self.fillTolerance:Enable(false)
			self.fillTo:Enable(false)
			self.fillColorTo:Enable(false)
		end
	elseif msg==56 then
		if (self.changeStrokeColor:Value() == true) then
			self.strokeFrom:Enable(true)
			self.strokeColorFrom:Enable(true)
			self.strokePM:Enable(true)
			self.strokeTolerance:Enable(true)
			self.strokeTo:Enable(true)
			self.strokeColorTo:Enable(true)
		else
			self.strokeFrom:Enable(false)
			self.strokeColorFrom:Enable(false)
			self.strokePM:Enable(false)
			self.strokeTolerance:Enable(false)
			self.strokeTo:Enable(false)
			self.strokeColorTo:Enable(false)
		end
	elseif msg == 58 then
		if (self.useStrokeWidth:Value() == true) then
			self.strokeWidth:Enable(true)
		else
			self.strokeWidth:Enable(false)
		end
	elseif msg == 59 then
		SZ_RecolorLayer.roundCaps = true
	elseif msg == 60 then
		SZ_RecolorLayer.roundCaps = false
	else
		if (self.useStroke:Value() == true) then
			self.strokeON:Enable(true)
			self.strokeOFF:Enable(true)
			self.strokeLeave:Enable(true)
			self.useStrokeColor:Enable(true)
			self.strokeColor:Enable(true)
			self.useStrokeWidth:Enable(true)
			self.changeStrokeColor:Enable(true)			
		else
			self.strokeON:Enable(false)
			self.strokeOFF:Enable(false)
			self.strokeLeave:Enable(false)
			self.useStrokeColor:SetValue(false)
			self.useStrokeColor:Enable(false)
			self.strokeColor:Enable(false)
			self.useStrokeWidth:SetValue(false)
			self.useStrokeWidth:Enable(false)
			self.strokeWidth:Enable(false)
			self.changeStrokeColor:SetValue(false)
			self.changeStrokeColor:Enable(false)
			self.strokeFrom:Enable(false)
			self.strokeColorFrom:Enable(false)
			self.strokeTo:Enable(false)
			self.strokeColorTo:Enable(false)
			self.strokeTolerance:Enable(false)
			self.strokePM:Enable(false)
		end
		
		if (self.useRandomLineWidth:Value() == true) then
			self.randomLineWidthMinText:Enable(true)
			self.randomLineWidthMaxText:Enable(true)
			self.randomLineWidthMin:Enable(true)
			self.randomLineWidthMax:Enable(true)
		else
			self.randomLineWidthMinText:Enable(false)
			self.randomLineWidthMaxText:Enable(false)
			self.randomLineWidthMin:Enable(false)
			self.randomLineWidthMax:Enable(false)
		end
		
		if (self.createNoisyKeyframe:Value() == true) then
			self.amplitudeText:Enable(true)
			self.amplitudeMinText:Enable(true)
			self.amplitudeMin:Enable(true)
			self.amplitudeMaxText:Enable(true)
			self.amplitudeMax:Enable(true)
			self.scaleText:Enable(true)
			self.scaleMinText:Enable(true)
			self.scaleMin:Enable(true)
			self.scaleMaxText:Enable(true)
			self.scaleMax:Enable(true)
		else
			self.amplitudeText:Enable(false)
			self.amplitudeMinText:Enable(false)
			self.amplitudeMin:Enable(false)
			self.amplitudeMaxText:Enable(false)
			self.amplitudeMax:Enable(false)
			self.scaleText:Enable(false)
			self.scaleMinText:Enable(false)
			self.scaleMin:Enable(false)
			self.scaleMaxText:Enable(false)
			self.scaleMax:Enable(false)
		end
		
		if (self.useFill:Value() == true) then
			self.fillON:Enable(true)
			self.fillOFF:Enable(true)
			self.fillLeave:Enable(true)
			self.useFillColor:Enable(true)
			self.fillColor:Enable(true)
			self.changeFillColor:Enable(true)
		else
			self.fillON:Enable(false)
			self.fillOFF:Enable(false)
			self.fillLeave:Enable(false)
			self.useFillColor:SetValue(false)
			self.useFillColor:Enable(false)
			self.fillColor:Enable(false)
			self.changeFillColor:SetValue(false)
			self.changeFillColor:Enable(false)
			self.fillFrom:Enable(false)
			self.fillColorFrom:Enable(false)
			self.fillTo:Enable(false)
			self.fillColorTo:Enable(false)
			self.fillTolerance:Enable(false)
			self.fillPM:Enable(false)
		end
		
		if (self.useRoundCaps:Value() == true) then
			self.roundCaps:Enable(true)
			self.dontRoundCaps:Enable(true)
		else
			self.roundCaps:Enable(false)
			self.dontRoundCaps:Enable(false)
		end
	end
end

-- Dialog localization

function SZ_RecolorLayerDialog:Localize(text)
	local fileWord = MOHO.Localize("/Menus/File/File=File")
	
	local phrase = {}
	
	phrase["name"] = "Recolor Layer"
	phrase["title"] = "Recolor Layer"
	phrase["description"] = "Recolors all shapes in a single vector layer or the entire document."
	phrase["label"] = "Recolor Layer"
	phrase["use_fill"] = "Use fill"
	phrase["turn_all_on"] = "Turn all ON"
	phrase["turn_all_off"] = "Turn all OFF"
	phrase["leave_as_is"] = "Leave as is"
	phrase["paint_all_fills"] = "Paint all fills with this color:"
	phrase["change_only_fills"] = "Change only fills that have color:"
	phrase["from"] = "from:"
	phrase["to"] = "to:"
	phrase["use_stroke"] = "Use stroke"
	phrase["set_stroke_width"] = "Set stroke width to:"
	phrase["paint_all_strokes"] = "Paint all strokes with this color:"
	phrase["change_only_strokes"] = "Change only strokes that have color:"
	phrase["use_random_line_width"] = "Use random line width (%):"
	phrase["min"] = "Min:"
	phrase["max"] = "Max:"
	phrase["create_noisy_keyframe"] = "Create noisy keyframes for the line width:"
	phrase["amplitude"] = "Amplitude:"
	phrase["scale"] = "Scale:"
	phrase["use_round_caps"] = "Use Round caps"
	phrase["round_caps"] = "Round caps"
	phrase["dont_round_caps"] = "Don't round caps"
	phrase["for_all_layers"] = "Do this for ALL layers"
	phrase["create_keyframe"] = "Create a keyframe"
	
	
	
	if fileWord == "Файл" then
		phrase["name"] = "Перекраска слоя"
		phrase["title"] = "Перекраска слоя"
		phrase["description"] = "Recolors all shapes in a single vector layer or the entire document."
		phrase["label"] = "Перекраска слоя"
		phrase["use_fill"] = "Применить к заливкам"
		phrase["turn_all_on"] = "Включить все"
		phrase["turn_all_off"] = "Выключить все"
		phrase["leave_as_is"] = "Оставить как есть"
		phrase["paint_all_fills"] = "Перекрасить все заливки в этот цвет:"
		phrase["change_only_fills"] = "Перекрасить только заливки определенного цвета:"
		phrase["from"] = "сейчас такой:"
		phrase["to"] = "а станет:"
		phrase["use_stroke"] = "Применить к контурам"
		phrase["set_stroke_width"] = "Установить всем контурам такую ширину:"
		phrase["paint_all_strokes"] = "Перекрасить все контуры в этот цвет:"
		phrase["change_only_strokes"] = "Перекрасить только контуры определенного цвета:"
		phrase["use_random_line_width"] = "Применить случайную ширину контура (%)"
		phrase["min"] = "Мин:"
		phrase["max"] = "Макс:"
		phrase["create_noisy_keyframe"] = "Создать беспорядочный ключ для ширины:"
		phrase["amplitude"] = "Амплитуда:"
		phrase["scale"] = "Масштаб:"
		phrase["use_round_caps"] = "Применить скругление углов"
		phrase["round_caps"] = "Скруглять"
		phrase["dont_round_caps"] = "Не скруглять"
		phrase["for_all_layers"] = "Применить ко ВСЕМ слоям"
		phrase["create_keyframe"] = "Создать ключ в текущем кадре"
		
	end
	
	return phrase[text];
end

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

function SZ_RecolorLayer:IsEnabled(moho)
    local vectorLayer = moho:LayerAsVector(moho.layer)
    if (vectorLayer) then
        return true
    end

    if (moho.layer:IsGroupType()) then
        return true
    end
    return false
end

function SZ_RecolorLayer:Run(moho)
	local dlog = SZ_RecolorLayerDialog:new(moho)
	if (dlog:DoModal() == LM.GUI.MSG_CANCEL) then
		return
	end
	
	moho.document:PrepMultiUndo()
	moho.document:SetDirty()
	
	local f = 0
	local l
	
	if (self.createKeyframe) then
		f = moho.frame
	end
	
	self:ScanLayers(moho)
	
	for k,id in ipairs(self.layersToRecolor) do
		l=moho:LayerAsVector(moho.document:LayerByAbsoluteID(id))
		self:RecolorLayer(moho,l,f)
	end
	
	for k in pairs(self.layersToRecolor) do
		self.layersToRecolor[k] = nil
	end
end

function SZ_RecolorLayer:RecolorLayer(moho, layer, frame)
	
	local mesh = layer:Mesh()
	
	for i = 0, mesh:CountShapes() - 1 do
		local shape = mesh:Shape(i)		
		
		if (self.useStroke) then			
			if self.strokeOption == 50 then
				shape.fHasOutline = true
			elseif self.strokeOption == 51 then
				shape.fHasOutline = false
			end
			
			if (self.useStrokeWidth) then
				shape.fMyStyle.fLineWidth = self.strokeWidth / moho.document:Height()
			end
			if (self.useStrokeColor) then	
				shape.fMyStyle.fLineCol:SetValue(frame, self.strokeColor)
			end
			if (self.changeStrokeColor) then
				local shapeColor = shape.fMyStyle.fLineCol.value
				if self:IsSimilarColors(self.strokeColorFrom, shapeColor, self.strokeTolerance) then 
					shape.fMyStyle.fLineCol:SetValue(frame, self.strokeColorTo)
				end
			end
		end
		
		if (self.useFill) then
			if self.fillOption == 53 then
				shape.fHasFill = true
			elseif self.fillOption == 54 then
				shape.fHasFill = false
			end
			
			if (self.useFillColor) then
				shape.fMyStyle.fFillCol:SetValue(frame, self.fillColor)
			end
			if (self.changeFillColor) then
				local shapeColor = shape.fMyStyle.fFillCol.value
				if self:IsSimilarColors(self.fillColorFrom, shapeColor, self.fillTolerance) then 
					shape.fMyStyle.fFillCol:SetValue(frame, self.fillColorTo)
				end
			end
		end
		
		if(self.useRoundCaps) then
			if (self.roundCaps) then
				shape.fMyStyle.fLineCaps = 1
			else
				shape.fMyStyle.fLineCaps = 0
			end
		end
	end	
	
	if (self.useRandomLineWidth) then
		local rnd, point
		for i = 0, mesh:CountPoints()-1 do
			rnd = math.random(self.randomLineWidthMin, self.randomLineWidthMax)
			point = mesh:Point(i)
			point.fWidth:SetValue(frame, rnd/100)
		end
	end
	
	if (self.createNoisyKeyframe) then
		-- local arnd, srnd, point, w
		for i = 0, mesh:CountPoints()-1 do
			local arnd = math.random(self.amplitudeMin * 10000, self.amplitudeMax * 10000)/10000
			local srnd = math.random(self.scaleMin * 10000, self.scaleMax * 10000)/10000
			local point = mesh:Point(i)
			local w = point.fWidth.value
			point.fWidth:SetValue(1, w)
			point.fWidth:SetKeyInterp(1, MOHO.INTERP_NOISY, arnd, 1/srnd)
		end
	end
	
end

function SZ_RecolorLayer:ScanLayers(moho)
	local layers
	if self.forAllLayers then
		layers = moho.document:CountLayers()-1
	else
		layers = moho.document:CountSelectedLayers()-1
	end
	
	for l = 0, layers do
		local layer
		if self.forAllLayers then
			layer = moho.document:Layer(l)
		else
			layer = moho.document:GetSelectedLayer(l)
		end
		if moho:LayerAsVector(layer) then
			local id = moho.document:LayerAbsoluteID(layer)
			if not self:IsInTable(id, self.layersToRecolor) then
				table.insert(self.layersToRecolor, id)
			end
		elseif layer:IsGroupType() then
			self:ScanGroup(moho, layer)
		end
	end
end

function SZ_RecolorLayer:ScanGroup(moho, group)
	local groupLayer = moho:LayerAsGroup(group)
	for i=0, groupLayer:CountLayers()-1 do
		local layer = group:Layer(i)
		if layer:IsGroupType() then
			self:ScanGroup(moho, layer) -- recursion
		elseif moho:LayerAsVector(layer) then
			local id = moho.document:LayerAbsoluteID(layer)
			if not self:IsInTable(id, self.layersToRecolor) then
				table.insert(self.layersToRecolor, id)
			end
		end
	end
end 

function SZ_RecolorLayer:IsSimilarColors(colorA, colorB, tolerance)
	local function IsSimilarNumbers(numA, numB)
		local lo = numA - tolerance
		local hi = numA + tolerance
		if numB >= lo and numB <= hi then
			return true
		end
		return false
	end
	
	if IsSimilarNumbers(colorA.r, colorB.r) and IsSimilarNumbers(colorA.g, colorB.g) and IsSimilarNumbers(colorA.b, colorB.b) and IsSimilarNumbers(colorA.a, colorB.a) then
		return true
	end
	return false
end

function SZ_RecolorLayer:IsInTable(item, tbl)
	for _,v in ipairs(tbl) do
		if (v == item) then
			return true
		end
	end
	return false
end

Recolor Layer
Listed

Author: Stan View Script
Script type: Button/Menu

Uploaded: Dec 23 2020, 19:38

Change all strokes/fills colors, add round corners, or create noisy line width
Image

Adding noisy line width:
Original:
Image

Using static random line width:
Image

Using noisy keyframes:
Image

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