The-Powder-Toy/The-Powder-Toy

Guideline Tool

Rebmiami opened this issue · 0 comments

While the Grid tool (G or shift+G) is useful for aligning things on a small scale, there is no such tool for larger-scale alignment. Thus, I propose a "guideline" tool that draws a specified number of equally-spaced lines on the screen for this purpose.

I've created this Lua script that implements this feature roughly as I envisioned it:

-- Use Alt+G to open the Guideline Tool
-- Use Shift+Alt+G to disable the Guideline Tool

local guidelinesActive = false
local guidelinesH 
local guidelinesV
local ignoreEdge = false

event.register(event.keypress, function(key, scan, r, shift, ctrl, alt)
	if key == 103 and alt then
		if shift then
			guidelinesActive = false
		else
			guidelinesActive = true
			guidelinesH = nil
			guidelinesV = nil

			local guidelineWindow = Window:new(-1, -1, 150, 80)

			local hLineLabel = Label:new(4, 4, 40, 16, "H lines:")
			guidelineWindow:addComponent(hLineLabel)
			
			local vLineLabel = Label:new(4, 24, 40, 16, "V lines:")
			guidelineWindow:addComponent(vLineLabel)
			
			local hLineTextbox = Textbox:new(50, 4, 80, 16)
			hLineTextbox:onTextChanged(
				function(sender)
					guidelinesH = math.min(math.max(math.floor(tonumber(sender:text())), 1), sim.YRES)
				end)
			guidelineWindow:addComponent(hLineTextbox)
			
			local vLineTextbox = Textbox:new(50, 24, 80, 16)
			vLineTextbox:onTextChanged(
				function(sender)
					guidelinesV = math.min(math.max(math.floor(tonumber(sender:text())), 1), sim.XRES)
				end)
			guidelineWindow:addComponent(vLineTextbox)
			
			local edgeCheckbox = Checkbox:new(4, 42, 50, 16, "Ignore 4 pixels at edges");
			edgeCheckbox:checked(ignoreEdge)
			edgeCheckbox:action(
				function(sender, checked)
					ignoreEdge = checked
				end)
			guidelineWindow:addComponent(edgeCheckbox)

			local closeButton = Button:new(0, 64, 150, 16, "Close")
			closeButton:action( function()
				interface.closeWindow(guidelineWindow)
			end)
			guidelineWindow:addComponent(closeButton)

			interface.showWindow(guidelineWindow)
			guidelineWindow:onTryExit(function()
				interface.closeWindow(guidelineWindow)
			end)
		end
		return false
	end
end)

event.register(event.tick, function()
	if guidelinesActive then
		local yres = sim.YRES
		local xres = sim.XRES
		local offset = 0

		if ignoreEdge then
			yres = sim.YRES - 8
			xres = sim.XRES - 8
			offset = 4
		end

		if guidelinesH then
			for i = 1, guidelinesH do
				local y = i / (guidelinesH + 1) * yres + offset
				graphics.drawLine(offset, y, xres + offset, y, 255, 255, 255, 31)
			end
		end
		if guidelinesV then
			for i = 1, guidelinesV do
				local x = i / (guidelinesV + 1) * xres + offset
				graphics.drawLine(x, offset, x, yres + offset, 255, 255, 255, 31)
			end
		end
	end
end)

The only major problem with this implementation is that it doesn't interact properly with the zoom window and I'd rather not make a convoluted workaround to get it to.

I used this implementation to create a display in one of my saves with several rectangles arranged like this:
image
I've left the gridlines shown in this image. It may also be useful for artists - see the rule of thirds - and there are likely other potential uses I haven't been able to think of yet.