Skip to content

Commit

Permalink
Merge pull request #665 from HSF/sponce_zipGLTF
Browse files Browse the repository at this point in the history
  • Loading branch information
EdwardMoyse authored Sep 3, 2024
2 parents 2032a45 + 29cac60 commit 810bbed
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 87 deletions.
28 changes: 14 additions & 14 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "firefox",
"request": "launch",
"name": "Launch FF against localhost",
"url": "http://localhost:4200",
"webRoot": "${workspaceFolder}"
}
]
}
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "firefox",
"request": "launch",
"name": "Launch FF against localhost",
"url": "http://localhost:4200",
"webRoot": "${workspaceFolder}"
}
]
}
6 changes: 3 additions & 3 deletions packages/phoenix-event-display/src/event-display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,16 +334,16 @@ export class EventDisplay {
* @returns Promise for loading the geometry.
*/
public async parseGLTFGeometry(file: File): Promise<void> {
const filename = file.name.split('/').pop();
this.loadingManager.addLoadableItem(`parse_gltf_${filename}`);
const name = file.name.split('/').pop();
this.loadingManager.addLoadableItem(`parse_gltf_${name}`);

const allGeometriesUIParameters =
await this.graphicsLibrary.parseGLTFGeometry(file);
for (const { object, menuNodeName } of allGeometriesUIParameters) {
this.ui.addGeometry(object, menuNodeName);
}

this.loadingManager.itemLoaded(`parse_gltf_${filename}`);
this.loadingManager.itemLoaded(`parse_gltf_${name}`);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,72 +208,121 @@ export class ImportManager {
});
}

/**
* handles some file content and loads a Geometry contained..
* It deals with zip file cases and then
* calls the given method on each file found
* @param path path of the original file
* @param filename name of the original file
* @param data content of the original file
* @param callback the method to be called on each file content
* @param resolve the method to be called on success
* @param reject the method to be called on failure
*/
private zipHandlingInternal(
path: string,
filename: string,
data: ArrayBuffer,
callback: (
fileContent: ArrayBuffer,
path: string,
name: string,
) => Promise<GeometryUIParameters[]>,
resolve: any,
reject: any,
) {
if (filename.split('.').pop() == 'zip') {
JSZip.loadAsync(data).then((archive) => {
const promises: Promise<any>[] = [];
for (const filePath in archive.files) {
promises.push(
archive
.file(filePath)
.async('arraybuffer')
.then((fileData) => {
return callback(fileData, path, filePath.split('.')[0]);
}),
);
}
let allGeometriesUIParameters: GeometryUIParameters[] = [];
Promise.all(promises).then((geos) => {
geos.forEach((geo) => {
allGeometriesUIParameters = allGeometriesUIParameters.concat(geo);
});
resolve(allGeometriesUIParameters);
});
});
} else {
callback(data, path, filename.split('.')[0]).then(
(geo) => {
resolve(geo);
},
(error) => {
reject(error);
},
);
}
}

/**
* Wraps a method taking a file and returning a Promise for
* loading a Geometry. It deals with zip file cases and then
* calls the original method on each file found
* @param file the original file
* @param callback the orignal mathod
* @param callback the original method
* @returns Promise for loading the geometry.
*/
private zipHandlingWrapper(
file: File | string,
private zipHandlingFileWrapper(
file: File,
callback: (
fileContent: ArrayBuffer,
path: string,
name: string,
) => Promise<GeometryUIParameters[]>,
): Promise<GeometryUIParameters[]> {
return new Promise<GeometryUIParameters[]>((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
this.zipHandlingInternal(
'',
file.name,
reader.result as ArrayBuffer,
callback,
resolve,
reject,
);
};
reader.readAsArrayBuffer(file);
});
}

