1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-22 16:24:17 +02:00
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> <MkButton v-if="engine.enableGridSnapping.value" :primary="engine.gridSnappingScale.value === 8" @click="engine.gridSnappingScale.value = 8">Snap: 8cm</MkButton>
</template> </template>
<MkButton v-if="engine.isSitting.value" @click="engine.standUp()">降りる (Q)</MkButton> <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>
</div> </div>
</template> </template>
<script lang="ts" setup> <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 { definePage } from '@/page.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { ensureSignin } from '@/i'; import { ensureSignin } from '@/i';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import { RoomEngine } from '@/utility/room/engine.js'; import { RoomEngine } from '@/utility/room/engine.js';
import { getObjectDef } from '@/utility/room/object-defs.js';
const canvas = useTemplateRef('canvas'); const canvas = useTemplateRef('canvas');
const engine = shallowRef<RoomEngine | null>(null); const engine = shallowRef<RoomEngine | null>(null);
const interacions = shallowRef<{
id: string;
label: string;
fn: () => void;
}[]>([]);
function resize() { function resize() {
if (engine.value != null) engine.value.resize(); if (engine.value != null) engine.value.resize();
} }
@@ -276,6 +286,20 @@ onMounted(() => {
canvas.value!.focus(); canvas.value!.focus();
window.addEventListener('resize', resize); 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(() => { onUnmounted(() => {

View File

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

View File

@@ -8,3 +8,11 @@ import { blind } from './objects/blind.js';
export const OBJECT_DEFS = [ export const OBJECT_DEFS = [
blind, 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: { adjustBladeRotation: {
label: 'Adjust blade rotation', label: 'Adjust blade rotation',
fn: () => { fn: () => {
o.options.angle += Math.PI / 24; o.options.angle += Math.PI / 8;
if (o.options.angle > Math.PI / 2) o.options.angle = 0; if (o.options.angle >= Math.PI / 2) o.options.angle = -Math.PI / 2;
applyAngle(); applyAngle();
}, },
}, },