preview interactiveobjects in scenario module

This commit is contained in:
2026-04-29 12:49:04 +03:00
parent 7c74038af4
commit 6e57276cad
5 changed files with 53 additions and 29 deletions
+6 -3
View File
@@ -126,11 +126,14 @@ const Utils = {
return string && string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string return string && string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}, },
toSafeJSON(data){ toSafeObject(data){
data = Utils.deepMerge({}, data, (k, v)=>{ return Utils.deepMerge({}, data, (k, v)=>{
return k.startsWith('__') ? undefined : v; return k.startsWith('__') ? undefined : v;
}) })
return JSON.stringify(data); },
toSafeJSON(data){
return JSON.stringify(Utils.toSafeObject(data));
} }
} }
@@ -24,12 +24,15 @@
<script> <script>
import { GameEngine } from '@/lib/GameEngine.js'; import { GameEngine } from '@/lib/GameEngine.js';
import { GameManager } from '@/lib/GameManager';
import Utils from '#/app/Utils';
import { InteractiveObject } from '../InteractiveObjects/InteractiveObject';
let engine = null; let engine = null;
export default{ export default{
props:{ props:{
object: Object, object: null,
objectId: Number,
autoplay: Boolean autoplay: Boolean
}, },
data(){ data(){
@@ -39,10 +42,20 @@ export default{
} }
}, },
async mounted(){ async mounted(){
if (this.object) { engine = new GameEngine();
this.obj = this.object; await engine.init(this.$refs.target, {
gizmo: true,
xr: true,
mode: 'ObjectPreview'
});
if (typeof this.object == 'number') {
this.obj = (await this.$api.gameObject.load(this.object)).data;
}else if (this.object?.io){
let ioData = Utils.toSafeObject(this.object?.io)
await GameManager.expandObjectData(ioData);
this.obj = ioData;
}else{ }else{
this.obj = (await this.$api.gameObject.load(this.objectId)).data; this.obj = this.object;
} }
}, },
beforeUnmount() { beforeUnmount() {
@@ -55,18 +68,12 @@ export default{
}, },
async obj(){ async obj(){
if (!this.obj) return; if (!this.obj) return;
engine = new GameEngine();
await engine.init(this.$refs.target, {
gizmo: true,
xr: true,
mode: 'ObjectPreview'
});
await this.loadAsset(); await this.loadAsset();
} }
}, },
computed:{ computed:{
forRendering() { forRendering() {
return this.$p.objectTypes.find(t=> t.value == this.obj?.type)?.render || this.obj?.asset?.name?.endsWith('ktx2') return this.object?.io || this.$p.objectTypes.find(t=> t.value == this.obj?.type)?.render || this.obj?.asset?.name?.endsWith('ktx2')
} }
}, },
methods:{ methods:{
@@ -74,7 +81,11 @@ export default{
if (this.forRendering) { if (this.forRendering) {
engine.resetScene(); engine.resetScene();
engine.ambientLight.intensity = 25; engine.ambientLight.intensity = 25;
if (this.obj.type == 'panorama2d') { if (this.object?.io){
let io = await new InteractiveObject(engine, this.obj);
this.placeCamera(io.object);
engine.activeObjects.add(io.object);
}else if (this.obj.type == 'panorama2d') {
await engine.loadPanorama(this.obj.asset.name); await engine.loadPanorama(this.obj.asset.name);
} else if(this.obj.asset.name.endsWith('ktx2')){ } else if(this.obj.asset.name.endsWith('ktx2')){
let tx = await engine.loadTexture(this.obj.asset.name); let tx = await engine.loadTexture(this.obj.asset.name);
@@ -87,18 +98,22 @@ export default{
this.animations = gltf.animations.map(a => ({ this.animations = gltf.animations.map(a => ({
name: a.name, id: a.uuid name: a.name, id: a.uuid
})); }));
engine.meshUtils.autoScale(gltf.scene); this.placeCamera(gltf.scene)
let bb = engine.meshUtils.getBoundingBox(gltf.scene);
let ln = engine.meshUtils.getBoundingBoxMaxLength(bb);
let cp = engine.meshUtils.getBoundingBoxCenterPoint(bb);
engine.camera.position.set(cp.x, cp.y*1.77, ln*1.5);
engine.orbitControls.target.set(cp.x,cp.y*1.77,cp.z)
engine.orbitControls.update();
engine.activeObjects.add(gltf.scene); engine.activeObjects.add(gltf.scene);
} }
} }
}, },
placeCamera(object){
engine.meshUtils.autoScale(object);
let bb = engine.meshUtils.getBoundingBox(object);
let ln = engine.meshUtils.getBoundingBoxMaxLength(bb);
let cp = engine.meshUtils.getBoundingBoxCenterPoint(bb);
engine.camera.position.set(cp.x, cp.y*1.77, ln*1.5);
engine.orbitControls.target.set(cp.x,cp.y*1.77,cp.z)
engine.orbitControls.update();
},
async toggleAnimation(animation){ async toggleAnimation(animation){
animation.playing = !animation.playing; animation.playing = !animation.playing;
engine.playAnimation( engine.playAnimation(
+2 -2
View File
@@ -14,8 +14,8 @@
<image v-if="modelValue.go" :href="`/asset/thumb/${modelValue.type}.webp`" width="25" class="cursor-pointer" <image v-if="modelValue.go" :href="`/asset/thumb/${modelValue.type}.webp`" width="25" class="cursor-pointer"
:x="vd.x1 + 37 - 10" :y="vd.y1 - 37 - 10"> :x="vd.x1 + 37 - 10" :y="vd.y1 - 37 - 10">
</image> </image>
<image v-if="modelValue.go" href="/static/svg/play-circle.svg" width="20" class="cursor-pointer" <image href="/static/svg/play-circle.svg" width="20" class="cursor-pointer"
:x="vd.x1 + 37 - 10" :y="vd.y1 + 37 - 10" @click="$emit('preview', modelValue.go)"> :x="vd.x1 + 37 - 10" :y="vd.y1 + 37 - 10" @click="$emit('preview', {io: modelValue})">
</image> </image>
</g> </g>
</teleport> </teleport>
@@ -73,7 +73,7 @@
</v-navigation-drawer> </v-navigation-drawer>
</div> </div>
<v-dialog v-model="previewDialog" width="auto" max-width="1200"> <v-dialog v-model="previewDialog" width="auto" max-width="1200">
<AssetPreview :objectId="previewObject" autoplay></AssetPreview> <AssetPreview :object="previewObject" autoplay></AssetPreview>
</v-dialog> </v-dialog>
</template> </template>
+9 -3
View File
@@ -169,14 +169,20 @@ class GameManager extends EventManager{
}) })
for (let i of scene.data.items || []) { for (let i of scene.data.items || []) {
Object.keys(i.data).filter(k=>k == 'go' || k.startsWith('go_')).forEach(k=>{ promises.push(GameManager.expandObjectData(i.data))
promises.push(api.gameObject.load(i.data[k]).then(r=>i.data['$'+k] = r.data));
})
} }
await Promise.all(promises); await Promise.all(promises);
scene.expanded = true; scene.expanded = true;
} }
static async expandObjectData(objectData){
const promises = [];
Object.keys(objectData).filter(k=>k == 'go' || k.startsWith('go_')).forEach(k=>{
promises.push(api.gameObject.load(objectData[k]).then(r=>objectData['$'+k] = r.data));
})
await Promise.all(promises);
}
setObjectAttributes(sceneObjects, data, object3d, source, autoScaleFactor = 1){ setObjectAttributes(sceneObjects, data, object3d, source, autoScaleFactor = 1){
if (sceneObjects[data.id]){ if (sceneObjects[data.id]){
['position', 'scale', 'rotation'].forEach(p=>{ ['position', 'scale', 'rotation'].forEach(p=>{