/* * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ import * as BABYLON from '@babylonjs/core'; import type { RoomEngine } from './engine.js'; import type { ModelManager } from './utility.js'; import type { Timer } from '../utility.js'; // babylonのドメイン知識は持たない export type RoomStateObject = { id: string; type: string; position: [number, number, number]; rotation: [number, number, number]; options: Options; /** * 別のオブジェクトのID */ sticky?: string | null; }; export type RoomObjectInstance = { onInited?: () => void; onOptionsUpdated?: (kv: [K, V]) => void; interactions: Record void; }>; primaryInteraction?: string | null; resetTemporaryState?: () => void; dispose?: () => void; }; type NumberOptionSchema = { type: 'number'; label: string; min?: number; max?: number; step?: number; }; type BooleanOptionSchema = { type: 'boolean'; label: string; }; type StringOptionSchema = { type: 'string'; label: string; }; type ColorOptionSchema = { type: 'color'; label: string; }; type EnumOptionSchema = { type: 'enum'; label: string; enum: string[]; }; type RangeOptionSchema = { type: 'range'; label: string; min: number; max: number; step?: number; }; type ImageOptionSchema = { type: 'image'; label: string; }; type SeedOptionSchema = { type: 'seed'; label: string; }; type OptionsSchema = Record; type GetOptionsSchemaValues = { [K in keyof T]: T[K] extends NumberOptionSchema ? number : T[K] extends BooleanOptionSchema ? boolean : T[K] extends StringOptionSchema ? string : T[K] extends ColorOptionSchema ? [number, number, number] : T[K] extends EnumOptionSchema ? T[K]['enum'][number] : T[K] extends RangeOptionSchema ? number : T[K] extends ImageOptionSchema ? string | null : T[K] extends SeedOptionSchema ? number : never; }; export type ObjectDef = { id: string; name: string; path?: string; options: { schema: OpSc; default: GetOptionsSchemaValues; }; placement: 'top' | 'side' | 'bottom' | 'wall' | 'ceiling' | 'floor'; hasCollisions?: boolean; hasTexture?: boolean; canPreMeshesMerging?: boolean; //groupingMeshes: string[]; // multi-materialなメッシュは複数のメッシュに分割されるが、それだと不便な場合に追加の親メッシュでグルーピングするための指定 isChair?: boolean; treatLoaderResult?: (loaderResult: BABYLON.AssetContainer) => void; createInstance: (args: { room?: RoomEngine | null; scene: BABYLON.Scene; root: BABYLON.Mesh; options: Readonly>; model: ModelManager; id: string; timer: Timer; stickyMarkerMeshUpdated?: (mesh: BABYLON.Mesh) => void; }) => RoomObjectInstance> | Promise>>; // TODO: createInstanceをasyncにするのではなく、別にreadyみたいなものを返させる }; export function defineObject(def: ObjectDef): ObjectDef { return def; } export function defineObjectClass(baseDef: Partial>): { extend: (childDef: Partial>) => ObjectDef; } { return { extend: (childDef) => ({ ...baseDef, ...childDef }) as ObjectDef, }; }