Skip to content

Commit

Permalink
feat(event-display): add and set up loading manager
Browse files Browse the repository at this point in the history
  • Loading branch information
9inpachi committed Nov 25, 2020
1 parent a6a1c19 commit 5f0f942
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 7 deletions.
6 changes: 6 additions & 0 deletions packages/phoenix-event-display/src/event-display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { InfoLogger } from './info-logger';
import { Configuration } from './extras/configuration';
import { StateManager } from './managers/state-manager';
import { JiveXMLLoader } from './loaders/jivexml-loader';
import { LoadingManager } from './managers/loading-manager';

declare global {
/**
Expand Down Expand Up @@ -33,6 +34,8 @@ export class EventDisplay {
private infoLogger: InfoLogger;
/** UI manager for UI menu. */
private ui: UIManager;
/** Loading manager for loadable resources */
private loadingManager: LoadingManager;

/**
* Create the Phoenix event display and intitialize all the elements.
Expand All @@ -42,6 +45,7 @@ export class EventDisplay {
this.infoLogger = new InfoLogger();
this.graphicsLibrary = new ThreeManager(this.infoLogger);
this.ui = new UIManager(this.graphicsLibrary);
this.loadingManager = new LoadingManager();
if (configuration) {
this.init(configuration);
}
Expand Down Expand Up @@ -128,11 +132,13 @@ export class EventDisplay {
* @param eventKey String that represents the event in the eventsData object.
*/
public loadEvent(eventKey: any) {
this.loadingManager.addLoadableItem();
const event = this.eventsData[eventKey];

if (event) {
this.buildEventDataFromJSON(event);
}
this.loadingManager.itemLoaded();
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/phoenix-event-display/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ export * from './loaders/objects/phoenix-objects';

// Managers
export * from './managers/state-manager';
export * from './managers/loading-manager';
7 changes: 7 additions & 0 deletions packages/phoenix-event-display/src/loaders/cms-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class CMSLoader extends PhoenixLoader {
* @param eventPathName Complete event path or event number as in the ".ig" archive.
*/
public readIgArchive(path: string, onFileRead: (allEvents: any[]) => void, eventPathName?: string) {
this.loadingManager.addLoadableItem();
const igArchive = new JSZip();
let eventsDataInIg = [];
fetch(path).then(res => res.arrayBuffer()).then((res) => {
Expand All @@ -63,12 +64,14 @@ export class CMSLoader extends PhoenixLoader {
eventsDataInIg.push(eventJSON);
if (i === allFilesPath.length) {
onFileRead(eventsDataInIg);
this.loadingManager.itemLoaded();
}
i++;
});
} else {
if (i === allFilesPath.length) {
onFileRead(eventsDataInIg);
this.loadingManager.itemLoaded();
}
i++;
}
Expand Down Expand Up @@ -100,6 +103,8 @@ export class CMSLoader extends PhoenixLoader {
public getEventData(): any {
const eventInfo = this.data?.['Collections']?.['Event_V2']?.[0];

this.loadingManager.addLoadableItem();

let eventData = {
runNumber: eventInfo?.[0],
eventNumber: eventInfo?.[1],
Expand Down Expand Up @@ -130,6 +135,8 @@ export class CMSLoader extends PhoenixLoader {
}
}

this.loadingManager.itemLoaded();

return eventData;
}

Expand Down
9 changes: 9 additions & 0 deletions packages/phoenix-event-display/src/loaders/phoenix-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { PhoenixObjects } from './objects/phoenix-objects';
import { InfoLogger } from '../info-logger';
import { PhoenixMenuNode } from '../ui/phoenix-menu/phoenix-menu-node';
import { EVENT_DATA_TYPE_COLORS } from '../helpers/constants';
import { LoadingManager } from '../managers/loading-manager';

/**
* Loader for processing and loading an event.
Expand All @@ -18,7 +19,12 @@ export class PhoenixLoader implements EventDataLoader {
private ui: UIManager;
/** Event data processed by the loader. */
private eventData: any;
/** Loading manager for loadable resources */
protected loadingManager: LoadingManager;

constructor() {
this.loadingManager = new LoadingManager();
}

/**
* Takes an object that represents ONE event and takes care of adding
Expand All @@ -34,13 +40,16 @@ export class PhoenixLoader implements EventDataLoader {
this.ui = ui;
this.eventData = eventData;

this.loadingManager.addLoadableItem();

// Replacing tracks with tracks through Runge-Kutta
// TODO - make this configurable? Or possibly automatic if tracks have <2 positions to draw?
// Object.assign(this.eventData.Tracks, this.getTracksWithRungeKutta(this.eventData['Tracks']));

// initiate load
this.loadObjectTypes(eventData);

this.loadingManager.itemLoaded();

const eventNumber = eventData['event number'] ? eventData['event number'] : eventData['eventNumber'];
const runNumber = eventData['run number'] ? eventData['run number'] : eventData['runNumber'];
Expand Down
11 changes: 11 additions & 0 deletions packages/phoenix-event-display/src/loaders/script-loader.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { LoadingManager } from "../managers/loading-manager";

/** Global JSROOT variable for accessing functions after loading JSRoot scripts. */
declare const JSROOT: any;

Expand All @@ -11,6 +13,8 @@ export class ScriptLoader {
* @param onScriptsLoaded Callback when all the JSRoot scripts have loaded.
*/
public static loadJSRootScripts(onScriptsLoaded: (JSROOT: any) => void) {
const loadingManager = new LoadingManager();
loadingManager.addLoadableItem();
(async () => {
const allScripts = [
'JSRootCore.js', 'three.min.js', 'three.extra.min.js',
Expand All @@ -20,6 +24,7 @@ export class ScriptLoader {
for (const script of allScripts) {
await ScriptLoader.loadScript('assets/jsroot/' + script, 'JSROOT');
}
loadingManager.itemLoaded();
onScriptsLoaded(JSROOT);
})();
}
Expand All @@ -34,6 +39,8 @@ export class ScriptLoader {
*/
public static loadScript(scriptURL: string, scriptFor?: string,
parentElement: HTMLElement = document.getElementsByTagName('head')[0]): Promise<any> {
const loadingManager = new LoadingManager();
loadingManager.addLoadableItem();
return new Promise<any>((resolve, reject) => {
const scriptExists = document
.querySelectorAll<HTMLScriptElement>('script[src="' + scriptURL + '"]');
Expand All @@ -48,19 +55,23 @@ export class ScriptLoader {
scriptElement.addEventListener('load', () => {
scriptElement.setAttribute('data-loaded', 'true');
resolve();
loadingManager.itemLoaded();
});
scriptElement.onerror = (event) => {
console.error('ERROR LOADING SCRIPT: ', event);
reject();
loadingManager.itemLoaded();
}
parentElement.appendChild(scriptElement);
} else {
// If script has already loaded then resolve else wait for it to load
if (scriptExists[0].dataset.loaded === 'true') {
resolve();
loadingManager.itemLoaded();
} else {
scriptExists[0].addEventListener('load', () => {
resolve();
loadingManager.itemLoaded();
});
}
}
Expand Down
93 changes: 93 additions & 0 deletions packages/phoenix-event-display/src/managers/loading-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* Phoenix loading manager for managing loadable items.
*/
export class LoadingManager {
/** Instance of the loading manager */
private static instance: LoadingManager;

/** Number of items to load. */
public toLoad: number = 0;
/** Number of items loaded */
public loaded: number = 0;

/** Callbacks to call on load. */
private onLoadCallbacks: (() => void)[] = [];
/** Callbacks to call on progress. */
private onProgressCallbacks: ((progress: number) => void)[] = [];

/** Progress for each named item. */
private progressItems: { [key: string]: number } = {};

/**
* Create the singleton Phoenix loading manager.
*/
constructor() {
if (LoadingManager.instance === undefined) {
LoadingManager.instance = this;
}
return LoadingManager.instance;
}

/**
* Add count for a loadable item.
*/
public addLoadableItem() {
this.toLoad++;
}

/**
* Add count for an item is loaded.
*/
public itemLoaded() {
this.loaded++;
if (this.toLoad === this.loaded) {
this.onLoadCallbacks.forEach(callback => callback());
}
}

/**
* When an item loading progresses.
* @param itemName Name of the item with the progress.
* @param progress Progress of the item.
*/
public onProgress(itemName: string, progress: number) {
this.progressItems[itemName] = progress;

let totalProgress = Object.values(this.progressItems)
.reduce((acc, val) => acc + val, 0);
let totalItems = Object.keys(this.progressItems).length;

const averageProgress = totalProgress / totalItems;

for (const callback of this.onProgressCallbacks) {
callback(averageProgress);
}
}

/**
* Add a listener for when all items have loaded.
* @param callback Callback to call when all items have loaded.
*/
public addLoadListener(callback: () => void) {
this.onLoadCallbacks.push(callback);
}

/**
* Add a listener for when an item progress.
* @param callback Callback to call when there is progress.
*/
public addProgressListener(callback: (progress: number) => void) {
this.onProgressCallbacks.push(callback);
}

/**
* Reset the loading manager and its items.
*/
public reset() {
this.toLoad = 0;
this.loaded = 0;
this.onLoadCallbacks = [];
this.onProgressCallbacks = [];
this.progressItems = {};
}
}
6 changes: 2 additions & 4 deletions packages/phoenix-event-display/src/managers/state-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ export class StateManager {
* Create the state manager.
*/
constructor() {
if (StateManager.instance) {
return StateManager.instance;
} else {
if (StateManager.instance === undefined) {
StateManager.instance = this;
return StateManager.instance;
}
return StateManager.instance;
}

/**
Expand Down
26 changes: 23 additions & 3 deletions packages/phoenix-event-display/src/three/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { InfoLogger } from '../info-logger';
import { EffectsManager } from './effects-manager';
import { VRManager } from './vr-manager';
import { StateManager } from '../managers/state-manager';
import { LoadingManager } from '../managers/loading-manager';

/**
* Manager for all three.js related functions.
Expand All @@ -49,6 +50,8 @@ export class ThreeManager {
private effectsManager: EffectsManager;
/** VR manager for VR related operations */
private vrManager: VRManager;
/** Loading manager for loadable resources */
private loadingManager: LoadingManager;
/** Loop to run for each frame of animation. */
private animationLoop: () => void;
/** Scene export ignore list */
Expand All @@ -70,6 +73,7 @@ export class ThreeManager {
*/
constructor(private infoLogger: InfoLogger) {
this.rendererManager = new RendererManager();
this.loadingManager = new LoadingManager();
}

/**
Expand Down Expand Up @@ -261,10 +265,13 @@ export class ThreeManager {
initiallyVisible: boolean = true,
setFlat: boolean = true
): Promise<unknown> {
this.loadingManager.addLoadableItem();

const geometries = this.sceneManager.getGeometries();
const callback = (object: Object3D) => {
object.visible = initiallyVisible;
geometries.add(object);
this.loadingManager.itemLoaded();
};
return this.importManager.loadOBJGeometry(callback, filename, name, color, doubleSided, setFlat);
}
Expand All @@ -277,12 +284,19 @@ export class ThreeManager {
* @param initiallyVisible Whether the geometry is initially visible or not.
* @returns Promise for loading the geometry.
*/
public loadGLTFGeometry(sceneUrl: any, name: string,
scale?: number, initiallyVisible: boolean = true): Promise<unknown> {
public loadGLTFGeometry(
sceneUrl: any,
name: string,
scale?: number,
initiallyVisible: boolean = true
): Promise<unknown> {
this.loadingManager.addLoadableItem();

const geometries = this.sceneManager.getGeometries();
const callback = (geometry: Object3D) => {
geometry.visible = initiallyVisible;
geometries.add(geometry);
this.loadingManager.itemLoaded();
};
return this.importManager.loadGLTFGeometry(sceneUrl, name, callback, scale);
}
Expand All @@ -294,10 +308,12 @@ export class ThreeManager {
* @param initiallyVisible Whether the geometry is initially visible or not.
*/
public parseOBJGeometry(geometry: string, name: string, initiallyVisible: boolean = true) {
this.loadingManager.addLoadableItem();
const geometries = this.sceneManager.getGeometries();
const object = this.importManager.parseOBJGeometry(geometry, name);
object.visible = initiallyVisible;
geometries.add(object);
this.loadingManager.itemLoaded();
}

/**
Expand All @@ -306,9 +322,11 @@ export class ThreeManager {
* @returns Promise for loading the geometry.
*/
public parseGLTFGeometry(geometry: any): Promise<unknown> {
this.loadingManager.addLoadableItem();
const callback = (geometries: Object3D, eventData: Object3D) => {
this.sceneManager.getScene().add(geometries);
this.sceneManager.getScene().add(eventData);
this.loadingManager.itemLoaded();
};
return this.importManager.parseGLTFGeometry(geometry, callback);
}
Expand All @@ -324,10 +342,12 @@ export class ThreeManager {
*/
public loadJSONGeometry(json: string | object, name: string, scale?: number,
doubleSided?: boolean, initiallyVisible: boolean = true): Promise<unknown> {
this.loadingManager.addLoadableItem();
const geometries = this.sceneManager.getGeometries();
const callback = (geometry: Object3D) => {
geometry.visible = initiallyVisible;
geometries.add(geometry);
this.loadingManager.itemLoaded();
};
return this.importManager.loadJSONGeometry(json, name, callback, scale, doubleSided);
}
Expand Down Expand Up @@ -594,7 +614,7 @@ export class ThreeManager {

const mainRenderer = this.rendererManager.getMainRenderer();
mainRenderer.xr.enabled = false;

mainRenderer.setAnimationLoop(null);
mainRenderer.setAnimationLoop(this.animationLoop.bind(this));

Expand Down

0 comments on commit 5f0f942

Please sign in to comment.