import { AbstractMesh } from '@babylonjs/core'; import { Animation as Animation_2 } from '@babylonjs/core'; import { AnimationEventHandler } from 'react'; import { AnimationGroup } from '@babylonjs/core'; import { AnyWebByteStream } from 'strtok3'; import { ArcRotateCamera } from '@babylonjs/core'; import { AriaRole } from 'react'; import { Attributes } from 'react'; import { Awareness } from 'rhine-var'; import { BaseTexture } from '@babylonjs/core'; import { ClipboardEventHandler } from 'react'; import { Color3 } from '@babylonjs/core'; import { Color3 as Color3_2 } from '@babylonjs/core/Maths/math.color'; import { Color4 } from '@babylonjs/core'; import { CompositionEventHandler } from 'react'; import { CSSProperties } from 'react'; import { CubeTexture } from '@babylonjs/core'; import { DetailedHTMLProps } from 'react'; import { DragEvent as DragEvent_2 } from 'react'; import { DragEventHandler } from 'react'; import { DynamicTexture } from '@babylonjs/core'; import { Engine } from '@babylonjs/core'; import { EventType } from 'rhine-var'; import { FocusEventHandler } from 'react'; import { FormEventHandler } from 'react'; import { ForwardRefExoticComponent } from 'react'; import { FunctionComponent } from 'react'; import { Geometry } from '@babylonjs/core'; import { HTMLAttributeAnchorTarget } from 'react'; import { HTMLAttributeReferrerPolicy } from 'react'; import { HTMLAttributes } from 'react'; import { InputBlock } from '@babylonjs/core'; import { InputEventHandler } from 'react'; import { IParticleSystem } from '@babylonjs/core'; import { JSX } from 'react/jsx-runtime'; import { Key } from 'react'; import { KeyboardEventHandler } from 'react'; import { Light } from '@babylonjs/core'; import { Locale as Locale_2 } from 'use-intl'; import { LocalePrefix } from 'next-intl/routing'; import { Material } from '@babylonjs/core'; import { Mesh } from '@babylonjs/core'; import { MouseEvent as MouseEvent_2 } from 'react'; import { MouseEventHandler } from 'react'; import { NavigateOptions } from 'next/dist/shared/lib/app-router-context.shared-runtime'; import { Node as Node_2 } from '@babylonjs/core'; import { NodeMaterial } from '@babylonjs/core'; import { NodeMaterialBlock } from '@babylonjs/core'; import { NodeMaterialBlockConnectionPointTypes } from '@babylonjs/core'; import { Observable } from '@babylonjs/core/Misc/observable'; import { PBRMaterial } from '@babylonjs/core'; import { PointerEventHandler } from 'react'; import { PrefetchOptions } from 'next/dist/shared/lib/app-router-context.shared-runtime'; import { Quaternion } from '@babylonjs/core'; import { QueryParams } from 'next-intl/navigation'; import { default as React_2 } from 'react'; import { ReactEventHandler } from 'react'; import { ReactNode } from 'react'; import { ReactPortal } from 'react'; import { RecursiveArray } from 'rhine-var'; import { RecursiveCrossRhineVar } from 'rhine-var'; import { RecursiveMap } from 'rhine-var'; import { RecursiveObject } from 'rhine-var'; import { RedirectType } from 'next/navigation'; import { Ref } from 'react'; import { RefAttributes } from 'react'; import type { Resource } from 'rhine-base/network'; import type { ResourceFileInfo } from 'rhine-base/network'; import { RhineVarArray } from 'rhine-var'; import { RhineVarMap } from 'rhine-var'; import { Root } from 'react-dom/client'; import { RvKey } from 'rhine-var'; import { RvPath } from 'rhine-var'; import { Scene } from '@babylonjs/core'; import { ShadowGenerator } from '@babylonjs/core'; import { SixDofDragBehavior } from '@babylonjs/core/Behaviors/Meshes/sixDofDragBehavior'; import { Skeleton } from '@babylonjs/core'; import { StandardMaterial } from '@babylonjs/core'; import { StoredRhineVar } from 'rhine-var'; import { Texture } from '@babylonjs/core'; import { TextureBlock } from '@babylonjs/core'; import { ToggleEventHandler } from 'react'; import { TouchEvent as TouchEvent_2 } from 'react'; import { TouchEventHandler } from 'react'; import { TransformNode } from '@babylonjs/core'; import { TransitionEventHandler } from 'react'; import { UIEventHandler } from 'react'; import { UrlObject } from 'url'; import { UtilityLayerRenderer } from '@babylonjs/core/Rendering/utilityLayerRenderer'; import { Vector2 } from '@babylonjs/core'; import { Vector3 } from '@babylonjs/core'; import { WebGPUEngine } from '@babylonjs/core'; import { WebXRDefaultExperience } from '@babylonjs/core/XR/webXRDefaultExperience'; import { WheelEvent as WheelEvent_2 } from 'react'; import { WheelEventHandler } from 'react'; /** * @public */ export declare const AcceptMime: { ANY: string; UNKNOWN: string; SCENE: string; MESH: string; LIGHT: string; CAMERA: string; TEXTURE: string; MATERIAL: string; UV: string; ANIMATION: string; GLB: string; GLTF: string; STL: string; OBJ: string; MP3: string; WAV: string; AAC: string; OGG: string; FLAC: string; OPUS: string; JPG: string; PNG: string; GIF: string; BMP: string; WebP: string; SVG: string; TIFF: string; ICO: string; HEIF: string; AVIF: string; MP4: string; WebM: string; AVI: string; MPEG: string; MOV: string; WMV: string; FLV: string; OGV: string; GP3: string; MKV: string; JSON: string; NF: string; TXT: string; MARKDOWN: string; SUPPORT_IMAGE_LIST: string[]; SUPPORT_MODEL_LIST: string[]; SUPPORT_VIDEO_LIST: string[]; SUPPORT_BABYLON_LIST: string[]; SUPPORT_AUDIO_LIST: string[]; SUPPORT_TEXT_LIST: string[]; SUPPORT_JSON_LIST: string[]; SUPPORT_NEXTFLOW_LIST: string[]; SUPPORT_ALL_LIST: string[]; SUPPORT_FILE_LIST: string[]; SUPPORT_RENDER_LIST: string[]; SUPPORT_TEXTURE_LIST: string[]; ATTACH_LIST: string[]; getMimeByBlob: typeof getMimeByBlob; getMimeByPath: typeof getMimeByPath; getMimeByUrl: typeof getMimeByUrl; getMimeByBuffer: typeof getMimeByBuffer; getMimeByStream: typeof getMimeByStream; getMime: typeof getMime; getExtension: typeof getExtension; isSupport: typeof isSupport; isSupportFile: typeof isSupportFile; isSupportImage: typeof isSupportImage; isSupportModel: typeof isSupportModel; isSupportVideo: typeof isSupportVideo; isSupportText: typeof isSupportText; isSupportJson: typeof isSupportJson; isBabylon: typeof isBabylon; isSupportAudio: typeof isSupportAudio; isSupportRender: typeof isSupportRender; isSupportTexture: typeof isSupportTexture; isTexture: typeof isTexture; isMaterial: typeof isMaterial; isUV: typeof isUV; isAttach: typeof isAttach; }; /** * @public */ export declare interface AddLocalDataOption extends Omit { status?: LocalDataStatus; progress?: number; } /** * @public */ export declare function Anchor(props: AnchorProps): JSX.Element; /** * @public */ export declare interface AnchorProps extends DivProps { list: string[]; value: number; onSelectChange: (value: number) => void; middle?: boolean; } /** * @public */ export declare enum AnimationDuration { BETWEEN = 1200, OPERATE = 350, FIRST = 700, IMMEDIATELY = 0, RESET = 300, IMMEDIATELY_MODE_THRESHOLD = 67 } /** * @public */ export declare class AnimationNativeAttribute extends NodeAttribute { path: string[]; defaultValue: RvNative; generate(sid: string, nid: string): RvNative; } declare function approximatelyEqual(n1: number, n2: number, bias?: number): boolean; /** * @public */ export declare type Attribute = NodeAttribute | StepAttribute | GlobalAttribute; /** * @public */ export declare class AttributeService { static get instance(): AttributeService; private constructor(); /** 黑名单 */ commonBlacklist: RvPath[]; nodeBlacklist: RvPath[]; stepBlacklist: RvPath[]; globalBlacklist: RvPath[]; /** 属性存储 */ nodeAttributes: NodeAttribute[]; stepAttributes: StepAttribute[]; globalAttributes: GlobalAttribute[]; /** 注册属性 */ register(attribute: Attribute): void; /** 通过路径精确匹配获取属性 */ get(type: AttributeType, path: RvPath | string): Attribute | undefined; /** 通过路径获取 NodeAttribute */ getNodeAttribute(path: RvPath | string): NodeAttribute | undefined; /** 通过路径获取 StepAttribute */ getStepAttribute(path: RvPath | string): StepAttribute | undefined; /** 通过路径获取 GlobalAttribute */ getGlobalAttribute(path: RvPath | string): GlobalAttribute | undefined; /** 根据类型获取属性列表,不传入类型的时候返回所有 */ getList(type?: AttributeType): Attribute[]; isPathConflict(type: AttributeType, path: RvPath): boolean; createContainer(source: StoredRhineVar, path: RvPath): RecursiveMap; } /** * @public */ export declare enum AttributeType { Global = "GLOBAL", Step = "STEP", Node = "NODE" } /** * 自动播放服务 * * 负责管理场景的自动播放功能,按照设定的时间间隔自动切换场景步骤(Step)。 * 支持循环播放模式,并根据会议状态和页面浏览状态自动控制播放行为。 * * @remarks * - 单例模式,通过 `AutoPlayService.instance` 获取实例 * - 自动播放会受到以下条件限制: * - 用户正在跟随访客时不播放 * - 页面不在浏览状态时不播放 * - 项目设置中未开启自动播放时不播放 * - 播放间隔和循环模式由 `RvProjectService.state.playing` 配置决定 * * @example * ```typescript * // 获取服务实例 * const autoPlayService = AutoPlayService.instance * * // 检查是否有下一个步骤 * const hasNext = autoPlayService.hasNextStep(true) * * // 尝试跳转到下一个步骤 * const success = autoPlayService.tryNextStep(false) * * // 手动启动下一次自动播放(通常由服务内部调用) * autoPlayService.next(3000, true) // 3秒后切换,循环播放 * ``` * * @public */ export declare class AutoPlayService { /** * 获取服务单例实例 * * @returns AutoPlayService 单例实例 * * @public */ static get instance(): AutoPlayService; /** * 私有构造函数 * * 确保单例模式,外部无法直接实例化。 * 构造时会自动调用初始化方法。 * * @private */ private constructor(); /** * 启动下一次自动播放 * * 设置一个定时器,在指定的时间间隔后自动切换到下一个场景步骤。 * 如果有下一个步骤,会递归调用自己继续下一轮播放。 * * @param interval - 播放间隔时间(毫秒) * @param loop - 是否循环播放,true 表示播放到最后一个步骤后回到第一个 * * @remarks * 此方法会持续递归调用直到没有下一个步骤或被 stopAutoPlay 中断。 * 定时器 ID 会存储在 currentTimeoutId 中,用于后续取消操作。 * * @public */ next(interval: number, loop: boolean): void; /** * 检查是否有下一个步骤 * * 判断当前场景是否可以切换到下一个步骤。 * * @param loop - 是否循环播放模式 * @returns true 表示有下一个步骤可以切换,false 表示已经是最后一个步骤且不循环 * * @remarks * 循环模式下,如果至少有2个步骤,则始终返回 true(可以循环回第一个)。 * 非循环模式下,只有当前步骤不是最后一个时才返回 true。 * * @public */ hasNextStep(loop: boolean): boolean; /** * 尝试切换到下一个步骤 * * 根据当前步骤位置和循环模式,切换到下一个场景步骤。 * * @param loop - 是否循环播放模式 * @returns true 表示成功切换到下一个步骤,false 或 undefined 表示切换失败 * * @remarks * - 如果当前不是最后一个步骤,切换到顺序中的下一个步骤 * - 如果已经是最后一个步骤且开启了循环模式,切换到第一个步骤 * - 循环模式至少需要2个步骤才能生效 * * 实际的步骤切换通过修改 `SpaceService.instance.page.sid` 实现。 * * @public */ tryNextStep(loop: boolean): true | undefined; } /** * @public */ export declare interface AwarenessChanges { added: number[]; updated: number[]; removed: number[]; } /** * @public */ export declare type AwarenessChangeSubscriber = (changeStates: Map, changes: AwarenessChanges) => void; /** * @public */ export declare class AwarenessService { DEFAULT_UPDATE_INTERVAL: number; static get instance(): AwarenessService; private constructor(); name: string; color: string; static COLORS: string[]; awareness: Awareness | undefined; states: Map; setLocalState(state?: RvAwareness): void; setLocalStateCamera(state?: RvCameraLocation): void; setLocalStateField(field: string, state: unknown): void; getLocalState(): { [x: string]: any; } | null; startUpdate(): void; stopUpdate(): void; setUpdateInterval(interval: number): void; resetUpdateInterval(): void; subscribeChange(subscriber: AwarenessChangeSubscriber): () => void; unsubscribeChange(subscriber: AwarenessChangeSubscriber): void; getCurrentRvAwareness(): RvAwareness; CLICK_RETENTION_PERIOD: number; CLICK_MAX_COUNT: number; addClick(position: V3): void; } /** * @public */ export declare abstract class BaseAttribute { abstract type: AttributeType; abstract path: RvPath; defaultValue: T; getPathString(): string; isMyPath(path: string | RvPath): boolean; } /** * @public */ export declare interface BasePlugin { id: string; version: string; namespace: string; intl?: Intl_2; createIntl: (namespace: string) => Intl_2; name: string; description: string; type: PluginType; theme: ThemeColor; data?: Record; messages?: Record; onInstall?: () => Promise; onEnable?: () => Promise; onDisable?: () => Promise; onUninstall?: () => Promise; } export declare class BasicAttribute extends NodeAttribute { path: string[]; defaultValue: RvBasic; generate(sid?: string, nid?: string): RvBasic; } /** * @public */ export declare function BatchApply(props: BatchApplyProps): JSX.Element; /** * @public */ export declare interface BatchApplyProps extends DivProps { tip?: string; onConfirm?: () => void; onCancel?: () => void; } /** * 批量应用服务 * * @remarks * 该服务用于管理多场景批量编辑功能。允许用户选择多个场景(step), * 并对选中的场景批量应用相同的属性变更。 * * 主要功能: * - 管理选中场景列表 * - 提供全选/取消全选功能 * - 支持订阅选中状态变化 * - 提供批量遍历和应用操作的方法 * * @example * ```typescript * // 获取服务实例 * const batchService = BatchApplyService.instance * * // 订阅选中状态变化 * const unsubscribe = batchService.subscribe((selected) => { * console.log('当前选中的场景:', selected) * }) * * // 选择所有场景 * batchService.selectAll() * * // 批量修改场景属性 * batchService.forEach((rvStep) => { * rvStep.name.set('新场景名称') * }) * * // 取消订阅 * unsubscribe() * ``` * * @public */ export declare class BatchApplyService { /** * 获取 BatchApplyService 的单例实例 * * @returns BatchApplyService 的单例实例 * * @public */ static get instance(): BatchApplyService; private constructor(); /** * 获取当前选中的场景ID数组 * * @returns 选中的场景ID数组 * * @public */ get selected(): string[]; /** * 设置当前选中的场景ID数组 * * @param selected - 要设置的场景ID数组 * * @remarks * 设置选中状态后,会自动通知所有订阅者 * * @public */ set selected(selected: string[]); /** * 选中所有场景 * * @remarks * 将当前项目中所有场景的ID添加到选中列表中 * * @example * ```typescript * BatchApplyService.instance.selectAll() * ``` * * @public */ selectAll(): void; /** * 取消选中所有场景 * * @remarks * 清空选中列表,不再选中任何场景 * * @example * ```typescript * BatchApplyService.instance.unselectAll() * ``` * * @public */ unselectAll(): void; /** * 判断是否已选中所有场景 * * @returns 如果所有场景都已选中返回 true,否则返回 false * * @example * ```typescript * if (BatchApplyService.instance.isAllSelected()) { * console.log('已选中所有场景') * } * ``` * * @public */ isAllSelected(): boolean; /** * 订阅选中状态变化 * * @param subscriber - 订阅回调函数,当选中状态变化时会被调用 * @returns 取消订阅的函数,调用后将移除该订阅者 * * @remarks * 当选中的场景列表发生变化时,所有订阅者都会收到通知 * * @example * ```typescript * const unsubscribe = BatchApplyService.instance.subscribe((selected) => { * console.log('选中场景数量:', selected.length) * console.log('选中场景ID:', selected) * }) * * // 需要取消订阅时调用 * unsubscribe() * ``` * * @public */ subscribe(subscriber: BatchApplySubscriber): () => void; /** * 取消订阅选中状态变化 * * @param subscriber - 要取消的订阅回调函数 * * @remarks * 从订阅列表中移除指定的订阅者 * * @public */ unsubscribe(subscriber: BatchApplySubscriber): void; /** * 遍历所有选中的场景并执行操作 * * @param f - 对每个场景执行的回调函数,接收场景的 RhineVar 对象 * * @throws 如果场景数据获取失败会抛出错误 * * @remarks * 遍历所有选中的场景,对每个场景执行指定的操作。 * 这是批量修改场景属性的核心方法。 * * @example * ```typescript * // 批量修改所有选中场景的名称 * BatchApplyService.instance.forEach((rvStep) => { * rvStep.name.set('统一场景名称') * }) * * // 批量修改场景的背景颜色 * BatchApplyService.instance.forEach((rvStep) => { * rvStep.background.color.set('#ffffff') * }) * ``` * * @public */ forEach(f: (rvStep: StoredRhineVar) => void): void; /** * 遍历所有选中场景中当前选中节点的属性并执行操作 * * @param f - 对每个节点执行的回调函数,接收节点的 RhineVar 对象 * * @throws 如果节点属性数据获取失败会抛出错误 * * @remarks * 该方法结合了场景批量选择和节点选择。它会遍历所有选中的场景, * 在每个场景中找到当前选中的节点(由 RsSelectionService 管理), * 然后对这些节点执行指定的操作。 * * 使用场景:当需要在多个场景中同时修改相同节点的属性时使用此方法。 * 例如:在多个场景中同时修改某个模型的颜色、位置等属性。 * * @example * ```typescript * // 在所有选中场景中,修改当前选中节点的可见性 * BatchApplyService.instance.forEachAttributes((rvNode) => { * rvNode.visible.set(false) * }) * * // 在所有选中场景中,修改当前选中节点的位置 * BatchApplyService.instance.forEachAttributes((rvNode) => { * rvNode.position.x.set(100) * rvNode.position.y.set(200) * }) * * // 在所有选中场景中,修改当前选中节点的材质颜色 * BatchApplyService.instance.forEachAttributes((rvNode) => { * rvNode.material.color.set('#ff0000') * }) * ``` * * @public */ forEachAttributes(f: (rvNode: StoredRhineVar) => void): void; } /** * 批量应用订阅者回调函数类型 * * @param selected - 当前选中的场景ID数组 * * @public */ export declare type BatchApplySubscriber = (selected: string[]) => void; export declare function Block(): JSX.Element; /** * @public */ export declare interface C3 { r: number; g: number; b: number; } /** * @public */ export declare interface C4 { r: number; g: number; b: number; a: number; } /** * @public */ export declare class CameraConfigurationAnimation { static get instance(): CameraConfigurationAnimation; private constructor(); play(data: CameraConfigurationData, duration?: number, quickMode?: boolean): void; distanceMin(value: number, duration?: number, quickMode?: boolean): void; distanceMax(value: number, duration?: number, quickMode?: boolean): void; fov(value: number, duration?: number, quickMode?: boolean): void; } /** * @public */ export declare class CameraLocationAnimation { static get instance(): CameraLocationAnimation; private constructor(); cameraAnimation: AnimationGroup | null; play(data: RvCameraLocation, duration?: number, enableNear?: boolean): void; playEasy(data: RvCameraLocation, duration: number): void; makeCameraAnimationsEase(data: RvCameraLocation, duration?: number): Animation_2[]; } declare function check(str: string): boolean; /** * 检查路径是否与目标列表中的任意路径重叠 * @param from - 要检查的路径 * @param targetList - 目标路径列表 * @returns 如果与任意目标路径重叠则返回 true */ declare function checkAnyRvPathOverlay(from: RvPath | string, targetList: (RvPath | string)[]): boolean; /** * 检查路径是否与目标列表中的任意路径完全相同 * @param from - 要检查的路径 * @param targetList - 目标路径列表 * @returns 如果与任意目标路径相同则返回 true */ declare function checkAnyRvPathSame(from: RvPath | string, targetList: (RvPath | string)[]): boolean; /** * @public */ export declare function CheckboxLine(): JSX.Element; /** * 检查两段路径是否完全重叠 * 长度可不同,从开头开始每一项比较,直到有一方结束,是否全部相同 * @param from - 第一个路径 * @param target - 第二个路径 * @returns 如果路径重叠则返回 true * @example * ```ts * RvUtils.checkRvPathOverlay("a.b", "a.b.c") // true * RvUtils.checkRvPathOverlay("a.b", "a.c") // false * ``` */ declare function checkRvPathOverlay(from: RvPath | string, target: RvPath | string): boolean; /** * 检查两段路径是否完全相同 * @param from - 第一个路径 * @param target - 第二个路径 * @returns 如果路径完全相同则返回 true * @example * ```ts * RvUtils.checkRvPathSame("a.b", "a.b") // true * RvUtils.checkRvPathSame("a.b", "a.b.c") // false * ``` */ declare function checkRvPathSame(from: RvPath | string, target: RvPath | string): boolean; declare function checkRvPathStartWith(from: RvPath | string, target: RvPath | string): boolean; declare function chunkHash(file: File): Promise; /** * 剪贴板工具集 * * 提供剪贴板读写操作,支持普通文本和节点列表的复制粘贴 * * @remarks * 节点列表使用特定格式 `` 存储在剪贴板中, * 便于在应用内识别和解析节点数据 * * @example * ```typescript * // 复制节点 * await ClipboardUtils.copyNodes(['node-1', 'node-2']) * * // 粘贴节点 * const nodes = await ClipboardUtils.getNodes() * ``` */ export declare const ClipboardUtils: { copy: typeof copy; copyNodes: typeof copyNodes; getText: typeof getText; getNodes: typeof getNodes; }; declare function computeSHA256(buffer: BufferSource): Promise; /** * @public */ export declare class ContextMenu { options: ContextMenuCreateOptions; id: string; lines: MenuLine[]; showIcon: boolean; x: number; y: number; closeOnOutsideClick: boolean; theme?: ThemeColor | undefined; controller: ContextMenuController | null; createTime: Date; constructor(options: ContextMenuCreateOptions, id: string, lines?: MenuLine[], showIcon?: boolean, x?: number, y?: number, closeOnOutsideClick?: boolean, theme?: ThemeColor | undefined, controller?: ContextMenuController | null, createTime?: Date); static fromOptions(id: string, options: ContextMenuCreateOptions, menuLines?: MenuLine[]): ContextMenu; } /** * @public */ export declare interface ContextMenuController { contextMenu: ContextMenu; show(): void; destroy(): void; } /** * @public */ export declare interface ContextMenuCreateOptions { id?: string; lines?: MenuLineCreateOptions[]; showIcon?: boolean; x?: number; y?: number; closeOnOutsideClick?: boolean; theme?: ThemeColor; onClose?: () => void; } /** * 右键菜单管理服务 * * @remarks * 该服务提供了一个集中管理系统,用于创建、显示和控制右键菜单。 * 采用单例模式,确保整个应用程序中只存在一个实例。 * * @public */ export declare class ContextMenuService { /** * 获取 ContextMenuService 的单例实例 * * @returns 单例实例 * * @public */ static get instance(): ContextMenuService; /** * 包含所有活动右键菜单的响应式数组 * * @remarks * 该数组使用 Valtio proxy 包装以实现响应式更新。 * 当右键菜单被添加或移除时,UI 将自动反映这些变化。 * * @public */ contextMenus: ContextMenu[]; /** * 创建一个新的右键菜单 * * @param options - 右键菜单的配置选项 * @returns 用于管理右键菜单生命周期的控制器对象 * * @remarks * 该方法使用指定的选项创建一个新的右键菜单。如果未提供 ID, * 将自动生成一个唯一的 ID。返回的控制器可用于显示或销毁菜单。 * * @example * ```typescript * const controller = ContextMenuService.instance.create({ * x: event.clientX, * y: event.clientY, * closeOnOutsideClick: true, * lines: [ * { * text: '删除', * icon: TrashIcon, * onClick: () => handleDelete() * } * ] * }) * controller.show() * ``` * * @public */ create(options: ContextMenuCreateOptions): ContextMenuController; /** * 根据 ID 获取右键菜单 * * @param id - 右键菜单的唯一 ID * @returns 如果找到则返回右键菜单实例,否则返回 undefined * * @example * ```typescript * const menu = ContextMenuService.instance.get('context-menu-0') * if (menu) { * console.log('Found menu at:', menu.x, menu.y) * } * ``` * * @public */ get(id: string): ContextMenu | undefined; /** * 关闭指定的右键菜单 * * @param contextMenu - 要关闭的右键菜单 ID 字符串或 ContextMenu 实例 * @returns 一个 Promise,如果菜单成功关闭则解析为 true,否则为 false * * @remarks * 该方法从活动菜单列表中移除右键菜单。如果未找到菜单或菜单当前未显示, * 则返回 false。 * * @example * ```typescript * // 通过 ID 关闭 * await ContextMenuService.instance.close('context-menu-0') * * // 通过实例关闭 * const menu = ContextMenuService.instance.get('context-menu-0') * if (menu) { * await ContextMenuService.instance.close(menu) * } * ``` * * @public */ close(contextMenu: string | ContextMenu): Promise; /** * 关闭所有活动的右键菜单 * * @returns 一个 Promise,解析为被关闭的菜单数量 * * @remarks * 该方法一次性从活动菜单列表中移除所有右键菜单。 * 适用于清理操作或需要重置菜单状态的场景。 * * @example * ```typescript * const closedCount = await ContextMenuService.instance.closeAll() * console.log(`Closed ${closedCount} menus`) * ``` * * @public */ closeAll(): Promise; } declare function convertBytesToHigherUnit(bn: number): string; declare function convertTimeText(seconds: number): string; /** * 复制文本到剪贴板 * * @param text - 要复制的文本内容 * @returns 复制完成的 Promise * @throws 当剪贴板 API 不可用或权限被拒绝时抛出异常 * * @example * ```typescript * await ClipboardUtils.copy('Hello World') * ``` */ declare function copy(text: string): Promise; declare function copyCurrentUrlToClipboard(): Promise; /** * 复制节点列表到剪贴板 * * 将节点 ID 列表格式化为 `` 格式并复制到剪贴板 * * @param nidList - 节点 ID 列表 * @returns 复制完成的 Promise * @throws 当剪贴板 API 不可用或权限被拒绝时抛出异常 * * @example * ```typescript * await ClipboardUtils.copyNodes(['node-1', 'node-2', 'node-3']) * // 剪贴板内容: * ``` */ declare function copyNodes(nidList: string[]): Promise; declare function copyText(text: string): Promise; /** * @public */ export declare class Counter { value: number; constructor(defaultValue?: number); add(): number; } /** * 创建属性右键菜单 * * @param mark * @param initialize * @param intl * @param defaultAttribute * @param defaultEnableMultiNode * @param defaultEnableBatchApply 是否默认启用 BatchApply, 如果为 undefined 则根据 defaultAttribute 判断, 若 defaultAttribute 为 undefined 则默认 false * * @public */ export declare function createAttributeContextMenu(mark: () => void, initialize: () => void, intl: Intl_2, defaultAttribute?: Attribute, defaultEnableMultiNode?: boolean, defaultEnableBatchApply?: boolean): { onContextMenu: (event: MouseEvent_2, label: string, paths: PathListWithOptionableAttribute | string, enableMultiNode?: boolean, enableBatchApply?: boolean) => void; }; /** * @public */ export declare const CryptoUtils: { computeSHA256: typeof computeSHA256; }; /** * @public */ export declare const DataUtils: { recursPathValue: typeof recursPathValue; }; declare function degreesToQuaternion(v: V3): Quaternion; declare function degreeToRadians(v: V3): V3; /** * 根据路径删除对象中的值 * @param source - 源对象 * @param path - 路径 * @example * ```ts * const obj = { a: { b: 1 } } * RvUtils.setByRvPath(obj, "a.b") // obj === { a: {} } * ``` */ declare function deleteByRvPath(source: StoredRhineVar, path: string | RvPath): void; /** * @public */ export declare class Dialog { options: DialogCreateOptions; id: string; title: string; titleIcon?: FunctionComponent | string | undefined; content: string; contentAlign: DialogContentAlign; contentView?: FunctionComponent | string | undefined; icon?: FunctionComponent | string | undefined; view?: FunctionComponent | string | undefined; theme: ThemeColor; leftMode: boolean; className: string; style: object; confirmText: string; cancelText: string; enableInput: boolean; defaultValue: string; inputPlaceholder: string; autoFocus: boolean; allowEmpty: boolean; onChange: (value: string) => void; onCheck: (value: string) => boolean; enableCloseButton: boolean; onConfirm: (value: string) => void; onCancel: () => void; onClose: () => void; onConfirmButtonClick: () => void; onCancelButtonClick: () => void; onOutsideClick: () => void; onCloseButtonClick: () => void; onRender: () => void; onEffect: () => () => void; closeOnConfirm: boolean; closeOnCancel: boolean; closeOnOutsideClick: boolean; closeOnCloseButtonClick: boolean; alignButton: boolean; inputValue: string; createTime: Date; focusInput: () => void; elements: Map; constructor(options: DialogCreateOptions, id: string, title?: string, titleIcon?: FunctionComponent | string | undefined, content?: string, contentAlign?: DialogContentAlign, contentView?: FunctionComponent | string | undefined, icon?: FunctionComponent | string | undefined, view?: FunctionComponent | string | undefined, theme?: ThemeColor, leftMode?: boolean, className?: string, style?: object, confirmText?: string, cancelText?: string, enableInput?: boolean, defaultValue?: string, inputPlaceholder?: string, autoFocus?: boolean, allowEmpty?: boolean, onChange?: (value: string) => void, onCheck?: (value: string) => boolean, enableCloseButton?: boolean, onConfirm?: (value: string) => void, onCancel?: () => void, onClose?: () => void, onConfirmButtonClick?: () => void, onCancelButtonClick?: () => void, onOutsideClick?: () => void, onCloseButtonClick?: () => void, onRender?: () => void, onEffect?: () => () => void, closeOnConfirm?: boolean, closeOnCancel?: boolean, closeOnOutsideClick?: boolean, closeOnCloseButtonClick?: boolean, alignButton?: boolean, inputValue?: string, createTime?: Date, focusInput?: () => void, elements?: Map); static fromOptions(id: string, options: DialogCreateOptions): Dialog; setHide: (value: boolean) => void; } /** * @public */ export declare enum DialogContentAlign { LEFT = "LEFT", CENTER = "CENTER", RIGHT = "RIGHT" } /** * @public */ export declare interface DialogCreateOptions { id?: string; title?: string; titleIcon?: FunctionComponent | string; content?: string; contentAlign?: DialogContentAlign; contentView?: FunctionComponent | string; icon?: FunctionComponent | string; view?: FunctionComponent | string; theme?: ThemeColor; leftMode?: boolean; className?: string; style?: object; confirmText?: string; cancelText?: string; enableCloseButton?: boolean; enableInput?: boolean; defaultValue?: string; inputPlaceholder?: string; autoFocus?: boolean; allowEmpty?: boolean; onChange?: (value: string) => void; onCheck?: (value: string) => boolean; onConfirm?: (value: string) => void; onCancel?: () => void; onClose?: () => void; onConfirmButtonClick?: () => void; onCancelButtonClick?: () => void; onOutsideClick?: () => void; onCloseButtonClick?: () => void; onRender?: () => void; onEffect?: () => () => void; closeOnConfirm?: boolean; closeOnCancel?: boolean; closeOnOutsideClick?: boolean; closeOnCloseButtonClick?: boolean; alignButton?: boolean; } /** * @public */ export declare interface DialogPlugin extends IconPlugin { options: DialogCreateOptions; view: MixView; onRender?: () => void; } /** * 对话框服务 * * @remarks * 用于管理应用中的所有对话框,提供创建、打开、关闭对话框的功能。 * 支持确认对话框和输入对话框两种常用类型。 * * @example * 创建确认对话框 * ```typescript * const result = await DialogService.instance.confirm({ * title: '删除确认', * content: '确定要删除这个文件吗?', * theme: ThemeColor.RED * }) * if (result) { * // 用户点击了确认 * } * ``` * * @example * 创建输入对话框 * ```typescript * const name = await DialogService.instance.input({ * title: '输入名称', * inputPlaceholder: '请输入文件名', * defaultValue: 'untitled' * }) * console.log('用户输入:', name) * ``` * * @public */ export declare class DialogService { /** * 获取 DialogService 的单例实例 * * @returns DialogService 实例 */ static get instance(): DialogService; private constructor(); /** * 创建一个自定义对话框 * * @remarks * 根据提供的配置创建对话框实例。如果未指定 ID,会自动生成唯一 ID。 * 可以通过 show 参数控制是否立即显示对话框。 * * @param options - 对话框配置选项 * @param show - 是否立即显示对话框,默认为 true * @returns 返回创建的 Dialog 实例 * * @example * ```typescript * const dialog = await DialogService.instance.create({ * title: '自定义对话框', * contentView: MyCustomComponent, * confirmText: '确定', * cancelText: '取消' * }) * ``` */ create(options: DialogCreateOptions, show?: boolean): Promise; /** * 当前所有对话框实例的数组 * * @remarks * 保存所有已创建的对话框实例,用于查询和管理 */ dialogs: Dialog[]; /** * 对话框渲染器实例 * * @remarks * 负责对话框的实际渲染和显示逻辑 */ renderer: DialogViewRenderer; /** * 创建确认对话框 * * @remarks * 显示一个带有确认和取消按钮的对话框,用户点击按钮后返回对应的布尔值。 * 适用于需要用户确认的操作场景,如删除、保存、提交等。 * * @param options - 确认对话框配置选项 * @param options.title - 对话框标题 * @param options.titleIcon - 标题图标,可以是 React 组件或字符串 * @param options.content - 对话框文本内容 * @param options.contentView - 自定义内容视图组件 * @param options.icon - 对话框图标 * @param options.theme - 主题颜色,默认为蓝色 * @param options.confirmText - 确认按钮文本,默认为 'Confirm' * @param options.cancelText - 取消按钮文本,默认为 'Cancel' * @param options.leftMode - 是否左对齐模式 * @param options.className - 自定义 CSS 类名 * @param options.style - 自定义样式对象 * @param options.onConfirm - 确认按钮点击回调 * @param options.onCancel - 取消按钮点击回调 * @param options.onClose - 对话框关闭回调 * @param options.closeOnOutsideClick - 是否允许点击外部关闭 * @param options.enableCloseButton - 是否显示关闭按钮,默认为 false * @param show - 是否立即显示对话框,默认为 true * @returns Promise,resolve 为 true 表示用户点击确认,false 表示取消 * * @example * ```typescript * const confirmed = await DialogService.instance.confirm({ * title: '删除文件', * content: '此操作不可恢复,确定要删除吗?', * theme: ThemeColor.RED, * confirmText: '删除', * cancelText: '取消' * }) * if (confirmed) { * // 执行删除操作 * } * ``` */ confirm(options: { title: string; titleIcon?: FunctionComponent | string; content?: string; contentView?: FunctionComponent | string; icon?: FunctionComponent | string; theme?: ThemeColor; confirmText?: string; cancelText?: string; leftMode?: boolean; className?: string; style?: object; onConfirm?: () => void; onCancel?: () => void; onClose?: () => void; closeOnOutsideClick?: boolean; enableCloseButton?: boolean; }, show?: boolean): Promise; /** * 创建输入对话框 * * @remarks * 显示一个带有输入框的对话框,用户可以输入文本内容。 * 支持默认值、占位符、输入验证等功能,适用于需要用户输入信息的场景。 * * @param options - 输入对话框配置选项 * @param options.title - 对话框标题 * @param options.titleIcon - 标题图标,可以是 React 组件或字符串 * @param options.content - 对话框文本内容 * @param options.contentView - 自定义内容视图组件 * @param options.icon - 对话框图标 * @param options.theme - 主题颜色,默认为蓝色 * @param options.leftMode - 是否左对齐模式 * @param options.className - 自定义 CSS 类名 * @param options.style - 自定义样式对象 * @param options.confirmText - 确认按钮文本,默认为 'Confirm' * @param options.cancelText - 取消按钮文本,默认为 'Cancel' * @param options.defaultValue - 输入框默认值 * @param options.inputPlaceholder - 输入框占位符文本 * @param options.autoFocus - 是否自动聚焦输入框 * @param options.allowEmpty - 是否允许空输入 * @param options.onChange - 输入内容变化回调 * @param options.onCheck - 输入验证函数,返回 true 表示验证通过 * @param options.onConfirm - 确认按钮点击回调,接收输入的值 * @param options.onCancel - 取消按钮点击回调 * @param options.onClose - 对话框关闭回调 * @param options.closeOnOutsideClick - 是否允许点击外部关闭 * @param options.enableCloseButton - 是否显示关闭按钮,默认为 false * @param show - 是否立即显示对话框,默认为 true * @returns Promise,resolve 为用户输入的字符串,取消时返回空字符串 * * @example * ```typescript * const name = await DialogService.instance.input({ * title: '重命名文件', * inputPlaceholder: '请输入新文件名', * defaultValue: 'myfile.txt', * onCheck: (value) => { * // 验证文件名格式 * return /^[a-zA-Z0-9._-]+$/.test(value) * } * }) * if (name) { * // 使用用户输入的名称 * console.log('新文件名:', name) * } * ``` */ input(options: { title: string; titleIcon?: FunctionComponent | string; content?: string; contentView?: FunctionComponent | string; icon?: FunctionComponent | string; theme?: ThemeColor; leftMode?: boolean; className?: string; style?: object; confirmText?: string; cancelText?: string; defaultValue?: string; inputPlaceholder?: string; autoFocus?: boolean; allowEmpty?: boolean; onChange?: (value: string) => void; onCheck?: (value: string) => boolean; onConfirm?: (value: string) => void; onCancel?: () => void; onClose?: () => void; closeOnOutsideClick?: boolean; enableCloseButton?: boolean; }, show?: boolean): Promise; /** * 根据 ID 获取对话框实例 * * @param id - 对话框的唯一标识符 * @returns 对话框实例,如果未找到则返回 undefined * * @example * ```typescript * const dialog = DialogService.instance.get('dialog-1') * if (dialog) { * console.log('找到对话框:', dialog.title) * } * ``` */ get(id: string): Dialog | undefined; /** * 打开对话框 * * @remarks * 显示指定的对话框。可以传入对话框实例或对话框 ID。 * 如果渲染器未加载或找不到指定的对话框,会抛出错误。 * * @param dialog - 对话框实例或对话框 ID * @returns Promise,resolve 为布尔值表示是否成功打开 * @throws 渲染器未加载时抛出 'Dialog renderer not loaded' * @throws 找不到指定对话框时抛出 'Failed to find dialog' * * @example * ```typescript * // 通过实例打开 * const dialog = await DialogService.instance.create(options, false) * await DialogService.instance.open(dialog) * * // 通过 ID 打开 * await DialogService.instance.open('dialog-1') * ``` */ open(dialog: Dialog | string): Promise; /** * 关闭对话框 * * @remarks * 关闭指定的对话框。可以传入对话框实例或对话框 ID。 * 如果渲染器未加载或找不到指定的对话框,会抛出错误。 * * @param dialog - 对话框实例或对话框 ID * @returns Promise,resolve 为布尔值表示是否成功关闭 * @throws 渲染器未加载时抛出 'Dialog renderer not loaded' * @throws 找不到指定对话框时抛出 'Failed to find dialog' * * @example * ```typescript * // 通过实例关闭 * await DialogService.instance.close(dialog) * * // 通过 ID 关闭 * await DialogService.instance.close('dialog-1') * ``` */ close(dialog: Dialog | string): Promise; /** * 关闭所有对话框 * * @remarks * 关闭当前所有打开的对话框。会依次关闭 dialogs 数组中的每个对话框。 * 如果渲染器未加载,会抛出错误。 * * @returns Promise,resolve 为成功关闭的对话框数量 * @throws 渲染器未加载时抛出 'Dialog renderer not loaded' * * @example * ```typescript * const closedCount = await DialogService.instance.closeAll() * console.log(`已关闭 ${closedCount} 个对话框`) * ``` */ closeAll(): Promise; } /** * @public */ export declare type DivProps = DetailedHTMLProps, HTMLDivElement>; /** * @public */ export declare type DivPropsSimple = Omit; /** * @public */ export declare class DomNotFoundError extends NotFoundError { constructor(message: string); } declare interface DragNodeInfo { nid: string; location: StoredRhineVar; initialPosition: V3; initialRotation?: V3; initialRotationQuaternion?: V4; initialScale: V3; } /** * @public */ export declare interface DrawerPlugin extends IconPlugin { title: string; tip: string; weight: number; drawer: MixView; onRender?: () => void; onTitleClick?: () => void; onTitleContextMenu?: () => void; } /** * @public */ export declare class EasyPropertyAnimation { static get instance(): EasyPropertyAnimation; private constructor(); animationMap: Map; }>; play(id: string, type: number, node: SupportAnimationTarget, keys: string[], to: number | Quaternion | Color3 | Color4 | Vector2 | Vector3, duration?: number, quickMode?: boolean, from?: number | Quaternion | Color3 | Color4 | Vector2 | Vector3, ease?: boolean): void; playSplit(id: string, callback: () => void, duration?: number, quickMode?: boolean): void; stop(id: string): boolean; } /** * @public */ export declare enum EnableLevel { NONE = "NONE", INSTALL = "INSTALL", ENABLE = "ENABLE", OPEN = "OPEN" } declare function ensureFileArray(files: File | File[] | FileList | null | undefined): File[]; /** * 确保路径为 RvPath 数组格式 * @param path - 字符串路径或 RvPath 数组 * @returns RvPath 数组 */ declare function ensureRvPath(path: string | RvPath): RvPath; /** * 确保路径为字符串格式 * @param path - 字符串路径或 RvPath 数组 * @returns 字符串路径 */ declare function ensureRvPathString(path: string | RvPath): string; declare function extractFilenameFromUrl(url: string, includeExtension?: boolean): string; declare function fetchBlobWithRetry(url: string, retries?: number): Promise; declare function fetchJsonWithRetry(url: string, retries?: number): Promise; /** * @public */ export declare interface FileData { fid: string; resourceId?: string; status: LocalDataStatus; name: string; progress: number; mime: string; filename?: string; extension?: string; description?: string; size?: string; preview?: string; } /** * @public */ export declare function FileProgressBar(props: FileProgressBarProps): JSX.Element; /** * @public */ export declare interface FileProgressBarProps extends DivProps { size: string; value: number; className?: string; theme?: string; } /** * @public */ export declare const FileUtils: { to3n: typeof to3n; convertBytesToHigherUnit: typeof convertBytesToHigherUnit; splitName: typeof splitName; ensureFileArray: typeof ensureFileArray; chunkHash: typeof chunkHash; isSameFile: typeof isSameFile; getFileInfo: typeof getFileInfo; }; /** * @public */ export declare class FirstLoadModelService { static get instance(): FirstLoadModelService; private constructor(); status: FirstLoadModelServiceStatus; rsModelList: RsModel[]; loadingNumber: number; loadedNumber: number; errorNumber: number; canceledNumber: number; totalSize: number; loadedSize: number; startTime: number; start(): void; subscribe(subscriber: FirstLoadModelServiceSubscriber): () => void; unsubscribe(subscriber: FirstLoadModelServiceSubscriber): void; } /** * @public */ export declare enum FirstLoadModelServiceEventType { START = "START", PROGRESS = "PROGRESS", LOADED = "LOADED", ERROR = "ERROR", CANCELED = "CANCELED" } /** * @public */ export declare enum FirstLoadModelServiceStatus { WAITING = "WAITING", LOADING = "LOADING", LOADED = "LOADED", ERROR = "ERROR", CANCELED = "CANCELED" } /** * @public */ export declare type FirstLoadModelServiceSubscriber = (type: FirstLoadModelServiceEventType) => void; /** * 首次加载服务 * * @remarks * 负责管理项目首次打开时所有文件的下载和加载过程。 * 该服务会在项目初始化时自动下载 RhineVarData.files 中定义的所有文件, * 并提供加载进度、状态监控和错误处理等功能。 * * 采用单例模式设计,通过 `FirstLoadService.instance` 访问唯一实例。 * * @example * ```typescript * // 启动首次加载 * FirstLoadService.instance.start() * * // 监听加载进度 * FirstLoadService.instance.subscribe((type) => { * if (type === FirstLoadServiceEventType.PROGRESS) { * console.log(`已加载: ${FirstLoadService.instance.loadedSize} / ${FirstLoadService.instance.totalSize}`) * } * }) * ``` * * @public */ export declare class FirstLoadService { /** * 获取 FirstLoadService 的单例实例 * * @returns FirstLoadService 的唯一实例 * * @public */ static get instance(): FirstLoadService; /** * 当前加载服务的状态 * * @remarks * 可能的状态值: * - WAITING: 等待开始 * - LOADING: 正在加载 * - LOADED: 加载完成 * - ERROR: 加载出错 * - CANCELED: 加载取消 * * @public */ status: FirstLoadServiceStatus; /** * 本地数据对象列表 * * @remarks * 包含所有正在加载或已加载的文件的本地数据对象, * 每个 LocalData 对象包含文件的 fid、状态、进度等信息。 * * @public */ localDataList: LocalData[]; /** * 当前正在加载中的文件数量 * * @remarks * 包括状态为 LOADING、WAITING 或 PAUSED 的文件 * * @public */ loadingNumber: number; /** * 已成功加载的文件数量 * * @public */ loadedNumber: number; /** * 加载失败的文件数量 * * @public */ errorNumber: number; /** * 已取消加载的文件数量 * * @public */ canceledNumber: number; /** * 需要加载的文件总大小(字节) * * @public */ totalSize: number; /** * 已加载的文件大小(字节) * * @remarks * 根据每个文件的下载进度计算得出,用于显示整体加载进度 * * @public */ loadedSize: number; /** * 开始加载的时间戳(毫秒) * * @remarks * 用于计算总加载耗时 * * @public */ startTime: number; /** * 开始加载所有文件 * * @remarks * 启动首次加载流程,会遍历 RvResourceService 缓存中的所有文件并开始下载。 * 该方法会: * 1. 检查是否有需要加载的文件 * 2. 跳过正在上传中的文件(uploading = true) * 3. 计算文件总大小 * 4. 调用 LocalDataService 加载每个文件 * 5. 监听加载进度和状态变化 * 6. 在所有文件加载完成或出错时触发相应事件 * * 如果加载过程中出现错误,会弹出对话框提示用户刷新页面重新加载。 * * @example * ```typescript * // 在项目初始化时启动文件加载 * FirstLoadService.instance.start() * ``` * * @public */ start(): void; /** * 订阅加载事件 * * @remarks * 注册一个回调函数来监听文件加载的各种事件: * - START: 开始加载 * - PROGRESS: 加载进度更新 * - LOADED: 所有文件加载完成 * - ERROR: 加载出错 * - CANCELED: 加载取消 * * @param subscriber - 事件回调函数 * @returns 取消订阅的函数,调用后将停止接收事件通知 * * @example * ```typescript * const unsubscribe = FirstLoadService.instance.subscribe((type) => { * if (type === FirstLoadServiceEventType.PROGRESS) { * console.log('Loading progress:', FirstLoadService.instance.loadedSize) * } else if (type === FirstLoadServiceEventType.LOADED) { * console.log('All files loaded!') * } * }) * * // 取消订阅 * unsubscribe() * ``` * * @public */ subscribe(subscriber: FirstLoadServiceSubscriber): () => void; /** * 取消订阅加载事件 * * @remarks * 从订阅者列表中移除指定的回调函数,移除后将不再接收事件通知 * * @param subscriber - 要取消订阅的回调函数 * * @public */ unsubscribe(subscriber: FirstLoadServiceSubscriber): void; } /** * @public */ export declare enum FirstLoadServiceEventType { START = "START", PROGRESS = "PROGRESS", LOADED = "LOADED", ERROR = "ERROR", CANCELED = "CANCELED" } /** * @public */ export declare enum FirstLoadServiceStatus { WAITING = "WAITING", LOADING = "LOADING", LOADED = "LOADED", ERROR = "ERROR", CANCELED = "CANCELED" } /** * @public */ export declare type FirstLoadServiceSubscriber = (type: FirstLoadServiceEventType) => void; /** * @public */ export declare function FlexGrow(props: { value?: number; }): JSX.Element; /** * @public */ export declare interface FlexGrowProps { value?: number; } /** * @public */ export declare enum FocusMode { DEFAULT = "DEFAULT", DESCRIPTION = "DESCRIPTION" } /** * @public */ export declare class FogAnimation { static get instance(): FogAnimation; private constructor(); play(data: FogData, duration?: number, quickMode?: boolean): void; enableAndDensity(enable: boolean, value: number, duration?: number, quickMode?: boolean): void; color(color: Color3 | string, duration?: number, quickMode?: boolean): void; } declare function formatDateTo17Digits(date?: Date): string; declare function formatDuration(startTimestamp: number, endTimestamp: number): string; declare function fromQuaternion(q: Quaternion): V4; declare function fromVector3(v: Vector3): V3; /** * @public */ export declare function getBlockDiagonalLength(x1: number, y1: number, z1: number, x2: number, y2: number, z2: number): number; /** * 根据路径从对象中获取值 * @typeParam T - 返回值的类型 * @param source - 源对象 * @param path - 访问路径 * @returns 路径对应的值,如果路径不存在则返回 undefined * @example * ```ts * RvUtils.getByRvPath({ a: { b: 1 } }, "a.b") // 1 * ``` */ declare function getByRvPath(source: StoredRhineVar | object, path: string | RvPath): T | undefined; declare function getDistance(x1: number, y1: number, x2: number, y2: number): number; declare function getDistance3d(x1: number, y1: number, z1: number, x2: number, y2: number, z2: number): number; declare function getDistanceBetweenEvents(e1: ReactEvent | NativeEvent, e2: ReactEvent | NativeEvent): number; declare function getEventPosition(e: ReactEvent | NativeEvent): [x: number, y: number]; declare function getExtension(mime?: string): Promise; declare function getFileInfo(url: string): Promise<{ name: string; size: number; }>; declare function getHashParam(name: string): string; declare function getMime(input?: File | Blob | string | ArrayBuffer | Uint8Array | AnyWebByteStream | BaseTexture | Material): Promise; declare function getMimeByBlob(object?: File | Blob): Promise; declare function getMimeByBuffer(buffer?: ArrayBuffer | Uint8Array): Promise; declare function getMimeByPath(path?: string): Promise; declare function getMimeByStream(stream: AnyWebByteStream): Promise; declare function getMimeByUrl(url?: string): Promise; /** * @public */ export declare function getNearestAngle(source: number, target: number): number; /** * @public */ export declare function getNearestAngleVector3(source: Vector3, target: Vector3): Vector3; declare function getNearestNumberIndex(x: number, list: number[]): number; /** * 获取剪贴板中的节点列表 * * 解析剪贴板中 `` 格式的文本,提取节点 ID 列表 * * @returns 节点 ID 列表,格式不符合时返回空数组 * @throws 当剪贴板 API 不可用或权限被拒绝时抛出异常 * * @example * ```typescript * // 假设剪贴板内容为: * const nodes = await ClipboardUtils.getNodes() * console.log(nodes) // ['node-1', 'node-2', 'node-3'] * * // 假设剪贴板内容为普通文本 * const nodes = await ClipboardUtils.getNodes() * console.log(nodes) // [] * ``` */ declare function getNodes(): Promise; declare function getPageTypeBySpaceText(space: string): PageType; declare function getParam(name: string): string; /** * @public */ export declare function getPointDistance(p1: Vector3, p2: Vector3): number; declare function getSearchParams(key: string): string | undefined; /** * 获取剪贴板中的文本 * * @returns 剪贴板中的文本内容 * @throws 当剪贴板 API 不可用或权限被拒绝时抛出异常 * * @example * ```typescript * const text = await ClipboardUtils.getText() * console.log(text) * ``` */ declare function getText(): Promise; /** * @public */ export declare abstract class GlobalAttribute extends BaseAttribute { type: AttributeType; generate(): T; initialize(): void; isInitialized(): boolean; mark(path: string | RvPath): void; get(): RecursiveCrossRhineVar | undefined; /** * 获取局部数据 * @param paths */ getPartial(paths: (string | RvPath)[]): PartialData; set(path: string | RvPath, value: unknown): void; /** * 设置局部数据 * @param pd */ setPartial(pd: PartialData): void; read(): T | RecursiveCrossRhineVar; /** * 读取局部数据 * @param paths */ readPartial(paths: (string | RvPath)[]): PartialData; edit(path: string | RvPath, value: unknown): void; /** * 编辑局部数据 * @param pd */ editPartial(pd: PartialData): void; subscribe(subscriber: GlobalAttributeSubscriber): () => void; unsubscribe(subscriber: GlobalAttributeSubscriber): void; } /** * @public */ export declare type GlobalAttributeSubscriber = (type: EventType, path: RvPath, value: unknown, oldValue: unknown) => void; /** * @public */ export declare class GroundAnimation { static get instance(): GroundAnimation; private constructor(); play(data: RvEnvironment['ground'], duration?: number, quickMode?: boolean): void; opacityRate(value: number, duration?: number, quickMode?: boolean): void; baseColor(color: Color3 | string, duration?: number, quickMode?: boolean): void; enableOnViewerMode(value: boolean, duration?: number, quickMode?: boolean): void; enableOnEditorMode(value: boolean, duration?: number, quickMode?: boolean): void; } /** * @public */ export declare function hasGeometry(mesh: AbstractMesh): boolean; /** * @public */ export declare interface HighLightInfo { uid: number; color: string; } /** * @public */ export declare class HistoryService { static get instance(): HistoryService; private constructor(); operate: string; stateList: unknown[]; undo(from?: string): void; redo(from?: string): void; canUndo(): boolean; canRedo(): boolean; pushState(state: unknown): void; mark(operate: string, forceStop?: boolean): void; markAttribute(attributePath: string | RvPath, path: string | RvPath, sidList?: string[], nidList?: string[]): void; stop(): void; clear(): void; removeLast(operate?: string): boolean; removeFirst(operate?: string): boolean; clearUndoStack(): void; clearRedoStack(): void; subscribe(subscriber: HistoryServiceSubscriber): () => void; unsubscribe(subscriber: HistoryServiceSubscriber): void; subscribeState(subscriber: HistoryServiceStateSubscriber): () => void; unsubscribeState(subscriber: HistoryServiceStateSubscriber): void; white(): void; } /** * @public */ export declare enum HistoryServiceEventType { 'UNDO' = "UNDO", 'REDO' = "REDO" } /** * @public */ export declare type HistoryServiceStateSubscriber = (state: unknown) => void; /** * @public */ export declare type HistoryServiceSubscriber = (type: HistoryServiceEventType, operate: string) => void; /** * @public */ export declare interface IconPlugin extends BasePlugin { position: IconPluginPosition; group: string; label: string; theme: ThemeColor; open: boolean; icon: MixView; onEnabledChange?: (value: boolean, e: MouseEvent) => void; onIconClick?: (e: MouseEvent) => void; onIconClickRouter?: (e: MouseEvent) => string; onIconContextMenu?: (e: MouseEvent) => void; } /** * @public */ export declare enum IconPluginPosition { TOP = 0, RIGHT = 1, BOTTOM = 2, LEFT = 3, TOP_LEFT = 4, BOTTOM_LEFT = 5, TOP_RIGHT = 6, BOTTOM_RIGHT = 7, UNKNOWN = 8 } /** * @public */ export declare interface IconViewProps extends DivProps { plugin: IconPlugin; } /** * @public */ export declare function InternationalizationProvider(props: InternationalizationProviderProps): JSX.Element; /** * @public */ export declare interface InternationalizationProviderProps { children?: ReactNode; } /** * @public */ export declare class InternationalizationService { static get instance(): InternationalizationService; private constructor(); ALL_SUPPORT: Locale[]; DEFAULT_SUPPORT: Locale; locale: Locale; messages: MessageTree; load(messages: MessageTree, namespace?: string): boolean; createIntl(namespace?: string): Intl_2; hasIntlCached(namespace?: string): boolean; deleteIntlCached(namespace?: string): boolean; clearIntlCached(namespace?: string): void; createIntlWithWait(namespace?: string): Promise; subscribe(subscriber: NamespaceSubscriber): () => void; unsubscribe(subscriber: NamespaceSubscriber): void; wait(namespace: string): Promise; } /** * @public */ declare type Intl_2 = (strings: TemplateStringsArray, ...values: unknown[]) => string; export { Intl_2 as Intl } /** * @public */ export declare function isAbstractMesh(node: Node_2): node is Mesh | AbstractMesh; declare function isAttach(mime?: string): boolean; declare function isBabylon(mime?: string): boolean; declare function isChangeEventType(type: EventType | string): boolean; /** * @public */ export declare function isEqualColor3(c1: Color3, c2: Color3): boolean; /** * @public */ export declare function isEqualColor3AndHex(c: Color3, hex: string): boolean; /** * @public */ export declare function isEqualColor4(c1: Color4, c2: Color4): boolean; declare function isFiniteVector(v: V3): boolean; declare function isMaterial(mime?: string): boolean; /** * @public */ export declare function isMesh(node: Node_2): node is Mesh; /** * 判断两个文件是否相同 * * @param file - 目标文件 * @param name - 另一个文件的名称 * @param size - 另一个文件的大小 * @param hash - 另一个文件的哈希 (可选) (通过上方 chunkHash 函数计算得出) * * @returns 是否相同 */ declare function isSameFile(file: File, name: string, size: number, hash?: string): Promise; declare function isSupport(mime?: string): boolean; declare function isSupportAudio(mime?: string): boolean; declare function isSupportFile(mime?: string): boolean; declare function isSupportImage(mime?: string): boolean; declare function isSupportJson(mime?: string): boolean; declare function isSupportModel(mime?: string): boolean; declare function isSupportRender(mime?: string): boolean; declare function isSupportText(mime?: string): boolean; declare function isSupportTexture(mime?: string): boolean; declare function isSupportVideo(mime?: string): boolean; declare function isTexture(mime?: string): boolean; declare function isUV(mime?: string): boolean; declare function isValidNumber(value: unknown): value is number; /** * @public */ export declare function joinPath(...args: (string | URL | JoinPathOptions)[]): string; /** * 一律用正斜杠(/)的智能路径拼接(URL 或 文件路径)。 * * 设计要点 * - 传入任意数量的段,顺序拼接 * - 自动识别 URL(含 protocol-relative 的 //host)与 file:// * - 文件路径(POSIX/Windows/UNC/驱动器号)统一输出为正斜杠 * - 规范化重复斜杠、"."、".." * - 末尾斜杠可选(默认不保留) * - ?query 与 #hash 以最后一个非空段为准(URL 模式才生效) * */ declare interface JoinPathOptions { /** 是否保留末尾斜杠(默认 false) */ keepTrailingSlash?: boolean; /** 强制作为 URL 处理(默认自动识别) */ treatAsUrl?: boolean; } /** * 合并两个RvPath * * @param pathA * @param pathB */ declare function joinRvPath(pathA: string | RvPath, pathB: string | RvPath): RvKey[]; /** * 合并两个RvPath 返回字符串 * * @param pathA * @param pathB */ declare function joinRvPathString(pathA: string | RvPath, pathB: string | RvPath): string; /** * @public */ export declare class LabelInfo { nid: string; node: TransformNode | null; text: string; theme: LabelTheme; x: number; y: number; parentElement: HTMLDivElement | null; pointElement: HTMLDivElement | null; lineElement: HTMLDivElement | null; blockElement: HTMLDivElement | null; textElement: HTMLDivElement | null; validate: boolean; always: boolean; show: boolean; lastClickTime: number; lastSp: Vector3 | null; constructor(nid: string, node?: TransformNode | null, text?: string, theme?: LabelTheme, x?: number, y?: number); } /** * @public */ export declare enum LabelTheme { Default = "Default" } /** * @public */ export declare type LastSubscriber = (value: RsSelectionNodeInfo | null) => void; /** * @public */ export declare class LightAnimation { static get instance(): LightAnimation; private constructor(); play(data: LightAnimationData, duration?: number, quickMode?: boolean): void; intensity(value: number, duration?: number, quickMode?: boolean): void; diffuseColor(color: Color3 | string, duration?: number, quickMode?: boolean): void; specularColor(color: Color3 | string, duration?: number, quickMode?: boolean): void; } /** * 定义光照动画数据接口 * @public */ declare interface LightAnimationData { intensity?: number; diffuseColor?: Color3 | string; specularColor?: Color3 | string; } /** * @public */ export declare interface LocalData { fid: string; type: LocalDataType; mime: string; status: LocalDataStatus; progress: number; url?: string; blob?: Blob; text?: string; json?: unknown; texture?: BaseTexture; material?: Material; uv?: unknown; object?: unknown; } /** * 本地数据服务 * * 负责管理所有本地数据,包括文件和一些模型内部的派生对象。 * 监听 RhineVar 文件系统的变化,实时加载文件到本地。 * 提供文件的加载、删除、状态管理和订阅功能。 * * @public * @example * ```typescript * // 获取服务实例 * const localDataService = LocalDataService.instance * * // 加载文件 * await localDataService.load(fid, url, mime) * * // 订阅文件加载事件 * localDataService.afterLoaded(fid, (localData) => { * console.log('文件已加载:', localData) * }) * ``` */ export declare class LocalDataService { /** * 获取 LocalDataService 单例实例 * * @returns LocalDataService 实例 * @public */ static get instance(): LocalDataService; private constructor(); /** * 本地数据文件存储 Map * * 键为文件ID(fid),值为本地数据对象(LocalData) * * @public */ files: Map; /** * 根据文件ID获取本地数据 * * @param fid - 文件ID * @returns 本地数据对象,如果不存在则返回 undefined * @public */ get(fid: string): LocalData | undefined; /** * 检查是否存在指定的本地数据 * * @param fid - 文件ID * @returns 如果存在返回 true,否则返回 false * @public */ has(fid: string): boolean; /** * 添加本地数据 * * 如果指定的文件ID已存在,则返回已存在的本地数据。 * 否则创建新的本地数据对象,并发布 ADD 和 LOADED 事件。 * * @param option - 添加本地数据的选项 * @returns 本地数据对象 * @public */ add(option: AddLocalDataOption): LocalData; /** * 将已有的本地数据重映射到新的文件 ID * * 上传文件时使用临时 ID 存储,上传完成后需要替换为后端返回的真实 fileId, * 以确保刷新页面后仍能通过真实 fileId 找到数据。 * * @param oldFid - 旧的临时文件 ID * @param newFid - 新的真实文件 ID * @returns 是否成功重映射 * @public */ remap(oldFid: string, newFid: string): boolean; /** * 加载一个文件到本地 * * 通过 fileId 从后端获取签名下载 URL,然后下载文件到本地。 * 支持下载进度跟踪,下载完成后会自动处理文件内容(JSON、文本等)。 * * @param fileId - 后端文件 ID * @param mime - 文件 MIME 类型,默认为 UNKNOWN * @returns Promise - 返回本地数据对象的 Promise * @public */ load(fileId: string, mime?: string): Promise; /** * 通过 File 对象加载文件到本地 * * 直接使用浏览器 File 对象创建本地数据,适用于用户上传文件的场景。 * 加载完成后会自动处理文件内容(JSON、文本等)。 * * @param fid - 文件ID * @param file - 浏览器 File 对象 * @param mime - 文件 MIME 类型,默认为 UNKNOWN * @returns Promise - 返回本地数据对象的 Promise * @public */ loadByFile(fid: string, file: File, mime?: string): Promise; /** * 处理文件加载完成后的操作 * * 根据文件 MIME 类型自动解析文件内容: * - 如果是 JSON 文件,解析为 JSON 对象并存储到 localData.json * - 如果是文本文件,读取为文本字符串并存储到 localData.text * * @param localData - 本地数据对象 * @returns Promise - 是否成功处理 * @public */ processAfterLoad(localData: LocalData): Promise; /** * 移除指定的本地数据 * * 从本地数据 Map 中删除指定的文件数据,并发布 REMOVE 事件。 * * @param fid - 文件ID * @returns 如果成功移除返回 true,如果文件不存在返回 false * @public */ remove(fid: string): boolean; /** * 将本地数据转换为浏览器可用的 Blob URL,用于在浏览器中显示或下载文件。 * 如果数据类型是 BLOB,则创建 Blob URL;如果是 OBJECT,则创建 MediaSource URL。 * * @param fid - 文件ID * @returns Blob URL 字符串,如果文件不存在或未加载完成则返回空字符串 * @public */ getLocalUrl(fid: string): string; /** * 释放本地文件的 Blob URL * * 释放之前通过 getLocalUrl 创建的 Blob URL,避免内存泄漏。 * * @param fid - 文件ID * @returns 如果成功释放返回 true,如果文件不存在或没有 URL 返回 false * @public */ releaseLocalUrl(fid: string): boolean; /** * 订阅所有本地数据的事件 * * 订阅所有文件的加载、进度、错误等事件。 * 每当任何文件发生事件时,订阅回调函数都会被调用。 * * @param subscriber - 订阅回调函数 * @returns 取消订阅的函数 * @public * @example * ```typescript * const unsubscribe = LocalDataService.instance.subscribe((type, localData) => { * console.log('事件类型:', type) * console.log('本地数据:', localData) * }) * * // 取消订阅 * unsubscribe() * ``` */ subscribe(subscriber: LocalDataServiceSubscriber): () => void; /** * 取消订阅所有本地数据的事件 * * @param subscriber - 要取消的订阅回调函数 * @public */ unsubscribe(subscriber: LocalDataServiceSubscriber): void; /** * 订阅单个文件的事件 * * 只订阅指定文件ID的事件,不会接收其他文件的事件通知。 * * @param fid - 文件ID * @param subscriber - 订阅回调函数 * @returns 取消订阅的函数 * @public * @example * ```typescript * const unsubscribe = LocalDataService.instance.subscribeSingle(fid, (type, localData) => { * if (type === LocalDataServiceEventType.LOADED) { * console.log('文件加载完成:', localData) * } * }) * * // 取消订阅 * unsubscribe() * ``` */ subscribeSingle(fid: string, subscriber: LocalDataServiceSubscriber): () => void; /** * 取消订阅单个文件的事件 * * @param fid - 文件ID * @param subscriber - 要取消的订阅回调函数 * @public */ unsubscribeSingle(fid: string, subscriber: LocalDataServiceSubscriber): void; /** * 文件加载完成后执行回调 * * 如果文件已加载完成,立即执行回调;否则订阅 LOADED 事件,触发后自动取消订阅。 * * @param fid - 文件 ID * @param subscriber - 加载完成后的回调函数 * @public */ afterLoaded(fid: string, subscriber: (localData: LocalData) => void): void; /** * 等待文件加载完成 * * 返回一个 Promise,在文件加载完成时 resolve。 * * @param fid - 文件 ID * @returns 加载完成的本地数据对象 * @public */ waitLoaded(fid: string): Promise; /** * 检查文件是否已加载完成 * * @param fid - 文件 ID * @returns true 已加载,false 未加载,undefined 文件不存在 * @public */ isLoaded(fid: string): boolean | undefined; } /** * @public */ export declare enum LocalDataServiceEventType { ADD = "ADD", REMOVE = "REMOVE", START = "START", PROGRESS = "PROGRESS", PAUSE = "PAUSE", RESUME = "RESUME", LOADED = "LOADED", ERROR = "ERROR", CANCELED = "CANCELED" } /** * @public */ export declare type LocalDataServiceSubscriber = (type: LocalDataServiceEventType, LocalData: LocalData) => void; /** * @public */ export declare enum LocalDataStatus { WAITING = "WAITING", LOADING = "LOADING", PAUSED = "PAUSED", LOADED = "LOADED", FAILED = "FAILED", CANCELED = "CANCELED" } /** * @public */ export declare enum LocalDataType { BLOB = "BLOB", OBJECT = "OBJECT" } /** * @public */ export declare enum Locale { ZH = "zh", EN = "en" } /** * @public */ export declare function MainPortal(props: MainPortalProps): ReactPortal; /** * @public */ export declare interface MainPortalProps { children: ReactNode; } /** * 将字符串路径转换为 RvPath 数组 * @param path - 以点分隔的路径字符串,如 "a.0.b" * @returns RvPath 数组,数字字符串会被转换为数字类型 * @example * RvUtils.makeRvPath("a.0.b") // ['a', 0, 'b'] */ declare function makeRvPath(path: string): RvPath; /** * 将 RvPath 数组转换为字符串路径 * @param path - RvPath 数组 * @returns 以点分隔的路径字符串 * @example * RvUtils.makeRvPathString(['a', 0, 'b']) // "a.0.b" */ declare function makeRvPathString(path: RvPath): string; export declare class MaterialNodeAttribute extends NodeAttribute { path: string[]; defaultValue: RvMaterialNode; multiInitialize(nidList?: string[]): void; } export declare class MaterialPbrAttribute extends NodeAttribute { path: string[]; defaultValue: RvMaterialPBR; multiInitialize(nidList?: string[]): void; generate(sid?: string, nid?: string): RvMaterialPBR; } /** * @public */ export declare function MaterialSymbol(props: MaterialSymbolProps): JSX.Element; /** * @public */ export declare function materialSymbol(icon: string, options?: MaterialSymbolOptions): FunctionComponent>; /** * @public */ export declare type MaterialSymbolFunction = (icon: string, options?: MaterialSymbolOptions) => FunctionComponent; /** * @public */ export declare interface MaterialSymbolOptions { fill?: boolean; size?: string; color?: string; className?: string; style?: React_2.CSSProperties; } /** * @public */ export declare interface MaterialSymbolProps extends SpanProps { size?: string; color?: string; className?: string; fill?: boolean; } /** * @public */ export declare const MathUtils: { toDegrees: typeof toDegrees; toRadians: typeof toRadians; approximatelyEqual: typeof approximatelyEqual; getDistance: typeof getDistance; getDistance3d: typeof getDistance3d; getNearestNumberIndex: typeof getNearestNumberIndex; }; /** * @public */ export declare class MeetingService { static get instance(): MeetingService; private constructor(); static PRESENTER_UPDATE_INTERVAL: number; static VISITOR_ANIMATION_DURATION: number; static CLICK_STORAGE_TIME: number; static CLICK_STORAGE_NUMBER: number; static CLICK_ANIMATION_DURATION: number; static CLICK_ALLOW_DELAY: number; state: MeetingState; setActiveMeeting(meetingId?: string): void; getActiveRvMeeting(): StoredRhineVar | null; readonly IN_MEETING_STATUS: MeetingStatus[]; inMeeting(): boolean; isPresenter(): boolean; isVisitor(): boolean; isFollowingVisitor(): boolean; isUnfollowingVisitor(): boolean; subscribe(subscriber: MeetingStateSubscriber): () => void; unsubscribe(subscriber: MeetingStateSubscriber): void; getInvitationLink(): string; } /** * @public */ export declare interface MeetingState { meetingId: string; presenterId: number; status: MeetingStatus; startTime: number; peopleCount: number; forceFollow: boolean; clickShareMode: ShareMode; cursorShareMode: ShareMode; selfFollow: boolean; } /** * @public */ export declare type MeetingStateSubscriber = (state: MeetingState) => void; /** * @public */ export declare enum MeetingStatus { PENDING = "PENDING", PROGRESSING = "PROGRESSING", ENDED = "ENDED", CANCELED = "CANCELED", BANNED = "BANNED" } /** * @public */ export declare class MenuLine { options: MenuLineCreateOptions; id: string; type: MenuLineType; text: string; tip: string; icon?: FunctionComponent | undefined; view?: FunctionComponent | undefined; color: string; disabled: boolean; shortcut: string; onClick: (e: MouseEvent_2) => void; onMouseOver: (e: MouseEvent_2) => void; onMouseOut: (e: MouseEvent_2) => void; closeAllOnClick: boolean; checkboxDefaultValue: boolean; onCheckboxChange: (value: boolean) => void; sub?: ContextMenuCreateOptions | undefined; createTime: Date; constructor(options: MenuLineCreateOptions, id: string, type?: MenuLineType, text?: string, tip?: string, icon?: FunctionComponent | undefined, view?: FunctionComponent | undefined, color?: string, disabled?: boolean, shortcut?: string, onClick?: (e: MouseEvent_2) => void, onMouseOver?: (e: MouseEvent_2) => void, onMouseOut?: (e: MouseEvent_2) => void, closeAllOnClick?: boolean, checkboxDefaultValue?: boolean, onCheckboxChange?: (value: boolean) => void, sub?: ContextMenuCreateOptions | undefined, // 子菜单项 createTime?: Date); static fromOptions(id: string, options: MenuLineCreateOptions): MenuLine; } /** * @public */ export declare interface MenuLineCreateOptions { id?: string; type?: MenuLineType; text?: string; tip?: string; icon?: FunctionComponent; view?: FunctionComponent; color?: string; disabled?: boolean; shortcut?: string; onClick?: (e: MouseEvent_2) => void; onMouseOver?: (e: MouseEvent_2) => void; onMouseOut?: (e: MouseEvent_2) => void; closeAllOnClick?: boolean; checkboxDefaultValue?: boolean; onCheckboxChange?: (value: boolean) => void; sub?: ContextMenuCreateOptions; } /** * @public */ export declare enum MenuLineType { BUTTON = "BUTTON",// 单个点击用按钮 DIVIDER = "DIVIDER",// 分割线 CHECKBOX = "CHECKBOX",// 单个可选中复选框 SUB = "SUB",// 二级菜单 VIEW = "VIEW" } /** * @public */ export declare class Message { text: string; type: MessageType; duration: number; id: number; show: boolean; height: number; opacity: number; constructor(text: string, type: MessageType, duration: number, id: number); } /** * @public */ export declare type MessageLeaf = string; /** * @public */ export declare type MessageLoader = (locale: Locale) => Promise; /** * @public */ export declare class MessageService { static get instance(): MessageService; private constructor(); messages: Message[]; info(text: string, translateNamespace?: string, duration?: number): void; success(text: string, translateNamespace?: string, duration?: number): void; warning(text: string, translateNamespace?: string, duration?: number): void; error(text: string, translateNamespace?: string, duration?: number): void; showWithTranslate(text: string, type: MessageType, translateNamespace?: string, duration?: number): Promise; show(text: string, type: MessageType, duration?: number): Promise; } /** * @public */ export declare type MessageState = 'before' | 'show' | 'after'; /** * @public */ export declare interface MessageTree { [key: string]: MessageTree | MessageLeaf; } /** * @public */ export declare type MessageType = 'info' | 'warning' | 'error' | 'success'; /** * 多属性的混合局部数据类。用于表示属性中的一部分数据,存储path和value的元素列表。 * * @public */ export declare class MixPartialData { data: Set; constructor(data?: [Attribute, string | RvPath, unknown][]); push(attribute: Attribute, path: string | RvPath, value: unknown): void; forEach(callback: (attribute: Attribute, path: RvPath, value: unknown) => void): void; forEachWithStringPath(callback: (attribute: Attribute, path: string, value: unknown) => void): void; toPartialData(): PartialData; get size(): number; } /** * @public */ export declare interface MixPartialDataItem { attribute: Attribute; path: RvPath; value: unknown; } /** * @public */ export declare type MixView = string | FunctionComponent; /** * @public */ export declare type NamespaceSubscriber = (namespaces: string[]) => void; /** * @public */ export declare type NativeAnyEventSubscriber = (e: Event | null) => void; /** * @public */ export declare type NativeDragEventSubscriber = (e: DragEvent) => void; declare type NativeEvent = MouseEvent | DragEvent | TouchEvent | WheelEvent; /** * @public */ export declare class NativeEventService { static get instance(): NativeEventService; PLAYER_ID: string; CANVAS_ID: string; private constructor(); subscribeClick(subscriber: NativeMouseEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeClick(subscriber: NativeMouseEventSubscriber): void; subscribeContextMenu(subscriber: NativeMouseEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeContextMenu(subscriber: NativeMouseEventSubscriber): void; subscribeDoubleClick(subscriber: NativeMouseEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeDoubleClick(subscriber: NativeMouseEventSubscriber): void; subscribeDrag(subscriber: NativeDragEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeDrag(subscriber: NativeDragEventSubscriber): void; subscribeDrop(subscriber: NativeDragEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeDrop(subscriber: NativeDragEventSubscriber): void; subscribeWheel(subscriber: NativeWheelEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeWheel(subscriber: NativeWheelEventSubscriber): void; subscribePointerDown(subscriber: NativePointerEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribePointerDown(subscriber: NativePointerEventSubscriber): void; subscribePointerMove(subscriber: NativePointerEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribePointerMove(subscriber: NativePointerEventSubscriber): void; subscribePointerUp(subscriber: NativePointerEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribePointerUp(subscriber: NativePointerEventSubscriber): void; subscribePointerCancel(subscriber: NativePointerEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribePointerCancel(subscriber: NativePointerEventSubscriber): void; subscribePointerEnter(subscriber: NativePointerEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribePointerEnter(subscriber: NativePointerEventSubscriber): void; subscribePointerLeave(subscriber: NativePointerEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribePointerLeave(subscriber: NativePointerEventSubscriber): void; subscribeKeyDown(subscriber: NativeKeyboardEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeKeyDown(subscriber: NativeKeyboardEventSubscriber): void; subscribeKeyUp(subscriber: NativeKeyboardEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeKeyUp(subscriber: NativeKeyboardEventSubscriber): void; subscribeKeyDownExceptInput(subscriber: NativeKeyboardEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeKeyDownExceptInput(subscriber: NativeKeyboardEventSubscriber): void; subscribeKeyUpExceptInput(subscriber: NativeKeyboardEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeKeyUpExceptInput(subscriber: NativeKeyboardEventSubscriber): void; subscribeFocus(subscriber: NativeFocusEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeFocus(subscriber: NativeFocusEventSubscriber): void; subscribeBlur(subscriber: NativeFocusEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeBlur(subscriber: NativeFocusEventSubscriber): void; subscribeScroll(subscriber: NativeUIEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeScroll(subscriber: NativeUIEventSubscriber): void; subscribeResize(subscriber: NativeAnyEventSubscriber, option?: NativeEventSubscribeOption): () => void; unsubscribeResize(subscriber: NativeAnyEventSubscriber): void; } /** * @public */ export declare interface NativeEventSubscribeOption { canvasOnly?: boolean; once?: boolean; capture?: boolean; } /** * @public */ export declare const NativeEventUtils: { getEventPosition: typeof getEventPosition; getDistanceBetweenEvents: typeof getDistanceBetweenEvents; preventDefaultListener: typeof preventDefaultListener; stopPropagationListener: typeof stopPropagationListener; preventDefaultStopPropagationListener: typeof preventDefaultStopPropagationListener; }; /** * @public */ export declare type NativeFocusEventSubscriber = (e: FocusEvent) => void; /** * @public */ export declare type NativeKeyboardEventSubscriber = (e: KeyboardEvent) => void; /** * @public */ export declare type NativeMouseEventSubscriber = (e: MouseEvent) => void; /** * @public */ export declare type NativePointerEventSubscriber = (e: PointerEvent) => void; /** * @public */ export declare type NativeUIEventSubscriber = (e: UIEvent) => void; /** * @public */ export declare type NativeWheelEventSubscriber = (e: WheelEvent) => void; /** * @public */ export declare const NetworkUtils: { fetchJsonWithRetry: typeof fetchJsonWithRetry; fetchBlobWithRetry: typeof fetchBlobWithRetry; }; /** * @public */ export declare abstract class NodeAttribute extends BaseAttribute { type: AttributeType; get targetSid(): string; get targetSidList(): string[]; get targetNid(): string; get targetNidList(): string[]; generate(sid?: string, nid?: string): T; multiGenerate(sidList?: string[], nidList?: string[]): Map>; readonly sameGenerateForStepsMode = true; readonly sameGenerateForNodesMode = false; initialize(nid?: string): void; isInitialized(nid?: string): boolean; multiInitialize(nidList?: string[]): void; isAllInitialized(nidList?: string[]): boolean; mark(path: string | RvPath, sid?: string, nid?: string): void; multiMark(path: string | RvPath, sidList?: string[], nidList?: string[]): void; get(sid?: string, nid?: string): StoredRhineVar | undefined; multiGet(sidList?: string[], nidList?: string[]): Map>>; /** * 获取指定元素的局部数据 * @param paths * @param sid * @param nid */ getPartial(paths: (string | RvPath)[], sid?: string, nid?: string): PartialData; /** * 获取多个元素的局部数据 * @param paths * @param sidList * @param nidList */ multiGetPartial(paths: (string | RvPath)[], sidList?: string[], nidList?: string[]): Map>; set(path: string | RvPath, value: unknown, sid?: string, nid?: string): void; multiSet(path: string | RvPath, value: unknown, sidList?: string[], nidList?: string[]): void; /** * 设置局部数据到指定节点 * * @param pd * @param sid * @param nid */ setPartial(pd: PartialData, sid?: string, nid?: string): void; /** * 设置局部数据到多个指定节点 * * @param pd * @param sidList * @param nidList */ multiSetPartial(pd: PartialData, sidList?: string[], nidList?: string[]): void; read(sid?: string, nid?: string): StoredRhineVar | T; multiRead(sidList?: string[], nidList?: string[]): Map | T>>; /** * 获取指定元素的局部数据 * @param paths * @param sid * @param nid */ readPartial(paths: (string | RvPath)[], sid?: string, nid?: string): PartialData; /** * 获取多个元素的局部数据 * @param paths * @param sidList * @param nidList */ multiReadPartial(paths: (string | RvPath)[], sidList?: string[], nidList?: string[]): Map>; edit(path: string | RvPath, value: unknown, sid?: string, nid?: string): void; multiEdit(path: string | RvPath, value: unknown, sidList?: string[], nidList?: string[]): void; editPartial(pd: PartialData, sid?: string, nid?: string): void; multiEditPartial(pd: PartialData, sidList?: string[], nidList?: string[]): void; subscribeTarget(subscriber: NodeAttributeTargetSubscriber): () => void; unsubscribeTarget(subscriber: NodeAttributeTargetSubscriber): void; } /** * @public */ export declare type NodeAttributeTargetSubscriber = (type: TChangeType, path: RvPath, value: unknown, oldValue: unknown, sid: string, nid: string, nidList: string[]) => void; /** * @public */ export declare type NodeMaterialChangeListener = (nid: string, fid: string, material: NodeMaterial) => void; /** * @public */ export declare interface NodeMaterialInfo { nid: string; fid: string; material: NodeMaterial; } /** * @public */ export declare interface NodePair { nid: string; uniqueId: number; node: Node_2; } /** * To [-PI, PI) * @public */ export declare function normalizeAngle(angle: number): number; /** * @public */ export declare function normalizeVector3Angle(vector: Vector3): Vector3; /** * @public */ export declare class NotFoundError extends Error { constructor(message: string); } declare function noZero(v: V3): boolean; /** * @public */ export declare const NumberUtils: { roundToX: typeof roundToX; r2: typeof r2; r3: typeof r3; isValidNumber: typeof isValidNumber; }; /** * @public */ export declare interface OssUploadInstance { fid: string; file: File; status: OssUploadInstanceStatus; progress: number; data?: unknown; } /** * @public */ export declare enum OssUploadInstanceStatus { WAITING = "WAITING", UPLOADING = "UPLOADING", PAUSED = "PAUSED", COMPLETED = "COMPLETED", FAILED = "FAILED", CANCELED = "CANCELED" } /** * 上传服务 * * 委托 rhine-base UploadService 完成文件上传, * 上传完成后将 fileId / resourceId 写入协同数据。 * * @public */ export declare class OssUploadService { private static _instance; static get instance(): OssUploadService; private constructor(); private initialize; /** 正在上传的实例 Map(fid -> OssUploadInstance) */ instances: Map; /** * 已完成上传但尚未获得 resourceId 的 rbFile.id 集合 * * rhine-base 上传流程分两步: * 1. 文件上传完成 → status='complete'(此时无 resourceId) * 2. 后端创建资源 → resourceId 被设置(再次 notify) * 需要在第二步时识别出该文件并写入协同数据 */ private pendingResourceIds; /** * 根据 fid 获取上传实例 * * @param fid - 文件 ID * @returns 上传实例,不存在则返回 undefined */ get(fid: string): OssUploadInstance | undefined; /** * 检查是否存在指定 fid 的上传实例 * * @param fid - 文件 ID */ has(fid: string): boolean; /** * 检查指定 File 对象是否正在上传中 * * @param file - 浏览器 File 对象 */ hasFile(file: File): boolean; /** * 上传文件 * * 委托 rhine-base UploadService 完成完整上传流程。 * 上传完成后自动将 fileId 和 resourceId 写入协同数据。 */ upload(file: File, fid?: string, mime?: string): Promise; /** * 取消指定文件的上传 * * @param fid - 文件 ID * @returns 是否成功取消 */ cancel(fid: string): boolean; private subscribers; private singleSubscribers; /** * 订阅所有上传事件 * * @param subscriber - 事件回调函数 * @returns 取消订阅的函数 */ subscribe(subscriber: OssUploadServiceSubscriber): () => void; /** * 取消订阅所有上传事件 * * @param subscriber - 要取消的回调函数 */ unsubscribe(subscriber: OssUploadServiceSubscriber): void; /** * 订阅单个文件的上传事件 * * @param fid - 文件 ID * @param subscriber - 事件回调函数 * @returns 取消订阅的函数 */ subscribeSingle(fid: string, subscriber: OssUploadServiceSubscriber): () => void; unsubscribeSingle(fid: string, subscriber: OssUploadServiceSubscriber): void; publish(fid: string, type: OssUploadServiceEventType, uploadInstance: OssUploadInstance): void; } /** * @public */ export declare enum OssUploadServiceEventType { START = "START", PROGRESS = "PROGRESS", PAUSE = "PAUSE", RESUME = "RESUME", UPLOADED = "UPLOADED", FAILED = "FAILED", CANCELED = "CANCELED" } /** * @public */ export declare type OssUploadServiceSubscriber = (type: OssUploadServiceEventType, ossUploadInstance: OssUploadInstance) => void; /** * @public */ export declare interface Page { type: PageType; mode: PageMode; viewing: boolean; pid: string; sid: string; } /** * @public */ export declare enum PageMode { DISPLAY = "DISPLAY",// 正常显示 FULL = "FULL",// 3D 场景全屏 - 隐藏所有 UI 元素 HP_BOX = "HP_BOX",// 全息投影盒 - 隐藏所有 UI 元素 - 且四摄像头渲染 VR = "VR",// VR 模式 MR = "MR" } /** * @public */ export declare enum PageType { EDITOR = "EDITOR", VIEWER = "VIEWER", VISITOR = "VISITOR" } /** * @public */ export declare const PageUtils: { getPageTypeBySpaceText: typeof getPageTypeBySpaceText; getSearchParams: typeof getSearchParams; }; /** * 属性的局部数据类。用于表示属性中的一部分数据,存储path和value的元素列表。 * * @public */ export declare class PartialData { data: Set; constructor(data?: [string | RvPath, unknown][]); push(path: string | RvPath, value: unknown): void; forEach(callback: (path: RvPath, value: unknown) => void): void; forEachWithStringPath(callback: (path: string, value: unknown) => void): void; toMixPartialData(attribute: Attribute): MixPartialData; get size(): number; } /** * @public */ export declare interface PartialDataItem { path: RvPath; value: unknown; } /** * @public */ export declare type PathListWithOptionableAttribute = ([path: string | RvPath] | [path: string | RvPath, attribute: Attribute])[]; declare type PathValueArray = { path: RvPath; value: T; }[]; /** * @public */ export declare interface PluginConfig { id: string; url: string; entry: string; css?: string; messages?: { path: string; namespace: string; support: Locale[]; default: Locale; }; official?: boolean; necessary?: boolean; private?: boolean; information: { name: string; icon?: FunctionComponent | string; version?: string; description?: string; }; } /** * @public */ export declare class PluginContainerService { /** * @public */ static get instance(): PluginContainerService; private constructor(); /** * @public */ get pluginList(): BasePlugin[]; /** * @public */ addPlugin(plugin: BasePlugin): void; /** * @public */ removePlugin(plugin: BasePlugin): void; /** * @public */ openPlugin(plugin: IconPlugin): Promise; /** * @public */ closePlugin(plugin: IconPlugin): Promise; /** * @public */ closeDrawerPluginByPosition(position: IconPluginPosition): Promise; } /** * @public */ export declare enum PluginEventType { ADD = "ADD", INSTALL = "INSTALL", ENABLE = "ENABLE", OPEN = "OPEN", CLOSE = "CLOSE", DISABLE = "DISABLE", UNINSTALL = "UNINSTALL", DEBUG = "DEBUG" } /** * @public */ export declare interface PluginInformation { plugin: BasePlugin; root?: Root; iconButton?: HTMLSpanElement; } /** * 插件系统核心服务 * * 本服务是整个插件系统的核心入口,负责插件的完整生命周期管理,包括添加、安装、启用、禁用、卸载等操作。 * 插件系统采用插件化架构设计,所有侧边栏、弹窗、功能按钮等都以插件形式存在,可按需装配。 * * ## 插件系统架构概览 * * 插件系统由以下核心模块组成: * * 1. PluginService (本文件) - 插件生命周期管理核心 * 2. PluginConnector - 插件与主项目的桥接器,向window注入全局API * 3. PluginApiProvider - 向插件暴露的主项目服务和组件集合 * 4. PluginContainerService - 插件UI容器管理,处理插件的DOM渲染 * 5. RvPluginService - 插件协同数据管理,存储插件配置到RhineVar * * ## 插件分类 * * 插件按类型(PluginType)分为以下几类: * * - BUTTON: 按钮插件,点击触发动作,无展开内容 * - SWITCH: 开关插件,点击切换状态 * - DRAWER: 抽屉插件,点击展开侧边栏面板 * - DIALOG: 对话框插件,点击弹出模态框 * - CONTENT: 内容插件,固定显示在内容区域 * - WINDOW: 窗口插件,浮动显示在画布上层 * - SERVICE: 服务插件,无UI,仅提供后台服务 * * ## 插件来源 * * 插件按来源分为两类: * * - 内置插件(BuiltIn): URL以`nfp://`开头,代码打包在主项目中,通过builtInPluginFactory创建实例 * - 外部插件(External): URL为http(s)地址,运行时动态加载JS/CSS文件 * * ## 插件生命周期 * * 插件的完整生命周期如下: * * ``` * add -> install -> enable -> open/close -> disable -> uninstall * ``` * * 各阶段说明: * * - add: 添加插件配置,创建PluginState,加载外部资源(JS/CSS/国际化文件) * - install: 执行插件的onInstall回调,标记installed=true * - enable: 将插件添加到UI容器,执行onEnable回调,标记enabled=true * - open: 打开可展开的插件(DRAWER/DIALOG/SWITCH) * - close: 关闭已打开的插件 * - disable: 从UI容器移除,执行onDisable回调,标记enabled=false * - uninstall: 执行onUninstall回调,移除DOM元素,从plugins Map中删除 * * ## 启用级别(EnableLevel) * * 协同数据中定义了插件的启用级别,决定插件在页面加载时的初始状态: * * - NONE: 不加载 * - INSTALL: 仅安装,不启用 * - ENABLE: 安装并启用,但不打开 * - OPEN: 安装、启用并打开 * * ## 调试模式 * * 支持插件热更新调试: * * - 通过URL参数`?plugin=id:urlPort:hmrPort`快速启动调试 * - 通过协同数据`plugin.debug`配置调试插件 * - WebSocket监听HMR消息,自动重载插件 * * ## 初始化流程 * * 1. 等待SyncInitialized状态 * 2. 解析URL中的调试插件参数 * 3. 并行处理所有配置中的插件(根据EnableLevel执行add/install/enable/open) * 4. 并行启动所有调试插件 * 5. 设置PluginEnabled状态 * 6. 订阅调试插件配置变化 * 7. 检查PreLoaded和PreRendered钩子 * * ## 事件订阅 * * 通过subscribe/unsubscribe方法订阅插件事件: * * - ADD: 插件添加完成 * - INSTALL: 插件安装完成 * - ENABLE: 插件启用完成 * - DISABLE: 插件禁用完成 * - UNINSTALL: 插件卸载完成 * * ## 相关文件索引 * * 核心服务: * - ./plugin-connector.ts - 插件桥接器,向window注入全局对象供外部插件访问 * - ./plugin-api-provider.ts - API提供器,汇总所有向插件暴露的服务、组件、工具函数 * - ./plugin-list.tsx - 插件列表,定义所有可用插件的配置信息和内置插件工厂 * * 类型定义: * - ./dto/plugin-config.type.ts - 插件配置类型,定义插件的基本信息结构 * - ./dto/plugin-state.interface.ts - 插件状态接口,记录插件运行时状态 * - ./dto/plugin-event-type.enum.ts - 插件事件类型枚举 * - ./dto/plugin-service-subscriber.type.ts - 事件订阅者类型定义 * * 插件实例接口: * - ./instance/base-plugin.ts - 插件基础接口,所有插件类型的公共属性 * - ./instance/icon-plugin.ts - 图标插件接口,带侧边栏按钮的插件基类 * - ./instance/drawer-plugin.ts - 抽屉插件接口,可展开侧边栏面板 * - ./instance/dialog-plugin.ts - 对话框插件接口,点击弹出模态框 * - ./instance/view-plugin.ts - 视图插件接口,CONTENT和WINDOW类型的基类 * - ./instance/dto/plugin-type.enum.ts - 插件类型枚举 * - ./instance/dto/icon-plugin-position.enum.ts - 图标插件位置枚举 * - ./instance/dto/icon-view-props.interface.ts - 图标视图Props接口 * - ./instance/dto/plugin-view-props.interface.ts - 插件视图Props接口 * * UI容器管理: * - ./view/plugin-container/plugin-container-service.ts - 容器服务,管理插件的DOM渲染和布局 * - ./view/plugin-container/dynamic/icon-button-manager.ts - 图标按钮管理器,创建和管理侧边栏按钮 * - ./view/plugin-container/dynamic/plugin-ordering-manager.ts - 排序管理器,处理按钮排序和分割线 * - ./view/plugin-container/dynamic/hover-manager.ts - 悬停管理器,处理按钮容器的悬停效果 * * 协同数据: * - ../sync/plugin/rv-plugin-service.ts - 插件协同数据服务,管理plugin配置的CRUD * - ../sync/plugin/default-plugin-config.ts - 默认插件配置,定义初始插件列表和启用级别 * - ../sync/interface/plugin/rv-plugin.ts - 插件协同数据结构 * - ../sync/interface/plugin/rv-plugin-config.interface.ts - 插件配置接口,含EnableLevel和VersionPoint * - ../sync/interface/plugin/rv-plugin-debug.ts - 调试插件配置接口 * * 内置插件示例: * - ../nfp/drawer/debug/debug-drawer-plugin.tsx - 调试抽屉插件,DrawerPlugin实现示例 * - ../nfp/button/home-button/home-button-plugin.tsx - 主页按钮插件,IconPlugin(BUTTON)实现示例 * - ../nfp/switch/select-switch/select-switch-plugin.tsx - 选择开关插件,IconPlugin(SWITCH)实现示例 * - ../nfp/dialog/plugin-manage-dialog/plugin-manage-dialog-plugin.tsx - 插件管理对话框,DialogPlugin实现示例 * - ../nfp/content/message-display/message-display-plugin.tsx - 消息显示插件,ViewPlugin(CONTENT)实现示例 * - ../nfp/window/context-menu-display/context-menu-display-plugin.tsx - 右键菜单插件,ViewPlugin(WINDOW)实现示例 * * 工具函数: * - ../../utils/render-mix-view.tsx - 混合视图渲染,支持字符串HTML或React组件 * - ../../types/view/mix-view.ts - MixView类型定义 * * @public */ export declare class PluginService { /** * 获取 PluginService 单例实例 * * 首次访问时会自动创建实例并触发初始化流程。 * * @returns PluginService 单例实例 * * @example * ```typescript * const pluginService = PluginService.instance * await pluginService.add(config) * ``` */ static get instance(): PluginService; /** * 私有构造函数,确保单例模式 * * 构造时自动触发异步初始化流程。 */ private constructor(); /** * 已注册插件的状态映射表 * * 以插件 ID 为键,存储每个插件的运行时状态信息。 * 包含插件实例、DOM 元素引用、安装/启用状态等。 * * @see PluginState */ plugins: Map; /** * 详细日志模式开关 * * 开启后会在控制台输出更多插件操作的调试信息。 * 默认关闭,仅在开发调试时启用。 */ DETAILED_LOG_MODE: boolean; /** * 普通插件安装超时时间(毫秒) * * 等待插件安装完成的最大时间,超时后会抛出错误。 * @default 3000 */ INSTALL_TIMEOUT: number; /** * 调试插件安装超时时间(毫秒) * * 等待调试插件安装完成的最大时间,超时后会抛出错误。 * @default 3000 */ DEBUG_INSTALL_TIMEOUT: number; /** * 创建预加载钩子 * * 插件可在启用时调用此方法注册预加载任务。 * 注册后需调用 {@link completePreLoadedHook} 标记完成。 * * @param id - 插件 ID * * @example * ```typescript * // 在插件 onEnable 中 * PluginService.instance.createPreLoadedHook(this.id) * // 异步任务完成后 * PluginService.instance.completePreLoadedHook(this.id) * ``` */ createPreLoadedHook(id: string): void; /** * 完成预加载钩子 * * 标记指定插件的预加载任务已完成。 * 所有预加载任务完成后会触发 PluginPreLoaded 状态。 * * @param id - 插件 ID */ completePreLoadedHook(id: string): void; /** * 创建预渲染钩子 * * 插件可在启用时调用此方法注册预渲染任务。 * 注册后需调用 {@link completePreRenderedHook} 标记完成。 * * @param id - 插件 ID * * @example * ```typescript * // 在插件 onEnable 中 * PluginService.instance.createPreRenderedHook(this.id) * // 渲染准备完成后 * PluginService.instance.completePreRenderedHook(this.id) * ``` */ createPreRenderedHook(id: string): void; /** * 完成预渲染钩子 * * 标记指定插件的预渲染任务已完成。 * 所有预渲染任务完成后会触发 PluginPreRendered 状态。 * * @param id - 插件 ID */ completePreRenderedHook(id: string): void; /** * 订阅插件事件 * * 注册一个回调函数,在插件生命周期事件发生时被调用。 * * @param subscriber - 事件订阅回调函数 * @returns 取消订阅的函数 * * @example * ```typescript * const unsubscribe = PluginService.instance.subscribe((id, type) => { * console.log(`Plugin ${id} event: ${type}`) * }) * // 取消订阅 * unsubscribe() * ``` */ subscribe(subscriber: PluginServiceSubscriber): () => void; /** * 取消订阅插件事件 * * @param subscriber - 要取消的订阅回调函数 */ unsubscribe(subscriber: PluginServiceSubscriber): void; /** * 获取插件状态 * * 根据插件 ID 获取其运行时状态信息。 * * @param id - 插件 ID * @returns 插件状态对象,若不存在则返回 undefined * * @example * ```typescript * const state = PluginService.instance.get('my-plugin') * if (state?.enabled) { * console.log('Plugin is enabled') * } * ``` */ get(id: string): PluginState | undefined; /** * 添加插件 * * 根据插件配置添加插件到系统中。 * 自动识别内置插件(nfp://)和外部插件(http)并分别处理。 * * 对于外部插件: * - 创建 script 和 link 元素加载 JS/CSS * - 加载国际化资源文件 * - 将元素添加到 document.body * * 对于内置插件: * - 从 builtInPluginFactory 创建实例 * - 自动触发安装流程 * * @param config - 插件配置对象 * @returns 是否添加成功 * * @example * ```typescript * const success = await PluginService.instance.add({ * id: 'my-plugin', * url: 'https://cdn.example.com/plugins/my-plugin', * entry: 'index.js', * css: 'index.css', * information: { name: 'My Plugin' } * }) * ``` */ add(config: PluginConfig): Promise; /** * 启动插件调试模式 * * 加载调试插件并建立 WebSocket 连接监听 HMR 消息。 * 当收到编译完成消息时自动重新加载插件实现热更新。 * * @param debug - 调试插件配置(RhineVar 存储) * * @example * ```typescript * await PluginService.instance.debug(rvPluginDebug) * ``` */ debug(debug: StoredRhineVar): Promise; /** * 停止插件调试 * * 关闭 HMR WebSocket 连接并卸载调试插件。 * * @param id - 插件 ID */ stopDebug(id: string): Promise; /** * 加载插件国际化消息 * * 从插件的 messages 属性中加载当前语言的翻译资源。 * 内置插件可通过此方式提供多语言支持。 * * @param plugin - 插件实例 */ loadPluginMessages(plugin: BasePlugin): Promise; /** * 安装插件 * * 执行插件的安装流程: * 1. 将插件实例存入 PluginState * 2. 加载插件国际化消息 * 3. 调用插件的 onInstall 生命周期钩子 * 4. 标记 installed = true * 5. 发布 INSTALL 事件 * * 注意: 外部插件的 install 由插件 JS 加载完成后自动调用 PluginConnector.install 触发。 * * @param plugin - 插件实例 */ install(plugin: BasePlugin): Promise; /** * 启用插件 * * 执行插件的启用流程: * 1. 将插件添加到 UI 容器(创建按钮或渲染视图) * 2. 调用插件的 onEnable 生命周期钩子 * 3. 标记 enabled = true * 4. 发布 ENABLE 事件 * * @param id - 插件 ID */ enable(id: string): Promise; /** * 打开插件 * * 打开可展开的插件(DRAWER/DIALOG/SWITCH 类型)。 * 对于 DRAWER 类型会展开侧边栏面板,对于 DIALOG 类型会弹出对话框。 * * @param id - 插件 ID * @throws 若插件未安装则抛出错误 */ open(id: string): Promise; /** * 关闭插件 * * 关闭已打开的插件(DRAWER/DIALOG/SWITCH 类型)。 * * @param id - 插件 ID * @throws 若插件未安装则抛出错误 */ close(id: string): Promise; /** * 禁用插件 * * 执行插件的禁用流程: * 1. 从 UI 容器移除插件 * 2. 调用插件的 onDisable 生命周期钩子 * 3. 标记 enabled = false * 4. 发布 DISABLE 事件 * * @param id - 插件 ID */ disable(id: string): Promise; /** * 卸载插件 * * 执行插件的完整卸载流程: * 1. 若已启用则先禁用 * 2. 调用插件的 onUninstall 生命周期钩子 * 3. 标记 installed = false * 4. 移除 script 和 style DOM 元素 * 5. 从 plugins Map 中删除 * 6. 发布 UNINSTALL 事件 * * @param id - 插件 ID */ uninstall(id: string): Promise; /** * 等待插件安装完成 * * 返回一个 Promise,在指定插件安装完成时 resolve。 * 若插件已安装则立即 resolve。 * * @param id - 插件 ID * @param timeoutMs - 超时时间(毫秒),超时后 reject * @returns Promise,安装完成时 resolve * * @example * ```typescript * await PluginService.instance.waitInstall('my-plugin', 5000) * console.log('Plugin installed') * ``` */ waitInstall(id: string, timeoutMs?: number): Promise; /** * 等待插件启用完成 * * 返回一个 Promise,在指定插件启用完成时 resolve。 * 若插件已启用则立即 resolve。 * * @param id - 插件 ID * @param timeoutMs - 超时时间(毫秒),超时后 reject * @returns Promise,启用完成时 resolve */ waitEnable(id: string, timeoutMs?: number): Promise; /** * 判断是否为可打开的插件类型 * * 可打开的插件类型包括: DRAWER, DIALOG, SWITCH * * @param type - 插件类型 * @returns 是否可打开 */ isOpenablePlugin(type: PluginType): boolean; /** * 判断是否为侧边栏插件类型 * * 侧边栏插件会在左右两侧显示图标按钮。 * 包括: DRAWER, DIALOG, BUTTON, SWITCH * * @param type - 插件类型 * @returns 是否为侧边栏插件 */ isSideBarPlugin(type: PluginType): boolean; /** * 判断是否为视图插件类型 * * 视图插件直接渲染在内容区域或浮动窗口中。 * 包括: WINDOW, CONTENT * * @param type - 插件类型 * @returns 是否为视图插件 */ isViewPlugin(type: PluginType): boolean; } /** * 插件服务订阅者 * * @param id - 插件id * @param type - 事件类型 * @public */ export declare type PluginServiceSubscriber = (id: string, type: PluginEventType) => void; /** * @public */ export declare interface PluginState { instance?: BasePlugin; element?: HTMLScriptElement; styleElement?: HTMLLinkElement; installed: boolean; enabled: boolean; debug?: boolean; } /** * @public */ export declare enum PluginType { BUTTON = "BUTTON", SWITCH = "SWITCH", DRAWER = "DRAWER", DIALOG = "DIALOG", CONTENT = "CONTENT", WINDOW = "WINDOW", SERVICE = "SERVICE" } /** * @public */ export declare interface PluginViewProps extends DivProps { plugin: DrawerPlugin | ViewPlugin | DialogPlugin; } declare function preventDefaultListener(e: ReactEvent): void; declare function preventDefaultStopPropagationListener(e: ReactEvent): void; /** * @public */ export declare function ProgressBar(props: ProgressBarProps): JSX.Element; /** * @public */ export declare interface ProgressBarProps extends React_2.HTMLAttributes { value?: number; indeterminate?: boolean; slowTransition?: boolean; innerClassName?: string; } declare function r2(n: number): number; declare function r3(n: number): number; declare function radiansToDegrees(v: V3): V3; declare function radiansToQuaternion(v: V3): Quaternion; declare type ReactEvent = React_2.MouseEvent | React_2.DragEvent | React_2.TouchEvent | React_2.WheelEvent; /** * @public */ export declare function recursNode(node: Node_2, fun: (node: Node_2) => void): void; declare function recursPathValue(path: RvPath, value: T): PathValueArray; /** * @public */ export declare function removeMixView(parent: HTMLElement): void; /** * @public */ export declare function renderMixView(view: MixView, parent: HTMLElement, props?: T): void; /** * @public */ export declare function ResourcePreview(props: ResourcePreviewProps): JSX.Element; /** * @public */ export declare interface ResourcePreviewProps extends DivProps { className?: string; mime?: string; preview?: string; } /** * 资源管理服务 * * 负责资源的上传、批量上传、重复检测、纹理预览图生成等功能。 * 上传操作委托 OssUploadService 完成,最终由 rhine-base UploadService 执行。 * * @public */ export declare class ResourceService { /** * @public */ static get instance(): ResourceService; private constructor(); /** 资源拖拽状态(Valtio 响应式) */ dragState: { fid: string; data: null; x: number; y: number; offsetX: number; offsetY: number; }; /** * 上传单个文件为资源 * * @param file - 浏览器 File 对象 * @param fid - 可选的文件 ID,不传则由上传服务自动生成 * @param check - 是否标记历史记录 * @returns 文件 ID */ upload(file: File, fid?: string, check?: boolean): Promise; /** * 批量上传文件为资源 * * 自动检测重复文件并提示用户。fidList 长度需与 fileList 一致或为空。 * * @param fileList - 文件列表,支持 FileList、File[]、单个 File 或 null * @param check - 是否标记历史记录 * @param fidList - 可选的文件 ID 列表,与 fileList 一一对应 */ uploadMulti(fileList: FileList | File[] | File | null | undefined, check?: boolean, fidList?: string[]): Promise; /** 预览图宽度(像素) */ PREVIEW_IMAGE_WIDTH: number; /** 预览图高度(像素) */ PREVIEW_IMAGE_HEIGHT: number; /** * 生成纹理的描述信息 * * @param texture - BabylonJS 纹理对象 * @param fromFileId - 纹理来源的文件 ID * @returns 包含分辨率和来源文件名的描述字符串 */ generateDescribeForTexture(texture: BaseTexture, fromFileId: string): string; /** * 生成纹理的预览图文件 * * 将 BabylonJS 纹理渲染为 256x256 的 PNG 预览图,保持宽高比居中绘制。 * * @param texture - BabylonJS 纹理对象 * @param filename - 输出文件名,默认 'texture.png' * @returns PNG 格式的 File 对象,失败返回 null */ generatePreviewForTexture(texture: BaseTexture, filename?: string): Promise; /** * 上传文件并等待完成 * * 监听上传和资源添加事件,成功时返回 resourceId,失败时 reject。 * * @param file - 浏览器 File 对象 * @param fid - 可选的文件 ID,不传则由上传服务自动生成 * @returns Promise,上传成功返回资源 ID,失败则 reject */ uploadAndWait(file: File, fid?: string): Promise; /** * 批量上传文件并等待所有完成 * * 自动检测重复文件并提示用户。返回成功上传的资源 ID 列表。 * * @param fileList - 文件列表,支持 FileList、File[]、单个 File 或 null * @param fidList - 可选的文件 ID 列表,与 fileList 一一对应 * @returns Promise,成功上传的资源 ID 列表 */ uploadMultiAndWait(fileList: FileList | File[] | File | null | undefined, fidList?: string[]): Promise; /** * 通过已有文件 ID 创建资源 * * 调用后端资源创建接口,在当前用户容器中创建一个引用指定文件的资源。 * 创建成功后自动将资源元数据写入缓存并添加到协同数据。 * * @param fileId - 已存在的后端文件 ID * @param name - 资源名称 * @returns 创建成功的 resourceId * @public */ createByFileId(fileId: string, name: string): Promise; /** * 生成资源/文件 ID * * @returns 以 'F' 为前缀的唯一 ID */ generateId(): string; } /** * @public */ export declare function rootParent(node: Node_2): Node_2; declare function roundToX(num: number, x: number): number; /** * 动画管理器对象 * @public */ export declare class RsAnimationManager { constructor(); static initialize(): Promise; static analyzeAnimationDuration(step: StoredRhineVar, lastStep?: RvStep): number; static specialAnimation(): void; } /** * @public */ export declare class RsAudioService { static get instance(): RsAudioService; private constructor(); processStepAudioMap(step: StoredRhineVar): void; fadeOutAndPauseAllAudio(): void; processAudioMap(audioMap: RvAudio | undefined, idKey: string): void; } /** * @public */ export declare class RsBasicService { static get instance(): RsBasicService; private constructor(); updateBasic(nid: string, node: Node_2, path: string[] | RvPath, value: unknown, rvBasic: StoredRhineVar): void; updateEnable(nid: string, node: Node_2, rvBasic: RvBasic, recursive: boolean, duration?: number, quickMode?: boolean): void; } /** * @public */ export declare class RsClick { static get instance(): RsClick; private constructor(); simplifyDoneList(delay: number): void; show(position: V3, color: string, timestamp: number, duration?: number, id?: string): void; } /** * @public */ export declare function RsdButton(props: RsdButtonProps): JSX.Element; /** * @public */ export declare interface RsdButtonProps extends DivProps { onClick: MouseEventHandler; dashed?: boolean; text: string; tip?: string; icon?: string; iconSize?: number; single?: boolean; } /** * @public */ export declare function RsdCheckableButton(props: RsdCheckableButtonProps): JSX.Element; /** * @public */ export declare interface RsdCheckableButtonProps extends DivPropsSimple { value: boolean; onChange: (value: boolean) => void; label: string; className?: string; theme?: string; children?: ReactNode; } /** * @public */ export declare function RsdCheckbox(props: RsdCheckboxProps): JSX.Element; /** * @public */ export declare interface RsdCheckboxProps extends DivPropsSimple { value: boolean; onChange: (value: boolean) => void; label: string; className?: string; theme?: string; } /** * @public */ export declare function RsdColor(props: RsdColorProps): JSX.Element; /** * @public */ export declare interface RsdColorProps extends DivPropsSimple { value: string; onChange: (value: string) => void; label: string; disableAlpha?: boolean; className?: string; theme?: string; } /** * @public */ export declare function RsdFileSelect(props: RsdFileSelectProps): JSX.Element; /** * @public */ export declare function RsdFileSelectButton(props: RsdFileSelectProps): JSX.Element; /** * @public */ export declare interface RsdFileSelectProps extends DivPropsSimple { label: string; value: string; onChange: (value: string) => void; accept: string[]; tip?: string; className?: string; theme?: ThemeColor; } /** * @public */ export declare function RsdInput(props: RsdInputProps): JSX.Element; /** * @public */ export declare interface RsdInputProps extends DivPropsSimple { value: string; onChange: (value: string) => void; type?: 'text' | 'number' | 'password'; placeholder?: string; className?: string; rows?: number; maxLength?: number; } /** * @public */ export declare function RsdNone(props: RsdNoneProps): JSX.Element; /** * @public */ export declare interface RsdNoneProps extends DivProps { label: string; className?: string; theme?: string; } /** * @public */ export declare function RsdNumber(props: RsdNumberProps): JSX.Element; /** * @public */ export declare function RsdNumberList(props: RsdNumberListProps): JSX.Element; /** * @public */ export declare interface RsdNumberListProps extends DivProps { style?: React.CSSProperties; value: number[]; keys: string[]; onChangeIndex: (index: number, value: number | null) => void; min?: number; className?: string; theme?: string; shrink?: boolean; } /** * @public */ export declare interface RsdNumberProps extends DivPropsSimple { value: number; onChange: (value: number) => void; label: string; className?: string; theme?: string; min?: number; max?: number; step?: number; } /** * @public */ export declare function RsdSelect(props: RsdSelectProps): JSX.Element; /** * @public */ export declare interface RsdSelectProps extends DivPropsSimple { value: ValueType; defaultValue?: ValueType; options: { value: ValueType; label: string; }[]; onChange: (value: ValueType) => void; label: string; className?: string; theme?: string; smallWidth?: boolean; } /** * @public */ export declare function RsdSwitch(props: RsdSwitchProps): JSX.Element; /** * @public */ export declare interface RsdSwitchProps extends DivPropsSimple { value: boolean; onChange: (value: boolean) => void; label: string; className?: string; theme?: string; } /** * @public */ export declare function RsdTargetInfo(props: RsdTargetInfoProps): JSX.Element; /** * @public */ export declare interface RsdTargetInfoProps extends DivPropsSimple { nid: string; getSummaryText?(): string; getTipText?(): string; showTipText?: boolean; showGetChildrenTip?: boolean; } /** * @public */ export declare function RsdTextarea(props: RsdInputProps): JSX.Element; /** * @public */ export declare function RsdTitle(props: RsdTitleProps): JSX.Element; /** * @public */ export declare interface RsdTitleProps extends DivProps { title: string; className?: string; tip?: string; detail?: string; mt?: boolean; } /** * @public */ export declare function RsdTitleSwitch(props: RsdTitleSwitchProps): JSX.Element; /** * @public */ export declare interface RsdTitleSwitchProps extends DivPropsSimple { title: string; tip?: string; value: boolean; onChange: (value: boolean) => void; className?: string; } /** * @public */ export declare class RsEnableService { /** * @public */ static get instance(): RsEnableService; private constructor(); get(nid: string): boolean; clear(): void; } /** * @public */ export declare class RsEngine { static get instance(): RsEngine; private constructor(); canvas: HTMLCanvasElement | null; initialized: boolean; initialize(): Promise; } /** * @public */ export declare class RsEnvironment { static get instance(): RsEnvironment; private constructor(); mainCamera: ArcRotateCamera; rightCamera: ArcRotateCamera; backCamera: ArcRotateCamera; leftCamera: ArcRotateCamera; lights: Light[]; shadow: ShadowGenerator; environmentTexture: CubeTexture; STANDARD_MODE: boolean; adjustCamera(models: AbstractMesh[] | AbstractMesh): void; getCameraInfo(): { target: { x: number; y: number; z: number; }; alpha: number; beta: number; radius: number; }; addShadows(meshes: AbstractMesh[] | AbstractMesh): void; initLight(): void; initFourCamera(camerasNode: TransformNode): void; setActiveCamera(isFour?: boolean): void; normalizeCameraAngle(): void; setCameraDistance(distance: number): void; setBackgroundColor(color: Color3): void; getPositionToCameraDistance(p: V3 | Vector3): number; } /** * @public */ export declare class RsEnvironmentService { static get instance(): RsEnvironmentService; private constructor(); updateEnvironment(path: RvPath, step: StoredRhineVar): void; getCurrentCameraLocation(): RvCameraLocation; } /** * 管理和渲染3D场景中的标签 * @public */ export declare class RsLabelService { static get instance(): RsLabelService; private constructor(); labels: LabelInfo[]; updateClick(nid: string | null | undefined): void; getLabel(nid: string): LabelInfo | null; ensureLabel(nid: string, node?: TransformNode | null): LabelInfo; removeLabel(nid: string): void; updateLabelWithNid(nid: string, rvLabel: RvLabel): void; } /** * @public */ export declare class RsLoopAnimationManager { static get instance(): RsLoopAnimationManager; private constructor(); state: { enableInEditorMode: boolean; }; restartAnimation(nid: string, resetLocation?: boolean): void; startAllLoopAnimations(): void; startAnimationLoop(nid: string, node: TransformNode, data: RvLoop, locationData: RvLocation): void; stopAllLoopAnimations(resetLocation?: boolean): void; stopAnimation(nid: string): void; makeTripAnimation(dis: number, speed: number, start: number, name: string, axis: string, fr: number): Animation_2; makeSpinAnimation(value: number, start: number, name: string, axis: string, fr: number): Animation_2; makeQuaternionAnimation(value: number, start: Vector3, name: string, axis: 'x' | 'y' | 'z', fr: number): Animation_2; } /** * @public */ export declare class RsMaterialService { static get instance(): RsMaterialService; private constructor(); updateMaterial(nid: string, mesh: AbstractMesh, path: string[] | RvPath, value: unknown, rvMaterial: StoredRhineVar): Promise; updateGeneralMaterialSingle(material: Material, path: RvPath, value: unknown): void; updatePBRMaterialSingle(material: PBRMaterial, path: RvPath, value: unknown): void; updateNodeMaterialSingle(material: NodeMaterial, path: RvPath, value: unknown, inputs?: RvMaterialNodeInput[]): void; } /** * @public */ export declare interface RsModel { mid: string; progress: number; status: RsModelStatus; node?: Node_2; } /** * @public */ export declare class RsModelService { static get instance(): RsModelService; private constructor(); DETAILED_LOG_MODE: boolean; models: Map; get(mid: string): RsModel | undefined; has(mid: string): boolean; add(rsModel: RsModel): boolean; remove(mid: string): boolean; load(mid: string): Promise; pause(mid: string): boolean; resume(mid: string): boolean; cancel(mid: string): boolean; subscribe(subscriber: RsModelServiceSubscriber): () => void; unsubscribe(subscriber: RsModelServiceSubscriber): void; subscribeSingle(mid: string, subscriber: RsModelServiceSubscriber): () => void; unsubscribeSingle(mid: string, subscriber: RsModelServiceSubscriber): void; publish(mid: string, type: RsModelServiceEventType, rsModel: RsModel): void; afterLoaded(mid: string, subscriber: (rsModel: RsModel) => void): void; waitLoaded(mid: string): Promise; isLoaded(mid: string): boolean | undefined; } /** * @public */ export declare enum RsModelServiceEventType { ADD = "ADD", REMOVE = "REMOVE", START = "START", PROGRESS = "PROGRESS", PAUSE = "PAUSE", RESUME = "RESUME", LOADED = "LOADED", ERROR = "ERROR", CANCELED = "CANCELED" } /** * @public */ export declare type RsModelServiceSubscriber = (type: RsModelServiceEventType, rsModel: RsModel) => void; /** * @public */ export declare enum RsModelStatus { WAITING = "WAITING", LOADING = "LOADING", LOADED = "LOADED", ERROR = "ERROR", CANCELED = "CANCELED" } /** * @public */ export declare class RsNodeMaterialAnalyzer { /** * @public */ static get instance(): RsNodeMaterialAnalyzer; static TEXTURE_NAME_MAP: Map; isTextureBlockName(name: string): boolean; } /** * @public */ export declare class RsNodeMaterialManager { static get instance(): RsNodeMaterialManager; private constructor(); materials: NodeMaterialInfo[]; has(nid: string): boolean; add(nid: string, fid: string, material: NodeMaterial): void; get(nid: string): NodeMaterialInfo | null; set(nid: string, fid: string, material: NodeMaterial): void; remove(nid: string): void; waitFid(nid: string, fid: string): Promise; updateNodeMaterialTemplate(nid: string, fid: string, syncStateWhenCreate?: boolean): Promise; uploadNodeMaterialTemplate(nid: string, fid: string, material: NodeMaterial): void; nodeMaterialToFile(material: NodeMaterial): File; } /** * RsNodeService - 渲染节点服务 * * 负责管理 Babylon.js 3D 场景节点与 RhineVar 同步数据之间的映射关系。 * 主要功能包括: * - 生成节点映射表(NodePair):将 3D 场景中的节点树结构映射到唯一的 nid(节点ID) * - 解析压缩的节点数据:从 RvModel 中读取压缩后的节点结构并还原成 NodePair * - 节点查询:通过 nid、uniqueId、mid、fid 等标识符快速查找节点 * - 发布订阅机制:当节点映射关系更新时通知订阅者 * * @remarks * nid 格式:`${mid}--L${level}-N${index}` * - mid: model id,模型ID * - level: 节点在树中的层级(从0开始) * - index: 节点在当前生成过程中的序号(深度优先遍历顺序) * 注意 nid 的格式并非绝对,请勿从 nid 中截取信息,来用于后续的计算 * * @example * ```typescript * const service = RsNodeService.instance * service.generateNodePairs('model-123', rootNode) * const node = service.getNodeByNid('model-123--L0-N0') * ``` * * @public */ export declare class RsNodeService { /** * 获取 RsNodeService 单例实例 * * @returns RsNodeService 单例对象 */ static get instance(): RsNodeService; private constructor(); /** * 移除节点映射(不销毁 Babylon 节点) * * @param nid - 节点唯一标识符 * @returns 是否成功移除 */ removeNodePair(nid: string): boolean; /** * 从 Babylon 场景中删除节点(包括子节点)并移除映射 * * @param nid - 节点唯一标识符 * @returns 是否成功删除 */ remove(nid: string): boolean; /** * 生成场景节点结构并添加到 RvScene * * 遍历 Babylon.js 节点树,生成 RvSceneNode 结构并添加到 RvSceneService。 * RvSceneNode 是 RhineVar 同步数据中的场景节点表示,支持多人协同编辑场景结构。 * * 使用场景:首次创建场景或添加新模型到场景时调用。 * * @param mid - 模型ID * @param root - 模型的根节点对象 * * @example * ```typescript * // 添加模型到场景 * RsNodeService.instance.generateSceneNode('model-123', root) * ``` */ generateSceneNode(mid: string, root: Node_2): void; /** * 生成节点指纹 * * 根据节点的多种几何属性生成唯一指纹字符串,用于区分同名节点。 * 指纹包含节点的空间变换信息和网格几何特征。 * * ## 指纹组成 * * | 前缀 | 含义 | 适用类型 | * |------|------|----------| * | C | 子节点数量 | 所有 Node | * | P | 位置 (position) | TransformNode 及子类 | * | R | 旋转 (rotation) | TransformNode 及子类 | * | S | 缩放 (scaling) | TransformNode 及子类 | * | V | 顶点数量 | Mesh | * | I | 索引数量(面数×3) | Mesh | * | B | 包围盒 min/max | Mesh | * | D | 采样顶点坐标 | Mesh | * * ## 采样策略 * * 对于 Mesh 节点,会采样 3.33%、50%、96.67% 位置的顶点坐标, * 以较小的数据量捕获网格的几何特征。 * * @param node - Babylon.js 节点对象 * @returns 指纹字符串,格式如 `C2P10000200003000R00000000000000S10000100001000V1234I5678B...D...` * * @example * ```typescript * const fingerprint = RsNodeService.instance.generateFingerprint(meshNode) * // fingerprint = "C0P10000200003000R00000000000000S10000100001000V1024I3072B..." * ``` * * @see {@link matchOriginalNodes} 使用指纹进行节点匹配 * @see {@link rescueGenerateSceneNode} 生成场景时调用此方法 */ generateFingerprint(node: Node_2): string; /** * 根据 nid 获取节点映射信息 * * @param nid - 节点唯一标识符 * @returns NodePair 对象,未找到则返回 null * * @example * ```typescript * const pair = RsNodeService.instance.getNodePairByNid('model-123--L0-N0') * if (pair) { * console.log(pair.node.name) * console.log(pair.uniqueId) * } * ``` */ getNodePairByNid(nid: string): NodePair | null; /** * 根据 Babylon.js uniqueId 获取节点映射信息 * * @param uniqueId - Babylon.js 节点的内部唯一ID * @returns NodePair 对象,未找到则返回 null * * @example * ```typescript * const pickedMesh = scene.pick(event.x, event.y) * if (pickedMesh.hit) { * const pair = RsNodeService.instance.getNodePairByUniqueId(pickedMesh.pickedMesh.uniqueId) * console.log('Clicked node nid:', pair?.nid) * } * ``` */ getNodePairByUniqueId(uniqueId: number): NodePair | null; /** * 根据 nid 获取 Babylon.js 节点对象 * * @param nid - 节点唯一标识符 * @returns Babylon.js Node 对象,未找到则返回 null * * @example * ```typescript * const node = RsNodeService.instance.getNodeByNid('model-123--L1-N5') * if (node) { * node.setEnabled(false) * } * ``` */ getNodeByNid(nid: string): Node_2 | null; getMeshByNid(nid: string): Mesh | null; getMaterialByNid(nid: string): Material | null; /** * 根据 Babylon.js uniqueId 获取 nid * * @param uniqueId - Babylon.js 节点的内部唯一ID * @returns nid 字符串,未找到则返回 null * * @example * ```typescript * const pickedMesh = scene.pick(event.x, event.y) * if (pickedMesh.hit) { * const nid = RsNodeService.instance.getNidByUniqueId(pickedMesh.pickedMesh.uniqueId) * // Use nid to update RhineVar sync data * } * ``` */ getNidByUniqueId(uniqueId: number): string | null; /** * 从 nid 中提取模型ID (mid) * * @param nid - 节点唯一标识符,格式:`${mid}--L${level}-N${index}` * @returns mid 字符串,格式不正确则返回 null * * @example * ```typescript * const mid = RsNodeService.instance.getMidByNid('model-123--L1-N5') * // mid = 'model-123' * ``` */ getMidByNid(nid: string): string | null; /** * 分析并加载指定模型的所有节点映射 * * 当模型文件加载完成后调用此方法,将 RhineVar 协同数据中的 RvSceneNode * 与 Babylon.js 场景中的实际节点建立映射关系。 * * 执行流程: * 1. 从 RvSceneService 获取所有 source.mid 为该 mid 的原始节点(非复制节点) * 2. 调用 matchOriginalNodes 将协同数据节点与 Babylon 节点进行匹配 * 3. 匹配成功后通过 addNodePair 建立 nid 到 Node 的映射 * * @param mid - 模型ID,用于筛选属于该模型的 RvSceneNode * @param root - 模型的 Babylon.js 根节点对象 * * @throws {Error} 当找不到任何属于该 mid 的 RvSceneNode 时抛出异常 * * @example * ```typescript * // 模型加载完成后建立节点映射 * const root = loadedModel.rootNode * RsNodeService.instance.analyzeSceneNode('model-123', root) * * // 之后可以通过 nid 获取节点 * const node = RsNodeService.instance.getNodeByNid('model-123--L0-N0') * ``` * * @see {@link matchOriginalNodes} 内部匹配逻辑 * @see {@link generateSceneNode} 首次生成场景节点(与此方法互补) */ analyzeSceneNode(mid: string, root: Node_2): void; /** * 根据模型ID获取文件ID (fid) * * 从 RvModelService 中查询模型的关联文件ID。 * * @param mid - 模型ID * @returns fid 字符串,未找到则返回 null * * @example * ```typescript * const fid = RsNodeService.instance.getFidByMid('model-123') * // fid 指向模型文件在文件系统中的ID * ``` */ getFidByMid(mid: string): string | null; /** * 根据节点ID获取文件ID (fid) * * 组合 getMidByNid 和 getFidByMid 功能。 * * @param nid - 节点唯一标识符 * @returns fid 字符串,未找到则返回 null * * @example * ```typescript * const fid = RsNodeService.instance.getFidByNid('model-123--L1-N5') * // fid = 模型文件ID * ``` */ getFidByNid(nid: string): string | null; /** * 订阅节点映射变化 * * 当 nodePairs 更新时(如加载新模型、解析节点等),订阅者会收到通知。 * * @param subscriber - 订阅回调函数,参数为最新的 NodePair 数组 * @returns 取消订阅函数 * * @example * ```typescript * const unsubscribe = RsNodeService.instance.subscribeNodePairs((pairs) => { * console.log('NodePairs updated, total nodes:', pairs.length) * // Update UI or perform other actions * }) * * // Later, unsubscribe * unsubscribe() * ``` */ subscribeNodePairs(subscriber: (pairs: NodePair[]) => void): () => void; /** * 取消订阅节点映射变化 * * @param subscriber - 要取消的订阅回调函数 * * @example * ```typescript * const callback = (pairs: NodePair[]) => { ... } * RsNodeService.instance.subscribeNodePairs(callback) * // Later * RsNodeService.instance.unsubscribeNodePairs(callback) * ``` */ unsubscribeNodePairs(subscriber: (pairs: NodePair[]) => void): void; } /** * RsSceneService 管理所有场景节点的嵌套关系变动 * @public */ export declare class RsSceneService { static get instance(): RsSceneService; private constructor(); /** * 同步所有 Babylon 节点与 RvSceneNode 协同数据 * * 将 Babylon.js 场景中的节点树结构与 RhineVar 协同数据中的 RvSceneNode 完全对齐。 * * ## 同步流程 * * 1. **创建缺失的 copy 节点**:检查所有带 `source.copy` 的 RvSceneNode, * 若对应 Babylon 节点不存在则 clone 创建。按层级顺序处理,确保父节点先于子节点创建。 * 2. **同步 parent 关系**:检查所有节点的父子关系,修正不一致的 parent 指向。 * 3. **同步 deleted 状态**:将 RvSceneNode 的 `deleted` 字段同步到 Babylon 节点的 `enabled` 状态。 * * @throws {Error} 当 copy 源节点不存在时抛出异常 * @throws {Error} 当 Babylon clone 操作失败时抛出异常 */ syncAll(): void; /** * 同步单个节点的 Babylon 状态与 RvSceneNode 协同数据 * * @param nid - 节点唯一标识符 * @param sceneNode - RvSceneNode 协同数据,默认从 RvSceneService 获取 * @param targetNode - 目标 Babylon 节点,默认从 RsNodeService 获取 * @param parentNode - 父 Babylon 节点,默认从 RsNodeService 获取 * @returns 是否发生了变更 * * @throws {Error} 当非 copy 节点的 Babylon 节点不存在时抛出异常 * @throws {Error} 当 copy 源节点不存在时抛出异常 * @throws {Error} 当 Babylon clone 操作失败时抛出异常 */ sync(nid: string, sceneNode?: RvSceneNode | null, targetNode?: Node_2 | null, parentNode?: Node_2 | null): boolean; } /** * @public */ export declare class RsSelection { static get instance(): RsSelection; private constructor(); gm: GizmoManager | null; makeInfo(nid: string): RsSelectionNodeInfo | null; } /** * @public */ export declare interface RsSelectionMaterialInfo { allNumber: number; supportEditMaterialNumber: number; hasGeometryNumber: number; hasOtherMaterialNumber: number; hasChildrenNumber: number; isAbstractMeshNumber: number; } /** * @public */ export declare interface RsSelectionNodeInfo { nid: string; nodeName: string; babylonNode: Node_2; uniqueId: number; mid: string; modelLoadName: string; rvModel: RvModel; isTransformNode: boolean; isAbstractMesh: boolean; isMesh: boolean; isCoordinateFlip: boolean; isCoordinateRotation: boolean; hasGeometry: boolean; isRoot: boolean; childrenNumber: number; supportQuaternion: boolean; animationNumber: number; skeletonNumber: number; hasMaterial: boolean; isSupportMaterial: boolean; supportEditMaterial: boolean; } /** * @public */ export declare class RsSelectionService { static get instance(): RsSelectionService; private constructor(); click(nid?: string, ctrl?: boolean): void; set(nidList: string[]): void; add(nid: string): void; remove(nid: string): void; clear(): void; has(nid: string): boolean; get(nid: string): RsSelectionNodeInfo | null; selected: RsSelectionNodeInfo[]; last: RsSelectionNodeInfo | null; branchMode: boolean; materialInfo: RsSelectionMaterialInfo; highlight: HighLightInfo[]; getSelectedNidList(): string[]; changeBranchMode(value?: boolean, message?: boolean): void; toAllChildren(log?: boolean): boolean; subscribe(subscriber: SelectedSubscriber): () => void; unsubscribe(subscriber: SelectedSubscriber): void; subscribeLast(subscriber: LastSubscriber): () => void; unsubscribeLast(subscriber: LastSubscriber): void; } /** * @public */ export declare interface RsSelectionState { highlight: HighLightInfo[]; selected: RsSelectionNodeInfo[]; last: RsSelectionNodeInfo | null; branchMode: boolean; materialInfo: RsSelectionMaterialInfo; } /** * 材质分离渲染服务 * * 在 BabylonJS 渲染层执行实际的材质分离操作。 * 当多个 mesh 共享同一材质时,通过 clone 材质实现独立编辑, * 避免修改一个节点的材质影响其他节点。 * * @remarks * 采用"按需分离"策略,只在需要独立编辑时才 clone 材质,节省内存。 * * 典型流程: * 1. 文件加载后调用 {@link analyzeByMeshes} 分析共享材质的节点 * 2. 编辑材质时调用 {@link get} 或 {@link getWithEnsureType} 获取独立材质 * * @example * ```typescript * // 获取节点的独立材质(按需分离) * const material = await RsSeparateService.instance.get(nid) * * // 获取并确保材质类型匹配 * const material = await RsSeparateService.instance.getWithEnsureType(nid, rvMaterial) * ``` * * @see {@link RvSeparateService} 协同数据层材质分离服务 */ export declare class RsSeparateService { /** * 获取单例实例 * * @returns 服务单例 */ static get instance(): RsSeparateService; private constructor(); /** * 已完成材质分离的节点 nid 列表 * * 记录在当前会话中已经执行过材质 clone 的节点,避免重复分离。 */ separated: string[]; /** * 检查节点是否已完成材质分离 * * @param nid - 节点唯一标识符 * @returns 是否已分离 */ has(nid: string): boolean; /** * 标记节点为已分离,并可选地设置材质 * * @param nid - 节点唯一标识符 * @param mesh - 目标 mesh(可选) * @param material - 要设置的材质(可选) */ add(nid: string, mesh?: AbstractMesh, material?: Material | null): void; /** * 获取节点分离后的材质 * * 如果节点在分离组中但尚未分离,则 clone 原材质并赋给该 mesh。 * 如果已分离或不在分离组中,直接返回当前材质。 * * @param nid - 节点唯一标识符 * @param node - 可选的已知节点,避免重复查找 * @returns 分离后的材质,若节点无材质则返回 null */ get(nid: string, node?: Node_2): Promise; /** * 获取节点分离后的材质,并确保材质类型匹配 * * 会检查当前材质类型是否与协同数据中定义的类型一致, * 不一致则创建新的对应类型材质。 * * @param nid - 节点唯一标识符 * @param rvMaterial - 协同数据中的材质定义 * @param node - 可选的已知节点,避免重复查找 * @returns 类型匹配的分离材质,若无法创建则返回 null */ getWithEnsureType(nid: string, rvMaterial: RvMaterial, node?: Node_2): Promise; /** * 检查材质实例是否匹配指定类型 * * @param material - BabylonJS 材质实例 * @param type - 期望的材质类型枚举值 * @returns 是否匹配 */ checkMaterialType(material: Material, type: RvMaterialType): boolean; /** * 分析一组 mesh,找出共享材质的节点并写入协同数据 * * 遍历所有 mesh,按材质 uniqueId 分组,将共享同一材质的节点 nid 记录到 * {@link RvSeparateService} 的协同数据中。 * * @remarks * 通常在文件加载完成后调用,用于初始化材质分离信息。 * * @param meshes - 要分析的 mesh 数组 */ analyzeByMeshes(meshes: AbstractMesh[]): void; } /** * @public */ export declare class RsService { static get instance(): RsService; private constructor(); canvas: HTMLCanvasElement | undefined; scene: Scene | undefined; engine: Engine | WebGPUEngine | undefined; rendering: boolean; experience: WebXRDefaultExperience | null; initialize(canvas: HTMLCanvasElement, scene: Scene, engine: Engine | WebGPUEngine): void; isSupportWebXR(): boolean; isWebXRInitialized(): boolean; enterVR(onInitialize: () => void): Promise; } /** * @public */ export declare class RsTextureService { static get instance(): RsTextureService; private constructor(); get(fid: string): TextureInfo | null; getWhiteTexture(): DynamicTexture; getBlackTexture(): DynamicTexture; add(fid: string): Promise; getTexture(fid: string, without?: number): Promise; pushTexture(fid: string, texture: Texture, url?: string): TextureInfo; remove(fid: string): void; } /** * @public */ export declare class RsTransformGround { static get instance(): RsTransformGround; private constructor(); readonly root: TransformNode; readonly ground: Mesh | undefined; readonly mb: StandardMaterial; readonly m1: NodeMaterial; readonly m10: NodeMaterial; readonly m1Color: InputBlock; readonly m10Color: InputBlock; readonly m1Alpha: InputBlock; readonly m10Alpha: InputBlock; g1: Mesh | undefined; g10: Mesh | undefined; createGround(): void; hideGround(): void; showGround(): void; freshGround(viewing?: boolean, enableOnViewerMode?: boolean, enableOnEditorMode?: boolean): void; } /** * @public */ export declare interface RvAnimation { loop?: RvLoop; embedded?: RvNative; } /** * @public */ export declare enum RvAttachType { TEXTURE = "TEXTURE", MATERIAL = "MATERIAL", UV = "UV" } /** * @public */ export declare interface RvAudio { autoPlay: boolean; fid: string; loop: boolean; speed: number; volume: number; } /** * @public */ export declare interface RvAwareness { clientId: number; user: RvAwarenessUser; device: RvAwarenessDevice; sid: string; meetingId: string; selected: string[]; camera: RvCameraLocation; clicks: RvAwarenessClick[]; window: RvAwarenessWindow; cursor: V3; openedDrawers: string[]; } /** * @public */ export declare interface RvAwarenessClick { position: V3; timestamp: number; } /** * @public */ export declare interface RvAwarenessDevice { platform: string; } /** * @public */ export declare interface RvAwarenessUser { name: string; color: string; avatar: string; uuid: string; } /** * @public */ export declare interface RvAwarenessWindow { innerWidth: number; innerHeight: number; } /** * 全局协同数据总变量 * * 所有项目数据的根结构,通过 RhineVar 实现多人实时同步。 * resources 仅存储 ID 列表,元数据通过 RvResourceService 从后端获取并缓存在本地。 * * @public */ export declare interface RvBase { /** 项目全局配置 */ project: RvProject; /** 场景展示顺序(sid 列表) */ order: RhineVarArray; /** 场景 Map(sid -> RvStep) */ steps: RhineVarMap; /** 插件信息 */ plugin: RvPlugin; /** 资源 ID 列表,元数据通过 RvResourceService.getMetadata() 获取 */ resources: RhineVarArray; /** 场景节点树 */ scene: RhineVarMap; /** 模型列表 */ models: RhineVarMap; /** 材质分离数据 */ separate: RvSeparate; /** 历史记录 */ history: RvHistory; /** 会议信息 */ meetings: RhineVarMap; /** 版本信息 */ version: RvVersion; } /** * @public */ export declare interface RvBasic { enable: boolean; isPickable: boolean; visibility: number; receiveShadows: boolean; } /** * @public */ export declare interface RvBasicConfig { type: RvBasicType; args?: Record; text?: string; } /** * @public */ export declare enum RvBasicType { TEXT = "TEXT", CUBE = "CUBE", SPHERE = "SPHERE", CONE = "CONE", PRISM = "PRISM", POLYHEDRON = "POLYHEDRON", TORUS = "TORUS", CYLINDER = "CYLINDER", ICO_SPHERE = "ICO_SPHERE", CAPSULE = "CAPSULE", PLANE = "PLANE", TRANSFORM_NODE = "TRANSFORM_NODE" } /** * @public */ export declare interface RvCamera { enable: boolean; location: RvCameraLocation; config: { easy: boolean; distanceMin: number; distanceMax: number; fov: number; }; } /** * @public */ export declare interface RvCameraLocation { alpha: number; beta: number; radius: number; target: V3; } /** * @public */ export declare interface RvCode { jumpTargetOnClick: string; } /** * @public */ export declare interface RvConfiguration { information: { collapseDescription: boolean; description: string; favorite: boolean; group: string; }; interval: { enable: boolean; enter: number; exit: number; }; jump: { delay: number; onlyOnce: boolean; target: string; }; ui: { theme: Theme; enableStepChangeButton: boolean; enableTopbar: boolean; hideStep: boolean; importantStep: boolean; }; audio: RvAudio; secondAudio: RvAudio; } /** * @public */ export declare interface RvEnvironment { skybox: { background: string; }; light: { intensity: number; diffuseColor: string; specularColor: string; }; ground: { opacityRate: number; baseColor: string; enableOnViewerMode: boolean; enableOnEditorMode: boolean; }; shadow: { enable: boolean; darkness: number; blurOffset: number; blurScale: number; onlyOnGround: boolean; normalBias: number; }; camera: RvCamera; fog: { enable: boolean; density: number; color: string; }; } /** * @public */ export declare interface RvHistory { white: number; } /** * @public */ export declare interface RvLabel { enable: boolean; text: string; alwaysShow: boolean; } /** * @public */ export declare interface RvLocation { position: V3; rotation?: V3; nearMode: boolean; scale: V3; rotationQuaternion?: V4; } /** * @public */ export declare interface RvLoop { rotationSpeed: V3; rotationPivot: V3; slideSpeed: V3; slideDistance: V3; } /** * @public */ export declare interface RvMaterial { general: RvMaterialGeneral; pbr?: RvMaterialPBR; node?: RvMaterialNode; texture: RvMaterialTexture; } /** * @public */ export declare interface RvMaterialGeneral { type: RvMaterialType; isExtracted: boolean; transparencyMode: TransparencyMode; needDepthPrePass: boolean; preset: RvPresetType; } /** * @public */ export declare interface RvMaterialNode { fid: string; inputs: RvMaterialNodeInput[]; } /** * @public */ export declare interface RvMaterialNodeInput { type: NodeMaterialBlockConnectionPointTypes; key: string; value: string | number; range?: [number, number]; } /** * @public */ export declare interface RvMaterialPBR { basic: { albedoColor: string; metallic: number; roughness: number; emissiveColor: string; alpha: number; }; advance: { reflectivityColor: string; ambientColor: string; indexOfRefraction: number; metallicF0Factor: number; reflectionColor: string; }; coat: { enable: boolean; intensity: number; roughness: number; indexOfRefraction: number; useRoughnessFromMainTexture: boolean; clearCoatTexture: string; roughnessTexture: string; bumpTexture: string; enableTint: boolean; tintColor: string; atDistance: number; tintThickness: number; }; } /** * @public */ export declare interface RvMaterialTexture { basic: { albedoTexture: string; metallicRoughnessTexture: string; bumpTexture: string; emissiveTexture: string; opacityTexture: string; ambientTexture: string; reflectionTexture: string; metallicReflectanceTexture: string; refractionTexture: string; reflectivityTexture: string; microSurfaceTexture: string; lightMapTexture: string; detailMapTexture: string; reflectanceTexture: string; tintTexture: string; }; extra: { texture1: string; texture2: string; texture3: string; texture4: string; }; } /** * @public */ export declare enum RvMaterialType { NONE = "NONE", PBR = "PBR", STANDARD = "STANDARD", NODE = "NODE", OTHER = "OTHER", TERRAIN = "TERRAIN", FUR = "FUR", WATER = "WATER", LAVA = "LAVA", SKY = "SKY", BACKGROUND = "BACKGROUND", MULTI = "MULTI", SHADER = "SHADER" } /** * @public */ export declare interface RvMeeting { meetingId: string; status: MeetingStatus; startTime: number; current: RvMeetingCurrent; statistic: RvMeetingStatistic; endTime?: number; } /** * @public */ export declare interface RvMeetingCurrent { presenterId: number; state: { peopleCount: number; }; config: { forceFollow: boolean; clickShareMode: ShareMode; cursorShareMode: ShareMode; }; visitors: number[]; } /** * @public */ export declare class RvMeetingService { static get instance(): RvMeetingService; private constructor(); meetings: RecursiveMap; getRvMeeting(meetingId: string): StoredRhineVar | null; generateId(): string; removeAllMeetings(): void; } /** * @public */ export declare interface RvMeetingStatistic { people: { total: number; }; } /** * @public */ export declare interface RvModel { mid: string; name: string; origin: RvModelOrigin; fid?: string; config?: RvBasicConfig | Record; } /** * @public */ export declare interface RvModelNode { nid: string; name: string; children?: RvModelNode[]; } /** * @public */ export declare enum RvModelOrigin { BASIC = "BASIC", PROVIDE = "PROVIDE", UPLOAD = "UPLOAD" } /** * @public */ export declare class RvModelService { static get instance(): RvModelService; private constructor(); uploadMulti(fileList: FileList | File[] | File | null | undefined, check?: boolean): Promise; addByFid(fid: string, provide?: boolean): string; models: RecursiveMap; get(mid: string): RecursiveObject | undefined; has(mid: string): boolean; hasFid(fid: string): boolean; add(rvModel: RvModel): string; addTransformNode(name?: string): string; remove(mid: string): boolean; generateId(): string; } /** * @public */ export declare interface RvNative { enableAnimation: boolean; playTime: number; startFrame: number; endFrame: number; enableLoop: boolean; speedRatio: number; } /** * @public */ export declare interface RvNode { basic?: RvBasic; location?: RvLocation; material?: RvMaterial; label?: RvLabel; animation?: RvAnimation; code?: RvCode; } /** * @public */ export declare class RvNodeMaterialAnalyzer { static get instance(): RvNodeMaterialAnalyzer; ensure(material: StoredRhineVar, nid: string): Promise; } /** * @public */ export declare class RvNodeService { static get instance(): RvNodeService; private constructor(); initialize(nid: string): void; isInitialized(nid: string): boolean; multiInitialize(nidList: string[]): void; isAllInitialized(nidList: string[]): boolean; copy(fromNid: string, toNid: string): void; delete(nid: string): void; forEachAny(callback: (node: StoredRhineVar, sid: string, nid: string) => void, nidList?: string[], sidList?: string[]): void; forEach(callback: (node: StoredRhineVar, sid: string) => void, nid: string): void; forEachMulti(callback: (nodes: Map>, sid: string) => void, nidList?: string[]): void; forEachMap(callback: (nodes: RecursiveMap, sid: string) => void): void; getCurrentMap(): RecursiveMap; getMap(sid?: string): RecursiveMap | undefined; get(nid: string, sid?: string): StoredRhineVar | undefined; multiGet(sidList?: string[], nidList?: string[]): Map>>; resetAll(): void; } /** * @public */ export declare interface RvPlugin { config: RhineVarMap; debug: RhineVarMap; order: string[]; } /** * @public */ export declare interface RvPluginConfig { id: string; version: string | VersionPoint; enable: { viewer: EnableLevel; editor: EnableLevel; }; } /** * RvPluginDebug * * Example: * * ```ts * { * id: 'example-plugin', * name: 'Example Plugin', * enable: true, * * url: 'http://localhost:8080', * hmr: 'ws://localhost:8081', * * entry: 'index.js', * css: 'index.css', * messages: { * path: 'messages', * support: ['en', 'zh'], * default: 'en' * } * } * ``` * @public */ export declare interface RvPluginDebug { id: string; name: string; enable: boolean; url: string; hmr: string; entry: string; css: string; messages: { path: string; namespace: string; support: Locale[]; default: Locale; }; } /** * @public */ export declare enum RvPresetType { NONE = "NONE", METAL = "METAL", PLASTIC = "PLASTIC", GLASS = "GLASS", WOOD = "WOOD", MIRROR = "MIRROR", CRYSTAL = "CRYSTAL", PAINT = "PAINT", CLOTH = "CLOTH" } /** * @public */ export declare interface RvProject { information: { title: string; description: string; tags: string; }; ui: { theme: Theme; }; playing: { auto: boolean; loop: boolean; interval: number; }; support: { VR: boolean; AR: boolean; MR: boolean; HP: boolean; }; } /** * @public */ export declare class RvProjectService { static get instance(): RvProjectService; private constructor(); state: StoredRhineVar; } /** * 资源元数据接口 * * 描述项目中一个资源的完整元信息。资源是用户可见的文件或程序资源(如材质、贴图)。 * 协同数据中仅存储资源 ID,完整元数据通过 RvResourceService.getMetadata() 从后端获取并缓存。 * * 一个资源可能对应多个文件(如图片资源 + 缩略图文件), * 一个文件也可能对应多个资源(如模型文件内部的多个贴图为 Attach 型资源)。 * * @public */ export declare interface RvResource { /** 关联的文件 ID */ fid: string; /** 资源名称 */ name: string; /** 资源类型: FILE(独立文件资源)或 ATTACH(主资源的内置子资源) */ type: RvResourceType; /** MIME 类型 */ mime: string; /** 预览图 URL */ preview?: string; /** 资源描述信息 */ description?: string; /** Attach 型资源的来源信息,仅当 type 为 ATTACH 时存在 */ from?: { /** 来源文件 ID */ fid: string; /** Attach 类型: TEXTURE | MATERIAL | UV */ type: RvAttachType; /** 资源在文件内部的路径 */ path: string; }; /** 创建时间戳(毫秒) */ createdAt: number; /** 更新时间戳(毫秒) */ updatedAt: number; /** 扩展数据 */ extra?: Record; } /** * 资源协同数据服务 * * 管理协同数据中的 resourceId 列表,以及本地资源和文件元数据缓存。 * * @public */ export declare class RvResourceService { static get instance(): RvResourceService; private constructor(); resources: StoredRhineVar; private metadataCache; private fileToResourceMap; /** * 添加 resourceId 到协同数据 * * 如果资源元数据已在缓存中,会自动同步文件元数据并触发下载 */ add(resourceId: string): void; /** * 从协同数据移除 resourceId,并清理 fileToResourceMap 中的映射 */ remove(resourceId: string): boolean; /** * 检查 resourceId 是否在列表中 */ has(resourceId: string): boolean; /** * 获取缓存的资源元数据 */ getMetadata(resourceId: string): Resource | undefined; /** * 通过 fileId 获取对应的资源元数据(返回第一个匹配的资源) * * @deprecated 当一个文件对应多个资源时,此方法只返回第一个。建议使用 getAllMetadataByFileId() */ getMetadataByFileId(fileId: string): Resource | undefined; /** * 通过 fileId 获取所有对应的资源元数据列表 */ getAllMetadataByFileId(fileId: string): Resource[]; /** * 通过 fileId 获取所有对应的 resourceId 列表(包含后端缓存中的所有资源) */ getResourceIdsByFileId(fileId: string): string[]; /** * 通过 fileId 获取协同数据中已添加的对应 resourceId 列表 * * 与 getResourceIdsByFileId 不同,此方法仅返回已存在于协同数据 resources 中的资源, * 排除仅在后端缓存但未添加到协同数据的资源。 */ getAddedResourceIdsByFileId(fileId: string): string[]; /** * 设置资源元数据缓存 */ setMetadata(resourceId: string, metadata: Resource): void; private fileMetadataCache; /** * 添加文件元数据到本地缓存,并发布 ADD 事件 */ addFile(fileId: string, metadata?: ResourceFileInfo): void; /** * 从本地缓存移除文件元数据,并发布 REMOVE 事件 */ removeFile(fileId: string): boolean; /** * 检查文件是否在本地缓存中 */ hasFile(fileId: string): boolean; /** * 获取缓存的文件元数据 */ getFileMetadata(fileId: string): ResourceFileInfo | undefined; /** * 设置文件元数据缓存(不触发事件) */ setFileMetadata(fileId: string, metadata: ResourceFileInfo): void; /** * 获取所有文件 ID 列表 */ getFileIds(): string[]; /** * 获取文件下载 URL(通过后端签名) */ getDownloadUrl(fileId: string): Promise; /** * 从后端同步资源列表到本地缓存 * * 通过 listResources 一次性拉取后端完整资源列表, * 仅填充本地元数据缓存,不自动添加到协同数据。 * 需要手动调用 add() 方法将资源添加到协同数据。 * * 同步完成后会自动清理孤立资源(没有对应文件的资源) */ syncFromBackend(): Promise; /** * 获取所有后端资源的元数据列表(从本地缓存) * * @returns 资源元数据数组 */ getAllMetadata(): Resource[]; /** * 获取所有未添加到协同数据的资源列表 * * @returns 未添加的资源元数据数组 */ getUnaddedResources(): Resource[]; /** * 订阅资源列表变化事件(ADD/REMOVE) */ subscribe(subscriber: RvResourceServiceSubscriber): () => void; unsubscribe(subscriber: RvResourceServiceSubscriber): void; subscribeSingle(resourceId: string, subscriber: RvResourceServiceSubscriber): () => void; unsubscribeSingle(resourceId: string, subscriber: RvResourceServiceSubscriber): void; /** * 订阅文件变化事件(ADD/REMOVE) */ subscribeFile(subscriber: RvResourceServiceSubscriber): () => void; unsubscribeFile(subscriber: RvResourceServiceSubscriber): void; } /** * @public */ export declare enum RvResourceServiceEventType { ADD = "ADD", REMOVE = "REMOVE" } /** * @public */ export declare type RvResourceServiceSubscriber = (type: RvResourceServiceEventType, resourceId: string) => void; /** * @public */ export declare enum RvResourceType { FILE = "FILE", ATTACH = "ATTACH" } /** * 场景中的模型树节点的协同数据 * * 记录了这个节点的信息,来源,嵌套关系 * * @public */ export declare interface RvSceneNode { nid: string; name: string; parent: string; source: { mid: string; name: string; fingerprint?: string; copy?: string; }; deleted?: boolean; } /** * @public */ export declare class RvSceneService { static get instance(): RvSceneService; private constructor(); scene: RecursiveMap; isDescendant(nid: string, of: string): boolean; /** * 是否存在来自指定mid的节点 * * @param mid */ hasNodeFromMid(mid: string): boolean; isAncestor(nid: string, of: string): boolean; isParent(nid: string, of: string): boolean; isChild(nid: string, of: string): boolean; newTransformNode(parent?: string, name?: string): string; move(nid: string, newParent?: string): void; delete(nid: string): void; getDescendantsWithSelf(nid: string): string[]; generateId(mid: string, layer?: number, index?: number): string; generateIdAndNameForCopy(fromNid: string): { nid: string; name: string; from: RvSceneNode; base: RvSceneNode; }; getSortedSceneNodeWithRelatedInfoList(): SceneNodeWithRelatedInfo[]; } /** * @public */ export declare interface RvSeparate { groups: RhineVarArray>; } /** * 材质分离协同数据服务 * * 管理材质分离相关的 RhineVar 协同数据,记录哪些节点共享同一材质。 * 当 GLB 文件中多个 mesh 共用材质时,需要记录这些共享关系, * 以便在用户编辑某个节点材质时进行按需分离。 * * @remarks * 数据结构 `RvSeparate.groups: string[][]`,每个 group 是一组共享同一材质的节点 nid 列表。 * * @example * ```typescript * // 检查节点是否与其他节点共享材质 * if (RvSeparateService.instance.has(nid)) { * // 需要分离材质 * } * ``` * * @see {@link RsSeparateService} 渲染层材质分离服务 */ export declare class RvSeparateService { private static _instance; /** * 获取单例实例 * * @returns 服务单例 */ static get instance(): RvSeparateService; private constructor(); /** * 材质分离协同数据 * * 包含 `groups` 字段,记录所有共享材质的节点分组。 */ separate: StoredRhineVar; /** * 检查节点是否在任意材质分离组中 * * 若返回 true,表示该节点与其他节点共享材质,编辑前需要进行材质分离。 * * @param nid - 节点唯一标识符 * @returns 是否在分离组中 */ has(nid: string): boolean; /** * 将新节点与源节点加入同一材质分离组 * * 用于复制节点时,确保复制出的节点与原节点共享材质分离信息。 * 如果源节点已在某个分离组中,则将新节点加入该组; * 否则创建一个新的分离组包含这两个节点。 * * @param fromNid - 源节点 nid * @param newNid - 新复制的节点 nid */ addCopyToGroup(fromNid: string, newNid: string): void; } /** * @public */ export declare interface RvStep { name: string; sid: string; nodes: RhineVarMap; configuration: RvConfiguration; environment: RvEnvironment; } /** * @public */ export declare class RvStepService { /** * @public */ static get instance(): RvStepService; private constructor(); order: RecursiveArray; steps: RecursiveMap; get(sid: string): RecursiveObject | undefined; multiGet(sidList?: string[]): Map>; /** * Add a new step * * @param from - Copy all step data from another step * @param index - Insert the new step at this index, default to the end */ add(from?: string, index?: number): string; move(sid: string, to: number): boolean; remove(sid: string): boolean; forEach(callback: (rvStep: StoredRhineVar, sid: string) => void): void; getStepOptions(withDisable?: boolean): StepOptions; getStepIndex(sid: string): number; getStepByIndex(index: number): StoredRhineVar | undefined; getCurrentStep(): StoredRhineVar; generateId(): string; } /** * RvPath 路径工具类 * 提供 RvPath 的创建、转换、访问和比较等功能 * @public */ export declare const RvUtils: { makeRvPath: typeof makeRvPath; makeRvPathString: typeof makeRvPathString; ensureRvPath: typeof ensureRvPath; ensureRvPathString: typeof ensureRvPathString; getByRvPath: typeof getByRvPath; setByRvPath: typeof setByRvPath; deleteByRvPath: typeof deleteByRvPath; joinRvPath: typeof joinRvPath; joinRvPathString: typeof joinRvPathString; checkRvPathOverlay: typeof checkRvPathOverlay; checkRvPathStartWith: typeof checkRvPathStartWith; checkAnyRvPathOverlay: typeof checkAnyRvPathOverlay; checkRvPathSame: typeof checkRvPathSame; checkAnyRvPathSame: typeof checkAnyRvPathSame; isChangeEventType: typeof isChangeEventType; }; /** * @public */ export declare interface RvVersion { code: number; label: string; } declare function scaleV3(ratio: number, v: V3): V3; declare function scaleV4(ratio: number, v: V4): V4; /** * @public */ export declare interface SceneNodeWithRelatedInfo extends RvSceneNode { children: string[]; parents: string[]; } /** * @public */ export declare class SceneService { static get instance(): SceneService; private constructor(); /** * UI场景模型树拖拽中的节点信息 */ dragState: { nid: string; x: number; y: number; offsetX: number; offsetY: number; }; newTransformNode(parent?: string, name?: string): void; /** * 批量复制 * * @param fromNidList * @param onlyCurrent * @param withNodeData */ batchCopy(fromNidList: string[], onlyCurrent?: boolean, withNodeData?: boolean): string[]; /** * 复制指定节点 * * @param fromNid - 从指定nid的模型复制 * @param onlyCurrent - 是否只复制当前节点 (为false则递归复制子元素) * @param withNodeData - 是否同时复制节点数据 */ copy(fromNid: string, onlyCurrent?: boolean, withNodeData?: boolean): string; /** * 内部复制实现 * * @param fromNid - 从指定nid的模型复制 * @param onlyCurrent - 是否只复制当前节点 (为false则递归复制子元素) * @param withNodeData - 是否同时复制节点数据 * @param newParentNid - 新父节点nid (内部递归使用) */ private copyInternal; /** * 批量删除节点 * * @param nidList - 要删除的节点nid列表 */ batchDelete(nidList: string[]): void; /** * 删除指定节点及其所有子节点 * * @param nid - 要删除的节点nid */ delete(nid: string): void; /** * 内部删除实现 * * @param nid - 要删除的节点nid */ private deleteInternal; } /** * @public */ declare interface Screen_2 { size: ScreenSize; scale: number; shadowAround: boolean; focusMode: FocusMode; showBabylonConsole: boolean; } export { Screen_2 as Screen } /** * @public */ export declare enum ScreenSize { XS = "XS", SM = "SM", MD = "MD", LG = "LG", XL = "XL" } declare enum ScriptStatus { Idle = "idle", Loading = "loading", Ready = "ready", Error = "error" } /** * @public */ export declare function ScrollBar(props: ScrollBarProps): JSX.Element; /** * @public */ export declare interface ScrollBarProps extends Omit, 'children'> { children: ReactNode | undefined; className?: string; innerClassName?: string; barPaddingStart?: string; barPaddingEnd?: string; } /** * @public */ export declare type SelectedSubscriber = (value: RsSelectionNodeInfo[]) => void; /** * 根据路径设置对象中的值 * @param source - 源对象 * @param path - 设置路径 * @param value - 要设置的值 * @example * ```ts * const obj = { a: { b: 1 } } * RvUtils.setByRvPath(obj, "a.b", 2) // obj.a.b === 2 * ``` */ declare function setByRvPath(source: StoredRhineVar, path: string | RvPath, value: unknown): void; /** * @public */ export declare class ShadowAnimation { static get instance(): ShadowAnimation; private constructor(); play(data: ShadowAnimationData, duration?: number, quickMode?: boolean): void; enable(value: boolean, duration?: number, quickMode?: boolean): void; darkness(value: number, duration?: number, quickMode?: boolean): void; blurOffset(value: number, duration?: number, quickMode?: boolean): void; blurScale(value: number, duration?: number, quickMode?: boolean): void; onlyOnGround(value: boolean, duration?: number, quickMode?: boolean): void; normalBias(value: number, duration?: number, quickMode?: boolean): void; } /** * @public * 定义阴影动画数据接口 */ declare interface ShadowAnimationData { enable?: boolean; darkness?: number; blurOffset?: number; blurScale?: number; onlyOnGround?: boolean; normalBias?: number; } /** * @public */ export declare enum ShareMode { NONE = "NONE", SELF = "SELF", ALL = "ALL" } /** * @public */ export declare type ShowAttributeContextMenu = (options: ShowAttributeContextMenuOptions) => void; /** * @public */ export declare function showAttributeContextMenu(options: ShowAttributeContextMenuOptions): void; /** * @public */ export declare interface ShowAttributeContextMenuOptions { event: MouseEvent_2; label?: string; copy?: () => void; batchApply?: () => void; jumpToLearn?: () => void; reset?: () => void; } /** * @public */ export declare class SkyboxAnimation { static get instance(): SkyboxAnimation; private constructor(); play(data: { background?: Color4 | Color3 | string; }, duration?: number, quickMode?: boolean): void; background(color: Color4 | Color3 | string, duration?: number, quickMode?: boolean): void; } /** * @public */ export declare function sleep(time: number): Promise; /** * @public */ export declare class SpaceService { static get instance(): SpaceService; page: Page; screen: Screen_2; private constructor(); /** * @public */ updateScreenSize(): void; /** * @public */ subscribeStepChange(subscriber: StepChangeSubscriber): void; /** * @public */ unsubscribeStepChange(subscriber: StepChangeSubscriber): void; /** * @public */ setSid(sid: string): void; /** * @public */ setScreenSize(size: ScreenSize): void; /** * @public */ isEditorPage(type?: PageType): boolean; /** * @public */ isBoxMode(mode?: PageMode): boolean; /** * @public */ isFullMode(mode?: PageMode): boolean; } /** * @public */ export declare type SpanProps = DetailedHTMLProps, HTMLSpanElement>; /** * @public */ export declare type SpanPropsSimple = Omit; declare function splitName(name: string): [string, string]; /** * @public */ export declare class StaticClassInstantiationError extends Error { constructor(className: string); } /** * @public */ export declare interface Status { Authenticated: boolean; DataSynchronized: boolean; SyncInitialized: boolean; RsInitialized: boolean; AllInitialized: boolean; PluginEnabled: boolean; PluginPreLoaded: boolean; FileLoaded: boolean; ModelLoaded: boolean; SceneLoaded: boolean; PluginPreRendered: boolean; Rendered: boolean; Shown: boolean; } /** * @public */ export declare type StatusChangeSubscriber = (value: boolean) => void; /** * @public */ export declare class StatusService { static get instance(): StatusService; private constructor(); status: Status; subscribeAuthenticated(subscriber: StatusChangeSubscriber): () => void; unsubscribeAuthenticated(subscriber: StatusChangeSubscriber): void; afterAuthenticated(subscriber: StatusChangeSubscriber): void; waitAuthenticated(): Promise; subscribeDataSynchronized(subscriber: StatusChangeSubscriber): () => void; unsubscribeDataSynchronized(subscriber: StatusChangeSubscriber): void; afterDataSynchronized(subscriber: StatusChangeSubscriber): void; waitDataSynchronized(): Promise; subscribeSyncInitialized(subscriber: StatusChangeSubscriber): () => void; unsubscribeSyncInitialized(subscriber: StatusChangeSubscriber): void; afterSyncInitialized(subscriber: StatusChangeSubscriber): void; waitSyncInitialized(): Promise; subscribeRsInitialized(subscriber: StatusChangeSubscriber): () => void; unsubscribeRsInitialized(subscriber: StatusChangeSubscriber): void; afterRsInitialized(subscriber: StatusChangeSubscriber): void; waitRsInitialized(): Promise; subscribeAllInitialized(subscriber: StatusChangeSubscriber): () => void; unsubscribeAllInitialized(subscriber: StatusChangeSubscriber): void; afterAllInitialized(subscriber: StatusChangeSubscriber): void; waitAllInitialized(): Promise; subscribePluginEnabled(subscriber: StatusChangeSubscriber): () => void; unsubscribePluginEnabled(subscriber: StatusChangeSubscriber): void; afterPluginEnabled(subscriber: StatusChangeSubscriber): void; waitPluginEnabled(): Promise; subscribePluginPreLoaded(subscriber: StatusChangeSubscriber): () => void; unsubscribePluginPreLoaded(subscriber: StatusChangeSubscriber): void; afterPluginPreLoaded(subscriber: StatusChangeSubscriber): void; waitPluginPreLoaded(): Promise; subscribeFileLoaded(subscriber: StatusChangeSubscriber): () => void; unsubscribeFileLoaded(subscriber: StatusChangeSubscriber): void; afterFileLoaded(subscriber: StatusChangeSubscriber): void; waitFileLoaded(): Promise; subscribeModelLoaded(subscriber: StatusChangeSubscriber): () => void; unsubscribeModelLoaded(subscriber: StatusChangeSubscriber): void; afterModelLoaded(subscriber: StatusChangeSubscriber): void; waitModelLoaded(): Promise; subscribeSceneLoaded(subscriber: StatusChangeSubscriber): () => void; unsubscribeSceneLoaded(subscriber: StatusChangeSubscriber): void; afterSceneLoaded(subscriber: StatusChangeSubscriber): void; waitSceneLoaded(): Promise; subscribePluginPreRendered(subscriber: StatusChangeSubscriber): () => void; unsubscribePluginPreRendered(subscriber: StatusChangeSubscriber): void; afterPluginPreRendered(subscriber: StatusChangeSubscriber): void; waitPluginPreRendered(): Promise; subscribeRendered(subscriber: StatusChangeSubscriber): () => void; unsubscribeRendered(subscriber: StatusChangeSubscriber): void; afterRendered(subscriber: StatusChangeSubscriber): void; waitRendered(): Promise; subscribeShown(subscriber: StatusChangeSubscriber): () => void; unsubscribeShown(subscriber: StatusChangeSubscriber): void; afterShown(subscriber: StatusChangeSubscriber): void; waitShown(): Promise; } /** * @public */ export declare abstract class StepAttribute extends BaseAttribute { type: AttributeType; get targetSid(): string; get targetSidList(): string[]; generate(sid?: string): T; multiGenerate(sidList?: string[]): Map; readonly sameGenerateForStepsMode = true; initialize(): void; isInitialized(): boolean; mark(path: string | RvPath, sid?: string): void; multiMark(path: string | RvPath, sidList?: string[]): void; get(sid?: string): StoredRhineVar | undefined; multiGet(sidList?: string[]): Map>; /** * 获取指定 Step 的局部数据 * @param paths * @param sid */ getPartial(paths: (string | RvPath)[], sid?: string): PartialData; /** * 获取多个 Step 的局部数据 * @param paths * @param sidList */ multiGetPartial(paths: (string | RvPath)[], sidList?: string[]): Map; set(path: string | RvPath, value: unknown, sid?: string): void; multiSet(path: string | RvPath, value: unknown, sidList?: string[]): void; /** * 设置局部数据到指定 Step * @param pd * @param sid */ setPartial(pd: PartialData, sid?: string): void; /** * 设置局部数据到多个指定 Step * @param pd * @param sidList */ multiSetPartial(pd: PartialData, sidList?: string[]): void; read(sid?: string): T | StoredRhineVar; multiRead(sidList?: string[]): Map>; /** * 读取指定 Step 的局部数据 * @param paths * @param sid */ readPartial(paths: (string | RvPath)[], sid?: string): PartialData; /** * 读取多个 Step 的局部数据 * @param paths * @param sidList */ multiReadPartial(paths: (string | RvPath)[], sidList?: string[]): Map; edit(path: string | RvPath, value: unknown, sid?: string): void; multiEdit(path: string | RvPath, value: unknown, sidList?: string[]): void; /** * 编辑指定 Step 的局部数据 * @param pd * @param sid */ editPartial(pd: PartialData, sid?: string): void; /** * 编辑多个 Step 的局部数据 * @param pd * @param sidList */ multiEditPartial(pd: PartialData, sidList?: string[]): void; subscribeTarget(subscriber: StepAttributeTargetSubscriber): () => void; unsubscribeTarget(subscriber: StepAttributeTargetSubscriber): void; } /** * @public */ export declare type StepAttributeTargetSubscriber = (type: TChangeType, path: RvPath, value: unknown, oldValue: unknown, sid: string) => void; /** * @public */ export declare function StepBlockSelect(props: StepBlockSelectProps): JSX.Element; /** * @public */ export declare interface StepBlockSelectProps extends DivPropsSimple { value: string[]; onChange: (value: string[]) => void; } /** * @public */ export declare type StepChangeSubscriber = (sid: string, step: StoredRhineVar, lastSid: string, lastStep: RvStep | undefined) => void; /** * @public */ export declare type StepOptions = { label: string; value: string; }[]; declare function stopPropagationListener(e: ReactEvent): void; /** * @public */ export declare type SupportAnimationTarget = Node_2 | Scene | Material | NodeMaterialBlock | ShadowGenerator; /** * 同步服务 - 管理多人协同数据的核心服务 * * @description * SyncService 是管理 Next Flow 所有协同数据的基础服务。 * 它负责初始化和协调 RhineVar 同步系统,管理客户端连接, * 并编排所有子服务,包括文件、资源、模型、场景和插件等。 * * 该服务采用单例模式,首次访问时自动初始化。 * 所有协同状态存储在 `state` 属性中,这是一个 RhineVar 代理对象, * 会实时同步到所有连接的客户端。 * * @example * ```typescript * // 获取同步服务实例 * const syncService = SyncService.instance * * // 为新实体生成唯一 ID * const newId = syncService.generateId('model') * * // 访问协同状态 * const steps = syncService.state.steps * ``` * * @public */ export declare class SyncService { /** * 启用 RhineVar 内部日志 * * @description * 启用时,打开 RhineVar 操作的详细日志。 * 用于调试同步问题。 * * @defaultValue false * @public */ ENABLE_RHINE_VAR_LOG: boolean; /** * 获取 SyncService 的单例实例 * * @description * 返回 SyncService 的单例实例。如果不存在则创建新实例。 * 服务在首次访问时自动开始初始化。 * * @returns SyncService 单例实例 * * @example * ```typescript * const syncService = SyncService.instance * ``` * * @public */ static get instance(): SyncService; /** * RhineVar 同步服务器的 WebSocket 地址 * * @description * 用于连接 RhineVar 同步服务器的 URL。 * 使用当前页面的项目 ID 构造而成。 * * @public */ private getUrl; private getToken; /** * RhineVar 协同状态对象 * * @description * 在所有客户端之间同步的根协同状态对象。 * 该对象包含所有项目数据,包括场景步骤、文件、资源、模型、场景节点等。 * 对此状态的任何修改都会自动同步到所有连接的客户端。 * * 配置选项: * - 覆写模式(如果启用) * - 撤销管理器用于历史记录跟踪 * - 协作感知用于跟踪其他用户 * * @see {@link RvBase} 查看完整的状态结构 * * @example * ```typescript * // 访问场景步骤 * const steps = SyncService.instance.state.steps * * // 访问资源 * const resources = SyncService.instance.state.resources * * // 等待同步完成 * await SyncService.instance.state.waitSynced() * ``` * * @public */ state: RecursiveObject; /** * 客户端唯一标识符 * * @description * RhineVar 同步系统分配给此客户端的唯一数字 ID。 * 用于在所有连接的客户端中识别此客户端,并生成唯一的实体 ID。 * * @public */ clientId: number; /** * 使用指定前缀生成唯一 ID * * @description * 通过组合以下内容生成唯一标识符: * - 提供的前缀 * - 该前缀的自增计数器 * - 当前客户端 ID * * 这确保了 ID 在所有客户端和实体类型之间都是唯一的。 * * @param prefix - 用于 ID 的前缀(例如:'model'、'step'、'file') * @returns 格式为 `{prefix}{counter}-{clientId}` 的唯一 ID 字符串 * * @example * ```typescript * // 生成唯一的模型 ID * const modelId = SyncService.instance.generateId('model') * // 返回: "model0-12345" (其中 12345 是客户端 ID) * * // 再次生成模型 ID * const modelId2 = SyncService.instance.generateId('model') * // 返回: "model1-12345" * * // 生成场景步骤 ID * const stepId = SyncService.instance.generateId('step') * // 返回: "step0-12345" * ``` * * @public */ generateId(prefix: string): string; /** * 重置所有协同数据 * * @description * **⚠️ 危险操作:这是一个破坏性操作!** * * 通过删除底层 RhineVar YMap 中的状态,完全清除所有协同数据。 * 这将影响所有连接的客户端,并且无法撤销。 * * 请极其谨慎使用,通常仅用于: * - 开发/测试目的 * - 从损坏的状态中恢复 * - 经过用户确认的有意项目重置 * * @returns 如果重置成功返回 `true`,如果未找到基础映射表返回 `false` * * @example * ```typescript * // 重置所有数据(请谨慎使用!) * const success = SyncService.instance.reset() * if (success) { * console.log('All collaborative data has been cleared') * } * ``` * * @public */ reset(): boolean; transact(callback: () => void): void; } /** * @public */ export declare class TargetMultiNodeService { static get instance(): TargetMultiNodeService; private constructor(); sid: string; nid: string; nidList: string[]; subscribe(subscriber: TargetMultiNodeSubscriber): () => void; unsubscribe(subscriber: TargetMultiNodeSubscriber): void; } /** * @public */ export declare type TargetMultiNodeSubscriber = (type: TChangeType, path: RvPath, value: unknown, oldValue: unknown, sid: string, nid: string, nidList: string[]) => void; /** * @public */ export declare class TargetNodeService { static get instance(): TargetNodeService; private constructor(); state: StoredRhineVar | null; sid: string; nid: string; subscribe(subscriber: TargetNodeSubscriber): () => void; unsubscribe(subscriber: TargetNodeSubscriber): void; } /** * @public */ export declare type TargetNodeSubscriber = (type: TChangeType, path: RvPath, value: unknown, oldValue: unknown, sid: string, nid: string, rvNode: StoredRhineVar | null) => void; /** * @public */ export declare class TargetStepService { static get instance(): TargetStepService; private constructor(); /** * Target step state */ sid: string; state: StoredRhineVar; subscribe(subscriber: TargetStepSubscriber): () => void; unsubscribe(subscriber: TargetStepSubscriber): void; subscribeNode(subscriber: TargetNodeSubscriber): () => void; unsubscribeNode(subscriber: TargetNodeSubscriber): void; /** * Set value by path * * @param path - * @param value - */ set(path: string | RvPath, value: T): void; /** * Get value by path * * @param path - */ get(path: string | RvPath): T | undefined; isValueChange(type: TChangeType): boolean; } /** * @public */ export declare type TargetStepSubscriber = (type: TChangeType, path: RvPath, value: unknown, oldValue: unknown, sid: string) => void; /** * @public */ export declare enum TChangeType { SYNC = "SYNC", STEP = "STEP", SELECT = "SELECT", ADD = "ADD", UPDATE = "UPDATE", DELETE = "DELETE" } /** * @public */ export declare interface TextureInfo { fid: string; localUrl: string; texture: Texture; } /** * @public */ export declare enum Theme { DEFAULT = "DEFAULT", BACKGROUND = "BACKGROUND", LIGHT = "LIGHT", DARK = "DARK" } /** * @public */ export declare enum ThemeColor { GREEN = "GREEN", PURPLE = "PURPLE", BLUE = "BLUE", PINK = "PINK" } /** * @public */ export declare function ThemeRoot(props: ThemeRootProps): JSX.Element; /** * @public */ export declare interface ThemeRootProps extends DivProps { theme?: Theme.LIGHT | Theme.DARK; themeColor?: ThemeColor; themeShape?: ThemeShape; } /** * @public */ export declare class ThemeService { static get instance(): ThemeService; private constructor(); state: ThemeState; updateBackground(): void; updateBackgroundByColor(color: string): void; isDarkTheme(): boolean; } /** * @public */ export declare enum ThemeShape { GENERAL = "GENERAL", RHINE = "RHINE" } /** * @public */ export declare interface ThemeState { theme: Theme; color: ThemeColor; shape: ThemeShape; } /** * @public */ export declare function throttle void>(func: T, wait: number): T; /** * @public */ export declare const TimeUtils: { convertTimeText: typeof convertTimeText; formatDateTo17Digits: typeof formatDateTo17Digits; formatDuration: typeof formatDuration; }; declare function to3n(bn: number): string; declare function toArray(v: V3 | V4): number[]; declare function toArrayWithRound4(v: V3 | V4, n?: number): number[]; declare function toDegrees(angle: number): number; /** * @public */ export declare function toEuler(quaternion: Quaternion): Vector3; declare function toEulerDegrees(v: V4): V3; declare function toEulerRadians(v: V4): V3; /** * 360度制欧拉角转四元数 * @public */ export declare function toQuaternion(x: number, y: number, z: number): Quaternion; declare function toQuaternionVector(v: V4): Quaternion; declare function toRadians(angle: number): number; declare function toVector3(v: V3): Vector3; /** * @public */ export declare enum TransparencyMode { OPAQUE = "OPAQUE", ALPHA_TEST = "ALPHA_TEST", ALPHA_BLEND = "ALPHA_BLEND", ALPHA_TEST_AND_BLEND = "ALPHA_TEST_AND_BLEND" } declare function trySetClipboard(url: string): Promise; /** * @public */ export declare function UploadButtonAndList(props: UploadButtonAndListProps): JSX.Element; /** * @public */ export declare interface UploadButtonAndListProps { uploadText: string; accept: string[]; modelMode?: boolean; } /** * @public */ export declare const UrlUtils: { getParam: typeof getParam; getHashParam: typeof getHashParam; check: typeof check; copyCurrentUrlToClipboard: typeof copyCurrentUrlToClipboard; copyText: typeof copyText; trySetClipboard: typeof trySetClipboard; extractFilenameFromUrl: typeof extractFilenameFromUrl; }; /** * @public */ export declare function useAllSelectedInfo(): { selected: RsSelectionNodeInfo[]; materialInfo: RsSelectionMaterialInfo; last: RsSelectionNodeInfo | null; }; /** * @public */ export declare function useGlobalAttribute(path?: string | RvPath): { state: T | StoredRhineVar; path: string | RvPath; targetGlobalAttribute: GlobalAttribute; initialize: () => void; isInitialized: () => boolean; mark: (path: string | RvPath) => void; get: () => RecursiveCrossRhineVar | undefined; set: (path: string | RvPath, value: unknown) => void; read: () => T | RecursiveCrossRhineVar; edit: (path: string | RvPath, value: unknown) => void; getPartial: (paths: (string | RvPath)[]) => PartialData; setPartial: (pd: PartialData) => void; readPartial: (paths: (string | RvPath)[]) => PartialData; editPartial: (pd: PartialData) => void; }; /** * @public */ export declare function useLastSelectedInfo(): RsSelectionNodeInfo | null; /** * @public */ export declare interface UserAuth { token: string; refreshToken: string; ip: string; timestamp: number; } /** * @public */ export declare interface UserInfo { uid: string; name: string; phone: string; description: string; headIcon: string; permission: string; } /** * @public */ export declare class UserService { static get instance(): UserService; private constructor(); auth: UserAuth; info: UserInfo; clear(): void; } /** * @public */ export declare function useScript(src: string): ScriptStatus; /** * @public */ export declare function useSelectedInfo(): RsSelectionNodeInfo[]; /** * @public */ export declare function useSelectedMaterialInfo(): RsSelectionMaterialInfo; /** * @public */ export declare function useStepOptions(withDisable?: boolean): StepOptions; /** * @public */ export declare function useTargetNodeAttribute(path?: string | RvPath): { state: T | StoredRhineVar; path: string | RvPath; sid: string; nid: string; nidList: string[]; targetNodeAttribute: NodeAttribute; initialize: (nid?: string) => void; isInitialized: (nid?: string) => boolean; multiInitialize: (nidList?: string[]) => void; isAllInitialized: (nidList?: string[]) => boolean; mark: (path: string | RvPath, sid?: string, nid?: string) => void; multiMark: (path: string | RvPath, sidList?: string[], nidList?: string[]) => void; get: (sid?: string, nid?: string) => RecursiveCrossRhineVar | undefined; multiGet: (sidList?: string[], nidList?: string[]) => Map>>; set: (path: string | RvPath, value: unknown, sid?: string, nid?: string) => void; multiSet: (path: string | RvPath, value: unknown, sidList?: string[], nidList?: string[]) => void; read: (sid?: string, nid?: string) => T | RecursiveCrossRhineVar; multiRead: (sidList?: string[], nidList?: string[]) => Map>>; edit: (path: string | RvPath, value: unknown, sid?: string, nid?: string) => void; multiEdit: (path: string | RvPath, value: unknown, sidList?: string[], nidList?: string[]) => void; getPartial: (paths: (string | RvPath)[], sid?: string, nid?: string) => PartialData; multiGetPartial: (paths: (string | RvPath)[], sidList?: string[], nidList?: string[]) => Map>; setPartial: (pd: PartialData, sid?: string, nid?: string) => void; multiSetPartial: (pd: PartialData, sidList?: string[], nidList?: string[]) => void; readPartial: (paths: (string | RvPath)[], sid?: string, nid?: string) => PartialData; multiReadPartial: (paths: (string | RvPath)[], sidList?: string[], nidList?: string[]) => Map>; editPartial: (pd: PartialData, sid?: string, nid?: string) => void; multiEditPartial: (pd: PartialData, sidList?: string[], nidList?: string[]) => void; subscribe: (subscriber: NodeAttributeTargetSubscriber) => () => void; unsubscribe: (subscriber: NodeAttributeTargetSubscriber) => void; }; /** * @public */ export declare function useTargetStepAttribute(path?: string | RvPath): { state: T | StoredRhineVar; path: string | RvPath; sid: string; targetStepAttribute: StepAttribute; initialize: () => void; isInitialized: () => boolean; mark: (path: string | RvPath, sid?: string) => void; multiMark: (path: string | RvPath, sidList?: string[]) => void; get: (sid?: string) => RecursiveCrossRhineVar | undefined; multiGet: (sidList?: string[]) => Map>; set: (path: string | RvPath, value: unknown, sid?: string) => void; multiSet: (path: string | RvPath, value: unknown, sidList?: string[]) => void; read: (sid?: string) => T | RecursiveCrossRhineVar; multiRead: (sidList?: string[]) => Map>; edit: (path: string | RvPath, value: unknown, sid?: string) => void; multiEdit: (path: string | RvPath, value: unknown, sidList?: string[]) => void; getPartial: (paths: (string | RvPath)[], sid?: string) => PartialData; multiGetPartial: (paths: (string | RvPath)[], sidList?: string[]) => Map; setPartial: (pd: PartialData, sid?: string) => void; multiSetPartial: (pd: PartialData, sidList?: string[]) => void; readPartial: (paths: (string | RvPath)[], sid?: string) => PartialData; multiReadPartial: (paths: (string | RvPath)[], sidList?: string[]) => Map; editPartial: (pd: PartialData, sid?: string) => void; multiEditPartial: (pd: PartialData, sidList?: string[]) => void; subscribe: (subscriber: StepAttributeTargetSubscriber) => () => void; unsubscribe: (subscriber: StepAttributeTargetSubscriber) => void; }; /** * @public */ export declare interface V2 { x: number; y: number; } /** * @public */ export declare interface V3 { x: number; y: number; z: number; } /** * @public */ export declare interface V4 { x: number; y: number; z: number; w: number; } /** * @public */ export declare const VectorUtils: { xyToArray: typeof xyToArray; xyzToArray: typeof xyzToArray; xyzwToArray: typeof xyzwToArray; scaleV3: typeof scaleV3; radiansToDegrees: typeof radiansToDegrees; degreeToRadians: typeof degreeToRadians; radiansToQuaternion: typeof radiansToQuaternion; degreesToQuaternion: typeof degreesToQuaternion; toVector3: typeof toVector3; fromVector3: typeof fromVector3; withRound: typeof withRound; isFiniteVector: typeof isFiniteVector; noZero: typeof noZero; scaleV4: typeof scaleV4; toQuaternionVector: typeof toQuaternionVector; toEulerRadians: typeof toEulerRadians; toEulerDegrees: typeof toEulerDegrees; toArray: typeof toArray; fromQuaternion: typeof fromQuaternion; toArrayWithRound4: typeof toArrayWithRound4; }; /** * @public */ export declare enum VersionPoint { LATEST_STABLE = "LATEST_STABLE", LATEST_NIGHTLY = "LATEST_NIGHTLY", LATEST_CANARY = "LATEST_CANARY" } /** * @public */ export declare interface ViewPlugin extends BasePlugin { view: MixView; onRender?: () => void; } /** * @public */ export declare interface WithOption { subscriber: T; option?: NativeEventSubscribeOption; } declare function withRound(v: V3, n?: number): V3; declare function xyToArray(data: V2 | null | undefined, round?: number, defaultValue?: [number, number]): [number, number]; declare function xyzToArray(data: V3 | null | undefined, round?: number, defaultValue?: [number, number, number]): [number, number, number]; declare function xyzwToArray(data: V4 | null | undefined, round?: number, defaultValue?: [number, number, number, number]): [number, number, number, number]; export declare const spaceService: SpaceService export declare const statusService: StatusService export declare const pluginService: PluginService export declare const themeService: ThemeService export declare const internationalizationService: InternationalizationService export declare const meetingService: MeetingService export declare const userService: UserService export declare const messageService: MessageService export declare const localDataService: LocalDataService export declare const ossUploadService: OssUploadService export declare const resourceService: ResourceService export declare const firstLoadService: FirstLoadService export declare const firstLoadModelService: FirstLoadModelService export declare const dialogService: DialogService export declare const nativeEventService: NativeEventService export declare const pluginContainerService: PluginContainerService export declare const sceneService: SceneService export declare const contextMenuService: ContextMenuService export declare const batchApplyService: BatchApplyService export declare const cameraConfigurationAnimation: CameraConfigurationAnimation export declare const cameraLocationAnimation: CameraLocationAnimation export declare const fogAnimation: FogAnimation export declare const groundAnimation: GroundAnimation export declare const lightAnimation: LightAnimation export declare const shadowAnimation: ShadowAnimation export declare const skyboxAnimation: SkyboxAnimation export declare const easyPropertyAnimation: EasyPropertyAnimation export declare const rsLoopAnimationManager: RsLoopAnimationManager export declare const rsAudioService: RsAudioService export declare const rsSelectionService: RsSelectionService export declare const rsSelection: RsSelection export declare const rsNodeService: RsNodeService export declare const rsModelService: RsModelService export declare const rsEnvironment: RsEnvironment export declare const rsEnvironmentService: RsEnvironmentService export declare const rsTextureService: RsTextureService export declare const rsClick: RsClick export declare const rsLabelService: RsLabelService export declare const rsNodeMaterialManager: RsNodeMaterialManager export declare const rsMaterialService: RsMaterialService export declare const rsSeparateService: RsSeparateService export declare const rsService: RsService export declare const syncService: SyncService export declare const attributeService: AttributeService export declare const awarenessService: AwarenessService export declare const historyService: HistoryService export declare const rvStepService: RvStepService export declare const rvResourceService: RvResourceService export declare const rvSceneService: RvSceneService export declare const rvModelService: RvModelService export declare const rvNodeService: RvNodeService export declare const rvNodeMaterialAnalyzer: RvNodeMaterialAnalyzer export declare const targetMultiNodeService: TargetMultiNodeService export declare const targetNodeService: TargetNodeService export declare const targetStepService: TargetStepService export declare const rss: Record export declare const autoPlayService: AutoPlayService export declare const rsBasicService: RsBasicService export declare const rsEnableService: RsEnableService export declare const rsEngine: RsEngine export declare const rsNodeMaterialAnalyzer: RsNodeMaterialAnalyzer export declare const rsSceneService: RsSceneService export declare const rsTransformGround: RsTransformGround export declare const rvMeetingService: RvMeetingService