lunchboxjs 0.1.4018 → 0.2.1001-beta.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/README.md +47 -0
- package/dist/lunchboxjs.js +1738 -1687
- package/dist/lunchboxjs.min.js +1 -1
- package/dist/lunchboxjs.module.js +1688 -1688
- package/extras/OrbitControlsWrapper.vue +12 -4
- package/package.json +11 -4
- package/src/components/LunchboxWrapper/LunchboxScene.tsx +8 -0
- package/src/components/LunchboxWrapper/LunchboxWrapper.tsx +299 -0
- package/src/components/LunchboxWrapper/prepCanvas.ts +27 -21
- package/src/components/LunchboxWrapper/resizeCanvas.ts +13 -12
- package/src/components/index.ts +0 -2
- package/src/core/createNode.ts +1 -17
- package/src/core/ensure.ts +9 -196
- package/src/core/index.ts +0 -2
- package/src/core/instantiateThreeObject/index.ts +6 -1
- package/src/core/interaction/index.ts +2 -2
- package/src/core/interaction/setupAutoRaycaster.ts +215 -207
- package/src/core/minidom.ts +4 -8
- package/src/core/update.ts +99 -48
- package/src/core/updateObjectProp.ts +2 -16
- package/src/index.ts +238 -75
- package/src/keys.ts +24 -0
- package/src/nodeOps/createElement.ts +2 -5
- package/src/nodeOps/insert.ts +11 -32
- package/src/nodeOps/remove.ts +1 -17
- package/src/types.ts +38 -6
- 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/core/.DS_Store +0 -0
- package/src/core/allNodes.ts +0 -4
- package/src/core/start.ts +0 -11
package/src/core/update.ts
CHANGED
|
@@ -1,31 +1,39 @@
|
|
|
1
|
-
import {
|
|
1
|
+
// import {
|
|
2
|
+
//ensureRenderer,
|
|
3
|
+
// ensuredScene,
|
|
4
|
+
// ensuredCamera,
|
|
5
|
+
// } from '.'
|
|
2
6
|
import { Lunch } from '..'
|
|
3
|
-
import { toRaw, watch, WatchStopHandle } from 'vue'
|
|
7
|
+
import { inject, toRaw, watch, WatchStopHandle } from 'vue'
|
|
8
|
+
import * as Keys from '../keys'
|
|
4
9
|
|
|
5
|
-
let frameID: number
|
|
6
|
-
let watchStopHandle: WatchStopHandle
|
|
10
|
+
// let frameID: number
|
|
11
|
+
// let watchStopHandle: WatchStopHandle
|
|
7
12
|
|
|
8
|
-
export const beforeRender = [] as Lunch.UpdateCallback[]
|
|
9
|
-
export const afterRender = [] as Lunch.UpdateCallback[]
|
|
13
|
+
// export const beforeRender = [] as Lunch.UpdateCallback[]
|
|
14
|
+
// export const afterRender = [] as Lunch.UpdateCallback[]
|
|
10
15
|
|
|
11
16
|
const requestUpdate = (opts: Lunch.UpdateCallbackProperties) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
if (typeof opts.app.config.globalProperties.lunchbox.frameId === 'number') {
|
|
18
|
+
cancelAnimationFrame(opts.app.config.globalProperties.lunchbox.frameId)
|
|
19
|
+
}
|
|
20
|
+
opts.app.config.globalProperties.lunchbox.frameId = requestAnimationFrame(
|
|
21
|
+
() =>
|
|
22
|
+
update({
|
|
23
|
+
app: opts.app,
|
|
24
|
+
renderer: opts.renderer,
|
|
25
|
+
scene: opts.scene,
|
|
26
|
+
camera: opts.camera,
|
|
27
|
+
updateSource: opts.updateSource,
|
|
28
|
+
})
|
|
21
29
|
)
|
|
22
30
|
}
|
|
23
31
|
|
|
24
32
|
export const update: Lunch.UpdateCallback = (opts) => {
|
|
25
33
|
if (opts.updateSource) {
|
|
26
|
-
if (!watchStopHandle) {
|
|
34
|
+
if (!opts.app.config.globalProperties.lunchbox.watchStopHandle) {
|
|
27
35
|
// request next frame only when state changes
|
|
28
|
-
watchStopHandle = watch(
|
|
36
|
+
opts.app.config.globalProperties.lunchbox.watchStopHandle = watch(
|
|
29
37
|
opts.updateSource,
|
|
30
38
|
() => {
|
|
31
39
|
requestUpdate(opts)
|
|
@@ -44,10 +52,8 @@ export const update: Lunch.UpdateCallback = (opts) => {
|
|
|
44
52
|
const { app, renderer, scene, camera } = opts
|
|
45
53
|
|
|
46
54
|
// BEFORE RENDER
|
|
47
|
-
beforeRender.forEach((cb
|
|
48
|
-
|
|
49
|
-
cb(opts)
|
|
50
|
-
}
|
|
55
|
+
app.config.globalProperties.lunchbox.beforeRender.forEach((cb) => {
|
|
56
|
+
cb?.(opts)
|
|
51
57
|
})
|
|
52
58
|
|
|
53
59
|
// RENDER
|
|
@@ -55,56 +61,101 @@ export const update: Lunch.UpdateCallback = (opts) => {
|
|
|
55
61
|
if (app.customRender) {
|
|
56
62
|
app.customRender(opts)
|
|
57
63
|
} else {
|
|
58
|
-
renderer.render(
|
|
64
|
+
renderer.render(
|
|
65
|
+
toRaw(scene),
|
|
66
|
+
// opts.app.config.globalProperties.lunchbox.camera!
|
|
67
|
+
toRaw(camera)
|
|
68
|
+
)
|
|
59
69
|
}
|
|
60
70
|
}
|
|
61
71
|
|
|
62
72
|
// AFTER RENDER
|
|
63
|
-
afterRender.forEach((cb
|
|
64
|
-
|
|
65
|
-
cb(opts)
|
|
66
|
-
}
|
|
73
|
+
app.config.globalProperties.lunchbox.afterRender.forEach((cb) => {
|
|
74
|
+
cb?.(opts)
|
|
67
75
|
})
|
|
68
76
|
}
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
// before render
|
|
79
|
+
// ====================
|
|
80
|
+
// TODO: document
|
|
81
|
+
export const useBeforeRender = () => {
|
|
82
|
+
return {
|
|
83
|
+
onBeforeRender: inject<typeof onBeforeRender>(Keys.onBeforeRenderKey),
|
|
84
|
+
offBeforeRender: inject<typeof offBeforeRender>(
|
|
85
|
+
Keys.offBeforeRenderKey
|
|
86
|
+
),
|
|
75
87
|
}
|
|
76
88
|
}
|
|
77
89
|
|
|
90
|
+
// TODO: document
|
|
91
|
+
export const onBeforeRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
92
|
+
useBeforeRender().onBeforeRender?.(cb, index)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// TODO: document
|
|
78
96
|
export const offBeforeRender = (cb: Lunch.UpdateCallback | number) => {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
97
|
+
useBeforeRender().offBeforeRender?.(cb)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// after render
|
|
101
|
+
// ====================
|
|
102
|
+
// TODO: document
|
|
103
|
+
export const useAfterRender = () => {
|
|
104
|
+
return {
|
|
105
|
+
onAfterRender: inject<typeof onAfterRender>(Keys.onBeforeRenderKey),
|
|
106
|
+
offAfterRender: inject<typeof offAfterRender>(Keys.offBeforeRenderKey),
|
|
84
107
|
}
|
|
85
108
|
}
|
|
86
109
|
|
|
110
|
+
// TODO: document
|
|
87
111
|
export const onAfterRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
88
|
-
|
|
89
|
-
afterRender.push(cb)
|
|
90
|
-
} else {
|
|
91
|
-
afterRender.splice(index, 0, cb)
|
|
92
|
-
}
|
|
112
|
+
useBeforeRender().onBeforeRender?.(cb, index)
|
|
93
113
|
}
|
|
94
114
|
|
|
115
|
+
// TODO: document
|
|
95
116
|
export const offAfterRender = (cb: Lunch.UpdateCallback | number) => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
117
|
+
useBeforeRender().offBeforeRender?.(cb)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// export const onAfterRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
121
|
+
// if (index === Infinity) {
|
|
122
|
+
// afterRender.push(cb)
|
|
123
|
+
// } else {
|
|
124
|
+
// afterRender.splice(index, 0, cb)
|
|
125
|
+
// }
|
|
126
|
+
// }
|
|
127
|
+
|
|
128
|
+
// export const offAfterRender = (cb: Lunch.UpdateCallback | number) => {
|
|
129
|
+
// if (isFinite(cb as number)) {
|
|
130
|
+
// afterRender.splice(cb as number, 1)
|
|
131
|
+
// } else {
|
|
132
|
+
// const idx = afterRender.findIndex((v) => v == cb)
|
|
133
|
+
// afterRender.splice(idx, 1)
|
|
134
|
+
// }
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
// TODO: document
|
|
138
|
+
export const useCancelUpdate = () => {
|
|
139
|
+
const frameId = inject<number>(Keys.frameIdKey)
|
|
140
|
+
return () => {
|
|
141
|
+
if (frameId !== undefined) cancelAnimationFrame(frameId)
|
|
101
142
|
}
|
|
102
143
|
}
|
|
103
144
|
|
|
145
|
+
// TODO: document
|
|
104
146
|
export const cancelUpdate = () => {
|
|
105
|
-
|
|
147
|
+
useCancelUpdate()?.()
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// TODO: document
|
|
151
|
+
export const useCancelUpdateSource = () => {
|
|
152
|
+
const cancel = inject<
|
|
153
|
+
Lunch.App['config']['globalProperties']['watchStopHandle']
|
|
154
|
+
>(Keys.watchStopHandleKey)
|
|
155
|
+
return () => cancel?.()
|
|
106
156
|
}
|
|
107
157
|
|
|
158
|
+
// TODO: document
|
|
108
159
|
export const cancelUpdateSource = () => {
|
|
109
|
-
|
|
160
|
+
useCancelUpdateSource()?.()
|
|
110
161
|
}
|
|
@@ -67,7 +67,6 @@ export function updateObjectProp({
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// change property
|
|
70
|
-
// first, save as array in case we need to spread it
|
|
71
70
|
if (liveProperty && isNumber(value) && liveProperty.setScalar) {
|
|
72
71
|
// if value is a number and the property has a `setScalar` method, use that
|
|
73
72
|
liveProperty.setScalar(value)
|
|
@@ -76,21 +75,8 @@ export function updateObjectProp({
|
|
|
76
75
|
const nextValueAsArray = Array.isArray(value) ? value : [value]
|
|
77
76
|
;(target as any)[finalKey].set(...nextValueAsArray)
|
|
78
77
|
} else if (typeof liveProperty === 'function') {
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
finalKey.toLowerCase() === 'onbeforerender' ||
|
|
82
|
-
finalKey.toLowerCase() === 'onafterrender'
|
|
83
|
-
) {
|
|
84
|
-
;(target as any)[finalKey] = value
|
|
85
|
-
} else {
|
|
86
|
-
if (!Array.isArray(value)) {
|
|
87
|
-
throw new Error(
|
|
88
|
-
'Arguments on a declarative method must be wrapped in an array.\nWorks:\n<example :methodCall="[256]" />\nDoesn\'t work:\n<example :methodCall="256" />'
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
// if property is a function, let's try calling it
|
|
92
|
-
liveProperty.bind(node.instance)(...value)
|
|
93
|
-
}
|
|
78
|
+
// if property is a function, let's try calling it
|
|
79
|
+
liveProperty.bind(node.instance)(...value)
|
|
94
80
|
|
|
95
81
|
// pass the result to the parent
|
|
96
82
|
// const parent = node.parentNode
|
package/src/index.ts
CHANGED
|
@@ -1,82 +1,54 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
createRenderer,
|
|
4
|
+
Component,
|
|
5
|
+
inject,
|
|
6
|
+
watch,
|
|
7
|
+
reactive,
|
|
8
|
+
} from 'vue'
|
|
2
9
|
import { nodeOps } from './nodeOps'
|
|
3
10
|
import {
|
|
4
|
-
// createdCamera,
|
|
5
|
-
// createdRenderer,
|
|
6
|
-
// autoScene,
|
|
7
11
|
ensuredCamera,
|
|
8
12
|
ensureRenderer,
|
|
9
13
|
ensuredScene,
|
|
10
|
-
ensureRootNode,
|
|
11
14
|
extend,
|
|
12
|
-
|
|
13
|
-
mousePos,
|
|
14
|
-
rootUuid,
|
|
15
|
+
MiniDom,
|
|
15
16
|
} from './core'
|
|
16
17
|
import { components } from './components'
|
|
17
18
|
import { Lunch } from './types'
|
|
18
19
|
|
|
19
|
-
export { lunchboxRootNode as lunchboxTree } from './core'
|
|
20
|
-
export
|
|
21
|
-
offAfterRender,
|
|
22
|
-
offBeforeRender,
|
|
23
|
-
onAfterRender,
|
|
24
|
-
onBeforeRender,
|
|
25
|
-
onStart,
|
|
26
|
-
} from './core'
|
|
20
|
+
// export { lunchboxRootNode as lunchboxTree } 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
|
|
51
|
+
callback(newVal.value)
|
|
80
52
|
},
|
|
81
53
|
{ immediate: true }
|
|
82
54
|
)
|
|
@@ -84,38 +56,207 @@ 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
|
|
|
108
140
|
// CREATE APP
|
|
109
141
|
// ====================
|
|
110
142
|
export const createApp = (root: Component) => {
|
|
111
|
-
app = createRenderer(nodeOps).createApp(root) as Lunch.App
|
|
143
|
+
const app = createRenderer(nodeOps).createApp(root) as Lunch.App
|
|
112
144
|
|
|
113
145
|
// register all components
|
|
146
|
+
// ====================
|
|
114
147
|
Object.keys(components).forEach((key) => {
|
|
115
148
|
app?.component(key, (components as any)[key])
|
|
116
149
|
})
|
|
117
150
|
|
|
151
|
+
// provide custom renderer functions
|
|
152
|
+
// ====================
|
|
153
|
+
app.provide(
|
|
154
|
+
Keys.setCustomRenderKey,
|
|
155
|
+
(render: (opts: Lunch.UpdateCallbackProperties) => void) => {
|
|
156
|
+
app.setCustomRender(render)
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
app.provide(Keys.clearCustomRenderKey, () => {
|
|
160
|
+
app.clearCustomRender()
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
// before render
|
|
164
|
+
// ====================
|
|
165
|
+
const beforeRender = [] as Lunch.UpdateCallback[]
|
|
166
|
+
app.provide(Keys.beforeRenderKey, beforeRender)
|
|
167
|
+
app.provide(
|
|
168
|
+
Keys.onBeforeRenderKey,
|
|
169
|
+
(cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
170
|
+
if (index === Infinity) {
|
|
171
|
+
beforeRender.push(cb)
|
|
172
|
+
} else {
|
|
173
|
+
beforeRender.splice(index, 0, cb)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
)
|
|
177
|
+
app.provide(
|
|
178
|
+
Keys.offBeforeRenderKey,
|
|
179
|
+
(cb: Lunch.UpdateCallback | number) => {
|
|
180
|
+
if (isFinite(cb as number)) {
|
|
181
|
+
beforeRender.splice(cb as number, 1)
|
|
182
|
+
} else {
|
|
183
|
+
const idx = beforeRender.findIndex((v) => v == cb)
|
|
184
|
+
if (idx !== -1) {
|
|
185
|
+
beforeRender.splice(idx, 1)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
// after render
|
|
192
|
+
// ====================
|
|
193
|
+
const afterRender = [] as Lunch.UpdateCallback[]
|
|
194
|
+
app.provide(Keys.afterRenderKey, afterRender)
|
|
195
|
+
app.provide(
|
|
196
|
+
Keys.onAfterRenderKey,
|
|
197
|
+
(cb: Lunch.UpdateCallback, index = Infinity) => {
|
|
198
|
+
if (index === Infinity) {
|
|
199
|
+
afterRender.push(cb)
|
|
200
|
+
} else {
|
|
201
|
+
afterRender.splice(index, 0, cb)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
)
|
|
205
|
+
app.provide(Keys.offAfterRenderKey, (cb: Lunch.UpdateCallback | number) => {
|
|
206
|
+
if (isFinite(cb as number)) {
|
|
207
|
+
afterRender.splice(cb as number, 1)
|
|
208
|
+
} else {
|
|
209
|
+
const idx = afterRender.findIndex((v) => v == cb)
|
|
210
|
+
if (idx !== -1) {
|
|
211
|
+
afterRender.splice(idx, 1)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
// save app-level components
|
|
217
|
+
// ====================
|
|
218
|
+
app.config.globalProperties.lunchbox = reactive({
|
|
219
|
+
afterRender,
|
|
220
|
+
beforeRender,
|
|
221
|
+
camera: null,
|
|
222
|
+
dpr: 1,
|
|
223
|
+
frameId: -1,
|
|
224
|
+
renderer: null,
|
|
225
|
+
scene: null,
|
|
226
|
+
watchStopHandle: null,
|
|
227
|
+
|
|
228
|
+
// TODO: inputActive, mousePos
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
// provide app-level globals & globals update method
|
|
232
|
+
// ====================
|
|
233
|
+
app.provide(Keys.globalsInjectionKey, app.config.globalProperties.lunchbox)
|
|
234
|
+
app.provide<Lunch.AppGlobalsUpdate>(
|
|
235
|
+
Keys.updateGlobalsInjectionKey,
|
|
236
|
+
(newGlobals: Partial<Lunch.AppGlobals>) => {
|
|
237
|
+
Object.keys(newGlobals).forEach((key) => {
|
|
238
|
+
const typedKey = key as keyof Lunch.AppGlobals
|
|
239
|
+
// TODO: fix
|
|
240
|
+
app.config.globalProperties.lunchbox[typedKey] = newGlobals[
|
|
241
|
+
typedKey
|
|
242
|
+
] as any
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
// frame ID (used for update functions)
|
|
248
|
+
// ====================
|
|
249
|
+
app.provide(Keys.frameIdKey, app.config.globalProperties.lunchbox.frameId)
|
|
250
|
+
|
|
251
|
+
// watch stop handler (used for conditional update loop)
|
|
252
|
+
// ====================
|
|
253
|
+
app.provide(
|
|
254
|
+
Keys.watchStopHandleKey,
|
|
255
|
+
app.config.globalProperties.lunchbox.watchStopHandle
|
|
256
|
+
)
|
|
257
|
+
|
|
118
258
|
// update mount function to match Lunchbox.Node
|
|
259
|
+
// ====================
|
|
119
260
|
const { mount } = app
|
|
120
261
|
app.mount = (root, ...args) => {
|
|
121
262
|
// find DOM element to use as app root
|
|
@@ -123,43 +264,65 @@ export const createApp = (root: Component) => {
|
|
|
123
264
|
typeof root === 'string' ? document.querySelector(root) : root
|
|
124
265
|
) as HTMLElement
|
|
125
266
|
// create or find root node
|
|
126
|
-
const rootNode =
|
|
267
|
+
const rootNode = new MiniDom.RendererRootNode({
|
|
127
268
|
domElement,
|
|
128
269
|
isLunchboxRootNode: true,
|
|
129
270
|
name: 'root',
|
|
130
271
|
metaType: 'rootMeta',
|
|
131
272
|
type: 'root',
|
|
132
|
-
uuid:
|
|
273
|
+
uuid: 'LUNCHBOX_ROOT',
|
|
133
274
|
})
|
|
134
|
-
app
|
|
275
|
+
app.rootNode = rootNode
|
|
276
|
+
app.provide(Keys.appRootNodeKey, rootNode)
|
|
135
277
|
const mounted = mount(rootNode, ...args)
|
|
136
278
|
return mounted
|
|
137
279
|
}
|
|
138
280
|
|
|
139
281
|
// embed .extend function
|
|
282
|
+
// ====================
|
|
140
283
|
app.extend = (targets: Record<string, any>) => {
|
|
141
284
|
extend({ app: app!, ...targets })
|
|
142
285
|
return app!
|
|
143
286
|
}
|
|
144
287
|
|
|
288
|
+
// start callback functions
|
|
289
|
+
// ====================
|
|
290
|
+
const startCallbacks: Lunch.UpdateCallback[] = []
|
|
291
|
+
app.provide(Keys.startCallbackKey, startCallbacks)
|
|
292
|
+
|
|
145
293
|
// prep for custom render support
|
|
294
|
+
// ====================
|
|
146
295
|
app.setCustomRender = (
|
|
147
296
|
newRender: (opts: Lunch.UpdateCallbackProperties) => void
|
|
148
297
|
) => {
|
|
149
|
-
app
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// add queued custom render if we have one
|
|
153
|
-
if (queuedCustomRenderFunction) {
|
|
154
|
-
app.setCustomRender(queuedCustomRenderFunction)
|
|
155
|
-
queuedCustomRenderFunction = null
|
|
298
|
+
if (app) {
|
|
299
|
+
app.customRender = newRender
|
|
300
|
+
}
|
|
156
301
|
}
|
|
157
302
|
|
|
158
303
|
// add custom render removal
|
|
159
304
|
app.clearCustomRender = () => {
|
|
160
|
-
app
|
|
305
|
+
if (app) {
|
|
306
|
+
app.customRender = null
|
|
307
|
+
}
|
|
161
308
|
}
|
|
162
309
|
|
|
310
|
+
// provide app
|
|
311
|
+
// ====================
|
|
312
|
+
app.provide(Keys.appKey, app)
|
|
313
|
+
app.provide(
|
|
314
|
+
Keys.appRenderersKey,
|
|
315
|
+
computed(() => app.config.globalProperties.lunchbox.renderer)
|
|
316
|
+
)
|
|
317
|
+
app.provide(
|
|
318
|
+
Keys.appSceneKey,
|
|
319
|
+
computed(() => app.config.globalProperties.lunchbox.scene)
|
|
320
|
+
)
|
|
321
|
+
app.provide(
|
|
322
|
+
Keys.appCameraKey,
|
|
323
|
+
computed(() => app.config.globalProperties.lunchbox.camera)
|
|
324
|
+
)
|
|
325
|
+
|
|
163
326
|
// done
|
|
164
327
|
return app
|
|
165
328
|
}
|
package/src/keys.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
|
|
24
|
+
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
|