diff --git a/packages/frontend/assets/room/objects/wall-shelf/textures/wood.png b/packages/frontend/assets/room/objects/wall-shelf/textures/wood.png new file mode 100644 index 0000000000..3d0c47a25a Binary files /dev/null and b/packages/frontend/assets/room/objects/wall-shelf/textures/wood.png differ diff --git a/packages/frontend/assets/room/objects/wall-shelf/wall-shelf.blend b/packages/frontend/assets/room/objects/wall-shelf/wall-shelf.blend new file mode 100644 index 0000000000..42392dbdc0 Binary files /dev/null and b/packages/frontend/assets/room/objects/wall-shelf/wall-shelf.blend differ diff --git a/packages/frontend/assets/room/objects/wall-shelf/wall-shelf.glb b/packages/frontend/assets/room/objects/wall-shelf/wall-shelf.glb new file mode 100644 index 0000000000..04228ca431 Binary files /dev/null and b/packages/frontend/assets/room/objects/wall-shelf/wall-shelf.glb differ diff --git a/packages/frontend/src/pages/room.vue b/packages/frontend/src/pages/room.vue index f679fbef08..33a0ba5851 100644 --- a/packages/frontend/src/pages/room.vue +++ b/packages/frontend/src/pages/room.vue @@ -33,6 +33,9 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+ +
@@ -602,5 +605,7 @@ definePage(() => ({ right: 16px; z-index: 1; padding: 16px; + box-sizing: border-box; + width: 300px; } diff --git a/packages/frontend/src/utility/room/engine.ts b/packages/frontend/src/utility/room/engine.ts index b4b0ba07fc..2272a60bd5 100644 --- a/packages/frontend/src/utility/room/engine.ts +++ b/packages/frontend/src/utility/room/engine.ts @@ -25,7 +25,7 @@ import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic'; import { BoundingBoxRenderer } from '@babylonjs/core/Rendering/boundingBoxRenderer'; import { GridMaterial } from '@babylonjs/materials'; import { ShowInspector } from '@babylonjs/inspector'; -import { reactive, ref, shallowRef, watch } from 'vue'; +import { reactive, ref, shallowRef, triggerRef, watch } from 'vue'; import { genId } from '../id.js'; import { getObjectDef } from './object-defs.js'; import { HorizontalCameraKeyboardMoveInput } from './utility.js'; @@ -78,16 +78,16 @@ type ColorOptionSchema = { label: string; }; -type SelectOptionSchema = { - type: 'select'; +type EnumOptionSchema = { + type: 'enum'; label: string; enum: string[]; }; -type OptionsSchema = Record; +type OptionsSchema = Record; type GetOptionsSchemaValues = { - [K in keyof T]: T[K] extends NumberOptionSchema ? number : T[K] extends ColorOptionSchema ? [number, number, number] : T[K] extends SelectOptionSchema ? T[K]['enum'][number] : never; + [K in keyof T]: T[K] extends NumberOptionSchema ? number : T[K] extends ColorOptionSchema ? [number, number, number] : T[K] extends EnumOptionSchema ? T[K]['enum'][number] : never; }; type ObjectDef = { @@ -1213,6 +1213,10 @@ export class RoomEngine { const obji = this.objectInstances.get(objectId); if (obji == null) return; obji.onOptionsUpdated?.([key, value]); + + if (this.selected.value?.objectId === objectId) { + triggerRef(this.selected); + } } public resize() { diff --git a/packages/frontend/src/utility/room/object-defs.ts b/packages/frontend/src/utility/room/object-defs.ts index 01693026a8..1c50f321a6 100644 --- a/packages/frontend/src/utility/room/object-defs.ts +++ b/packages/frontend/src/utility/room/object-defs.ts @@ -39,6 +39,7 @@ import { tabletopCalendar } from './objects/tabletopCalendar.js'; import { tabletopDigitalClock } from './objects/tabletopDigitalClock.js'; import { tv } from './objects/tv.js'; import { wallClock } from './objects/wallClock.js'; +import { wallShelf } from './objects/wallShelf.js'; import { woodSoundAbsorbingPanel } from './objects/woodSoundAbsorbingPanel.js'; export const OBJECT_DEFS = [ @@ -78,6 +79,7 @@ export const OBJECT_DEFS = [ tabletopDigitalClock, tv, wallClock, + wallShelf, woodSoundAbsorbingPanel, ]; diff --git a/packages/frontend/src/utility/room/objects/tabletopDigitalClock.ts b/packages/frontend/src/utility/room/objects/tabletopDigitalClock.ts index 74ec2f9772..d75a920393 100644 --- a/packages/frontend/src/utility/room/objects/tabletopDigitalClock.ts +++ b/packages/frontend/src/utility/room/objects/tabletopDigitalClock.ts @@ -13,7 +13,7 @@ export const tabletopDigitalClock = defineObject({ options: { schema: { bodyStyle: { - type: 'select', + type: 'enum', label: 'Body Style', enum: ['color', 'wood'], }, @@ -37,7 +37,7 @@ export const tabletopDigitalClock = defineObject({ const [r, g, b] = options.bodyColor; bodyMaterial.albedoColor = new BABYLON.Color3(r, g, b); } else { - bodyMaterial.albedoTexture = room.scene.getTextureByName('tabletop_digital_clock_wood'); + } }; diff --git a/packages/frontend/src/utility/room/objects/wallShelf.ts b/packages/frontend/src/utility/room/objects/wallShelf.ts new file mode 100644 index 0000000000..d72914708f --- /dev/null +++ b/packages/frontend/src/utility/room/objects/wallShelf.ts @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as BABYLON from '@babylonjs/core'; +import { defineObject } from '../engine.js'; + +export const wallShelf = defineObject({ + id: 'wallShelf', + name: 'Wall Shelf', + options: { + schema: { + style: { + type: 'enum', + label: 'Style', + enum: ['A', 'B'], + }, + boardStyle: { + type: 'enum', + label: 'Board style', + enum: ['color', 'wood'], + }, + boardColor: { + type: 'color', + label: 'Board color', + }, + }, + default: { + style: 'A', + boardStyle: 'wood', + boardColor: [1, 1, 1], + }, + }, + placement: 'side', + createInstance: ({ room, options, root }) => { + const applyStyle = () => { + const aMeshes = root.getChildMeshes().filter(m => m.name.includes('__X_VARIATION_A__')); + const bMeshes = root.getChildMeshes().filter(m => m.name.includes('__X_VARIATION_B__')); + + for (const m of aMeshes) { + (m as BABYLON.Mesh).setEnabled(options.style === 'A'); + } + for (const m of bMeshes) { + (m as BABYLON.Mesh).setEnabled(options.style === 'B'); + } + }; + + applyStyle(); + + const bodyMesh = root.getChildMeshes().find(m => m.name.includes('__X_BOARD__')) as BABYLON.Mesh; + const bodyMaterial = bodyMesh.material as BABYLON.PBRMaterial; + const bodyTexture = bodyMaterial.albedoTexture as BABYLON.Texture; + + const applyBoardColor = () => { + const [r, g, b] = options.boardColor; + bodyMaterial.albedoColor = new BABYLON.Color3(r, g, b); + + if (options.boardStyle === 'color') { + bodyMaterial.albedoTexture = null; + } else { + bodyMaterial.albedoTexture = bodyTexture; + } + }; + + applyBoardColor(); + + return { + onOptionsUpdated: ([k, v]) => { + applyStyle(); + applyBoardColor(); + }, + interactions: {}, + }; + }, +});