lunchboxjs 0.1.4013 → 0.1.4016

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.
@@ -158,18 +158,10 @@ export const ensuredCamera = computed<Lunch.Node<THREE.Camera> | null>({
158
158
  },
159
159
  })
160
160
 
161
- // export const ensuredCamera = buildEnsured<THREE.Camera>(
162
- // ['PerspectiveCamera', 'OrthographicCamera'],
163
- // fallbackCameraUuid,
164
- // {
165
- // args: [45, 0.5625, 1, 1000],
166
- // }
167
- // )
168
-
169
161
  // ENSURE RENDERER
170
162
  // ====================
171
163
  export const fallbackRendererUuid = 'FALLBACK_RENDERER'
172
- export const v = buildEnsured(
164
+ export const ensuredRenderer = buildEnsured(
173
165
  // TODO: ensure support for css/svg renderers
174
166
  ['WebGLRenderer'], //, 'CSS2DRenderer', 'CSS3DRenderer', 'SVGRenderer'],
175
167
  fallbackRendererUuid,
@@ -181,7 +173,9 @@ export const rendererReady = ref(false)
181
173
 
182
174
  export const ensureRenderer = computed<Lunch.Node<THREE.WebGLRenderer> | null>({
183
175
  get() {
184
- return (rendererReady.value ? (v.value as any) : (null as any)) as any
176
+ return (
177
+ rendererReady.value ? (ensuredRenderer.value as any) : (null as any)
178
+ ) as any
185
179
  },
186
180
  set(val: any) {
187
181
  const t = val.type ?? ''
@@ -1,10 +1,18 @@
1
1
  import { Lunch } from '../..'
2
2
 
3
3
  /** Process props into either themselves or the $attached value */
4
- export function processProp<T, U = THREE.Object3D>({ node, prop }: { node: Lunch.StandardMeta<U>, prop: any }) {
4
+ export function processProp<T, U = THREE.Object3D>({
5
+ node,
6
+ prop,
7
+ }: {
8
+ node: Lunch.StandardMeta<U>
9
+ prop: any
10
+ }) {
5
11
  // return $attachedArray value if needed
6
12
  if (typeof prop === 'string' && prop.startsWith('$attachedArray')) {
7
- return node.attachedArray[prop.replace('$attachedArray.', '')] as any as T
13
+ return node.attachedArray[
14
+ prop.replace('$attachedArray.', '')
15
+ ] as any as T
8
16
  }
9
17
 
10
18
  // return $attached value if needed
@@ -16,8 +24,17 @@ export function processProp<T, U = THREE.Object3D>({ node, prop }: { node: Lunch
16
24
  return prop as T
17
25
  }
18
26
 
19
- export function processPropAsArray<T, U = THREE.Object3D>({ node, prop }: { node: Lunch.StandardMeta<U>, prop: any }) {
20
- const isAttachedArray = typeof prop === 'string' && prop.startsWith('$attachedArray')
27
+ export function processPropAsArray<T, U = THREE.Object3D>({
28
+ node,
29
+ prop,
30
+ }: {
31
+ node: Lunch.StandardMeta<U>
32
+ prop: any
33
+ }) {
34
+ const isAttachedArray =
35
+ typeof prop === 'string' && prop.startsWith('$attachedArray')
21
36
  const output = processProp<T, U>({ node, prop })
22
- return Array.isArray(output) && isAttachedArray ? output as Array<T> : [output]
23
- }
37
+ return Array.isArray(output) && isAttachedArray
38
+ ? (output as Array<T>)
39
+ : [output]
40
+ }
@@ -1,4 +1,4 @@
1
1
  import { ref } from 'vue'
2
2
 
3
3
  /** Mouse is down, touch is pressed, etc */
4
- export const inputActive = ref(false)
4
+ export const inputActive = ref(false)
@@ -17,6 +17,8 @@ let mouseUpListener: (event: MouseEvent) => void
17
17
  export const mousePos = ref({ x: Infinity, y: Infinity })
18
18
  let autoRaycasterEventsInitialized = false
19
19
 
20
+ let frameID: number
21
+
20
22
  export const setupAutoRaycaster = (node: Lunch.Node<THREE.Raycaster>) => {
21
23
  const instance = node.instance
22
24
 
@@ -67,8 +69,16 @@ export const setupAutoRaycaster = (node: Lunch.Node<THREE.Raycaster>) => {
67
69
 
68
70
  // TODO: add touch events
69
71
 
70
- // add to update loop
71
- onBeforeRender(autoRaycasterBeforeRender)
72
+ // process mouse events asynchronously, whenever the mouse state changes
73
+ watch(
74
+ () => [inputActive.value, mousePos.value.x, mousePos.value.y],
75
+ () => {
76
+ if (frameID) cancelAnimationFrame(frameID)
77
+ frameID = requestAnimationFrame(() => {
78
+ autoRaycasterBeforeRender()
79
+ })
80
+ }
81
+ )
72
82
 
73
83
  // mark complete
74
84
  autoRaycasterEventsInitialized = true
@@ -1,22 +1,44 @@
1
1
  import { ensureRenderer, ensuredScene, ensuredCamera } from '.'
2
2
  import { Lunch } from '..'
3
- import { toRaw } from 'vue'
3
+ import { toRaw, watch, WatchStopHandle } from 'vue'
4
4
 
5
5
  let frameID: number
6
+ let watchStopHandle: WatchStopHandle
6
7
 
7
8
  export const beforeRender = [] as Lunch.UpdateCallback[]
8
9
  export const afterRender = [] as Lunch.UpdateCallback[]
9
10
 
10
- export const update: Lunch.UpdateCallback = (opts) => {
11
- // request next frame
11
+ const requestUpdate = (opts: Lunch.UpdateCallbackProperties) => {
12
+ cancelUpdate()
12
13
  frameID = requestAnimationFrame(() =>
13
14
  update({
14
15
  app: opts.app,
15
16
  renderer: ensureRenderer.value?.instance,
16
17
  scene: ensuredScene.value.instance,
17
18
  camera: ensuredCamera.value?.instance,
19
+ updateSource: opts.updateSource,
18
20
  })
19
21
  )
22
+ }
23
+
24
+ export const update: Lunch.UpdateCallback = (opts) => {
25
+ if (opts.updateSource) {
26
+ if (!watchStopHandle) {
27
+ // request next frame only when state changes
28
+ watchStopHandle = watch(
29
+ opts.updateSource,
30
+ () => {
31
+ requestUpdate(opts)
32
+ },
33
+ {
34
+ deep: true,
35
+ }
36
+ )
37
+ }
38
+ } else {
39
+ // request next frame on a continuous loop
40
+ requestUpdate(opts)
41
+ }
20
42
 
21
43
  // prep options
22
44
  const { app, renderer, scene, camera } = opts
@@ -82,3 +104,7 @@ export const offAfterRender = (cb: Lunch.UpdateCallback | number) => {
82
104
  export const cancelUpdate = () => {
83
105
  if (frameID) cancelAnimationFrame(frameID)
84
106
  }
107
+
108
+ export const cancelUpdateSource = () => {
109
+ if (watchStopHandle) watchStopHandle()
110
+ }
package/src/index.ts CHANGED
@@ -1,11 +1,4 @@
1
- import {
2
- computed,
3
- createRenderer,
4
- Component,
5
- ref,
6
- watch,
7
- WatchStopHandle,
8
- } from 'vue'
1
+ import { computed, createRenderer, Component, ref, watch } from 'vue'
9
2
  import { nodeOps } from './nodeOps'
10
3
  import {
11
4
  // createdCamera,
@@ -47,20 +40,13 @@ export const globals = {
47
40
  export const camera = computed(() => ensuredCamera.value?.instance ?? null)
48
41
  /** Run a function using the current camera when it's present. */
49
42
  export function useCamera<T extends THREE.Camera = THREE.PerspectiveCamera>(
50
- callback: (cam: T) => void,
51
- once = true
43
+ callback: (cam: T) => void
52
44
  ) {
53
- let destroy: WatchStopHandle
54
- destroy = watch(
45
+ return watch(
55
46
  camera,
56
47
  (newVal) => {
57
48
  if (!newVal) return
58
-
59
- // TODO: better fix than `any`?
60
- callback(newVal as any)
61
- if (once) {
62
- destroy?.()
63
- }
49
+ callback(newVal as unknown as T)
64
50
  },
65
51
  { immediate: true }
66
52
  )
@@ -70,20 +56,13 @@ export function useCamera<T extends THREE.Camera = THREE.PerspectiveCamera>(
70
56
  export const renderer = computed(() => ensureRenderer.value?.instance ?? null)
71
57
  /** Run a function using the current renderer when it's present. */
72
58
  export function useRenderer<T extends THREE.Renderer = THREE.WebGLRenderer>(
73
- callback: (rend: T) => void,
74
- once = true
59
+ callback: (rend: T) => void
75
60
  ) {
76
- let destroy: WatchStopHandle
77
- destroy = watch(
61
+ return watch(
78
62
  renderer,
79
63
  (newVal) => {
80
64
  if (!newVal) return
81
-
82
- // TODO: better fix than `any`?
83
- callback(newVal as any)
84
- if (once) {
85
- destroy?.()
86
- }
65
+ callback(newVal as unknown as T)
87
66
  },
88
67
  { immediate: true }
89
68
  )
@@ -92,21 +71,12 @@ export function useRenderer<T extends THREE.Renderer = THREE.WebGLRenderer>(
92
71
  /** The current scene. Often easier to use `useScene` instead of this. */
93
72
  export const scene = computed(() => ensuredScene.value.instance)
94
73
  /** Run a function using the current scene when it's present. */
95
- export function useScene(
96
- callback: (newScene: THREE.Scene) => void,
97
- once = true
98
- ) {
99
- let destroy: WatchStopHandle
100
- destroy = watch(
74
+ export function useScene(callback: (newScene: THREE.Scene) => void) {
75
+ return watch(
101
76
  scene,
102
77
  (newVal) => {
103
78
  if (!newVal) return
104
-
105
- // TODO: better fix than `any`?
106
79
  callback(newVal as any)
107
- if (once) {
108
- destroy?.()
109
- }
110
80
  },
111
81
  { immediate: true }
112
82
  )
@@ -142,15 +112,17 @@ export const createApp = (root: Component) => {
142
112
 
143
113
  // register all components
144
114
  Object.keys(components).forEach((key) => {
145
- app!.component(key, (components as any)[key])
115
+ app?.component(key, (components as any)[key])
146
116
  })
147
117
 
148
118
  // update mount function to match Lunchbox.Node
149
119
  const { mount } = app
150
120
  app.mount = (root, ...args) => {
121
+ // find DOM element to use as app root
151
122
  const domElement = (
152
123
  typeof root === 'string' ? document.querySelector(root) : root
153
124
  ) as HTMLElement
125
+ // create or find root node
154
126
  const rootNode = ensureRootNode({
155
127
  domElement,
156
128
  isLunchboxRootNode: true,
@@ -5,7 +5,6 @@ import { overrides } from '../core'
5
5
  export const remove = (node: MiniDom.RendererBaseNode) => {
6
6
  if (!node) return
7
7
  const overrideKeys = Object.keys(overrides)
8
-
9
8
  // prep subtree
10
9
  const subtree: MiniDom.BaseNode[] = []
11
10
  node.walk((descendant) => {
package/src/types.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  type RootNode = import('./core/minidom').MiniDom.RendererRootNode
2
2
  type VNodeProps = import('vue').VNodeProps
3
3
  type VueApp<T> = import('vue').App<T>
4
+ type WatchSource = import('vue').WatchSource
4
5
  type RendererStandardNode<T = THREE.Object3D> =
5
6
  import('./core').MiniDom.RendererStandardNode<T>
6
7
 
@@ -127,6 +128,7 @@ export declare namespace Lunch {
127
128
  scene?: THREE.Scene | null
128
129
  renderer?: THREE.Renderer | null
129
130
  camera?: THREE.Camera | null
131
+ updateSource?: WatchSource | null
130
132
 
131
133
  // sceneNode: Node<THREE.Scene> | null
132
134
  // rendererNode: Node<THREE.Renderer> | null
@@ -145,11 +147,13 @@ export declare namespace Lunch {
145
147
  dpr?: number
146
148
  ortho?: boolean
147
149
  orthographic?: boolean
150
+ r3f?: boolean
148
151
  // TODO: Why doesn't ConstructorParameters<THREE.WebGLRenderer> work here?
149
152
  rendererArguments?: object
150
153
  rendererProperties?: Partial<THREE.WebGLRenderer>
151
154
  shadow?: ShadowSugar
152
155
  transparent?: boolean
153
156
  zoom?: number
157
+ updateSource?: WatchSource | null
154
158
  }
155
159
  }