feat: camera and resizing improvements
This commit is contained in:
@@ -9,30 +9,40 @@ import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_in
|
||||
/// Call [createViewerWithOptions] to create an instance of [ThermionViewer].
|
||||
///
|
||||
class ThermionFlutterPlugin {
|
||||
|
||||
ThermionFlutterPlugin._();
|
||||
|
||||
static bool _initializing = false;
|
||||
|
||||
static ThermionViewer? _viewer;
|
||||
|
||||
static ThermionFlutterOptions? options;
|
||||
|
||||
static Future<ThermionViewer> createViewer(
|
||||
{ThermionFlutterOptions options =
|
||||
const ThermionFlutterOptions.empty()}) async {
|
||||
|
||||
if (_initializing) {
|
||||
throw Exception("Existing call to createViewer has not completed.");
|
||||
}
|
||||
_initializing = true;
|
||||
|
||||
if (_viewer != null) {
|
||||
throw Exception(
|
||||
"Instance of ThermionViewer has already been created. Ensure you call dispose() on that instance.");
|
||||
}
|
||||
|
||||
options = options;
|
||||
|
||||
_viewer =
|
||||
await ThermionFlutterPlatform.instance.createViewer(options: options);
|
||||
|
||||
var camera = await _viewer!.getActiveCamera();
|
||||
camera.setLensProjection();
|
||||
|
||||
_viewer!.onDispose(() async {
|
||||
_viewer = null;
|
||||
ThermionFlutterPlugin.options = null;
|
||||
});
|
||||
_initializing = false;
|
||||
return _viewer!;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,14 +7,32 @@ import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dar
|
||||
import 'package:vector_math/vector_math_64.dart' hide Colors;
|
||||
|
||||
class ThermionTextureWidget extends StatefulWidget {
|
||||
///
|
||||
///
|
||||
///
|
||||
final ThermionViewer viewer;
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
final t.View view;
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
final Widget? initial;
|
||||
|
||||
///
|
||||
/// A callback that will be invoked whenever this widget (and the underlying texture is resized).
|
||||
///
|
||||
final Future Function(Size size, t.View view, double pixelRatio)? onResize;
|
||||
|
||||
const ThermionTextureWidget(
|
||||
{super.key, required this.viewer, required this.view, this.initial});
|
||||
{super.key,
|
||||
required this.viewer,
|
||||
required this.view,
|
||||
this.initial,
|
||||
this.onResize});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
@@ -54,9 +72,16 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
|
||||
.createTexture(widget.view, width, height);
|
||||
|
||||
await widget.view.updateViewport(_texture!.width, _texture!.height);
|
||||
var camera = await widget.view.getCamera();
|
||||
await camera.setLensProjection(
|
||||
aspect: _texture!.width / _texture!.height);
|
||||
|
||||
try {
|
||||
await widget.onResize?.call(
|
||||
Size(_texture!.width.toDouble(), _texture!.height.toDouble()),
|
||||
widget.view,
|
||||
dpr);
|
||||
} catch (err, st) {
|
||||
print(err);
|
||||
print(st);
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
@@ -124,7 +149,9 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
|
||||
|
||||
_resizing.add(completer.future);
|
||||
|
||||
newSize *= MediaQuery.of(context).devicePixelRatio;
|
||||
final dpr = MediaQuery.of(context).devicePixelRatio;
|
||||
|
||||
newSize *= dpr;
|
||||
|
||||
var newWidth = newSize.width.ceil();
|
||||
var newHeight = newSize.height.ceil();
|
||||
@@ -136,11 +163,13 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
|
||||
0,
|
||||
);
|
||||
|
||||
|
||||
await widget.view.updateViewport(_texture!.width, _texture!.height);
|
||||
var camera = await widget.view.getCamera();
|
||||
await camera.setLensProjection(
|
||||
aspect: _texture!.width.toDouble() / _texture!.height.toDouble());
|
||||
|
||||
await widget.onResize?.call(
|
||||
Size(_texture!.width.toDouble(), _texture!.height.toDouble()),
|
||||
widget.view,
|
||||
dpr);
|
||||
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
@@ -169,108 +198,3 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// class _ThermionWidgetState extends State<ThermionWidget> {
|
||||
|
||||
// ThermionFlutterTexture? _texture;
|
||||
|
||||
// @override
|
||||
// void initState() {
|
||||
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
// await widget.viewer.initialized;
|
||||
// widget.viewer.onDispose(() async {
|
||||
// _rendering = false;
|
||||
|
||||
// if (_texture != null) {
|
||||
// var texture = _texture;
|
||||
// _texture = null;
|
||||
// if (mounted) {
|
||||
// setState(() {});
|
||||
// }
|
||||
// await ThermionFlutterPlugin.destroyTexture(texture!);
|
||||
// }
|
||||
// });
|
||||
// var dpr = MediaQuery.of(context).devicePixelRatio;
|
||||
|
||||
// var size = ((context.findRenderObject()) as RenderBox).size;
|
||||
// _texture = await ThermionFlutterPlugin.createTexture(
|
||||
// size.width, size.height, 0, 0, dpr);
|
||||
|
||||
// if (mounted) {
|
||||
// setState(() {});
|
||||
// }
|
||||
|
||||
// _requestFrame();
|
||||
// });
|
||||
// super.initState();
|
||||
// }
|
||||
|
||||
// bool _rendering = false;
|
||||
|
||||
// void _requestFrame() {
|
||||
// WidgetsBinding.instance.scheduleFrameCallback((d) async {
|
||||
// if (!_rendering) {
|
||||
// _rendering = true;
|
||||
// await widget.viewer.requestFrame();
|
||||
// _rendering = false;
|
||||
// }
|
||||
// _requestFrame();
|
||||
// });
|
||||
// }
|
||||
|
||||
// bool _resizing = false;
|
||||
// Timer? _resizeTimer;
|
||||
|
||||
// Future _resizeTexture(Size newSize) async {
|
||||
// _resizeTimer?.cancel();
|
||||
// _resizeTimer = Timer(const Duration(milliseconds: 500), () async {
|
||||
// if (_resizing || !mounted) {
|
||||
// return;
|
||||
// }
|
||||
// _resizeTimer!.cancel();
|
||||
// _resizing = true;
|
||||
|
||||
// if (!mounted) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// var dpr = MediaQuery.of(context).devicePixelRatio;
|
||||
|
||||
// _texture.resize(newSize.width.ceil(), newSize.height.ceil(), 0, 0, dpr);
|
||||
// setState(() {});
|
||||
// _resizing = false;
|
||||
// });
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// if (_texture == null || _resizing) {
|
||||
// return widget.initial ??
|
||||
// Container(
|
||||
// color:
|
||||
// kIsWeb ? const Color.fromARGB(0, 170, 129, 129) : Colors.red);
|
||||
// }
|
||||
|
||||
// var textureWidget = Texture(
|
||||
// key: ObjectKey("texture_${_texture!.flutterId}"),
|
||||
// textureId: _texture!.flutterId!,
|
||||
// filterQuality: FilterQuality.none,
|
||||
// freeze: false,
|
||||
// );
|
||||
|
||||
// return ResizeObserver(
|
||||
// onResized: _resizeTexture,
|
||||
// child: Stack(children: [
|
||||
// Positioned.fill(
|
||||
// child: Platform.isLinux || Platform.isWindows
|
||||
// ? 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: textureWidget)
|
||||
// : textureWidget)
|
||||
// ]));
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -8,6 +8,16 @@ import 'package:thermion_flutter_web/thermion_flutter_web_options.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/shared_types/view.dart' as t;
|
||||
import 'thermion_widget_windows.dart';
|
||||
|
||||
Future kDefaultResizeCallback(Size size, t.View view, double pixelRatio) async {
|
||||
var camera = await view.getCamera();
|
||||
var near = await camera.getNear();
|
||||
var far = await camera.getCullingFar();
|
||||
var focalLength = await camera.getFocalLength();
|
||||
|
||||
await camera.setLensProjection(near:near, far:far, focalLength: focalLength,
|
||||
aspect: size.width.toDouble() / size.height.toDouble());
|
||||
}
|
||||
|
||||
class ThermionWidget extends StatefulWidget {
|
||||
///
|
||||
/// The viewer.
|
||||
@@ -15,14 +25,25 @@ class ThermionWidget extends StatefulWidget {
|
||||
final ThermionViewer viewer;
|
||||
|
||||
///
|
||||
/// The view.
|
||||
/// The [View] associated with this widget. If null, the default View will be used.
|
||||
///
|
||||
final t.View? view;
|
||||
|
||||
///
|
||||
/// The options to use when creating this widget.
|
||||
/// A callback to invoke whenever this widget and the underlying surface are
|
||||
/// resized. If a callback is not explicitly provided, the default callback
|
||||
/// will be run, which changes the aspect ratio for the active camera in
|
||||
/// the View managed by this widget. If you specify your own callback,
|
||||
/// you probably want to preserve this behaviour (otherwise the aspect ratio)
|
||||
/// will be incorrect.
|
||||
///
|
||||
/// To completely disable the resize callback, pass [null].
|
||||
///
|
||||
/// IMPORTANT - size is specified in physical pixels, not logical pixels.
|
||||
/// If you need to work with Flutter dimensions, divide [size] by
|
||||
/// [pixelRatio].
|
||||
///
|
||||
final ThermionFlutterOptions? options;
|
||||
final Future Function(Size size, t.View view, double pixelRatio)? onResize;
|
||||
|
||||
///
|
||||
/// The content to render before the texture widget is available.
|
||||
@@ -31,7 +52,11 @@ class ThermionWidget extends StatefulWidget {
|
||||
final Widget? initial;
|
||||
|
||||
const ThermionWidget(
|
||||
{Key? key, this.initial, required this.viewer, this.view, this.options})
|
||||
{Key? key,
|
||||
this.initial,
|
||||
required this.viewer,
|
||||
this.view,
|
||||
this.onResize = kDefaultResizeCallback})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
@@ -66,7 +91,7 @@ class _ThermionWidgetState extends State<ThermionWidget> {
|
||||
if (kIsWeb) {
|
||||
return ThermionWidgetWeb(
|
||||
viewer: widget.viewer,
|
||||
options: widget.options as ThermionFlutterWebOptions);
|
||||
options: ThermionFlutterPlugin.options as ThermionFlutterWebOptions?);
|
||||
}
|
||||
|
||||
if (Platform.isWindows) {
|
||||
@@ -77,6 +102,7 @@ class _ThermionWidgetState extends State<ThermionWidget> {
|
||||
key: ObjectKey(view!),
|
||||
initial: widget.initial,
|
||||
viewer: widget.viewer,
|
||||
view: view!);
|
||||
view: view!,
|
||||
onResize: widget.onResize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,3 +3,4 @@ library;
|
||||
export 'src/thermion_widget.dart';
|
||||
export 'src/thermion_listener_widget.dart';
|
||||
export 'src/camera/camera_selector_widget.dart';
|
||||
export 'src/camera/camera_orientation_widget.dart';
|
||||
|
||||
Reference in New Issue
Block a user