local l={Name="\080\097\105\110\116 \084\111\111\108",Color=BrickColor.new("\082\101\097\108\108\121 \114\101\100"),BrickColor=nil}l.ManualText="\060\102\111\110\116 \102\097\099\101\061\"\071\111\116\104\097\109\066\108\097\099\107\" \115\105\122\101\061\"\049\054\"\062\080\097\105\110\116 \084\111\111\108  \240\159\155\160\060\047\102\111\110\116\062\n\076\101\116\115 \121\111\117 \112\097\105\110\116 \112\097\114\116\115 \105\110 \100\105\102\102\101\114\101\110\116 \099\111\108\111\114\115\046\060\102\111\110\116 \115\105\122\101\061\"\054\"\062\060\098\114 \047\062\060\047\102\111\110\116\062\n\n\060\098\062\084\073\080\058\060\047\098\062 \080\114\101\115\115 \060\098\062\060\105\062\082\060\047\105\062\060\047\098\062 \119\104\105\108\101 \104\111\118\101\114\105\110\103 \111\118\101\114 \097 \112\097\114\116 \116\111 \099\111\112\121 \105\116\115 \099\111\108\111\114\046"function l.Equip(l)l.Maid=Maid.new()ShowUI()l:BindShortcutKeys()l:EnableClickPainting()end function l.Unequip(l)HideUI()l.Maid=l.Maid:Destroy()end function ShowUI()if l.UI then l.UI.Visible=true UIUpdater=Support.ScheduleRecurringTask(UpdateUI,.1)return end l.UI=Core.Tool.Interfaces.BTPaintToolGUI:Clone()l.UI.Parent=Core.UI l.UI.Visible=true PaletteButtons={}for l,w in pairs(l.UI.Palette:GetChildren())do for l,w in pairs(w:GetChildren())do if w.ClassName=="\084\101\120\116\066\117\116\116\111\110"then w.MouseButton1Click:Connect(function()SetColor((BrickColor.new(w.Name)).Color)end)PaletteButtons[w.Name]=w end end end l.UI.Controls.LastColorButton.MouseButton1Click:Connect(PaintParts)local w=nil l.UI.Controls.ColorPickerButton.MouseButton1Click:Connect(function()local l=Support.IdentifyCommonProperty(Selection.Parts,"\067\111\108\111\114")local Z=Roact.createElement(ColorPicker,{InitialColor=l or Color3.fromRGB(255,255,255),SetPreviewColor=PreviewColor,OnConfirm=function(l)SetColor(l)w=Roact.unmount(w)end,OnCancel=function()w=Roact.unmount(w)end})w=w and Roact.update(w,Z)or Roact.mount(Z,Core.UI,"\067\111\108\111\114\080\105\099\107\101\114")end)local Z=(l.UI:WaitForChild("\084\105\116\108\101")):WaitForChild("\083\105\103\110\097\116\117\114\101")ListenForManualWindowTrigger(l.ManualText,l.Color.Color,Z)UIUpdater=Support.ScheduleRecurringTask(UpdateUI,.1)end function HideUI()if not l.UI then return end l.UI.Visible=false UIUpdater:Stop()end function UpdateUI()if not l.UI then return end for l,w in pairs(PaletteButtons)do w.Text=""end for l,w in pairs(Selection.Parts)do if PaletteButtons[w.BrickColor.Name]and w.Color==w.BrickColor.Color then PaletteButtons[w.BrickColor.Name].Text="\043"end end local w=Support.IdentifyCommonProperty(Selection.Parts,"\067\111\108\111\114")l.UI.Controls.ColorPickerButton.ImageColor3=w or l.BrickColor or Color3.new(1,0,0)end function SetColor(w)l.BrickColor=w local Z=BrickColor.new(w)local M=("\040\037\100\044 \037\100\044 \037\100\041"):format(w.r*255,w.g*255,w.b*255)local I=Z.Color==w and Z.Name or M local K=l.UI.Controls.LastColorButton.ColorName local G=K.ColorSquare K.Visible=true K.Text=I G.BackgroundColor3=w G.Position=UDim2.new(1,-K.TextBounds.X-18,.2,1)PaintParts()end function PaintParts()if not l.BrickColor or#Selection.Parts==0 then return end local w=PaintHistoryRecord.new()w.TargetColor=l.BrickColor w:Apply(true)Core.History.Add(w)end function PreviewColor(l)if not l and InitialState then for l,w in pairs(InitialState)do l.Color=w.Color if l.ClassName=="\085\110\105\111\110\079\112\101\114\097\116\105\111\110"then l.UsePartColor=w.UsePartColor end end InitialState=nil return elseif not l then return elseif not InitialState then InitialState={}for l,w in pairs(Selection.Parts)do InitialState[w]={Color=w.Color;UsePartColor=w.ClassName=="\085\110\105\111\110\079\112\101\114\097\116\105\111\110"and w.UsePartColor or nil}end end for w,Z in pairs(Selection.Parts)do Z.Color=l if Z.ClassName=="\085\110\105\111\110\079\112\101\114\097\116\105\111\110"then Z.UsePartColor=true end end end function l.BindShortcutKeys(l)l.Maid.Hotkeys=Support.AddUserInputListener("\066\101\103\097\110","\075\101\121\098\111\097\114\100",false,function(l)if l.KeyCode.Name=="\082\101\116\117\114\110"or l.KeyCode.Name=="\075\101\121\112\097\100\069\110\116\101\114"then return PaintParts()end if l.KeyCode.Name=="\082"and not Selection.Multiselecting then if Core.Mouse.Target then SetColor(Core.Mouse.Target.Color)end end end)end function l.EnableClickPainting(l)l.Maid.ClickPainting=Selection.FocusChanged:Connect(function(l)local w,Z=Core.Targeting:UpdateTarget()if Selection.IsSelected(Z)then PaintParts()end end)end

