render directly to Texture rather than PlatformView (Android only)

This commit is contained in:
Nick Fisher
2022-08-17 19:46:02 +10:00
parent b7fa36a320
commit cab2ac45f8
11 changed files with 773 additions and 773 deletions

View File

@@ -5,7 +5,10 @@ import 'package:flutter/services.dart';
typedef FilamentAsset = int;
abstract class FilamentController {
void onFilamentViewCreated(int id);
late int textureId;
Future initialize(int width, int height);
Future resize(int width, int height);
Future setBackgroundImage(String path);
Future loadSkybox(String skyboxPath);
Future removeSkybox();
@@ -45,28 +48,24 @@ abstract class FilamentController {
}
class PolyvoxFilamentController extends FilamentController {
late int _id;
late MethodChannel _channel;
final Function(int id)? onFilamentViewCreatedHandler;
late MethodChannel _channel = MethodChannel("app.polyvox.filament/event");
PolyvoxFilamentController({this.onFilamentViewCreatedHandler});
@override
void onFilamentViewCreated(int id) async {
_id = id;
_channel = MethodChannel("app.polyvox.filament/filament_view_$id");
PolyvoxFilamentController() {
_channel.setMethodCallHandler((call) async {
print("Received Filament method channel call : ${call.method}");
if (call.method == "ready") {
onFilamentViewCreatedHandler?.call(_id);
return Future.value(true);
} else {
throw Exception("Unknown method channel invocation ${call.method}");
}
throw Exception("Unknown method channel invocation ${call.method}");
});
}
Future initialize(int width, int height) async {
textureId = await _channel.invokeMethod("initialize", [width, height]);
}
Future resize(int width, int height) async {
await _channel.invokeMethod("resize", [width, height]);
}
@override
Future setBackgroundImage(String path) async {
await _channel.invokeMethod("setBackgroundImage", path);

88
lib/filament_widget.dart Normal file
View File

@@ -0,0 +1,88 @@
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
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;
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
var size = ((context.findRenderObject()) as RenderBox).size;
print("Requesting texture creation for Filament of size $size");
await widget.controller.initialize(size.width.toInt(), size.height.toInt());
print("Filament texture available");
setState(() {
_ready = true;
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
if(!_ready) {
return Container();
}
return ResizeObserver(
onResized: (Size oldSize, Size newSize) async {
await widget.controller.resize(newSize.width.toInt(), newSize.height.toInt());
},
child:Texture(
textureId: widget.controller.textureId,
filterQuality: FilterQuality.none,
));
}
}

View File

@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'filament_controller.dart';
import 'view/filament_widget.dart';
import 'filament_widget.dart';
class GestureDetectingFilamentView extends StatefulWidget {
final FilamentController controller;

View File

@@ -1,39 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'filament_view_platform.dart';
class FilamentView extends FilamentViewPlatform {
static const FILAMENT_VIEW_ID = 'app.polyvox.filament/filament_view';
@override
Widget buildView(
int creationId,
FilamentViewCreatedCallback onFilamentViewCreated,
) {
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return AndroidView(
viewType: FILAMENT_VIEW_ID,
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{},
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
onPlatformViewCreated: (id) {
onFilamentViewCreated(id);
});
case TargetPlatform.iOS:
return UiKitView(
viewType: FILAMENT_VIEW_ID,
onPlatformViewCreated: (int id) {
onFilamentViewCreated(id);
},
);
case TargetPlatform.windows:
return Text("Flutter doesn't support platform view on Windows yet.");
default:
return Text(
'$defaultTargetPlatform is not yet implemented by Filament plugin.');
}
}
}

View File

@@ -1,21 +0,0 @@
import 'package:flutter/widgets.dart';
import 'package:polyvox_filament/view/filament_view.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
typedef FilamentViewCreatedCallback = void Function(int id);
abstract class FilamentViewPlatform extends PlatformInterface {
FilamentViewPlatform() : super(token: _token);
static final Object _token = Object();
static final FilamentViewPlatform _instance = FilamentView();
static FilamentViewPlatform get instance => _instance;
Widget buildView(
int creationId,
FilamentViewCreatedCallback onFilamentViewCreated,
) {
throw UnimplementedError('buildView() has not been implemented.');
}
}

View File

@@ -1,29 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:polyvox_filament/view/filament_view.dart';
import '../filament_controller.dart';
import 'filament_view_platform.dart';
int _nextFilamentCreationId = 0;
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> {
final _viewId = _nextFilamentCreationId++;
@override
Widget build(BuildContext context) {
return FilamentViewPlatform.instance
.buildView(_viewId, widget.controller.onFilamentViewCreated);
}
}