diff --git a/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue b/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue
index aae3c2e6..63fabd10 100644
--- a/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue
+++ b/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue
@@ -137,6 +137,14 @@ function handleHoverLeave({ item }) {
+
+
+
+
+
diff --git a/app/stores/hybrid_viewer.js b/app/stores/hybrid_viewer.js
index dbd05268..74e1bfe1 100644
--- a/app/stores/hybrid_viewer.js
+++ b/app/stores/hybrid_viewer.js
@@ -9,6 +9,7 @@ import {
WHEEL_TIME_OUT_MS,
applySnapshot,
computeAverageBrightness,
+ focusCameraOnBounds,
getCameraOptions,
performCameraOrientation,
performClickPicking,
@@ -159,6 +160,18 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
syncRemoteCamera();
}
+ function focusCameraOnObject(id) {
+ if (!hybridDb[id]) {
+ return;
+ }
+ const bounds = hybridDb[id].actor.getBounds();
+ focusCameraOnBounds(bounds, {
+ genericRenderWindow: genericRenderWindow.value,
+ imageStyle,
+ syncRemoteCamera,
+ });
+ }
+
function setCameraOrientation(orientation) {
performCameraOrientation(orientation, {
genericRenderWindow: genericRenderWindow.value,
@@ -229,6 +242,7 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
return;
}
is_moving.value = false;
+ genericRenderWindow.value.getRenderer().resetCameraClippingRange();
syncRemoteCamera();
},
});
@@ -240,6 +254,7 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
clearTimeout(wheelEventEndTimeout);
wheelEventEndTimeout = setTimeout(() => {
is_moving.value = false;
+ genericRenderWindow.value.getRenderer().resetCameraClippingRange();
syncRemoteCamera();
}, WHEEL_TIME_OUT_MS);
});
@@ -309,6 +324,7 @@ export const useHybridViewerStore = defineStore("hybridViewer", () => {
remoteRender,
resize,
resetCamera,
+ focusCameraOnObject,
setCameraOrientation,
setContainer,
zScale,
diff --git a/app/utils/local/scripts.js b/app/utils/local/scripts.js
index 84459372..2f9b8808 100644
--- a/app/utils/local/scripts.js
+++ b/app/utils/local/scripts.js
@@ -8,9 +8,32 @@ import { appMode } from "./app_mode.js";
function commandExistsSync(execName) {
const envPath = process.env.PATH || "";
- return envPath.split(path.delimiter).some((dir) => {
+ const paths = envPath.split(path.delimiter);
+
+ let currentDir = process.cwd();
+ while (currentDir !== path.parse(currentDir).root) {
+ const venvScripts = path.join(
+ currentDir,
+ ".venv",
+ process.platform === "win32" ? "Scripts" : "bin",
+ );
+ if (fs.existsSync(venvScripts)) {
+ paths.unshift(venvScripts);
+ break;
+ }
+ currentDir = path.dirname(currentDir);
+ }
+
+ return paths.some((dir) => {
const filePath = path.join(dir, execName);
- return fs.existsSync(filePath) && fs.statSync(filePath).isFile();
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) return true;
+ if (process.platform === "win32") {
+ return [".exe", ".cmd", ".bat", ".ps1"].some((ext) => {
+ const withExt = `${filePath}${ext}`;
+ return fs.existsSync(withExt) && fs.statSync(withExt).isFile();
+ });
+ }
+ return false;
});
}
diff --git a/internal/stores/hybrid_viewer.js b/internal/stores/hybrid_viewer.js
index 04d72b14..952970ba 100644
--- a/internal/stores/hybrid_viewer.js
+++ b/internal/stores/hybrid_viewer.js
@@ -129,6 +129,20 @@ function centerCameraOnPosition(camera, pickedPosition) {
);
}
+function focusCameraOnBounds(bounds, options) {
+ const { genericRenderWindow, imageStyle, syncRemoteCamera } = options;
+ if (!bounds || bounds.length < 6 || bounds.some((v) => !isFinite(v))) {
+ return;
+ }
+ const renderer = genericRenderWindow.getRenderer();
+ renderer.resetCamera(bounds);
+ if (imageStyle) {
+ imageStyle.opacity = 0;
+ }
+ genericRenderWindow.getRenderWindow().render();
+ syncRemoteCamera();
+}
+
function performClickPicking(event, options) {
const { container, viewerStore, viewer_schemas, genericRenderWindow, syncRemoteCamera } = options;
const rect = container.getBoundingClientRect();
@@ -270,6 +284,7 @@ export {
applySnapshot,
centerCameraOnPosition,
computeAverageBrightness,
+ focusCameraOnBounds,
getCameraOptions,
performCameraOrientation,
performClickPicking,