Very stuck on Drawing System

For the past few months I been working on an advanced drawing system (inside of a UI) and I am near finishing, and I just have the undo & redo system, converting the drawn frames to scale, and few bug fixes.

I have been having some issues with these and I really need help I will provide all the code below into sections.

Let me define somethings and explain how my system works.

CircleLine = A circle imagelabel that is used for drawing
DrawLine = the lines to fill in the gaps in between the circles

Old prototype example without the lines in between:

https://gyazo.com/729d2248682710049178d3c660d83f46

Converting to scale issue

I am having trouble converting my currently drawn pieces from offset to scale, they are frames.
Currently, it isn’t converting anything because I had to undo, if you could please explain how I can do this it would be great.
Whenever I do it nothing will work, the “CircleLine” which is an circle works, but not the gap filling lines.

local selectedColor = bg:GetAttribute("Color")
		local DrawCircle = CircleBrush:Clone()
		DrawCircle.ZIndex = layer
		print(OffsetToScale({20,20}))
		DrawCircle.Size = UDim2.new(0,20, 0, 20)
		DrawCircle.Parent = Canvas
		local X = mouse.X - Canvas.AbsolutePosition.X
		local Y = mouse.Y - Canvas.AbsolutePosition.Y
		--DrawCircle.Position = UDim2.fromOffset(mouse.X, mouse.Y)
		DrawCircle.Position = UDim2.fromOffset(X, Y)
		--DrawCircle.Position = UDim2.new(0, BrushCricleDecal.AbsolutePosition.X, 0, BrushCricleDecal.AbsolutePosition.Y)
		
		DrawCircle.Transparency = tonumber(DrawingTransparencyTxtBox.Text) or 0
		DrawCircle.ZIndex = layer
		if isDrawing then
			DrawCircle.Name = "DrawCircle"..numberthing
			print(numberthing)
			print("Renamed")
			DrawCircle.BackgroundColor3 = selectedColor
			numberthing += 1
			if oldDot then
				if tonumber(DrawingTransparencyTxtBox.Text) > 0 then
					local startX, startY = oldDot.Position.X.Offset, oldDot.Position.Y.Offset
					local endX, endY = DrawCircle.Position.X.Offset, DrawCircle.Position.Y.Offset
					local line = circleLineBrush:Clone()
					line.Name = "line"..numberthing
					line.AnchorPoint = Vector2.new(0.5,0.5)
					line.Size = UDim2.new(0,(oldDot.AbsolutePosition - DrawCircle.AbsolutePosition).Magnitude,0, 20)
					line.Position = UDim2.new(0, (startX + endX) / 2, 0, (startY + endY) / 2)
					line.Rotation = math.atan2(endY - startY, endX - startX) * (180 / math.pi)
					line.BackgroundColor3 = selectedColor
					line.BackgroundTransparency = 0
					line.ZIndex = layer
					line.Parent = Canvas
					local whiteOldDot = oldDot:Clone()
					whiteOldDot.Transparency = 0
					whiteOldDot.BackgroundColor3 = selectedColor
					whiteOldDot.ZIndex = layer
					whiteOldDot.Parent = Canvas
					local newOldDot = whiteOldDot:Clone()
					newOldDot.Transparency = tonumber(DrawingTransparencyTxtBox.Text)
					newOldDot.BackGroundColor3 = selectedColor
					newOldDot.ZIndex = layer
					newOldDot.Parent = Canvas
				elseif tonumber(DrawingTransparencyTxtBox.Text) == 0 then
					local startX, startY = oldDot.Position.X.Offset, oldDot.Position.Y.Offset
					local endX, endY = DrawCircle.Position.X.Offset, DrawCircle.Position.Y.Offset
					local line = circleLineBrush:Clone()
					line.Name = "line"..numberthing
					line.AnchorPoint = Vector2.new(0.5,0.5)
					line.Size = UDim2.new(0,(oldDot.AbsolutePosition - DrawCircle.AbsolutePosition).Magnitude,0,20)
					line.Position = UDim2.new(0, (startX + endX) / 2, 0, (startY + endY) / 2)
					line.Rotation = math.atan2(endY - startY, endX - startX) * (180 / math.pi)
					line.BackgroundColor3 = selectedColor
					line.BackgroundTransparency = 0
					line.ZIndex = layer
					line.Parent = Canvas
				end
			end
			oldDot = DrawCircle
			

There are checks outside of this that are not needed, let me know if you need more information.

Undo & Redo

My undo & redo system issue:

I kind of have it working…? (Not really)

I do have the base of the system but not working properly.
I don’t think I need to explain what the undo and redo is suppose to do, it it clear, undo and redo a drawing fragment.

Here is what happens with my system:

https://gyazo.com/3ebc1f9933302c71a37df575d8b9b397

Issues:

  1. It completely deletes everything and doesn’t go back to the last cache(as I refer to in my code) / action
  2. There is a tiny bit left even when it deletes the wrong thing.

Here is my code:

How I cache the drawings:

function cacheDrawing(ui)
	if #CacheTable >= 20 then
		table.remove(CacheTable, 1)
		oldCacheNumber += 1
		
		for i, v in pairs(ui:GetChildren()) do
			local clone = v:Clone()
			tempCacheTble = {}
			table.insert(tempCacheTble, clone)
		end
		table.insert(CacheTable, tempCacheTble)
		totalAmountOfCache += 1
		print(#CacheTable)
	else
		totalAmountOfCache += 1
		for i, v in pairs(ui:GetChildren()) do
			local clone = v:Clone()
			tempCacheTble = {}
			table.insert(tempCacheTble, clone)
		end
		table.insert(CacheTable, tempCacheTble)
		print(#CacheTable)
	end
end

How I undo:

function UndoAction(index)
	local getframe = CacheTable[#CacheTable]
	table.insert(redoTable, Canvas:GetChildren())
	local orgChild = Canvas:GetChildren()	
	
	for z, x in pairs(orgChild) do
		if not x:IsA("UIStroke") then
			print(typeof(x))
			x:Destroy()
		end
		
	end
	
	for i, v in pairs(getframe) do
		if not v:IsA("UIStroke") then
			print(typeof(v))
			v.Parent = Canvas
		end
	end
	
end

Redo isn’t finished, I wanted undo working first because then I can just reverse it in theory.

The cachetable is called whenever the user was holding down mouse button and lets go, or they leave the drawing canvas.

1 Like

You need to do bresenham line algorithm between every 2 points. Make sure to check they aren’t degenerate.
bresenhamlinealgoderivation.pdf (725.6 KB)

1 Like

Is this for drawing lines? I wanted them rounded, when I had them straight using triangulation there were tiny white spaces

yea you were doing it wrong then. when you draw notice how you create points? the reason why there is gaps is cause sometimes you are moving your mouse so fast your computer has no time to process it. it is why you gotta use a line algorithm like jacks one or DDA.

That example I showed was older to show the needs of the lines this is the newest, but I see what you mean
https://gyazo.com/4aae860f8f6922e8fb3b487f0ca3b778

Correct me if I am wrong but I am pretty sure you meant that as in filling in the blanks on the drawing system older prototype example

Thanks for the useful information though

1 Like