@ringozz/react-godot 0.1.0 → 0.1.1
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 +94 -0
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @ringozz/react-godot
|
|
2
|
+
|
|
3
|
+
React bindings for the Godot Engine, built on [`@ringozz/godot`](../godot/README.md). A custom `react-reconciler` host config lets you build Godot scenes declaratively with JSX.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
bun add @ringozz/react-godot @ringozz/godot react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`@ringozz/godot` and `react` (`^19.2`) are peer dependencies. Configure the JSX runtime in `tsconfig.json`:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"compilerOptions": {
|
|
16
|
+
"jsx": "react-jsx",
|
|
17
|
+
"jsxImportSource": "@ringozz/react-godot"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## API
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { createRoot, createPortal, useSignal, useMutableCallback, type ComponentProps } from '@ringozz/react-godot';
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- **`createRoot(parent: Node)`** — mounts a React tree into a Godot `Node` (e.g. `SceneTree.root`). Returns `{ render, unmount }`; `render` resolves when the commit completes. StrictMode is enabled only when `NODE_ENV === 'development'`.
|
|
29
|
+
- **`createPortal(children, container)`** — renders into another Godot `Node` (a `CanvasLayer` for overlays, a `SubViewport`, a dedicated parent node). The container must be a `Node` — portals cannot target `Resource`s. Unmounting frees the portal's children.
|
|
30
|
+
- **`useSignal<T extends (...args: any[]) => any>(signal, handler)`** — connects a Godot `Signal` for the component's lifetime, disconnecting on unmount. Uses a mutable callback ref, so the handler always sees fresh state.
|
|
31
|
+
- **`useMutableCallback<T>(fn)`** — returns a `RefObject<T>` whose `.current` always holds the latest `fn`.
|
|
32
|
+
- **`ComponentProps<typeof ClassName>`** — full prop validation for an element (Godot properties + `children`/`ref` + `object`/`attach`).
|
|
33
|
+
|
|
34
|
+
## Example
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { Engine } from '@ringozz/godot/Engine';
|
|
38
|
+
import { SceneTree } from '@ringozz/godot/SceneTree';
|
|
39
|
+
import { Label } from '@ringozz/godot/Label';
|
|
40
|
+
import { createRoot, useSignal } from '@ringozz/react-godot';
|
|
41
|
+
import { useRef } from 'react';
|
|
42
|
+
|
|
43
|
+
const tree = Engine.getMainLoop() as SceneTree;
|
|
44
|
+
const { render } = createRoot(tree.root);
|
|
45
|
+
|
|
46
|
+
function Hud() {
|
|
47
|
+
const label = useRef<Label>(null);
|
|
48
|
+
useSignal(tree.processFrame, () => {
|
|
49
|
+
if (label.current) label.current.text = String(Math.floor(performance.now() / 1000));
|
|
50
|
+
});
|
|
51
|
+
return <Label ref={label} position={[16, 16]} text="ticking" />;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
render(<Hud />);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Render a component
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
function App() {
|
|
61
|
+
return (
|
|
62
|
+
<WorldEnvironment>
|
|
63
|
+
<Environment attach="environment" backgroundColor={[0.05, 0.1, 0.25]} />
|
|
64
|
+
</WorldEnvironment>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## How elements map to Godot
|
|
70
|
+
|
|
71
|
+
- Each element instantiates its class via `ClassDB.instantiate(type)` (or uses an existing instance passed through the `object` prop, which bypasses instantiation and `.reference()`s `RefCounted` objects).
|
|
72
|
+
- **`attach="prop"`** sets the element as a named property of its parent instead of adding it as a child — use it for resources. A physics body's shape goes on the **shape resource element**, never on the `CollisionShape3D` node:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<StaticBody3D>
|
|
76
|
+
<CollisionShape3D>
|
|
77
|
+
<BoxShape3D attach="shape" size={[1, 1, 1]} />
|
|
78
|
+
</CollisionShape3D>
|
|
79
|
+
<MeshInstance3D>
|
|
80
|
+
<BoxMesh attach="mesh" />
|
|
81
|
+
<StandardMaterial3D attach="materialOverride" />
|
|
82
|
+
</MeshInstance3D>
|
|
83
|
+
</StaticBody3D>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The `attach` value may not change across updates.
|
|
87
|
+
- **`object` prop**: pass an existing Godot instance (nodes or resources) to render rather than create one.
|
|
88
|
+
- **Text**: standalone text nodes are unsupported. A single string child is mapped to the node's `text` property — fine for `Label`/`Label3D` — but arrays/mixed string children throw; use a `text` prop instead.
|
|
89
|
+
|
|
90
|
+
## Notes
|
|
91
|
+
|
|
92
|
+
- `Node` children are added/moved with `addChild`/`moveChild`/`removeChild`; unmounting a subtree calls `free()` on each deleted instance.
|
|
93
|
+
- Portals and other non-React children of a root container are never touched by the reconciler.
|
|
94
|
+
- See the demo in the repo (`dev/DemoApp.tsx`) for physics, camera controls, and a portal HUD, and `AGENTS.md` for reconciler internals.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ringozz/react-godot",
|
|
3
3
|
"author": "Vladimir Davidovich",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"description": "React reconciler bindings for Godot Engine via @ringozz/godot",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./src/index.ts",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"./jsx-dev-runtime": "./src/react-jsx.ts"
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
|
-
"src/"
|
|
15
|
+
"src/",
|
|
16
|
+
"*.md"
|
|
16
17
|
],
|
|
17
18
|
"dependencies": {
|
|
18
19
|
"react-reconciler": "^0.33.0"
|