mirror of
https://github.com/galacean/engine.git
synced 2026-06-09 01:03:09 +08:00
@@ -38,6 +38,17 @@ export class SafeLoopArray<T> {
|
||||
this._loopArrayDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove item from array that pass the specified comparison function.
|
||||
* @param filter - The comparison function
|
||||
*/
|
||||
findAndRemove(filter: (value: T) => boolean): void {
|
||||
const array = this._array;
|
||||
for (let i = array.length - 1; i >= 0; i--) {
|
||||
filter(array[i]) && this.removeByIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The index of the item.
|
||||
* @param item - The item which want to get the index
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export { ClearableObjectPool } from "./ClearableObjectPool";
|
||||
export type { IPoolElement } from "./ObjectPool";
|
||||
export { ReturnableObjectPool } from "./ReturnableObjectPool";
|
||||
export { SafeLoopArray } from "./SafeLoopArray";
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
import {
|
||||
AssetPromise,
|
||||
AssetType,
|
||||
Engine,
|
||||
EngineConfiguration,
|
||||
Loader,
|
||||
LoadItem,
|
||||
resourceLoader,
|
||||
ResourceManager
|
||||
} from "@galacean/engine-core";
|
||||
import { AssetPromise, AssetType, Loader, LoadItem, resourceLoader, ResourceManager } from "@galacean/engine-core";
|
||||
import { PrefabParser } from "./prefab/PrefabParser";
|
||||
import { PrefabResource } from "./prefab/PrefabResource";
|
||||
import { IHierarchyFile } from "./resource-deserialize";
|
||||
import { PrefabParser } from "./prefab/PrefabParser";
|
||||
|
||||
@resourceLoader(AssetType.Prefab, ["prefab"])
|
||||
export class PrefabLoader extends Loader<PrefabResource> {
|
||||
|
||||
@@ -30,4 +30,3 @@ export { KTX2Loader, KTX2Transcoder } from "./ktx2/KTX2Loader";
|
||||
export { KTX2TargetFormat } from "./ktx2/KTX2TargetFormat";
|
||||
export * from "./resource-deserialize";
|
||||
export * from "./prefab/PrefabResource";
|
||||
export { PrefabLoader } from "./PrefabLoader";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Engine } from "@galacean/engine-core";
|
||||
import { BufferReader } from "./utils/BufferReader";
|
||||
import { decoderMap, decoder } from "./utils/Decorator";
|
||||
import { decoderMap } from "./utils/Decorator";
|
||||
import { FileHeader } from "./utils/FileHeader";
|
||||
|
||||
export { MeshDecoder } from "./resources/mesh/MeshDecoder";
|
||||
@@ -29,3 +29,7 @@ export * from "./resources/scene/SceneParser";
|
||||
export * from "./resources/scene/MeshLoader";
|
||||
export * from "./resources/scene/EditorTextureLoader";
|
||||
export * from "./resources/parser/ParserContext";
|
||||
|
||||
export * from "./utils/BufferReader";
|
||||
export * from "./utils/Decorator";
|
||||
export * from "./utils/FileHeader";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Engine, ReferResource, Scene } from "@galacean/engine-core";
|
||||
import { Engine, Scene } from "@galacean/engine-core";
|
||||
import type { IScene } from "../schema";
|
||||
import { HierarchyParser } from "../parser/HierarchyParser";
|
||||
import { ParserContext, ParserType } from "../parser/ParserContext";
|
||||
|
||||
@@ -25,7 +25,16 @@ export class WebXRDevice implements IXRDevice {
|
||||
}
|
||||
|
||||
isSupportedFeature(type: XRFeatureType): boolean {
|
||||
return true;
|
||||
switch (type) {
|
||||
case XRFeatureType.HitTest:
|
||||
case XRFeatureType.PlaneTracking:
|
||||
return typeof XRPlane !== "undefined";
|
||||
case XRFeatureType.AnchorTracking:
|
||||
return typeof XRAnchor !== "undefined";
|
||||
case XRFeatureType.ImageTracking:
|
||||
// @ts-ignore
|
||||
return typeof XRImageTrackingResult !== "undefined";
|
||||
}
|
||||
}
|
||||
|
||||
createPlatformFeature(type: XRFeatureType, ...args: any[]): WebXRFeature {
|
||||
|
||||
@@ -140,7 +140,7 @@ export class WebXRSession implements IXRSession {
|
||||
session.removeEventListener("squeeze", onSessionEvent);
|
||||
session.removeEventListener("squeezestart", onSessionEvent);
|
||||
session.removeEventListener("squeezeend", onSessionEvent);
|
||||
session.addEventListener("end", this._onSessionExit);
|
||||
session.removeEventListener("end", this._onSessionExit);
|
||||
this._events.length = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,29 +8,22 @@ import { XRSessionManager } from "./session/XRSessionManager";
|
||||
import { XRSessionMode } from "./session/XRSessionMode";
|
||||
import { XRSessionState } from "./session/XRSessionState";
|
||||
/**
|
||||
* XRManager is the entry point of the XR system.
|
||||
* @internal
|
||||
*/
|
||||
export class XRManagerExtended extends XRManager {
|
||||
/** @internal */
|
||||
static _featureMap: Map<TFeatureConstructor<XRFeature>, XRFeatureType> = new Map();
|
||||
|
||||
/** Input manager for XR. */
|
||||
override inputManager: XRInputManager;
|
||||
/** Session manager for XR. */
|
||||
override sessionManager: XRSessionManager;
|
||||
/** Camera manager for XR. */
|
||||
override cameraManager: XRCameraManager;
|
||||
override readonly features: XRFeature[] = [];
|
||||
|
||||
/** @internal */
|
||||
_platformDevice: IXRDevice;
|
||||
|
||||
private _origin: Entity;
|
||||
private _features: XRFeature[];
|
||||
|
||||
/**
|
||||
* The current origin of XR space.
|
||||
* @remarks The connection point between the virtual world and the real world ( XR Space )
|
||||
*/
|
||||
override get origin(): Entity {
|
||||
return this._origin;
|
||||
}
|
||||
@@ -42,45 +35,31 @@ export class XRManagerExtended extends XRManager {
|
||||
this._origin = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the specified feature is supported.
|
||||
* @param type - The type of the feature
|
||||
* @returns If the feature is supported
|
||||
*/
|
||||
override isSupportedFeature<T extends XRFeature>(feature: TFeatureConstructor<T>): boolean {
|
||||
return this._platformDevice.isSupportedFeature(XRManagerExtended._featureMap.get(feature));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add feature based on the xr feature type.
|
||||
* @param type - The type of the feature
|
||||
* @param args - The constructor params of the feature
|
||||
* @returns The feature which has been added
|
||||
*/
|
||||
override addFeature<T extends new (xrManager: XRManagerExtended, ...args: any[]) => XRFeature>(
|
||||
type: T,
|
||||
...args: TFeatureConstructorArguments<T>
|
||||
): XRFeature | null {
|
||||
): InstanceType<T> | null {
|
||||
if (this.sessionManager._platformSession) {
|
||||
throw new Error("Cannot add feature when the session is initialized.");
|
||||
}
|
||||
const { _features: features } = this;
|
||||
for (let i = 0, n = features.length; i < n; i++) {
|
||||
const feature = features[i];
|
||||
if (feature instanceof type) throw new Error("The feature has been added");
|
||||
if (!this._platformDevice.isSupportedFeature(XRManagerExtended._featureMap.get(type))) {
|
||||
throw new Error("The feature is not supported");
|
||||
}
|
||||
const feature = new type(this, ...args);
|
||||
this._features.push(feature);
|
||||
const { features } = this;
|
||||
for (let i = 0, n = features.length; i < n; i++) {
|
||||
if (features[i] instanceof type) throw new Error("The feature has been added");
|
||||
}
|
||||
const feature = new type(this, ...args) as InstanceType<T>;
|
||||
features.push(feature);
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get feature which match the type.
|
||||
* @param type - The type of the feature
|
||||
* @returns The feature which match type
|
||||
*/
|
||||
override getFeature<T extends XRFeature>(type: TFeatureConstructor<T>): T | null {
|
||||
const { _features: features } = this;
|
||||
const { features } = this;
|
||||
for (let i = 0, n = features.length; i < n; i++) {
|
||||
const feature = features[i];
|
||||
if (feature instanceof type) {
|
||||
@@ -89,26 +68,6 @@ export class XRManagerExtended extends XRManager {
|
||||
}
|
||||
}
|
||||
|
||||
override getFeatures<T extends XRFeature>(type: TFeatureConstructor<T>, out?: T[]): T[] {
|
||||
if (out) {
|
||||
out.length = 0;
|
||||
} else {
|
||||
out = [];
|
||||
}
|
||||
const { _features: features } = this;
|
||||
for (let i = 0, n = features.length; i < n; i--) {
|
||||
const feature = features[i];
|
||||
feature instanceof type && out.push(feature);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter XR immersive mode, when you call this method, it will initialize and display the XR virtual world.
|
||||
* @param sessionMode - The mode of the session
|
||||
* @param autoRun - Whether to automatically run the session, when `autoRun` is set to true, xr will start working immediately after initialization. Otherwise, you need to call `sessionManager.run` later to work.
|
||||
* @returns A promise that resolves if the XR virtual world is entered, otherwise rejects
|
||||
*/
|
||||
override enterXR(sessionMode: XRSessionMode, autoRun: boolean = true): Promise<void> {
|
||||
const { sessionManager } = this;
|
||||
if (sessionManager._platformSession) {
|
||||
@@ -120,8 +79,9 @@ export class XRManagerExtended extends XRManager {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 1. Check if this xr mode is supported
|
||||
sessionManager.isSupportedMode(sessionMode).then(() => {
|
||||
sessionManager._setState(XRSessionState.Initializing);
|
||||
// 2. Initialize session
|
||||
sessionManager._initialize(sessionMode, this._features).then(() => {
|
||||
sessionManager._initialize(sessionMode, this.features).then(() => {
|
||||
autoRun && sessionManager.run();
|
||||
resolve();
|
||||
}, reject);
|
||||
@@ -129,10 +89,6 @@ export class XRManagerExtended extends XRManager {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit XR immersive mode, when you call this method, it will destroy the XR virtual world.
|
||||
* @returns A promise that resolves if the XR virtual world is destroyed, otherwise rejects
|
||||
*/
|
||||
override exitXR(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.sessionManager._exit().then(() => {
|
||||
@@ -141,36 +97,26 @@ export class XRManagerExtended extends XRManager {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
override _initialize(engine: Engine, xrDevice: IXRDevice): void {
|
||||
this._features = [];
|
||||
this._platformDevice = xrDevice;
|
||||
this.sessionManager = new XRSessionManager(this, engine);
|
||||
this.inputManager = new XRInputManager(this, engine);
|
||||
this.cameraManager = new XRCameraManager(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
override _update(): void {
|
||||
const { sessionManager } = this;
|
||||
if (sessionManager.state !== XRSessionState.Running) return;
|
||||
sessionManager._onUpdate();
|
||||
this.inputManager._onUpdate();
|
||||
this.cameraManager._onUpdate();
|
||||
const { _features: features } = this;
|
||||
const { features } = this;
|
||||
for (let i = 0, n = features.length; i < n; i++) {
|
||||
const feature = features[i];
|
||||
feature.enabled && feature._onUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
override _destroy(): void {
|
||||
if (this.sessionManager._platformSession) {
|
||||
this.exitXR().then(() => {
|
||||
@@ -185,23 +131,14 @@ export class XRManagerExtended extends XRManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
override _getRequestAnimationFrame(): (callback: FrameRequestCallback) => number {
|
||||
return this.sessionManager._getRequestAnimationFrame();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
override _getCancelAnimationFrame(): (id: number) => void {
|
||||
return this.sessionManager._getCancelAnimationFrame();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
override _getCameraClearFlagsMask(type: CameraType): CameraClearFlags {
|
||||
return this.cameraManager._getCameraClearFlagsMask(type);
|
||||
}
|
||||
@@ -210,7 +147,7 @@ export class XRManagerExtended extends XRManager {
|
||||
* @internal
|
||||
*/
|
||||
_onSessionStop(): void {
|
||||
const { _features: features } = this;
|
||||
const { features } = this;
|
||||
for (let i = 0, n = features.length; i < n; i++) {
|
||||
const feature = features[i];
|
||||
feature.enabled && feature._onSessionStop();
|
||||
@@ -221,7 +158,7 @@ export class XRManagerExtended extends XRManager {
|
||||
* @internal
|
||||
*/
|
||||
_onSessionInit(): void {
|
||||
const { _features: features } = this;
|
||||
const { features } = this;
|
||||
for (let i = 0, n = features.length; i < n; i++) {
|
||||
const feature = features[i];
|
||||
feature.enabled && feature._onSessionInit();
|
||||
@@ -233,7 +170,7 @@ export class XRManagerExtended extends XRManager {
|
||||
*/
|
||||
_onSessionStart(): void {
|
||||
this.cameraManager._onSessionStart();
|
||||
const { _features: features } = this;
|
||||
const { features } = this;
|
||||
for (let i = 0, n = features.length; i < n; i++) {
|
||||
const feature = features[i];
|
||||
feature.enabled && feature._onSessionStart();
|
||||
@@ -245,7 +182,7 @@ export class XRManagerExtended extends XRManager {
|
||||
*/
|
||||
_onSessionExit(): void {
|
||||
this.cameraManager._onSessionExit();
|
||||
const { _features: features } = this;
|
||||
const { features } = this;
|
||||
for (let i = 0, n = features.length; i < n; i++) {
|
||||
const feature = features[i];
|
||||
feature.enabled && feature._onSessionExit();
|
||||
@@ -264,6 +201,11 @@ export function registerXRFeature<T extends XRFeature>(type: XRFeatureType): (fe
|
||||
};
|
||||
}
|
||||
|
||||
export interface IXRListener {
|
||||
fn: (...args: any[]) => any;
|
||||
destroyed?: boolean;
|
||||
}
|
||||
|
||||
type TFeatureConstructor<T extends XRFeature> = new (xrManager: XRManagerExtended, ...args: any[]) => T;
|
||||
|
||||
type TFeatureConstructorArguments<T extends new (xrManager: XRManagerExtended, ...args: any[]) => XRFeature> =
|
||||
@@ -277,6 +219,8 @@ declare module "@galacean/engine" {
|
||||
sessionManager: XRSessionManager;
|
||||
/** Camera manager for XR. */
|
||||
cameraManager: XRCameraManager;
|
||||
/** Initialized features. */
|
||||
readonly features: XRFeature[];
|
||||
|
||||
/**
|
||||
* The current origin of XR space.
|
||||
@@ -285,19 +229,6 @@ declare module "@galacean/engine" {
|
||||
get origin(): Entity;
|
||||
set origin(value: Entity);
|
||||
|
||||
/**
|
||||
* Get all initialized features at this moment.
|
||||
* @param type - The type of the feature
|
||||
*/
|
||||
getFeatures<T extends XRFeature>(type: TFeatureConstructor<T>): T[];
|
||||
|
||||
/**
|
||||
* Get all initialized features at this moment.
|
||||
* @param type - The type of the feature
|
||||
* @param out - Save all features in `out`
|
||||
*/
|
||||
getFeatures<T extends XRFeature>(type: TFeatureConstructor<T>, out: T[]): T[];
|
||||
|
||||
/**
|
||||
* Check if the specified feature is supported.
|
||||
* @param type - The type of the feature
|
||||
@@ -314,7 +245,7 @@ declare module "@galacean/engine" {
|
||||
addFeature<T extends new (xrManager: XRManagerExtended, ...args: any[]) => XRFeature>(
|
||||
type: T,
|
||||
...args: TFeatureConstructorArguments<T>
|
||||
): XRFeature | null;
|
||||
): InstanceType<T> | null;
|
||||
|
||||
/**
|
||||
* Get feature which match the type.
|
||||
@@ -322,7 +253,6 @@ declare module "@galacean/engine" {
|
||||
* @returns The feature which match type
|
||||
*/
|
||||
getFeature<T extends XRFeature>(type: TFeatureConstructor<T>): T | null;
|
||||
getFeatures<T extends XRFeature>(type: TFeatureConstructor<T>, out?: T[]): T[];
|
||||
/**
|
||||
* Enter XR immersive mode, when you call this method, it will initialize and display the XR virtual world.
|
||||
* @param sessionMode - The mode of the session
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { SafeLoopArray } from "@galacean/engine";
|
||||
import { IXRTrackablePlatformFeature } from "@galacean/engine-design";
|
||||
import { IXRListener } from "../../XRManagerExtended";
|
||||
import { XRTrackingState } from "../../input/XRTrackingState";
|
||||
import { XRFeature } from "../XRFeature";
|
||||
import { XRFeatureType } from "../XRFeatureType";
|
||||
@@ -9,9 +11,10 @@ import { XRTracked } from "./XRTracked";
|
||||
/**
|
||||
* The base class of XR trackable manager.
|
||||
*/
|
||||
export abstract class XRTrackableFeature<T extends XRTracked, K extends XRRequestTracking<T>> extends XRFeature<
|
||||
IXRTrackablePlatformFeature<T, K>
|
||||
> {
|
||||
export abstract class XRTrackableFeature<
|
||||
T extends XRTracked = XRTracked,
|
||||
K extends XRRequestTracking<T> = XRRequestTracking<T>
|
||||
> extends XRFeature<IXRTrackablePlatformFeature<T, K>> {
|
||||
protected static _uuid = 0;
|
||||
|
||||
protected _requestTrackings: K[] = [];
|
||||
@@ -20,14 +23,14 @@ export abstract class XRTrackableFeature<T extends XRTracked, K extends XRReques
|
||||
protected _updated: T[] = [];
|
||||
protected _removed: T[] = [];
|
||||
protected _statusSnapshot: Record<number, XRTrackingState> = {};
|
||||
private _listeners: ((added: readonly T[], updated: readonly T[], removed: readonly T[]) => void)[] = [];
|
||||
private _listeners: SafeLoopArray<IXRListener> = new SafeLoopArray<IXRListener>();
|
||||
|
||||
/**
|
||||
* Add a listening function for tracked object changes.
|
||||
* @param listener - The listening function
|
||||
*/
|
||||
addChangedListener(listener: (added: readonly T[], updated: readonly T[], removed: readonly T[]) => void): void {
|
||||
this._listeners.push(listener);
|
||||
this._listeners.push({ fn: listener });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,11 +38,7 @@ export abstract class XRTrackableFeature<T extends XRTracked, K extends XRReques
|
||||
* @param listener - The listening function
|
||||
*/
|
||||
removeChangedListener(listener: (added: readonly T[], updated: readonly T[], removed: readonly T[]) => void): void {
|
||||
const { _listeners: listeners } = this;
|
||||
const index = listeners.indexOf(listener);
|
||||
if (index >= 0) {
|
||||
listeners.splice(index, 1);
|
||||
}
|
||||
this._listeners.findAndRemove((value) => (value.fn === listener ? (value.destroyed = true) : false));
|
||||
}
|
||||
|
||||
override _onUpdate(): void {
|
||||
@@ -47,7 +46,6 @@ export abstract class XRTrackableFeature<T extends XRTracked, K extends XRReques
|
||||
const { frame: platformFrame } = platformSession;
|
||||
const {
|
||||
_platformFeature: platformFeature,
|
||||
_listeners: listeners,
|
||||
_requestTrackings: requestTrackings,
|
||||
_statusSnapshot: statusSnapshot,
|
||||
_tracked: allTracked,
|
||||
@@ -108,8 +106,10 @@ export abstract class XRTrackableFeature<T extends XRTracked, K extends XRReques
|
||||
requestTrackings[i].state === XRRequestTrackingState.Destroyed && requestTrackings.splice(i, 1);
|
||||
}
|
||||
if (added.length > 0 || updated.length > 0 || removed.length > 0) {
|
||||
const listeners = this._listeners.getLoopArray();
|
||||
for (let i = 0, n = listeners.length; i < n; i++) {
|
||||
listeners[i](added, updated, removed);
|
||||
const listener = listeners[i];
|
||||
!listener.destroyed && listener.fn(added, updated, removed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,12 +120,8 @@ export abstract class XRTrackableFeature<T extends XRTracked, K extends XRReques
|
||||
|
||||
override _onSessionExit(): void {
|
||||
// prettier-ignore
|
||||
this._requestTrackings.length = this._tracked.length = this._added.length = this._updated.length = this._removed.length = 0;
|
||||
}
|
||||
|
||||
override _onDestroy(): void {
|
||||
// prettier-ignore
|
||||
this._requestTrackings.length = this._tracked.length = this._added.length = this._updated.length = this._removed.length = 0;
|
||||
this._requestTrackings.length = this._tracked.length = this._added.length = this._updated.length = this._removed.length = 0;
|
||||
this._listeners.findAndRemove((value) => (value.destroyed = true));
|
||||
}
|
||||
|
||||
protected _addRequestTracking(requestTracking: K): void {
|
||||
|
||||
@@ -4,6 +4,8 @@ import "./XRManagerExtended";
|
||||
export { XRPose } from "./XRPose";
|
||||
// xr feature
|
||||
export { XRFeature } from "./feature/XRFeature";
|
||||
export { XRTrackableFeature } from "./feature/trackable/XRTrackableFeature";
|
||||
export { XRTracked } from "./feature/trackable/XRTracked";
|
||||
// camera
|
||||
export { XRCameraManager } from "./feature/camera/XRCameraManager";
|
||||
// hitTest
|
||||
@@ -38,3 +40,6 @@ export { XRFeatureType } from "./feature/XRFeatureType";
|
||||
export { XRRequestTrackingState } from "./feature/trackable/XRRequestTrackingState";
|
||||
export { XRInputEventType } from "./input/XRInputEventType";
|
||||
export { XRTargetRayMode } from "./input/XRTargetRayMode";
|
||||
|
||||
export * from "./loader/XRReferenceImageDecoder";
|
||||
export * from "./loader/XRReferenceImageLoader";
|
||||
|
||||
17
packages/xr/src/loader/XRReferenceImageDecoder.ts
Normal file
17
packages/xr/src/loader/XRReferenceImageDecoder.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { BufferReader, Engine, decoder } from "@galacean/engine";
|
||||
import { XRReferenceImage } from "../feature/trackable/image/XRReferenceImage";
|
||||
|
||||
@decoder("XRReferenceImage")
|
||||
export class XRReferenceImageDecoder {
|
||||
static decode(engine: Engine, bufferReader: BufferReader): Promise<XRReferenceImage> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const physicalWidth = bufferReader.nextFloat32();
|
||||
bufferReader.nextUint8();
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
resolve(new XRReferenceImage("", img, physicalWidth));
|
||||
};
|
||||
img.src = URL.createObjectURL(new window.Blob([bufferReader.nextImagesData(1)[0]]));
|
||||
});
|
||||
}
|
||||
}
|
||||
17
packages/xr/src/loader/XRReferenceImageLoader.ts
Normal file
17
packages/xr/src/loader/XRReferenceImageLoader.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { AssetPromise, decode, Loader, LoadItem, resourceLoader, ResourceManager } from "@galacean/engine";
|
||||
import { XRReferenceImage } from "../feature/trackable/image/XRReferenceImage";
|
||||
|
||||
@resourceLoader("XRReferenceImage", [])
|
||||
export class XRReferenceImageLoader extends Loader<XRReferenceImage> {
|
||||
load(item: LoadItem, resourceManager: ResourceManager): AssetPromise<XRReferenceImage> {
|
||||
return new AssetPromise((resolve, reject) => {
|
||||
this.request<ArrayBuffer>(item.url, { ...item, type: "arraybuffer" })
|
||||
.then((data) => {
|
||||
decode<XRReferenceImage>(data, resourceManager.engine).then((referenceImage) => {
|
||||
resolve(referenceImage);
|
||||
});
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Engine } from "@galacean/engine";
|
||||
import { Engine, SafeLoopArray } from "@galacean/engine";
|
||||
import { IHardwareRenderer, IXRSession } from "@galacean/engine-design";
|
||||
import { XRManagerExtended } from "../XRManagerExtended";
|
||||
import { IXRListener, XRManagerExtended } from "../XRManagerExtended";
|
||||
import { XRFeature } from "../feature/XRFeature";
|
||||
import { XRSessionMode } from "./XRSessionMode";
|
||||
import { XRSessionState } from "./XRSessionState";
|
||||
@@ -17,6 +17,7 @@ export class XRSessionManager {
|
||||
private _rhi: IHardwareRenderer;
|
||||
private _raf: (callback: FrameRequestCallback) => number;
|
||||
private _caf: (id: number) => void;
|
||||
private _listeners: SafeLoopArray<IXRListener> = new SafeLoopArray<IXRListener>();
|
||||
|
||||
/**
|
||||
* The current session mode( AR or VR ).
|
||||
@@ -78,7 +79,7 @@ export class XRSessionManager {
|
||||
throw new Error("Without session to run.");
|
||||
}
|
||||
platformSession.start();
|
||||
this._state = XRSessionState.Running;
|
||||
this._setState(XRSessionState.Running);
|
||||
this._xrManager._onSessionStart();
|
||||
if (!engine.isPaused) {
|
||||
engine.pause();
|
||||
@@ -100,7 +101,7 @@ export class XRSessionManager {
|
||||
rhi._mainFrameBuffer = null;
|
||||
rhi._mainFrameWidth = rhi._mainFrameHeight = 0;
|
||||
platformSession.stop();
|
||||
this._state = XRSessionState.Paused;
|
||||
this._setState(XRSessionState.Paused);
|
||||
this._xrManager._onSessionStop();
|
||||
if (!engine.isPaused) {
|
||||
engine.pause();
|
||||
@@ -108,6 +109,34 @@ export class XRSessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listening function for session state changes.
|
||||
* @param listener - The listening function
|
||||
*/
|
||||
addStateChangedListener(listener: (state: XRSessionState) => void): void {
|
||||
this._listeners.push({ fn: listener });
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listening function of session state changes.
|
||||
* @param listener - The listening function
|
||||
*/
|
||||
removeStateChangedListener(listener: (state: XRSessionState) => void): void {
|
||||
this._listeners.findAndRemove((value) => (value.fn === listener ? (value.destroyed = true) : false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_setState(value: XRSessionState) {
|
||||
this._state = value;
|
||||
const listeners = this._listeners.getLoopArray();
|
||||
for (let i = 0, n = listeners.length; i < n; i++) {
|
||||
const listener = listeners[i];
|
||||
!listener.destroyed && listener.fn(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -125,7 +154,7 @@ export class XRSessionManager {
|
||||
.then((platformSession: IXRSession) => {
|
||||
this._mode = mode;
|
||||
this._platformSession = platformSession;
|
||||
this._state = XRSessionState.Initialized;
|
||||
this._setState(XRSessionState.Initialized);
|
||||
platformSession.setSessionExitCallBack(this._onSessionExit);
|
||||
platformSession.addEventListener();
|
||||
xrManager._onSessionInit();
|
||||
@@ -183,7 +212,7 @@ export class XRSessionManager {
|
||||
rhi._mainFrameWidth = rhi._mainFrameHeight = 0;
|
||||
platformSession.removeEventListener();
|
||||
this._platformSession = null;
|
||||
this._state = XRSessionState.None;
|
||||
this._setState(XRSessionState.None);
|
||||
this._xrManager._onSessionExit();
|
||||
if (!engine.isPaused) {
|
||||
engine.pause();
|
||||
@@ -194,5 +223,8 @@ export class XRSessionManager {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_onDestroy(): void {}
|
||||
_onDestroy(): void {
|
||||
this._listeners.findAndRemove((value) => (value.destroyed = true));
|
||||
this._raf = this._caf = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
export enum XRSessionState {
|
||||
/** Not initialized. */
|
||||
None,
|
||||
/** Initializing session. */
|
||||
Initializing,
|
||||
/** Initialized but not started. */
|
||||
Initialized,
|
||||
/** Running. */
|
||||
|
||||
Reference in New Issue
Block a user