local imgui = require 'mimgui'
local Vector3D = require 'vector3d'
local snowt = {}
local gravity = Vector3D(0,0,0)
imgui.OnInitialize(function()
imgui.GetIO().IniFilename = nil
sw, sh = getScreenResolution()
wndSize = imgui.ImVec2(sw / 4, sh / 2)
wndPos = imgui.ImVec2(sw / 2 - wndSize.x / 2, sh / 2 - wndSize.y / 2)
Snowflake.CreateSnowFlakes(snowt, 300, 1, 15, 0, 0, sw, sh, Vector3D(0, 0.005, 0), imgui.ColorConvertFloat4ToU32(imgui.ImVec4(1,1,1,0.25)))
end)
imgui.OnFrame(function() return true end, function(self)
imgui.SetNextWindowPos(wndPos, imgui.Cond.FirstUseEver)
imgui.SetNextWindowSize(wndSize, imgui.Cond.FirstUseEver)
imgui.Begin("tested window with snow background", _, imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoScrollbar)
wndPos = imgui.GetWindowPos()
wndSize = imgui.GetWindowSize()
Snowflake.Update(snowt, Vector3D(getCursorPos(), 0), Vector3D(wndPos.x, wndPos.y, 0))
imgui.Text "Tested text"
imgui.Button "Btn Text"
Snowflake.ChangeWindowPos(snowt, Vector3D(wndPos.x, wndPos.y, 0))
Snowflake.ChangeWindowSize(snowt, Vector3D(wndSize.x, wndSize.y, 0))
imgui.End()
self.HideCursor = false
end)
Snowflake = {}
Snowflake.__index = Snowflake
function Snowflake.new(minSize, maxSize, windowX, windowY, width, height, color)
local self = setmetatable({
minSize = minSize,
maxSize = maxSize,
windowX = windowX,
windowY = windowY,
width = width,
height = height,
color = color,
pos = Vector3D(RandomFloat(windowX, windowX + width), RandomFloat(windowY - 100, windowY - 10), 0),
velocity = Vector3D(0,0,0),
accelaretion = Vector3D(0,0,0),
radius = GetRandomSize(minSize, maxSize)
}, Snowflake)
return self
end
function Snowflake:ApplyForce(force)
self.accelaretion = self.accelaretion + (force * self.radius)
end
function Snowflake:Render()
imgui.GetWindowDrawList():AddCircleFilled(imgui.ImVec2(self.pos.x, self.pos.y), self.radius, self.color)
end
function Snowflake:OffScreen()
return (
(self.pos.y > self.windowY + self.height + self.radius)
or (self.pos.x < self.windowX - self.radius)
or (self.pos.x > self.windowX + self.width + self.radius)
)
end
function Snowflake:Randomize()
self.pos = Vector3D(
RandomFloat(self.windowX, self.windowX + self.width),
RandomFloat(self.windowY - 100, self.windowY - 10), 0
)
self.velocity = Vector3D(0,0,0)
self.accelaretion = Vector3D(0,0,0)
self.radius = GetRandomSize(self.minSize, self.maxSize)
end
function Snowflake:Update_e()
self.velocity = self.velocity + self.accelaretion
limit_vector(self.velocity, self.radius * 0.2)
self.pos = self.pos + self.velocity
self.accelaretion = self.accelaretion * 0
if self:OffScreen() then
self:Randomize()
end
end
function Snowflake:__eq(target)
return (
(self.pos == target.pos)
and (self.velocity == target.velocity)
and (self.accelaretion == target.accelaretion)
and (self.radius == target.radius)
)
end
function Snowflake.CreateSnowFlakes(snow, limit, minSize, maxSize, windowX, windowY, width, height, _gravity, color)
math.randomseed(os.time())
gravity = _gravity
for i = 1, limit do
table.insert(snow, i, Snowflake.new(minSize, maxSize, windowX, windowY, width, height, color))
end
end
function Snowflake.Update(snow, mouse, windowPos)
mouse.x = mouse.x - windowPos.x
mouse.y = mouse.y - windowPos.y
for _, flake in pairs(snow) do
local xOff = flake.pos.x / (flake.windowX + flake.width)
local yOff = flake.pos.y / (flake.windowY + flake.height)
local wx = Map(mouse.x - flake.windowX, 0, flake.width, -0.002, 0.002, true)
local wind = Vector3D(wx + (xOff * 0.002), (yOff * 0.002), 0)
wind = wind * 0.5
flake:ApplyForce(gravity)
flake:ApplyForce(wind)
flake:Update_e()
flake:Render()
end
end
function Snowflake.ChangeWindowPos(snow, window)
for _, flake in pairs(snow) do
flake.pos.x = flake.pos.x + window.x - flake.windowX
flake.pos.y = flake.pos.y + window.y - flake.windowY
flake.windowX = window.x
flake.windowY = window.y
end
end
function Snowflake.ChangeWindowSize(snow, size)
for _, flake in ipairs(snow) do
flake.width = size.x
flake.height = size.y
end
end
function Map(n, start1, stop1, start2, stop2, withinBounds)
local newVal = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2
if not withinBounds then return newVal end
if start2 < stop2 then return Constrain(newVal, start2, stop2)
else return Constrain(newVal, stop2, start2)end
end
function limit_vector(vec, max)
local mSq = vec.x * vec.x + vec.y * vec.y + vec.z * vec.z
if (mSq > max * max) then
local mSq = math.sqrt(mSq)
vec.x = vec.x / mSq
vec.y = vec.y / mSq
vec.z = vec.z / mSq
vec.x = vec.x * max
vec.y = vec.y * max
vec.z = vec.z * max
end
return Vector3D(vec.x, vec.y, vec.z)
end
function min(a, b) return a < b and a or b end
function max(a, b) return a > b and a or b end
function Constrain(n, low, high) return max(min(n, high), low) end
function RandomFloat(a, b) return a + (math.random() * (b - a)) end
function GetRandomSize(min, max) return Constrain(math.pow(RandomFloat(0, 1), 3) * max, min, max) end