phantasmal-world/src/viewer/controllers/TextureController.ts

80 lines
3.4 KiB
TypeScript
Raw Normal View History

import { Controller } from "../../core/controllers/Controller";
import { filename_extension } from "../../core/util";
import { read_file } from "../../core/files";
2020-01-07 06:32:14 +08:00
import { is_xvm, parse_xvm, XvrTexture } from "../../core/data_formats/parsing/ninja/texture";
import { ArrayBufferCursor } from "../../core/data_formats/cursor/ArrayBufferCursor";
import { Endianness } from "../../core/data_formats/Endianness";
import { parse_afs } from "../../core/data_formats/parsing/afs";
import { LogManager } from "../../core/Logger";
import { WritableListProperty } from "../../core/observable/property/list/WritableListProperty";
import { list_property } from "../../core/observable";
import { ListProperty } from "../../core/observable/property/list/ListProperty";
import { prs_decompress } from "../../core/data_formats/compression/prs/decompress";
2020-01-07 06:32:14 +08:00
import { failure, Result, result_builder } from "../../core/Result";
import { Severity } from "../../core/Severity";
const logger = LogManager.get("viewer/controllers/TextureController");
export class TextureController extends Controller {
private readonly _textures: WritableListProperty<XvrTexture> = list_property();
readonly textures: ListProperty<XvrTexture> = this._textures;
2020-01-09 04:42:12 +08:00
load_file = async (file: File): Promise<Result<unknown>> => {
2020-01-07 06:32:14 +08:00
let result: Result<unknown>;
try {
const ext = filename_extension(file.name).toLowerCase();
const buffer = await read_file(file);
2020-01-07 06:32:14 +08:00
const cursor = new ArrayBufferCursor(buffer, Endianness.Little);
if (ext === "xvm") {
2020-01-07 06:32:14 +08:00
const xvm_result = (result = parse_xvm(cursor));
2020-01-07 06:32:14 +08:00
if (xvm_result.success) {
this._textures.val = xvm_result.value.textures;
}
} else if (ext === "afs") {
2020-01-07 06:32:14 +08:00
const rb = result_builder(logger);
const afs_result = parse_afs(cursor);
rb.add_result(afs_result);
2020-01-07 06:32:14 +08:00
if (!afs_result.success) {
result = rb.failure();
} else {
const textures: XvrTexture[] = afs_result.value.flatMap(file => {
const cursor = new ArrayBufferCursor(file, Endianness.Little);
2020-01-07 06:32:14 +08:00
if (is_xvm(cursor)) {
const xvm_result = parse_xvm(cursor);
rb.add_result(xvm_result);
return xvm_result.value?.textures ?? [];
} else {
const xvm_result = parse_xvm(prs_decompress(cursor.seek_start(0)));
rb.add_result(xvm_result);
return xvm_result.value?.textures ?? [];
}
2020-01-07 06:32:14 +08:00
});
if (textures.length) {
result = rb.success(textures);
} else {
result = rb.failure();
}
2020-01-07 06:32:14 +08:00
this._textures.val = textures;
}
} else {
logger.debug(`Unsupported file extension in filename "${file.name}".`);
result = failure([
{ severity: Severity.Error, ui_message: "Unsupported file type." },
]);
}
} catch (e) {
logger.error("Couldn't read file.", e);
2020-01-07 06:32:14 +08:00
result = failure();
}
2020-01-07 06:32:14 +08:00
2020-01-09 04:42:12 +08:00
return result;
};
}