require createViewer to be specified manually
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:flutter_filament/animations/animation_data.dart';
|
||||
@@ -11,9 +10,9 @@ enum ToneMapper { ACES, FILMIC, LINEAR }
|
||||
|
||||
class TextureDetails {
|
||||
final int textureId;
|
||||
|
||||
|
||||
// both width and height are in physical, not logical pixels
|
||||
final int width;
|
||||
final int width;
|
||||
final int height;
|
||||
|
||||
TextureDetails(
|
||||
@@ -21,12 +20,11 @@ class TextureDetails {
|
||||
}
|
||||
|
||||
abstract class FilamentController {
|
||||
|
||||
///
|
||||
///
|
||||
/// Whether a Flutter Texture widget should be inserted into the widget hierarchy.
|
||||
/// This will be false on certain platforms where we use a transparent window underlay.
|
||||
/// Used internally by [FilamentWidget]; you probably don't need to access this property directly.
|
||||
///
|
||||
///
|
||||
bool get requiresTextureWidget;
|
||||
|
||||
///
|
||||
@@ -35,17 +33,6 @@ abstract class FilamentController {
|
||||
///
|
||||
final textureDetails = ValueNotifier<TextureDetails?>(null);
|
||||
|
||||
|
||||
///
|
||||
/// A stream to indicate whether a FilamentViewer is available.
|
||||
/// [FilamentWidget] will (asynchronously) create a [FilamentViewer] after being inserted into the widget hierarchy;
|
||||
/// listen to this stream beforehand to perform any work necessary once the viewer is available.
|
||||
/// [FilamentWidget] may also destroy/recreate the viewer on certain lifecycle events (e.g. backgrounding a mobile app);
|
||||
/// listen for any corresponding [false]/[true] events to perform related work.
|
||||
/// Note this is not a broadcast stream; only one listener can be registered and events will be buffered.
|
||||
///
|
||||
Stream<bool> get hasViewer;
|
||||
|
||||
///
|
||||
/// The result(s) of calling [pick] (see below).
|
||||
/// This may be a broadcast stream, so you should ensure you have subscribed to this stream before calling [pick].
|
||||
@@ -73,13 +60,6 @@ abstract class FilamentController {
|
||||
///
|
||||
Future setFrameRate(int framerate);
|
||||
|
||||
///
|
||||
/// Called by FilamentGestureDetector to set the pixel ratio (obtained from [MediaQuery]) before creating the texture/viewport.
|
||||
/// You may call this yourself if you want to increase/decrease the pixel density of the viewport, but calling this method won't do anything on its own.
|
||||
/// You will need to manually recreate the texture/viewer afterwards.
|
||||
///
|
||||
void setPixelRatio(double ratio);
|
||||
|
||||
///
|
||||
/// Destroys the viewer and all backing textures. You can leave the FilamentWidget in the hierarchy after this is called, but you will need to manually call [createViewer] to
|
||||
///
|
||||
@@ -96,24 +76,26 @@ abstract class FilamentController {
|
||||
Future destroyTexture();
|
||||
|
||||
///
|
||||
/// Called by [FilamentWidget]; you generally will not need to call this yourself.
|
||||
/// To recap, you can create a viewport is created in the Flutter rendering hierarchy by:
|
||||
/// 1) Create a FilamentController
|
||||
/// 2) Insert a FilamentWidget into the rendering tree, passing your FilamentController
|
||||
/// 3) Initially, the FilamentWidget will only contain an empty Container (by default, with a solid red background).
|
||||
/// This widget will render a single frame to get its actual size, then will itself call [createViewer]. You do not need to call [createViewer] yourself.
|
||||
/// This will dispatch a request to the native platform to create a hardware texture (Metal on iOS, OpenGL on Linux, GLES on Android and Windows) and a FilamentViewer (the main interface for manipulating the 3D scene) .
|
||||
/// 4) The FilamentController will notify FilamentWidget that a texture is available
|
||||
/// 5) The FilamentWidget will replace the empty Container with a Texture widget
|
||||
/// If you need to wait until a FilamentViewer has been created, listen to the [viewer] stream.
|
||||
/// Create a FilamentViewer. Must be called at least one frame after a [FilamentWidget] has been inserted into the rendering hierarchy.
|
||||
///
|
||||
Future createViewer(Rect rect);
|
||||
/// Before a FilamentViewer is created, the FilamentWidget will only contain an empty Container (by default, with a solid red background).
|
||||
/// FilamentWidget will then call [setDimensions] with dimensions/pixel ratio of the viewport
|
||||
/// Calling [createViewer] will then dispatch a request to the native platform to create a hardware texture (Metal on iOS, OpenGL on Linux, GLES on Android and Windows) and a FilamentViewer (the main interface for manipulating the 3D scene) .
|
||||
/// [FilamentWidget] will be notified that a texture is available and will replace the empty Container with a Texture widget
|
||||
///
|
||||
Future createViewer();
|
||||
|
||||
///
|
||||
/// Resize the viewport & backing texture.
|
||||
/// Sets the dimensions of the viewport and pixel ratio (obtained from [MediaQuery]) to be used the next time [resize] or [createViewer] is called.
|
||||
/// This is called by FilamentWidget; you shouldn't need to invoke this manually.
|
||||
///
|
||||
Future resize(Rect rect);
|
||||
Future setDimensions(ui.Rect rect, double pixelRatio);
|
||||
|
||||
///
|
||||
/// Resize the viewport & backing texture to the current dimensions (as last set by [setDimensions]).
|
||||
/// This is called by FilamentWidget; you shouldn't need to invoke this manually.
|
||||
///
|
||||
Future resize();
|
||||
|
||||
///
|
||||
/// Set the background image to [path] (which should have a file extension .png, .jpg, or .ktx).
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'dart:io';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:flutter_filament/filament_controller.dart';
|
||||
|
||||
@@ -31,9 +32,10 @@ class FilamentControllerFFI extends FilamentController {
|
||||
|
||||
final String? uberArchivePath;
|
||||
|
||||
Pointer<Void> _driver = nullptr.cast<Void>();
|
||||
|
||||
@override
|
||||
Stream<bool> get hasViewer => _hasViewerController.stream;
|
||||
final _hasViewerController = StreamController<bool>();
|
||||
final rect = ValueNotifier<Rect?>(null);
|
||||
|
||||
@override
|
||||
Stream<FilamentEntity> get pickResult => _pickResultController.stream;
|
||||
@@ -62,8 +64,9 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_resizingWidth = call.arguments[0];
|
||||
_resizingHeight = call.arguments[1];
|
||||
_resizeTimer = Timer(const Duration(milliseconds: 500), () async {
|
||||
await resize(Offset.zero &
|
||||
ui.Size(_resizingWidth!.toDouble(), _resizingHeight!.toDouble()));
|
||||
this.rect.value = Offset.zero &
|
||||
ui.Size(_resizingWidth!.toDouble(), _resizingHeight!.toDouble());
|
||||
await resize();
|
||||
});
|
||||
});
|
||||
late DynamicLibrary dl;
|
||||
@@ -73,15 +76,15 @@ class FilamentControllerFFI extends FilamentController {
|
||||
dl = DynamicLibrary.open("libflutter_filament_android.so");
|
||||
}
|
||||
_lib = NativeLibrary(dl);
|
||||
if(Platform.isWindows) {
|
||||
if (Platform.isWindows) {
|
||||
_channel.invokeMethod("usesBackingWindow").then((result) {
|
||||
_usesBackingWindow = result;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool _rendering = false;
|
||||
@override
|
||||
bool get rendering => _rendering;
|
||||
|
||||
@override
|
||||
@@ -107,9 +110,10 @@ class FilamentControllerFFI extends FilamentController {
|
||||
}
|
||||
|
||||
@override
|
||||
void setPixelRatio(double ratio) {
|
||||
Future setDimensions(Rect rect, double ratio) async {
|
||||
this.rect.value = Rect.fromLTWH(rect.left, rect.top,
|
||||
rect.width * _pixelRatio, rect.height * _pixelRatio);
|
||||
_pixelRatio = ratio;
|
||||
print("Set pixel ratio to $ratio");
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -129,7 +133,6 @@ class FilamentControllerFFI extends FilamentController {
|
||||
|
||||
_assetManager = null;
|
||||
_lib.destroy_filament_viewer_ffi(viewer!);
|
||||
_hasViewerController.add(false);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -141,14 +144,15 @@ class FilamentControllerFFI extends FilamentController {
|
||||
print("Texture destroyed");
|
||||
}
|
||||
|
||||
Pointer<Void> _driver = nullptr.cast<Void>();
|
||||
|
||||
///
|
||||
/// Called by `FilamentWidget`. You do not need to call this yourself.
|
||||
///
|
||||
@override
|
||||
Future createViewer(Rect rect) async {
|
||||
|
||||
Future createViewer() async {
|
||||
if (rect.value == null) {
|
||||
throw Exception(
|
||||
"Dimensions have not yet been set by FilamentWidget. You need to wait for at least one frame after FilamentWidget has been inserted into the hierarchy");
|
||||
}
|
||||
if (_viewer != null) {
|
||||
throw Exception(
|
||||
"Viewer already exists, make sure you call destroyViewer first");
|
||||
@@ -164,8 +168,6 @@ class FilamentControllerFFI extends FilamentController {
|
||||
throw Exception("Failed to get resource loader");
|
||||
}
|
||||
|
||||
rect = Rect.fromLTWH(rect.left, rect.top, rect.width * _pixelRatio, rect.height * _pixelRatio);
|
||||
|
||||
if (Platform.isWindows && requiresTextureWidget) {
|
||||
_driver = Pointer<Void>.fromAddress(
|
||||
await _channel.invokeMethod("getDriverPlatform"));
|
||||
@@ -178,7 +180,9 @@ class FilamentControllerFFI extends FilamentController {
|
||||
var renderCallbackOwner =
|
||||
Pointer<Void>.fromAddress(renderCallbackResult[1]);
|
||||
|
||||
var renderingSurface = await _createRenderingSurface(rect);
|
||||
var renderingSurface = await _createRenderingSurface();
|
||||
|
||||
print("Got rendering surface");
|
||||
|
||||
_viewer = _lib.create_filament_viewer_ffi(
|
||||
Pointer<Void>.fromAddress(renderingSurface.sharedContext ?? 0),
|
||||
@@ -187,7 +191,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
loader,
|
||||
renderCallback,
|
||||
renderCallbackOwner);
|
||||
|
||||
print("Created viewer");
|
||||
if (_viewer!.address == 0) {
|
||||
throw Exception("Failed to create viewer. Check logs for details");
|
||||
}
|
||||
@@ -195,34 +199,36 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_assetManager = _lib.get_asset_manager(_viewer!);
|
||||
|
||||
_lib.create_swap_chain_ffi(_viewer!, renderingSurface.surface,
|
||||
rect.width.toInt(), rect.height.toInt());
|
||||
rect.value!.width.toInt(), rect.value!.height.toInt());
|
||||
print("Created swap chain");
|
||||
if (renderingSurface.textureHandle != 0) {
|
||||
print(
|
||||
"Creating render target from native texture ${renderingSurface.textureHandle}");
|
||||
_lib.create_render_target_ffi(_viewer!, renderingSurface.textureHandle,
|
||||
rect.width.toInt(), rect.height.toInt());
|
||||
rect.value!.width.toInt(), rect.value!.height.toInt());
|
||||
}
|
||||
|
||||
textureDetails.value = TextureDetails(
|
||||
textureId: renderingSurface.flutterTextureId!,
|
||||
width: rect.width.toInt(),
|
||||
height: rect.height.toInt());
|
||||
|
||||
width: rect.value!.width.toInt(),
|
||||
height: rect.value!.height.toInt());
|
||||
print("texture details ${textureDetails.value}");
|
||||
_lib.update_viewport_and_camera_projection_ffi(
|
||||
_viewer!, rect.width.toInt(), rect.height.toInt(), 1.0);
|
||||
|
||||
_hasViewerController.add(true);
|
||||
_viewer!, rect.value!.width.toInt(), rect.value!.height.toInt(), 1.0);
|
||||
}
|
||||
|
||||
Future<RenderingSurface> _createRenderingSurface(Rect rect) async {
|
||||
return RenderingSurface.from(await _channel.invokeMethod(
|
||||
"createTexture",
|
||||
[rect.width, rect.height, rect.left, rect.top]));
|
||||
Future<RenderingSurface> _createRenderingSurface() async {
|
||||
return RenderingSurface.from(await _channel.invokeMethod("createTexture", [
|
||||
rect.value!.width,
|
||||
rect.value!.height,
|
||||
rect.value!.left,
|
||||
rect.value!.top
|
||||
]));
|
||||
}
|
||||
|
||||
///
|
||||
/// When a FilamentWidget is resized, it will call the [resize] method below, which will tear down/recreate the swapchain.
|
||||
/// For "once-off" resizes, this is fine; however, this can be problematic for consecutive resizes
|
||||
/// For "once-off" resizes, this is fine; however, this can be problematic for consecutive resizes
|
||||
/// (e.g. dragging to expand/contract the parent window on desktop, or animating the size of the FilamentWidget itself).
|
||||
/// It is too expensive to recreate the swapchain multiple times per second.
|
||||
/// We therefore add a timer to FilamentWidget so that the call to [resize] is delayed (e.g. 500ms).
|
||||
@@ -286,8 +292,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
///
|
||||
bool _resizing = false;
|
||||
@override
|
||||
Future resize(Rect rect) async {
|
||||
|
||||
Future resize() async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("Cannot resize without active viewer");
|
||||
}
|
||||
@@ -296,54 +301,56 @@ class FilamentControllerFFI extends FilamentController {
|
||||
throw Exception("Resize currently underway, ignoring");
|
||||
}
|
||||
|
||||
rect = Rect.fromLTWH(rect.left, rect.top, rect.width * _pixelRatio, rect.height * _pixelRatio);
|
||||
|
||||
_resizing = true;
|
||||
|
||||
_lib.set_rendering_ffi(_viewer!, false);
|
||||
|
||||
if(!_usesBackingWindow) {
|
||||
if (!_usesBackingWindow) {
|
||||
_lib.destroy_swap_chain_ffi(_viewer!);
|
||||
}
|
||||
|
||||
|
||||
if (requiresTextureWidget) {
|
||||
if(textureDetails.value != null) {
|
||||
if (textureDetails.value != null) {
|
||||
await _channel.invokeMethod(
|
||||
"destroyTexture", textureDetails.value!.textureId);
|
||||
}
|
||||
} else if(Platform.isWindows) {
|
||||
print("Resizing window with rect $rect");
|
||||
await _channel.invokeMethod(
|
||||
"resizeWindow", [rect.width, rect.height, rect.left, rect.top]);
|
||||
} else if (Platform.isWindows) {
|
||||
print("Resizing window with rect $rect");
|
||||
await _channel.invokeMethod("resizeWindow", [
|
||||
rect.value!.width,
|
||||
rect.value!.height,
|
||||
rect.value!.left,
|
||||
rect.value!.top
|
||||
]);
|
||||
}
|
||||
|
||||
var renderingSurface = await _createRenderingSurface(rect);
|
||||
var renderingSurface = await _createRenderingSurface();
|
||||
|
||||
if (_viewer!.address == 0) {
|
||||
throw Exception("Failed to create viewer. Check logs for details");
|
||||
}
|
||||
|
||||
_assetManager = _lib.get_asset_manager(_viewer!);
|
||||
|
||||
if(!_usesBackingWindow) {
|
||||
|
||||
if (!_usesBackingWindow) {
|
||||
_lib.create_swap_chain_ffi(_viewer!, renderingSurface.surface,
|
||||
rect.width.toInt(), rect.height.toInt());
|
||||
rect.value!.width.toInt(), rect.value!.height.toInt());
|
||||
}
|
||||
|
||||
if (renderingSurface.textureHandle != 0) {
|
||||
print(
|
||||
"Creating render target from native texture ${renderingSurface.textureHandle}");
|
||||
_lib.create_render_target_ffi(_viewer!, renderingSurface.textureHandle,
|
||||
rect.width.toInt(), rect.height.toInt());
|
||||
rect.value!.width.toInt(), rect.value!.height.toInt());
|
||||
}
|
||||
|
||||
textureDetails.value = TextureDetails(
|
||||
textureId: renderingSurface.flutterTextureId!,
|
||||
width: rect.width.toInt(),
|
||||
height: rect.height.toInt());
|
||||
width: rect.value!.width.toInt(),
|
||||
height: rect.value!.height.toInt());
|
||||
|
||||
_lib.update_viewport_and_camera_projection_ffi(
|
||||
_viewer!, rect.width.toInt(), rect.height.toInt(), 1.0);
|
||||
_viewer!, rect.value!.width.toInt(), rect.value!.height.toInt(), 1.0);
|
||||
|
||||
await setRendering(_rendering);
|
||||
|
||||
@@ -739,6 +746,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_assetManager!, asset, index, loop, reverse, replaceActive, crossfade);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setAnimationFrame(
|
||||
FilamentEntity asset, int index, int animationFrame) async {
|
||||
if (_viewer == null) {
|
||||
@@ -747,6 +755,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_animation_frame(_assetManager!, asset, index, animationFrame);
|
||||
}
|
||||
|
||||
@override
|
||||
Future stopAnimation(FilamentEntity asset, int animationIndex) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -792,6 +801,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_bloom_ffi(_viewer!, bloom);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCameraFocalLength(double focalLength) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -799,6 +809,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_camera_focal_length(_viewer!, focalLength);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCameraFocusDistance(double focusDistance) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -806,6 +817,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_camera_focus_distance(_viewer!, focusDistance);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCameraPosition(double x, double y, double z) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -813,6 +825,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_camera_position(_viewer!, x, y, z);
|
||||
}
|
||||
|
||||
@override
|
||||
Future moveCameraToAsset(FilamentEntity asset) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -828,6 +841,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_view_frustum_culling(_viewer!, enabled);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCameraExposure(
|
||||
double aperture, double shutterSpeed, double sensitivity) async {
|
||||
if (_viewer == null) {
|
||||
@@ -836,6 +850,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_camera_exposure(_viewer!, aperture, shutterSpeed, sensitivity);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCameraRotation(double rads, double x, double y, double z) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -843,6 +858,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_camera_rotation(_viewer!, rads, x, y, z);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCameraModelMatrix(List<double> matrix) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -856,6 +872,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
calloc.free(ptr);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setMaterialColor(FilamentEntity asset, String meshName,
|
||||
int materialIndex, Color color) async {
|
||||
if (_viewer == null) {
|
||||
@@ -875,6 +892,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future transformToUnitCube(FilamentEntity asset) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -882,6 +900,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.transform_to_unit_cube(_assetManager!, asset);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setPosition(FilamentEntity asset, double x, double y, double z) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -889,6 +908,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_position(_assetManager!, asset, x, y, z);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setScale(FilamentEntity asset, double scale) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -896,6 +916,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_scale(_assetManager!, asset, scale);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setRotation(
|
||||
FilamentEntity asset, double rads, double x, double y, double z) async {
|
||||
if (_viewer == null) {
|
||||
@@ -904,6 +925,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
_lib.set_rotation(_assetManager!, asset, rads, x, y, z);
|
||||
}
|
||||
|
||||
@override
|
||||
Future hide(FilamentEntity asset, String meshName) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -913,6 +935,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
1) {}
|
||||
}
|
||||
|
||||
@override
|
||||
Future reveal(FilamentEntity asset, String meshName) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
@@ -924,6 +947,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String? getNameForEntity(FilamentEntity entity) {
|
||||
final result = _lib.get_name_for_entity(_assetManager!, entity);
|
||||
if (result == nullptr) {
|
||||
@@ -932,6 +956,7 @@ class FilamentControllerFFI extends FilamentController {
|
||||
return result.cast<Utf8>().toDartString();
|
||||
}
|
||||
|
||||
@override
|
||||
void pick(int x, int y) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
|
||||
@@ -121,16 +121,17 @@ class _SizedFilamentWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
|
||||
|
||||
String? _error;
|
||||
|
||||
late final AppLifecycleListener _appLifecycleListener;
|
||||
|
||||
Rect get _rect {
|
||||
final renderBox =(context.findRenderObject()) as RenderBox;
|
||||
final size = renderBox.size;
|
||||
final translation = renderBox.getTransformTo(null).getTranslation();
|
||||
return Rect.fromLTWH(translation.x, translation.y, size.width, size.height);
|
||||
late double _pixelRatio;
|
||||
|
||||
Rect get _rect {
|
||||
final renderBox = (context.findRenderObject()) as RenderBox;
|
||||
final size = renderBox.size;
|
||||
final translation = renderBox.getTransformTo(null).getTranslation();
|
||||
return Rect.fromLTWH(translation.x, translation.y, size.width, size.height);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -139,13 +140,12 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
|
||||
onStateChange: _handleStateChange,
|
||||
);
|
||||
|
||||
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
try {
|
||||
widget.controller.setPixelRatio(MediaQuery.of(context).devicePixelRatio);
|
||||
await widget.controller.createViewer(_rect);
|
||||
_pixelRatio = MediaQuery.of(context).devicePixelRatio;
|
||||
widget.controller.setDimensions(_rect, _pixelRatio);
|
||||
} catch (err) {
|
||||
print("Fatal error : $err");
|
||||
_error = err.toString();
|
||||
}
|
||||
setState(() {});
|
||||
@@ -167,17 +167,19 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
|
||||
// debug mode does need a longer timeout.
|
||||
_resizeTimer?.cancel();
|
||||
|
||||
_resizeTimer =
|
||||
Timer(Duration(milliseconds: (kReleaseMode || Platform.isWindows) ? 10 : 100), () async {
|
||||
_resizeTimer = Timer(
|
||||
Duration(milliseconds: (kReleaseMode || Platform.isWindows) ? 10 : 100),
|
||||
() async {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
while (_resizing) {
|
||||
await Future.delayed(const Duration(milliseconds: 20));
|
||||
}
|
||||
|
||||
|
||||
_resizing = true;
|
||||
await widget.controller.resize(_rect);
|
||||
await widget.controller.setDimensions(_rect, _pixelRatio);
|
||||
await widget.controller.resize();
|
||||
_resizeTimer = null;
|
||||
setState(() {});
|
||||
_resizing = false;
|
||||
|
||||
Reference in New Issue
Block a user