@lukekaalim/act-three 7.1.1 → 8.0.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @lukekaalim/act-three
2
2
 
3
+ ## 8.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - bf3138f: Added PrimitiveRegistry for dynamically adding more elements to act-three, implemented in backstage
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [bf3138f]
12
+ - @lukekaalim/act-backstage@3.2.0
13
+ - @lukekaalim/act-web@5.2.0
14
+ - @lukekaalim/act@4.3.0
15
+
16
+ ## 7.1.2
17
+
18
+ ### Patch Changes
19
+
20
+ - Fix missing package.json updates from last patch
21
+
3
22
  ## 7.1.1
4
23
 
5
24
  ### Patch Changes
package/builder.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { NodeBuilder } from "@lukekaalim/act-backstage";
2
2
  import { Object3D } from "three";
3
- import { getElementHandler } from "./elements";
3
+ import { registry } from "./elements";
4
4
  import { Component, h, specialNodeTypes } from "@lukekaalim/act";
5
5
 
6
6
  export const ThreeJSRoot: Component = ({ children }) => h(specialNodeTypes.render, { type: 'threejs' }, children);
@@ -9,15 +9,10 @@ export const createThreeJSBuilder = (rootObject: Object3D | null = null): NodeBu
9
9
  roots: new Set(['threejs']),
10
10
 
11
11
  create(element) {
12
- const handler = getElementHandler(element.type);
13
- if (handler)
14
- return handler.create(element.props);
15
- return null;
12
+ return registry.create(element);
16
13
  },
17
14
  update(el, next, prev) {
18
- const handler = getElementHandler(next.type);
19
- if (handler)
20
- handler.setProps(el, prev && prev.props, next.props);
15
+ registry.update(el, next, prev);
21
16
  },
