This commit is contained in:
2026-03-25 16:34:38 +02:00
parent 008cc428d4
commit 6d05be2fec
5 changed files with 77 additions and 23 deletions
+65 -18
View File
@@ -16,19 +16,29 @@
</v-btn-toggle>
<div v-if="currentObject" :version="version">
<v-card subtitle="Position" class="ma-1" color="light-blue-darken-4">
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="x" v-model="currentObject.position.x"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="y" v-model="currentObject.position.y"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="z" v-model="currentObject.position.z"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="x" v-model="currentObject.position.x" :step="0.1"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="y" v-model="currentObject.position.y" :step="0.1"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="z" v-model="currentObject.position.z" :step="0.1"></v-number-input>
</v-card>
<v-card subtitle="Rotation" class="ma-1" color="green-darken-4">
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="x" v-model="currentObject.rotation.x"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="y" v-model="currentObject.rotation.y"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="z" v-model="currentObject.rotation.z"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="x" v-model="currentObject.rotation.x" :step="0.1"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="y" v-model="currentObject.rotation.y" :step="0.1"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="z" v-model="currentObject.rotation.z" :step="0.1"></v-number-input>
</v-card>
<v-card subtitle="Scale" class="ma-1" color="pink-darken-4">
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="x" v-model="currentObject.scale.x"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="y" v-model="currentObject.scale.y"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="z" v-model="currentObject.scale.z"></v-number-input>
<template v-slot:append>
<v-btn :icon="uniformScale ? 'mdi-lock-outline' : 'mdi-lock-open-variant-outline'" size="x-small" variant="text" density="compact" @click="uniformScale = !uniformScale"></v-btn>
</template>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="x" v-model="currentObject.scale.x" :step="0.01"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="y" v-model="currentObject.scale.y" :step="0.01"></v-number-input>
<v-number-input :precision="null" controlVariant="stacked" hide-details density="compact" label="z" v-model="currentObject.scale.z" :step="0.01"></v-number-input>
</v-card>
<v-card subtitle="Info" v-if="objectInfo" class="ma-1" color="purple-darken-4">
<div class="d-flex flex-column text-caption px-3">
<div>Width: {{ (currentObject.scale.x * objectInfo.width).toFixed(2) }}</div>
<div>Height: {{ (currentObject.scale.y * objectInfo.height).toFixed(2) }}</div>
<div>Depth: {{ (currentObject.scale.z * objectInfo.depth).toFixed(2) }}</div>
</div>
</v-card>
</div>
</v-navigation-drawer>
@@ -84,6 +94,7 @@ export default {
pointerDownTime: 0,
renderType: 'ST',
cameraType: 'perspective',
uniformScale: true,
version: 0
}
},
@@ -98,8 +109,8 @@ export default {
});
manager = await new GameManager(engine, this.modelValue, null, {
onObjectLoad:(sceneObjects, data, object3d, source)=>{
['position', 'scale', 'rotation', 'visible'].forEach(p=>{
sceneObjects[data.id][p] = object3d[p];
['position', 'scale', 'rotation'].forEach(p=>{
sceneObjects[data.id][p] = object3d[p].clone();
})
sceneObjects[data.id].__o = markRaw(object3d);
sceneObjects[data.id].__animations = markRaw(source.animations || []);
@@ -124,6 +135,19 @@ export default {
manager = null;
},
computed:{
objectInfo(){
if (this.currentObject.__o.userData?.bbox){
let b = this.currentObject.__o.userData.bbox;
return {
width: b.max.x - b.min.x,
height: b.max.y - b.min.y,
depth: b.max.z - b.min.z
}
}
}
},
watch:{
mode(n){
engine.transformControls.setMode(n)
@@ -137,22 +161,49 @@ export default {
}else{
engine.setCameraOrthographic();
}
},
'currentObject':{
deep: true,
handler(v){
this.handleScale(this.currentObject, this.currentObject.__o)
}
}
},
methods:{
async loadScene(sceneId){
engine.transformControls.removeEventListener('change', this.update)
await manager.loadScene(sceneId)
this.currentScene = manager.scenarioData.scenes.find(sc=>sc.data.id == sceneId);
this.sceneObjects = this.modelValue.scenes?.[sceneId]?.objects
engine.transformControls.addEventListener('change', this.update)
engine.transformControls.addEventListener('objectChange', this.handleTransformControlsChange)
},
handleScale(src, dst){
if (this.uniformScale){
for (let p of ['x', 'y', 'z']){
if (src.scale[p] != dst.scale[p]) {
let k = src.scale[p]/dst.scale[p];
['x', 'y', 'z'].filter(c=>src.scale[c] == dst.scale[c]).forEach(c=>{
src.scale[c] = dst.scale[c] * k;
engine.transformControls._scaleStart[c] = src.scale[c];
})
break;
}
}
}
['position', 'scale', 'rotation'].forEach(p=>{
dst[p].copy(src[p]);
})
},
handleTransformControlsChange(){
this.handleScale(this.currentObject.__o, this.currentObject);
},
selectObject(oid){
this.currentObject = this.sceneObjects[oid];
engine.transformControls.attach(this.currentObject.__o);
engine.gizmo.target = this.currentObject.__o.position;
engine.gizmo.target = this.currentObject.position;
engine.camera.updateProjectionMatrix();
this.objectAnimations = this.currentObject?.__animations?.map(a => ({
name: a.name, id: a.uuid, a
@@ -189,10 +240,6 @@ export default {
engine.resize(r.clientWidth, r.clientHeight);
//this.zoom = Math.min(r.clientWidth / this.viewBox.w, r.clientHeight / this.viewBox.h);
},
update(){
this.version ++;
}
}
}
</script>
+1 -1
View File
@@ -26,7 +26,7 @@ THREE.Cache.enabled = true
const assetPath = '/asset/default/';
const defaultLightIntensity = 11;
const sceneScale = 1//.33;
const sceneScale = 1.33;
class GameEngine extends EventManager{
+4 -1
View File
@@ -19,7 +19,10 @@ class GameManager{
this.loadScene = async function(sceneId){
let scene = scenarioData.scenes.find(sc=>sc.data.id == sceneId);
let sceneObjects = gameData.scenes?.[sceneId]?.objects || {};
gameData.scenes = gameData.scenes || {};
gameData.scenes[sceneId] = gameData.scenes[sceneId] || {};
gameData.scenes[sceneId].objects = gameData.scenes[sceneId].objects || {};
let sceneObjects = gameData.scenes[sceneId].objects;
engine.tm?.setGame(gameData.id);
let intro;
await engine.resetScene();
+6 -2
View File
@@ -38,8 +38,12 @@ class MeshUtils {
getBoundingBox(object){
let bb = new Box3().setFromObject(object);
bb.min.multiplyScalar(1 / this.engine.scale);
bb.max.multiplyScalar(1 / this.engine.scale);
let scale = new Vector3(1,1,1);
object.traverseAncestors(o=>{
scale.multiply(o.scale);
});
bb.min.divide(scale);
bb.max.divide(scale);
return bb;
}
+1 -1
View File
@@ -62,7 +62,7 @@ export default {
async save(params) {
this.loading = true;
try {
this.debug('saving', this.object)
//this.debug('saving', this.object)
let result = await this.$api.game.save(this.object);
this.object.id = result.data.object.id;
if (this.id == 'add') {