i got this working, sort of, heres the module. you can tinker with it. i dont use this anymore
-- services
-- functions
function lerp(a, b, t)
return a + (b - a) * t
end
local AnimationCurve = {}
AnimationCurve.__index = AnimationCurve
function AnimationCurve.new()
local self = setmetatable({
points = {},
size = Vector2.new(450, 450),
visualizerCount = 100,
}, AnimationCurve)
return self
end
function AnimationCurve:_sort()
table.sort(self.points, function(a, b)
return a.time < b.time
end)
end
function AnimationCurve:addKey(time, value, inTangent, outTangent)
local key = { time = time, value = value, inTangent = inTangent, outTangent = outTangent }
table.insert(self.points, key)
--self:recalculateMinMax()
self:_sort()
return key
end
function AnimationCurve:removeKey(time)
for i, point in ipairs(self.points) do
if point.time == time then
table.remove(self.points, i)
break
end
end
self:_sort()
--self:recalculateMinMax()
end
function AnimationCurve:clear()
self.points = {}
end
function AnimationCurve:evaluate(time)
if #self.points == 0 then
error("Animation curve contains no keyframes")
end
self:_sort()
if time <= self.points[1].time then
return self.points[1].value
end
if time >= self.points[#self.points].time then
return self.points[#self.points].value
end
-- find the keyframe point
local left_point, right_point = nil, nil
for i, point in ipairs(self.points) do
if point.time > time then
left_point = self.points[i - 1]
right_point = point
break
end
end
local time_range = right_point.time - left_point.time
if time_range == 0 then
return left_point.value
end
local t = (time - left_point.time) / time_range
-- cubic hermite
local t2 = t * t
local t3 = t2 * t
local a = 2 * t3 - 3 * t2 + 1
local b = -2 * t3 + 3 * t2
local c = t3 - 2 * t2 + t
local d = t3 - t2
return a * left_point.value + b * right_point.value + c * left_point.outTangent + d * right_point.inTangent
end
function AnimationCurve:recalculateMinMax()
self:_sort()
local minX, maxX, minY, maxY = math.huge, -math.huge, math.huge, -math.huge
for i = 1, self.visualizerCount do
local t = (i - 1) / (self.visualizerCount - 1)
local x = lerp(self.points[1].time, self.points[#self.points].time, t)
local y = self:evaluate(x)
minX, maxX = math.min(minX, x), math.max(maxX, x)
minY, maxY = math.min(minY, y), math.max(maxY, y)
end
self.minX, self.maxX, self.minY, self.maxY = minX, maxX, minY, maxY
end
function AnimationCurve:updateVisualizer(parent)
local size = self.size
local anchor = Vector2.new(parent.AbsoluteSize.x - size.x, parent.AbsoluteSize.y - size.y)
if self.frames then
for _,frame in ipairs(self.frames) do
frame:Destroy()
end
end
self.frames = {}
local minX, maxX, minY, maxY = self.minX, self.maxX, self.minY, self.maxY
for i = 1, self.visualizerCount do
local t = (i - 1) / (self.visualizerCount - 1)
local x = lerp(self.points[1].time, self.points[#self.points].time, t)
local y = self:evaluate(x)
local frame = Instance.new("Frame")
frame.Parent = parent
frame.Size = UDim2.new(0, 10, 0, 10)
frame.AnchorPoint = Vector2.new(0.5, 0.5)
frame.Position = UDim2.new(
0,
(x - minX) / (maxX - minX) * size.x + (anchor.x / 2),
0,
size.y - (y - minY) / (maxY - minY) * size.y + (anchor.y / 2)
)
table.insert(self.frames, frame)
end
end
function AnimationCurve:getGuiPosition(time, parent, isEvaluated)
local size = self.size
local anchor = Vector2.new(parent.AbsoluteSize.x - size.x, parent.AbsoluteSize.y - size.y)
self:_sort()
local left_time, right_time = nil, nil
for i, point in ipairs(self.points) do
if point.time > time and i ~= 1 then
left_time = self.points[i - 1].time
right_time = point.time
break
end
end
local t
if time <= self.points[1].time then
t = 0
elseif time >= self.points[#self.points].time then
t = 1
else
local time_range = right_time - left_time
if time_range == 0 then
warn('its 0')
end
t = (time - left_time) / time_range
end
local minX, maxX, minY, maxY = self.minX, self.maxX, self.minY, self.maxY
local x = time
if isEvaluated then
if time <= self.points[1].time then
x = minX
elseif time >= self.points[#self.points].time then
x = maxX
end
end
local y = self:evaluate(time)
return UDim2.new(
0,
(x - minX) / (maxX - minX) * self.size.x + (anchor.x / 2),
0,
self.size.y - (y - minY) / (maxY - minY) * self.size.y + (anchor.y / 2)
)
end
return AnimationCurve