diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e46b287e2e..a7d73a0d65 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -4031,3 +4031,6 @@ _miRoom: frameMat: "フレームの素材" height: "段数" width: "幅" + kakejiku: "掛軸" + _kakejiku: + image: "画像" diff --git a/packages/backend/src/core/WorldRoomService.ts b/packages/backend/src/core/WorldRoomService.ts index 32c15a1712..e253b6af97 100644 --- a/packages/backend/src/core/WorldRoomService.ts +++ b/packages/backend/src/core/WorldRoomService.ts @@ -36,6 +36,7 @@ const driveFileReferencingOptions = { laptopPc: ['image'], handheldGameConsole: ['image'], largeMousepad: ['image'], + kakejiku: ['image'], } as Record; @Injectable() diff --git a/packages/frontend-misskey-world-engine/src/room/furniture-defs.ts b/packages/frontend-misskey-world-engine/src/room/furniture-defs.ts index d0611c144d..b83257a2c3 100644 --- a/packages/frontend-misskey-world-engine/src/room/furniture-defs.ts +++ b/packages/frontend-misskey-world-engine/src/room/furniture-defs.ts @@ -117,6 +117,7 @@ import { woodSoundAbsorbingPanel } from './furnitures/woodSoundAbsorbingPanel.js import { haniwa } from './furnitures/haniwa.js'; import { ceilingFan } from './furnitures/ceilingFan.js'; import { downlight } from './furnitures/downlight.js'; +import { kakejiku } from './furnitures/kakejiku.js'; import type { FurnitureDef } from './furniture.js'; export const FUNITURE_DEFS = [ @@ -232,6 +233,7 @@ export const FUNITURE_DEFS = [ wireBasket, haniwa, downlight, + kakejiku, ] as FurnitureDef[]; export function getFurnitureDef(type: string): FurnitureDef { diff --git a/packages/frontend-misskey-world-engine/src/room/furnitures/kakejiku.ts b/packages/frontend-misskey-world-engine/src/room/furnitures/kakejiku.ts new file mode 100644 index 0000000000..f4dce6e9e4 --- /dev/null +++ b/packages/frontend-misskey-world-engine/src/room/furnitures/kakejiku.ts @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as BABYLON from '@babylonjs/core/pure.js'; +import { kakejiku_schema } from 'misskey-world/src/room/furnitures/kakejiku.schema.js'; +import { createTextureManager, defineFuniture } from '../furniture.js'; + +export const kakejiku = defineFuniture(kakejiku_schema, { + createInstance: async ({ scene, options, model }) => { + const imageMesh = model.findMesh('__X_IMAGE__'); + imageMesh.rotationQuaternion = null; + + const imageMaterial = model.findMaterial('__X_IMAGE__'); + imageMaterial.albedoColor = new BABYLON.Color3(1, 1, 1); + + const textureManager = createTextureManager(imageMesh, () => 33.5 / 88, scene); + + const applyImage = () => { + imageMaterial.unfreeze(); + let url: string | null = null; + if (options.image.type === '_custom_') { + url = options.image.custom?.url ?? null; + } + return textureManager.change(url, options.image.fit, options.image.rotation).then((tex) => { + imageMaterial.albedoTexture = tex; + }); + }; + + await applyImage(); + + return { + onInited: () => { + + }, + onOptionsUpdated: ([k, v]) => { + switch (k) { + case 'image': + applyImage(); + break; + } + }, + interactions: {}, + dispose: () => { + textureManager.dispose(); + }, + }; + }, +}); diff --git a/packages/frontend/assets/world/objects/kakejiku/kakejiku.blend b/packages/frontend/assets/world/objects/kakejiku/kakejiku.blend new file mode 100644 index 0000000000..800af80ac9 Binary files /dev/null and b/packages/frontend/assets/world/objects/kakejiku/kakejiku.blend differ diff --git a/packages/frontend/assets/world/objects/kakejiku/kakejiku.glb b/packages/frontend/assets/world/objects/kakejiku/kakejiku.glb new file mode 100644 index 0000000000..ec49500c06 Binary files /dev/null and b/packages/frontend/assets/world/objects/kakejiku/kakejiku.glb differ diff --git a/packages/frontend/assets/world/objects/kakejiku/texture.af b/packages/frontend/assets/world/objects/kakejiku/texture.af new file mode 100644 index 0000000000..7a10784b27 Binary files /dev/null and b/packages/frontend/assets/world/objects/kakejiku/texture.af differ diff --git a/packages/frontend/assets/world/objects/kakejiku/texture.png b/packages/frontend/assets/world/objects/kakejiku/texture.png new file mode 100644 index 0000000000..22c9968a1f Binary files /dev/null and b/packages/frontend/assets/world/objects/kakejiku/texture.png differ diff --git a/packages/frontend/src/world/room/furniture-ui-defs.ts b/packages/frontend/src/world/room/furniture-ui-defs.ts index c112014ef6..aeeb28b8e0 100644 --- a/packages/frontend/src/world/room/furniture-ui-defs.ts +++ b/packages/frontend/src/world/room/furniture-ui-defs.ts @@ -115,6 +115,7 @@ import { woodSoundAbsorbingPanel_ui } from './furnitures/woodSoundAbsorbingPanel import { haniwa_ui } from './furnitures/haniwa.ui.js'; import { ceilingFan_ui } from './furnitures/ceilingFan.ui.js'; import { downlight_ui } from './furnitures/downlight.ui.js'; +import { kakejiku_ui } from './furnitures/kakejiku.ui.js'; import type { FurnitureUiDef } from './defineFurnitureUi.js'; export const FURNITURE_UI_DEFS = { @@ -229,6 +230,7 @@ export const FURNITURE_UI_DEFS = { wireBasket: wireBasket_ui, haniwa: haniwa_ui, downlight: downlight_ui, + kakejiku: kakejiku_ui, } as Record; export function getFurnitureUiDef(type: string): FurnitureUiDef { diff --git a/packages/frontend/src/world/room/furnitures/kakejiku.ui.ts b/packages/frontend/src/world/room/furnitures/kakejiku.ui.ts new file mode 100644 index 0000000000..a83b083321 --- /dev/null +++ b/packages/frontend/src/world/room/furnitures/kakejiku.ui.ts @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineFurnitureUi } from '../defineFurnitureUi.js'; +import type { kakejiku_schema } from 'misskey-world/src/room/furnitures/kakejiku.schema.js'; +import { i18n } from '@/i18n.js'; + +export const kakejiku_ui = defineFurnitureUi({ + name: i18n.ts._miRoom._furnitures.kakejiku, + options: { + image: { + label: i18n.ts._miRoom._furnitures._kakejiku.image, + }, + }, +}); diff --git a/packages/i18n/src/autogen/locale.ts b/packages/i18n/src/autogen/locale.ts index 0d1ce9b45b..0ddad512e4 100644 --- a/packages/i18n/src/autogen/locale.ts +++ b/packages/i18n/src/autogen/locale.ts @@ -14991,6 +14991,16 @@ export interface Locale extends ILocale { */ "width": string; }; + /** + * 掛軸 + */ + "kakejiku": string; + "_kakejiku": { + /** + * 画像 + */ + "image": string; + }; }; }; } diff --git a/packages/misskey-world/src/room/furniture-schema-defs.ts b/packages/misskey-world/src/room/furniture-schema-defs.ts index 481e515a7e..79d1360ee0 100644 --- a/packages/misskey-world/src/room/furniture-schema-defs.ts +++ b/packages/misskey-world/src/room/furniture-schema-defs.ts @@ -115,6 +115,7 @@ import { woodSoundAbsorbingPanel_schema } from './furnitures/woodSoundAbsorbingP import { haniwa_schema } from './furnitures/haniwa.schema.js'; import { ceilingFan_schema } from './furnitures/ceilingFan.schema.js'; import { downlight_schema } from './furnitures/downlight.schema.js'; +import { kakejiku_schema } from './furnitures/kakejiku.schema.js'; import type { FurnitureSchemaDef } from './furniture.js'; export const FURNITURE_SCHEMA_DEFS = { @@ -229,6 +230,7 @@ export const FURNITURE_SCHEMA_DEFS = { wireBasket: wireBasket_schema, haniwa: haniwa_schema, downlight: downlight_schema, + kakejiku: kakejiku_schema, } as Record>; export function getFurnitureSchemaDef(type: string): FurnitureSchemaDef { diff --git a/packages/misskey-world/src/room/furnitures/kakejiku.schema.ts b/packages/misskey-world/src/room/furnitures/kakejiku.schema.ts new file mode 100644 index 0000000000..15cc10b797 --- /dev/null +++ b/packages/misskey-world/src/room/furnitures/kakejiku.schema.ts @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineFurnitureSchema } from '../furniture.js'; +export const kakejiku_schema = defineFurnitureSchema({ + id: 'kakejiku', + options: { + schema: { + image: { + type: 'image', + presets: [], + }, + }, + default: { + image: { type: null }, + }, + }, + placement: 'side', + hasCollisions: false, + hasTexture: true, +});