------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


function GUIParticles.New(gui, particle)
	--- Check if gui argument is a GUI instance or UDIM2 position
	local isGeneratedGui = not pcall(function()  local x = gui.Parent  end)
	
	--- Generate GUI holder if it is a UDIM2 position
	if isGeneratedGui then
		local fakeGuiHolder = Instance.new("ScreenGui")
		fakeGuiHolder.Parent = _L.Player.Get("PlayerGui")
		local fakeGui = Instance.new("Frame")
		fakeGui.BackgroundTransparency = 1
		fakeGui.Size = UDim2.new(0, 1, 0, 1)
		fakeGui.Position = gui
		fakeGui.AnchorPoint = Vector2.new(0.5, 0.5)
		fakeGui.Parent = fakeGuiHolder
		gui = fakeGui
	end
	
	--- Setup particle folder if it doesn't already exist
	if particleFolder == nil then
		particleFolder = Instance.new("Folder")
		particleFolder.Name = "GUI Particles"
		particleFolder.Parent = game.Workspace.CurrentCamera
	end
	
	--- Create particle's part holder
	local particlePart = Instance.new("Part")
	particlePart.Transparency = 1
	particlePart.Material = Enum.Material.SmoothPlastic
	particlePart.CanCollide = false
	particlePart.Anchored = true
	particlePart.Size = Vector3.new(0, 0, 0)
	particlePart.Name = particle.Name
	particlePart.Parent = particleFolder
	
	--- Create attachment for particles (avoid spread)
	local attachment = Instance.new("Attachment")
	attachment.Parent = particlePart
	
	--- Add in particles
	particle = particle:Clone()
	particle.ZOffset = particle.ZOffset + displayZ * 0.645 --- Hack of the century 
	particle.Parent = attachment
	
	--- Math
	local function Update()
		local camera = game.Workspace.CurrentCamera
		local cameraSize = camera.ViewportSize
		local sizeX, sizeY = gui.AbsoluteSize.X, gui.AbsoluteSize.Y
		local posX, posY = gui.AbsolutePosition.X + (sizeX / 2), gui.AbsolutePosition.Y + (sizeY / 2)
		--[[local sizeInStudsTop = camera:ScreenPointToRay(gui.AbsolutePosition.X, gui.AbsolutePosition.Y, displayZ).Origin
		local sizeInStudsBottom = camera:ScreenPointToRay(gui.AbsolutePosition.X+sizeX, gui.AbsolutePosition.Y+sizeY, displayZ).Origin
		particlePart.Size = Vector3.new(math.abs(sizeInStudsBottom.X-sizeInStudsTop.X), math.abs(sizeInStudsBottom.Y-sizeInStudsTop.Y), 0.05) ]]
		local positionInStuds = camera:ScreenPointToRay(posX, posY, displayZ).Origin
		particlePart.CFrame = CFrame.new(positionInStuds) * CFrame.Angles(camera.CFrame:toEulerAnglesXYZ())
	end
	
	--- Main
	coroutine.wrap(function()
		--- Update
		while (gui and particleFolder and particle and particlePart and particle.Parent) do
			Update()
			_L.Services.RunService.RenderStepped:wait()
		end
		
		--- Destroy
		if gui.Parent and isGeneratedGui then  gui.Parent:Destroy()  end
		if particle then  particle:Destroy()  end
		if particlePart then  particlePart:Destroy()  end
	end)()
	
	--
	return particle
end