mirror of
https://github.com/yeicor-3d/yet-another-cad-viewer.git
synced 2025-12-20 06:27:04 +01:00
better model updates, broken tool/selection init
This commit is contained in:
30
src/App.vue
30
src/App.vue
@@ -1,6 +1,6 @@
|
|||||||
<!--suppress SillyAssignmentJS -->
|
<!--suppress SillyAssignmentJS -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {defineAsyncComponent, provide, Ref, ref, shallowRef} from "vue";
|
import {defineAsyncComponent, provide, Ref, ref, shallowRef, triggerRef} from "vue";
|
||||||
import Sidebar from "./misc/Sidebar.vue";
|
import Sidebar from "./misc/Sidebar.vue";
|
||||||
import Loading from "./misc/Loading.vue";
|
import Loading from "./misc/Loading.vue";
|
||||||
import Tools from "./tools/Tools.vue";
|
import Tools from "./tools/Tools.vue";
|
||||||
@@ -23,25 +23,23 @@ const ModelViewerWrapper = defineAsyncComponent({
|
|||||||
|
|
||||||
let openSidebarsByDefault: Ref<boolean> = ref(window.innerWidth > 1200);
|
let openSidebarsByDefault: Ref<boolean> = ref(window.innerWidth > 1200);
|
||||||
|
|
||||||
let sceneUrl = ref("")
|
const sceneUrl = ref("")
|
||||||
let viewer: Ref<InstanceType<typeof ModelViewerWrapperT> | null> = ref(null);
|
const viewer: Ref<InstanceType<typeof ModelViewerWrapperT> | null> = ref(null);
|
||||||
let document = shallowRef(new Document());
|
const sceneDocument = shallowRef(new Document());
|
||||||
let models: Ref<InstanceType<typeof Models> | null> = ref(null)
|
provide('sceneDocument', {sceneDocument});
|
||||||
provide('document', document);
|
const models: Ref<InstanceType<typeof Models> | null> = ref(null)
|
||||||
let disableTap = ref(false);
|
const disableTap = ref(false);
|
||||||
let setDisableTap = (val: boolean) => {
|
const setDisableTap = (val: boolean) => disableTap.value = val;
|
||||||
disableTap.value = val;
|
|
||||||
}
|
|
||||||
provide('disableTap', {disableTap, setDisableTap});
|
provide('disableTap', {disableTap, setDisableTap});
|
||||||
|
|
||||||
async function onModelLoadRequest(model: NetworkUpdateEvent) {
|
async function onModelLoadRequest(model: NetworkUpdateEvent) {
|
||||||
await SceneMgr.loadModel(sceneUrl, document, model.name, model.url);
|
sceneDocument.value = await SceneMgr.loadModel(sceneUrl, sceneDocument.value, model.name, model.url);
|
||||||
document.value = document.value.clone(); // Force update from this component!
|
triggerRef(sceneDocument); // Why not triggered automatically?
|
||||||
}
|
}
|
||||||
|
|
||||||
function onModelRemoveRequest(name: string) {
|
async function onModelRemoveRequest(name: string) {
|
||||||
SceneMgr.removeModel(sceneUrl, document, name);
|
sceneDocument.value = await SceneMgr.removeModel(sceneUrl, sceneDocument.value, name);
|
||||||
document.value = document.value.clone(); // Force update from this component!
|
triggerRef(sceneDocument); // Why not triggered automatically?
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the load model event listener
|
// Set up the load model event listener
|
||||||
@@ -76,7 +74,7 @@ async function loadModelManual() {
|
|||||||
<svg-icon type="mdi" :path="mdiPlus"/>
|
<svg-icon type="mdi" :path="mdiPlus"/>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<models ref="models" :viewer="viewer" :document="document" @remove="onModelRemoveRequest"/>
|
<models ref="models" :viewer="viewer" @remove="onModelRemoveRequest"/>
|
||||||
</sidebar>
|
</sidebar>
|
||||||
|
|
||||||
<!-- The right collapsible sidebar has the list of tools -->
|
<!-- The right collapsible sidebar has the list of tools -->
|
||||||
|
|||||||
@@ -9,26 +9,28 @@ import {Matrix4} from 'three/src/math/Matrix4'
|
|||||||
/** This class helps manage SceneManagerData. All methods are static to support reactivity... */
|
/** This class helps manage SceneManagerData. All methods are static to support reactivity... */
|
||||||
export class SceneMgr {
|
export class SceneMgr {
|
||||||
/** Loads a GLB model from a URL and adds it to the viewer or replaces it if the names match */
|
/** Loads a GLB model from a URL and adds it to the viewer or replaces it if the names match */
|
||||||
static async loadModel(sceneUrl: Ref<string>, document: ShallowRef<Document>, name: string, url: string) {
|
static async loadModel(sceneUrl: Ref<string>, document: Document, name: string, url: string): Promise<Document> {
|
||||||
let loadStart = performance.now();
|
let loadStart = performance.now();
|
||||||
|
|
||||||
// Start merging into the current document, replacing or adding as needed
|
// Start merging into the current document, replacing or adding as needed
|
||||||
document.value = await mergePartial(url, name, document.value);
|
document = await mergePartial(url, name, document);
|
||||||
|
|
||||||
|
console.log("Model", name, "loaded in", performance.now() - loadStart, "ms");
|
||||||
|
|
||||||
if (name !== extrasNameValueHelpers) {
|
if (name !== extrasNameValueHelpers) {
|
||||||
// Reload the helpers to fit the new model
|
// Reload the helpers to fit the new model
|
||||||
await this.reloadHelpers(sceneUrl, document);
|
document = await this.reloadHelpers(sceneUrl, document);
|
||||||
} else {
|
} else {
|
||||||
// Display the final fully loaded model
|
// Display the final fully loaded model
|
||||||
await this.showCurrentDoc(sceneUrl, document);
|
let displayStart = performance.now();
|
||||||
|
document = await this.showCurrentDoc(sceneUrl, document);
|
||||||
|
console.log("Scene displayed in", performance.now() - displayStart, "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Model", name, "loaded in", performance.now() - loadStart, "ms");
|
|
||||||
|
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async reloadHelpers(sceneUrl: Ref<string>, document: ShallowRef<Document>) {
|
private static async reloadHelpers(sceneUrl: Ref<string>, document: Document): Promise<Document> {
|
||||||
let bb = SceneMgr.getBoundingBox(document);
|
let bb = SceneMgr.getBoundingBox(document);
|
||||||
|
|
||||||
// Create the helper axes and grid box
|
// Create the helper axes and grid box
|
||||||
@@ -37,14 +39,14 @@ export class SceneMgr {
|
|||||||
newAxes(helpersDoc, bb.getSize(new Vector3()).multiplyScalar(0.5), transform);
|
newAxes(helpersDoc, bb.getSize(new Vector3()).multiplyScalar(0.5), transform);
|
||||||
newGridBox(helpersDoc, bb.getSize(new Vector3()), transform);
|
newGridBox(helpersDoc, bb.getSize(new Vector3()), transform);
|
||||||
let helpersUrl = URL.createObjectURL(new Blob([await toBuffer(helpersDoc)]));
|
let helpersUrl = URL.createObjectURL(new Blob([await toBuffer(helpersDoc)]));
|
||||||
await SceneMgr.loadModel(sceneUrl, document, extrasNameValueHelpers, helpersUrl);
|
return await SceneMgr.loadModel(sceneUrl, document, extrasNameValueHelpers, helpersUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getBoundingBox(document: ShallowRef<Document>): Box3 {
|
static getBoundingBox(document: Document): Box3 {
|
||||||
// Get bounding box of the model and use it to set the size of the helpers
|
// Get bounding box of the model and use it to set the size of the helpers
|
||||||
let bbMin: number[] = [1e6, 1e6, 1e6];
|
let bbMin: number[] = [1e6, 1e6, 1e6];
|
||||||
let bbMax: number[] = [-1e6, -1e6, -1e6];
|
let bbMax: number[] = [-1e6, -1e6, -1e6];
|
||||||
document.value.getRoot().listNodes().forEach(node => {
|
document.getRoot().listNodes().forEach(node => {
|
||||||
if ((node.getExtras()[extrasNameKey] ?? extrasNameValueHelpers) === extrasNameValueHelpers) return;
|
if ((node.getExtras()[extrasNameKey] ?? extrasNameValueHelpers) === extrasNameValueHelpers) return;
|
||||||
let transform = new Matrix4(...node.getWorldMatrix());
|
let transform = new Matrix4(...node.getWorldMatrix());
|
||||||
for (let prim of node.getMesh()?.listPrimitives() ?? []) {
|
for (let prim of node.getMesh()?.listPrimitives() ?? []) {
|
||||||
@@ -64,29 +66,31 @@ export class SceneMgr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Removes a model from the viewer */
|
/** Removes a model from the viewer */
|
||||||
static async removeModel(sceneUrl: Ref<string>, document: ShallowRef<Document>, name: string) {
|
static async removeModel(sceneUrl: Ref<string>, document: Document, name: string): Promise<Document> {
|
||||||
let loadStart = performance.now();
|
let loadStart = performance.now();
|
||||||
|
|
||||||
// Remove the model from the document
|
// Remove the model from the document
|
||||||
document.value = await removeModel(name, document.value)
|
document = await removeModel(name, document)
|
||||||
|
|
||||||
console.log("Model", name, "removed in", performance.now() - loadStart, "ms");
|
console.log("Model", name, "removed in", performance.now() - loadStart, "ms");
|
||||||
|
|
||||||
// Reload the helpers to fit the new model (will also show the document)
|
// Reload the helpers to fit the new model (will also show the document)
|
||||||
await this.reloadHelpers(sceneUrl, document);
|
document = await this.reloadHelpers(sceneUrl, document);
|
||||||
|
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Serializes the current document into a GLB and updates the viewerSrc */
|
/** Serializes the current document into a GLB and updates the viewerSrc */
|
||||||
private static async showCurrentDoc(sceneUrl: Ref<string>, document: ShallowRef<Document>) {
|
private static async showCurrentDoc(sceneUrl: Ref<string>, document: Document): Promise<Document> {
|
||||||
// Make sure the document is fully loaded and ready to be shown
|
// Make sure the document is fully loaded and ready to be shown
|
||||||
document.value = await mergeFinalize(document.value);
|
document = await mergeFinalize(document);
|
||||||
|
|
||||||
// Serialize the document into a GLB and update the viewerSrc
|
// Serialize the document into a GLB and update the viewerSrc
|
||||||
let buffer = await toBuffer(document.value);
|
let buffer = await toBuffer(document);
|
||||||
let blob = new Blob([buffer], {type: 'model/gltf-binary'});
|
let blob = new Blob([buffer], {type: 'model/gltf-binary'});
|
||||||
console.debug("Showing current doc", document, "as", Array.from(buffer));
|
console.debug("Showing current doc", document, "as", Array.from(buffer));
|
||||||
sceneUrl.value = URL.createObjectURL(blob);
|
sceneUrl.value = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
return document;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,9 @@ export const settings = {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
// new URL('../../assets/fox.glb', import.meta.url).href,
|
// new URL('../../assets/fox.glb', import.meta.url).href,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
// new URL('../../assets/logo.glb', import.meta.url).href,
|
new URL('../../assets/logo.glb', import.meta.url).href,
|
||||||
// Websocket URLs automatically listen for new models from the python backend
|
// Websocket URLs automatically listen for new models from the python backend
|
||||||
"ws://192.168.1.132:32323/"
|
// "ws://192.168.1.132:32323/"
|
||||||
],
|
],
|
||||||
displayLoadingEveryMs: 1000, /* How often to display partially loaded models */
|
displayLoadingEveryMs: 1000, /* How often to display partially loaded models */
|
||||||
checkServerEveryMs: 100, /* How often to check for a new server */
|
checkServerEveryMs: 100, /* How often to check for a new server */
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
} from "vuetify/lib/components";
|
} from "vuetify/lib/components";
|
||||||
import {extrasNameKey, extrasNameValueHelpers} from "../misc/gltf";
|
import {extrasNameKey, extrasNameValueHelpers} from "../misc/gltf";
|
||||||
import {Document, Mesh} from "@gltf-transform/core";
|
import {Document, Mesh} from "@gltf-transform/core";
|
||||||
import {inject, ref, ShallowRef, watch} from "vue";
|
import {inject, ref, ShallowRef, watch, Ref} from "vue";
|
||||||
import type ModelViewerWrapper from "../viewer/ModelViewerWrapper.vue";
|
import type ModelViewerWrapper from "../viewer/ModelViewerWrapper.vue";
|
||||||
import {
|
import {
|
||||||
mdiCircleOpacity,
|
mdiCircleOpacity,
|
||||||
@@ -34,8 +34,7 @@ import {Vector3} from "three/src/math/Vector3";
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
meshes: Array<Mesh>,
|
meshes: Array<Mesh>,
|
||||||
viewer: InstanceType<typeof ModelViewerWrapper> | null,
|
viewer: InstanceType<typeof ModelViewerWrapper> | null
|
||||||
document: Document
|
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits<{ remove: [] }>()
|
const emit = defineEmits<{ remove: [] }>()
|
||||||
|
|
||||||
@@ -111,7 +110,7 @@ function onOpacityChange(newOpacity: number) {
|
|||||||
|
|
||||||
watch(opacity, onOpacityChange);
|
watch(opacity, onOpacityChange);
|
||||||
|
|
||||||
let document: ShallowRef<Document> = inject('document');
|
let {sceneDocument}: {sceneDocument: ShallowRef<Document>} = inject('sceneDocument');
|
||||||
|
|
||||||
function onClipPlanesChange() {
|
function onClipPlanesChange() {
|
||||||
let scene = props.viewer?.scene;
|
let scene = props.viewer?.scene;
|
||||||
@@ -126,7 +125,7 @@ function onClipPlanesChange() {
|
|||||||
// Global value for all models, once set it cannot be unset (unknown for other models...)
|
// Global value for all models, once set it cannot be unset (unknown for other models...)
|
||||||
props.viewer.renderer.threeRenderer.localClippingEnabled = true;
|
props.viewer.renderer.threeRenderer.localClippingEnabled = true;
|
||||||
// Due to model-viewer's camera manipulation, the bounding box needs to be transformed
|
// Due to model-viewer's camera manipulation, the bounding box needs to be transformed
|
||||||
bbox = SceneMgr.getBoundingBox(document);
|
bbox = SceneMgr.getBoundingBox(sceneDocument.value);
|
||||||
bbox.applyMatrix4(sceneModel.matrixWorld);
|
bbox.applyMatrix4(sceneModel.matrixWorld);
|
||||||
}
|
}
|
||||||
sceneModel.traverse((child) => {
|
sceneModel.traverse((child) => {
|
||||||
|
|||||||
@@ -5,16 +5,18 @@ import Loading from "../misc/Loading.vue";
|
|||||||
import {Document, Mesh} from "@gltf-transform/core";
|
import {Document, Mesh} from "@gltf-transform/core";
|
||||||
import {extrasNameKey} from "../misc/gltf";
|
import {extrasNameKey} from "../misc/gltf";
|
||||||
import Model from "./Model.vue";
|
import Model from "./Model.vue";
|
||||||
import {ref} from "vue";
|
import {ref, watch, inject, Ref} from "vue";
|
||||||
|
|
||||||
const props = defineProps<{ viewer: InstanceType<typeof ModelViewerWrapper> | null, document: Document }>();
|
const props = defineProps<{ viewer: InstanceType<typeof ModelViewerWrapper> | null }>();
|
||||||
const emit = defineEmits<{ remove: [string] }>()
|
const emit = defineEmits<{ remove: [string] }>()
|
||||||
|
|
||||||
|
let {sceneDocument} = inject<{ sceneDocument: Ref<Document> }>('sceneDocument');
|
||||||
|
|
||||||
let expandedNames = ref<Array<string>>([]);
|
let expandedNames = ref<Array<string>>([]);
|
||||||
|
|
||||||
function meshesList(document: Document): Array<Array<Mesh>> {
|
function meshesList(sceneDocument: Document): Array<Array<Mesh>> {
|
||||||
// Grouped by shared name
|
// Grouped by shared name
|
||||||
return document.getRoot().listMeshes().reduce((acc, mesh) => {
|
return sceneDocument.getRoot().listMeshes().reduce((acc, mesh) => {
|
||||||
let name = mesh.getExtras()[extrasNameKey]?.toString() ?? 'Unnamed';
|
let name = mesh.getExtras()[extrasNameKey]?.toString() ?? 'Unnamed';
|
||||||
let group = acc.find((group) => meshName(group[0]) === name);
|
let group = acc.find((group) => meshName(group[0]) === name);
|
||||||
if (group) {
|
if (group) {
|
||||||
@@ -44,10 +46,9 @@ defineExpose({findModel})
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Loading v-if="!props.document"/>
|
<v-expansion-panels v-for="meshes in meshesList(sceneDocument)" :key="meshName(meshes[0])"
|
||||||
<v-expansion-panels v-else v-for="meshes in meshesList(props.document)" :key="meshName(meshes[0])"
|
|
||||||
v-model="expandedNames" multiple>
|
v-model="expandedNames" multiple>
|
||||||
<model :meshes="meshes" :viewer="props.viewer" :document="props.document" @remove="onRemove(meshes[0])"/>
|
<model :meshes="meshes" :viewer="props.viewer" @remove="onRemove(meshes[0])"/>
|
||||||
</v-expansion-panels>
|
</v-expansion-panels>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export type MObject3D = Object3D & {
|
|||||||
|
|
||||||
let props = defineProps<{ viewer: typeof ModelViewerWrapperT | null }>();
|
let props = defineProps<{ viewer: typeof ModelViewerWrapperT | null }>();
|
||||||
let emit = defineEmits<{ findModel: [string] }>();
|
let emit = defineEmits<{ findModel: [string] }>();
|
||||||
let {setDisableTap} = inject<{setDisableTap: (boolean) => void}>('disableTap');
|
let {setDisableTap} = inject<{ setDisableTap: (boolean) => void }>('disableTap');
|
||||||
let selectionEnabled = ref(false);
|
let selectionEnabled = ref(false);
|
||||||
let selected = defineModel<Array<Intersection<MObject3D>>>({default: []});
|
let selected = defineModel<Array<Intersection<MObject3D>>>({default: []});
|
||||||
let highlightNextSelection = ref([false, false]); // Second is whether selection was enabled before
|
let highlightNextSelection = ref([false, false]); // Second is whether selection was enabled before
|
||||||
@@ -180,11 +180,11 @@ function toggleHighlightNextSelection() {
|
|||||||
|
|
||||||
function toggleShowBoundingBox() {
|
function toggleShowBoundingBox() {
|
||||||
showBoundingBox.value = !showBoundingBox.value;
|
showBoundingBox.value = !showBoundingBox.value;
|
||||||
if (!firstLoad /*bug?*/) updateBoundingBox();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let viewerFound = false
|
let viewerFound = false
|
||||||
let firstLoad = true;
|
let firstLoad = true;
|
||||||
|
let hasListeners = false;
|
||||||
let cameraChangeWaiting = false;
|
let cameraChangeWaiting = false;
|
||||||
let cameraChangeLast = 0
|
let cameraChangeLast = 0
|
||||||
let onCameraChange = () => {
|
let onCameraChange = () => {
|
||||||
@@ -206,29 +206,38 @@ let onCameraChange = () => {
|
|||||||
setTimeout(waitingHandler, 100); // Wait for the camera to stop moving
|
setTimeout(waitingHandler, 100); // Wait for the camera to stop moving
|
||||||
};
|
};
|
||||||
watch(() => props.viewer, (viewer) => {
|
watch(() => props.viewer, (viewer) => {
|
||||||
|
console.log('Viewer changed', viewer)
|
||||||
if (!viewer) return;
|
if (!viewer) return;
|
||||||
if (viewerFound) return;
|
|
||||||
viewerFound = true;
|
|
||||||
let hasListeners = false;
|
|
||||||
// props.viewer.elem may not yet be available, so we need to wait for it
|
// props.viewer.elem may not yet be available, so we need to wait for it
|
||||||
viewer.onElemReady((elem) => {
|
viewer.onElemReady((elem) => {
|
||||||
|
if (viewerFound) return;
|
||||||
|
viewerFound = true;
|
||||||
if (hasListeners) return;
|
if (hasListeners) return;
|
||||||
hasListeners = true;
|
hasListeners = true;
|
||||||
elem.addEventListener('mouseup', selectionListener);
|
elem.addEventListener('mouseup', selectionListener);
|
||||||
elem.addEventListener('mousedown', selectionMoveListener); // Avoid clicking when dragging
|
elem.addEventListener('mousedown', selectionMoveListener); // Avoid clicking when dragging
|
||||||
elem.addEventListener('load', () => {
|
elem.addEventListener('load', () => {
|
||||||
|
console.log('Model loaded')
|
||||||
if (firstLoad) {
|
if (firstLoad) {
|
||||||
toggleShowBoundingBox();
|
toggleShowBoundingBox();
|
||||||
firstLoad = false;
|
firstLoad = false;
|
||||||
} else {
|
|
||||||
updateBoundingBox();
|
|
||||||
}
|
}
|
||||||
|
updateBoundingBox();
|
||||||
});
|
});
|
||||||
|
console.log(elem)
|
||||||
|
if (elem.loaded) {
|
||||||
|
console.log('Model already loaded')
|
||||||
|
if (firstLoad) {
|
||||||
|
toggleShowBoundingBox();
|
||||||
|
firstLoad = false;
|
||||||
|
}
|
||||||
|
updateBoundingBox();
|
||||||
|
}
|
||||||
elem.addEventListener('camera-change', onCameraChange);
|
elem.addEventListener('camera-change', onCameraChange);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let document: ShallowRef<Document> = inject('document');
|
let {sceneDocument}: { sceneDocument: ShallowRef<Document> } = inject('sceneDocument');
|
||||||
|
|
||||||
|
|
||||||
let boundingBoxLines: { [points: string]: number } = {}
|
let boundingBoxLines: { [points: string]: number } = {}
|
||||||
@@ -250,7 +259,7 @@ function updateBoundingBox() {
|
|||||||
}
|
}
|
||||||
bb.applyMatrix4(new Matrix4().makeTranslation(props.viewer?.scene.getTarget()));
|
bb.applyMatrix4(new Matrix4().makeTranslation(props.viewer?.scene.getTarget()));
|
||||||
} else {
|
} else {
|
||||||
bb = SceneMgr.getBoundingBox(document);
|
bb = SceneMgr.getBoundingBox(sceneDocument.value);
|
||||||
}
|
}
|
||||||
// Define each edge of the bounding box, to draw a line for each axis
|
// Define each edge of the bounding box, to draw a line for each axis
|
||||||
let corners = [
|
let corners = [
|
||||||
@@ -361,33 +370,31 @@ function updateDistances() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({onCameraChange})
|
|
||||||
|
|
||||||
// Add keyboard shortcuts
|
// Add keyboard shortcuts
|
||||||
window.addEventListener('keydown', (event) => {
|
window.addEventListener('keydown', (event) => {
|
||||||
if (event.key === 's') {
|
if (event.key === 's') {
|
||||||
if(selectFilter.value == 'Any (S)') toggleSelection();
|
if (selectFilter.value == 'Any (S)') toggleSelection();
|
||||||
else {
|
else {
|
||||||
selectFilter.value = 'Any (S)';
|
selectFilter.value = 'Any (S)';
|
||||||
if(!selectionEnabled.value) toggleSelection();
|
if (!selectionEnabled.value) toggleSelection();
|
||||||
}
|
}
|
||||||
} else if (event.key === 'f') {
|
} else if (event.key === 'f') {
|
||||||
if(selectFilter.value == '(F)aces') toggleSelection();
|
if (selectFilter.value == '(F)aces') toggleSelection();
|
||||||
else {
|
else {
|
||||||
selectFilter.value = '(F)aces';
|
selectFilter.value = '(F)aces';
|
||||||
if(!selectionEnabled.value) toggleSelection();
|
if (!selectionEnabled.value) toggleSelection();
|
||||||
}
|
}
|
||||||
} else if (event.key === 'e') {
|
} else if (event.key === 'e') {
|
||||||
if(selectFilter.value == '(E)dges') toggleSelection();
|
if (selectFilter.value == '(E)dges') toggleSelection();
|
||||||
else {
|
else {
|
||||||
selectFilter.value = '(E)dges';
|
selectFilter.value = '(E)dges';
|
||||||
if(!selectionEnabled.value) toggleSelection();
|
if (!selectionEnabled.value) toggleSelection();
|
||||||
}
|
}
|
||||||
} else if (event.key === 'v') {
|
} else if (event.key === 'v') {
|
||||||
if(selectFilter.value == '(V)ertices') toggleSelection();
|
if (selectFilter.value == '(V)ertices') toggleSelection();
|
||||||
else {
|
else {
|
||||||
selectFilter.value = '(V)ertices';
|
selectFilter.value = '(V)ertices';
|
||||||
if(!selectionEnabled.value) toggleSelection();
|
if (!selectionEnabled.value) toggleSelection();
|
||||||
}
|
}
|
||||||
} else if (event.key === 'b') {
|
} else if (event.key === 'b') {
|
||||||
toggleShowBoundingBox();
|
toggleShowBoundingBox();
|
||||||
|
|||||||
@@ -20,12 +20,14 @@ def build_logo() -> TopoDS_Shape:
|
|||||||
|
|
||||||
return logo_obj.part.wrapped
|
return logo_obj.part.wrapped
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
# Start an offline "server" to merge the CAD part of the logo with the animated GLTF part of the logo
|
# Start an offline "server" to merge the CAD part of the logo with the animated GLTF part of the logo
|
||||||
os.environ['YACV_DISABLE_SERVER'] = '1'
|
os.environ['YACV_DISABLE_SERVER'] = '1'
|
||||||
from yacv_server import show_object, server
|
from yacv_server import show_object, server
|
||||||
|
|
||||||
ASSETS_DIR = os.getenv('ASSETS_DIR', os.path.join(os.path.dirname(__file__), '..', 'assets'))
|
ASSETS_DIR = os.getenv('ASSETS_DIR', os.path.join(os.path.dirname(__file__), '..', 'assets'))
|
||||||
|
|
||||||
# Add the CAD part of the logo to the server
|
# Add the CAD part of the logo to the server
|
||||||
@@ -38,6 +40,7 @@ if __name__ == "__main__":
|
|||||||
async def writer():
|
async def writer():
|
||||||
f.write(await server.export('logo'))
|
f.write(await server.export('logo'))
|
||||||
|
|
||||||
|
|
||||||
asyncio.run(writer())
|
asyncio.run(writer())
|
||||||
|
|
||||||
print('Logo saved to', os.path.join(ASSETS_DIR, 'logo.glb'))
|
print('Logo saved to', os.path.join(ASSETS_DIR, 'logo.glb'))
|
||||||
|
|||||||
Reference in New Issue
Block a user