add onLoad/onUnload streams

This commit is contained in:
Nick Fisher
2023-11-08 17:47:11 +08:00
parent 7b0dcf2c1c
commit af543f46b2
2 changed files with 56 additions and 9 deletions

View File

@@ -27,6 +27,17 @@ class TextureDetails {
}
abstract class FilamentController {
///
/// A Stream containing every FilamentEntity added to the scene (i.e. via [loadGlb], [loadGltf] or [addLight]).
/// This is provided for convenience so you can set listeners in front-end widgets that can respond to entity loads without manually passing around the FilamentEntity returned from those methods.
///
Stream<FilamentEntity> get onLoad;
///
/// A Stream containing every FilamentEntity removed from the scene (i.e. via [removeAsset], [clearAssets], [removeLight] or [clearLights]).
Stream<FilamentEntity> get onUnload;
///
/// A [ValueNotifier] that holds the current dimensions (in physical pixels, after multiplying by pixel ratio) of the FilamentWidget.
/// If you need to perform work as early as possible, add a listener to this property before a [FilamentWidget] has been inserted into the widget hierarchy.
@@ -201,7 +212,8 @@ abstract class FilamentController {
/// [relativeResourcePath] is the folder path where the glTF resources are stored;
/// this is usually the parent directory of the .gltf file itself.
///
Future<FilamentEntity> loadGltf(String path, String relativeResourcePath);
Future<FilamentEntity> loadGltf(String path, String relativeResourcePath,
{bool force = false});
///
/// Called by `FilamentGestureDetector`. You probably don't want to call this yourself.

View File

@@ -20,7 +20,14 @@ const FilamentEntity _FILAMENT_ASSET_ERROR = 0;
class FilamentControllerFFI extends FilamentController {
final _channel = const MethodChannel("app.polyvox.filament/event");
///
/// This will be set on constructor invocation.
/// On Windows, this will be set to the value returned by the [usesBackingWindow] method call.
/// On Web, this will always be true;
/// On other platforms, this will always be false.
///
bool _usesBackingWindow = false;
@override
bool get requiresTextureWidget => !_usesBackingWindow;
@@ -49,6 +56,15 @@ class FilamentControllerFFI extends FilamentController {
Timer? _resizeTimer;
final _lights = <FilamentEntity>{};
final _entities = <FilamentEntity>{};
final _onLoadController = StreamController<FilamentEntity>.broadcast();
Stream<FilamentEntity> get onLoad => _onLoadController.stream;
final _onUnloadController = StreamController<FilamentEntity>.broadcast();
Stream<FilamentEntity> get onUnload => _onUnloadController.stream;
///
/// This controller uses platform channels to bridge Dart with the C/C++ code for the Filament API.
/// Setting up the context/texture (since this is platform-specific) and the render ticker are platform-specific; all other methods are passed through by the platform channel to the methods specified in FlutterFilamentApi.h.
@@ -450,15 +466,19 @@ class FilamentControllerFFI extends FilamentController {
}
var entity = add_light_ffi(_viewer!, type, colour, intensity, posX, posY,
posZ, dirX, dirY, dirZ, castShadows);
_onLoadController.sink.add(entity);
_lights.add(entity);
return entity;
}
@override
Future removeLight(FilamentEntity light) async {
Future removeLight(FilamentEntity entity) async {
if (_viewer == null) {
throw Exception("No viewer available, ignoring");
}
remove_light_ffi(_viewer!, light);
_lights.remove(entity);
remove_light_ffi(_viewer!, entity);
_onUnloadController.add(entity);
}
@override
@@ -467,6 +487,10 @@ class FilamentControllerFFI extends FilamentController {
throw Exception("No viewer available, ignoring");
}
clear_lights_ffi(_viewer!);
for (final entity in _lights) {
_onUnloadController.add(entity);
}
_lights.clear();
}
@override
@@ -477,12 +501,14 @@ class FilamentControllerFFI extends FilamentController {
if (unlit) {
throw Exception("Not yet implemented");
}
var asset =
var entity =
load_glb_ffi(_assetManager!, path.toNativeUtf8().cast<Char>(), unlit);
if (asset == _FILAMENT_ASSET_ERROR) {
if (entity == _FILAMENT_ASSET_ERROR) {
throw Exception("An error occurred loading the asset at $path");
}
return asset;
_entities.add(entity);
_onLoadController.sink.add(entity);
return entity;
}
@override
@@ -495,12 +521,14 @@ class FilamentControllerFFI extends FilamentController {
if (_viewer == null) {
throw Exception("No viewer available, ignoring");
}
var asset = load_gltf_ffi(_assetManager!, path.toNativeUtf8().cast<Char>(),
var entity = load_gltf_ffi(_assetManager!, path.toNativeUtf8().cast<Char>(),
relativeResourcePath.toNativeUtf8().cast<Char>());
if (asset == _FILAMENT_ASSET_ERROR) {
if (entity == _FILAMENT_ASSET_ERROR) {
throw Exception("An error occurred loading the asset at $path");
}
return asset;
_entities.add(entity);
_onLoadController.sink.add(entity);
return entity;
}
@override
@@ -700,7 +728,9 @@ class FilamentControllerFFI extends FilamentController {
if (_viewer == null) {
throw Exception("No viewer available, ignoring");
}
_entities.remove(entity);
remove_asset_ffi(_viewer!, entity);
_onUnloadController.add(entity);
}
@override
@@ -709,6 +739,11 @@ class FilamentControllerFFI extends FilamentController {
throw Exception("No viewer available, ignoring");
}
clear_assets_ffi(_viewer!);
for (final entity in _entities) {
_onUnloadController.add(entity);
}
_entities.clear();
}
@override