I made my own drawing system for fun and I want to use this for a slightly bigger project since I really enjoy this, but I’m afraid it will cause lag.
This sketch I drew using this demo I threw together uses 2149 frames in total, a lot more than I was hoping it would use.
My only idea/solution is to find a way to detect straight lines, but since drawing systems have existed on Roblox for a while I wanted to ask for help.
“new canvas” module code:
local canvas = Instance.new('ImageButton')
canvas.Size = UDim2.fromOffset(w,h)
canvas.BackgroundColor3=Color3.new(1,1,1)
canvas.AutoButtonColor=false
local down = false
canvas.MouseButton1Down:Connect(function()down = true;end)
canvas.MouseButton1Up:Connect(function()down = false;end)
canvas.BorderSizePixel = 0
local commands = {}
--[[
-->> drawing system
]]
local history,redo = {},{}-- make stacks
local historysnapshotitems = {}
-- stack functions
local function snapshot(items)
history[#history+1] = items
for _,t in pairs(redo) do for i,v in pairs(t) do
v:Destroy()
end end
redo = {}
-- Limit undo size
while #history > 50 do
table.remove(history,1)
end
end
--
local dragging = false
local lp:Vector2 --last position
-- dragging toggle
canvas.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
historysnapshotitems = {}
lp = Vector2.new(input.Position.X,input.Position.Y) - canvas.AbsolutePosition
dragging = true end end)
canvas.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
dragging = false
snapshot(historysnapshotitems)
end end)
-- drawing function
local linethickness,color = 3,Color3.new()
commands.LineThickness = linethickness
commands.Color = color
local gap = math.ceil(linethickness/2)
local function draw(input)
local position = Vector2.new(input.Position.X,input.Position.Y) - canvas.AbsolutePosition
local point = Instance.new("Frame")
historysnapshotitems[#historysnapshotitems+1] = point
point.BackgroundColor3=color;point.BorderSizePixel=0
point.AnchorPoint = Vector2.new(.5,.5)
point.Size = UDim2.fromOffset(
math.sqrt(math.pow(position.X-lp.X, 2) + math.pow(position.Y-lp.Y, 2)) + gap
,
linethickness
)
local c = Vector2.new((position.X + lp.X)/2, (position.Y + lp.Y)/2)
point.Position = UDim2.fromOffset(c.X,c.Y)
point.Rotation = math.deg(math.atan2(position.Y - lp.Y, position.X - lp.X))
--point.Name = ' '
point.Parent = canvas
lp = position
end
canvas.InputChanged:Connect(function(input)
if dragging then
draw(input)
end
end)
--[[
<<--
]]
function commands.Clear()
for i,v in pairs(history:GetChildren()) do
v:Destroy()
end
for i,v in pairs(redo:GetChildren()) do
v:Destroy()
end
history,redo = {},{}
end
function commands.Undo()
if #history > 0 then
for i,v in pairs(history[#history]) do
v.Parent = nil
end
redo[#redo + 1] = history[#history]
history[#history] = nil
end
end
function commands:Redo()
if #redo > 0 then
local redoindex = redo[#redo]
for i,v in pairs(redoindex) do
v.Parent = canvas
end
history[#history + 1] = redoindex
redo[#redo] = nil
end
end
function commands.ChangeLineThickness(n:number)
if not n then return end
linethickness = n
gap = math.ceil(linethickness/2)
commands.LineThickness = n
end
function commands.ChangeColor(c:Color3)
if not c then return end
color = c
commands.Color = c
end
return canvas,commands
end
return newcanvas
How I used this in the demo:
w,h,color=600,600,Color3.new()
local uis = game:GetService('UserInputService')
local nc = require(script["new canvas"])
local holder = script.Parent
local canvas,cmds = nc(w,h);holder.Size = UDim2.fromOffset(w,h);canvas.Parent = holder
cmds.ChangeColor(color)
uis.InputBegan:Connect(function(input)
if not uis:IsKeyDown(Enum.KeyCode.LeftControl) then return end
if input.KeyCode == Enum.KeyCode.Z then
cmds.Undo()
elseif input.KeyCode == Enum.KeyCode.Y then
cmds.Redo()
end
end)