mirror of
https://github.com/flash555588/ai-model-workbench.git
synced 2026-07-22 06:56:38 +00:00
Cache measurement snap candidates
This commit is contained in:
parent
d20fffbba7
commit
18b78e8e9d
4 changed files with 42 additions and 17 deletions
|
|
@ -6,6 +6,7 @@
|
|||
- Stability: make the direct-view load gate settings-aware for preferred OBJ conversion and keep mobile direct-format reads on Obsidian vault APIs instead of desktop Node path helpers.
|
||||
- UI: upgrade measurement calibration so users can scale the loaded model uniformly from the latest ruler distance, keep overlays anchored in model space, apply locked model-size scaling from one known axis, and verify the workflow through preview automation.
|
||||
- UI: make distance measurement lock the selected object by default and snap endpoints to mesh vertices or visible crease/perimeter triangle edges, filtering coplanar face diagonals and preferring edge projection outside the corner radius, with first-click target selection when needed and Alt/Option-click preserving the older free surface pick as a backup.
|
||||
- Performance: cache selected-target measurement snap candidates while measuring so hover previews do not repeatedly rebuild vertex and edge lists for the same object.
|
||||
- UI: restyle distance measurements as orthographic drawing-style dimension callouts with extension lines, arrowheads, and compact drafting labels instead of thick freehand ruler lines.
|
||||
- UI: remove the preview canvas native hover tooltip while preserving keyboard shortcut metadata for accessibility.
|
||||
- UI: clarify render scale versus measurement scale by showing render resolution as percentages, syncing the toolbar to the active renderer budget, and applying the configured scale to `3dgrid`.
|
||||
|
|
|
|||
6
main.js
6
main.js
File diff suppressed because one or more lines are too long
|
|
@ -116,6 +116,7 @@ import {
|
|||
setMeasurementCanvasActive,
|
||||
snapMeasurementPointToGeometry,
|
||||
unscaleMeasurementPointToBase,
|
||||
type MeasurementGeometrySnapInput,
|
||||
type MeasurementSnapEdgeCandidate,
|
||||
type MeasurementSnapVertexCandidate,
|
||||
type MeasurementReading,
|
||||
|
|
@ -312,6 +313,8 @@ export class BabylonModelPreview implements WorkbenchPreview {
|
|||
private measurementMarkerPoints: Vector3[] = [];
|
||||
private measurementTargetNode: BabylonSelectablePartNode | null = null;
|
||||
private measurementTargetMeshes: AbstractMesh[] = [];
|
||||
private measurementSnapInputCache: MeasurementGeometrySnapInput | null = null;
|
||||
private measurementSnapInputCacheTargetId: number | null = null;
|
||||
private measurementSnapKind: MeasurementSnapKind | null = null;
|
||||
private readonly measurementObservers = new Set<() => void>();
|
||||
private pendingPoint: Vector3 | null = null;
|
||||
|
|
@ -1079,6 +1082,7 @@ export class BabylonModelPreview implements WorkbenchPreview {
|
|||
|
||||
setMeasurementScale(scale: MeasurementScale): void {
|
||||
this.measurementScale = sanitizeMeasurementScale(scale);
|
||||
this.invalidateMeasurementSnapInputCache();
|
||||
this.applyMeasurementModelScale();
|
||||
this.updateMeasurementOverlayPositions();
|
||||
this.updateMeasurementLabels();
|
||||
|
|
@ -1167,6 +1171,7 @@ export class BabylonModelPreview implements WorkbenchPreview {
|
|||
this.measurementBaseRootScaling = new Vector3(1, 1, 1);
|
||||
this.measurementBaseBounds = null;
|
||||
this.measurementMarkerPoints = [];
|
||||
this.invalidateMeasurementSnapInputCache();
|
||||
}
|
||||
|
||||
private applyMeasurementModelScale(): void {
|
||||
|
|
@ -1878,6 +1883,7 @@ export class BabylonModelPreview implements WorkbenchPreview {
|
|||
|
||||
private setMeasurementTargetNode(node: BabylonSelectablePartNode | null, notify = true): void {
|
||||
this.clearMeasurementTargetVisual(false);
|
||||
this.invalidateMeasurementSnapInputCache();
|
||||
const target = node && !isBabylonNodeDisposed(node) ? this.findSelectableNode(node) : null;
|
||||
if (!target || isBabylonNodeDisposed(target)) {
|
||||
this.measurementTargetNode = null;
|
||||
|
|
@ -1940,6 +1946,11 @@ export class BabylonModelPreview implements WorkbenchPreview {
|
|||
}
|
||||
}
|
||||
|
||||
private invalidateMeasurementSnapInputCache(): void {
|
||||
this.measurementSnapInputCache = null;
|
||||
this.measurementSnapInputCacheTargetId = null;
|
||||
}
|
||||
|
||||
private getMeasurementTargetName(): string | null {
|
||||
const target = this.measurementTargetNode;
|
||||
if (!target || isBabylonNodeDisposed(target)) return null;
|
||||
|
|
@ -1977,14 +1988,12 @@ export class BabylonModelPreview implements WorkbenchPreview {
|
|||
return toBabylonVector3(snapped.point);
|
||||
}
|
||||
|
||||
private createMeasurementGeometrySnapInput(): {
|
||||
vertices: MeasurementSnapVertexCandidate[];
|
||||
edges: MeasurementSnapEdgeCandidate[];
|
||||
targetId?: string;
|
||||
vertexRadius: number;
|
||||
} | null {
|
||||
private createMeasurementGeometrySnapInput(): MeasurementGeometrySnapInput | null {
|
||||
const target = this.measurementTargetNode;
|
||||
if (!this.rootMesh || !target || isBabylonNodeDisposed(target)) return null;
|
||||
if (this.measurementSnapInputCache && this.measurementSnapInputCacheTargetId === target.uniqueId) {
|
||||
return this.measurementSnapInputCache;
|
||||
}
|
||||
const meshes = this.getMeasurementTargetMeshes(target);
|
||||
if (meshes.length === 0) return null;
|
||||
|
||||
|
|
@ -2013,12 +2022,15 @@ export class BabylonModelPreview implements WorkbenchPreview {
|
|||
if (vertices.length === 0 && edges.length === 0) return null;
|
||||
const bounds = this.getMeasurementTargetBounds();
|
||||
const size = bounds ? getPreviewBoundsSize(bounds) : { x: 1, y: 1, z: 1 };
|
||||
return {
|
||||
const input = {
|
||||
vertices,
|
||||
edges,
|
||||
targetId,
|
||||
vertexRadius: Math.max(size.x, size.y, size.z, 0.001) * 0.045,
|
||||
};
|
||||
this.measurementSnapInputCache = input;
|
||||
this.measurementSnapInputCacheTargetId = target.uniqueId;
|
||||
return input;
|
||||
}
|
||||
|
||||
private getMeasurementTargetMeshes(target = this.measurementTargetNode): AbstractMesh[] {
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ import {
|
|||
setMeasurementCanvasActive,
|
||||
snapMeasurementPointToGeometry,
|
||||
unscaleMeasurementPointToBase,
|
||||
type MeasurementGeometrySnapInput,
|
||||
type MeasurementSnapEdgeCandidate,
|
||||
type MeasurementSnapVertexCandidate,
|
||||
type MeasurementReading,
|
||||
|
|
@ -299,6 +300,8 @@ export class ThreeModelPreview implements WorkbenchPreview {
|
|||
private measurementMarkerPoints: Vector3[] = [];
|
||||
private measurementTargetObject: Object3D | null = null;
|
||||
private measurementTargetHelper: BoxHelper | null = null;
|
||||
private measurementSnapInputCache: MeasurementGeometrySnapInput | null = null;
|
||||
private measurementSnapInputCacheTarget: Object3D | null = null;
|
||||
private measurementSnapKind: MeasurementSnapKind | null = null;
|
||||
private readonly measurementObservers = new Set<() => void>();
|
||||
private pendingPoint: Vector3 | null = null;
|
||||
|
|
@ -938,6 +941,7 @@ export class ThreeModelPreview implements WorkbenchPreview {
|
|||
|
||||
setMeasurementScale(scale: MeasurementScale): void {
|
||||
this.measurementScale = sanitizeMeasurementScale(scale);
|
||||
this.invalidateMeasurementSnapInputCache();
|
||||
this.applyMeasurementModelScale();
|
||||
this.updateMeasurementOverlayPositions();
|
||||
this.updateMeasurementLabels();
|
||||
|
|
@ -1026,6 +1030,7 @@ export class ThreeModelPreview implements WorkbenchPreview {
|
|||
this.measurementBaseRootScale.set(1, 1, 1);
|
||||
this.measurementBaseBounds = null;
|
||||
this.measurementMarkerPoints = [];
|
||||
this.invalidateMeasurementSnapInputCache();
|
||||
}
|
||||
|
||||
private applyMeasurementModelScale(): void {
|
||||
|
|
@ -2607,6 +2612,7 @@ export class ThreeModelPreview implements WorkbenchPreview {
|
|||
|
||||
private setMeasurementTargetObject(object: Object3D | null, notify = true): void {
|
||||
this.clearMeasurementTargetHelper(false);
|
||||
this.invalidateMeasurementSnapInputCache();
|
||||
const target = object && this.isObjectInLoadedRoot(object) ? object : null;
|
||||
this.measurementTargetObject = target;
|
||||
this.setMeasurementSnapKind(null, false);
|
||||
|
|
@ -2633,6 +2639,11 @@ export class ThreeModelPreview implements WorkbenchPreview {
|
|||
this.measurementTargetHelper.update();
|
||||
}
|
||||
|
||||
private invalidateMeasurementSnapInputCache(): void {
|
||||
this.measurementSnapInputCache = null;
|
||||
this.measurementSnapInputCacheTarget = null;
|
||||
}
|
||||
|
||||
private setMeasurementSnapKind(kind: MeasurementSnapKind | null, notify = true): void {
|
||||
if (this.measurementSnapKind === kind) return;
|
||||
this.measurementSnapKind = kind;
|
||||
|
|
@ -2692,14 +2703,12 @@ export class ThreeModelPreview implements WorkbenchPreview {
|
|||
return new Vector3(snapped.point.x, snapped.point.y, snapped.point.z);
|
||||
}
|
||||
|
||||
private createMeasurementGeometrySnapInput(): {
|
||||
vertices: MeasurementSnapVertexCandidate[];
|
||||
edges: MeasurementSnapEdgeCandidate[];
|
||||
targetId?: string;
|
||||
vertexRadius: number;
|
||||
} | null {
|
||||
private createMeasurementGeometrySnapInput(): MeasurementGeometrySnapInput | null {
|
||||
const target = this.measurementTargetObject;
|
||||
if (!target || !this.isObjectInLoadedRoot(target)) return null;
|
||||
if (this.measurementSnapInputCache && this.measurementSnapInputCacheTarget === target) {
|
||||
return this.measurementSnapInputCache;
|
||||
}
|
||||
const renderables = this.getMeasurementTargetRenderables();
|
||||
if (renderables.length === 0) return null;
|
||||
const vertices: MeasurementSnapVertexCandidate[] = [];
|
||||
|
|
@ -2726,12 +2735,15 @@ export class ThreeModelPreview implements WorkbenchPreview {
|
|||
if (vertices.length === 0 && edges.length === 0) return null;
|
||||
const bounds = this.getMeasurementTargetBounds();
|
||||
const size = bounds ? getPreviewBoundsSize(bounds) : { x: 1, y: 1, z: 1 };
|
||||
return {
|
||||
const input = {
|
||||
vertices,
|
||||
edges,
|
||||
targetId,
|
||||
vertexRadius: Math.max(size.x, size.y, size.z, 0.001) * 0.045,
|
||||
};
|
||||
this.measurementSnapInputCache = input;
|
||||
this.measurementSnapInputCacheTarget = target;
|
||||
return input;
|
||||
}
|
||||
|
||||
private getMeasurementTargetRenderables(): ThreeRenderableObject[] {
|
||||
|
|
|
|||
Loading…
Reference in a new issue