@ringozz/react-godot 4.7.2-594 → 4.7.2-604
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/package.json +2 -2
- package/src/react-hooks.ts +46 -46
package/README.md
CHANGED
|
@@ -284,7 +284,7 @@ export function App() {
|
|
|
284
284
|
| `createPortal(children, container)` | Function | Renders children into a target Godot `Node` (e.g. `CanvasLayer` or `SubViewport`). |
|
|
285
285
|
| `useSignal(signal, callback)` | Hook | Connects a callback to a Godot object signal (e.g. `tree.processFrame`, `node.treeEntered`). Disconnects on unmount. |
|
|
286
286
|
| `useMutableCallback(fn)` | Hook | Returns a `RefObject` whose `.current` always points to the latest callback implementation. |
|
|
287
|
-
| `useTween<NodeT>(create, deps)` | Hook | Reactive tween-as-prop-value. Returns `[spring, tweenRef]` — spread `spring` onto a node; `tweenRef.current` is the live native `Tween`. The optional node type (`useTween<Node3D>`) types `to`/`from` array goals as that node's value-type tuples. |
|
|
287
|
+
| `useTween<NodeT>(create, deps)` | Hook | Reactive tween-as-prop-value. Returns `[spring, tweenRef]` — spread `spring` onto a node; `tweenRef.current` is the live native `Tween`. The optional node type (`useTween<Node3D>`) types `to`/`from` array goals as that node's value-type tuples. |
|
|
288
288
|
| `ComponentProps<T>` | Type | Utility type to infer valid React JSX props for any Godot node class `T`. |
|
|
289
289
|
|
|
290
290
|
## Animating props with `useTween`
|
|
@@ -292,9 +292,9 @@ export function App() {
|
|
|
292
292
|
`useTween` animates a node's properties declaratively. You describe the target values once per `to` key; spreading the returned `spring` onto a node binds the tween to it. Re-rendering with the same `deps` keeps the same tween (nothing restarts); changing `deps` creates a new `Tween` and animates from the current values.
|
|
293
293
|
|
|
294
294
|
```tsx
|
|
295
|
-
const [spring, tweenRef] = useTween<Node3D>(() => ({
|
|
296
|
-
from: { position: [0, 0, 0] },
|
|
297
|
-
to: { position: [0, 2, 0], globalRotation: [0, 90, 0] },
|
|
295
|
+
const [spring, tweenRef] = useTween<Node3D>(() => ({
|
|
296
|
+
from: { position: [0, 0, 0] },
|
|
297
|
+
to: { position: [0, 2, 0], globalRotation: [0, 90, 0] },
|
|
298
298
|
config: { duration: 0.6, transition: TransitionType.TRANS_QUAD, ease: EaseType.EASE_IN_OUT },
|
|
299
299
|
delay: 0, loops: 1, immediate: false,
|
|
300
300
|
onFinished: () => {},
|
|
@@ -303,8 +303,8 @@ const [spring, tweenRef] = useTween<Node3D>(() => ({
|
|
|
303
303
|
return <Node3D {...spring} />;
|
|
304
304
|
```
|
|
305
305
|
|
|
306
|
-
- **`spring`** holds one function per `to` key (spread them all onto the node; each contributes its own prop's tweener to the shared `Tween`). Array values are converted to the property's value type.
|
|
307
|
-
- **Node-typed goals**: call `useTween<Node3D>(...)` so `to`/`from` are typed against that node's props — `position: [0, 2, 0]` and nested `basis: [[…]]` infer as `Vector3`/`Basis`, with no `as Vector3` casts. Only scalar-number and value-type props are tweenable (signals, `Node` refs, bools, strings, containers are rejected); the returned `spring` is that whole prop set (all optional), so `{...spring}` stays JSX-spreadable. A bare `useTween(...)` keeps array goals loose (`number[]`).
|
|
306
|
+
- **`spring`** holds one function per `to` key (spread them all onto the node; each contributes its own prop's tweener to the shared `Tween`). Array values are converted to the property's value type.
|
|
307
|
+
- **Node-typed goals**: call `useTween<Node3D>(...)` so `to`/`from` are typed against that node's props — `position: [0, 2, 0]` and nested `basis: [[…]]` infer as `Vector3`/`Basis`, with no `as Vector3` casts. Only scalar-number and value-type props are tweenable (signals, `Node` refs, bools, strings, containers are rejected); the returned `spring` is that whole prop set (all optional), so `{...spring}` stays JSX-spreadable. A bare `useTween(...)` keeps array goals loose (`number[]`).
|
|
308
308
|
- **`tweenRef.current`** is the **live native Godot `Tween`**, created when the node mounts (null before that): `tweenRef.current?.kill()`, `?.pause()`, `?.play()`, `?.setSpeedScale(n)`, `?.isRunning()`, `?.finished`…
|
|
309
309
|
- **`config`** maps to the Godot Tween API: `duration` (seconds), `transition`/`ease` (`TransitionType`/`EaseType` — the tween's defaults), `easing` (a `[0,1]→[0,1]` function → `setCustomInterpolator`), `speedScale`.
|
|
310
310
|
- **`onStart`** fires when the tween is created/bound (on mount or when `deps` change), before it starts stepping.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ringozz/react-godot",
|
|
3
3
|
"author": "Vladimir Davidovich",
|
|
4
|
-
"version": "4.7.2-
|
|
4
|
+
"version": "4.7.2-604",
|
|
5
5
|
"description": "A React renderer for Godot Engine via @ringozz/godot",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"*.md"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@ringozz/godot": "^4.7.2-
|
|
26
|
+
"@ringozz/godot": "^4.7.2-604",
|
|
27
27
|
"@types/react-reconciler": "^0.33.0",
|
|
28
28
|
"react-reconciler": "^0.33.0"
|
|
29
29
|
},
|
package/src/react-hooks.ts
CHANGED
|
@@ -6,10 +6,10 @@ import type { Signal } from '@ringozz/godot';
|
|
|
6
6
|
import type { Node } from '@ringozz/godot/Node';
|
|
7
7
|
import type { Object as Instance } from '@ringozz/godot/Object';
|
|
8
8
|
import { PropertyTweener } from '@ringozz/godot/PropertyTweener';
|
|
9
|
-
import { Tween, type EaseType, type TransitionType } from '@ringozz/godot/Tween';
|
|
10
|
-
import type React from 'react';
|
|
11
|
-
import { useEffect, useMemo, useRef } from 'react';
|
|
12
|
-
import { toValueType } from '@ringozz/godot/runtime';
|
|
9
|
+
import { Tween, type EaseType, type TransitionType } from '@ringozz/godot/Tween';
|
|
10
|
+
import type React from 'react';
|
|
11
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
12
|
+
import { toValueType } from '@ringozz/godot/runtime';
|
|
13
13
|
|
|
14
14
|
// Tween/PropertyTweener are only type-used here; value-reference them so their
|
|
15
15
|
// `_R` class registration isn't tree-shaken (otherwise createTween's wrapper
|
|
@@ -47,24 +47,24 @@ export function useSignal<T extends (...args: any[]) => any>(signal: Signal<T>,
|
|
|
47
47
|
// identity diff drops them, so nothing restarts); changing deps creates a new
|
|
48
48
|
// tween (the previous one is killed).
|
|
49
49
|
|
|
50
|
-
// Tweenable goal values: scalars and value-type tuples. `GodotVar` (the base of
|
|
51
|
-
// *every* Godot object) is deliberately NOT a member — `useTween` always wraps
|
|
52
|
-
// goals through `toValueType`, so callers pass plain numbers/tuples, and
|
|
53
|
-
// including `GodotVar` would wrongly admit signals/`Node` refs/object props.
|
|
54
|
-
//
|
|
55
|
-
// When the caller passes a node instance type (e.g. `useTween<Node3D>`), `to`
|
|
56
|
-
// /`from` are contextually typed against that node's settable props, so each
|
|
57
|
-
// array goal infers as the property's value-type tuple (Vector3, Basis, …). A
|
|
58
|
-
// bare `useTween(...)` call keeps the loose behavior below (`number[]` goals).
|
|
59
|
-
type TweenValue = number | number[] | number[][];
|
|
60
|
-
|
|
61
|
-
// Settable props whose value is a tweenable goal (`number`/value-type tuple).
|
|
62
|
-
// Signals, `Node` refs and other Godot objects are not `TweenValue`s, so they
|
|
63
|
-
// never leak into `spring` (`{...spring}` stays JSX-spreadable). Mapping over
|
|
64
|
-
// `keyof T` lets `to` be contextually typed with the node's value-type tuples.
|
|
65
|
-
type TweenableProps<T> = {
|
|
66
|
-
[K in keyof T as T[K] extends TweenValue ? K : never]: T[K];
|
|
67
|
-
};
|
|
50
|
+
// Tweenable goal values: scalars and value-type tuples. `GodotVar` (the base of
|
|
51
|
+
// *every* Godot object) is deliberately NOT a member — `useTween` always wraps
|
|
52
|
+
// goals through `toValueType`, so callers pass plain numbers/tuples, and
|
|
53
|
+
// including `GodotVar` would wrongly admit signals/`Node` refs/object props.
|
|
54
|
+
//
|
|
55
|
+
// When the caller passes a node instance type (e.g. `useTween<Node3D>`), `to`
|
|
56
|
+
// /`from` are contextually typed against that node's settable props, so each
|
|
57
|
+
// array goal infers as the property's value-type tuple (Vector3, Basis, …). A
|
|
58
|
+
// bare `useTween(...)` call keeps the loose behavior below (`number[]` goals).
|
|
59
|
+
type TweenValue = number | number[] | number[][];
|
|
60
|
+
|
|
61
|
+
// Settable props whose value is a tweenable goal (`number`/value-type tuple).
|
|
62
|
+
// Signals, `Node` refs and other Godot objects are not `TweenValue`s, so they
|
|
63
|
+
// never leak into `spring` (`{...spring}` stays JSX-spreadable). Mapping over
|
|
64
|
+
// `keyof T` lets `to` be contextually typed with the node's value-type tuples.
|
|
65
|
+
type TweenableProps<T> = {
|
|
66
|
+
[K in keyof T as T[K] extends TweenValue ? K : never]: T[K];
|
|
67
|
+
};
|
|
68
68
|
|
|
69
69
|
export interface TweenConfig {
|
|
70
70
|
/** Seconds (default 1). */
|
|
@@ -79,11 +79,11 @@ export interface TweenConfig {
|
|
|
79
79
|
speedScale?: number;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
export interface TweenProps<P extends Record<string, unknown> = Record<string, TweenValue>> {
|
|
83
|
-
/** Start values, applied on the first build (mount) before animating to `to`. */
|
|
84
|
-
from?: Partial<P>;
|
|
85
|
-
/** Target values — one assigner is returned per key. */
|
|
86
|
-
to: P;
|
|
82
|
+
export interface TweenProps<P extends Record<string, unknown> = Record<string, TweenValue>> {
|
|
83
|
+
/** Start values, applied on the first build (mount) before animating to `to`. */
|
|
84
|
+
from?: Partial<P>;
|
|
85
|
+
/** Target values — one assigner is returned per key. */
|
|
86
|
+
to: P;
|
|
87
87
|
config?: TweenConfig;
|
|
88
88
|
/** Seconds; per-tweener PropertyTweener.setDelay. */
|
|
89
89
|
delay?: number;
|
|
@@ -96,19 +96,19 @@ export interface TweenProps<P extends Record<string, unknown> = Record<string, T
|
|
|
96
96
|
onFinished?: () => void;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
export type Spring<P extends Record<string, unknown>> = { [K in keyof P]: P[K] };
|
|
99
|
+
export type Spring<P extends Record<string, unknown>> = { [K in keyof P]: P[K] };
|
|
100
100
|
|
|
101
101
|
// tweenProperty/set reject generic JS arrays, so array goals are reconstructed
|
|
102
102
|
// as the property's value type by `toValueType` (resolves the node's
|
|
103
103
|
// property type and returns a GodotVar carrier the `_C` tween path unwraps;
|
|
104
104
|
// non-array goals pass through unchanged).
|
|
105
105
|
|
|
106
|
-
function makeSpring<P extends Record<string, unknown>>(
|
|
107
|
-
tweenRef: { current: Tween | null },
|
|
108
|
-
props: TweenProps<P>,
|
|
109
|
-
): Spring<P> {
|
|
110
|
-
const config = props.config ?? {};
|
|
111
|
-
const spring = {} as Spring<P>;
|
|
106
|
+
function makeSpring<P extends Record<string, unknown>>(
|
|
107
|
+
tweenRef: { current: Tween | null },
|
|
108
|
+
props: TweenProps<P>,
|
|
109
|
+
): Spring<P> {
|
|
110
|
+
const config = props.config ?? {};
|
|
111
|
+
const spring = {} as Spring<P>;
|
|
112
112
|
let started = false;
|
|
113
113
|
let applyFrom = false;
|
|
114
114
|
|
|
@@ -141,18 +141,18 @@ function makeSpring<P extends Record<string, unknown>>(
|
|
|
141
141
|
if (props.delay !== undefined) tw.setDelay(props.delay);
|
|
142
142
|
if (config.easing) tw.setCustomInterpolator(config.easing);
|
|
143
143
|
};
|
|
144
|
-
spring[key as keyof P] = assigner as unknown as P[keyof P];
|
|
145
|
-
}
|
|
146
|
-
return spring;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export function useTween<
|
|
150
|
-
T extends Instance = any,
|
|
151
|
-
P extends Partial<TweenableProps<T>> = Partial<TweenableProps<T>>,
|
|
152
|
-
>(
|
|
153
|
-
create: () => TweenProps<P>,
|
|
154
|
-
deps: unknown[] = [],
|
|
155
|
-
): [Spring<P>, React.RefObject<Tween | null>] {
|
|
144
|
+
spring[key as keyof P] = assigner as unknown as P[keyof P];
|
|
145
|
+
}
|
|
146
|
+
return spring;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function useTween<
|
|
150
|
+
T extends Instance = any,
|
|
151
|
+
P extends Partial<TweenableProps<T>> = Partial<TweenableProps<T>>,
|
|
152
|
+
>(
|
|
153
|
+
create: () => TweenProps<P>,
|
|
154
|
+
deps: unknown[] = [],
|
|
155
|
+
): [Spring<P>, React.RefObject<Tween | null>] {
|
|
156
156
|
const tweenRef = useRef<Tween | null>(null);
|
|
157
157
|
// 'create' is intentionally re-evaluated via `deps`, not listed here.
|
|
158
158
|
/* oxlint-disable-next-line react-hooks/exhaustive-deps */
|