refactor: continual refactor to support multiple render targets

This commit is contained in:
Nick Fisher
2024-09-28 18:28:05 +08:00
parent 65e60da288
commit 921a994eb6
51 changed files with 1714 additions and 877 deletions

View File

@@ -1,8 +1,6 @@
import 'dart:async';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:flutter/widgets.dart';
import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart';
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
///
/// Handles all platform-specific initialization to create a backing rendering
@@ -11,118 +9,30 @@ import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dar
/// Call [createViewerWithOptions] to create an instance of [ThermionViewer].
///
class ThermionFlutterPlugin {
ThermionFlutterPlugin._();
static AppLifecycleListener? _appLifecycleListener;
ThermionFlutterPlugin._();
static bool _initializing = false;
static ThermionViewer? _viewer;
static bool _wasRenderingOnInactive = false;
static void _handleStateChange(AppLifecycleState state) async {
if (_viewer == null) {
return;
}
await _viewer!.initialized;
switch (state) {
case AppLifecycleState.detached:
if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = _viewer!.rendering;
}
await _viewer!.setRendering(false);
break;
case AppLifecycleState.hidden:
if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = _viewer!.rendering;
}
await _viewer!.setRendering(false);
break;
case AppLifecycleState.inactive:
if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = _viewer!.rendering;
}
// on Windows in particular, restoring a window after minimizing stalls the renderer (and the whole application) for a considerable length of time.
// disabling rendering on minimize seems to fix the issue (so I wonder if there's some kind of command buffer that's filling up while the window is minimized).
await _viewer!.setRendering(false);
break;
case AppLifecycleState.paused:
if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = _viewer!.rendering;
}
await _viewer!.setRendering(false);
break;
case AppLifecycleState.resumed:
await _viewer!.setRendering(_wasRenderingOnInactive);
break;
}
}
@Deprecated("Use createViewerWithOptions")
static Future<ThermionViewer> createViewer({String? uberArchivePath}) async {
static Future<ThermionViewer> createViewer(
{ThermionFlutterOptions options =
const ThermionFlutterOptions.empty()}) async {
if (_initializing) {
throw Exception("Existing call to createViewer has not completed.");
}
_initializing = true;
_viewer = await ThermionFlutterPlatform.instance
.createViewer(uberarchivePath: uberArchivePath);
_appLifecycleListener = AppLifecycleListener(
onStateChange: _handleStateChange,
);
_viewer!.onDispose(() async {
_viewer = null;
_appLifecycleListener?.dispose();
_appLifecycleListener = null;
});
_initializing = false;
return _viewer!;
}
static Future<ThermionViewer> createViewerWithOptions(
{ThermionFlutterOptions options = const ThermionFlutterOptions.empty()}) async {
if (_initializing) {
throw Exception("Existing call to createViewer has not completed.");
}
_initializing = true;
_viewer =
await ThermionFlutterPlatform.instance.createViewerWithOptions(options);
_appLifecycleListener = AppLifecycleListener(
onStateChange: _handleStateChange,
);
await ThermionFlutterPlatform.instance.createViewer(options: options);
_viewer!.onDispose(() async {
_viewer = null;
_appLifecycleListener?.dispose();
_appLifecycleListener = null;
});
_initializing = false;
return _viewer!;
}
static Future<ThermionFlutterTexture?> createTexture(
double width,
double height,
double offsetLeft,
double offsetTop,
double pixelRatio) async {
return ThermionFlutterPlatform.instance
.createTexture(width, height, offsetLeft, offsetTop, pixelRatio);
}
static Future destroyTexture(ThermionFlutterTexture texture) async {
return ThermionFlutterPlatform.instance.destroyTexture(texture);
}
static Future<ThermionFlutterTexture?> resizeTexture(
ThermionFlutterTexture texture,
int width,
int height,
int offsetLeft,
int offsetTop,
double pixelRatio) async {
return ThermionFlutterPlatform.instance.resizeTexture(
texture, width, height, offsetLeft, offsetTop, pixelRatio);
}
}

View File

