1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-14 06:25:52 +02:00
This commit is contained in:
syuilo
2026-04-30 18:06:50 +09:00
parent b34e957c25
commit ce2e74f3ca
4 changed files with 71 additions and 61 deletions

View File

@@ -65,10 +65,10 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
<div v-if="controller.isReady.value && controller.isEditMode.value && controller.selected.value != null && !controller.grabbing.value" :key="controller.selected.value.objectId" class="_panel" :class="$style.overlayObjectInfoPanel">
{{ controller.selected.value.objectDef.name }}
<div v-if="controller.isReady.value && controller.isEditMode.value && controller.selected.value != null && selectedObjectDef != null && !controller.grabbing.value" :key="controller.selected.value.objectId" class="_panel" :class="$style.overlayObjectInfoPanel">
{{ selectedObjectDef.name }}
<XObjectCustomizeForm :schema="controller.selected.value.objectDef.options.schema" :options="controller.selected.value.objectState.options" @update="(k, v) => controller.updateObjectOption(controller.selected.value.objectId, k, v)"></XObjectCustomizeForm>
<XObjectCustomizeForm :schema="selectedObjectDef.options.schema" :options="controller.selected.value.objectState.options" @update="(k, v) => controller.updateObjectOption(controller.selected.value.objectId, k, v)"></XObjectCustomizeForm>
</div>
<div v-if="isRoomSettingsOpen && controller.isEditMode.value" class="_panel" :class="$style.overlayObjectInfoPanel">
@@ -120,6 +120,7 @@ import MkProgressBar from '@/components/MkProgressBar.vue';
import { Joystick } from '@/world/joystick.js';
import { isTouchUsing } from '@/utility/touch.js';
import { prefer } from '@/preferences.js';
import { getObjectDef } from '@/world/room/object-defs.js';
const canvas = useTemplateRef('canvas');
@@ -304,6 +305,8 @@ if (data.heya.options.pillars == null) {
};
}
console.log('installedObjects:', data.installedObjects.length);
let latestData = deepClone(data);
const roomControllerOptions = computed<RoomControllerOptions>(() => ({
@@ -317,6 +320,8 @@ const roomControllerOptions = computed<RoomControllerOptions>(() => ({
const controller = new RoomController(data, roomControllerOptions.value);
const selectedObjectDef = computed(() => controller.selected.value == null ? null : getObjectDef(controller.selected.value.objectState.type));
onMounted(async () => {
if (!await BABYLON.WebGPUEngine.IsSupportedAsync) {
os.alert({

View File

@@ -5,11 +5,12 @@
import { reactive, ref, shallowRef, triggerRef, watch } from 'vue';
import * as BABYLON from '@babylonjs/core';
import { EventEmitter } from 'eventemitter3';
import { cm } from '../utility.js';
import RoomWorker from './worker?worker';
import { GRAPHICS_QUALITY_MEDIUM, RoomEngine } from './engine.js';
import type { ShallowRef } from 'vue';
import type { RoomState } from './engine.js';
import type { RoomEngineEvents, RoomState } from './engine.js';
import type { ObjectDef, RoomStateObject } from './object.js';
import * as sound from '@/utility/sound.js';
import * as os from '@/os.js';
@@ -38,7 +39,6 @@ export class RoomController {
public selected = ref<{
objectId: string;
objectState: RoomStateObject;
objectDef: ObjectDef;
} | null>(null);
public roomState: ShallowRef<RoomState>;
public initializeProgress = ref(0);
@@ -60,23 +60,22 @@ export class RoomController {
this.canvas.width = canvas.clientWidth;
this.canvas.height = canvas.clientHeight;
const engineEvents = new EventEmitter<RoomEngineEvents>();
if (this.options.workerMode) {
const offscreen = canvas.transferControlToOffscreen();
this.worker = new RoomWorker();
this.worker.postMessage({ type: 'init', canvas: offscreen, roomState: this.roomState.value, options: this.options }, [offscreen]);
this.worker.onmessage = (event) => {
switch (event.data?.type) {
case 'progress': {
this.initializeProgress.value = event.data.progress;
break;
}
case 'inited': {
this.initializeProgress.value = 1;
this.isReady.value = true;
break;
}
case 'changeEditMode': {
this.isEditMode.value = event.data.isEditMode;
case 'ev': {
const { type, ctx } = event.data.ev;
engineEvents.emit(type, ctx);
break;
}
default: {
@@ -104,8 +103,8 @@ export class RoomController {
...this.options,
});
this.engine.on('loadingProgress', ({ progress }) => {
this.initializeProgress.value = progress;
this.engine.on('ev', ({ type, ctx }) => {
engineEvents.emit(type, ctx);
});
await this.engine.init();
@@ -113,31 +112,6 @@ export class RoomController {
this.initializeProgress.value = 1;
this.isReady.value = true;
this.engine.on('changeGrabbingState', ({ grabbing }) => {
this.grabbing.value = grabbing;
});
this.engine.on('changeEditMode', ({ isEditMode }) => {
this.isEditMode.value = isEditMode;
});
this.engine.on('changeGridSnapping', ({ gridSnapping }) => {
this.gridSnapping.value = gridSnapping;
});
this.engine.on('changeSelectedState', ({ selected }) => {
this.selected.value = selected;
});
this.engine.on('changeRoomState', ({ roomState }) => {
this.roomState.value = roomState;
triggerRef(this.selected);
});
this.engine.on('playSfxUrl', ({ url, options }) => {
sound.playUrl(url, options);
});
if (_DEV_) {
(window as any).showBabylonInspector = () => {
import('@babylonjs/inspector').then(({ ShowInspector }) => {
@@ -147,6 +121,35 @@ export class RoomController {
}
}
engineEvents.on('loadingProgress', ({ progress }) => {
this.initializeProgress.value = progress;
});
engineEvents.on('changeGrabbingState', ({ grabbing }) => {
this.grabbing.value = grabbing;
});
engineEvents.on('changeEditMode', ({ isEditMode }) => {
this.isEditMode.value = isEditMode;
});
engineEvents.on('changeGridSnapping', ({ gridSnapping }) => {
this.gridSnapping.value = gridSnapping;
});
engineEvents.on('changeSelectedState', ({ selected }) => {
this.selected.value = selected;
});
engineEvents.on('changeRoomState', ({ roomState }) => {
this.roomState.value = roomState;
triggerRef(this.selected);
});
engineEvents.on('playSfxUrl', ({ url, options }) => {
sound.playUrl(url, options);
});
this.canvas.addEventListener('keydown', this.onCanvasKeydown);
this.canvas.addEventListener('keyup', this.onCanvasKeyup);
this.canvas.addEventListener('wheel', this.onCanvasWheel);

View File

@@ -104,7 +104,6 @@ export type RoomEngineEvents = {
selected: {
objectId: string;
objectState: RoomStateObject<any>;
objectDef: ObjectDef<any>;
} | null;
}) => void;
'changeGrabbingState': (ctx: { grabbing: { forInstall: boolean } | null }) => void;
@@ -121,7 +120,7 @@ export type RoomEngineEvents = {
'loadingProgress': (ctx: { progress: number }) => void;
};
export class RoomEngine extends EventEmitter<RoomEngineEvents> {
export class RoomEngine extends EventEmitter {
private useGlow: boolean;
private engine: BABYLON.WebGPUEngine;
public scene: BABYLON.Scene;
@@ -156,7 +155,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
}
set grabbingCtx(v) {
this._grabbingCtx = v;
this.emit('changeGrabbingState', { grabbing: v == null ? null : { forInstall: v.forInstall } });
this.ev('changeGrabbingState', { grabbing: v == null ? null : { forInstall: v.forInstall } });
}
// TODO: たぶんオブジェクト内の値のmutateはsetで検知できないので、そのような操作を実際に行うようになった & それを検知する必要性が出てきたら専用の設定関数などを新設してそれを使わせる
@@ -171,7 +170,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
}
set selected(v) {
this._selected = v;
this.emit('changeSelectedState', { selected: v == null ? null : { objectId: v.objectId, objectState: v.objectState, objectDef: v.objectDef } });
this.ev('changeSelectedState', { selected: v == null ? null : { objectId: v.objectId, objectState: v.objectState } });
}
private time: 0 | 1 | 2 = 0; // 0: 昼, 1: 夕, 2: 夜
@@ -184,7 +183,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
set gridSnapping(v) {
this._gridSnapping = v;
if (this.gridMaterial != null) this.gridMaterial.gridRatio = v.scale; // setter内でconstructor内設定の値に依存するのはタイミングによってはundefinedになりそうなので、実際に当該マテリアルを表示する必要が生じる直前に利用側で設定させた方がいいかもしれない
this.emit('changeGridSnapping', { gridSnapping: v });
this.ev('changeGridSnapping', { gridSnapping: v });
}
private putParticleSystem: BABYLON.ParticleSystem;
@@ -206,7 +205,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
}
set isEditMode(v) {
this._isEditMode = v;
this.emit('changeEditMode', { isEditMode: v });
this.ev('changeEditMode', { isEditMode: v });
}
public isSitting = false;
@@ -440,6 +439,11 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
}
}
private ev<K extends keyof RoomEngineEvents>(type: K, ctx: Parameters<RoomEngineEvents[K]>[0]) {
console.log(type, ctx);
this.emit('ev', { type, ctx });
}
public async init() {
await this.loadHeya();
if (RENDER_OUTDOOR_ENV) await this.loadEnvModel();
@@ -455,7 +459,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
options: o.options,
}).then(() => {
loadedCount++;
this.emit('loadingProgress', { progress: loadedCount / objects.length });
this.ev('loadingProgress', { progress: loadedCount / objects.length });
})));
// 不具合のもと
@@ -829,7 +833,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
}
}
public async changeHeyaType(type: RoomState['heya']['type']) {
public async changeHeyaType(type: RoomState['heya']['type'], forInit = false) {
this.roomState.heya.type = type;
if (this.heyaManager != null) {
@@ -867,11 +871,13 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
// TODO
}
this.emit('changeRoomState', { roomState: this.roomState });
if (!forInit) {
this.ev('changeRoomState', { roomState: this.roomState });
}
}
private async loadHeya() {
await this.changeHeyaType(this.roomState.heya.type);
await this.changeHeyaType(this.roomState.heya.type, true);
}
private async loadObject(args: {
@@ -1343,7 +1349,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
this.roomState.installedObjects.find(o => o.id === selectedObject.metadata.objectId)!.position = [pos.x, pos.y, pos.z];
this.roomState.installedObjects.find(o => o.id === selectedObject.metadata.objectId)!.rotation = [rotation.x, rotation.y, rotation.z];
this.emit('changeRoomState', { roomState: this.roomState });
this.ev('changeRoomState', { roomState: this.roomState });
});
},
};
@@ -1410,7 +1416,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
public updateRoomLightColor(color: [number, number, number]) {
this.roomLight.diffuse = new BABYLON.Color3(...color);
this.roomState.roomLightColor = color;
this.emit('changeRoomState', { roomState: this.roomState });
this.ev('changeRoomState', { roomState: this.roomState });
}
private turnOnRoomLight(forInit = false) {
@@ -1590,7 +1596,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
options,
});
this.emit('changeRoomState', { roomState: this.roomState });
this.ev('changeRoomState', { roomState: this.roomState });
},
};
@@ -1700,7 +1706,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
for (const o of this.roomState.installedObjects.filter(o => o.sticky === objectId)) {
o.sticky = null;
}
this.emit('changeRoomState', { roomState: this.roomState });
this.ev('changeRoomState', { roomState: this.roomState });
this.selected = null;
this.playSfxUrl('/client-assets/room/sfx/remove.mp3', {
@@ -1725,7 +1731,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
if (options == null) return;
options[key] = value;
this.emit('changeRoomState', { roomState: this.roomState });
this.ev('changeRoomState', { roomState: this.roomState });
const entity = this.objectEntities.get(objectId);
if (entity == null) return;
@@ -1735,11 +1741,11 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
public updateHeyaOptions(options: RoomState['heya']['options']) {
this.roomState.heya.options = options;
this.heyaManager.applyOptions(options);
this.emit('changeRoomState', { roomState: this.roomState });
this.ev('changeRoomState', { roomState: this.roomState });
}
private playSfxUrl(url: string, options: { volume: number; playbackRate: number }) {
this.emit('playSfxUrl', { url, options });
this.ev('playSfxUrl', { url, options });
}
public resize() {

View File

@@ -29,12 +29,8 @@ onmessage = async (event) => {
...event.data.options,
});
engine.on('loadingProgress', ({ progress }) => {
self.postMessage({ type: 'progress', progress });
});
engine.on('changeEditMode', ({ isEditMode }) => {
self.postMessage({ type: 'changeEditMode', isEditMode });
engine.on('ev', ({ type, ctx }) => {
self.postMessage({ type: 'ev', ev: { type, ctx } });
});
await engine.init();