diff --git a/packages/frontend/assets/room/objects/tabletop-iron-frame-stand/tabletop-iron-frame-stand.blend b/packages/frontend/assets/room/objects/tabletop-iron-frame-stand/tabletop-iron-frame-stand.blend new file mode 100644 index 0000000000..c8748320e8 Binary files /dev/null and b/packages/frontend/assets/room/objects/tabletop-iron-frame-stand/tabletop-iron-frame-stand.blend differ diff --git a/packages/frontend/assets/room/objects/tabletop-iron-frame-stand/tabletop-iron-frame-stand.glb b/packages/frontend/assets/room/objects/tabletop-iron-frame-stand/tabletop-iron-frame-stand.glb new file mode 100644 index 0000000000..5b1debb58b Binary files /dev/null and b/packages/frontend/assets/room/objects/tabletop-iron-frame-stand/tabletop-iron-frame-stand.glb differ diff --git a/packages/frontend/src/utility/room/object-defs.ts b/packages/frontend/src/utility/room/object-defs.ts index 07b2d79174..50909d7187 100644 --- a/packages/frontend/src/utility/room/object-defs.ts +++ b/packages/frontend/src/utility/room/object-defs.ts @@ -73,6 +73,7 @@ import { tabletopCalendar } from './objects/tabletopCalendar.js'; import { tabletopDigitalClock } from './objects/tabletopDigitalClock.js'; import { tabletopFlag } from './objects/tabletopFlag.js'; import { tabletopGlassPictureFrame } from './objects/tabletopGlassPictureFrame.js'; +import { tabletopIronFrameStand } from './objects/tabletopIronFrameStand.js'; import { tabletopPictureFrame } from './objects/tabletopPictureFrame.js'; import { tapestry } from './objects/tapestry.js'; import { tetrapod } from './objects/tetrapod.js'; @@ -160,6 +161,7 @@ export const OBJECT_DEFS = [ tabletopDigitalClock, tabletopFlag, tabletopGlassPictureFrame, + tabletopIronFrameStand, tabletopPictureFrame, tapestry, tetrapod, diff --git a/packages/frontend/src/utility/room/objects/desk.ts b/packages/frontend/src/utility/room/objects/desk.ts index be4741308c..5e6b9d3820 100644 --- a/packages/frontend/src/utility/room/objects/desk.ts +++ b/packages/frontend/src/utility/room/objects/desk.ts @@ -80,6 +80,7 @@ export const desk = defineObject({ case 'frameColor': applyFrameColor(); break; case 'boardColor': applyBoardColor(); break; case 'width': applySize(); break; + case 'depth': applySize(); break; } }, interactions: {}, diff --git a/packages/frontend/src/utility/room/objects/tabletopIronFrameStand.ts b/packages/frontend/src/utility/room/objects/tabletopIronFrameStand.ts new file mode 100644 index 0000000000..4ac66ddf93 --- /dev/null +++ b/packages/frontend/src/utility/room/objects/tabletopIronFrameStand.ts @@ -0,0 +1,101 @@ +/* + * 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 tabletopIronFrameStand = defineObject({ + id: 'tabletopIronFrameStand', + name: 'tabletopIronFrameStand', + options: { + schema: { + frameColor: { + type: 'color', + label: 'Frame color', + }, + boardColor: { + type: 'color', + label: 'Board color', + }, + width: { + type: 'range', + label: 'Width', + min: 0, + max: 1, + step: 0.01, + }, + depth: { + type: 'range', + label: 'Depth', + min: 0, + max: 1, + step: 0.01, + }, + height: { + type: 'range', + label: 'Height', + min: 0, + max: 1, + step: 0.01, + }, + }, + default: { + frameColor: [0.8, 0.8, 0.8], + boardColor: [0.8, 0.4, 0.1], + width: 0.2, + depth: 0.1, + height: 0.1, + }, + }, + placement: 'top', + createInstance: ({ options, model }) => { + const frameMaterial = model.findMaterial('__X_FRAME__'); + const boardMaterial = model.findMaterial('__X_BOARD__'); + + const applyFrameColor = () => { + const [r, g, b] = options.frameColor; + frameMaterial.albedoColor = new BABYLON.Color3(r, g, b); + }; + + applyFrameColor(); + + const applyBoardColor = () => { + const [r, g, b] = options.boardColor; + boardMaterial.albedoColor = new BABYLON.Color3(r, g, b); + }; + + applyBoardColor(); + + const applySize = () => { + for (const mesh of model.root.getChildMeshes()) { + if (mesh.morphTargetManager != null && mesh.morphTargetManager.getTargetByName('W') != null) { + mesh.morphTargetManager.getTargetByName('W').influence = options.width; + } + if (mesh.morphTargetManager != null && mesh.morphTargetManager.getTargetByName('D') != null) { + mesh.morphTargetManager.getTargetByName('D').influence = options.depth; + } + if (mesh.morphTargetManager != null && mesh.morphTargetManager.getTargetByName('H') != null) { + mesh.morphTargetManager.getTargetByName('H').influence = options.height; + } + } + model.updated(); + }; + + applySize(); + + return { + onOptionsUpdated: ([k, v]) => { + switch (k) { + case 'frameColor': applyFrameColor(); break; + case 'boardColor': applyBoardColor(); break; + case 'width': applySize(); break; + case 'depth': applySize(); break; + case 'height': applySize(); break; + } + }, + interactions: {}, + }; + }, +});