From eb33c8a93faf2d2bc9c820b5509fbf9c34625d34 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Mon, 25 May 2026 15:51:51 +0900 Subject: [PATCH] wip --- .../pages/rooms/room.add-object-dialog.vue | 2 +- .../src/world/room/ObjectContainer.ts | 2 - .../frontend/src/world/room/defineObjectUi.ts | 8 ++-- packages/frontend/src/world/room/engine.ts | 2 +- packages/frontend/src/world/room/object.ts | 27 +++++++----- .../world/room/objects/allInOnePc.schema.ts | 42 +++++++++++++++++++ .../src/world/room/objects/allInOnePc.ts | 36 +--------------- .../src/world/room/objects/allInOnePc.ui.ts | 4 +- .../frontend/src/world/room/previewEngine.ts | 4 +- 9 files changed, 70 insertions(+), 57 deletions(-) create mode 100644 packages/frontend/src/world/room/objects/allInOnePc.schema.ts diff --git a/packages/frontend/src/pages/rooms/room.add-object-dialog.vue b/packages/frontend/src/pages/rooms/room.add-object-dialog.vue index 937d6b9668..27fc95ac9b 100644 --- a/packages/frontend/src/pages/rooms/room.add-object-dialog.vue +++ b/packages/frontend/src/pages/rooms/room.add-object-dialog.vue @@ -69,7 +69,7 @@ import { ref, useTemplateRef, watch, onMounted, onUnmounted, reactive, nextTick, import * as Misskey from 'misskey-js'; import XObjectCustomizeForm from './room.object-customize-form.vue'; import XItem from './room.add-object-dialog.item.vue'; -import type { RawOptions, RoomObjectInstance, RoomStateObject } from '@/world/room/object.js'; +import type { RawOptions } from '@/world/room/object.js'; import type { PreviewEngineControllerOptions } from '@/world/room/previewEngineController.js'; import type { RoomAttachments } from '@/world/room/utility.js'; import { i18n } from '@/i18n.js'; diff --git a/packages/frontend/src/world/room/ObjectContainer.ts b/packages/frontend/src/world/room/ObjectContainer.ts index 8284f2e2ac..3b1a97efb9 100644 --- a/packages/frontend/src/world/room/ObjectContainer.ts +++ b/packages/frontend/src/world/room/ObjectContainer.ts @@ -163,8 +163,6 @@ export class ObjectContainer { subRootMesh.dispose(); - def.treatLoaderResult?.(loaderResult); - this.registerMeshes(this.subRoot.getChildMeshes()); this.model = new ModelManager(this.subRoot, loaderResult.meshes.filter(m => !m.isDisposed() && m.name !== '__root__'), def.hasTexture, (meshes) => { diff --git a/packages/frontend/src/world/room/defineObjectUi.ts b/packages/frontend/src/world/room/defineObjectUi.ts index d5d9ea05b9..79b75bafb9 100644 --- a/packages/frontend/src/world/room/defineObjectUi.ts +++ b/packages/frontend/src/world/room/defineObjectUi.ts @@ -3,13 +3,13 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import type { GetOptionsSchemaUiDef, OptionsSchema } from './object.js'; +import type { GetOptionsSchemaUiDef, ObjectSchemaDef } from './object.js'; -export type ObjectUiDef = { +export type ObjectUiDef = { name: string; - options: GetOptionsSchemaUiDef; + options: GetOptionsSchemaUiDef; }; -export function defineObjectUi(def: ObjectUiDef): ObjectUiDef { +export function defineObjectUi>(def: ObjectUiDef): ObjectUiDef { return def; } diff --git a/packages/frontend/src/world/room/engine.ts b/packages/frontend/src/world/room/engine.ts index 3f866a4096..be56911d6d 100644 --- a/packages/frontend/src/world/room/engine.ts +++ b/packages/frontend/src/world/room/engine.ts @@ -25,7 +25,7 @@ import { findMaterial, GRAPHICS_QUALITY, ModelManager, SYSTEM_HEYA_MESH_NAMES, S import { JapaneseEnvManager, MuseumEnvManager, SimpleEnvManager } from './env.js'; import { ObjectContainer } from './ObjectContainer.js'; import type { RoomAttachments } from './utility.js'; -import type { ObjectDef, RawOptions, RoomObjectInstance, RoomStateObject } from './object.js'; +import type { ObjectDef, RawOptions, RoomStateObject } from './object.js'; import type { GridMaterial } from '@babylonjs/materials'; import type { EnvManager, JapaneseEnvOptions, SimpleEnvOptions } from './env.js'; import { genId } from '@/utility/id.js'; diff --git a/packages/frontend/src/world/room/object.ts b/packages/frontend/src/world/room/object.ts index 1cc613ac79..310e2157e9 100644 --- a/packages/frontend/src/world/room/object.ts +++ b/packages/frontend/src/world/room/object.ts @@ -85,7 +85,7 @@ type SeedOptionSchema = { type: 'seed'; }; -export type OptionsSchema = Record; +type OptionsSchema = Record; export type RawOptions = Record & { readonly __brand: unique symbol; @@ -146,7 +146,7 @@ export type SnapshotRenderingHelperWrapper = { fixParticleSystem: (ps: BABYLON.ParticleSystem) => void; }; -export type ObjectDef = { +export type ObjectSchemaDef = { id: string; options: { schema: string extends keyof OpSc ? OptionsSchema : OpSc; @@ -156,10 +156,11 @@ export type ObjectDef = { hasCollisions?: boolean; hasTexture?: boolean; canPreMeshesMerging?: boolean; // TODO: 除外するメッシュ名を指定できるようにする - //groupingMeshes: string[]; // multi-materialなメッシュは複数のメッシュに分割されるが、それだと不便な場合に追加の親メッシュでグルーピングするための指定 isChair?: boolean; - treatLoaderResult?: (loaderResult: BABYLON.AssetContainer) => void; - path?: (options: string extends keyof OpSc ? ConvertedOptions : Readonly>) => string; +}; + +export type ObjectDef = Schema & { + path?: (options: string extends keyof Schema['options']['schema'] ? ConvertedOptions : Readonly>) => string; createInstance: (args: { scene: BABYLON.Scene; // TODO: snapshot renderingの関心を隠蔽した方が綺麗かもしれない @@ -167,7 +168,7 @@ export type ObjectDef = { sr: SnapshotRenderingHelperWrapper; lc: BABYLON.ClusteredLightContainer | null; root: BABYLON.TransformNode; - options: string extends keyof OpSc ? ConvertedOptions : Readonly>; + options: string extends keyof Schema['options']['schema'] ? ConvertedOptions : Readonly>; model: ModelManager; id: string; timer: Timer; @@ -175,18 +176,22 @@ export type ObjectDef = { stickyMarkerMeshUpdated?: (mesh: BABYLON.Mesh) => void; sitChair?: () => void; reloadModel: () => void; - }) => RoomObjectInstance> | Promise>>; // TODO: createInstanceをasyncにするのではなく、別にreadyみたいなものを返させる + }) => RoomObjectInstance> | Promise>>; // TODO: createInstanceをasyncにするのではなく、別にreadyみたいなものを返させる }; -export function defineObject(def: ObjectDef): ObjectDef { +export function defineObjectSchema(def: ObjectSchemaDef): ObjectSchemaDef { return def; } -export function defineObjectClass(baseDef: Partial>): { - extend: (childDef: Partial>) => ObjectDef; +export function defineObject>(schema: Schema, def: Pick, 'path' | 'createInstance'>): ObjectDef { + return { ...schema, ...def }; +} + +export function defineObjectClass>(baseDef: Partial>): { + extend: (childDef: Partial>) => ObjectDef; } { return { - extend: (childDef) => ({ ...baseDef, ...childDef }) as ObjectDef, + extend: (childDef) => ({ ...baseDef, ...childDef }) as ObjectDef, }; } diff --git a/packages/frontend/src/world/room/objects/allInOnePc.schema.ts b/packages/frontend/src/world/room/objects/allInOnePc.schema.ts new file mode 100644 index 0000000000..f7b2529af5 --- /dev/null +++ b/packages/frontend/src/world/room/objects/allInOnePc.schema.ts @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineObjectSchema } from '../object.js'; + +export const allInOnePc_schema = defineObjectSchema({ + id: 'allInOnePc', + placement: 'top', + hasTexture: true, + options: { + schema: { + bodyMat: { + type: 'material', + }, + bezelMat: { + type: 'material', + }, + screenBrightness: { + type: 'range', + min: 0, + max: 1, + step: 0.01, + }, + image: { + type: 'image', + presets: [{ + value: 'desktop', + }], + }, + }, + default: { + bodyMat: { color: [1, 1, 1], roughness: 0.5, metallic: 1 }, + bezelMat: { color: [0, 0, 0], roughness: 0, metallic: 0 }, + screenBrightness: 0.5, + image: { + type: null, + }, + }, + }, +}); diff --git a/packages/frontend/src/world/room/objects/allInOnePc.ts b/packages/frontend/src/world/room/objects/allInOnePc.ts index 0eff4ab974..d4d1721ca2 100644 --- a/packages/frontend/src/world/room/objects/allInOnePc.ts +++ b/packages/frontend/src/world/room/objects/allInOnePc.ts @@ -7,41 +7,9 @@ import * as BABYLON from '@babylonjs/core'; import { createTextureManager, defineObject } from '../object.js'; import { cm, WORLD_SCALE } from '../../utility.js'; import { getLightRangeFactorByGraphicsQuality } from '../utility.js'; +import { allInOnePc_schema } from './allInOnePc.schema.js'; -export const allInOnePc = defineObject({ - id: 'allInOnePc', - options: { - schema: { - bodyMat: { - type: 'material', - }, - bezelMat: { - type: 'material', - }, - screenBrightness: { - type: 'range', - min: 0, - max: 1, - step: 0.01, - }, - image: { - type: 'image', - presets: [{ - value: 'desktop', - }], - }, - }, - default: { - bodyMat: { color: [1, 1, 1], roughness: 0.5, metallic: 1 }, - bezelMat: { color: [0, 0, 0], roughness: 0, metallic: 0 }, - screenBrightness: 0.5, - image: { - type: null, - }, - }, - }, - placement: 'top', - hasTexture: true, +export const allInOnePc = defineObject(allInOnePc_schema, { createInstance: async ({ lc, scene, options, model, graphicsQuality }) => { const matrix = model.root.getWorldMatrix(true); const scale = new BABYLON.Vector3(); diff --git a/packages/frontend/src/world/room/objects/allInOnePc.ui.ts b/packages/frontend/src/world/room/objects/allInOnePc.ui.ts index ef80152113..2302887bbd 100644 --- a/packages/frontend/src/world/room/objects/allInOnePc.ui.ts +++ b/packages/frontend/src/world/room/objects/allInOnePc.ui.ts @@ -4,10 +4,10 @@ */ import { defineObjectUi } from '../defineObjectUi.js'; -import type { allInOnePc } from './allInOnePc.js'; +import type { allInOnePc_schema } from './allInOnePc.schema.js'; import { i18n } from '@/i18n.js'; -export const allInOnePc_ui = defineObjectUi({ +export const allInOnePc_ui = defineObjectUi({ name: i18n.ts._miRoom._objects.allInOnePc, options: { bodyMat: { diff --git a/packages/frontend/src/world/room/previewEngine.ts b/packages/frontend/src/world/room/previewEngine.ts index 79a7960f03..a5c007e3c7 100644 --- a/packages/frontend/src/world/room/previewEngine.ts +++ b/packages/frontend/src/world/room/previewEngine.ts @@ -9,9 +9,9 @@ import { GridMaterial } from '@babylonjs/materials'; import { camelToKebab, WORLD_SCALE, cm, getMeshesBoundingBox, Timer, sleep, ArcRotateCameraManualInput } from '../utility.js'; import { EngineBase } from '../EngineBase.js'; import { getObjectDef } from './object-defs.js'; -import { SYSTEM_MESH_NAMES, ModelManager, GRAPHICS_QUALITY } from './utility.js'; +import { SYSTEM_MESH_NAMES, GRAPHICS_QUALITY } from './utility.js'; import { ObjectContainer } from './ObjectContainer.js'; -import type { RawOptions, RoomObjectInstance } from './object.js'; +import type { RawOptions } from './object.js'; import type { RoomAttachments } from './utility.js'; import { genId } from '@/utility/id.js'; import { deepClone } from '@/utility/clone.js';