@@ -0,0 +1,12 @@
import 'package:flutter/widgets.dart';
class PixelRatioAware extends StatelessWidget {
final Widget Function(BuildContext context, double pixelRatio) builder;
const PixelRatioAware({Key? key, required this.builder}) : super(key: key);
@override
Widget build(BuildContext context) {
return builder(context, MediaQuery.of(context).devicePixelRatio);
}
}

View File

@@ -5,6 +5,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:thermion_flutter/src/widgets/src/pixel_ratio_aware.dart';
import 'package:vector_math/vector_math_64.dart';
extension OffsetExtension on Offset {
@@ -79,54 +80,64 @@ class _ThermionListenerWidgetState extends State<ThermionListenerWidget> {
HardwareKeyboard.instance.removeHandler(_handleKeyEvent);
}
Widget _desktop() {
Widget _desktop(double pixelRatio) {
return Listener(
onPointerHover: (event) => widget.gestureHandler
.onPointerHover(event.localPosition.toVector2(), event.delta.toVector2()),
onPointerHover: (event) => widget.gestureHandler.onPointerHover(
event.localPosition.toVector2() * pixelRatio,
event.delta.toVector2() * pixelRatio),
onPointerSignal: (PointerSignalEvent pointerSignal) {
if (pointerSignal is PointerScrollEvent) {
widget.gestureHandler.onPointerScroll(
pointerSignal.localPosition.toVector2(),
pointerSignal.scrollDelta.dy);
pointerSignal.localPosition.toVector2() * pixelRatio,
pointerSignal.scrollDelta.dy * pixelRatio);
}
},
onPointerPanZoomStart: (pzs) {
throw Exception("TODO - is this a pinch zoom on laptop trackpad?");
},
onPointerDown: (d) => widget.gestureHandler
.onPointerDown(d.localPosition.toVector2(), d.buttons & kMiddleMouseButton != 0),
onPointerMove: (d) => widget.gestureHandler
.onPointerMove(d.localPosition.toVector2(), d.delta.toVector2(), d.buttons & kMiddleMouseButton != 0),
onPointerUp: (d) => widget.gestureHandler.onPointerUp(d.buttons & kMiddleMouseButton != 0),
onPointerDown: (d) => widget.gestureHandler.onPointerDown(
d.localPosition.toVector2() * pixelRatio,
d.buttons & kMiddleMouseButton != 0),
onPointerMove: (d) => widget.gestureHandler.onPointerMove(
d.localPosition.toVector2() * pixelRatio,
d.delta.toVector2() * pixelRatio,
d.buttons & kMiddleMouseButton != 0),
onPointerUp: (d) => widget.gestureHandler
.onPointerUp(d.buttons & kMiddleMouseButton != 0),
child: widget.child,
);
}
Widget _mobile() {
return _MobileListenerWidget(gestureHandler: widget.gestureHandler);
Widget _mobile(double pixelRatio) {
return _MobileListenerWidget(
gestureHandler: widget.gestureHandler, pixelRatio: pixelRatio);
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: widget.gestureHandler.initialized,
builder: (_, initialized) {
if (initialized.data != true) {
return widget.child ?? Container();
}
return Stack(children: [
if (widget.child != null) Positioned.fill(child: widget.child!),
if (isDesktop) Positioned.fill(child: _desktop()),
if (!isDesktop) Positioned.fill(child: _mobile())
]);
});
return PixelRatioAware(builder: (ctx, pixelRatio) {
return FutureBuilder(
initialData: 1.0,
future: widget.gestureHandler.initialized,
builder: (_, initialized) {
if (initialized.data != true) {
return widget.child ?? Container();
}
return Stack(children: [
if (widget.child != null) Positioned.fill(child: widget.child!),
if (isDesktop) Positioned.fill(child: _desktop(pixelRatio)),
if (!isDesktop) Positioned.fill(child: _mobile(pixelRatio))
]);
});
});
}
}
class _MobileListenerWidget extends StatefulWidget {
final InputHandler gestureHandler;
final double pixelRatio;
const _MobileListenerWidget({Key? key, required this.gestureHandler})
const _MobileListenerWidget({Key? key, required this.gestureHandler, required this.pixelRatio})
: super(key: key);
@override
@@ -146,7 +157,7 @@ class _MobileListenerWidgetState extends State<_MobileListenerWidget> {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTapDown: (details) => widget.gestureHandler
.onPointerDown(details.localPosition.toVector2(), false),
.onPointerDown(details.localPosition.toVector2() * widget.pixelRatio, false),
onDoubleTap: () {
widget.gestureHandler.setActionForType(InputType.SCALE1,
isPan ? InputAction.TRANSLATE : InputAction.ROTATE);

View File

@@ -0,0 +1,270 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:thermion_dart/src/viewer/src/shared_types/view.dart' as t;
import 'package:thermion_flutter/src/widgets/src/resize_observer.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
import 'package:vector_math/vector_math_64.dart' hide Colors;
class ThermionTextureWidget extends StatefulWidget {
final ThermionViewer viewer;
final t.View view;
final Widget? initial;
const ThermionTextureWidget(
{super.key, required this.viewer, required this.view, this.initial});
@override
State<StatefulWidget> createState() {
return _ThermionTextureWidgetState();
}
}
class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
ThermionFlutterTexture? _texture;
RenderTarget? _renderTarget;
@override
void dispose() {
super.dispose();
_texture?.destroy();
}
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
await widget.viewer.initialized;
var dpr = MediaQuery.of(context).devicePixelRatio;
var size = ((context.findRenderObject()) as RenderBox).size;
var width = (size.width * dpr).ceil();
var height = (size.height * dpr).ceil();
_texture =
await ThermionFlutterPlatform.instance.createTexture(width, height);
_renderTarget = await widget.viewer.createRenderTarget(
_texture!.width, _texture!.height, _texture!.hardwareId);
await widget.view.setRenderTarget(_renderTarget!);
await widget.view.updateViewport(width, height);
var camera = await widget.view.getCamera();
await camera.setLensProjection(aspect: width / height);
if (mounted) {
setState(() {});
}
_requestFrame();
widget.viewer.onDispose(() async {
var texture = _texture;
if (mounted) {
setState(() {});
}
if (texture != null) {
_renderTarget = await widget.viewer.createRenderTarget(
texture.width, texture.height, texture.flutterId);
await widget.view.setRenderTarget(null);
await _renderTarget!.destroy();
texture.destroy();
}
});
});
super.initState();
}
bool _rendering = false;
void _requestFrame() {
WidgetsBinding.instance.scheduleFrameCallback((d) async {
if (!_rendering) {
_rendering = true;
await widget.viewer.requestFrame();
await _texture?.markFrameAvailable();
_rendering = false;
}
_requestFrame();
});
}
bool _resizing = false;
Timer? _resizeTimer;
Future _resize(Size newSize) async {
_resizeTimer?.cancel();
_resizeTimer = Timer(const Duration(milliseconds: 10), () async {
if (_resizing || !mounted) {
return;
}
_resizeTimer!.cancel();
_resizing = true;
if (!mounted) {
return;
}
newSize *= MediaQuery.of(context).devicePixelRatio;
var newWidth = newSize.width.ceil();
var newHeight = newSize.height.ceil();
await _texture?.resize(
newWidth,
newHeight,
0,
0,
);
await widget.view.updateViewport(newWidth, newHeight);
var camera = await widget.view.getCamera();
await camera.setLensProjection(aspect: newWidth / newHeight);
setState(() {});
_resizing = false;
});
}
@override
Widget build(BuildContext context) {
if (_texture == null) {
return widget.initial ?? Container(color: Colors.red);
}
return Stack(children: [
Positioned.fill(
child: ResizeObserver(
onResized: _resize,
child: Stack(children: [
Positioned.fill(
child: Texture(
key: ObjectKey("flutter_texture_${_texture!.flutterId}"),
textureId: _texture!.flutterId,
filterQuality: FilterQuality.none,
freeze: false,
))
]))),
Align(
alignment: Alignment.bottomLeft,
child: ElevatedButton(
onPressed: () async {
var img =
await widget.viewer.capture(renderTarget: _renderTarget!);
print(img);
},
child: Text("CAPTURE")),
)
]);
}
}
// 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)
// ]));
// }
// }

