lunchboxjs 0.1.4017 → 0.2.1001-beta.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/dist/lunchboxjs.js +1666 -1659
- package/dist/lunchboxjs.min.js +1 -1
- package/dist/lunchboxjs.module.js +1620 -1659
- package/extras/OrbitControlsWrapper.vue +12 -4
- package/package.json +12 -4
- package/src/components/LunchboxEventHandlers.tsx +239 -0
- package/src/components/LunchboxWrapper/LunchboxScene.tsx +8 -0
- package/src/components/LunchboxWrapper/LunchboxWrapper.tsx +300 -0
- package/src/components/LunchboxWrapper/prepCanvas.ts +27 -21
- package/src/components/LunchboxWrapper/resizeCanvas.ts +13 -12
- package/src/components/autoGeneratedComponents.ts +1 -1
- package/src/components/index.ts +2 -4
- package/src/core/createNode.ts +2 -18
- package/src/core/ensure.ts +9 -196
- package/src/core/extend.ts +1 -1
- package/src/core/index.ts +0 -2
- package/src/core/instantiateThreeObject/index.ts +7 -2
- package/src/core/instantiateThreeObject/processProps.ts +1 -1
- package/src/core/interaction.ts +55 -0
- package/src/core/minidom.ts +5 -9
- package/src/core/update.ts +74 -51
- package/src/core/updateObjectProp.ts +5 -14
- package/src/index.ts +248 -76
- package/src/keys.ts +25 -0
- package/src/nodeOps/createElement.ts +2 -5
- package/src/nodeOps/index.ts +70 -57
- package/src/nodeOps/insert.ts +11 -32
- package/src/nodeOps/remove.ts +1 -17
- package/src/types.ts +34 -10
- package/src/utils/index.ts +1 -4
- package/dist/.DS_Store +0 -0
- package/src/.DS_Store +0 -0
- package/src/components/LunchboxWrapper/LunchboxWrapper.ts +0 -312
- package/src/components/catalogue.ts +0 -3
- package/src/core/.DS_Store +0 -0
- package/src/core/allNodes.ts +0 -4
- package/src/core/interaction/index.ts +0 -102
- package/src/core/interaction/input.ts +0 -4
- package/src/core/interaction/interactables.ts +0 -14
- package/src/core/interaction/setupAutoRaycaster.ts +0 -224
- package/src/core/start.ts +0 -11
|
@@ -5,35 +5,39 @@ import { resizeCanvas } from './resizeCanvas'
|
|
|
5
5
|
|
|
6
6
|
const getInnerDimensions = (node: Element) => {
|
|
7
7
|
const computedStyle = getComputedStyle(node)
|
|
8
|
-
const width =
|
|
9
|
-
|
|
8
|
+
const width =
|
|
9
|
+
node.clientWidth -
|
|
10
|
+
parseFloat(computedStyle.paddingLeft) -
|
|
11
|
+
parseFloat(computedStyle.paddingRight)
|
|
12
|
+
const height =
|
|
13
|
+
node.clientHeight -
|
|
14
|
+
parseFloat(computedStyle.paddingTop) -
|
|
15
|
+
parseFloat(computedStyle.paddingBottom)
|
|
10
16
|
return { width, height }
|
|
11
17
|
}
|
|
12
18
|
|
|
13
19
|
export const prepCanvas = (
|
|
14
20
|
container: Ref<MiniDom.RendererDomNode | undefined>,
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
camera: THREE.Camera,
|
|
22
|
+
renderer: THREE.Renderer,
|
|
23
|
+
scene: THREE.Scene,
|
|
17
24
|
sizePolicy?: Lunch.SizePolicy
|
|
18
25
|
) => {
|
|
19
26
|
const containerElement = container.value?.domElement
|
|
20
27
|
if (!containerElement) throw new Error('missing container')
|
|
21
28
|
|
|
22
|
-
// save
|
|
23
|
-
// ...and size element
|
|
29
|
+
// save and size element
|
|
24
30
|
const resizeCanvasByPolicy = () => {
|
|
25
|
-
if (sizePolicy ===
|
|
26
|
-
const dims = getInnerDimensions(containerElement)
|
|
27
|
-
resizeCanvas(dims.width, dims.height)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
};
|
|
32
|
-
resizeCanvasByPolicy();
|
|
31
|
+
if (sizePolicy === 'container') {
|
|
32
|
+
const dims = getInnerDimensions(containerElement)
|
|
33
|
+
resizeCanvas(camera, renderer, scene, dims.width, dims.height)
|
|
34
|
+
} else resizeCanvas(camera, renderer, scene)
|
|
35
|
+
}
|
|
36
|
+
resizeCanvasByPolicy()
|
|
33
37
|
|
|
34
38
|
// attach listeners
|
|
35
|
-
|
|
36
|
-
resizeCanvasByPolicy()
|
|
39
|
+
let observer = new ResizeObserver(() => {
|
|
40
|
+
resizeCanvasByPolicy()
|
|
37
41
|
})
|
|
38
42
|
// window.addEventListener('resize', resizeCanvas)
|
|
39
43
|
if (containerElement) {
|
|
@@ -41,9 +45,11 @@ export const prepCanvas = (
|
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
// cleanup
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
return {
|
|
49
|
+
dispose() {
|
|
50
|
+
if (containerElement) {
|
|
51
|
+
observer.unobserve(containerElement)
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
}
|
|
49
55
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { ensuredCamera, ensureRenderer, ensuredScene } from '../../core'
|
|
2
1
|
import { toRaw } from 'vue'
|
|
3
2
|
|
|
4
|
-
export const resizeCanvas = (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
export const resizeCanvas = (
|
|
4
|
+
camera: THREE.Camera,
|
|
5
|
+
renderer: THREE.Renderer,
|
|
6
|
+
scene: THREE.Scene,
|
|
7
|
+
width?: number,
|
|
8
|
+
height?: number
|
|
9
|
+
) => {
|
|
9
10
|
// ignore if no element
|
|
10
11
|
if (!renderer?.domElement || !scene || !camera) return
|
|
11
12
|
|
|
@@ -15,12 +16,12 @@ export const resizeCanvas = (width?: number, height?: number) => {
|
|
|
15
16
|
// update camera
|
|
16
17
|
const aspect = width / height
|
|
17
18
|
if (camera.type?.toLowerCase() === 'perspectivecamera') {
|
|
18
|
-
const perspectiveCamera = camera
|
|
19
|
+
const perspectiveCamera = camera as THREE.PerspectiveCamera
|
|
19
20
|
perspectiveCamera.aspect = aspect
|
|
20
21
|
perspectiveCamera.updateProjectionMatrix()
|
|
21
22
|
} else if (camera.type?.toLowerCase() === 'orthographiccamera') {
|
|
22
|
-
//
|
|
23
|
-
const orthoCamera = camera
|
|
23
|
+
// TODO: ortho camera update
|
|
24
|
+
const orthoCamera = camera as THREE.OrthographicCamera
|
|
24
25
|
const heightInTermsOfWidth = height / width
|
|
25
26
|
orthoCamera.top = heightInTermsOfWidth * 10
|
|
26
27
|
orthoCamera.bottom = -heightInTermsOfWidth * 10
|
|
@@ -28,13 +29,13 @@ export const resizeCanvas = (width?: number, height?: number) => {
|
|
|
28
29
|
orthoCamera.left = -10
|
|
29
30
|
orthoCamera.updateProjectionMatrix()
|
|
30
31
|
} else {
|
|
31
|
-
|
|
32
|
+
// TODO: non-ortho or perspective camera
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
// update canvas
|
|
35
36
|
renderer.setSize(width, height)
|
|
36
37
|
// render immediately so there's no flicker
|
|
37
|
-
if (scene && camera
|
|
38
|
-
renderer.render(toRaw(scene), toRaw(camera
|
|
38
|
+
if (scene && camera) {
|
|
39
|
+
renderer.render(toRaw(scene), toRaw(camera))
|
|
39
40
|
}
|
|
40
41
|
}
|
|
@@ -106,6 +106,7 @@ export const autoGeneratedComponents = [
|
|
|
106
106
|
'group',
|
|
107
107
|
'catmullRomCurve3',
|
|
108
108
|
'points',
|
|
109
|
+
'raycaster',
|
|
109
110
|
|
|
110
111
|
// helpers
|
|
111
112
|
'cameraHelper',
|
|
@@ -157,7 +158,6 @@ export const autoGeneratedComponents = [
|
|
|
157
158
|
|
|
158
159
|
|
|
159
160
|
// misc
|
|
160
|
-
raycaster: RaycasterProps
|
|
161
161
|
vector2: Vector2Props
|
|
162
162
|
vector3: Vector3Props
|
|
163
163
|
vector4: Vector4Props
|
package/src/components/index.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { h, defineComponent } from 'vue'
|
|
2
2
|
import { LunchboxWrapper } from './LunchboxWrapper/LunchboxWrapper'
|
|
3
3
|
import { autoGeneratedComponents } from './autoGeneratedComponents'
|
|
4
|
+
import type { Lunch } from '../types'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
export { catalogue }
|
|
7
|
-
|
|
8
|
-
export const lunchboxDomComponentNames = ['canvas', 'div', 'LunchboxWrapper']
|
|
6
|
+
export const catalogue: Lunch.Catalogue = {}
|
|
9
7
|
|
|
10
8
|
// component creation utility
|
|
11
9
|
const createComponent = (tag: string) =>
|
package/src/core/createNode.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { isLunchboxRootNode } from '../utils'
|
|
2
|
-
import { instantiateThreeObject, MiniDom
|
|
3
|
-
import { Lunch } from '..'
|
|
4
|
-
import { ensuredCamera } from './ensure'
|
|
2
|
+
import { instantiateThreeObject, MiniDom } from '.'
|
|
3
|
+
import type { Lunch } from '..'
|
|
5
4
|
|
|
6
5
|
/** Create a new Lunchbox comment node. */
|
|
7
6
|
export function createCommentNode(options: Partial<Lunch.CommentMeta> = {}) {
|
|
@@ -59,13 +58,6 @@ export function createNode<T extends object = THREE.Object3D>(
|
|
|
59
58
|
})
|
|
60
59
|
|
|
61
60
|
if (node.type && !isLunchboxRootNode(node) && !node.instance) {
|
|
62
|
-
// if (node.type.includes('Camera')) {
|
|
63
|
-
// console.log(node.type, {
|
|
64
|
-
// ...node.props,
|
|
65
|
-
// ...props,
|
|
66
|
-
// })
|
|
67
|
-
// console.trace()
|
|
68
|
-
// }
|
|
69
61
|
node.instance = instantiateThreeObject({
|
|
70
62
|
...node,
|
|
71
63
|
props: {
|
|
@@ -75,13 +67,5 @@ export function createNode<T extends object = THREE.Object3D>(
|
|
|
75
67
|
})
|
|
76
68
|
}
|
|
77
69
|
|
|
78
|
-
// TODO: these manual overrides are a bit brittle - replace?
|
|
79
|
-
if (node.type?.toLowerCase() === 'scene') {
|
|
80
|
-
// manually set scene override
|
|
81
|
-
ensuredScene.value = node as Lunch.Node<THREE.Scene>
|
|
82
|
-
} else if (node.type?.toLowerCase().endsWith('camera')) {
|
|
83
|
-
ensuredCamera.value = node as Lunch.Node<THREE.Camera>
|
|
84
|
-
}
|
|
85
|
-
|
|
86
70
|
return node
|
|
87
71
|
}
|
package/src/core/ensure.ts
CHANGED
|
@@ -1,203 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { computed, reactive, ref, WritableComputedRef } from 'vue'
|
|
4
|
-
import { Lunch } from '..'
|
|
1
|
+
import { ComputedRef, inject } from 'vue'
|
|
2
|
+
import * as Keys from '../keys'
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export const rootUuid = 'LUNCHBOX_ROOT'
|
|
9
|
-
export let lunchboxRootNode: MiniDom.RendererRootNode
|
|
10
|
-
export function ensureRootNode(options: Partial<Lunch.RootMeta> = {}) {
|
|
11
|
-
if (!lunchboxRootNode) {
|
|
12
|
-
lunchboxRootNode = new MiniDom.RendererRootNode(options)
|
|
13
|
-
}
|
|
14
|
-
return lunchboxRootNode
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// This is used in `buildEnsured` below and `LunchboxWrapper`
|
|
18
|
-
/** Search the overrides record and the node tree for a node in the given types */
|
|
19
|
-
export function tryGetNodeWithInstanceType<T extends THREE.Object3D>(
|
|
20
|
-
pascalCaseTypes: string | string[]
|
|
21
|
-
) {
|
|
22
|
-
if (!Array.isArray(pascalCaseTypes)) {
|
|
23
|
-
pascalCaseTypes = [pascalCaseTypes]
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// default to override if we have one
|
|
27
|
-
for (let singleType of pascalCaseTypes) {
|
|
28
|
-
if (overrides[singleType]) return overrides[singleType] as Lunch.Node<T>
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// look for auto-created node
|
|
32
|
-
for (let singleType of pascalCaseTypes) {
|
|
33
|
-
const found =
|
|
34
|
-
autoCreated[singleType] ||
|
|
35
|
-
allNodes.find(
|
|
36
|
-
(node) =>
|
|
37
|
-
(node as MiniDom.RendererBaseNode).type?.toLowerCase() ===
|
|
38
|
-
singleType.toLowerCase()
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
// cancel if found example is marked !isDefault
|
|
42
|
-
if (
|
|
43
|
-
isMinidomNode(found) &&
|
|
44
|
-
(found.props['is-default'] === false ||
|
|
45
|
-
!found.props['isDefault'] === false)
|
|
46
|
-
) {
|
|
47
|
-
return null
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// if we have one, save and return
|
|
51
|
-
if (found) {
|
|
52
|
-
const createdAsNode = found as MiniDom.RendererStandardNode<T>
|
|
53
|
-
autoCreated[singleType] = createdAsNode
|
|
54
|
-
return createdAsNode
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return null
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// GENERIC ENSURE FUNCTION
|
|
62
|
-
// ====================
|
|
63
|
-
// Problem:
|
|
64
|
-
// I want to make sure an object of type Xyz exists in my Lunchbox app.
|
|
65
|
-
// If it doesn't exist, I want to create it and add it to the root node.
|
|
66
|
-
//
|
|
67
|
-
// Solution:
|
|
68
|
-
// export const ensuredXyz = buildEnsured<Xyz>('Xyz', 'FALLBACK_XYZ')
|
|
69
|
-
//
|
|
70
|
-
// Now in other components, you can do both:
|
|
71
|
-
// import { ensuredXyz }
|
|
72
|
-
// ensuredXyz.value (...)
|
|
73
|
-
// and:
|
|
74
|
-
// ensuredXyz.value = ...
|
|
75
|
-
export const autoCreated: Record<string, Lunch.Node | null> = reactive({})
|
|
76
|
-
export const overrides: Record<string, Lunch.Node | null> = reactive({})
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Build a computed ensured value with a getter and setter.
|
|
80
|
-
* @param pascalCaseTypes List of types this can be. Will autocreate first type if array provided.
|
|
81
|
-
* @param fallbackUuid Fallback UUID to use.
|
|
82
|
-
* @param props Props to pass to autocreated element
|
|
83
|
-
* @returns Computed getter/setter for ensured object.
|
|
84
|
-
*/
|
|
85
|
-
function buildEnsured<T extends THREE.Object3D>(
|
|
86
|
-
pascalCaseTypes: string | string[],
|
|
87
|
-
fallbackUuid: string,
|
|
88
|
-
props: Record<string, any> = {},
|
|
89
|
-
callback: ((node: MiniDom.RendererStandardNode<T>) => void) | null = null
|
|
90
|
-
) {
|
|
91
|
-
// make sure we've got an array
|
|
92
|
-
if (!Array.isArray(pascalCaseTypes)) {
|
|
93
|
-
pascalCaseTypes = [pascalCaseTypes]
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// add type for autoCreated and overrides
|
|
97
|
-
for (let singleType of pascalCaseTypes) {
|
|
98
|
-
if (!autoCreated[singleType]) {
|
|
99
|
-
autoCreated[singleType] = null
|
|
100
|
-
}
|
|
101
|
-
if (!overrides[singleType]) {
|
|
102
|
-
overrides[singleType] = null
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return computed({
|
|
107
|
-
get(): MiniDom.RendererStandardNode<T> {
|
|
108
|
-
// try to get existing type
|
|
109
|
-
const existing = tryGetNodeWithInstanceType<T>(
|
|
110
|
-
pascalCaseTypes as string[]
|
|
111
|
-
)
|
|
112
|
-
if (existing) return existing
|
|
113
|
-
|
|
114
|
-
// otherwise, create a new node
|
|
115
|
-
const root = ensureRootNode()
|
|
116
|
-
const node = createNode<T>({
|
|
117
|
-
type: pascalCaseTypes[0],
|
|
118
|
-
uuid: fallbackUuid,
|
|
119
|
-
props,
|
|
120
|
-
})
|
|
121
|
-
root.addChild(node)
|
|
122
|
-
autoCreated[pascalCaseTypes[0]] = node
|
|
123
|
-
if (callback) {
|
|
124
|
-
callback(node)
|
|
125
|
-
}
|
|
126
|
-
return node
|
|
127
|
-
},
|
|
128
|
-
set(val: MiniDom.RendererStandardNode<T>) {
|
|
129
|
-
const t = val.type ?? ''
|
|
130
|
-
const pascalType = t[0].toUpperCase() + t.slice(1)
|
|
131
|
-
overrides[pascalType] = val
|
|
132
|
-
},
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ENSURE CAMERA
|
|
137
|
-
// ====================
|
|
138
|
-
export const fallbackCameraUuid = 'FALLBACK_CAMERA'
|
|
139
|
-
export const defaultCamera = buildEnsured(
|
|
140
|
-
['PerspectiveCamera', 'OrthographicCamera'],
|
|
141
|
-
fallbackCameraUuid,
|
|
142
|
-
{ args: [45, 0.5625, 1, 1000] }
|
|
143
|
-
) as unknown as WritableComputedRef<Lunch.Node<THREE.Camera>>
|
|
144
|
-
/** Special value to be changed ONLY in `LunchboxWrapper`.
|
|
145
|
-
* Functions waiting for a Camera need to wait for this to be true. */
|
|
146
|
-
export const cameraReady = ref(false)
|
|
147
|
-
|
|
148
|
-
export const ensuredCamera = computed<Lunch.Node<THREE.Camera> | null>({
|
|
149
|
-
get() {
|
|
150
|
-
return (
|
|
151
|
-
cameraReady.value ? (defaultCamera.value as any) : (null as any)
|
|
152
|
-
) as any
|
|
153
|
-
},
|
|
154
|
-
set(val: any) {
|
|
155
|
-
const t = val.type ?? ''
|
|
156
|
-
const pascalType = t[0].toUpperCase() + t.slice(1)
|
|
157
|
-
overrides[pascalType] = val as any
|
|
158
|
-
},
|
|
159
|
-
})
|
|
4
|
+
export const ensuredCamera = <T extends THREE.Camera = THREE.Camera>() =>
|
|
5
|
+
inject<ComputedRef<T>>(Keys.appCameraKey)!
|
|
160
6
|
|
|
161
7
|
// ENSURE RENDERER
|
|
162
8
|
// ====================
|
|
163
|
-
export const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
['WebGLRenderer'], //, 'CSS2DRenderer', 'CSS3DRenderer', 'SVGRenderer'],
|
|
167
|
-
fallbackRendererUuid,
|
|
168
|
-
{}
|
|
169
|
-
) as unknown as WritableComputedRef<Lunch.Node<THREE.WebGLRenderer>>
|
|
170
|
-
/** Special value to be changed ONLY in `LunchboxWrapper`.
|
|
171
|
-
* Functions waiting for a Renderer need to wait for this to be true. */
|
|
172
|
-
export const rendererReady = ref(false)
|
|
173
|
-
|
|
174
|
-
export const ensureRenderer = computed<Lunch.Node<THREE.WebGLRenderer> | null>({
|
|
175
|
-
get() {
|
|
176
|
-
return (
|
|
177
|
-
rendererReady.value ? (ensuredRenderer.value as any) : (null as any)
|
|
178
|
-
) as any
|
|
179
|
-
},
|
|
180
|
-
set(val: any) {
|
|
181
|
-
const t = val.type ?? ''
|
|
182
|
-
const pascalType = t[0].toUpperCase() + t.slice(1)
|
|
183
|
-
overrides[pascalType] = val as any
|
|
184
|
-
},
|
|
185
|
-
})
|
|
9
|
+
export const ensureRenderer = <
|
|
10
|
+
T extends THREE.Renderer = THREE.WebGLRenderer
|
|
11
|
+
>() => inject<ComputedRef<T>>(Keys.appRenderersKey)
|
|
186
12
|
|
|
187
13
|
// ENSURE SCENE
|
|
188
14
|
// ====================
|
|
189
|
-
export const
|
|
190
|
-
|
|
191
|
-
'Scene',
|
|
192
|
-
fallbackSceneUuid
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
// ENSURE AUTO-RAYCASTER
|
|
196
|
-
export const autoRaycasterUuid = 'AUTO_RAYCASTER'
|
|
197
|
-
// `unknown` is intentional here - we need to typecast the node since Raycaster isn't an Object3D
|
|
198
|
-
export const ensuredRaycaster = buildEnsured(
|
|
199
|
-
'Raycaster',
|
|
200
|
-
autoRaycasterUuid,
|
|
201
|
-
{},
|
|
202
|
-
(node) => setupAutoRaycaster(node as unknown as Lunch.Node<THREE.Raycaster>)
|
|
203
|
-
) as unknown as WritableComputedRef<Lunch.Node<THREE.Raycaster>>
|
|
15
|
+
export const ensuredScene = <T extends THREE.Scene = THREE.Scene>() =>
|
|
16
|
+
inject<ComputedRef<T>>(Keys.appSceneKey)
|
package/src/core/extend.ts
CHANGED
package/src/core/index.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
export * from './allNodes'
|
|
2
1
|
export * from './createNode'
|
|
3
2
|
export * from './ensure'
|
|
4
3
|
export * from './interaction'
|
|
5
4
|
export * from './extend'
|
|
6
5
|
export * from './instantiateThreeObject'
|
|
7
6
|
export * from './minidom'
|
|
8
|
-
export * from './start'
|
|
9
7
|
export * from './update'
|
|
10
8
|
export * from './updateObjectProp'
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { catalogue } from '../../components'
|
|
2
2
|
import * as THREE from 'three'
|
|
3
3
|
import { processPropAsArray } from './processProps'
|
|
4
|
-
import { Lunch } from '../..'
|
|
4
|
+
import type { Lunch } from '../..'
|
|
5
5
|
|
|
6
6
|
export function instantiateThreeObject<T>(node: Lunch.StandardMeta<T>) {
|
|
7
7
|
if (!node.type) return null
|
|
8
8
|
|
|
9
9
|
// what class will we be instantiating?
|
|
10
10
|
const uppercaseType = node.type[0].toUpperCase() + node.type.slice(1)
|
|
11
|
-
const
|
|
11
|
+
const translatedType = uppercaseType.replace(/Lunchbox$/, '')
|
|
12
|
+
const targetClass =
|
|
13
|
+
catalogue[node.type] ||
|
|
14
|
+
(THREE as any)[uppercaseType] ||
|
|
15
|
+
catalogue[translatedType] ||
|
|
16
|
+
(THREE as any)[translatedType]
|
|
12
17
|
if (!targetClass)
|
|
13
18
|
throw `${uppercaseType} is not part of the THREE namespace! Did you forget to extend? import {extend} from 'lunchbox'; extend({app, YourComponent, ...})`
|
|
14
19
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Ref } from 'vue'
|
|
2
|
+
import type { Lunch } from '..'
|
|
3
|
+
|
|
4
|
+
/** Add an event listener to the given node. Also creates the event teardown function and any necessary raycaster/interaction dictionary updates. */
|
|
5
|
+
export function addEventListener({
|
|
6
|
+
node,
|
|
7
|
+
key,
|
|
8
|
+
interactables,
|
|
9
|
+
value,
|
|
10
|
+
}: {
|
|
11
|
+
node: Lunch.Node
|
|
12
|
+
key: Lunch.EventKey
|
|
13
|
+
interactables: Ref<Lunch.Node[]>
|
|
14
|
+
value: Lunch.EventCallback
|
|
15
|
+
}) {
|
|
16
|
+
// create new records for this key if needed
|
|
17
|
+
if (!node.eventListeners[key]) {
|
|
18
|
+
node.eventListeners[key] = []
|
|
19
|
+
}
|
|
20
|
+
if (!node.eventListenerRemoveFunctions[key]) {
|
|
21
|
+
node.eventListenerRemoveFunctions[key] = []
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// add event listener
|
|
25
|
+
node.eventListeners[key].push(value)
|
|
26
|
+
|
|
27
|
+
// if we need it, let's get/create the main raycaster
|
|
28
|
+
if (interactionsRequiringRaycaster.includes(key)) {
|
|
29
|
+
if (node.instance && !interactables.value.includes(node)) {
|
|
30
|
+
// add to interactables
|
|
31
|
+
interactables.value.push(node)
|
|
32
|
+
node.eventListenerRemoveFunctions[key].push(() => {
|
|
33
|
+
// remove from interactables
|
|
34
|
+
const idx = interactables.value.indexOf(node)
|
|
35
|
+
if (idx !== -1) {
|
|
36
|
+
interactables.value.splice(idx, 1)
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return node
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const interactionsRequiringRaycaster = [
|
|
46
|
+
'onClick',
|
|
47
|
+
'onPointerUp',
|
|
48
|
+
'onPointerDown',
|
|
49
|
+
'onPointerOver',
|
|
50
|
+
'onPointerOut',
|
|
51
|
+
'onPointerEnter',
|
|
52
|
+
'onPointerLeave',
|
|
53
|
+
'onPointerMove',
|
|
54
|
+
// 'onPointerMissed',
|
|
55
|
+
]
|
package/src/core/minidom.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { v4 as createUuid } from 'uuid'
|
|
2
|
-
import {
|
|
3
|
-
import { Lunch } from '..'
|
|
2
|
+
import type { Lunch } from '..'
|
|
4
3
|
|
|
5
4
|
// MiniDom recreates DOM node properties and methods.
|
|
6
5
|
// Since Vue 3 is a DOM-first framework, many of its nodeOps depend on
|
|
@@ -17,7 +16,7 @@ export namespace MiniDom {
|
|
|
17
16
|
this.minidomType = 'MinidomBaseNode'
|
|
18
17
|
this.uuid = options?.uuid ?? createUuid()
|
|
19
18
|
|
|
20
|
-
allNodes.push(this)
|
|
19
|
+
// allNodes.push(this)
|
|
21
20
|
}
|
|
22
21
|
uuid: Lunch.Uuid
|
|
23
22
|
|
|
@@ -89,10 +88,10 @@ export namespace MiniDom {
|
|
|
89
88
|
/** Drop this node. Removes parent's knowledge of this node
|
|
90
89
|
* and resets this node's internal parent. */
|
|
91
90
|
drop() {
|
|
92
|
-
// remove parent
|
|
93
|
-
this.parentNode = null
|
|
94
91
|
// remove as child
|
|
95
92
|
this.removeAsChildFromAnyParents()
|
|
93
|
+
// remove parent
|
|
94
|
+
this.parentNode = null
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
/** Walk over the entire subtree. Return falsey value in callback to end early. */
|
|
@@ -124,7 +123,7 @@ export namespace MiniDom {
|
|
|
124
123
|
minidomType: MiniDom.NodeType
|
|
125
124
|
|
|
126
125
|
removeAsChildFromAnyParents() {
|
|
127
|
-
|
|
126
|
+
this.parentNode?.removeChild(this)
|
|
128
127
|
}
|
|
129
128
|
}
|
|
130
129
|
|
|
@@ -255,6 +254,3 @@ export namespace MiniDom {
|
|
|
255
254
|
export function isMinidomNode(item: any): item is MiniDom.RendererBaseNode {
|
|
256
255
|
return (item as MiniDom.BaseNode)?.minidomType === 'RendererNode'
|
|
257
256
|
}
|
|
258
|
-
|
|
259
|
-
export const rootNode = new MiniDom.RendererRootNode()
|
|
260
|
-
rootNode.minidomType = 'RootNode'
|