|
@@ -8,6 +8,39 @@ import { useCamera } from '../useCamera'
|
|
|
import type { UseRendererOptions } from '../useRenderer'
|
|
|
import { useRenderer } from '../useRenderer'
|
|
|
import { extend } from '../../core/catalogue'
|
|
|
+import { useLogger } from '../useLogger'
|
|
|
+
|
|
|
+export interface InternalState {
|
|
|
+ priority: Ref<number>
|
|
|
+ frames: Ref<number>
|
|
|
+ maxFrames: number
|
|
|
+}
|
|
|
+
|
|
|
+export interface RenderState {
|
|
|
+ /**
|
|
|
+ * If set to 'on-demand', the scene will only be rendered when the current frame is invalidated
|
|
|
+ * If set to 'manual', the scene will only be rendered when advance() is called
|
|
|
+ * If set to 'always', the scene will be rendered every frame
|
|
|
+ */
|
|
|
+ mode: Ref<'always' | 'on-demand' | 'manual'>
|
|
|
+ priority: Ref<number>
|
|
|
+ frames: Ref<number>
|
|
|
+ maxFrames: number
|
|
|
+ canBeInvalidated: ComputedRef<boolean>
|
|
|
+}
|
|
|
+
|
|
|
+export interface PerformanceState {
|
|
|
+ maxFrames: number
|
|
|
+ fps: {
|
|
|
+ value: number
|
|
|
+ accumulator: number[]
|
|
|
+ }
|
|
|
+ memory: {
|
|
|
+ currentMem: number
|
|
|
+ allocatedMem: number
|
|
|
+ accumulator: number[]
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
export interface TresContext {
|
|
|
scene: ShallowRef<Scene>
|
|
@@ -18,18 +51,16 @@ export interface TresContext {
|
|
|
controls: Ref<(EventDispatcher & { enabled: boolean }) | null>
|
|
|
renderer: ShallowRef<WebGLRenderer>
|
|
|
raycaster: ShallowRef<Raycaster>
|
|
|
- perf: {
|
|
|
- maxFrames: number
|
|
|
- fps: {
|
|
|
- value: number
|
|
|
- accumulator: number[]
|
|
|
- }
|
|
|
- memory: {
|
|
|
- currentMem: number
|
|
|
- allocatedMem: number
|
|
|
- accumulator: number[]
|
|
|
- }
|
|
|
- }
|
|
|
+ perf: PerformanceState
|
|
|
+ render: RenderState
|
|
|
+ /**
|
|
|
+ * Invalidates the current frame when renderMode === 'on-demand'
|
|
|
+ */
|
|
|
+ invalidate: () => void
|
|
|
+ /**
|
|
|
+ * Advance one frame when renderMode === 'manual'
|
|
|
+ */
|
|
|
+ advance: () => void
|
|
|
registerCamera: (camera: Camera) => void
|
|
|
setCameraActive: (cameraOrUuid: Camera | string) => void
|
|
|
deregisterCamera: (camera: Camera) => void
|
|
@@ -41,14 +72,18 @@ export function useTresContextProvider({
|
|
|
windowSize,
|
|
|
disableRender,
|
|
|
rendererOptions,
|
|
|
+ emit,
|
|
|
}: {
|
|
|
scene: Scene
|
|
|
canvas: MaybeRef<HTMLCanvasElement>
|
|
|
windowSize: MaybeRefOrGetter<boolean>
|
|
|
disableRender: MaybeRefOrGetter<boolean>
|
|
|
rendererOptions: UseRendererOptions
|
|
|
+ emit: (event: string, ...args: any[]) => void
|
|
|
}): TresContext {
|
|
|
|
|
|
+ const { logWarning } = useLogger()
|
|
|
+
|
|
|
const elementSize = computed(() =>
|
|
|
toValue(windowSize)
|
|
|
? useWindowSize()
|
|
@@ -83,16 +118,47 @@ export function useTresContextProvider({
|
|
|
setCameraActive,
|
|
|
} = useCamera({ sizes, scene })
|
|
|
|
|
|
+ // Render state
|
|
|
+
|
|
|
+ const render: RenderState = {
|
|
|
+ mode: ref<'always' | 'on-demand' | 'manual'>(rendererOptions.renderMode || 'always'),
|
|
|
+ priority: ref(0),
|
|
|
+ frames: ref(0),
|
|
|
+ maxFrames: 60,
|
|
|
+ canBeInvalidated: computed(() => render.mode.value === 'on-demand' && render.frames.value === 0),
|
|
|
+ }
|
|
|
+
|
|
|
+ function invalidate(frames = 1) {
|
|
|
+ // Increase the frame count, ensuring not to exceed a maximum if desired
|
|
|
+ if (rendererOptions.renderMode === 'on-demand') {
|
|
|
+ render.frames.value = Math.min(render.maxFrames, render.frames.value + frames)
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ logWarning('`invalidate` can only be used when `renderMode` is set to `on-demand`')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function advance() {
|
|
|
+ if (rendererOptions.renderMode === 'manual') {
|
|
|
+ render.frames.value = 1
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ logWarning('`advance` can only be used when `renderMode` is set to `manual`')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
const { renderer } = useRenderer(
|
|
|
{
|
|
|
scene,
|
|
|
canvas,
|
|
|
options: rendererOptions,
|
|
|
- contextParts: { sizes, camera },
|
|
|
+ emit,
|
|
|
+ // TODO: replace contextParts with full ctx at https://github.com/Tresjs/tres/issues/516
|
|
|
+ contextParts: { sizes, camera, render, invalidate, advance },
|
|
|
disableRender,
|
|
|
})
|
|
|
|
|
|
- const toProvide: TresContext = {
|
|
|
+ const ctx: TresContext = {
|
|
|
sizes,
|
|
|
scene: localScene,
|
|
|
camera,
|
|
@@ -112,13 +178,19 @@ export function useTresContextProvider({
|
|
|
accumulator: [],
|
|
|
},
|
|
|
},
|
|
|
+ render,
|
|
|
+ advance,
|
|
|
extend,
|
|
|
+ invalidate,
|
|
|
registerCamera,
|
|
|
setCameraActive,
|
|
|
deregisterCamera,
|
|
|
}
|
|
|
|
|
|
- provide('useTres', toProvide)
|
|
|
+ provide('useTres', ctx)
|
|
|
+
|
|
|
+ // Add context to scene.userData
|
|
|
+ ctx.scene.value.userData.tres__context = ctx
|
|
|
|
|
|
// Performance
|
|
|
const updateInterval = 100 // Update interval in milliseconds
|
|
@@ -131,8 +203,8 @@ export function useTresContextProvider({
|
|
|
|
|
|
// Update WebGL Memory Usage (Placeholder for actual logic)
|
|
|
// perf.memory.value = calculateMemoryUsage(gl)
|
|
|
- if (toProvide.scene.value) {
|
|
|
- toProvide.perf.memory.allocatedMem = calculateMemoryUsage(toProvide.scene.value as unknown as TresObject)
|
|
|
+ if (ctx.scene.value) {
|
|
|
+ ctx.perf.memory.allocatedMem = calculateMemoryUsage(ctx.scene.value as unknown as TresObject)
|
|
|
}
|
|
|
|
|
|
// Update memory usage
|
|
@@ -140,24 +212,24 @@ export function useTresContextProvider({
|
|
|
lastUpdateTime = timestamp
|
|
|
|
|
|
// Update FPS
|
|
|
- toProvide.perf.fps.accumulator.push(fps.value as never)
|
|
|
+ ctx.perf.fps.accumulator.push(fps.value as never)
|
|
|
|
|
|
- if (toProvide.perf.fps.accumulator.length > maxFrames) {
|
|
|
- toProvide.perf.fps.accumulator.shift()
|
|
|
+ if (ctx.perf.fps.accumulator.length > maxFrames) {
|
|
|
+ ctx.perf.fps.accumulator.shift()
|
|
|
}
|
|
|
|
|
|
- toProvide.perf.fps.value = fps.value
|
|
|
+ ctx.perf.fps.value = fps.value
|
|
|
|
|
|
// Update memory
|
|
|
if (isSupported.value && memory.value) {
|
|
|
- toProvide.perf.memory.accumulator.push(memory.value.usedJSHeapSize / 1024 / 1024 as never)
|
|
|
+ ctx.perf.memory.accumulator.push(memory.value.usedJSHeapSize / 1024 / 1024 as never)
|
|
|
|
|
|
- if (toProvide.perf.memory.accumulator.length > maxFrames) {
|
|
|
- toProvide.perf.memory.accumulator.shift()
|
|
|
+ if (ctx.perf.memory.accumulator.length > maxFrames) {
|
|
|
+ ctx.perf.memory.accumulator.shift()
|
|
|
}
|
|
|
|
|
|
- toProvide.perf.memory.currentMem
|
|
|
- = toProvide.perf.memory.accumulator.reduce((a, b) => a + b, 0) / toProvide.perf.memory.accumulator.length
|
|
|
+ ctx.perf.memory.currentMem
|
|
|
+ = ctx.perf.memory.accumulator.reduce((a, b) => a + b, 0) / ctx.perf.memory.accumulator.length
|
|
|
|
|
|
}
|
|
|
}
|
|
@@ -167,7 +239,7 @@ export function useTresContextProvider({
|
|
|
let accumulatedTime = 0
|
|
|
const interval = 1 // Interval in milliseconds, e.g., 1000 ms = 1 second
|
|
|
|
|
|
- const { pause, resume } = useRafFn(({ delta }) => {
|
|
|
+ const { pause } = useRafFn(({ delta }) => {
|
|
|
if (!window.__TRES__DEVTOOLS__) return
|
|
|
|
|
|
updatePerformanceData({ timestamp: performance.now() })
|
|
@@ -177,7 +249,7 @@ export function useTresContextProvider({
|
|
|
|
|
|
// Check if the accumulated time is greater than or equal to the interval
|
|
|
if (accumulatedTime >= interval) {
|
|
|
- window.__TRES__DEVTOOLS__.cb(toProvide)
|
|
|
+ window.__TRES__DEVTOOLS__.cb(ctx)
|
|
|
|
|
|
// Reset the accumulated time
|
|
|
accumulatedTime = 0
|
|
@@ -189,7 +261,7 @@ export function useTresContextProvider({
|
|
|
pause()
|
|
|
})
|
|
|
|
|
|
- return toProvide
|
|
|
+ return ctx
|
|
|
}
|
|
|
|
|
|
export function useTresContext(): TresContext {
|