local PaintTool = {
	Name = 'Paint Tool';
	Color = BrickColor.new 'Really red';

	-- Default options
	BrickColor = nil;
}

PaintTool.ManualText = [[<font face="GothamBlack" size="16">Paint Tool  🛠</font>
Lets you paint parts in different colors.<font size="6"><br /></font>

<b>TIP:</b> Press <b><i>R</i></b> while hovering over a part to copy its color.]]

function PaintTool:Equip()
	-- Enables the tool's equipped functionality

	-- Set up maid for cleanup
	self.Maid = Maid.new()

	-- Start up our interface
	ShowUI();
	self:BindShortcutKeys()
	self:EnableClickPainting()

end;

function PaintTool:Unequip()
	-- Disables the tool's equipped functionality

	-- Hide UI
	HideUI()

	-- Clean up resources
	self.Maid = self.Maid:Destroy()

end;

function ShowUI()
	-- Creates and reveals the UI

	-- Reveal UI if already created
	if PaintTool.UI then

		-- Reveal the UI
		PaintTool.UI.Visible = true;

		-- Update the UI every 0.1 seconds
		UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

		-- Skip UI creation
		return;

	end;

	-- Create the UI
	PaintTool.UI = Core.Tool.Interfaces.BTPaintToolGUI:Clone();
	PaintTool.UI.Parent = Core.UI;
	PaintTool.UI.Visible = true;

	-- Track palette buttons
	PaletteButtons = {};

	-- Enable the palette
	for _, Column in pairs(PaintTool.UI.Palette:GetChildren()) do
		for _, Button in pairs(Column:GetChildren()) do
			if Button.ClassName == 'TextButton' then

				-- Recolor the selection when the button is clicked
				Button.MouseButton1Click:Connect(function ()
					SetColor(BrickColor.new(Button.Name).Color);
				end);

				-- Register the button
				PaletteButtons[Button.Name] = Button;

			end;
		end;
	end;

	-- Paint selection when current color indicator is clicked
	PaintTool.UI.Controls.LastColorButton.MouseButton1Click:Connect(PaintParts);

	-- Enable color picker button
	local ColorPickerHandle = nil
	PaintTool.UI.Controls.ColorPickerButton.MouseButton1Click:Connect(function ()
		local CommonColor = Support.IdentifyCommonProperty(Selection.Parts, 'Color')
		local ColorPickerElement = Roact.createElement(ColorPicker, {
			InitialColor = CommonColor or Color3.fromRGB(255, 255, 255);
			SetPreviewColor = PreviewColor;
			OnConfirm = function (Color)
				SetColor(Color)
				ColorPickerHandle = Roact.unmount(ColorPickerHandle)
			end;
			OnCancel = function ()
				ColorPickerHandle = Roact.unmount(ColorPickerHandle)
			end;
		})
		ColorPickerHandle = ColorPickerHandle and
			Roact.update(ColorPickerHandle, ColorPickerElement) or
			Roact.mount(ColorPickerElement, Core.UI, 'ColorPicker')
	end)

	-- Hook up manual triggering
	local SignatureButton = PaintTool.UI:WaitForChild('Title'):WaitForChild('Signature')
	ListenForManualWindowTrigger(PaintTool.ManualText, PaintTool.Color.Color, SignatureButton)

	-- Update the UI every 0.1 seconds
	UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

end;

function HideUI()
	-- Hides the tool UI

	-- Make sure there's a UI
	if not PaintTool.UI then
		return;
	end;

	-- Hide the UI
	PaintTool.UI.Visible = false;

	-- Stop updating the UI
	UIUpdater:Stop();