View File

@@ -1,18 +1,27 @@
import 'dart:io';
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:thermion_flutter/src/widgets/src/thermion_texture_widget.dart';
import 'package:thermion_flutter/src/widgets/src/thermion_widget_web.dart';
import 'package:thermion_flutter/src/widgets/src/transparent_filament_widget.dart';
import 'dart:async';
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'package:thermion_flutter_web/thermion_flutter_web_options.dart';
import 'resize_observer.dart';
import 'package:thermion_dart/src/viewer/src/shared_types/view.dart' as t;
import 'thermion_widget_windows.dart';
class ThermionWidget extends StatefulWidget {
///
/// The viewer.
///
final ThermionViewer viewer;
///
/// The view.
///
final t.View? view;
///
/// The options to use when creating this widget.
///
final ThermionFlutterOptions? options;
///
@@ -22,130 +31,51 @@ class ThermionWidget extends StatefulWidget {
final Widget? initial;
const ThermionWidget(
{Key? key, this.initial, required this.viewer, this.options})
{Key? key, this.initial, required this.viewer, this.view, this.options})
: super(key: key);
@override
_ThermionWidgetState createState() => _ThermionWidgetState();
State<ThermionWidget> createState() => _ThermionWidgetState();
}
class _ThermionWidgetState extends State<ThermionWidget> {
ThermionFlutterTexture? _texture;
t.View? view;
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
await widget.viewer.initialized;
widget.viewer.onDispose(() async {
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();
initialize();
}
bool _rendering = false;
void _requestFrame() {
WidgetsBinding.instance.scheduleFrameCallback((d) async {
if (!_rendering) {
_rendering = true;
await widget.viewer.requestFrame();
_rendering = false;
Future initialize() async {
if (widget.view != null) {
view = widget.view;
} else {
view = await widget.viewer.getViewAt(0);
}
_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;
var oldTexture = _texture;
_texture = null;
if (!mounted) {
return;
}
var dpr = MediaQuery.of(context).devicePixelRatio;
_texture = await ThermionFlutterPlugin.resizeTexture(
oldTexture!, newSize.width.ceil(), newSize.height.ceil(), 0, 0, dpr);
setState(() {});
_resizing = false;
});
setState(() {});
}
@override
Widget build(BuildContext context) {
if (view == null) {
return widget.initial ?? Container(color: Colors.red);
}
// Windows & Web don't support imported textures yet
if (kIsWeb) {
if (_texture == null || _resizing) {
return widget.initial ?? Container(color: Colors.red);
}
return ResizeObserver(
onResized: _resizeTexture,
child: ThermionWidgetWeb(
options: widget.options as ThermionFlutterWebOptions?));
return ThermionWidgetWeb(
viewer: widget.viewer,
options: widget.options as ThermionFlutterWebOptions);
}
if (_texture?.usesBackingWindow == true) {
return ResizeObserver(
onResized: _resizeTexture,
child: Stack(children: [
Positioned.fill(child: CustomPaint(painter: TransparencyPainter()))
]));
if (Platform.isWindows) {
return ThermionWidgetWindows(viewer: widget.viewer);
}
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!.flutterTextureId}"),
textureId: _texture!.flutterTextureId!,
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)
]));
return ThermionTextureWidget(
key: ObjectKey(view!),
initial: widget.initial,
viewer: widget.viewer,
view: view!);
}
}

