diff --git a/src/index.js b/src/index.js index aa0091a9c00947e77d0df1eb4cc07c1d55fff119..efe2f3a7a19e635a2339e6d3cd83b1d7e449f097 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,12 @@ import { ToolboxType, WindowSlot, NotificationType } from '@vcmap/ui'; -import { Cesium3DTileStyle, Math as CMath, ConstantProperty, Transforms, HeadingPitchRoll, Cesium3DTileset } from '@vcmap-cesium/engine'; -import { AbstractInteraction, EventType } from '@vcmap/core'; +import { Cesium3DTileStyle, Math as CMath, Cartesian3, ConstantProperty, Transforms, HeadingPitchRoll, Cesium3DTileset, Matrix4 } from '@vcmap-cesium/engine'; +import { AbstractInteraction, createTransformationHandler, EventType, ScaleInteraction, TransformationHandler, TransformationMode } from '@vcmap/core'; import { name, version, mapVersion } from '../package.json'; -import BIMOptions, { windowId } from './upload.vue'; -import objectList, {} from './objectList.vue'; +import BIMOptions, { bimOptionsId } from './upload.vue'; +import objectList, { objectListId } from './objectList.vue'; +import scaleControl, { scaleControlId } from './scaleControl.vue'; -let url; let model; let conditions = [[true, true]]; let activeMouseEvent; @@ -16,6 +16,7 @@ const hpRollMap = new Map(); let placedModels = []; let hpRoll; let app; +let currentlyScaledModel; const hidingFeatures = []; const hidingListener = function(tile) { let allHidden = true; @@ -34,7 +35,7 @@ const hidingListener = function(tile) { const primitives = app.maps.activeMap.getScene().primitives; for (let i = 0; i < primitives.length; i++) { const tileSet = primitives.get(i); - if (!tileSet instanceof Cesium3DTileset) { + if (!(tileSet instanceof Cesium3DTileset)) { continue; } tileSet.tileVisible.removeEventListener(hidingListener); @@ -46,6 +47,40 @@ function updateHideCondition(gmlId) { conditions.unshift(['${gml_id} === "' + gmlId + '"', false]); } +function setScale(scaleValue) { + const vcMap = app.maps.activeMap; + const name = currentlyScaledModel.name; + const position = currentlyScaledModel.position.getValue(); + const orientation = currentlyScaledModel.orientation; + const uri = currentlyScaledModel.model.uri; + + vcMap.getEntities().remove(currentlyScaledModel); + removePlacedModel(currentlyScaledModel); + + // Add the new model to the viewer + const newModel = vcMap.getEntities().add({ + name: name, + position: position, + orientation: orientation, + model: { + uri: uri, + scale: scaleValue, + show: true, + }, + }); + placedModels.push({ + model: newModel, + name: name, + }); + + const oldHpRoll = hpRollMap.get(currentlyScaledModel); + if (oldHpRoll !== undefined) { + hpRollMap.set(newModel, oldHpRoll); + } + + currentlyScaledModel = newModel; +} + function saveObjects() { const outputObject = {}; const outputArray = []; @@ -59,6 +94,7 @@ function saveObjects() { name: m.name, position: m.model.position.getValue(), heading: heading, + scale: m.model.model.scale.getValue(), }); } outputObject.placedObjects = outputArray; @@ -69,7 +105,7 @@ function saveObjects() { outputObject.hiddenObjects = hiddenObjects; let textData = JSON.stringify(outputObject); let blobData = new Blob([textData], {type: "application/json"}); - saveFile('ObjektPlatzierung.json', window.URL.createObjectURL(blobData)); + saveFile('ObjektPositionierung.json', window.URL.createObjectURL(blobData)); } function saveFile(fileName, urlFile){ @@ -89,7 +125,6 @@ function setupModel(vcsApp, windowPos, url, name) { const scene = vcMap.getScene(); const ray = scene.camera.getPickRay(windowPos); const center = scene.globe.pick(ray, scene); - heightDif = 0; // Add the model to the viewer model = vcMap.getEntities().add({ name: name, @@ -239,6 +274,7 @@ export default function smartVillagesPlugin(config, baseUrl) { }, pluginState, setupModel, + setScale, saveObjects, loadObjects(app) { // Create an input element @@ -283,6 +319,7 @@ export default function smartVillagesPlugin(config, baseUrl) { position: loadingObject.position, model: { uri: objectUrl, + scale: loadingObject.scale, show: true, }, }); @@ -304,15 +341,17 @@ export default function smartVillagesPlugin(config, baseUrl) { loops: 0, }); } - const primitives = vcMap.getScene().primitives; - for (let i = 0; i < primitives.length; i++) { - const tileSet = primitives.get(i); - if (!tileSet instanceof Cesium3DTileset) { - continue; + if (objects.hiddenObjects.length > 0) { + const primitives = vcMap.getScene().primitives; + for (let i = 0; i < primitives.length; i++) { + const tileSet = primitives.get(i); + if (!(tileSet instanceof Cesium3DTileset)) { + continue; + } + tileSet.tileVisible.addEventListener(hidingListener); } - tileSet.tileVisible.addEventListener(hidingListener); + } - } reader.readAsText(file); }); @@ -326,7 +365,8 @@ export default function smartVillagesPlugin(config, baseUrl) { }, initialize(vcsApp) { app = vcsApp; - vcsApp.contextMenuManager.addEventHandler(async (event) => { + + vcsApp.contextMenuManager.addEventHandler(async (event) => { const actions = []; const pick = vcsApp.maps.activeMap.getScene().pick(event.windowPosition); if (pick !== undefined && pick.primitive !== undefined && pick.primitive.id !== undefined) { @@ -364,13 +404,31 @@ export default function smartVillagesPlugin(config, baseUrl) { }, }); + actions.push({ + id: 'scale', + name: 'Objekt skalieren', + callback() { + currentlyScaledModel = model; + vcsApp.windowManager.add( + { + id: scaleControlId, + component: scaleControl, + slot: WindowSlot.DYNAMIC_LEFT, + state: { + headerTitle: "Skalierung", + }, + }, + name, + ); + } + }); + actions.push({ id: 'delete', name: 'Objekt entfernen', callback() { vcsApp.maps.activeMap.getEntities().remove(model); removePlacedModel(model); - console.log(placedModels); }, }); @@ -435,7 +493,7 @@ export default function smartVillagesPlugin(config, baseUrl) { callback() { vcsApp.windowManager.add( { - id: windowId, + id: bimOptionsId, component: BIMOptions, slot: WindowSlot.DETACHED, position: { @@ -460,7 +518,7 @@ export default function smartVillagesPlugin(config, baseUrl) { callback() { vcsApp.windowManager.add( { - id: windowId, + id: objectListId, component: objectList, slot: WindowSlot.DYNAMIC_LEFT, state: { diff --git a/src/objectList.vue b/src/objectList.vue index c94e7b450aa8ce969c440d3418375dd6387e2a79..d82cbb3bc567043efa9b1811519ccf2a7d47b43c 100644 --- a/src/objectList.vue +++ b/src/objectList.vue @@ -133,6 +133,7 @@ function uploadModel() { const exporter = new GLTFExporter(); const options = { binary: true, + animations: gltf.animations, }; exporter.parse(gltf.scene, // called when the gltf has been generated @@ -189,6 +190,8 @@ function uploadModel() { return `$${keys[index]}`; } + export const objectListId = "object_list_id"; + export default { name: 'objectList', components: { diff --git a/src/scaleControl.vue b/src/scaleControl.vue new file mode 100644 index 0000000000000000000000000000000000000000..6a62819b52aa21ed0ddc6b0b3981ca69280fa116 --- /dev/null +++ b/src/scaleControl.vue @@ -0,0 +1,94 @@ +<template> + <v-sheet> + <VcsFormSection heading="Skalierung"> + <template #default> + <v-container class="py-0 px-1"> + <v-row no-gutters> + <v-col> + <VcsLabel html-for="numberInput" :dense="dense"> + Skalierungsfaktor: + </VcsLabel> + </v-col> + <v-col> + <VcsTextField id="numberInput" :dense="dense" type="number" step="0.1" unit="" v-model.number="scale" + show-spin-buttons /> + </v-col> + </v-row> + <v-row no-gutters justify="center"> + <v-col> + <VcsFormButton id="loadBtn" @click="scaleModel()"> Skalieren </VcsFormButton> + </v-col> + </v-row> + </v-container> + </template> + </VcsFormSection> + </v-sheet> +</template> + +<script setup> +import { inject, ref, watch } from 'vue'; + +let app = undefined; +const scale = ref(1.0); +app = inject('vcsApp'); +const { setScale } = app.plugins.getByKey(name); + +function scaleModel() { + setScale(scale.value); +} + +</script> + +<script> +import { + VcsList, + VcsFormButton, + VcsTextField, + Icons, + VcsFormSection, + createListItemRenameAction, + NotificationType, +} from '@vcmap/ui'; +import { + VSwitch, + VSheet, + VDialog, + VCard, + VForm, + VContainer, + VRow, + VCol, +} from 'vuetify/lib'; +import { inject, watch } from 'vue'; +import { name } from '../package.json'; + + +export const scaleControlId = "scale_control_id"; + +export default { + name: 'scaleControl', + components: { + VcsFormButton, + VcsTextField, + VcsFormSection, + VSwitch, + VSheet, + VDialog, + VCard, + VForm, + VContainer, + VRow, + VCol, + }, + setup() { + + }, +}; +</script> + +<style lang="scss" scoped> +.d-grid { + display: grid; + grid-template-columns: 1fr 1fr; +} +</style> diff --git a/src/upload.vue b/src/upload.vue index 3601cfd63f7d55f9023ce20b2cb409cbdc10671b..991037f8f3487d466428d778a50e9ac6e4eef5ba 100644 --- a/src/upload.vue +++ b/src/upload.vue @@ -40,7 +40,7 @@ import { import { VContainer, VRow, VForm, VCol } from 'vuetify/lib'; import { name } from '../package.json'; -export const windowId = 'upload_ifc_id'; +export const bimOptionsId = 'upload_ifc_id'; export default { name: 'IFC Konvertierung',