end;

function UpdateUI()
	-- Updates information on the UI

	-- Make sure the UI's on
	if not PaintTool.UI then
		return;
	end;

	-----------------------------------------
	-- Update the color information indicator
	-----------------------------------------

	-- Clear old color indicators
	for Color, Button in pairs(PaletteButtons) do
		Button.Text = '';
	end;

	-- Indicate the variety of colors in the selection
	for _, Part in pairs(Selection.Parts) do
		if PaletteButtons[Part.BrickColor.Name] and Part.Color == Part.BrickColor.Color then
			PaletteButtons[Part.BrickColor.Name].Text = '+';
		end;
	end;

	-- Update the color picker button's background
	local CommonColor = Support.IdentifyCommonProperty(Selection.Parts, 'Color');
	PaintTool.UI.Controls.ColorPickerButton.ImageColor3 = CommonColor or PaintTool.BrickColor or Color3.new(1, 0, 0);

end;

function SetColor(Color)
	-- Changes the color option to `Color`

	-- Set the color option
	PaintTool.BrickColor = Color;

	-- Use BrickColor name if color matches one
	local EquivalentBrickColor = BrickColor.new(Color);
	local RGBText = ('(%d, %d, %d)'):format(Color.r * 255, Color.g * 255, Color.b * 255);
	local ColorText = (EquivalentBrickColor.Color == Color) and EquivalentBrickColor.Name or RGBText;

	-- Shortcuts to color indicators
	local ColorLabel = PaintTool.UI.Controls.LastColorButton.ColorName;
	local ColorSquare = ColorLabel.ColorSquare;

	-- Update the indicators
	ColorLabel.Visible = true;
	ColorLabel.Text = ColorText;
	ColorSquare.BackgroundColor3 = Color;
	ColorSquare.Position = UDim2.new(1, -ColorLabel.TextBounds.X - 18, 0.2, 1);

	-- Paint currently selected parts
	PaintParts();

end;

function PaintParts()
	-- Recolors the selection with the selected color

	-- Make sure painting is possible
	if (not PaintTool.BrickColor) or (#Selection.Parts == 0) then
		return
	end

	-- Create history record
	local Record = PaintHistoryRecord.new()
	Record.TargetColor = PaintTool.BrickColor

	-- Perform action
	Record:Apply(true)

	-- Register history record
	Core.History.Add(Record)

end

function PreviewColor(Color)
	-- Previews the given color on the selection

	-- Reset colors to initial state if previewing is over
	if not Color and InitialState then
		for Part, State in pairs(InitialState) do

			-- Reset part color
			Part.Color = State.Color;

			-- Update union coloring options
			if Part.ClassName == 'UnionOperation' then
				Part.UsePartColor = State.UsePartColor;
			end;
		end;

		-- Clear initial state
		InitialState = nil;

		-- Skip rest of function
		return;

	-- Ensure valid color is given
	elseif not Color then
		return;

	-- Save initial state if first time previewing
	elseif not InitialState then
		InitialState = {};
		for _, Part in pairs(Selection.Parts) do
			InitialState[Part] = { Color = Part.Color, UsePartColor = (Part.ClassName == 'UnionOperation') and Part.UsePartColor or nil };
		end;
	end;

	-- Apply preview color
	for _, Part in pairs(Selection.Parts) do
		Part.Color = Color;

		-- Enable union coloring
		if Part.ClassName == 'UnionOperation' then
			Part.UsePartColor = true;
		end;
	end;

end;

function PaintTool:BindShortcutKeys()
	-- Enables useful shortcut keys for this tool

	-- Track user input while this tool is equipped
	self.Maid.Hotkeys = Support.AddUserInputListener('Began', 'Keyboard', false, function (Input)

		-- Paint selection if Enter is pressed
		if (Input.KeyCode.Name == 'Return') or (Input.KeyCode.Name == 'KeypadEnter') then
			return PaintParts()
		end

		-- Check if the R key was pressed, and it wasn't the selection clearing hotkey
		if (Input.KeyCode.Name == 'R') and (not Selection.Multiselecting) then

			-- Set the current color to that of the current mouse target (if any)
			if Core.Mouse.Target then
				SetColor(Core.Mouse.Target.Color);
			end;

		end;

	end)

end;

function PaintTool:EnableClickPainting()
	-- Allows the player to paint parts by clicking on them

	-- Watch out for clicks on selected parts
	self.Maid.ClickPainting = Selection.FocusChanged:Connect(function (Focus)
		local Target, ScopeTarget = Core.Targeting:UpdateTarget()
		if Selection.IsSelected(ScopeTarget) then

			-- Paint the selected parts
			PaintParts();

		end;
	end);

end;
