local imgui = require 'mimgui'
local circles_pos = {}
local circles_dir = {}
local circles_radius = {}
---@param ImVec2 pos
---@param int radius
---@param ImVec4 color
function draw_circle(pos, radius, color)
imgui.GetWindowDrawList():AddCircleFilled(pos, radius - 1, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color.x, color.y, color.z, 75)))
end
---@param ImVec2 pos1
---@param ImVec2 pos2
---@param ImU32 color
---@param int radius
function draw_line(pos1, pos2, color, radius)
local draw_list = imgui.GetWindowDrawList()
local distance = math.sqrt(math.pow(pos2.x - pos1.x, 2) + math.pow(pos2.y - pos2.y, 2))
local alpha = (distance <= 20.0 and 255.0 or (1.0 - ((distance - 20.0) / 25.0)) * 255.0)
draw_list:AddLine(pos1, pos2, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color.x, color.y, color.z, alpha)), 1.0)
if distance >= 40 then
draw_list:AddCircleFilled(pos1, radius - 0.96, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color.x, color.y, color.z, alpha * 200)))
draw_list:AddCircleFilled(pos2, radius - 0.96, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color.x, color.y, color.z, alpha * 200)))
elseif distance <= 20 then
draw_list:AddCircleFilled(pos1, radius, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color.x, color.y, color.z, alpha * 200)))
draw_list:AddCircleFilled(pos2, radius, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color.x, color.y, color.z, alpha * 200)))
else
local radius_factor = 1.0 - ((distance - 20.0) / 20.0)
local offset_factor = 1.0 - radius_factor
local offset = (radius - radius * radius_factor) * offset_factor
draw_list:AddCircleFilled(pos1, radius - offset, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color.x, color.y, color.z, alpha * 200)))
draw_list:AddCircleFilled(pos2, radius - offset, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(color.x, color.y, color.z, alpha * 200)))
end
end
function move_circles()
for i = 1, #circles_pos do
local pos = circles_pos[i]
local dir = circles_dir[i]
local radius = circles_radius[i]
pos.x = pos.x + dir.x * 0.4
pos.y = pos.y + dir.y * 0.4
if (pos.x - radius) < 0 or (pos.x + radius) > imgui.GetWindowWidth() then
dir.x = -dir.x
dir.y = math.random(0, 360) % 2 == 0 and -1 or 1
end
if (pos.y - radius) < 0 or (pos.y + radius) > imgui.GetWindowHeight() then
dir.y = -dir.y
dir.x = math.random(0, 360) % 2 == 0 and -1 or 1
end
end
end
---@param ImU32 color
function draw_circles_and_lines(color)
move_circles()
for i = 1, #circles_pos do
draw_circle(circles_pos[i], circles_radius[i], color)
for j = i+1, #circles_pos do
local distance = imgui.GetIO().FontGlobalScale * math.sqrt(
math.pow(circles_pos[j].x - circles_pos[i].x, 2) +
math.pow(circles_pos[j].y - circles_pos[i].y, 2)
)
if distance <= 45 then
draw_line(circles_pos[i], circles_pos[j], color, circles_radius[i])
end
end
end
end
---@param int num_of_circles
function setup_circles(num_of_circles)
local sw, sh = getScreenResolution()
for i = 1, num_of_circles do
table.insert(circles_pos, imgui.ImVec2(math.random(0, sw), math.random(0, sh)))
table.insert(circles_dir, imgui.ImVec2(math.random(0, 1) == 0 and -1 or 1, math.random(0, 1) == 0 and -1 or 1))
table.insert(circles_radius, 3)
end
end
imgui.OnInitialize(function()
imgui.GetIO().IniFilename = nil
setup_circles(400)
end)
imgui.OnFrame(function() return true end, function()
imgui.SetNextWindowSize(imgui.ImVec2(getScreenResolution()), imgui.Cond.FirstUseEver)
if imgui.Begin("tested particle system") then
draw_circles_and_lines(imgui.ImVec4(0.5, 0.6, 0.11, 0.7))
imgui.End()
end
end)