This commit is contained in:
syuilo
2026-02-15 19:42:31 +09:00
parent 0996c2d9b2
commit d8d4b230b0
6 changed files with 47 additions and 23 deletions

View File

@@ -18,22 +18,32 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton v-if="engine.enableGridSnapping.value" :primary="engine.gridSnappingScale.value === 8" @click="engine.gridSnappingScale.value = 8">Snap: 8cm</MkButton>
</template>
<MkButton v-if="engine.isSitting.value" @click="engine.standUp()">降りる (Q)</MkButton>
<template v-for="interaction in interacions" :key="interaction.id">
<MkButton @click="interaction.fn()">{{ interaction.label }}</MkButton>
</template>
</div>
</div>
</template>
<script lang="ts" setup>
import { defineAsyncComponent, onMounted, onUnmounted, ref, shallowRef, useTemplateRef } from 'vue';
import { defineAsyncComponent, onMounted, onUnmounted, ref, shallowRef, useTemplateRef, watch } from 'vue';
import { definePage } from '@/page.js';
import { i18n } from '@/i18n.js';
import { ensureSignin } from '@/i';
import MkButton from '@/components/MkButton.vue';
import { RoomEngine } from '@/utility/room/engine.js';
import { getObjectDef } from '@/utility/room/object-defs.js';
const canvas = useTemplateRef('canvas');
const engine = shallowRef<RoomEngine | null>(null);
const interacions = shallowRef<{
id: string;
label: string;
fn: () => void;
}[]>([]);
function resize() {
if (engine.value != null) engine.value.resize();
}
@@ -276,6 +286,20 @@ onMounted(() => {
canvas.value!.focus();
window.addEventListener('resize', resize);
watch(engine.value.selectedObjectId, (v) => {
if (v == null) {
interacions.value = [];
} else {
const o = engine.value.def.objects.find(o => o.id === v)!;
const obji = engine.value.objectInstances.get(o.id)!;
interacions.value = Object.entries(obji.interactions).map(([interactionId, interactionInfo]) => ({
id: interactionId,
label: interactionInfo.label,
fn: interactionInfo.fn,
}));
}
});
});
onUnmounted(() => {

View File

@@ -22,7 +22,7 @@ import { BoundingBoxRenderer } from '@babylonjs/core/Rendering/boundingBoxRender
import { GridMaterial } from '@babylonjs/materials';
import { ShowInspector } from '@babylonjs/inspector';
import { ref, watch } from 'vue';
import { OBJECT_DEFS } from './object-defs.js';
import { getObjectDef, OBJECT_DEFS } from './object-defs.js';
import * as sound from '@/utility/sound.js';
type RoomSettingObject<Options = any> = {
@@ -339,14 +339,6 @@ const OBJECTS = {
},
};
function getObjectDef(type: string): typeof OBJECT_DEFS[number] {
const def = OBJECT_DEFS.find(x => x.id === type);
if (def == null) {
throw new Error(`Unrecognized object type: ${type}`);
}
return def;
}
const _assumedFramesPerSecond = 60;
class HorizontalCameraKeyboardMoveInput extends BABYLON.BaseCameraPointersInput {
@@ -476,7 +468,7 @@ export class RoomEngine {
private intervalIds: number[] = [];
private timeoutIds: number[] = [];
private objectMeshs: Map<string, BABYLON.Mesh> = new Map();
private objectInstances: Map<string, RoomObjectInstance<any>> = new Map();
public objectInstances: Map<string, RoomObjectInstance<any>> = new Map();
private grabbing: {
objectId: string;
mesh: BABYLON.Mesh;
@@ -488,10 +480,10 @@ export class RoomEngine {
descendantStickyObjectIds: string[];
isMainLight: boolean;
} | null = null;
private selectedObjectId: string | null = null;
public selectedObjectId = ref<string | null>(null);
private time: 0 | 1 | 2 = 2; // 0: 昼, 1: 夕, 2: 夜
private roomCollisionMeshes: BABYLON.AbstractMesh[] = [];
private def: RoomSetting;
public def: RoomSetting;
public enableGridSnapping = ref(true);
public gridSnappingScale = ref(8/*cm*/);
private putParticleSystem: BABYLON.ParticleSystem;
@@ -755,8 +747,8 @@ export class RoomEngine {
ev.stopPropagation();
if (this.isEditMode.value) {
this.toggleGrab();
} else if (this.selectedObjectId != null) {
this.interact(this.selectedObjectId);
} else if (this.selectedObjectId.value != null) {
this.interact(this.selectedObjectId.value);
}
} else if (ev.code === 'KeyR') {
ev.preventDefault();
@@ -869,14 +861,14 @@ export class RoomEngine {
}
public selectObject(objectId: string | null) {
if (this.selectedObjectId != null) {
const prevMesh = this.objectMeshs.get(this.selectedObjectId);
if (this.selectedObjectId.value != null) {
const prevMesh = this.objectMeshs.get(this.selectedObjectId.value);
if (prevMesh != null) {
for (const om of prevMesh.getChildMeshes()) {
om.renderOutline = false;
}
}
this.selectedObjectId = null;
this.selectedObjectId.value = null;
}
if (objectId != null) {
@@ -885,7 +877,7 @@ export class RoomEngine {
for (const om of mesh.getChildMeshes()) {
om.renderOutline = true;
}
this.selectedObjectId = objectId;
this.selectedObjectId.value = objectId;
}
}
}
@@ -1250,9 +1242,9 @@ export class RoomEngine {
return;
}
if (this.selectedObjectId == null) return;
if (this.selectedObjectId.value == null) return;
const selectedObject = this.objectMeshs.get(this.selectedObjectId)!;
const selectedObject = this.objectMeshs.get(this.selectedObjectId.value)!;
for (const om of selectedObject.getChildMeshes()) {
om.renderOutline = false;
}

View File

@@ -8,3 +8,11 @@ import { blind } from './objects/blind.js';
export const OBJECT_DEFS = [
blind,
];
export function getObjectDef(type: string): typeof OBJECT_DEFS[number] {
const def = OBJECT_DEFS.find(x => x.id === type);
if (def == null) {
throw new Error(`Unrecognized object type: ${type}`);
}
return def;
}

View File

@@ -54,8 +54,8 @@ export const blind = defineObject({
adjustBladeRotation: {
label: 'Adjust blade rotation',
fn: () => {
o.options.angle += Math.PI / 24;
if (o.options.angle > Math.PI / 2) o.options.angle = 0;
o.options.angle += Math.PI / 8;
if (o.options.angle >= Math.PI / 2) o.options.angle = -Math.PI / 2;
applyAngle();
},
},