refactor: export ThermionViewerWasm for web and hide FFI/WASM version

This commit is contained in:
Nick Fisher
2024-06-21 11:09:47 +08:00
parent c6c918907a
commit 0ec7e2af95
10 changed files with 890 additions and 1033 deletions

View File

@@ -1,5 +1,5 @@
library filament_dart;
export 'thermion_dart/thermion_viewer.dart';
export 'thermion_dart/thermion_viewer_ffi.dart';
export 'thermion_dart/compatibility/web/interop/thermion_viewer_wasm.dart' if (dart.library.io) 'thermion_dart/thermion_viewer_ffi.dart';
export 'thermion_dart/entities/entity_transform_controller.dart';

View File

@@ -1,118 +0,0 @@
import 'dart:async';
import 'dart:js_interop';
import 'package:thermion_dart/thermion_dart/compatibility/web/interop.dart';
import "allocator.dart";
export "allocator.dart";
export "thermion_dart.g.dart";
export 'package:ffi/ffi.dart' hide StringUtf8Pointer, Utf8Pointer;
export 'dart:ffi'
hide
Uint8Pointer,
FloatPointer,
DoublePointer,
Int32Pointer,
Int64Pointer,
PointerPointer,
Allocator;
const allocator = Allocator();
@AbiSpecificIntegerMapping({
Abi.androidArm: Uint8(),
Abi.androidArm64: Uint8(),
Abi.androidIA32: Int8(),
Abi.androidX64: Int8(),
Abi.androidRiscv64: Uint8(),
Abi.fuchsiaArm64: Uint8(),
Abi.fuchsiaX64: Int8(),
Abi.fuchsiaRiscv64: Uint8(),
Abi.iosArm: Int8(),
Abi.iosArm64: Int8(),
Abi.iosX64: Int8(),
Abi.linuxArm: Uint8(),
Abi.linuxArm64: Uint8(),
Abi.linuxIA32: Int8(),
Abi.linuxX64: Int8(),
Abi.linuxRiscv32: Uint8(),
Abi.linuxRiscv64: Uint8(),
Abi.macosArm64: Int8(),
Abi.macosX64: Int8(),
Abi.windowsArm64: Int8(),
Abi.windowsIA32: Int8(),
Abi.windowsX64: Int8(),
})
final class FooChar extends AbiSpecificInteger {
const FooChar();
}
class Compatibility {
final _foo = FooChar();
}
Future<void> withVoidCallback(
Function(Pointer<NativeFunction<Void Function()>>) func) async {
JSArray retVal = createVoidCallback();
var promise = retVal.toDart[0] as JSPromise<JSNumber>;
var fnPtrAddress = retVal.toDart[1] as JSNumber;
var fnPtr = Pointer<NativeFunction<Void Function()>>.fromAddress(
fnPtrAddress.toDartInt);
func(fnPtr);
await promise.toDart;
}
Future<int> withVoidPointerCallback(
void Function(Pointer<NativeFunction<Void Function(Pointer<Void>)>>)
func) async {
JSArray retVal = createVoidPointerCallback();
var promise = retVal.toDart[0] as JSPromise<JSNumber>;
var fnPtrAddress = retVal.toDart[1] as JSNumber;
var fnPtr = Pointer<NativeFunction<Void Function(Pointer<Void>)>>.fromAddress(
fnPtrAddress.toDartInt);
func(fnPtr);
final addr = await promise.toDart;
return addr.toDartInt;
}
Future<bool> withBoolCallback(
Function(Pointer<NativeFunction<Void Function(Bool)>>) func) async {
JSArray retVal = createBoolCallback();
var promise = retVal.toDart[0] as JSPromise<JSBoolean>;
var fnPtrAddress = retVal.toDart[1] as JSNumber;
var fnPtr = Pointer<NativeFunction<Void Function(Bool)>>.fromAddress(
fnPtrAddress.toDartInt);
func(fnPtr);
final addr = await promise.toDart;
return addr.toDart;
}
Future<int> withIntCallback(
Function(Pointer<NativeFunction<Void Function(Int32)>>) func) async {
JSArray retVal = createBoolCallback();
var promise = retVal.toDart[0] as JSPromise<JSNumber>;
var fnPtrAddress = retVal.toDart[1] as JSNumber;
var fnPtr = Pointer<NativeFunction<Void Function(Int32)>>.fromAddress(
fnPtrAddress.toDartInt);
func(fnPtr);
final addr = await promise.toDart;
return addr.toDartInt;
}
Future<String> withCharPtrCallback(
Function(Pointer<NativeFunction<Void Function(Pointer<Char>)>>)
func) async {
JSArray retVal = createVoidPointerCallback();
var promise = retVal.toDart[0] as JSPromise<JSNumber>;
var fnPtrAddress = retVal.toDart[1] as JSNumber;
var fnPtr = Pointer<NativeFunction<Void Function(Pointer<Char>)>>.fromAddress(
fnPtrAddress.toDartInt);
func(fnPtr);
final addr = await promise.toDart;
return Pointer<Utf8>.fromAddress(addr.toDartInt).toDartString();
}

