diff --git a/src/Animation/Spring.luau b/src/Animation/Spring.luau index 9d332be..18996e6 100644 --- a/src/Animation/Spring.luau +++ b/src/Animation/Spring.luau @@ -1,28 +1,20 @@ ---[[ - Forked from https://github.com/DervexDev/AdvancedSpring - Thank you @DervexDev! -]] +-- Forked from dervexdev/advancedspring +-- Variables +local Root = script.Parent.Parent +local Packages = script.Parent.Parent.Parent.Parent.Packages --- SERVICES > local RunService = game:GetService("RunService") --- FOLDERS > -local Aegis = script.Parent.Parent -local Runtime = Aegis.Runtime -local Utility = Aegis.Utility - --- DEPENDENCIES > +local Runtime = Root.Runtime local Scheduler = require(Runtime.Scheduler) local Storage = require(Runtime.Storage) -local Debugger = require(Utility.Debugger) -local Utils = require(Utility.Utils) -local Is = require(Utility.Is) +local Debugger = require(Packages.debugger) +local Utils = require(Root.Utility) +local Is = require(Root.Is) +local Types = require(Root.Types) -local Types = require(Aegis.Types) - --- VARIABLES > -local Class = {} :: Types.SpringFunc +local Class = {} local Epsilon = 1e-4 @@ -32,7 +24,7 @@ local cos = math.cos local sin = math.sin local pi = math.pi --- FUNCTIONS > +-- Functions local function IsSpringSettled(currentLinearPosition: { number }, targetLinearPosition: { number }): boolean for index, value in currentLinearPosition do if math.abs(value - targetLinearPosition[index]) > Epsilon then @@ -44,19 +36,19 @@ local function IsSpringSettled(currentLinearPosition: { number }, targetLinearPo return true end -function Class._bind(self: Types.Spring, prop: string, instance: Instance) +function Class._Bind(self: Types.Spring, prop: string, instance: Instance) local Mode = RunService:IsClient() and "Client" or "Server" local Connection: ((number) -> ())? - local TargetLinearPosition = self._type.ToLinear(self._state:Get()) - local CurrentValue = self._state:Get() + local TargetLinearPosition = self._type.ToLinear(self._State:Get()) + local CurrentValue = self._State:Get() if CurrentValue ~= nil then (instance :: any)[prop] = CurrentValue end - self._currentLinearPosition = TargetLinearPosition + self._CurrentLinearPosition = TargetLinearPosition - self._state:Listen(function(newValue) + ;(self._State :: any):Listen(function(newValue) TargetLinearPosition = self._type.ToLinear(newValue) if Connection ~= nil then @@ -65,9 +57,9 @@ function Class._bind(self: Types.Spring, prop: string, instance: Instance) if not Connection then Connection = Scheduler:Add(Mode, function(delta: number) - if self and self._update then - self:_update(TargetLinearPosition, delta); - (instance :: any)[prop] = self._type.FromLinear(self._currentLinearPosition) + if self and (self :: any)._Update then + (self :: any):_Update(TargetLinearPosition, delta); + (instance :: any)[prop] = self._type.FromLinear(self._CurrentLinearPosition) else if Connection then Scheduler:Remove(Mode, Connection) @@ -75,13 +67,13 @@ function Class._bind(self: Types.Spring, prop: string, instance: Instance) end end - if IsSpringSettled(self._currentLinearPosition, TargetLinearPosition) == true and Connection then + if IsSpringSettled(self._CurrentLinearPosition, TargetLinearPosition) == true and Connection then Scheduler:Remove(Mode, Connection) Connection = nil; - (instance :: any)[prop] = self._state:Get() + (instance :: any)[prop] = (self :: any)._State:Get() - for index = 1, #self._velocity do - self._velocity[index] = 0 + for index = 1, #self._Velocity do + self._Velocity[index] = 0 end end end) @@ -89,7 +81,7 @@ function Class._bind(self: Types.Spring, prop: string, instance: Instance) end) end -function Class._update(self: Types.Spring, targetLinearPosition: { number }, delta: number) +function Class._Update(self: Types.Spring, targetLinearPosition: { number }, delta: number) for index = 1, #targetLinearPosition do -- DO NOT CHANGE ANYTHING IN THE CALCULATION UNLESS YOU KNOW WHAT YOU ARE DOING --[[ @@ -107,25 +99,25 @@ function Class._update(self: Types.Spring, targetLinearPosition: { number }, del e2 = exp2 ]] - local d = self._damping - local f = self._frequency * pi * 2 + local d = self._Damping + local f = self._Frequency * pi * 2 local g = targetLinearPosition[index] - local p = self._currentLinearPosition[index] - local v = self._velocity[index] + local p = self._CurrentLinearPosition[index] + local v = self._Velocity[index] local offset = p - g local decay = exp(-delta * d * f) if d == 1 then - self._currentLinearPosition[index] = (v * delta + offset * (f * delta + 1)) * decay + g - self._velocity[index] = (v - (offset * f + v) * (f * delta)) * decay + self._CurrentLinearPosition[index] = (v * delta + offset * (f * delta + 1)) * decay + g + self._Velocity[index] = (v - (offset * f + v) * (f * delta)) * decay elseif d < 1 then local c = sqrt(1 - d * d) local i = cos(delta * f * c) local j = sin(delta * f * c) - self._currentLinearPosition[index] = (offset * i + (v + offset * (d * f)) * j / (f * c)) * decay + g - self._velocity[index] = (v * (i * c) - (v * d + offset * f) * j) * (decay / c) + self._CurrentLinearPosition[index] = (offset * i + (v + offset * (d * f)) * j / (f * c)) * decay + g + self._Velocity[index] = (v * (i * c) - (v * d + offset * f) * j) * (decay / c) else local c = sqrt(d * d - 1) local r1 = -f * (d - c) @@ -135,8 +127,8 @@ function Class._update(self: Types.Spring, targetLinearPosition: { number }, del local e1 = co1 * exp(r1 * delta) local e2 = co2 * exp(r2 * delta) - self._currentLinearPosition[index] = e1 + e2 + g - self._velocity[index] = r1 * e1 + r2 * e2 + self._CurrentLinearPosition[index] = e1 + e2 + g + self._Velocity[index] = r1 * e1 + r2 * e2 end end end @@ -157,7 +149,7 @@ end ]] function Class.Get(self: Types.Spring): Types.Animatable -- Return the unpacked format for improved clarity - return self._type.FromLinear(self._currentLinearPosition) + return self._type.FromLinear(self._CurrentLinearPosition) end --[[ @@ -174,38 +166,23 @@ end ``` ]] function Class.Destroy(self: Types.Spring): nil - self._state:Destroy() + (self :: any)._State:Destroy() Utils.CleanMetatable(self :: any) return nil end ---[[ - ## `Aegis.spring` - A constructor to create new spring objects. - #### Parameters - - **springInfo:** Table of information to create a new spring object. - #### Returns - - [`spring`](https://lumin-dev.github.io/Aegis/api/state) | [`Tutorial`](https://lumin-dev.github.io/Aegis/guide/managing-springs) - #### Example - ```luau - local MyState = Aegis.state(Vector3.new(0, 5, 0)) - local CustomSpring = Aegis.spring({ - State = MyState, - Damping = 0.3, - Frequency = 1.5, - }) - - Aegis.new("Part", { - Size = Vector3.new(4, 4, 4), - Anchored = true, - Parent = workspace, - Position = CustomSpring, - }) - ``` -]] -return function(springInfo: Types.SpringInfo): Types.Spring +--[=[ + Creates a new spring. + + [Learn More](https://luminlabsdev.github.io/ui-framework/api/#spring) +]=] +return function(springInfo: { + State: Types.State, + Damping: number?, + Frequency: number?, +}): Types.Spring -- Checks - if Is.AegisConstructor(springInfo.State :: any) == false then + if Is.Constructor(springInfo.State :: any) == false then Debugger.Error("TypeMismatch", "Aegis.State", typeof(springInfo.State)) end @@ -219,14 +196,14 @@ return function(springInfo: Types.SpringInfo): Types.Spring self.ConstructorClass = "spring" - self._damping = springInfo.Damping or 1 - self._frequency = springInfo.Frequency or 1 - self._state = springInfo.State + self._Damping = springInfo.Damping or 1 + self._Frequency = springInfo.Frequency or 1 + self._State = springInfo.State self._type = Type - self._currentLinearPosition = self._type.ToLinear(springInfo.State:Get()) + self._CurrentLinearPosition = self._type.ToLinear(springInfo.State:Get()) - self._velocity = table.create(#self._currentLinearPosition, 0) + self._Velocity = table.create(#self._CurrentLinearPosition, 0) return self end diff --git a/src/Instances/New.luau b/src/Instances/New.luau index d39256f..ffa45cd 100644 --- a/src/Instances/New.luau +++ b/src/Instances/New.luau @@ -1,10 +1,9 @@ -- Variables local Root = script.Parent.Parent -local Packages = script.Parent.Parent.Parent.Parent.Packages - -local Debugger = require(Packages.debugger) local Utility = require(Root.Utility) local Types = require(Root.Types) + +local Debugger = require(Root.Parent.debugger) local Default = require(Root.Instances.Default) -- Module diff --git a/src/Instances/Update.luau b/src/Instances/Update.luau index c3bf259..e6c663b 100644 --- a/src/Instances/Update.luau +++ b/src/Instances/Update.luau @@ -1,6 +1,7 @@ -- Variables -local Utility = require(script.Parent.Parent.Utility) -local Types = require(script.Parent.Parent.Types) +local Root = script.Parent.Parent +local Utility = require(Root.Utility) +local Types = require(Root.Types) -- Module diff --git a/src/Is.luau b/src/Is.luau index 905ea69..4c8ac36 100644 --- a/src/Is.luau +++ b/src/Is.luau @@ -2,7 +2,7 @@ local Types = require(script.Parent.Types) -- Functions -local function Constructor(item: Types.Constructor) +local function Constructor(item: Types.Constructor) return if type(item) == "table" and item._Type and item._Bind and item.Get then true else false end diff --git a/src/Keys/Change.luau b/src/Keys/Change.luau index 7574d27..74d30cf 100644 --- a/src/Keys/Change.luau +++ b/src/Keys/Change.luau @@ -1,13 +1,12 @@ -- Variables -local Packages = script.Parent.Parent.Parent.Parent.Packages -local Utility = script.Parent.Utility -local Keys = require(Utility.Keys) -local Debugger = require(Packages.debugger) +local Root = script.Parent.Parent +local Keys = require(script.Parent.List) +local Debugger = require(Root.Parent.debugger) -- Module --[=[ - Connects a callback to a certain property change event. + Connects a callback to a certain property change event, and supplies the changed prop as an arg. [Learn More](https://luminlabsdev.github.io/ui-framework/api/keys/#change) ]=] @@ -15,12 +14,14 @@ return function(prop: string) if not Keys["Change"] then Keys["Change"] = { Name = "Change", - Apply = function(instance: Instance, callback: (...any) -> ()) + Apply = function(instance: Instance, callback: (changed: any) -> ()) local Success, Event = pcall(instance.GetPropertyChangedSignal, instance :: any, prop :: any) if not Success or type(callback) ~= "function" then Debugger.Fatal("") end - Event:Connect(callback) + Event:Connect(function() + callback((instance :: any)[prop]) + end) end, } end diff --git a/src/Keys/Clean.luau b/src/Keys/Clean.luau index e73fbb2..3466dd4 100644 --- a/src/Keys/Clean.luau +++ b/src/Keys/Clean.luau @@ -1,8 +1,7 @@ -- Variables -local Packages = script.Parent.Parent.Parent.Parent.Packages -local Utility = script.Parent.Utility -local Keys = require(Utility.Keys) -local Debugger = require(Packages.debugger) +local Root = script.Parent.Parent +local Keys = require(script.Parent.List) +local Debugger = require(Root.Parent.debugger) -- Module diff --git a/src/Keys/Event.luau b/src/Keys/Event.luau index 084e8ca..a50b35f 100644 --- a/src/Keys/Event.luau +++ b/src/Keys/Event.luau @@ -1,9 +1,12 @@ -- Variables -local Packages = script.Parent.Parent.Parent.Parent.Packages -local Utility = script.Parent.Utility -local FindProp = require(Utility.FindProp) -local Keys = require(Utility.Keys) -local Debugger = require(Packages.debugger) +local Root = script.Parent.Parent +local Keys = require(script.Parent.List) +local Debugger = require(Root.Parent.debugger) + +-- Functions +local function Find(instance: Instance, property: string) + return (instance :: any)[property] +end -- Module @@ -17,7 +20,7 @@ return function(event: string) Keys["Event"] = { Name = "Event", Apply = function(instance: Instance, callback: (...any) -> ()) - local Success, Event = pcall(FindProp, instance :: any, event :: any) + local Success, Event = pcall(Find, instance :: any, event :: any) if not Success or type(callback) ~= "function" then Debugger.Fatal("") end diff --git a/src/Keys/Utility/Keys.luau b/src/Keys/List.luau similarity index 100% rename from src/Keys/Utility/Keys.luau rename to src/Keys/List.luau diff --git a/src/Keys/Tag.luau b/src/Keys/Tag.luau index 485037e..79c9f5d 100644 --- a/src/Keys/Tag.luau +++ b/src/Keys/Tag.luau @@ -1,6 +1,5 @@ -- Variables -local Utility = script.Parent.Utility -local Keys = require(Utility.Keys) +local Keys = require(script.Parent.List) -- Module diff --git a/src/Keys/Utility/FindProp.luau b/src/Keys/Utility/FindProp.luau deleted file mode 100644 index 04cd31c..0000000 --- a/src/Keys/Utility/FindProp.luau +++ /dev/null @@ -1,4 +0,0 @@ --- Check if a property/event exists on an instance or not -return function(instance: Instance, property: string) - return (instance :: any)[property] -end diff --git a/src/State/Compute.luau b/src/State/Compute.luau index 21b8c38..3f3a4e2 100644 --- a/src/State/Compute.luau +++ b/src/State/Compute.luau @@ -14,9 +14,9 @@ local Class = {} [Learn More](https://luminlabsdev.github.io/ui-framework/api/compute/#use) ]=] -local function use(value: Types.Constructor | any) +local function use(value: Types.Constructor | any) if Is.Constructor(value) then - return (value :: Types.Constructor):Get() + return (value :: Types.Constructor):Get() else return value end @@ -24,11 +24,11 @@ end local function ListenerFunction(self: Types.Compute) return function() - self._result = self._processor(use) + self._Result = self._Processor(use) - if self._instances ~= nil then - for prop, instance in self._instances do - (instance :: any)[prop] = self._result + if self._Instances ~= nil then + for prop, instance in self._Instances do + (instance :: any)[prop] = self._Result end end end @@ -40,16 +40,16 @@ end [Learn More](https://luminlabsdev.github.io/ui-framework/api/compute/#get) ]=] function Class.Get(self: Types.Compute): any - return self._result + return self._Result end function Class._Bind(self: Types.Compute, prop: string, instance: Instance) - if self._instances == nil then - self._instances = {} + if self._Instances == nil then + self._Instances = {} end - (self._instances :: {})[prop] = instance; - (instance :: any)[prop] = self._result + (self._Instances :: {})[prop] = instance; + (instance :: any)[prop] = self._Result end --[=[ @@ -58,10 +58,10 @@ end [Learn More](https://luminlabsdev.github.io/ui-framework/api/compute/#destroy) ]=] function Class.Destroy(self: Types.Compute): nil - if self._dependencies then - for dependency, disconnect in self._dependencies do + if self._Dependencies then + for dependency, disconnect in self._Dependencies do disconnect() - self._dependencies[dependency] = nil + self._Dependencies[dependency] = nil end end @@ -79,16 +79,16 @@ end ]=] return function( processor: (get: typeof(use)) -> (), - dependencies: { Types.State | Types.Spring | Types.Constructor }? + dependencies: { Types.State | Types.Spring | Types.Constructor }? ): Types.Compute - local Dependencies = nil :: { [Types.State | Types.Spring | Types.Constructor]: () -> () }? - local self = setmetatable({} :: Types.ComputeProps, { __index = Class } :: { __index: Types.ComputeFunc }) + local Dependencies = nil :: { [Types.State | Types.Spring | Types.Constructor]: () -> () }? + local self = setmetatable({}, { __index = Class }) - self.ConstructorClass = "compute" - self._processor = processor - self._dependencies = Dependencies - self._result = self._processor(use) - self._instances = {} + self._Type = "compute" + self._Processor = processor + self._Dependencies = Dependencies + self._Result = self._Processor(use) + self._Instances = {} if dependencies then local TypeOfDependencies = type(dependencies) @@ -100,10 +100,10 @@ return function( for _, v in dependencies do if Is.Constructor(v :: any) then - if (v :: Types.Constructor)._Type == "state" then - (Dependencies :: {})[v] = (v :: Types.State):Listen(ListenerFunction(self)) - elseif (v :: Types.Constructor)._Type == "spring" then - (Dependencies :: {})[v] = (v :: Types.Spring)._state:Listen(ListenerFunction(self)) + if (v :: Types.Constructor)._Type == "state" then + (Dependencies :: {})[v] = (v :: any):Listen(ListenerFunction(self :: any)) + elseif (v :: Types.Constructor)._Type == "spring" then + (Dependencies :: {})[v] = (v :: any)._State:Listen(ListenerFunction(self :: any)) else Debugger.Warn("ConstructorNotSupported", v._Type) end @@ -114,5 +114,5 @@ return function( end end - return self + return self :: any end diff --git a/src/State/Value.luau b/src/State/Value.luau index f843cd6..f52ffbc 100644 --- a/src/State/Value.luau +++ b/src/State/Value.luau @@ -1,11 +1,10 @@ -- Variables local Root = script.Parent.Parent -local Packages = script.Parent.Parent.Parent.Parent.Packages local Types = require(Root.Types) local Utility = require(Root.Utility) -local Debugger = require(Packages.debugger) +local Debugger = require(Root.Parent.debugger) -local Class = {} :: Types.StateFunc +local Class = {} -- Functions @@ -73,7 +72,7 @@ end function Class._Bind(self: Types.State, prop: string, instance: Instance) (instance :: any)[prop] = self._State - self:Listen(function(newValue) + ;(self :: any):Listen(function(newValue) (instance :: any)[prop] = newValue end) end @@ -103,11 +102,11 @@ return function(initial: any): Types.State initial = initial or nil end - local self = setmetatable({} :: Types.StateProps, { __index = Class } :: { __index: Types.StateFunc }) + local self = setmetatable({}, { __index = Class }) self._Type = "state" self._State = initial self._Listeners = {} - return self + return self :: any end diff --git a/src/Types.luau b/src/Types.luau index cae516e..5cf532f 100644 --- a/src/Types.luau +++ b/src/Types.luau @@ -21,76 +21,60 @@ export type Properties = { [string | Key]: any } export type Children = { [string | number]: any } export type Key = { - Name: string, - Apply: (instance: Instance, ...any) -> (), + Name: string, + Apply: (instance: Instance, ...any) -> (), } -export type Constructor = { - _Bind: (self: any, prop: string, instance: Instance) -> (), +export type Constructor = { + _Bind: (self: T, prop: string, instance: Instance) -> (), _Type: string, - Get: (self: any) -> any, - Destroy: (self: any) -> (), + Get: (self: T) -> any, + Destroy: (self: T) -> (), } -export type SpringInfo = { - State: State, - Damping: number?, - Frequency: number?, -} - -export type StateFunc = { - _init: (self: State, prop: string, instance: Instance) -> (), - _Bind: (self: State, prop: string, instance: Instance) -> (), - Get: (self: State) -> any, - Set: (self: State, value: any) -> State, - Listen: (self: State, listener: (new: any, old: any) -> ()) -> () -> (), - Destroy: (self: State) -> (), -} - -export type StateProps = { - _Type: "state", - _State: any, - _Listeners: { (newValue: any, oldValue: any) -> () }, -} - -export type State = typeof(setmetatable({} :: StateProps, {} :: { __index: StateFunc })) - -export type SpringFunc = { - _init: (self: Spring, prop: string, instance: Instance) -> (), - Get: (self: Spring) -> any, - _update: (self: Spring, linearTargetPosition: { number }, delta: number) -> (), - Destroy: (self: Spring) -> nil, -} - -export type SpringProps = { - ConstructorClass: "spring", - _state: State, - _damping: number, - _frequency: number, - _velocity: { number }, - _currentLinearPosition: { number }, - _type: { - ToLinear: (value: Animatable) -> { number }, - FromLinear: (value: { number }) -> Animatable, +export type State = typeof(setmetatable( + {} :: { + _Type: "state", + _State: any, + _Listeners: { (newValue: any, oldValue: any) -> () }, }, -} - -export type Spring = typeof(setmetatable({} :: SpringProps, {} :: { __index: SpringFunc })) - -export type ComputeFunc = { - _init: (self: Compute, prop: string, instance: Instance) -> (), - Get: (self: Compute) -> any, - Destroy: (self: Compute) -> nil, -} + {} :: { + __index: { + Set: (self: State, value: any) -> State, + Listen: (self: State, listener: (new: any, old: any) -> ()) -> () -> (), + } & Constructor, + } +)) -export type ComputeProps = { - ConstructorClass: "compute", - _processor: (get: (value: Constructor | any) -> ()) -> (), - _dependencies: { [State | Spring | Constructor]: () -> () }?, - _result: any, - _instances: { [string]: Instance }?, -} +export type Spring = typeof(setmetatable( + {} :: { + _Type: "spring", + _State: State, + _Damping: number, + _Frequency: number, + _Velocity: { number }, + _CurrentLinearPosition: { number }, + _type: { + ToLinear: (value: Animatable) -> { number }, + FromLinear: (value: { number }) -> Animatable, + }, + }, + {} :: { + __index: { + _Update: (self: Spring, linearTargetPosition: { number }, delta: number) -> (), + } & Constructor, + } +)) -export type Compute = typeof(setmetatable({} :: ComputeProps, {} :: { __index: ComputeFunc })) +export type Compute = typeof(setmetatable( + {} :: { + _Type: "compute", + _Processor: (get: (value: Constructor | any) -> ()) -> (), + _Dependencies: { [State | Spring | Constructor]: () -> () }?, + _Result: any, + _Instances: { [string]: Instance }?, + }, + {} :: { __index: Constructor } +)) return {} diff --git a/src/Utility.luau b/src/Utility.luau index 44ad2aa..2b8ce6c 100644 --- a/src/Utility.luau +++ b/src/Utility.luau @@ -31,12 +31,12 @@ local function CheckTypeAndCall(expected: any, received: any, interaction: () -> end end -local function ApplyConstructorProperty(instance: Instance, prop: string, value: Types.Constructor) +local function ApplyConstructorProperty(instance: Instance, prop: string, value: Types.Constructor) local Property = (instance :: any)[prop] -- Call the _bind method of the Service. CheckTypeAndCall(Property, value:Get(), function() - (value :: Types.Constructor):_Bind(prop, instance) + (value :: Types.Constructor):_Bind(prop, instance) end) end diff --git a/src/init.luau b/src/init.luau index a0465fd..7ffea54 100644 --- a/src/init.luau +++ b/src/init.luau @@ -1,5 +1,5 @@ -- Variables -local Packages = script.Parent.Parent.Packages +local Packages = script.Parent local Instances = script.Instances local Animation = script.Animation local State = script.State @@ -14,7 +14,6 @@ export type State = Types.State export type Spring = Types.Spring export type Compute = Types.Compute export type Animatable = Types.Animatable -export type SpringInfo = Types.SpringInfo export type Component = Types.Component -- Module @@ -30,7 +29,7 @@ return table.freeze({ Value = require(State.Value), Compute = require(State.Compute), - -- Spring = require(Animation.Spring), + Spring = require(Animation.Spring), -- Tween = require(Animation.Tween), Event = require(Keys.Event), diff --git a/tests/Client/UI.client.luau b/tests/Client/UI.client.luau index 2a5d3d2..3d4cc31 100644 --- a/tests/Client/UI.client.luau +++ b/tests/Client/UI.client.luau @@ -46,6 +46,11 @@ New("ScreenGui", { c+=1 State:Set(`Hello {c}`) end, + + [Framework.Change "Name"] = function(new_name: any) + print(new_name) + end, + Text = "Test", Position = UDim2.fromScale(0.5, 0.2), Size = UDim2.fromOffset(100, 100),