From 025e39318db71185fd817f3bd6fe17f2d4ed6c70 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Wed, 19 Jun 2024 12:59:16 +0800 Subject: [PATCH] add implementation for onDispose to ThermionViewerFFI --- .../thermion_dart/thermion_viewer_ffi.dart | 66 ++++++++++++------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/thermion_dart/lib/thermion_dart/thermion_viewer_ffi.dart b/thermion_dart/lib/thermion_dart/thermion_viewer_ffi.dart index ab83957e..894b689f 100644 --- a/thermion_dart/lib/thermion_dart/thermion_viewer_ffi.dart +++ b/thermion_dart/lib/thermion_dart/thermion_viewer_ffi.dart @@ -1,15 +1,11 @@ import 'dart:async'; -import 'dart:io'; import 'dart:math'; import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'package:thermion_dart/thermion_dart/compatibility/compatibility.dart'; - import 'package:thermion_dart/thermion_dart/entities/gizmo.dart'; - import 'package:vector_math/vector_math_64.dart'; import 'thermion_viewer.dart'; import 'scene.dart'; -import 'compatibility/compatibility.dart'; // ignore: constant_identifier_names const ThermionEntity _FILAMENT_ASSET_ERROR = 0; @@ -19,8 +15,8 @@ typedef RenderCallback = Pointer)>>; class ThermionViewerFFI extends ThermionViewer { final _compat = Compatibility(); - late SceneImpl _scene; - Scene get scene => _scene; + SceneImpl? _scene; + Scene get scene => _scene!; double _pixelRatio = 1.0; @@ -172,14 +168,39 @@ class ThermionViewerFFI extends ThermionViewer { set_frame_interval_ffi(_viewer!, interval); } + final _onDispose = []; + /// /// /// @override Future dispose() async { + if (_viewer == null) { + // we've already cleaned everything up, ignore the call to dispose + return; + } + await setRendering(false); + await clearEntities(); + await clearLights(); + await _scene!.dispose(); + _scene = null; destroy_filament_viewer_ffi(_viewer!); + _sceneManager = null; _viewer = null; + await _pickResultController.close(); + + for (final callback in _onDispose) { + await callback.call(); + } + _onDispose.clear(); + } + + /// + /// + /// + void onDispose(Future Function() callback) { + _onDispose.add(callback); } /// @@ -317,7 +338,7 @@ class ThermionViewerFFI extends ThermionViewer { throw Exception("Failed to add light to scene"); } - _scene.registerLight(entity); + _scene!.registerLight(entity); return entity; } @@ -326,7 +347,7 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future removeLight(ThermionEntity entity) async { - _scene.unregisterLight(entity); + _scene!.unregisterLight(entity); remove_light_ffi(_viewer!, entity); } @@ -337,7 +358,7 @@ class ThermionViewerFFI extends ThermionViewer { Future clearLights() async { clear_lights_ffi(_viewer!); - _scene.clearLights(); + _scene!.clearLights(); } /// @@ -393,7 +414,7 @@ class ThermionViewerFFI extends ThermionViewer { if (entity == _FILAMENT_ASSET_ERROR) { throw Exception("An error occurred loading the asset at $path"); } - _scene.registerEntity(entity); + _scene!.registerEntity(entity); return entity; } @@ -404,11 +425,6 @@ class ThermionViewerFFI extends ThermionViewer { @override Future loadGltf(String path, String relativeResourcePath, {bool force = false}) async { - // if (Platform.isWindows && !force) { - // throw Exception( - // "loadGltf has a race condition on Windows which is likely to crash your program. If you really want to try, pass force=true to loadGltf"); - // } - final pathPtr = path.toNativeUtf8(allocator: allocator).cast(); final relativeResourcePathPtr = relativeResourcePath.toNativeUtf8(allocator: allocator).cast(); @@ -419,7 +435,7 @@ class ThermionViewerFFI extends ThermionViewer { if (entity == _FILAMENT_ASSET_ERROR) { throw Exception("An error occurred loading the asset at $path"); } - _scene.registerEntity(entity); + _scene!.registerEntity(entity); return entity; } @@ -676,8 +692,8 @@ class ThermionViewerFFI extends ThermionViewer { Future addBoneAnimation(ThermionEntity entity, BoneAnimationData animation, {int skinIndex = 0, double fadeOutInSecs = 0.0, - double fadeInInSecs = 0.0, - double maxDelta=1.0}) async { + double fadeInInSecs = 0.0, + double maxDelta = 1.0}) async { if (animation.space != Space.Bone && animation.space != Space.ParentWorldRotation) { throw UnimplementedError("TODO - support ${animation.space}"); @@ -720,7 +736,7 @@ class ThermionViewerFFI extends ThermionViewer { var world = Matrix4.identity(); // this odd use of ! is intentional, without it, the WASM optimizer gets in trouble var parentBoneEntity = (await getParent(boneEntity))!; - while(true) { + while (true) { if (!bones.contains(parentBoneEntity!)) { break; } @@ -758,7 +774,7 @@ class ThermionViewerFFI extends ThermionViewer { numFrames, animation.frameLengthInMs, fadeOutInSecs, - fadeInInSecs, + fadeInInSecs, maxDelta); } allocator.free(data); @@ -894,7 +910,7 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future removeEntity(ThermionEntity entity) async { - _scene.unregisterEntity(entity); + _scene!.unregisterEntity(entity); await withVoidCallback( (callback) => remove_entity_ffi(_viewer!, entity, callback)); @@ -911,7 +927,7 @@ class ThermionViewerFFI extends ThermionViewer { await withVoidCallback((callback) { clear_entities_ffi(_viewer!, callback); }); - _scene.clearEntities(); + _scene!.clearEntities(); } /// @@ -1296,7 +1312,7 @@ class ThermionViewerFFI extends ThermionViewer { x: (x / _pixelRatio).toDouble(), y: (viewportDimensions.$2 - y) / _pixelRatio )); - _scene.registerSelected(entityId); + _scene!.registerSelected(entityId); } late NativeCallable @@ -1307,7 +1323,7 @@ class ThermionViewerFFI extends ThermionViewer { /// @override void pick(int x, int y) async { - _scene.unregisterSelected(); + _scene!.unregisterSelected(); filament_pick( _viewer!, @@ -1624,7 +1640,7 @@ class ThermionViewerFFI extends ThermionViewer { throw Exception("Failed to create geometry"); } - _scene.registerEntity(entity); + _scene!.registerEntity(entity); allocator.free(materialPathPtr); allocator.free(vertexPtr);