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
package/src/core/update.ts
CHANGED
|
@@ -1,31 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
let frameID: number
|
|
6
|
-
let watchStopHandle: WatchStopHandle
|
|
7
|
-
|
|
8
|
-
export const beforeRender = [] as Lunch.UpdateCallback[]
|
|
9
|
-
export const afterRender = [] as Lunch.UpdateCallback[]
|
|
1
|
+
import type { Lunch } from '..'
|
|
2
|
+
import { inject, toRaw, watch } from 'vue'
|
|
3
|
+
import * as Keys from '../keys'
|
|
10
4
|
|
|
11
5
|
const requestUpdate = (opts: Lunch.UpdateCallbackProperties) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
if (typeof opts.app.config.globalProperties.lunchbox.frameId === 'number') {
|
|
7
|
+
cancelAnimationFrame(opts.app.config.globalProperties.lunchbox.frameId)
|
|
8
|
+
}
|
|
9
|
+
opts.app.config.globalProperties.lunchbox.frameId = requestAnimationFrame(
|
|
10
|
+
() =>
|
|
11
|
+
update({
|
|
12
|
+
app: opts.app,
|
|
13
|
+
renderer: opts.renderer,
|
|
14
|
+
scene: opts.scene,
|
|
15
|
+
camera: opts.camera,
|
|
16
|
+
updateSource: opts.updateSource,
|
|
17
|
+
})
|
|
21
18
|
)
|
|
22
19
|
}
|
|
23
20
|
|
|
24
21
|
export const update: Lunch.UpdateCallback = (opts) => {
|
|
25
22
|
if (opts.updateSource) {
|
|
26
|
-
if (!watchStopHandle) {
|
|
23
|
+
if (!opts.app.config.globalProperties.lunchbox.watchStopHandle) {
|
|
27
24
|
// request next frame only when state changes
|
|
28
|
-
watchStopHandle = watch(
|
|
25
|
+
opts.app.config.globalProperties.lunchbox.watchStopHandle = watch(
|
|
29
26
|
opts.updateSource,
|
|
30
27
|
() => {
|
|
31
28
|
requestUpdate(opts)
|
|
@@ -44,10 +41,8 @@ export const update: Lunch.UpdateCallback = (opts) => {
|
|
|
44
41
|
const { app, renderer, scene, camera } = opts
|
|
45
42
|
|
|
46
43
|
// BEFORE RENDER
|
|
47
|
-
beforeRender.forEach((cb
|
|
48
|
-
|
|
49
|
-
cb(opts)
|
|
50
|
-
}
|
|
44
|
+
app.config.globalProperties.lunchbox.beforeRender.forEach((cb) => {
|
|
45
|
+
cb?.(opts)
|
|
51
46
|
})
|
|
52
47
|
|
|
53
48
|
// RENDER
|
|
@@ -55,56 +50,84 @@ export const update: Lunch.UpdateCallback = (opts) => {
|
|
|
55
50
|
if (app.customRender) {
|
|
56
51
|
app.customRender(opts)
|
|
57
52
|
} else {
|
|
58
|
-
renderer.render(
|
|
53
|
+
renderer.render(
|
|
54
|
+
toRaw(scene),
|
|
55
|
+
// opts.app.config.globalProperties.lunchbox.camera!
|
|
56
|
+
toRaw(camera)
|
|
57
|
+
)
|
|
59
58
|
}
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
// AFTER RENDER
|
|
63
|
-
afterRender.forEach((cb
|
|
64
|
-
|
|
65
|
-
cb(opts)
|
|
66
|
-
}
|
|
62
|
+
app.config.globalProperties.lunchbox.afterRender.forEach((cb) => {
|
|
63
|
+
cb?.(opts)
|
|
67
64
|
})
|
|
68
65
|
}
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
// before render
|
|
68
|
+
// ====================
|
|
69
|
+
// TODO: document
|
|
70
|
+
export const useBeforeRender = () => {
|
|
71
|
+
return {
|
|
72
|
+
onBeforeRender: inject<typeof onBeforeRender>(Keys.onBeforeRenderKey),
|
|
73
|
+
offBeforeRender: inject<typeof offBeforeRender>(
|
|
74
|
+
Keys.offBeforeRenderKey
|
|
75
|
+
),
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
// TODO: document
|
|
80
|
+
export const onBeforeRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
81
|
+
useBeforeRender().onBeforeRender?.(cb, index)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// TODO: document
|
|
78
85
|
export const offBeforeRender = (cb: Lunch.UpdateCallback | number) => {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
useBeforeRender().offBeforeRender?.(cb)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// after render
|
|
90
|
+
// ====================
|
|
91
|
+
// TODO: document
|
|
92
|
+
export const useAfterRender = () => {
|
|
93
|
+
return {
|
|
94
|
+
onAfterRender: inject<typeof onAfterRender>(Keys.onBeforeRenderKey),
|
|
95
|
+
offAfterRender: inject<typeof offAfterRender>(Keys.offBeforeRenderKey),
|
|
84
96
|
}
|
|
85
97
|
}
|
|
86
98
|
|
|
99
|
+
// TODO: document
|
|
87
100
|
export const onAfterRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
88
|
-
|
|
89
|
-
afterRender.push(cb)
|
|
90
|
-
} else {
|
|
91
|
-
afterRender.splice(index, 0, cb)
|
|
92
|
-
}
|
|
101
|
+
useBeforeRender().onBeforeRender?.(cb, index)
|
|
93
102
|
}
|
|
94
103
|
|
|
104
|
+
// TODO: document
|
|
95
105
|
export const offAfterRender = (cb: Lunch.UpdateCallback | number) => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
useBeforeRender().offBeforeRender?.(cb)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// TODO: document
|
|
110
|
+
export const useCancelUpdate = () => {
|
|
111
|
+
const frameId = inject<number>(Keys.frameIdKey)
|
|
112
|
+
return () => {
|
|
113
|
+
if (frameId !== undefined) cancelAnimationFrame(frameId)
|
|
101
114
|
}
|
|
102
115
|
}
|
|
103
116
|
|
|
117
|
+
// TODO: document
|
|
104
118
|
export const cancelUpdate = () => {
|
|
105
|
-
|
|
119
|
+
useCancelUpdate()?.()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// TODO: document
|
|
123
|
+
export const useCancelUpdateSource = () => {
|
|
124
|
+
const cancel = inject<
|
|
125
|
+
Lunch.App['config']['globalProperties']['watchStopHandle']
|
|
126
|
+
>(Keys.watchStopHandleKey)
|
|
127
|
+
return () => cancel?.()
|
|
106
128
|
}
|
|
107
129
|
|
|
130
|
+
// TODO: document
|
|
108
131
|
export const cancelUpdateSource = () => {
|
|
109
|
-
|
|
132
|
+
useCancelUpdateSource()?.()
|
|
110
133
|
}
|
|
@@ -1,34 +1,25 @@
|
|
|
1
1
|
import { isEventKey, isLunchboxStandardNode } from '../utils'
|
|
2
2
|
import { addEventListener } from './interaction'
|
|
3
3
|
import { get, isNumber, set } from 'lodash'
|
|
4
|
-
import { Lunch } from '..'
|
|
5
|
-
|
|
6
|
-
/** Update the given node so all of its props are current. */
|
|
7
|
-
export function updateAllObjectProps({ node }: { node: Lunch.Node }) {
|
|
8
|
-
// set props
|
|
9
|
-
const props = node.props || {}
|
|
10
|
-
let output = node
|
|
11
|
-
Object.keys(props).forEach((key) => {
|
|
12
|
-
output = updateObjectProp({ node, key, value: props[key] })
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
return output
|
|
16
|
-
}
|
|
4
|
+
import type { Lunch } from '..'
|
|
5
|
+
import type { Ref } from 'vue'
|
|
17
6
|
|
|
18
7
|
/** Update a single prop on a given node. */
|
|
19
8
|
export function updateObjectProp({
|
|
20
9
|
node,
|
|
21
10
|
key,
|
|
11
|
+
interactables,
|
|
22
12
|
value,
|
|
23
13
|
}: {
|
|
24
14
|
node: Lunch.Node
|
|
25
15
|
key: string
|
|
16
|
+
interactables: Ref<Lunch.Node[]>
|
|
26
17
|
value: any
|
|
27
18
|
}) {
|
|
28
19
|
// handle and return early if prop is an event
|
|
29
20
|
// (event list from react-three-fiber)
|
|
30
21
|
if (isEventKey(key)) {
|
|
31
|
-
return addEventListener({ node, key, value })
|
|
22
|
+
return addEventListener({ node, key, interactables, value })
|
|
32
23
|
}
|
|
33
24
|
|
|
34
25
|
// update THREE property
|
package/src/index.ts
CHANGED
|
@@ -1,82 +1,54 @@
|
|
|
1
|
-
import { computed, createRenderer, Component, ref, watch } from 'vue'
|
|
2
|
-
import { nodeOps } from './nodeOps'
|
|
3
1
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
computed,
|
|
3
|
+
createRenderer,
|
|
4
|
+
Component,
|
|
5
|
+
inject,
|
|
6
|
+
watch,
|
|
7
|
+
reactive,
|
|
8
|
+
Ref,
|
|
9
|
+
} from 'vue'
|
|
10
|
+
import { createNodeOps } from './nodeOps'
|
|
11
|
+
import {
|
|
7
12
|
ensuredCamera,
|
|
8
13
|
ensureRenderer,
|
|
9
14
|
ensuredScene,
|
|
10
|
-
ensureRootNode,
|
|
11
15
|
extend,
|
|
12
|
-
|
|
13
|
-
mousePos,
|
|
14
|
-
rootUuid,
|
|
16
|
+
MiniDom,
|
|
15
17
|
} from './core'
|
|
16
18
|
import { components } from './components'
|
|
17
19
|
import { Lunch } from './types'
|
|
18
20
|
|
|
19
|
-
export
|
|
20
|
-
export {
|
|
21
|
-
offAfterRender,
|
|
22
|
-
offBeforeRender,
|
|
23
|
-
onAfterRender,
|
|
24
|
-
onBeforeRender,
|
|
25
|
-
onStart,
|
|
26
|
-
} from './core'
|
|
21
|
+
export * from './core'
|
|
27
22
|
export * from './types'
|
|
28
23
|
|
|
24
|
+
import * as Keys from './keys'
|
|
25
|
+
export * from './keys'
|
|
26
|
+
|
|
29
27
|
// Utilities
|
|
30
28
|
export * from './utils/find'
|
|
31
29
|
|
|
32
|
-
/** Useful globals. */
|
|
33
|
-
export const globals = {
|
|
34
|
-
dpr: ref(1),
|
|
35
|
-
inputActive,
|
|
36
|
-
mousePos,
|
|
37
|
-
}
|
|
38
|
-
|
|
39
30
|
/** The current camera. Often easier to use `useCamera` instead of this. */
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
) {
|
|
45
|
-
return watch(
|
|
46
|
-
camera,
|
|
47
|
-
(newVal) => {
|
|
48
|
-
if (!newVal) return
|
|
49
|
-
callback(newVal as unknown as T)
|
|
50
|
-
},
|
|
51
|
-
{ immediate: true }
|
|
52
|
-
)
|
|
53
|
-
}
|
|
31
|
+
// TODO: update docs
|
|
32
|
+
export const camera = ensuredCamera
|
|
33
|
+
// TODO: update docs
|
|
34
|
+
export const useCamera = () => ensuredCamera()
|
|
54
35
|
|
|
55
|
-
/** The current renderer. Often easier to use `useRenderer` instead of this. */
|
|
56
|
-
export const renderer =
|
|
36
|
+
/** The current renderer as a computed value. Often easier to use `useRenderer` instead of this. */
|
|
37
|
+
export const renderer = ensureRenderer
|
|
57
38
|
/** Run a function using the current renderer when it's present. */
|
|
58
|
-
export
|
|
59
|
-
callback: (rend: T) => void
|
|
60
|
-
) {
|
|
61
|
-
return watch(
|
|
62
|
-
renderer,
|
|
63
|
-
(newVal) => {
|
|
64
|
-
if (!newVal) return
|
|
65
|
-
callback(newVal as unknown as T)
|
|
66
|
-
},
|
|
67
|
-
{ immediate: true }
|
|
68
|
-
)
|
|
69
|
-
}
|
|
39
|
+
export const useRenderer = () => ensureRenderer()!
|
|
70
40
|
|
|
71
41
|
/** The current scene. Often easier to use `useScene` instead of this. */
|
|
72
|
-
|
|
42
|
+
// TODO: update docs
|
|
43
|
+
export const scene = ensuredScene
|
|
73
44
|
/** Run a function using the current scene when it's present. */
|
|
45
|
+
// TODO: update docs
|
|
74
46
|
export function useScene(callback: (newScene: THREE.Scene) => void) {
|
|
75
47
|
return watch(
|
|
76
48
|
scene,
|
|
77
49
|
(newVal) => {
|
|
78
50
|
if (!newVal) return
|
|
79
|
-
callback(newVal as
|
|
51
|
+
callback(newVal.value as THREE.Scene)
|
|
80
52
|
},
|
|
81
53
|
{ immediate: true }
|
|
82
54
|
)
|
|
@@ -84,38 +56,216 @@ export function useScene(callback: (newScene: THREE.Scene) => void) {
|
|
|
84
56
|
|
|
85
57
|
// CUSTOM RENDER SUPPORT
|
|
86
58
|
// ====================
|
|
87
|
-
let app: Lunch.App | null = null
|
|
88
|
-
let queuedCustomRenderFunction:
|
|
89
|
-
| ((opts: Lunch.UpdateCallbackProperties) => void)
|
|
90
|
-
| null = null
|
|
91
|
-
|
|
92
59
|
/** Set a custom render function, overriding the Lunchbox app's default render function.
|
|
93
60
|
* Changing this requires the user to manually render their scene.
|
|
61
|
+
*
|
|
62
|
+
* Invokes immediately - use `useCustomRender().setCustomRender`
|
|
63
|
+
* if you need to call somewhere outside of `setup`.
|
|
94
64
|
*/
|
|
95
65
|
export const setCustomRender = (
|
|
96
66
|
render: (opts: Lunch.UpdateCallbackProperties) => void
|
|
97
67
|
) => {
|
|
98
|
-
|
|
99
|
-
else queuedCustomRenderFunction = render
|
|
68
|
+
useCustomRender()?.setCustomRender?.(render)
|
|
100
69
|
}
|
|
101
70
|
|
|
102
|
-
/** Clear the active app's custom render function.
|
|
71
|
+
/** Clear the active app's custom render function.
|
|
72
|
+
*
|
|
73
|
+
* Invokes immediately - use `useCustomRender().clearCustomRender`
|
|
74
|
+
* if you need to call somewhere outside of `setup`.
|
|
75
|
+
*/
|
|
103
76
|
export const clearCustomRender = () => {
|
|
104
|
-
|
|
105
|
-
|
|
77
|
+
useCustomRender()?.clearCustomRender?.()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Provides `setCustomRender` and `clearCustomRender` functions to be called in a non-`setup` context. */
|
|
81
|
+
export const useCustomRender = () => {
|
|
82
|
+
return {
|
|
83
|
+
/** Set a custom render function, overriding the Lunchbox app's default render function.
|
|
84
|
+
* Changing this requires the user to manually render their scene. */
|
|
85
|
+
setCustomRender: inject<Lunch.CustomRenderFunctionSetter>(
|
|
86
|
+
Keys.setCustomRenderKey
|
|
87
|
+
),
|
|
88
|
+
/** Clear the active app's custom render function. */
|
|
89
|
+
clearCustomRender: inject<() => void>(Keys.clearCustomRenderKey),
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Use app-level globals. */
|
|
94
|
+
export const useGlobals = () =>
|
|
95
|
+
inject<Lunch.AppGlobals>(Keys.globalsInjectionKey)!
|
|
96
|
+
|
|
97
|
+
/** Construct a function to update your app-level globals.
|
|
98
|
+
*
|
|
99
|
+
* ```js
|
|
100
|
+
* // in setup():
|
|
101
|
+
* const updateGlobals = useUpdateGlobals()
|
|
102
|
+
*
|
|
103
|
+
* // ...later, to update the device pixel resolution...
|
|
104
|
+
* updateGlobals({ dpr: 2 })
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export const useUpdateGlobals = () =>
|
|
108
|
+
inject<Lunch.AppGlobalsUpdate>(Keys.updateGlobalsInjectionKey)
|
|
109
|
+
|
|
110
|
+
/** Update app-level globals.
|
|
111
|
+
*
|
|
112
|
+
* Invokes immediately - use `useUpdateGlobals`
|
|
113
|
+
* if you need to call somewhere outside of `setup`.
|
|
114
|
+
*/
|
|
115
|
+
export const updateGlobals = (newValue: Partial<Lunch.AppGlobals>) => {
|
|
116
|
+
useUpdateGlobals()?.(newValue)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// TODO: document
|
|
120
|
+
export const useRootNode = () =>
|
|
121
|
+
inject<MiniDom.RendererRootNode>(Keys.appRootNodeKey)
|
|
122
|
+
|
|
123
|
+
// TODO: document
|
|
124
|
+
export const useApp = () => inject<Lunch.App>(Keys.appKey)
|
|
125
|
+
|
|
126
|
+
// TODO: document
|
|
127
|
+
export const useStartCallbacks = () =>
|
|
128
|
+
inject<Lunch.UpdateCallback[]>(Keys.startCallbackKey) //[] as Lunch.UpdateCallback[]
|
|
129
|
+
|
|
130
|
+
// TODO: document
|
|
131
|
+
export const onStart = (cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
132
|
+
const callbacks = useStartCallbacks()
|
|
133
|
+
if (index === Infinity) {
|
|
134
|
+
callbacks?.push(cb)
|
|
135
|
+
} else {
|
|
136
|
+
callbacks?.splice(index, 0, cb)
|
|
137
|
+
}
|
|
106
138
|
}
|
|
107
139
|
|
|
140
|
+
// TODO: document
|
|
141
|
+
export const useLunchboxInteractables = () =>
|
|
142
|
+
inject<Ref<Lunch.Node[]>>(Keys.lunchboxInteractables)
|
|
143
|
+
|
|
108
144
|
// CREATE APP
|
|
109
145
|
// ====================
|
|
110
146
|
export const createApp = (root: Component) => {
|
|
111
|
-
|
|
147
|
+
const { nodeOps, interactables } = createNodeOps()
|
|
148
|
+
const app = createRenderer(nodeOps).createApp(root) as Lunch.App
|
|
149
|
+
|
|
150
|
+
// provide Lunchbox interaction handlers flag (modified when user references events via
|
|
151
|
+
// @click, etc)
|
|
152
|
+
app.provide(Keys.lunchboxInteractables, interactables)
|
|
112
153
|
|
|
113
154
|
// register all components
|
|
155
|
+
// ====================
|
|
114
156
|
Object.keys(components).forEach((key) => {
|
|
115
157
|
app?.component(key, (components as any)[key])
|
|
116
158
|
})
|
|
117
159
|
|
|
160
|
+
// provide custom renderer functions
|
|
161
|
+
// ====================
|
|
162
|
+
app.provide(
|
|
163
|
+
Keys.setCustomRenderKey,
|
|
164
|
+
(render: (opts: Lunch.UpdateCallbackProperties) => void) => {
|
|
165
|
+
app.setCustomRender(render)
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
app.provide(Keys.clearCustomRenderKey, () => {
|
|
169
|
+
app.clearCustomRender()
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
// before render
|
|
173
|
+
// ====================
|
|
174
|
+
const beforeRender = [] as Lunch.UpdateCallback[]
|
|
175
|
+
app.provide(Keys.beforeRenderKey, beforeRender)
|
|
176
|
+
app.provide(
|
|
177
|
+
Keys.onBeforeRenderKey,
|
|
178
|
+
(cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
179
|
+
if (index === Infinity) {
|
|
180
|
+
beforeRender.push(cb)
|
|
181
|
+
} else {
|
|
182
|
+
beforeRender.splice(index, 0, cb)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
app.provide(
|
|
187
|
+
Keys.offBeforeRenderKey,
|
|
188
|
+
(cb: Lunch.UpdateCallback | number) => {
|
|
189
|
+
if (isFinite(cb as number)) {
|
|
190
|
+
beforeRender.splice(cb as number, 1)
|
|
191
|
+
} else {
|
|
192
|
+
const idx = beforeRender.findIndex((v) => v == cb)
|
|
193
|
+
if (idx !== -1) {
|
|
194
|
+
beforeRender.splice(idx, 1)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
// after render
|
|
201
|
+
// ====================
|
|
202
|
+
const afterRender = [] as Lunch.UpdateCallback[]
|
|
203
|
+
app.provide(Keys.afterRenderKey, afterRender)
|
|
204
|
+
app.provide(
|
|
205
|
+
Keys.onAfterRenderKey,
|
|
206
|
+
(cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
207
|
+
if (index === Infinity) {
|
|
208
|
+
afterRender.push(cb)
|
|
209
|
+
} else {
|
|
210
|
+
afterRender.splice(index, 0, cb)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
app.provide(Keys.offAfterRenderKey, (cb: Lunch.UpdateCallback | number) => {
|
|
215
|
+
if (isFinite(cb as number)) {
|
|
216
|
+
afterRender.splice(cb as number, 1)
|
|
217
|
+
} else {
|
|
218
|
+
const idx = afterRender.findIndex((v) => v == cb)
|
|
219
|
+
if (idx !== -1) {
|
|
220
|
+
afterRender.splice(idx, 1)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
// save app-level components
|
|
226
|
+
// ====================
|
|
227
|
+
app.config.globalProperties.lunchbox = reactive({
|
|
228
|
+
afterRender,
|
|
229
|
+
beforeRender,
|
|
230
|
+
camera: null,
|
|
231
|
+
dpr: 1,
|
|
232
|
+
frameId: -1,
|
|
233
|
+
renderer: null,
|
|
234
|
+
scene: null,
|
|
235
|
+
watchStopHandle: null,
|
|
236
|
+
|
|
237
|
+
// TODO: inputActive, mousePos
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
// provide app-level globals & globals update method
|
|
241
|
+
// ====================
|
|
242
|
+
app.provide(Keys.globalsInjectionKey, app.config.globalProperties.lunchbox)
|
|
243
|
+
app.provide<Lunch.AppGlobalsUpdate>(
|
|
244
|
+
Keys.updateGlobalsInjectionKey,
|
|
245
|
+
(newGlobals: Partial<Lunch.AppGlobals>) => {
|
|
246
|
+
Object.keys(newGlobals).forEach((key) => {
|
|
247
|
+
const typedKey = key as keyof Lunch.AppGlobals
|
|
248
|
+
// TODO: fix
|
|
249
|
+
app.config.globalProperties.lunchbox[typedKey] = newGlobals[
|
|
250
|
+
typedKey
|
|
251
|
+
] as any
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
// frame ID (used for update functions)
|
|
257
|
+
// ====================
|
|
258
|
+
app.provide(Keys.frameIdKey, app.config.globalProperties.lunchbox.frameId)
|
|
259
|
+
|
|
260
|
+
// watch stop handler (used for conditional update loop)
|
|
261
|
+
// ====================
|
|
262
|
+
app.provide(
|
|
263
|
+
Keys.watchStopHandleKey,
|
|
264
|
+
app.config.globalProperties.lunchbox.watchStopHandle
|
|
265
|
+
)
|
|
266
|
+
|
|
118
267
|
// update mount function to match Lunchbox.Node
|
|
268
|
+
// ====================
|
|
119
269
|
const { mount } = app
|
|
120
270
|
app.mount = (root, ...args) => {
|
|
121
271
|
// find DOM element to use as app root
|
|
@@ -123,43 +273,65 @@ export const createApp = (root: Component) => {
|
|
|
123
273
|
typeof root === 'string' ? document.querySelector(root) : root
|
|
124
274
|
) as HTMLElement
|
|
125
275
|
// create or find root node
|
|
126
|
-
const rootNode =
|
|
276
|
+
const rootNode = new MiniDom.RendererRootNode({
|
|
127
277
|
domElement,
|
|
128
278
|
isLunchboxRootNode: true,
|
|
129
279
|
name: 'root',
|
|
130
280
|
metaType: 'rootMeta',
|
|
131
281
|
type: 'root',
|
|
132
|
-
uuid:
|
|
282
|
+
uuid: 'LUNCHBOX_ROOT',
|
|
133
283
|
})
|
|
134
|
-
app
|
|
284
|
+
app.rootNode = rootNode
|
|
285
|
+
app.provide(Keys.appRootNodeKey, rootNode)
|
|
135
286
|
const mounted = mount(rootNode, ...args)
|
|
136
287
|
return mounted
|
|
137
288
|
}
|
|
138
289
|
|
|
139
290
|
// embed .extend function
|
|
291
|
+
// ====================
|
|
140
292
|
app.extend = (targets: Record<string, any>) => {
|
|
141
293
|
extend({ app: app!, ...targets })
|
|
142
294
|
return app!
|
|
143
295
|
}
|
|
144
296
|
|
|
297
|
+
// start callback functions
|
|
298
|
+
// ====================
|
|
299
|
+
const startCallbacks: Lunch.UpdateCallback[] = []
|
|
300
|
+
app.provide(Keys.startCallbackKey, startCallbacks)
|
|
301
|
+
|
|
145
302
|
// prep for custom render support
|
|
303
|
+
// ====================
|
|
146
304
|
app.setCustomRender = (
|
|
147
305
|
newRender: (opts: Lunch.UpdateCallbackProperties) => void
|
|
148
306
|
) => {
|
|
149
|
-
app
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// add queued custom render if we have one
|
|
153
|
-
if (queuedCustomRenderFunction) {
|
|
154
|
-
app.setCustomRender(queuedCustomRenderFunction)
|
|
155
|
-
queuedCustomRenderFunction = null
|
|
307
|
+
if (app) {
|
|
308
|
+
app.customRender = newRender
|
|
309
|
+
}
|
|
156
310
|
}
|
|
157
311
|
|
|
158
312
|
// add custom render removal
|
|
159
313
|
app.clearCustomRender = () => {
|
|
160
|
-
app
|
|
314
|
+
if (app) {
|
|
315
|
+
app.customRender = null
|
|
316
|
+
}
|
|
161
317
|
}
|
|
162
318
|
|
|
319
|
+
// provide app
|
|
320
|
+
// ====================
|
|
321
|
+
app.provide(Keys.appKey, app)
|
|
322
|
+
app.provide(
|
|
323
|
+
Keys.appRenderersKey,
|
|
324
|
+
computed(() => app.config.globalProperties.lunchbox.renderer)
|
|
325
|
+
)
|
|
326
|
+
app.provide(
|
|
327
|
+
Keys.appSceneKey,
|
|
328
|
+
computed(() => app.config.globalProperties.lunchbox.scene)
|
|
329
|
+
)
|
|
330
|
+
app.provide(
|
|
331
|
+
Keys.appCameraKey,
|
|
332
|
+
computed(() => app.config.globalProperties.lunchbox.camera)
|
|
333
|
+
)
|
|
334
|
+
|
|
163
335
|
// done
|
|
164
336
|
return app
|
|
165
337
|
}
|
package/src/keys.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const globalsInjectionKey = Symbol()
|
|
2
|
+
export const updateGlobalsInjectionKey = Symbol()
|
|
3
|
+
|
|
4
|
+
export const setCustomRenderKey = Symbol()
|
|
5
|
+
export const clearCustomRenderKey = Symbol()
|
|
6
|
+
|
|
7
|
+
export const beforeRenderKey = Symbol()
|
|
8
|
+
export const onBeforeRenderKey = Symbol()
|
|
9
|
+
export const offBeforeRenderKey = Symbol()
|
|
10
|
+
|
|
11
|
+
export const afterRenderKey = Symbol()
|
|
12
|
+
export const onAfterRenderKey = Symbol()
|
|
13
|
+
export const offAfterRenderKey = Symbol()
|
|
14
|
+
|
|
15
|
+
export const frameIdKey = Symbol()
|
|
16
|
+
export const watchStopHandleKey = Symbol()
|
|
17
|
+
|
|
18
|
+
export const appRootNodeKey = Symbol()
|
|
19
|
+
export const appKey = Symbol()
|
|
20
|
+
export const appRenderersKey = Symbol()
|
|
21
|
+
export const appSceneKey = Symbol()
|
|
22
|
+
export const appCameraKey = Symbol()
|
|
23
|
+
export const lunchboxInteractables = Symbol()
|
|
24
|
+
|
|
25
|
+
export const startCallbackKey = Symbol()
|
|
@@ -10,13 +10,10 @@ export const createElement = (
|
|
|
10
10
|
isCustomizedBuiltin?: string,
|
|
11
11
|
vnodeProps?: Lunch.LunchboxMetaProps
|
|
12
12
|
) => {
|
|
13
|
-
const options = { type
|
|
14
|
-
if (vnodeProps) {
|
|
15
|
-
options.props = vnodeProps
|
|
16
|
-
}
|
|
13
|
+
const options: Partial<Lunch.MetaBase> = { type, props: vnodeProps }
|
|
17
14
|
|
|
18
15
|
// handle dom node
|
|
19
|
-
const isDomNode = isLunchboxDomComponent(
|
|
16
|
+
const isDomNode = isLunchboxDomComponent(options)
|
|
20
17
|
if (isDomNode) {
|
|
21
18
|
const node = createDomNode(options)
|
|
22
19
|
return node
|