View File

@@ -1,403 +0,0 @@
@JS()
library thermion_flutter_js;
import 'dart:js_interop';
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
///
/// An extension type on [JSObject] that represents a
/// Javascript shim implementation for the [ThermionViewer] interface.
///
extension type ThermionDartAPIJSShim(JSObject _) implements JSObject {
@JS('wasm_test')
external JSPromise wasm_test(String str);
@JS('set_rendering')
external JSPromise set_rendering(bool render);
@JS('render')
external JSPromise render();
@JS('setFrameRate')
external JSPromise setFrameRate(int framerate);
@JS('setBackgroundImage')
external JSPromise setBackgroundImage(String path, bool fillHeight);
@JS('setBackgroundImagePosition')
external JSPromise setBackgroundImagePosition(double x, double y, bool clamp);
@JS('clearBackgroundImage')
external JSPromise clearBackgroundImage();
@JS('setBackgroundColor')
external JSPromise setBackgroundColor(
double r, double g, double b, double alpha);
@JS('loadSkybox')
external JSPromise loadSkybox(String skyboxPath);
@JS('removeSkybox')
external JSPromise removeSkybox();
@JS('loadIbl')
external JSPromise loadIbl(String lightingPath, double intensity);
@JS('rotateIbl')
external JSPromise rotateIbl(JSArray<JSNumber> rotationMatrix);
@JS('removeIbl')
external JSPromise removeIbl();
@JS('addLight')
external JSPromise<JSNumber> addLight(
int type,
double colour,
double intensity,
double posX,
double posY,
double posZ,
double dirX,
double dirY,
double dirZ,
double falloffRadius,
double spotLightConeInner,
double spotLightConeOuter,
double sunAngularRadius,
double sunHaloSize,
double sunHaloFallof,
bool castShadows);
@JS('removeLight')
external JSPromise removeLight(ThermionEntity light);
@JS('clearLights')
external JSPromise clearLights();
@JS('loadGlb')
external JSPromise<JSNumber> loadGlb(String path, int numInstances);
@JS('createInstance')
external JSPromise<JSNumber> createInstance(ThermionEntity entity);
@JS('getInstanceCount')
external JSPromise<JSNumber> getInstanceCount(ThermionEntity entity);
@JS('getInstances')
external JSPromise<JSArray<JSNumber>> getInstances(ThermionEntity entity);
@JS('loadGltf')
external JSPromise<JSNumber> loadGltf(
String path, String relativeResourcePath);
@JS('panStart')
external JSPromise panStart(double x, double y);
@JS('panUpdate')
external JSPromise panUpdate(double x, double y);
@JS('panEnd')
external JSPromise panEnd();
@JS('rotateStart')
external JSPromise rotateStart(double x, double y);
@JS('rotateUpdate')
external JSPromise rotateUpdate(double x, double y);
@JS('rotateEnd')
external JSPromise rotateEnd();
@JS('setMorphTargetWeights')
external JSPromise setMorphTargetWeights(
ThermionEntity entity, JSArray<JSNumber> weights);
@JS('getMorphTargetNames')
external JSPromise<JSArray<JSString>> getMorphTargetNames(
ThermionEntity entity, ThermionEntity childEntity);
@JS('getBoneNames')
external JSPromise<JSArray<JSString>> getBoneNames(
ThermionEntity entity, int skinIndex);
@JS('getAnimationNames')
external JSPromise<JSArray<JSString>> getAnimationNames(
ThermionEntity entity);
@JS('getAnimationDuration')
external JSPromise<JSNumber> getAnimationDuration(
ThermionEntity entity, int animationIndex);
@JS('setMorphAnimationData')
external JSPromise setMorphAnimationData(
ThermionEntity entity,
JSArray<JSArray<JSNumber>> animation,
JSArray<JSString> morphTargets,
JSArray<JSString>? targetMeshNames,
double frameLengthInMs);
@JS('resetBones')
external JSPromise resetBones(ThermionEntity entity);
@JS('addBoneAnimation')
external JSPromise addBoneAnimation(
ThermionEntity entity,
JSArray<JSString> bones,
JSArray<JSArray<JSArray<JSNumber>>> frameData,
JSNumber frameLengthInMs,
JSNumber spaceEnum,
JSNumber skinIndex,
JSNumber fadeInInSecs,
JSNumber fadeOutInSecs,
JSNumber maxDelta);
@JS('removeEntity')
external JSPromise removeEntity(ThermionEntity entity);
@JS('clearEntities')
external JSPromise clearEntities();
@JS('zoomBegin')
external JSPromise zoomBegin();
@JS('zoomUpdate')
external JSPromise zoomUpdate(double x, double y, double z);
@JS('zoomEnd')
external JSPromise zoomEnd();
@JS('playAnimation')
external JSPromise playAnimation(
ThermionEntity entity,
int index,
bool loop,
bool reverse,
bool replaceActive,
double crossfade,
);
@JS('playAnimationByName')
external JSPromise playAnimationByName(
ThermionEntity entity,
String name,
bool loop,
bool reverse,
bool replaceActive,
double crossfade,
);
@JS('setAnimationFrame')
external JSPromise setAnimationFrame(
ThermionEntity entity, int index, int animationFrame);
@JS('stopAnimation')
external JSPromise stopAnimation(ThermionEntity entity, int animationIndex);
@JS('stopAnimationByName')
external JSPromise stopAnimationByName(ThermionEntity entity, String name);
@JS('setCamera')
external JSPromise setCamera(ThermionEntity entity, String? name);
@JS('setMainCamera')
external JSPromise setMainCamera();
@JS('getMainCamera')
external JSPromise<JSNumber> getMainCamera();
@JS('setCameraFov')
external JSPromise setCameraFov(double degrees, double width, double height);
@JS('setToneMapping')
external JSPromise setToneMapping(int mapper);
@JS('setBloom')
external JSPromise setBloom(double bloom);
@JS('setCameraFocalLength')
external JSPromise setCameraFocalLength(double focalLength);
@JS('setCameraCulling')
external JSPromise setCameraCulling(double near, double far);
@JS('getCameraCullingNear')
external JSPromise<JSNumber> getCameraCullingNear();
@JS('getCameraCullingFar')
external JSPromise<JSNumber> getCameraCullingFar();
@JS('setCameraFocusDistance')
external JSPromise setCameraFocusDistance(double focusDistance);
@JS('getCameraPosition')
external JSPromise<JSArray<JSNumber>> getCameraPosition();
@JS('getCameraModelMatrix')
external JSPromise<JSArray<JSNumber>> getCameraModelMatrix();
@JS('getCameraViewMatrix')
external JSPromise<JSArray<JSNumber>> getCameraViewMatrix();
@JS('getCameraProjectionMatrix')
external JSPromise<JSArray<JSNumber>> getCameraProjectionMatrix();
@JS('getCameraCullingProjectionMatrix')
external JSPromise<JSArray<JSNumber>> getCameraCullingProjectionMatrix();
@JS('getCameraFrustum')
external JSPromise<JSObject> getCameraFrustum();
@JS('setCameraPosition')
external JSPromise setCameraPosition(double x, double y, double z);
@JS('getCameraRotation')
external JSPromise<JSArray<JSNumber>> getCameraRotation();
@JS('moveCameraToAsset')
external JSPromise moveCameraToAsset(ThermionEntity entity);
@JS('setViewFrustumCulling')
external JSPromise setViewFrustumCulling(JSBoolean enabled);
@JS('setCameraExposure')
external JSPromise setCameraExposure(
double aperture, double shutterSpeed, double sensitivity);
@JS('setCameraRotation')
external JSPromise setCameraRotation(JSArray<JSNumber> quaternion);
@JS('setCameraModelMatrix')
external JSPromise setCameraModelMatrix(JSArray<JSNumber> matrix);
@JS('setMaterialColor')
external JSPromise setMaterialColor(ThermionEntity entity, String meshName,
int materialIndex, double r, double g, double b, double a);
@JS('transformToUnitCube')
external JSPromise transformToUnitCube(ThermionEntity entity);
@JS('setPosition')
external JSPromise setPosition(
ThermionEntity entity, double x, double y, double z);
@JS('setScale')
external JSPromise setScale(ThermionEntity entity, double scale);
@JS('setRotation')
external JSPromise setRotation(
ThermionEntity entity, double rads, double x, double y, double z);
@JS('queuePositionUpdate')
external JSPromise queuePositionUpdate(
ThermionEntity entity, double x, double y, double z, bool relative);
@JS('queueRotationUpdate')
external JSPromise queueRotationUpdate(ThermionEntity entity, double rads,
double x, double y, double z, bool relative);
@JS('queueRotationUpdateQuat')
external JSPromise queueRotationUpdateQuat(
ThermionEntity entity, JSArray<JSNumber> quat, bool relative);
@JS('setPostProcessing')
external JSPromise setPostProcessing(bool enabled);
@JS('setAntiAliasing')
external JSPromise setAntiAliasing(bool msaa, bool fxaa, bool taa);
@JS('setRotationQuat')
external JSPromise setRotationQuat(
ThermionEntity entity, JSArray<JSNumber> rotation);
@JS('reveal')
external JSPromise reveal(ThermionEntity entity, String? meshName);
@JS('hide')
external JSPromise hide(ThermionEntity entity, String? meshName);
@JS('pick')
external void pick(int x, int y);
@JS('getNameForEntity')
external String? getNameForEntity(ThermionEntity entity);
@JS('setCameraManipulatorOptions')
external JSPromise setCameraManipulatorOptions(
int mode,
double orbitSpeedX,
double orbitSpeedY,
double zoomSpeed,
);
@JS('getChildEntities')
external JSPromise<JSArray<JSNumber>> getChildEntities(
ThermionEntity parent, bool renderableOnly);
@JS('getChildEntity')
external JSPromise<JSNumber> getChildEntity(
ThermionEntity parent, String childName);
@JS('getChildEntityNames')
external JSPromise<JSArray<JSString>> getChildEntityNames(
ThermionEntity entity, bool renderableOnly);
@JS('setRecording')
external JSPromise setRecording(JSBoolean recording);
@JS('setRecordingOutputDirectory')
external JSPromise setRecordingOutputDirectory(String outputDirectory);
@JS('addAnimationComponent')
external JSPromise addAnimationComponent(ThermionEntity entity);
@JS('removeAnimationComponent')
external JSPromise removeAnimationComponent(ThermionEntity entity);
@JS('addCollisionComponent')
external JSPromise addCollisionComponent(ThermionEntity entity);
@JS('removeCollisionComponent')
external JSPromise removeCollisionComponent(ThermionEntity entity);
@JS('createGeometry')
external JSPromise<JSNumber> createGeometry(JSArray<JSNumber> vertices,
JSArray<JSNumber> indices, String? materialPath, int primitiveType);
@JS('setParent')
external JSPromise setParent(ThermionEntity child, ThermionEntity parent);
@JS('getParent')
external JSPromise<JSNumber> getParent(ThermionEntity child);
@JS('getParent')
external JSPromise<JSNumber> getBone(
ThermionEntity child, int boneIndex, int skinIndex);
@JS('testCollisions')
external JSPromise testCollisions(ThermionEntity entity);
@JS('setPriority')
external JSPromise setPriority(ThermionEntity entityId, int priority);
@JS('getLocalTransform')
external JSPromise<JSArray<JSNumber>> getLocalTransform(
ThermionEntity entity);
@JS('getWorldTransform')
external JSPromise<JSArray<JSNumber>> getWorldTransform(
ThermionEntity entity);
@JS('updateBoneMatrices')
external JSPromise updateBoneMatrices(ThermionEntity entity);
@JS('setTransform')
external JSPromise setTransform(
ThermionEntity entity, JSArray<JSNumber> transform);
@JS('setBoneTransform')
external JSPromise setBoneTransform(
ThermionEntity entity, int boneIndex, JSArray<JSNumber> transform, int skinIndex);
}

