diff --git a/src/use-motion/use-motion.ts b/src/use-motion/use-motion.ts index 8f8e36c..e0c3095 100644 --- a/src/use-motion/use-motion.ts +++ b/src/use-motion/use-motion.ts @@ -1,10 +1,33 @@ import type { Binding } from "@rbxts/react"; -import { useBinding, useMemo } from "@rbxts/react"; +import { useBinding, useEffect, useMemo } from "@rbxts/react"; import type { Motion, MotionGoal } from "@rbxts/ripple"; import { createMotion } from "@rbxts/ripple"; -import { useEventListener } from "../use-event-listener"; import { RunService } from "@rbxts/services"; +const callbacks = new Set<(dt: number) => void>(); +let connection: RBXScriptConnection | undefined; + +function connect(callback: (dt: number) => void) { + callbacks.add(callback); + + if (!connection) { + connection = RunService.Heartbeat.Connect((dt) => { + for (const callback of callbacks) { + callback(dt); + } + }); + } +} + +function disconnect(callback: (dt: number) => void) { + callbacks.delete(callback); + + if (callbacks.isEmpty()) { + connection?.Disconnect(); + connection = undefined; + } +} + export function useMotion(initialValue: number): LuaTuple<[Binding, Motion]>; export function useMotion(initialValue: T): LuaTuple<[Binding, Motion]>; export function useMotion(initialValue: T) { @@ -14,13 +37,19 @@ export function useMotion(initialValue: T) { const [binding, setValue] = useBinding(initialValue); - useEventListener(RunService.Heartbeat, (delta) => { - const value = motion.step(delta); + useEffect(() => { + const callback = (delta: number) => { + const value = motion.step(delta); + + if (value !== binding.getValue()) { + setValue(value); + } + }; - if (value !== binding.getValue()) { - setValue(value); - } - }); + connect(callback); + + return () => disconnect(callback); + }, []); return $tuple(binding, motion); }