Skip to content

Commit fde8cf0

Browse files
authored
Merge pull request #81 from vimaec/sroberge/ultra_update
Sroberge/ultra update
2 parents 8b21bb0 + af5f611 commit fde8cf0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1414
-1514
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
node_modules
22
dist
33
docs
4+
docs2
45
src/pages/*.vim

package.json

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vim-web",
3-
"version": "0.4.1",
3+
"version": "0.5.0-dev.17",
44
"description": "A demonstration app built on top of the vim-webgl-viewer",
55
"type": "module",
66
"files": [
@@ -23,13 +23,12 @@
2323
"scripts": {
2424
"dev": "vite",
2525
"eslint": "eslint --ext .js,.ts,.tsx src --fix",
26-
"documentation": "typedoc --entryPoints src/vim-web/index.ts --entryPointStrategy expand --out docs --excludeProtected --excludeExternals --excludePrivate",
27-
"declarations": "tsc --project tsconfig.json --declaration --emitDeclarationOnly --outdir ./dist/types",
28-
"build": "vite build --config vite.config.js && npm run declarations",
29-
"package": "npm run build && npm publish",
26+
"documentation": "typedoc --entryPoints src/vim-web/index.ts --entryPointStrategy expand --out docs2 --excludeProtected --excludeExternals --excludePrivate",
27+
"declarations": "tsc -p tsconfig.types.json",
28+
"build": "vite build && npm run declarations",
3029
"publish:package": "npm run build && npm publish",
31-
"publish:documentation": "npm run documentation && gh-pages -d docs",
32-
"publish": "npm run publish:package && npm run publish:documentation"
30+
"publish:documentation": "npm run documentation && gh-pages -d docs2",
31+
"publish:both": "npm run publish:package && npm run publish:documentation"
3332
},
3433
"devDependencies": {
3534
"@types/dom-webcodecs": "^0.1.13",

src/vim-web/core-viewers/shared/inputAdapter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export interface IInputAdapter{
44
init: () => void
55

66
toggleOrthographic: () => void
7+
toggleCameraOrbitMode: () => void
78
resetCamera: () => void
89
clearSelection: () => void
910
frameCamera: () => void

src/vim-web/core-viewers/shared/inputHandler.ts

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,6 @@ export class InputHandler extends BaseInputHandler {
6363
this.rotateSpeed = settings.rotateSpeed ?? 1
6464
this.orbitSpeed = settings.orbitSpeed ?? 1
6565

66-
this.reg(document, 'contextmenu', (e: MouseEvent) => {
67-
this._onContextMenu.dispatch(new THREE.Vector2(e.clientX, e.clientY))
68-
e.preventDefault()
69-
})
7066
this.keyboard = new KeyboardHandler(canvas)
7167
this.mouse = new MouseHandler(canvas)
7268
this.touch = new TouchHandler(canvas)
@@ -76,13 +72,9 @@ export class InputHandler extends BaseInputHandler {
7672
this.keyboard.onKeyUp = (key: string) => adapter.keyUp(key)
7773

7874
this.keyboard.registerKeyUp('KeyP', 'replace', () => adapter.toggleOrthographic());
79-
this.keyboard.registerKeyUp('Equal', 'replace', () => this.moveSpeed++);
80-
this.keyboard.registerKeyUp('Minus', 'replace', () => this.moveSpeed--);
81-
this.keyboard.registerKeyUp('Space', 'replace', () => {
82-
this._pointerActive = this._pointerActive === PointerMode.ORBIT ? PointerMode.LOOK : PointerMode.ORBIT;
83-
this._pointerFallback = this._pointerActive;
84-
this._onPointerModeChanged.dispatch();
85-
});
75+
this.keyboard.registerKeyUp(['Equal', 'NumpadAdd'], 'replace', () => this.moveSpeed++);
76+
this.keyboard.registerKeyUp(['Minus', 'NumpadSubtract'], 'replace', () => this.moveSpeed--);
77+
this.keyboard.registerKeyUp('Space', 'replace', () => adapter.toggleCameraOrbitMode());
8678
this.keyboard.registerKeyUp('Home', 'replace', () => adapter.resetCamera());
8779
this.keyboard.registerKeyUp('Escape', 'replace', () => adapter.clearSelection());
8880
this.keyboard.registerKeyUp('KeyF', 'replace', () => {
@@ -95,18 +87,29 @@ export class InputHandler extends BaseInputHandler {
9587
}
9688

9789
// Mouse controls
90+
this.mouse.onContextMenu = (pos: THREE.Vector2) => this._onContextMenu.dispatch(pos);
9891
this.mouse.onButtonDown = adapter.mouseDown
9992
this.mouse.onMouseMove = adapter.mouseMove
100-
this.mouse.onButtonUp = adapter.mouseUp
93+
this.mouse.onButtonUp = (pos: THREE.Vector2, button: number) => {
94+
this.pointerOverride = undefined
95+
adapter.mouseUp(pos, button)
96+
}
10197
this.mouse.onDrag = (delta: THREE.Vector2, button: number) =>{
10298
if(button === 0){
103-
if(this._pointerActive === PointerMode.ORBIT) adapter.orbitCamera(toRotation(delta, this.orbitSpeed))
104-
if(this._pointerActive === PointerMode.LOOK) adapter.rotateCamera(toRotation(delta, this.rotateSpeed))
105-
if(this._pointerActive === PointerMode.PAN) adapter.panCamera(delta)
106-
if(this._pointerActive === PointerMode.ZOOM) adapter.dollyCamera(delta)
99+
if(this.pointerActive === PointerMode.ORBIT) adapter.orbitCamera(toRotation(delta, this.orbitSpeed))
100+
if(this.pointerActive === PointerMode.LOOK) adapter.rotateCamera(toRotation(delta, this.rotateSpeed))
101+
if(this.pointerActive === PointerMode.PAN) adapter.panCamera(delta)
102+
if(this.pointerActive === PointerMode.ZOOM) adapter.dollyCamera(delta)
107103
}
108-
if(button === 2) adapter.rotateCamera(toRotation(delta,1))
109-
if(button === 1) adapter.panCamera(delta)
104+
if(button === 2){
105+
this.pointerOverride = PointerMode.LOOK
106+
adapter.rotateCamera(toRotation(delta,1))
107+
108+
}
109+
if(button === 1){
110+
this.pointerOverride = PointerMode.PAN
111+
adapter.panCamera(delta)
112+
}
110113
}
111114

112115
this.mouse.onClick = (pos: THREE.Vector2, modif: boolean) => adapter.selectAtPointer(pos, modif)

src/vim-web/core-viewers/shared/keyboardHandler.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,12 @@ export class KeyboardHandler extends BaseInputHandler {
126126
* @param code The event.code of the key.
127127
* @param handler Callback invoked on key up.
128128
*/
129-
public registerKeyUp(code: string, mode: CallbackMode, handler: () => void): void {
130-
this.registerKey(this.keyUpHandlers, code, mode, handler);
129+
public registerKeyUp(code: string | string[], mode: CallbackMode, handler: () => void): void {
130+
if (Array.isArray(code)) {
131+
code.forEach(c => this.registerKey(this.keyUpHandlers, c, mode, handler));
132+
} else {
133+
this.registerKey(this.keyUpHandlers, code, mode, handler);
134+
}
131135
}
132136

133137
private registerKey(map: Map<string, () => void>, code: string, mode: CallbackMode, callback: () => void){

src/vim-web/core-viewers/shared/mouseHandler.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export class MouseHandler extends BaseInputHandler {
1919
onClick: (position: THREE.Vector2, ctrl: boolean) => void;
2020
onDoubleClick: (position: THREE.Vector2) => void;
2121
onWheel: (value: number, ctrl: boolean) => void;
22+
onContextMenu: (position: THREE.Vector2) => void;
2223

2324
constructor(canvas: HTMLCanvasElement) {
2425
super(canvas);
@@ -64,6 +65,7 @@ export class MouseHandler extends BaseInputHandler {
6465
this.handleDoubleClick(event);
6566
}else{
6667
this.handleMouseClick(event);
68+
this.handleContextMenu(event);
6769
}
6870
event.preventDefault();
6971
}
@@ -82,6 +84,20 @@ export class MouseHandler extends BaseInputHandler {
8284
this.onClick?.(pos, modif);
8385
}
8486

87+
private async handleContextMenu(event: PointerEvent): Promise<void> {
88+
if (event.pointerType !== 'mouse') return;
89+
if(event.button !== 2) return;
90+
91+
const pos = this.relativePosition(event);
92+
93+
if (!Utils.almostEqual(this._lastMouseDownPosition, pos, 0.01)) {
94+
return;
95+
}
96+
97+
this.onContextMenu?.(new THREE.Vector2(event.clientX, event.clientY));
98+
}
99+
100+
85101
private handlePointerMove(event: PointerEvent): void {
86102
if (event.pointerType !== 'mouse') return;
87103
this._canvas.focus();
@@ -143,13 +159,25 @@ class CaptureHandler {
143159

144160
class DoubleClickHandler {
145161
private _lastClickTime: number = 0;
146-
private _clickDelay: number = 300; // Delay in milliseconds to consider a double click
162+
private _clickDelay: number = 300; // Max time between clicks for double-click
163+
private _lastClickPosition: THREE.Vector2 | null = null;
164+
private _positionThreshold: number = 5; // Max pixel distance between clicks
147165

148-
checkForDoubleClick(event: MouseEvent) {
166+
checkForDoubleClick(event: MouseEvent): boolean {
149167
const currentTime = Date.now();
168+
const currentPosition = new THREE.Vector2(event.clientX, event.clientY);
150169
const timeDiff = currentTime - this._lastClickTime;
170+
171+
const isClose =
172+
this._lastClickPosition !== null &&
173+
this._lastClickPosition.distanceTo(currentPosition) < this._positionThreshold;
174+
175+
const isWithinTime = timeDiff < this._clickDelay;
176+
151177
this._lastClickTime = currentTime;
152-
return timeDiff < this._clickDelay;
178+
this._lastClickPosition = currentPosition;
179+
180+
return isClose && isWithinTime;
153181
}
154182
}
155183

src/vim-web/core-viewers/shared/vim.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export interface IVim<T extends IVimElement> {
2626
* @param instance - The instance index of the of one of the instance included in the element.
2727
* @returns The object corresponding to the instance, or undefined if not found.
2828
*/
29-
getElementFromInstanceIndex(instance: number): T | undefined
29+
getElement(instance: number): T | undefined
3030

3131
/**
3232
* Retrieves the element associated with the specified id.

src/vim-web/core-viewers/ultra/camera.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ export class Camera implements ICamera {
8484
* @param segment - Optional segment to save as the camera position
8585
*/
8686
async save(segment?: Segment){
87-
this._savedPosition = segment ?? await this._rpc.RPCGetCameraPosition()
87+
this._savedPosition = segment ?? await this._rpc.RPCGetCameraView()
8888
}
8989

9090
/**
9191
* Resets the camera to the last saved position
9292
*/
9393
restoreSavedPosition(blendTime: number = this._defaultBlendTime){
9494
if(!this._savedPosition) return
95-
this._rpc.RPCSetCameraPosition(this._savedPosition, blendTime)
95+
this._rpc.RPCSetCameraView(this._savedPosition, blendTime)
9696
}
9797

9898
/**
@@ -102,7 +102,7 @@ export class Camera implements ICamera {
102102
restoreLastPosition(blendTime: number = this._defaultBlendTime){
103103
if(this._lastPosition?.isValid()){
104104
console.log('Restoring camera position: ', this._lastPosition)
105-
this._rpc.RPCSetCameraPosition(this._lastPosition, blendTime)
105+
this._rpc.RPCSetCameraView(this._lastPosition, blendTime)
106106
}
107107
}
108108

@@ -120,7 +120,7 @@ export class Camera implements ICamera {
120120
}
121121

122122
set(position: THREE.Vector3, target: THREE.Vector3, blendTime: number = this._defaultBlendTime){
123-
this._rpc.RPCSetCameraPosition(new Segment(position, target), blendTime)
123+
this._rpc.RPCSetCameraView(new Segment(position, target), blendTime)
124124
}
125125

126126
/**
@@ -137,7 +137,7 @@ export class Camera implements ICamera {
137137
* @returns Promise that resolves when the framing animation is complete
138138
*/
139139
async frameAll (blendTime: number = this._defaultBlendTime): Promise<Segment | undefined> {
140-
const segment = await this._rpc.RPCFrameAll(blendTime)
140+
const segment = await this._rpc.RPCFrameScene(blendTime)
141141
this._savedPosition = this._savedPosition ?? segment
142142
return segment
143143
}
@@ -148,31 +148,32 @@ export class Camera implements ICamera {
148148
* @param blendTime - Duration of the camera animation in seconds (defaults to 0.5)
149149
*/
150150
async frameBox(box: THREE.Box3, blendTime: number = this._defaultBlendTime) : Promise<Segment | undefined> {
151-
const segment = await this._rpc.RPCFrameBox(box, blendTime)
151+
152+
const segment = await this._rpc.RPCFrameAABB(box, blendTime)
152153
this._savedPosition = this._savedPosition ?? segment
153154
return segment
154155
}
155156

156157
/**
157158
* Frames specific nodes of a Vim model in the camera view
158159
* @param vim - The Vim model containing the nodes to frame
159-
* @param nodes - Array of node indices to frame, or 'all' to frame the entire model
160+
* @param elements - Array of element indices to frame, or 'all' to frame the entire model
160161
* @param blendTime - Duration of the camera animation in seconds (defaults to 0.5)
161162
* @returns Promise that resolves when the framing animation is complete
162163
*/
163-
async frameVim(vim: Vim, nodes: number[] | 'all', blendTime: number = this._defaultBlendTime): Promise<Segment | undefined> {
164+
async frameVim(vim: Vim, elements: number[] | 'all', blendTime: number = this._defaultBlendTime): Promise<Segment | undefined> {
164165
let segment: Segment | undefined
165-
if (nodes === 'all') {
166+
if (elements === 'all') {
166167
segment = await this._rpc.RPCFrameVim(vim.handle, blendTime);
167168
} else {
168-
segment = await this._rpc.RPCFrameInstances(vim.handle, nodes, blendTime);
169+
segment = await this._rpc.RPCFrameElements(vim.handle, elements, blendTime);
169170
}
170171
this._savedPosition = this._savedPosition ?? segment
171172
return segment
172173
}
173174

174175
async frameObject(object: Element3D, blendTime: number = this._defaultBlendTime) : Promise<Segment | undefined> {
175-
const segment = await this._rpc.RPCFrameInstances(object.vim.handle, [object.instance], blendTime)
176+
const segment = await this._rpc.RPCFrameElements(object.vim.handle, [object.element], blendTime)
176177
this._savedPosition = this._savedPosition ?? segment
177178
return segment
178179
}

0 commit comments

Comments
 (0)