add implementation for onDispose to ThermionViewerFFI

This commit is contained in:
Nick Fisher
2024-06-19 12:59:16 +08:00
parent cfa7805970
commit 025e39318d

View File

@@ -1,15 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:thermion_dart/thermion_dart/compatibility/compatibility.dart'; import 'package:thermion_dart/thermion_dart/compatibility/compatibility.dart';
import 'package:thermion_dart/thermion_dart/entities/gizmo.dart'; import 'package:thermion_dart/thermion_dart/entities/gizmo.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
import 'thermion_viewer.dart'; import 'thermion_viewer.dart';
import 'scene.dart'; import 'scene.dart';
import 'compatibility/compatibility.dart';
// ignore: constant_identifier_names // ignore: constant_identifier_names
const ThermionEntity _FILAMENT_ASSET_ERROR = 0; const ThermionEntity _FILAMENT_ASSET_ERROR = 0;
@@ -19,8 +15,8 @@ typedef RenderCallback = Pointer<NativeFunction<Void Function(Pointer<Void>)>>;
class ThermionViewerFFI extends ThermionViewer { class ThermionViewerFFI extends ThermionViewer {
final _compat = Compatibility(); final _compat = Compatibility();
late SceneImpl _scene; SceneImpl? _scene;
Scene get scene => _scene; Scene get scene => _scene!;
double _pixelRatio = 1.0; double _pixelRatio = 1.0;
@@ -172,14 +168,39 @@ class ThermionViewerFFI extends ThermionViewer {
set_frame_interval_ffi(_viewer!, interval); set_frame_interval_ffi(_viewer!, interval);
} }
final _onDispose = <Future Function()>[];
/// ///
/// ///
/// ///
@override @override
Future dispose() async { 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!); destroy_filament_viewer_ffi(_viewer!);
_sceneManager = null; _sceneManager = null;
_viewer = 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"); throw Exception("Failed to add light to scene");
} }
_scene.registerLight(entity); _scene!.registerLight(entity);
return entity; return entity;
} }
@@ -326,7 +347,7 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future removeLight(ThermionEntity entity) async { Future removeLight(ThermionEntity entity) async {
_scene.unregisterLight(entity); _scene!.unregisterLight(entity);
remove_light_ffi(_viewer!, entity); remove_light_ffi(_viewer!, entity);
} }
@@ -337,7 +358,7 @@ class ThermionViewerFFI extends ThermionViewer {
Future clearLights() async { Future clearLights() async {
clear_lights_ffi(_viewer!); clear_lights_ffi(_viewer!);
_scene.clearLights(); _scene!.clearLights();
} }
/// ///
@@ -393,7 +414,7 @@ class ThermionViewerFFI extends ThermionViewer {
if (entity == _FILAMENT_ASSET_ERROR) { if (entity == _FILAMENT_ASSET_ERROR) {
throw Exception("An error occurred loading the asset at $path"); throw Exception("An error occurred loading the asset at $path");
} }
_scene.registerEntity(entity); _scene!.registerEntity(entity);
return entity; return entity;
} }
@@ -404,11 +425,6 @@ class ThermionViewerFFI extends ThermionViewer {
@override @override
Future<ThermionEntity> loadGltf(String path, String relativeResourcePath, Future<ThermionEntity> loadGltf(String path, String relativeResourcePath,
{bool force = false}) async { {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<Char>(); final pathPtr = path.toNativeUtf8(allocator: allocator).cast<Char>();
final relativeResourcePathPtr = final relativeResourcePathPtr =
relativeResourcePath.toNativeUtf8(allocator: allocator).cast<Char>(); relativeResourcePath.toNativeUtf8(allocator: allocator).cast<Char>();
@@ -419,7 +435,7 @@ class ThermionViewerFFI extends ThermionViewer {
if (entity == _FILAMENT_ASSET_ERROR) { if (entity == _FILAMENT_ASSET_ERROR) {
throw Exception("An error occurred loading the asset at $path"); throw Exception("An error occurred loading the asset at $path");
} }
_scene.registerEntity(entity); _scene!.registerEntity(entity);
return entity; return entity;
} }
@@ -676,8 +692,8 @@ class ThermionViewerFFI extends ThermionViewer {
Future addBoneAnimation(ThermionEntity entity, BoneAnimationData animation, Future addBoneAnimation(ThermionEntity entity, BoneAnimationData animation,
{int skinIndex = 0, {int skinIndex = 0,
double fadeOutInSecs = 0.0, double fadeOutInSecs = 0.0,
double fadeInInSecs = 0.0, double fadeInInSecs = 0.0,
double maxDelta=1.0}) async { double maxDelta = 1.0}) async {
if (animation.space != Space.Bone && if (animation.space != Space.Bone &&
animation.space != Space.ParentWorldRotation) { animation.space != Space.ParentWorldRotation) {
throw UnimplementedError("TODO - support ${animation.space}"); throw UnimplementedError("TODO - support ${animation.space}");
@@ -720,7 +736,7 @@ class ThermionViewerFFI extends ThermionViewer {
var world = Matrix4.identity(); var world = Matrix4.identity();
// this odd use of ! is intentional, without it, the WASM optimizer gets in trouble // this odd use of ! is intentional, without it, the WASM optimizer gets in trouble
var parentBoneEntity = (await getParent(boneEntity))!; var parentBoneEntity = (await getParent(boneEntity))!;
while(true) { while (true) {
if (!bones.contains(parentBoneEntity!)) { if (!bones.contains(parentBoneEntity!)) {
break; break;
} }
@@ -758,7 +774,7 @@ class ThermionViewerFFI extends ThermionViewer {
numFrames, numFrames,
animation.frameLengthInMs, animation.frameLengthInMs,
fadeOutInSecs, fadeOutInSecs,
fadeInInSecs, fadeInInSecs,
maxDelta); maxDelta);
} }
allocator.free(data); allocator.free(data);
@@ -894,7 +910,7 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future removeEntity(ThermionEntity entity) async { Future removeEntity(ThermionEntity entity) async {
_scene.unregisterEntity(entity); _scene!.unregisterEntity(entity);
await withVoidCallback( await withVoidCallback(
(callback) => remove_entity_ffi(_viewer!, entity, callback)); (callback) => remove_entity_ffi(_viewer!, entity, callback));
@@ -911,7 +927,7 @@ class ThermionViewerFFI extends ThermionViewer {
await withVoidCallback((callback) { await withVoidCallback((callback) {
clear_entities_ffi(_viewer!, callback); clear_entities_ffi(_viewer!, callback);
}); });
_scene.clearEntities(); _scene!.clearEntities();
} }
/// ///
@@ -1296,7 +1312,7 @@ class ThermionViewerFFI extends ThermionViewer {
x: (x / _pixelRatio).toDouble(), x: (x / _pixelRatio).toDouble(),
y: (viewportDimensions.$2 - y) / _pixelRatio y: (viewportDimensions.$2 - y) / _pixelRatio
)); ));
_scene.registerSelected(entityId); _scene!.registerSelected(entityId);
} }
late NativeCallable<Void Function(Int32 entityId, Int x, Int y)> late NativeCallable<Void Function(Int32 entityId, Int x, Int y)>
@@ -1307,7 +1323,7 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
void pick(int x, int y) async { void pick(int x, int y) async {
_scene.unregisterSelected(); _scene!.unregisterSelected();
filament_pick( filament_pick(
_viewer!, _viewer!,
@@ -1624,7 +1640,7 @@ class ThermionViewerFFI extends ThermionViewer {
throw Exception("Failed to create geometry"); throw Exception("Failed to create geometry");
} }
_scene.registerEntity(entity); _scene!.registerEntity(entity);
allocator.free(materialPathPtr); allocator.free(materialPathPtr);
allocator.free(vertexPtr); allocator.free(vertexPtr);