So, recently(today), I have started on an new project, an open source module to manage UIAnimations and Effects. I have created typechecking, and two effects: Float On Hover, and Fade.
Features:
- Manageable Effects, easy to use and delete to clear up memory
- Full Typechecking
- UI sounds, instant cleanup for sounds
Upcoming Features
- Easy to plan out ui animations(move the ui to one place, click an button on an plugin, etc)
- An easy UIBlur implementation
- Auto Setup for UIDragDetectors
- Loading screen animations
- Lots of new effects
Here is the current Module:
--!strict
local UIAnimatorClass = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
UIAnimatorClass.__index = UIAnimatorClass
local UIEffects = {}
UIEffects.__index = UIEffects
export type UIEffect = {
connection1: RBXScriptConnection,
connection2: RBXScriptConnection,
connection3: RBXScriptConnection,
connection4: RBXScriptConnection,
name: string,
effect: string,
guiObject: GuiObject,
effectPMS: {},
Destroy: (self:UIEffect) -> nil
}
export type HoverPM = {
hoverOffset: number,
sound: Sound,
floatTime: number,
}
export type FadePM = {
fadeTime:number,
visibility:"visible"|"invisible"
}
export type UIAnimator = {
guiObject: GuiObject,
state: string,
create: (guiObject: GuiObject) -> UIAnimator,
effects: {},
runningEffect: nil | UIEffect,
passiveEffect: nil | UIEffect,
}
export type UIAnimatorClass = {
create: (guiObject: GuiObject) -> UIAnimator,
}
function UIEffects.create(name, effectName, guiObject, effectPMS: FadePM & HoverPM) --add anyother effect in here for typing
local self: UIEffect = setmetatable({}, UIEffects) :: any
self.name = name
self.effect = effectName
self.effectPMS = effectPMS
self.guiObject = guiObject
if effectName == "floatHover" then
local hoverTween
self.connection1 = self.guiObject.MouseEnter:Connect(function()
local goal =
{ guiObject.Position + UDim2.new(0, 0, guiObject.Position.Y.Scale + effectPMS["hoverOffset"], 0) }
local TweenInfo = TweenInfo.new(effectPMS["floatTime"], Enum.EasingStyle.Sine)
hoverTween = TweenService:Create(guiObject, TweenInfo, goal)
hoverTween:Play()
local soundClone = effectPMS["sound"]:Clone()
soundClone.PlayOnRemove = true
soundClone:Destroy()
end)
self.connection2 = self.guiObject.MouseLeave:Connect(function()
if hoverTween then
hoverTween:Cancel()
end
local goal =
{ guiObject.Position + UDim2.new(0, 0, guiObject.Position.Y.Scale - effectPMS["hoverOffset"], 0) }
local TweenInfo = TweenInfo.new(effectPMS["floatTime"], Enum.EasingStyle.Sine)
hoverTween = TweenService:Create(guiObject, TweenInfo, goal)
hoverTween:Play()
end)
end
if effectName == "fade" then
local tweenInfo = TweenInfo.new(effectPMS.fadeTime, Enum.EasingStyle.Sine)
local goal:{}
if effectPMS.visibility == "invisible" then
goal = {BackgroundTransparency = 1}
end
if effectPMS.visibility == "visible" then
goal = {BackgroundTransparency = 0}
end
local MainTween = TweenService:Create(guiObject, tweenInfo, goal)
MainTween:Play()
for _, child:GuiObject | Instance in pairs(guiObject:GetDescendants()) do
if child:IsA("GuiObject") then
local newTween = TweenService:Create(child, tweenInfo, goal)
newTween:Play()
end
--TODO ADD TEXT TRANSPARENCY
end
self.connection1 = MainTween.Completed:Wait()
end
return self
end
function UIEffects.Destroy(self: UIEffect)
if self.connection1 then
self.connection1:Disconnect()
end
if self.connection2 then
self.connection2:Disconnect()
end
if self.connection3 then
self.connection3:Disconnect()
end
if self.connection4 then
self.connection4:Disconnect()
end
end
function UIAnimatorClass.create(guiObject: GuiObject): UIAnimator
local self: UIAnimator = setmetatable({}, UIAnimatorClass) :: any
self.guiObject = guiObject
self.state = "visible"
self.effects = {}
self.runningEffect = nil
return self
end
function UIAnimatorClass.addEffect(self: UIAnimator, effect, name, effectPM)
local RunningEffects = self.effects
local neweffect = UIEffects.create(name, effect, self.guiObject, effectPM)
table.insert(RunningEffects, neweffect)
end
function UIAnimatorClass.runEffect(self: UIAnimator, name): UIEffect
for _, effect: UIEffect in self.effects :: any do
if effect.name == name then
self.runningEffect = effect
return effect
end
end
return nil :: any
end
function UIAnimatorClass.runPassiveEffect(self:UIAnimator, name): UIEffect
for _, effect: UIEffect in self.effects :: any do
if effect.name == name then
self.passiveEffect = effect
return effect
end
end
return nil :: any
end
function UIAnimatorClass.clearRunEffect(self:UIAnimator)
local effect:UIEffect = self.runningEffect::UIEffect
effect:Destroy()
end
function UIAnimatorClass.clearPassiveEffect(self:UIAnimator)
local effect:UIEffect = self.passiveEffect::UIEffect
effect:Destroy()
end
return UIAnimatorClass