Files
cup_edit/lib/filament_widget.dart
2022-12-15 16:56:57 +08:00

114 lines
2.9 KiB
Dart

import 'dart:io';
import 'dart:math';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'dart:async';
import 'filament_controller.dart';
typedef ResizeCallback = void Function(Size oldSize, Size newSize);
class ResizeObserver extends SingleChildRenderObjectWidget {
final ResizeCallback onResized;
const ResizeObserver({
Key? key,
required this.onResized,
Widget? child,
}) : super(
key: key,
child: child,
);
@override
RenderObject createRenderObject(BuildContext context) =>
_RenderResizeObserver(onLayoutChangedCallback: onResized);
}
class _RenderResizeObserver extends RenderProxyBox {
final ResizeCallback onLayoutChangedCallback;
_RenderResizeObserver({
RenderBox? child,
required this.onLayoutChangedCallback,
}) : super(child);
late var _oldSize = size;
@override
void performLayout() {
super.performLayout();
if (size != _oldSize) {
onLayoutChangedCallback(_oldSize, size);
_oldSize = size;
}
}
}
class FilamentWidget extends StatefulWidget {
final FilamentController controller;
const FilamentWidget({Key? key, required this.controller}) : super(key: key);
@override
_FilamentWidgetState createState() => _FilamentWidgetState();
}
class _FilamentWidgetState extends State<FilamentWidget> {
bool _ready = false;
StreamSubscription? _listener;
@override
void initState() {
_listener = widget.controller.onInitializationRequested.listen((_) {
if (_ready) {
return;
}
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
.createTextureViewer(size.width.toInt(), size.height.toInt());
print("Filament texture/viewer created.");
setState(() {
_ready = true;
});
_listener!.cancel();
_listener = null;
});
// we need to make sure a new frame is requested, otherwise the callback may not run
setState(() {});
});
super.initState();
}
void dispose() {
_listener?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (!_ready) {
return Container();
}
var texture = Texture(
textureId: widget.controller.textureId,
filterQuality: FilterQuality.high,
);
return ResizeObserver(
onResized: (Size oldSize, Size newSize) async {
await widget.controller
.resize(newSize.width.toInt(), newSize.height.toInt());
},
child: Platform.isLinux
? Transform(
alignment: Alignment.center,
transform: Matrix4.rotationX(pi),
child: texture)
: texture);
}
}