diff --git a/CHANGELOG.md b/CHANGELOG.md index dd69f369d3903161dc701177b68582e0c78db685..1ce156f5543e9b1e57a6ed05ff7aee1ae3d1333e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ n - Add various options to customize the axes camera-helper - Fix issue with texture-mesh color smoothing when changing themes - Add fast boundary helper and corresponding unit trait +- Add Observable for Canvas3D commits ## [v3.30.0] - 2023-01-29 diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index b65f42eb74df809aabf86620e4d5cbd07f911673..aeb8d12ceac26f586dd281654de73eb64efceb38 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -260,6 +260,7 @@ interface Canvas3D { notifyDidDraw: boolean, readonly didDraw: BehaviorSubject<now.Timestamp> readonly commited: BehaviorSubject<now.Timestamp> + readonly commitQueueSize: BehaviorSubject<number> readonly reprCount: BehaviorSubject<number> readonly resized: BehaviorSubject<any> @@ -306,6 +307,7 @@ namespace Canvas3D { let startTime = now(); const didDraw = new BehaviorSubject<now.Timestamp>(0 as now.Timestamp); const commited = new BehaviorSubject<now.Timestamp>(0 as now.Timestamp); + const commitQueueSize = new BehaviorSubject<number>(0); const { gl, contextRestored } = webgl; @@ -593,7 +595,11 @@ namespace Canvas3D { // snapshot the current bounding sphere of visible objects Sphere3D.copy(oldBoundingSphereVisible, scene.boundingSphereVisible); - if (!scene.commit(isSynchronous ? void 0 : sceneCommitTimeoutMs)) return false; + if (!scene.commit(isSynchronous ? void 0 : sceneCommitTimeoutMs)) { + commitQueueSize.next(scene.commitQueueSize); + return false; + } + commitQueueSize.next(0); if (helper.debug.isEnabled) helper.debug.update(); if (!p.camera.manualReset && (reprCount.value === 0 || shouldResetCamera())) { @@ -790,6 +796,7 @@ namespace Canvas3D { set notifyDidDraw(v: boolean) { notifyDidDraw = v; }, didDraw, commited, + commitQueueSize, reprCount, resized, setProps: (properties, doNotRequestDraw = false) => { diff --git a/src/mol-gl/commit-queue.ts b/src/mol-gl/commit-queue.ts index c0355e3cc322d68f4813bd64a9b458a40ffbf8e7..c4f6e3824b7c984dcf9b7fe929dfaf774ef6089e 100644 --- a/src/mol-gl/commit-queue.ts +++ b/src/mol-gl/commit-queue.ts @@ -19,6 +19,10 @@ export class CommitQueue { return this.removeList.count === 0 && this.addList.count === 0; } + get size() { + return this.removeMap.size + this.addMap.size; + } + add(o: GraphicsRenderObject) { if (this.removeMap.has(o)) { const a = this.removeMap.get(o)!; diff --git a/src/mol-gl/scene.ts b/src/mol-gl/scene.ts index a8d32ab433578eadd79980ce165fb49dc9864cfe..2f84b7541b13697eca009b64ae3f34500583f018 100644 --- a/src/mol-gl/scene.ts +++ b/src/mol-gl/scene.ts @@ -77,6 +77,7 @@ interface Scene extends Object3D { remove: (o: GraphicsRenderObject) => void commit: (maxTimeMs?: number) => boolean readonly needsCommit: boolean + readonly commitQueueSize: number has: (o: GraphicsRenderObject) => boolean clear: () => void forEach: (callbackFn: (value: GraphicsRenderable, key: GraphicsRenderObject) => void) => void @@ -279,6 +280,7 @@ namespace Scene { add: (o: GraphicsRenderObject) => commitQueue.add(o), remove: (o: GraphicsRenderObject) => commitQueue.remove(o), commit: (maxTime = Number.MAX_VALUE) => commit(maxTime), + get commitQueueSize() { return commitQueue.size; }, get needsCommit() { return !commitQueue.isEmpty; }, has: (o: GraphicsRenderObject) => { return renderableMap.has(o); diff --git a/src/mol-plugin-ui/task.tsx b/src/mol-plugin-ui/task.tsx index f0520f683fd552fb4d75fe51ac194ee585ca662f..c262ad8db54519bbda309e66efe8754b4a718af8 100644 --- a/src/mol-plugin-ui/task.tsx +++ b/src/mol-plugin-ui/task.tsx @@ -11,6 +11,7 @@ import { Progress } from '../mol-task'; import { IconButton } from './controls/common'; import { CancelSvg } from './controls/icons'; import { useContext, useEffect, useState } from 'react'; +import { useBehavior } from './hooks/use-behavior'; export function BackgroundTaskProgress() { const plugin = useContext(PluginReactContext); @@ -36,6 +37,22 @@ export function BackgroundTaskProgress() { return <div className='msp-background-tasks'> {tracked.valueSeq().map(e => <ProgressEntry key={e!.id} event={e!} />)} + <CanvasCommitState /> + </div>; +} + +function CanvasCommitState() { + const plugin = useContext(PluginReactContext); + const queueSize = useBehavior(plugin.canvas3d?.commitQueueSize); + + if (!queueSize) return null; + + return <div className='msp-task-state'> + <div> + <div> + Commiting renderables... {queueSize} remaining + </div> + </div> </div>; }