diff --git a/ios/Classes/SwiftPolyvoxFilamentPlugin.swift b/ios/Classes/SwiftPolyvoxFilamentPlugin.swift index 0cc8d1db..f83fcee0 100644 --- a/ios/Classes/SwiftPolyvoxFilamentPlugin.swift +++ b/ios/Classes/SwiftPolyvoxFilamentPlugin.swift @@ -188,6 +188,10 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture createDisplayLink() result(self.flutterTextureId) case "resize": + if(viewer == nil) { + print("Error: cannot resize before a viewer has been created") + result(nil); + } rendering = false destroy_swap_chain(viewer) let args = call.arguments as! [Any] @@ -196,6 +200,7 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture create_swap_chain(viewer, pixelBufferTextureId, UInt32(args[0] as! Int64), UInt32(args[1] as! Int64)) update_viewport_and_camera_projection(viewer, Int32(args[0] as! Int64), Int32(args[1] as! Int64), Float(args[2] as! Double)) rendering = true + print("Resized to \(args[0])x\(args[1])") result(self.flutterTextureId); case "createFilamentViewer": let callback = make_resource_loader(loadResource, freeResource, Unmanaged.passUnretained(self).toOpaque()) @@ -205,6 +210,7 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture viewer = create_filament_viewer(nil, callback) var pixelBufferTextureId = unsafeBitCast(pixelBuffer!, to: UnsafeRawPointer.self) create_swap_chain(viewer, pixelBufferTextureId, UInt32(width), UInt32(height)) + update_viewport_and_camera_projection(viewer, Int32(args[0] as! Int64), Int32(args[1] as! Int64), 1.0) result(unsafeBitCast(viewer, to:Int64.self)) case "deleteFilamentViewer": delete_filament_viewer(viewer) @@ -545,10 +551,10 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture clear_assets(viewer) result(true) case "setCamera": - guard let args = call.arguments as? [Any], args.count == 3, + guard let args = call.arguments as? [Any], args.count == 2, let asset = args[0] as? Int64, let nodeName = args[1] as? String else { - result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected viewer, asset, and nodeName for set_camera", details: nil)) + result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected asset and nodeName for set_camera", details: nil)) return } let success = set_camera(viewer, Int32(asset), nodeName) diff --git a/ios/src/FilamentViewer.cpp b/ios/src/FilamentViewer.cpp index fb82d93e..66847d79 100644 --- a/ios/src/FilamentViewer.cpp +++ b/ios/src/FilamentViewer.cpp @@ -830,10 +830,10 @@ void FilamentViewer::updateViewportAndCameraProjection( const double aspect = (double)width / height; Camera& cam =_view->getCamera(); - cam.setLensProjection(_cameraFocalLength, aspect, kNearPlane, + cam.setLensProjection(_cameraFocalLength, 1.0f, kNearPlane, kFarPlane); - // cam.setScaling({1.0 / aspect, 1.0}); + cam.setScaling({1.0 / aspect, 1.0}); Log("Set viewport to width: %d height: %d aspect %f scaleFactor : %f", width, height, aspect, contentScaleFactor); diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index 7467441d..0a059953 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -70,7 +70,6 @@ class FilamentController { size = ui.Size(width * _pixelRatio, height * _pixelRatio); _textureId = await _channel.invokeMethod("createTexture", [size.width, size.height]); - _textureIdController.add(_textureId); await _channel .invokeMethod("createFilamentViewer", [size.width, size.height]); @@ -93,6 +92,7 @@ class FilamentController { _initialized.complete(true); _assetManager = await _channel.invokeMethod("getAssetManager"); + _textureIdController.add(_textureId); } Future resize(int width, int height, diff --git a/lib/filament_widget.dart b/lib/filament_widget.dart index a8c05e25..9b462fe0 100644 --- a/lib/filament_widget.dart +++ b/lib/filament_widget.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'dart:math'; +import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'dart:async'; @@ -55,78 +56,98 @@ class FilamentWidget extends StatefulWidget { } class _FilamentWidgetState extends State { - StreamSubscription? _listener; - + StreamSubscription? _initializationListener; + StreamSubscription? _textureIdListener; + int? _textureId; bool _resizing = false; + bool _hasViewer = false; @override void initState() { - _listener = widget.controller.onInitializationRequested.listen((_) { + _initializationListener = + widget.controller.onInitializationRequested.listen((_) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { var size = ((context.findRenderObject()) as RenderBox).size; print( "Requesting creation of Filament back-end texture/viewer for viewport size $size"); await widget.controller .createViewer(size.width.toInt(), size.height.toInt()); - print("Filament texture/viewer created."); - _listener!.cancel(); - _listener = null; + setState(() { + _hasViewer = true; + }); + + _initializationListener!.cancel(); + _initializationListener = null; + + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + var size = ((context.findRenderObject()) as RenderBox).size; + widget.controller.resize(size.width.toInt(), size.height.toInt()); + print("RESIZED IN POST FRAME CALLBACK TO $size"); + }); + setState(() {}); + }); + }); + _textureIdListener = widget.controller.textureId.listen((int? textureId) { + setState(() { + _textureId = textureId; }); - setState(() {}); }); super.initState(); } + @override void dispose() { - _listener?.cancel(); + _initializationListener?.cancel(); + _textureIdListener?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { - return StreamBuilder( - stream: widget.controller.textureId, - builder: (ctx, AsyncSnapshot textureId) { - if (textureId.data == null) { - return Container(); - } + return LayoutBuilder(builder: ((context, constraints) { + print("constraints $constraints"); + if (_textureId == null) { + return Container(color: Colors.transparent); + } - var texture = Texture( - key: ObjectKey("texture_${textureId.data}"), - textureId: textureId.data!, - filterQuality: FilterQuality.high, - ); - return LayoutBuilder( - builder: ((context, constraints) => SizedBox( - height: constraints.maxHeight, - width: constraints.maxWidth, - child: ResizeObserver( - onResized: (Size oldSize, Size newSize) async { - WidgetsBinding.instance.addPostFrameCallback((_) async { - setState(() { - _resizing = true; - }); + var texture = Texture( + key: ObjectKey("texture_$_textureId"), + textureId: _textureId!, + filterQuality: FilterQuality.high, + ); + return SizedBox( + height: constraints.maxHeight, + width: constraints.maxWidth, + child: ResizeObserver( + onResized: (Size oldSize, Size newSize) async { + if (!_hasViewer) { + return; + } + print("RESIZE OBSERVER $newSize"); + WidgetsBinding.instance.addPostFrameCallback((_) async { + setState(() { + _resizing = true; + }); - await widget.controller.resize( - newSize.width.toInt(), newSize.height.toInt()); - WidgetsBinding.instance - .addPostFrameCallback((_) async { - setState(() { - _resizing = false; - }); - }); - }); - }, - child: Platform.isLinux - ? _resizing - ? Container() - : Transform( - alignment: Alignment.center, - transform: Matrix4.rotationX( - pi), // TODO - this rotation is due to OpenGL texture coordinate working in a different space from Flutter, can we move this to the C++ side somewhere? - child: texture) - : texture)))); - }); + await widget.controller + .resize(newSize.width.toInt(), newSize.height.toInt()); + WidgetsBinding.instance.addPostFrameCallback((_) async { + setState(() { + _resizing = false; + }); + }); + }); + }, + child: Platform.isLinux + ? _resizing + ? Container() + : Transform( + alignment: Alignment.center, + transform: Matrix4.rotationX( + pi), // TODO - this rotation is due to OpenGL texture coordinate working in a different space from Flutter, can we move this to the C++ side somewhere? + child: texture) + : texture)); + })); } }