View File

@@ -2,18 +2,28 @@ import 'dart:js_util';
import 'dart:ui' as ui;
import 'dart:ui_web' as ui_web;
import 'package:logging/logging.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'package:thermion_flutter_web/thermion_flutter_web_options.dart';
import 'package:web/web.dart';
import 'package:flutter/widgets.dart';
class ThermionWidgetWeb extends StatelessWidget {
final ThermionFlutterWebOptions options;
final ThermionViewer viewer;
const ThermionWidgetWeb(
{super.key, this.options = const ThermionFlutterWebOptions.empty()});
{super.key, this.options = const ThermionFlutterWebOptions.empty(), required this.viewer});
@override
Widget build(BuildContext context) {
if (_texture == null || _resizing) {
return widget.initial ?? Container(color: Colors.red);
}
return ResizeObserver(
onResized: _resizeTexture,
child: ThermionWidgetWeb(
options: widget.options as ThermionFlutterWebOptions?));
if (options?.importCanvasAsWidget == true) {
return _ImageCopyingWidget();
}

View File

@@ -1,14 +1,16 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:thermion_flutter_ffi/thermion_flutter_ffi.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'package:thermion_flutter_web/thermion_flutter_web_options.dart';
class ThermionWidgetWeb extends StatefulWidget {
class ThermionWidgetWeb extends StatelessWidget {
final ThermionFlutterWebOptions? options;
final ThermionViewer viewer;
const ThermionWidgetWeb({super.key, required this.options, required this.viewer});
const ThermionWidgetWeb({super.key, required this.options});
@override
// ignore: no_logic_in_create_state
State<StatefulWidget> createState() => throw Exception();
Widget build(BuildContext context) {
throw Exception("STUB");
}
}

View File

@@ -0,0 +1,14 @@
import 'package:flutter/widgets.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
class ThermionWidgetWindows extends StatelessWidget {
final ThermionViewer viewer;
const ThermionWidgetWindows({super.key, required this.viewer});
@override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}

View File

@@ -55,14 +55,7 @@ public class SwiftThermionFlutterPlugin: NSObject, FlutterPlugin {
let instance:SwiftThermionFlutterPlugin = Unmanaged<SwiftThermionFlutterPlugin>.fromOpaque(resourcesPtr!).takeUnretainedValue()
instance.resources.removeValue(forKey:UInt32(rbuf.id))
}
var markTextureFrameAvailable : @convention(c) (UnsafeMutableRawPointer?) -> () = { instancePtr in
let instance:SwiftThermionFlutterPlugin = Unmanaged<SwiftThermionFlutterPlugin>.fromOpaque(instancePtr!).takeUnretainedValue()
if(instance.texture != nil) {
instance.registry.textureFrameAvailable(instance.texture!.flutterTextureId)
}
}
public static func register(with registrar: FlutterPluginRegistrar) {
let _messenger = registrar.messenger;
@@ -88,12 +81,12 @@ public class SwiftThermionFlutterPlugin: NSObject, FlutterPlugin {
resourceLoaderWrapper = make_resource_loader(loadResource, freeResource, Unmanaged.passUnretained(self).toOpaque())
}
result(Int64(Int(bitPattern: resourceLoaderWrapper!)))
case "markTextureFrameAvailable":
let flutterTextureId = call.arguments as! Int64
registry.textureFrameAvailable(flutterTextureId)
result(nil)
case "getRenderCallback":
if(renderCallbackHolder.isEmpty) {
renderCallbackHolder.append(unsafeBitCast(markTextureFrameAvailable, to:Int64.self))
renderCallbackHolder.append(unsafeBitCast(Unmanaged.passUnretained(self), to:UInt64.self))
}
result(renderCallbackHolder)
result(nil)
case "getDriverPlatform":
result(nil)
case "getSharedContext":

View File

@@ -6,11 +6,11 @@ public class ThermionFlutterTexture : NSObject, FlutterTexture {
var flutterTextureId: Int64 = -1
var registry: FlutterTextureRegistry
var texture: ThermionTexture
var texture: ThermionTextureSwift
init(registry:FlutterTextureRegistry, width:Int64, height:Int64) {
self.registry = registry
self.texture = ThermionTexture(width:width, height: height)
self.texture = ThermionTextureSwift(width:width, height: height)
super.init()
self.flutterTextureId = registry.register(self)
}

View File

@@ -14,7 +14,7 @@
#include "ResourceBuffer.hpp"
using namespace filament;
using namespace thermion_filament;
using namespace thermion;
using namespace std;
int _i = 0;