/**
* Wraps a method taking a URL and returning a Promise for
* loading a Geometry. It deals with zip file cases and then
* calls the original method on each file found
* @param file the original file
* @param callback the original method
* @returns Promise for loading the geometry.
*/
private zipHandlingURLWrapper(
file: string,
callback: (
fileContent: ArrayBuffer,
path: string,
name: string,
) => Promise<GeometryUIParameters[]>,
): Promise<GeometryUIParameters[]> {
if (typeof file != 'string') {
file = file.name;
}
const path = file.substr(0, file.lastIndexOf('/'));
return new Promise<GeometryUIParameters[]>((resolve, reject) => {
fetch(file).then((response) => {
return response.arrayBuffer().then((data) => {
if (file.split('.').pop() == 'zip') {
try {
JSZip.loadAsync(data).then((archive) => {
const promises: Promise<GeometryUIParameters[]>[] = [];
if (archive) {
for (const filePath in archive.files) {
const file = archive.file(filePath);
if (file) {
promises.push(
file.async('arraybuffer').then((fileData) => {
return callback(
fileData,
path,
filePath.split('.')[0],
);
}),
);
}
}
}
let allGeometriesUIParameters: GeometryUIParameters[] = [];
Promise.all(promises).then((geos) => {
geos.forEach((geo) => {
allGeometriesUIParameters =
allGeometriesUIParameters.concat(geo);
});
resolve(allGeometriesUIParameters);
});
});
} catch (error) {
console.warn('Could not read zip file', 'Error');
reject(error);
}
} else {
callback(data, path, file.split('.')[0]).then(
(geo) => {
resolve(geo);
},
(error) => {
reject(error);
},
);
}
this.zipHandlingInternal(
file.substr(0, file.lastIndexOf('/')),
file,
data,
callback,
resolve,
reject,
);
});
});
});
Expand All @@ -296,7 +345,7 @@ export class ImportManager {
scale: number,
initiallyVisible: boolean,
): Promise<GeometryUIParameters[]> {
return this.zipHandlingWrapper(
return this.zipHandlingURLWrapper(
sceneUrl,
(data: ArrayBuffer, path: string, ignoredName: string) => {
return this.loadGLTFGeometryInternal(
Expand Down Expand Up @@ -421,10 +470,12 @@ export class ImportManager {
* @param fileName of the geometry file (.gltf,.glb or a zip with such file(s))
* @returns Promise for loading the geometry.
*/
public parseGLTFGeometry(fileName: string): Promise<GeometryUIParameters[]> {
return this.zipHandlingWrapper(
fileName,
this.parseGLTFGeometryFromArrayBuffer,
public parseGLTFGeometry(file: File): Promise<GeometryUIParameters[]> {
return this.zipHandlingFileWrapper(
file,
(data: ArrayBuffer, path: string, name: string) => {
return this.parseGLTFGeometryFromArrayBuffer(data, path, name);
},
);
}

Expand Down Expand Up @@ -454,6 +505,7 @@ export class ImportManager {

for (const scene of gltf.scenes) {
scene.visible = scene.userData.visible;
console.log('Dealing with scene ', scene.name);
const sceneName = this.processGLTFSceneName(scene.name);
this.processGeometry(scene, sceneName?.name ?? name);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,7 @@ export class ThreeManager {
*/
public async parseGLTFGeometry(file: File): Promise<GeometryUIParameters[]> {
const allGeometriesUIParameters =
await this.importManager.parseGLTFGeometry(file.name);
await this.importManager.parseGLTFGeometry(file);

for (const { object } of allGeometriesUIParameters) {
this.sceneManager.getGeometries().add(object);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ describe('IoOptionsDialogComponent', () => {
expect(mockDialogRef.close).toHaveBeenCalled();
});

it('should handle glTF file input', () => {
const files = mockFileList([
new File(['{}'], 'testfile.gltf', {
type: 'application/json',
}),
]);
component.handleGLTFInput(files);
});

describe('handleFileInput', () => {
beforeEach(() => {
jest.spyOn(component, 'handleFileInput').mockImplementation(() => {});
Expand Down Expand Up @@ -135,15 +144,6 @@ describe('IoOptionsDialogComponent', () => {
component.handleSceneInput(files);
});

it('should handle glTF file input', () => {
const files = mockFileList([
new File(['{}'], 'testfile.gltf', {
type: 'application/json',
}),
]);
component.handleGLTFInput(files);
});

it('should handle phoenix file input', () => {
const files = mockFileList([
new File(['{}'], 'testfile.phnx', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,12 @@ export class IOOptionsDialogComponent implements OnInit {
}

handleGLTFInput(files: FileList) {
const callback = (content: any) => {
this.eventDisplay.parseGLTFGeometry(content);
const callback = (file: File) => {
this.eventDisplay.parseGLTFGeometry(file);
};
this.handleFileInput(files[0], 'gltf,glb,gltf.zip,glb.zip', callback);
if (this.isFileOfExtension(files[0].name, 'gltf,glb,gltf.zip,glb.zip')) {
callback(files[0]);
}
}

handlePhoenixInput(files: FileList) {
Expand Down Expand Up @@ -193,7 +195,7 @@ export class IOOptionsDialogComponent implements OnInit {
}

async handleZipEventDataInput(files: FileList) {
if (!this.isFileOfExtension(files[0].name, 'zip')) {
if (!this.isFileOfExtension(files[0].name, 'zip,json.zip')) {
return;
}

Expand Down Expand Up @@ -251,7 +253,9 @@ export class IOOptionsDialogComponent implements OnInit {
}

private isFileOfExtension(fileName: string, extensions: string): boolean {
if (extensions.split(',').includes(fileName.split('.', 2).pop())) {
if (
extensions.split(',').includes(fileName.slice(fileName.indexOf('.') + 1))
) {
return true;
}

Expand Down

0 comments on commit 810bbed

Please sign in to comment.