22
17
  linkRoot: rootObject && ((child) => {
23
18
  rootObject.add(child);
package/elements.ts CHANGED
@@ -1,69 +1,165 @@
1
- import { DirectionalLight, Group, Line, LineLoop, LineSegments, Mesh, Object3D, OrthographicCamera, PerspectiveCamera, PointLight, Points, Scene, SkinnedMesh, Sprite } from "three";
2
- import { act } from "./deps";
3
- import { Object3DProps, setProps } from "./props";
4
- import { Component, ElementType, h, Node } from "@lukekaalim/act";
1
+ import * as three from "three";
2
+ import { Ref } from "@lukekaalim/act";
3
+ import { createPrimitiveRegistry } from "@lukekaalim/act-backstage";
4
+ import { setProps } from "./props";
5
5
 
6
- const handlers = new Map<string | Symbol, ThreeNodeHandler<any>>();
6
+ export type PropsFromClass<T extends three.Object3D> = {
7
+ position?: three.Vector3Like,
8
+ rotation?: three.Euler,
9
+ quaternion?: three.QuaternionLike,
10
+ scale?: three.Vector3,
11
+ //pivot?: three.Vector3Like | null,
7
12
 
8
- export type ThreeNodeHandler<T extends Object3D> = {
9
- type: string | Symbol,
10
- create: (props: act.Props) => T,
11
- setProps: (instance: T, prevProps: null | act.Props, nextProps: act.Props) => unknown,
13
+ name?: string,
14
+ layers?: three.Layers,
15
+
16
+ visible?: boolean,
17
+ static?: boolean,
18
+ renderOrder?: number,
19
+ receiveShadow?: boolean,
20
+ castShadow?: boolean,
21
+ frustumCulled?: boolean,
22
+
23
+ animations?: three.AnimationClip[],
24
+
25
+ userData?: {},
26
+
27
+ //up?: three.Vector3Like,
28
+
29
+ //onChildAdded?: (child: three.Object3D) => void,
30
+ //onChildRemoved?: (child: three.Object3D) => void,
31
+ //onAdded?: (self: T) => void,
32
+ //onRemoved?: (self: T) => void,
33
+
34
+ ref?: Ref<null | T>
12
35
  }
36
+ & (T extends three.Mesh | three.Points | three.Line ? DrawableProps : {})
37
+ & (T extends three.Sprite ? SpriteProps : {})
38
+ & (T extends three.Light ? LightProps : {})
39
+ & (T extends three.Camera ? CameraProps<T> : {})
40
+ & (T extends three.Scene ? SceneProps : {})
13
41
 
14
- export const registerElementHandler = <T extends Object3D>(handler: ThreeNodeHandler<T>): void => {
15
- handlers.set(handler.type, handler);
42
+ type SceneProps = {
43
+ fog?: three.FogExp2 | three.Fog | null,
44
+ overrideMaterial?: three.Material | null,
45
+
46
+ background?: three.Color | three.Texture | null,
47
+ backgroundBlurriness?: number,
48
+ backgroundRotation?: number,
49
+ backgroundIntensity?: three.Euler,
50
+
51
+ environment?: three.Texture | null,
52
+ environmentRotation?: number,
53
+ environmentIntensity?: three.Euler,
16
54
  }
17
55
 
18
- export const getElementHandler = (type: act.ElementType): null | ThreeNodeHandler<Object3D> => {
19
- if (typeof type === 'string' || typeof type === 'symbol') {
20
- const handler = handlers.get(type);
21
- if (handler)
22
- return handler;
23
- }
24
- return null;
56
+ type DrawableProps = {
57
+ geometry?: three.BufferGeometry,
58
+ material?: three.Material | three.Material[]
59
+ }
60
+ type LightProps = {
61
+ color?: three.Color,
62
+ intensity?: number,
25
63
  }
64
+ type SpriteProps = {
65
+ center?: three.Vector2Like,
66
+ } & DrawableProps;
67
+ type CameraProps<T extends three.Camera> =
68
+ & T extends three.PerspectiveCamera ? {
69
+ aspect?: number,
70
+ far?: number,
71
+ near?: number,
72
+ focus?: number,
73
+ fov?: number,
74
+ zoom?: number,
75
+ } : {}
76
+ & T extends three.OrthographicCamera ? {
77
+ far?: number,
78
+ near?: number,
26
79
 
27
- export type Newable<T> = { new (): T; };
28
-
29
- export const addSimpleElement = <T extends Object3D>(type: string | symbol, ElementClass: Newable<T>) => {
30
- registerElementHandler<T>({
31
- type,
32
- create() {
33
- return new ElementClass();
34
- },
35
- setProps(instance, prevProps, nextProps) {
36
- setProps(instance, nextProps as Object3DProps<T>);
37
- },
38
- })
80
+ top?: number,
81
+ right?: number,
82
+ left?: number,
83
+ bottom?: number,
84
+
85
+ zoom?: number,
86
+ } : {}
87
+
88
+ type BuiltinRegistry = {
89
+ [Property in keyof THREE_CLASS_MAP]: PropsFromClass<InstanceType<THREE_CLASS_MAP[Property]>>
39
90
  }
40
91
 
41
- const elementMap = {
42
- mesh: Mesh,
43
- points: Points,
44
- group: Group,
45
- scene: Scene,
46
- sprite: Sprite,
47
- skinnedMesh: SkinnedMesh,
92
+ /**
93
+ * Users can write:
94
+ * ```ts
95
+ * declare module "@lukekaalim/act-three" {
96
+ * interface ExtendedPrimitives {
97
+ * MyPrimitive: { myProps: boolean }
98
+ * }
99
+ * }
100
+ * ```
101
+ * to add a new type definition for an element,
102
+ * and then supply an implementation via:
103
+ *
104
+ * ```ts
105
+ * registry
106
+ * .registerPrimitive(
107
+ * 'MyPrimitive',
108
+ * () => new MyPrimitive(),
109
+ * (primitive, props) => { primitive.myProps = props.myProps; })
110
+ * );
111
+ *
112
+ * ```
113
+ */
114
+ export interface ExtendedPrimitives {}
48
115
 
49
- pointLight: PointLight,
50
- directionalLight: DirectionalLight,
116
+ type AllPrimitives = ExtendedPrimitives & BuiltinRegistry;
51
117
 
52
- line: Line,
53
- lineLoop: LineLoop,
54
- lineSegments: LineSegments,
118
+ export const registry = createPrimitiveRegistry<AllPrimitives, three.Object3D>();
119
+ /**
120
+ * Type checked act-three primitive elements.
121
+ */
122
+ export const a3 = registry.elements;
55
123
 
56
- perspectiveCamera: PerspectiveCamera,
57
- orthographicCamera: OrthographicCamera,
58
- } as const;
59
- type ElementMap = typeof elementMap;
60
124
 
61
- for (const key in elementMap) {
62
- addSimpleElement(key, elementMap[key as keyof ElementMap] as any)
63
- }
125
+ type THREE_CLASS_MAP = typeof THREE_OBJECT3D_CLASS_MAP;
126
+ const THREE_OBJECT3D_CLASS_MAP = {
127
+ mesh: three.Mesh,
128
+ instancedMesh: three.InstancedMesh,
129
+ skinnedMesh: three.SkinnedMesh,
130
+
131
+ points: three.Points,
132
+
133
+ object: three.Object3D,
134
+ group: three.Group,
135
+ scene: three.Scene,
136
+
137
+ sprite: three.Sprite,
138
+
139
+ pointLight: three.PointLight,
140
+ directionalLight: three.DirectionalLight,
64
141
 
65
- type ElementNodes = {
66
- readonly [key in keyof ElementMap]: Component<Object3DProps<InstanceType<ElementMap[key]>>>
67
- };
142
+ line: three.Line,
143
+ lineLoop: three.LineLoop,
144
+ lineSegments: three.LineSegments,
68
145
 
69
- export const node: ElementNodes = Object.fromEntries(Object.keys(elementMap).map(k => [k, k as ElementType])) as ElementNodes;
146
+ perspectiveCamera: three.PerspectiveCamera,
147
+ orthographicCamera: three.OrthographicCamera,
148
+ cubeCamera: three.CubeCamera,
149
+ }
150
+
151
+ registry
152
+ .addGlobalCreateHandler((type, props) => {
153
+ const ObjectClass = (THREE_OBJECT3D_CLASS_MAP as any)[type];
154
+ if (ObjectClass) {
155
+ const object = new (ObjectClass as typeof three.Object3D)();
156
+ setProps(object, props as PropsFromClass<three.Object3D>);
157
+ return object;
158
+ }
159
+ console.warn(`I WONT MAKE ${type}`)
160
+ return null;
161
+ })
162
+ .addGlobalUpdateHandler((type, object, next, prev) => {
163
+ setProps(object, next as PropsFromClass<three.Object3D>);
164
+ })
165
+ .registerUnhandledPrimitives(Object.keys(THREE_OBJECT3D_CLASS_MAP) as any[])
package/index.ts CHANGED
@@ -1,4 +1,3 @@
1
- export { three } from './deps.ts';
2
1
  export * from './render.ts';
3
2
  export * from './props.ts';
4
3
  export * from './elements.ts';
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@lukekaalim/act-three",
3
- "main": "mod.ts",
4
- "version": "7.1.1",
3
+ "main": "index.ts",
4
+ "type": "module",
5
+ "version": "8.0.0",
5
6
  "dependencies": {
6
- "@lukekaalim/act": "^4.2.0",
7
- "@lukekaalim/act-backstage": "^3.1.1",
7
+ "@lukekaalim/act": "^4.3.0",
8
+ "@lukekaalim/act-backstage": "^3.2.0",
8
9
  "@lukekaalim/act-recon": "^4.0.0",
9
- "@lukekaalim/act-web": "^5.1.0",
10
+ "@lukekaalim/act-web": "^5.2.0",
10
11
  "@types/three": ">= 0.185.0"
11
12
  },
12
13
  "peerDependencies": {
package/props.ts CHANGED
@@ -1,39 +1,92 @@
1
- import { Object3D } from "three";
2
- import { act, three } from "./deps";
1
+ import * as three from 'three';
2
+ import * as act from '@lukekaalim/act';
3
+ import { PropsFromClass } from "./elements";
3
4
 
4
- export type Object3DProps<T extends Object3D> = {
5
- position?: three.Vector3,
6
- scale?: three.Vector3,
7
- quaternion?: three.Quaternion,
8
- rotation?: three.Euler,
9
5
 
10
- ref?: act.ReadonlyRef<null | three.Object3D>,
11
- }
12
- & (T extends three.Mesh ? { geometry?: three.BufferGeometry, material?: three.Material } : {})
13
- & (T extends three.Scene ? { background?: three.Color } : {})
14
-
15
- export const setProps = <T extends Object3D>(object: T, props: Object3DProps<T>) => {
6
+ export const setProps = (object: three.Object3D, props: PropsFromClass<three.Object3D>) => {
16
7
  if (props.position)
17
- object.position.copy(props.position as three.Vector3);
8
+ object.position.copy(props.position);
18
9
  if (props.scale)
19
- object.scale.copy(props.scale as three.Vector3);
10
+ object.scale.copy(props.scale);
20
11
  if (props.quaternion)
21
- object.quaternion.copy(props.quaternion as three.Quaternion);
12
+ object.quaternion.copy(props.quaternion);
22
13
  if (props.rotation)
23
- object.rotation.copy(props.rotation as three.Euler);
14
+ object.rotation.copy(props.rotation);
15
+
16
+ if (props.name !== undefined)
17
+ object.name = props.name;
18
+ if (props.layers)
19
+ object.layers = props.layers;
20
+
21
+ if (props.visible !== undefined)
22
+ object.visible = props.visible;
23
+ if (props.static !== undefined)
24
+ object.static = props.static;
25
+ if (props.renderOrder !== undefined)
26
+ object.renderOrder = props.renderOrder;
27
+ if (props.receiveShadow !== undefined)
28
+ object.receiveShadow = props.receiveShadow;
29
+ if (props.castShadow !== undefined)
30
+ object.castShadow = props.castShadow;
31
+ if (props.frustumCulled !== undefined)
32
+ object.frustumCulled = props.frustumCulled;
33
+
34
+ if (props.animations)
35
+ object.animations = props.animations;
36
+ if (props.userData)
37
+ object.userData = props.userData;
38
+
24
39
  if (props.ref)
25
- (props.ref as Record<string, unknown>).current = object;
40
+ props.ref.current = object;
26
41
 
27
- if (object instanceof three.Mesh) {
28
- const meshProps = props as Object3DProps<three.Mesh>;
42
+ if (object instanceof three.Mesh || object instanceof three.Points || object instanceof three.Line) {
43
+ const meshProps = props as PropsFromClass<three.Mesh | three.Points | three.Line>;
29
44
  object.geometry = meshProps.geometry;
30
45
  object.material = meshProps.material;
31
46
  }
47
+
32
48
  if (object instanceof three.PerspectiveCamera) {
49
+ const perspectiveCameraProps = props as PropsFromClass<three.PerspectiveCamera>;
50
+ if (perspectiveCameraProps.aspect)
51
+ object.aspect = perspectiveCameraProps.aspect;
52
+ if (perspectiveCameraProps.fov)
53
+ object.fov = perspectiveCameraProps.fov;
54
+
55
+ if (perspectiveCameraProps.far)
56
+ object.far = perspectiveCameraProps.far;
57
+ if (perspectiveCameraProps.near)
58
+ object.near = perspectiveCameraProps.near;
59
+
60
+ if (perspectiveCameraProps.zoom)
61
+ object.zoom = perspectiveCameraProps.zoom;
62
+
33
63
  object.updateProjectionMatrix();
34
64
  }
35
65
  if (object instanceof three.Scene) {
36
- const sceneProps = props as Object3DProps<three.Scene>;
37
- object.background = (sceneProps.background as three.Color);
66
+ const sceneProps = props as PropsFromClass<three.Scene>;
67
+ if (sceneProps.background !== undefined)
68
+ object.background = sceneProps.background;
69
+ if (sceneProps.environment !== undefined)
70
+ object.environment = sceneProps.environment;
71
+
72
+ if (sceneProps.fog !== undefined)
73
+ object.fog = sceneProps.fog;
74
+ if (sceneProps.overrideMaterial !== undefined)
75
+ object.overrideMaterial = sceneProps.overrideMaterial;
76
+ }
77
+
78
+ if (object instanceof three.Light) {
79
+ const lightProps = props as PropsFromClass<three.Light>;
80
+ if (lightProps.color)
81
+ object.color.copy(lightProps.color)
82
+ if (lightProps.intensity !== undefined)
83
+ object.intensity = lightProps.intensity;
84
+ }
85
+
86
+ if (object instanceof three.Sprite) {
87
+ const spriteProps = props as PropsFromClass<three.Sprite>;
88
+ if (spriteProps.center)
89
+ object.center.copy(spriteProps.center)
38
90
  }
39
91
  };
92
+
package/deps.ts DELETED
@@ -1,3 +0,0 @@
1
- export * as act from '@lukekaalim/act/mod.ts';
2
- export * as recon from '@lukekaalim/act-recon/mod.ts';
3
- export * as three from "three";