【Script】Tool Ring

I made a little script that was mainly intended for touch-screen/tablet.
It creates a button on the screen that when left mouse button down shows a ring of tools that you can switch to by hovering your cursor over and releasing the mouse button.
I made it so you can add your own selection of tools and customise button sizes and positions.

-----------------------------------------------------------------
-- Tool Ring for Aseprite
-- Made by apsyll
-- Version : 1.0.0
-- Date: 2024-06-15
-- https://community.aseprite.org/t/tool-ring-script/22314
-----------------------------------------------------------------


--Set the position where the main dialog should be drawn
local MAIN_DLG_POSITION = Point(850,60)
-- Set the size of the buttons for each tool
local BUTTON_SIZE = 30
--Set the extra space for the dialog sorrounding the buttons
local BORDER_SIZE = 6
--Set the distance the ring should be drawn around the main dialog
local RING_DISTANCE = 40
-- Set if right click closes the main dialog, if true the main dialog won't show the title bar as well making the icon more space efficient
-- but harder to move around
local RIGHT_MOUSE_CLOSE = true

-- set the tool list of all tools that should be includet to the ring
local tool_list ={
    "pencil",
    "eraser",
    "eyedropper",
    "paint_bucket",
    "move",
    "hand",
    "rectangular_marquee",
    "lasso",
    "magic_wand"
}

-- functional code starts here all set up can be done above --

local main_dlg = Dialog{"Main Canvas",
    notitlebar = RIGHT_MOUSE_CLOSE}
local sub_list={}
local tool_amount = 0
local icon_size = 16
local dialog_title_buffer = 0

function showSubs(x, y)
  local angle = 0
  local distance = RING_DISTANCE
  for i,dlg in ipairs(sub_list) do
    local rad = math.rad(angle)
    local new_x = x + distance * math.cos(rad)
    local new_y = y + distance * math.sin(rad)
    dlg:show{ wait=false,
        bounds=Rectangle(new_x, new_y,BUTTON_SIZE + BORDER_SIZE,BUTTON_SIZE + BORDER_SIZE),
        notitlebar=true,
        }
    angle = angle + (360 / tool_amount)
  end
end

--Create the sub dialog windows as well linking the tools to each uniquely
function createSubsCanvas()
    tool_amount = #tool_list
    for i,tool in ipairs(tool_list) do
        local dlg = Dialog{"SUB"..i,
          notitlebar=true,
        }     
        table.insert( sub_list, dlg)
        local center = Point(BUTTON_SIZE/2,BUTTON_SIZE/2)
        dlg:canvas{ id="sub_canvas"..i,
                    width=BUTTON_SIZE,
                    height=BUTTON_SIZE,
                    onpaint = function(ev)
                        local ctx = ev.context
                        ctx:drawThemeRect("sunken_normal", Rectangle(0, 0, BUTTON_SIZE, BUTTON_SIZE))
                        local size = Rectangle(0, 0, icon_size, icon_size)
                        ctx:drawThemeImage("tool_"..tool, center.x - size.width / 2,
                                 center.y - size.height / 2)
                    end,
                    onmouseup=function()
                        app.activeTool = tool
                        updateMainDLG()
                        closeSubs()
                    end 
        }
    end
end

function closeSubs()
    for i,dlg in ipairs(sub_list) do
        dlg:close()
    end
end

--redraw the main with the new active tool
function updateMainDLG()
    local center = Point(BUTTON_SIZE/2,BUTTON_SIZE/2)
    main_dlg:modify{ id="main_canvas",
    onpaint = function(ev)
        local ctx = ev.context
        ctx:drawThemeRect("button_normal", Rectangle(0, 0, BUTTON_SIZE, BUTTON_SIZE))
        local size = Rectangle(0, 0, icon_size, icon_size)
        ctx:drawThemeImage("tool_"..app.activeTool.id, center.x - size.width / 2,
            center.y - size.height / 2)

    end 
    }
    main_dlg:repaint()
end

--set up the main dialog
function setup()
    if not(RIGHT_MOUSE_CLOSE) then
        dialog_title_buffer = 10
    end
    main_dlg:modify{onclose=function()
        closeSubs()
        ColorShadingWindowBounds = dlg.bounds
      end}
    local center = Point(BUTTON_SIZE/2,BUTTON_SIZE/2)
    main_dlg:canvas{
                id="main_canvas",
                width=BUTTON_SIZE,
                height=BUTTON_SIZE,
                onpaint = function(ev)
                    local ctx = ev.context
                    ctx:drawThemeRect("button_normal", Rectangle(0, 0, BUTTON_SIZE, BUTTON_SIZE))
                    local size = Rectangle(0, 0, icon_size, icon_size)
                    ctx:drawThemeImage("tool_"..app.activeTool.id, center.x - size.width / 2,
                    center.y - size.height / 2)
                end,
                onmousedown=function()
                    showSubs(main_dlg.bounds.x, main_dlg.bounds.y + dialog_title_buffer)
                end,
                onmouseup=function(ev)
                    updateMainDLG()
                    closeSubs()
                    if ev.button == MouseButton.RIGHT and RIGHT_MOUSE_CLOSE then
                        main_dlg:close()
                    end
                end  
    }
    createSubsCanvas()
    local size = Rectangle(MAIN_DLG_POSITION.x,MAIN_DLG_POSITION.y,BUTTON_SIZE + BORDER_SIZE*3, BUTTON_SIZE + BORDER_SIZE*3)
    if RIGHT_MOUSE_CLOSE then
        size =Rectangle(MAIN_DLG_POSITION.x,MAIN_DLG_POSITION.y,BUTTON_SIZE + BORDER_SIZE, BUTTON_SIZE + BORDER_SIZE)
    end
    main_dlg:show{ wait=false,
        bounds= size,
    }
end

do
    setup()
end
3 Likes