View File

@@ -2,7 +2,7 @@
library thermion_flutter_js;
import 'dart:js_interop';
import 'package:thermion_dart/thermion_dart/compatibility/web/interop/shims/thermion_viewer_js_shim.dart';
import 'package:thermion_dart/thermion_dart/compatibility/web/interop/thermion_viewer_js_shim.dart';
import 'package:vector_math/vector_math_64.dart' as v64;
import 'package:animation_tools_dart/animation_tools_dart.dart';
@@ -15,8 +15,8 @@ import 'package:vector_math/vector_math_64.dart';
/// A (Dart) class that wraps a (Dart) instance of [ThermionViewer],
/// but exported to JS by binding to a global property.
/// This is effectively an implementation of [ThermionViewerJSShim];
/// allowing users to interact with an instance of [ThermionViewer]
/// (presumably compiled to WASM) from any Javascript context (including
/// allowing users to interact with an instance of [ThermionViewer]
/// (presumably compiled to WASM) from any Javascript context (including
/// the browser console).
///
@JSExport()
@@ -24,9 +24,8 @@ class ThermionViewerJSDartBridge {
final ThermionViewer viewer;
ThermionViewerJSDartBridge(this.viewer);
void bind(
{String globalPropertyName = "filamentViewer"}) {
void bind({String globalPropertyName = "thermionViewer"}) {
var wrapper = createJSInteropWrapper<ThermionViewerJSDartBridge>(this)
as ThermionViewerJSShim;
globalContext.setProperty(globalPropertyName.toJS, wrapper);
@@ -131,10 +130,13 @@ class ThermionViewerJSDartBridge {
@JSExport()
JSPromise<JSNumber> loadGlb(String path, {int numInstances = 1}) {
print("Loading GLB from path $path with numInstances $numInstances");
return viewer
.loadGlb(path, numInstances: numInstances)
.then((entity) => entity.toJS)
.toJS;
.catchError((err) {
print("Error: $err");
}).toJS;
}
@JSExport()

View File

@@ -8,7 +8,7 @@ import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
import 'package:thermion_dart/thermion_dart/scene_impl.dart';
import 'package:vector_math/vector_math_64.dart';
import 'shims/thermion_viewer_js_shim.dart';
import 'thermion_viewer_js_shim.dart';
///
/// An [ThermionViewer] implementation that forwards calls to

View File

@@ -49,7 +49,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY build/out)
add_executable(${MODULE_NAME}
"${CMAKE_CURRENT_SOURCE_DIR}/../src/SceneManager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../src/ThermionViewerFFI.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../src/FilamentViewer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../src/ThermionDartApi.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../src/ThermionDartFFIApi.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../src/StreamBufferAdapter.cpp"
@@ -221,10 +221,10 @@ target_link_libraries(${MODULE_NAME}
tinyexr
)
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND dart --enable-experiment=native-assets run ffigen --config ffigen/web.yaml WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../
COMMAND ${CMAKE_COMMAND} -DINPUTFILE=${CMAKE_CURRENT_SOURCE_DIR}/../../lib/thermion_dart/compatibility/web/thermion_dart.g.dart -DOUTPUTFILE=${CMAKE_CURRENT_SOURCE_DIR}/../../lib/thermion_dart/compatibility/web/thermion_dart.g.dart "-DTO_REPLACE=symbol: '" "-DREPLACEMENT=symbol: '_" -P ${CMAKE_CURRENT_SOURCE_DIR}/replace_in_file.cmake
# COMMAND ${CMAKE_COMMAND} -DINPUTFILE=${CMAKE_CURRENT_SOURCE_DIR}/build/build/out/thermion_dart.js -DOUTPUTFILE=${CMAKE_CURRENT_SOURCE_DIR}/build/build/out/thermion_dart.js "-DTO_REPLACE=var moduleRtn" "-DREPLACEMENT=var moduleRtn\;GLctx=moduleArg.ctx" -P ${CMAKE_CURRENT_SOURCE_DIR}/replace_in_file.cmake
VERBATIM
)
# add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
# COMMAND dart --enable-experiment=native-assets run ffigen --config ffigen/web.yaml WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../
# COMMAND ${CMAKE_COMMAND} -DINPUTFILE=${CMAKE_CURRENT_SOURCE_DIR}/../../lib/thermion_dart/compatibility/web/thermion_dart.g.dart -DOUTPUTFILE=${CMAKE_CURRENT_SOURCE_DIR}/../../lib/thermion_dart/compatibility/web/thermion_dart.g.dart "-DTO_REPLACE=symbol: '" "-DREPLACEMENT=symbol: '_" -P ${CMAKE_CURRENT_SOURCE_DIR}/replace_in_file.cmake
# # COMMAND ${CMAKE_COMMAND} -DINPUTFILE=${CMAKE_CURRENT_SOURCE_DIR}/build/build/out/thermion_dart.js -DOUTPUTFILE=${CMAKE_CURRENT_SOURCE_DIR}/build/build/out/thermion_dart.js "-DTO_REPLACE=var moduleRtn" "-DREPLACEMENT=var moduleRtn\;GLctx=moduleArg.ctx" -P ${CMAKE_CURRENT_SOURCE_DIR}/replace_in_file.cmake
# VERBATIM
# )

View File

@@ -3,5 +3,4 @@ library thermion_flutter;
export 'thermion/thermion_flutter_plugin.dart';
export 'thermion/widgets/thermion_widget.dart';
export 'thermion/widgets/camera/gestures/thermion_gesture_detector.dart';
export 'package:thermion_dart/thermion_dart.dart';

View File

@@ -1,9 +1,9 @@
import 'package:thermion_dart/thermion_dart/compatibility/web/interop/thermion_viewer_wasm.dart';
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart';
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:thermion_dart/thermion_dart/compatibility/web/interop/thermion_dart_js_extension_type.dart';
import 'package:thermion_dart/thermion_dart/compatibility/web/interop/js_interop_filament_viewer.dart';
import 'package:web/web.dart';
class ThermionFlutterWebPlugin extends ThermionFlutterPlatform {
static void registerWith(Registrar registrar) {
@@ -12,30 +12,31 @@ class ThermionFlutterWebPlugin extends ThermionFlutterPlatform {
@override
Future<ThermionFlutterTexture?> createTexture(
int width, int height, int offsetLeft, int offsetRight) async {}
@override
Future destroyTexture(ThermionFlutterTexture texture) async {}
@override
void dispose() {
// TODO: implement dispose
int width, int height, int offsetLeft, int offsetRight) async {
return ThermionFlutterTexture(null, null, 0, 0, null);
}
@override
Future initialize({String? uberArchivePath}) async {
print("Creating viewer in web plugin");
viewer = JsInteropThermionViewerFFI("filamentViewer");
print("Waiting for initialized");
await viewer.initialized;
print("int complete");
Future destroyTexture(ThermionFlutterTexture texture) async {
// noop
}
@override
Future<ThermionFlutterTexture?> resizeTexture(ThermionFlutterTexture texture,
int width, int height, int offsetLeft, int offsetRight) async {}
int width, int height, int offsetLeft, int offsetRight) async {
return ThermionFlutterTexture(null, null, 0, 0, null);
}
@override
// TODO: implement viewer
late final ThermionViewer viewer;
Future<ThermionViewer> createViewer({String? uberArchivePath}) async {
final canvas = document.getElementById("canvas") as HTMLCanvasElement;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var width = window.innerWidth;
var height = window.innerHeight;
var viewer = ThermionViewerWasm();
await viewer.initialize(width, height, uberArchivePath: uberArchivePath);
return viewer;
}
}