Merge pull request #13 from odd-io/feature-code-quality

Refactored /lib code to reduce analyze warnings
This commit is contained in:
Nick Fisher
2023-11-07 08:42:49 +08:00
committed by GitHub
9 changed files with 102 additions and 95 deletions

View File

@@ -25,8 +25,9 @@ class AnimationBuilder {
} }
MorphAnimationData build() { MorphAnimationData build() {
if (availableMorphs.isEmpty == 0 || _duration == 0 || _frameLengthInMs == 0) if (availableMorphs.isEmpty || _duration == 0 || _frameLengthInMs == 0) {
throw Exception(); throw Exception();
}
int numFrames = _duration * 1000 ~/ _frameLengthInMs; int numFrames = _duration * 1000 ~/ _frameLengthInMs;
@@ -64,10 +65,10 @@ class AnimationBuilder {
AnimationBuilder interpolateMorphWeights( AnimationBuilder interpolateMorphWeights(
double start, double end, double startValue, double endValue) { double start, double end, double startValue, double endValue) {
this._interpMorphStart = start; _interpMorphStart = start;
this._interpMorphEnd = end; _interpMorphEnd = end;
this._interpMorphStartValue = startValue; _interpMorphStartValue = startValue;
this._interpMorphEndValue = endValue; _interpMorphEndValue = endValue;
return this; return this;
} }
@@ -124,7 +125,7 @@ class AnimationBuilder {
// _BoneAnimationDatas!.add(DartBoneAnimationData([boneName], [meshName], animData)); // _BoneAnimationDatas!.add(DartBoneAnimationData([boneName], [meshName], animData));
return this; // return this;
} }
} }

View File

@@ -234,7 +234,7 @@ abstract class FilamentController {
Future rotateEnd(); Future rotateEnd();
/// ///
/// Set the weights for all morph targets under node [meshName] in [asset] to [weights]. /// Set the weights for all morph targets under node [meshName] in [entity] to [weights].
/// ///
Future setMorphTargetWeights( Future setMorphTargetWeights(
FilamentEntity entity, String meshName, List<double> weights); FilamentEntity entity, String meshName, List<double> weights);
@@ -269,7 +269,7 @@ abstract class FilamentController {
/// ///
/// Removes/destroys the specified entity from the scene. /// Removes/destroys the specified entity from the scene.
/// [asset] will no longer be a valid handle after this method is called; ensure you immediately discard all references once this method is complete. /// [entity] will no longer be a valid handle after this method is called; ensure you immediately discard all references once this method is complete.
/// ///
Future removeAsset(FilamentEntity entity); Future removeAsset(FilamentEntity entity);
@@ -295,7 +295,7 @@ abstract class FilamentController {
Future zoomEnd(); Future zoomEnd();
/// ///
/// Schedules the glTF animation at [index] in [asset] to start playing on the next frame. /// Schedules the glTF animation at [index] in [entity] to start playing on the next frame.
/// ///
Future playAnimation(FilamentEntity entity, int index, Future playAnimation(FilamentEntity entity, int index,
{bool loop = false, {bool loop = false,
@@ -308,7 +308,7 @@ abstract class FilamentController {
Future stopAnimation(FilamentEntity entity, int animationIndex); Future stopAnimation(FilamentEntity entity, int animationIndex);
/// ///
/// Sets the current scene camera to the glTF camera under [name] in [asset]. /// Sets the current scene camera to the glTF camera under [name] in [entity].
/// ///
Future setCamera(FilamentEntity entity, String? name); Future setCamera(FilamentEntity entity, String? name);
@@ -358,7 +358,7 @@ abstract class FilamentController {
Future<Matrix3> getCameraRotation(); Future<Matrix3> getCameraRotation();
/// ///
/// Repositions the camera to the last vertex of the bounding box of [asset], looking at the penultimate vertex. /// Repositions the camera to the last vertex of the bounding box of [entity], looking at the penultimate vertex.
/// ///
Future moveCameraToAsset(FilamentEntity entity); Future moveCameraToAsset(FilamentEntity entity);
@@ -390,12 +390,12 @@ abstract class FilamentController {
FilamentEntity entity, String meshName, int materialIndex, Color color); FilamentEntity entity, String meshName, int materialIndex, Color color);
/// ///
/// Scale [asset] to fit within the unit cube. /// Scale [entity] to fit within the unit cube.
/// ///
Future transformToUnitCube(FilamentEntity entity); Future transformToUnitCube(FilamentEntity entity);
/// ///
/// Sets the world space position for [asset] to the given coordinates. /// Sets the world space position for [entity] to the given coordinates.
/// ///
Future setPosition(FilamentEntity entity, double x, double y, double z); Future setPosition(FilamentEntity entity, double x, double y, double z);

View File

@@ -1,8 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:ffi'; import 'dart:ffi';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'dart:developer' as dev;
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:ffi/ffi.dart'; import 'package:ffi/ffi.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
@@ -69,7 +69,7 @@ class FilamentControllerFFI extends FilamentController {
_resizingWidth = call.arguments[0]; _resizingWidth = call.arguments[0];
_resizingHeight = call.arguments[1]; _resizingHeight = call.arguments[1];
_resizeTimer = Timer(const Duration(milliseconds: 500), () async { _resizeTimer = Timer(const Duration(milliseconds: 500), () async {
this.rect.value = Offset.zero & rect.value = Offset.zero &
ui.Size(_resizingWidth!.toDouble(), _resizingHeight!.toDouble()); ui.Size(_resizingWidth!.toDouble(), _resizingHeight!.toDouble());
await resize(); await resize();
}); });
@@ -115,10 +115,10 @@ class FilamentControllerFFI extends FilamentController {
} }
@override @override
Future setDimensions(Rect rect, double ratio) async { Future setDimensions(Rect rect, double pixelRatio) async {
this.rect.value = Rect.fromLTWH(rect.left, rect.top, this.rect.value = Rect.fromLTWH(rect.left, rect.top,
rect.width * _pixelRatio, rect.height * _pixelRatio); rect.width * _pixelRatio, rect.height * _pixelRatio);
_pixelRatio = ratio; _pixelRatio = pixelRatio;
} }
@override @override
@@ -147,7 +147,7 @@ class FilamentControllerFFI extends FilamentController {
await _channel.invokeMethod( await _channel.invokeMethod(
"destroyTexture", textureDetails.value!.textureId); "destroyTexture", textureDetails.value!.textureId);
} }
print("Texture destroyed"); dev.log("Texture destroyed");
} }
/// ///
@@ -188,16 +188,16 @@ class FilamentControllerFFI extends FilamentController {
var renderingSurface = await _createRenderingSurface(); var renderingSurface = await _createRenderingSurface();
print("Got rendering surface"); dev.log("Got rendering surface");
_viewer = _lib.create_filament_viewer_ffi( _viewer = _lib.create_filament_viewer_ffi(
Pointer<Void>.fromAddress(renderingSurface.sharedContext ?? 0), Pointer<Void>.fromAddress(renderingSurface.sharedContext),
_driver, _driver,
uberArchivePath?.toNativeUtf8().cast<Char>() ?? nullptr, uberArchivePath?.toNativeUtf8().cast<Char>() ?? nullptr,
loader, loader,
renderCallback, renderCallback,
renderCallbackOwner); renderCallbackOwner);
print("Created viewer"); dev.log("Created viewer");
if (_viewer!.address == 0) { if (_viewer!.address == 0) {
throw Exception("Failed to create viewer. Check logs for details"); throw Exception("Failed to create viewer. Check logs for details");
} }
@@ -206,19 +206,19 @@ class FilamentControllerFFI extends FilamentController {
_lib.create_swap_chain_ffi(_viewer!, renderingSurface.surface, _lib.create_swap_chain_ffi(_viewer!, renderingSurface.surface,
rect.value!.width.toInt(), rect.value!.height.toInt()); rect.value!.width.toInt(), rect.value!.height.toInt());
print("Created swap chain"); dev.log("Created swap chain");
if (renderingSurface.textureHandle != 0) { if (renderingSurface.textureHandle != 0) {
print( dev.log(
"Creating render target from native texture ${renderingSurface.textureHandle}"); "Creating render target from native texture ${renderingSurface.textureHandle}");
_lib.create_render_target_ffi(_viewer!, renderingSurface.textureHandle, _lib.create_render_target_ffi(_viewer!, renderingSurface.textureHandle,
rect.value!.width.toInt(), rect.value!.height.toInt()); rect.value!.width.toInt(), rect.value!.height.toInt());
} }
textureDetails.value = TextureDetails( textureDetails.value = TextureDetails(
textureId: renderingSurface.flutterTextureId!, textureId: renderingSurface.flutterTextureId,
width: rect.value!.width.toInt(), width: rect.value!.width.toInt(),
height: rect.value!.height.toInt()); height: rect.value!.height.toInt());
print("texture details ${textureDetails.value}"); dev.log("texture details ${textureDetails.value}");
_lib.update_viewport_and_camera_projection_ffi( _lib.update_viewport_and_camera_projection_ffi(
_viewer!, rect.value!.width.toInt(), rect.value!.height.toInt(), 1.0); _viewer!, rect.value!.width.toInt(), rect.value!.height.toInt(), 1.0);
hasViewer.value = true; hasViewer.value = true;
@@ -322,7 +322,7 @@ class FilamentControllerFFI extends FilamentController {
"destroyTexture", textureDetails.value!.textureId); "destroyTexture", textureDetails.value!.textureId);
} }
} else if (Platform.isWindows) { } else if (Platform.isWindows) {
print("Resizing window with rect $rect"); dev.log("Resizing window with rect $rect");
await _channel.invokeMethod("resizeWindow", [ await _channel.invokeMethod("resizeWindow", [
rect.value!.width, rect.value!.width,
rect.value!.height, rect.value!.height,
@@ -345,14 +345,14 @@ class FilamentControllerFFI extends FilamentController {
} }
if (renderingSurface.textureHandle != 0) { if (renderingSurface.textureHandle != 0) {
print( dev.log(
"Creating render target from native texture ${renderingSurface.textureHandle}"); "Creating render target from native texture ${renderingSurface.textureHandle}");
_lib.create_render_target_ffi(_viewer!, renderingSurface.textureHandle, _lib.create_render_target_ffi(_viewer!, renderingSurface.textureHandle,
rect.value!.width.toInt(), rect.value!.height.toInt()); rect.value!.width.toInt(), rect.value!.height.toInt());
} }
textureDetails.value = TextureDetails( textureDetails.value = TextureDetails(
textureId: renderingSurface.flutterTextureId!, textureId: renderingSurface.flutterTextureId,
width: rect.value!.width.toInt(), width: rect.value!.width.toInt(),
height: rect.value!.height.toInt()); height: rect.value!.height.toInt());
@@ -558,7 +558,7 @@ class FilamentControllerFFI extends FilamentController {
@override @override
Future setMorphTargetWeights( Future setMorphTargetWeights(
FilamentEntity asset, String meshName, List<double> weights) async { FilamentEntity entity, String meshName, List<double> weights) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
@@ -567,23 +567,23 @@ class FilamentControllerFFI extends FilamentController {
for (int i = 0; i < weights.length; i++) { for (int i = 0; i < weights.length; i++) {
weightsPtr.elementAt(i).value = weights[i]; weightsPtr.elementAt(i).value = weights[i];
} }
_lib.set_morph_target_weights_ffi(_assetManager!, asset, _lib.set_morph_target_weights_ffi(_assetManager!, entity,
meshName.toNativeUtf8().cast<Char>(), weightsPtr, weights.length); meshName.toNativeUtf8().cast<Char>(), weightsPtr, weights.length);
calloc.free(weightsPtr); calloc.free(weightsPtr);
} }
@override @override
Future<List<String>> getMorphTargetNames( Future<List<String>> getMorphTargetNames(
FilamentEntity asset, String meshName) async { FilamentEntity entity, String meshName) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
var names = <String>[]; var names = <String>[];
var count = _lib.get_morph_target_name_count_ffi( var count = _lib.get_morph_target_name_count_ffi(
_assetManager!, asset, meshName.toNativeUtf8().cast<Char>()); _assetManager!, entity, meshName.toNativeUtf8().cast<Char>());
var outPtr = calloc<Char>(255); var outPtr = calloc<Char>(255);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
_lib.get_morph_target_name(_assetManager!, asset, _lib.get_morph_target_name(_assetManager!, entity,
meshName.toNativeUtf8().cast<Char>(), outPtr, i); meshName.toNativeUtf8().cast<Char>(), outPtr, i);
names.add(outPtr.cast<Utf8>().toDartString()); names.add(outPtr.cast<Utf8>().toDartString());
} }
@@ -592,15 +592,15 @@ class FilamentControllerFFI extends FilamentController {
} }
@override @override
Future<List<String>> getAnimationNames(FilamentEntity asset) async { Future<List<String>> getAnimationNames(FilamentEntity entity) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
var animationCount = _lib.get_animation_count(_assetManager!, asset); var animationCount = _lib.get_animation_count(_assetManager!, entity);
var names = <String>[]; var names = <String>[];
var outPtr = calloc<Char>(255); var outPtr = calloc<Char>(255);
for (int i = 0; i < animationCount; i++) { for (int i = 0; i < animationCount; i++) {
_lib.get_animation_name_ffi(_assetManager!, asset, outPtr, i); _lib.get_animation_name_ffi(_assetManager!, entity, outPtr, i);
names.add(outPtr.cast<Utf8>().toDartString()); names.add(outPtr.cast<Utf8>().toDartString());
} }
@@ -609,12 +609,12 @@ class FilamentControllerFFI extends FilamentController {
@override @override
Future<double> getAnimationDuration( Future<double> getAnimationDuration(
FilamentEntity asset, int animationIndex) async { FilamentEntity entity, int animationIndex) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
var duration = var duration =
_lib.get_animation_duration(_assetManager!, asset, animationIndex); _lib.get_animation_duration(_assetManager!, entity, animationIndex);
return duration; return duration;
} }
@@ -644,7 +644,7 @@ class FilamentControllerFFI extends FilamentController {
calloc.free(dataPtr); calloc.free(dataPtr);
calloc.free(idxPtr); calloc.free(idxPtr);
throw Exception( throw Exception(
"Morph target ${animation.morphTargets[i]} is specified in the animation but could not be found in the mesh ${animation.meshName} under entity ${entity}"); "Morph target ${animation.morphTargets[i]} is specified in the animation but could not be found in the mesh ${animation.meshName} under entity $entity");
} }
idxPtr.elementAt(i).value = index; idxPtr.elementAt(i).value = index;
} }
@@ -664,7 +664,7 @@ class FilamentControllerFFI extends FilamentController {
@override @override
Future setBoneAnimation( Future setBoneAnimation(
FilamentEntity asset, BoneAnimationData animation) async { FilamentEntity entity, BoneAnimationData animation) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
@@ -701,11 +701,11 @@ class FilamentControllerFFI extends FilamentController {
} }
@override @override
Future removeAsset(FilamentEntity asset) async { Future removeAsset(FilamentEntity entity) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_lib.remove_asset_ffi(_viewer!, asset); _lib.remove_asset_ffi(_viewer!, entity);
} }
@override @override
@@ -741,7 +741,7 @@ class FilamentControllerFFI extends FilamentController {
} }
@override @override
Future playAnimation(FilamentEntity asset, int index, Future playAnimation(FilamentEntity entity, int index,
{bool loop = false, {bool loop = false,
bool reverse = false, bool reverse = false,
bool replaceActive = true, bool replaceActive = true,
@@ -750,33 +750,33 @@ class FilamentControllerFFI extends FilamentController {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_lib.play_animation_ffi( _lib.play_animation_ffi(
_assetManager!, asset, index, loop, reverse, replaceActive, crossfade); _assetManager!, entity, index, loop, reverse, replaceActive, crossfade);
} }
@override @override
Future setAnimationFrame( Future setAnimationFrame(
FilamentEntity asset, int index, int animationFrame) async { FilamentEntity entity, int index, int animationFrame) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_lib.set_animation_frame(_assetManager!, asset, index, animationFrame); _lib.set_animation_frame(_assetManager!, entity, index, animationFrame);
} }
@override @override
Future stopAnimation(FilamentEntity asset, int animationIndex) async { Future stopAnimation(FilamentEntity entity, int animationIndex) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_lib.stop_animation(_assetManager!, asset, animationIndex); _lib.stop_animation(_assetManager!, entity, animationIndex);
} }
@override @override
Future setCamera(FilamentEntity asset, String? name) async { Future setCamera(FilamentEntity entity, String? name) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
var result = _lib.set_camera( var result = _lib.set_camera(
_viewer!, asset, name?.toNativeUtf8()?.cast<Char>() ?? nullptr); _viewer!, entity, name?.toNativeUtf8().cast<Char>() ?? nullptr);
if (!result) { if (!result) {
throw Exception("Failed to set camera"); throw Exception("Failed to set camera");
} }
@@ -833,11 +833,11 @@ class FilamentControllerFFI extends FilamentController {
} }
@override @override
Future moveCameraToAsset(FilamentEntity asset) async { Future moveCameraToAsset(FilamentEntity entity) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_lib.move_camera_to_asset(_viewer!, asset); _lib.move_camera_to_asset(_viewer!, entity);
} }
@override @override
@@ -880,75 +880,76 @@ class FilamentControllerFFI extends FilamentController {
} }
@override @override
Future setMaterialColor(FilamentEntity asset, String meshName, Future setMaterialColor(FilamentEntity entity, String meshName,
int materialIndex, Color color) async { int materialIndex, Color color) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
var result = _lib.set_material_color( var result = _lib.set_material_color(
_assetManager!, _assetManager!,
asset, entity,
meshName.toNativeUtf8().cast<Char>(), meshName.toNativeUtf8().cast<Char>(),
materialIndex, materialIndex,
color.red.toDouble() / 255.0, color.red.toDouble() / 255.0,
color.green.toDouble() / 255.0, color.green.toDouble() / 255.0,
color.blue.toDouble() / 255.0, color.blue.toDouble() / 255.0,
color.alpha.toDouble() / 255.0); color.alpha.toDouble() / 255.0);
if (result != 1) { if (!result) {
throw Exception("Failed to set material color"); throw Exception("Failed to set material color");
} }
} }
@override @override
Future transformToUnitCube(FilamentEntity asset) async { Future transformToUnitCube(FilamentEntity entity) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_lib.transform_to_unit_cube(_assetManager!, asset); _lib.transform_to_unit_cube(_assetManager!, entity);
} }
@override @override
Future setPosition(FilamentEntity asset, double x, double y, double z) async { Future setPosition(
FilamentEntity entity, double x, double y, double z) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_lib.set_position(_assetManager!, asset, x, y, z); _lib.set_position(_assetManager!, entity, x, y, z);
} }
@override @override
Future setScale(FilamentEntity asset, double scale) async { Future setScale(FilamentEntity entity, double scale) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_lib.set_scale(_assetManager!, asset, scale); _lib.set_scale(_assetManager!, entity, scale);
} }
@override @override
Future setRotation( Future setRotation(
FilamentEntity asset, double rads, double x, double y, double z) async { FilamentEntity entity, double rads, double x, double y, double z) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_lib.set_rotation(_assetManager!, asset, rads, x, y, z); _lib.set_rotation(_assetManager!, entity, rads, x, y, z);
} }
@override @override
Future hide(FilamentEntity asset, String meshName) async { Future hide(FilamentEntity entity, String meshName) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
if (_lib.hide_mesh( if (_lib.hide_mesh(
_assetManager!, asset, meshName.toNativeUtf8().cast<Char>()) != _assetManager!, entity, meshName.toNativeUtf8().cast<Char>()) !=
1) {} 1) {}
} }
@override @override
Future reveal(FilamentEntity asset, String meshName) async { Future reveal(FilamentEntity entity, String meshName) async {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
if (_lib.reveal_mesh( if (_lib.reveal_mesh(
_assetManager!, asset, meshName.toNativeUtf8().cast<Char>()) != _assetManager!, entity, meshName.toNativeUtf8().cast<Char>()) !=
1) { 1) {
throw Exception("Failed to reveal mesh $meshName"); throw Exception("Failed to reveal mesh $meshName");
} }

View File

@@ -1,7 +1,7 @@
// AUTO GENERATED FILE, DO NOT EDIT. // AUTO GENERATED FILE, DO NOT EDIT.
// //
// Generated by `package:ffigen`. // Generated by `package:ffigen`.
// ignore_for_file: type=lint // ignore_for_file: type=lint, unused_element, unused_field
import 'dart:ffi' as ffi; import 'dart:ffi' as ffi;
class NativeLibrary { class NativeLibrary {

View File

@@ -1,4 +1,5 @@
import 'dart:ffi'; import 'dart:ffi';
import 'dart:developer' as dev;
class RenderingSurface { class RenderingSurface {
final int flutterTextureId; final int flutterTextureId;
@@ -15,22 +16,23 @@ class RenderingSurface {
// null on iOS/Android, void* on MacOS (pointer to metal texture), GLuid on Windows/Linux // null on iOS/Android, void* on MacOS (pointer to metal texture), GLuid on Windows/Linux
var nativeTexture = platformMessage[2] as int? ?? 0; var nativeTexture = platformMessage[2] as int? ?? 0;
if(nativeTexture != 0) { if (nativeTexture != 0) {
assert(surfaceAddress == 0); assert(surfaceAddress == 0);
} }
var sharedContext = platformMessage[3] as int? ?? 0; var sharedContext = platformMessage[3] as int? ?? 0;
print( dev.log(
"Using flutterTextureId $flutterTextureId, surface $surfaceAddress nativeTexture $nativeTexture and sharedContext $sharedContext"); "Using flutterTextureId $flutterTextureId, surface $surfaceAddress nativeTexture $nativeTexture and sharedContext $sharedContext");
return RenderingSurface( return RenderingSurface(
sharedContext: sharedContext, sharedContext: sharedContext,
flutterTextureId: flutterTextureId, flutterTextureId: flutterTextureId,
surface: Pointer<Void>.fromAddress(surfaceAddress), surface: Pointer<Void>.fromAddress(surfaceAddress),
textureHandle: nativeTexture); textureHandle: nativeTexture);
} }
RenderingSurface({required this.sharedContext, RenderingSurface(
{required this.sharedContext,
required this.flutterTextureId, required this.flutterTextureId,
required this.surface, required this.surface,
required this.textureHandle}); required this.textureHandle});

View File

@@ -1,14 +1,12 @@
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_filament/widgets/filament_gesture_detector_desktop.dart'; import 'package:flutter_filament/widgets/filament_gesture_detector_desktop.dart';
import 'package:flutter_filament/widgets/filament_gesture_detector_mobile.dart'; import 'package:flutter_filament/widgets/filament_gesture_detector_mobile.dart';
import '../filament_controller.dart'; import '../filament_controller.dart';
enum GestureType { RotateCamera, PanCamera, PanBackground } enum GestureType { rotateCamera, panCamera, panBackground }
/// ///
/// A widget that translates finger/mouse gestures to zoom/pan/rotate actions. /// A widget that translates finger/mouse gestures to zoom/pan/rotate actions.

View File

@@ -49,7 +49,8 @@ class _FilamentGestureDetectorDesktopState
/// ///
/// ///
/// ///
bool _scaling = false; // ignore: unused_field
final bool _scaling = false;
bool _pointerMoving = false; bool _pointerMoving = false;
@@ -78,7 +79,7 @@ class _FilamentGestureDetectorDesktopState
// we don't want to end the zoom in the same frame, because this will destroy the camera manipulator (and cancel the zoom update). // we don't want to end the zoom in the same frame, because this will destroy the camera manipulator (and cancel the zoom update).
// here, we just defer calling [zoomEnd] for 100ms to ensure the update is propagated through. // here, we just defer calling [zoomEnd] for 100ms to ensure the update is propagated through.
_scrollTimer = Timer(Duration(milliseconds: 100), () async { _scrollTimer = Timer(const Duration(milliseconds: 100), () async {
await widget.controller.zoomEnd(); await widget.controller.zoomEnd();
}); });
} }

View File

@@ -2,7 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../filament_controller.dart'; import '../filament_controller.dart';
enum GestureType { RotateCamera, PanCamera, PanBackground } enum GestureType { rotateCamera, panCamera, panBackground }
/// ///
/// A widget that translates finger/mouse gestures to zoom/pan/rotate actions. /// A widget that translates finger/mouse gestures to zoom/pan/rotate actions.
@@ -49,12 +49,12 @@ class FilamentGestureDetectorMobile extends StatefulWidget {
class _FilamentGestureDetectorMobileState class _FilamentGestureDetectorMobileState
extends State<FilamentGestureDetectorMobile> { extends State<FilamentGestureDetectorMobile> {
GestureType gestureType = GestureType.PanCamera; GestureType gestureType = GestureType.panCamera;
final _icons = { final _icons = {
GestureType.PanBackground: Icons.image, GestureType.panBackground: Icons.image,
GestureType.PanCamera: Icons.pan_tool, GestureType.panCamera: Icons.pan_tool,
GestureType.RotateCamera: Icons.rotate_90_degrees_ccw GestureType.rotateCamera: Icons.rotate_90_degrees_ccw
}; };
// on mobile, we can't differentiate between pointer down events like we do on desktop with primary/secondary/tertiary buttons // on mobile, we can't differentiate between pointer down events like we do on desktop with primary/secondary/tertiary buttons
@@ -69,8 +69,11 @@ class _FilamentGestureDetectorMobileState
// to avoid duplicating code for pan/rotate (panStart, panUpdate, panEnd, rotateStart, rotateUpdate etc) // to avoid duplicating code for pan/rotate (panStart, panUpdate, panEnd, rotateStart, rotateUpdate etc)
// we have only a single function for start/update/end. // we have only a single function for start/update/end.
// when the gesture type is changed, these properties are updated to point to the correct function. // when the gesture type is changed, these properties are updated to point to the correct function.
// ignore: unused_field
late Function(double x, double y) _functionStart; late Function(double x, double y) _functionStart;
// ignore: unused_field
late Function(double x, double y) _functionUpdate; late Function(double x, double y) _functionUpdate;
// ignore: unused_field
late Function() _functionEnd; late Function() _functionEnd;
@override @override
@@ -81,18 +84,18 @@ class _FilamentGestureDetectorMobileState
void _setFunction() { void _setFunction() {
switch (gestureType) { switch (gestureType) {
case GestureType.RotateCamera: case GestureType.rotateCamera:
_functionStart = widget.controller.rotateStart; _functionStart = widget.controller.rotateStart;
_functionUpdate = widget.controller.rotateUpdate; _functionUpdate = widget.controller.rotateUpdate;
_functionEnd = widget.controller.rotateEnd; _functionEnd = widget.controller.rotateEnd;
break; break;
case GestureType.PanCamera: case GestureType.panCamera:
_functionStart = widget.controller.panStart; _functionStart = widget.controller.panStart;
_functionUpdate = widget.controller.panUpdate; _functionUpdate = widget.controller.panUpdate;
_functionEnd = widget.controller.panEnd; _functionEnd = widget.controller.panEnd;
break; break;
// TODO // TODO
case GestureType.PanBackground: case GestureType.panBackground:
_functionStart = (x, y) async {}; _functionStart = (x, y) async {};
_functionUpdate = (x, y) async {}; _functionUpdate = (x, y) async {};
_functionEnd = () async {}; _functionEnd = () async {};
@@ -109,6 +112,7 @@ class _FilamentGestureDetectorMobileState
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
} }
// ignore: unused_field
Timer? _scrollTimer; Timer? _scrollTimer;
double _lastScale = 0; double _lastScale = 0;

View File

@@ -1,5 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'dart:developer' as dev;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -110,8 +111,7 @@ class _SizedFilamentWidget extends StatefulWidget {
final FilamentController controller; final FilamentController controller;
const _SizedFilamentWidget( const _SizedFilamentWidget(
{super.key, {required this.width,
required this.width,
required this.height, required this.height,
this.initial, this.initial,
required this.controller}); required this.controller});
@@ -145,7 +145,7 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
_pixelRatio = MediaQuery.of(context).devicePixelRatio; _pixelRatio = MediaQuery.of(context).devicePixelRatio;
widget.controller.setDimensions(_rect, _pixelRatio); widget.controller.setDimensions(_rect, _pixelRatio);
} catch (err) { } catch (err) {
print("Fatal error : $err"); dev.log("Fatal error : $err");
_error = err.toString(); _error = err.toString();
} }
setState(() {}); setState(() {});
@@ -158,7 +158,7 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
bool _resizing = false; bool _resizing = false;
Future _resize() { Future _resize() {
print("Resizing widget"); dev.log("Resizing widget");
final completer = Completer(); final completer = Completer();
// resizing the window can be sluggish (particular in debug mode), exacerbated when simultaneously recreating the swapchain and resize the window. // resizing the window can be sluggish (particular in debug mode), exacerbated when simultaneously recreating the swapchain and resize the window.
// to address this, whenever the widget is resized, we set a timer for Xms in the future. // to address this, whenever the widget is resized, we set a timer for Xms in the future.
@@ -186,7 +186,7 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
setState(() {}); setState(() {});
_resizing = false; _resizing = false;
} catch (err) { } catch (err) {
print("Error resizing FilamentWidget: $err"); dev.log("Error resizing FilamentWidget: $err");
} finally { } finally {
completer.complete(); completer.complete();
} }
@@ -215,21 +215,21 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
void _handleStateChange(AppLifecycleState state) async { void _handleStateChange(AppLifecycleState state) async {
switch (state) { switch (state) {
case AppLifecycleState.detached: case AppLifecycleState.detached:
print("Detached"); dev.log("Detached");
if (!_wasRenderingOnInactive) { if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = widget.controller.rendering; _wasRenderingOnInactive = widget.controller.rendering;
} }
await widget.controller.setRendering(false); await widget.controller.setRendering(false);
break; break;
case AppLifecycleState.hidden: case AppLifecycleState.hidden:
print("Hidden"); dev.log("Hidden");
if (!_wasRenderingOnInactive) { if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = widget.controller.rendering; _wasRenderingOnInactive = widget.controller.rendering;
} }
await widget.controller.setRendering(false); await widget.controller.setRendering(false);
break; break;
case AppLifecycleState.inactive: case AppLifecycleState.inactive:
print("Inactive"); dev.log("Inactive");
if (!_wasRenderingOnInactive) { if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = widget.controller.rendering; _wasRenderingOnInactive = widget.controller.rendering;
} }
@@ -238,14 +238,14 @@ class _SizedFilamentWidgetState extends State<_SizedFilamentWidget> {
await widget.controller.setRendering(false); await widget.controller.setRendering(false);
break; break;
case AppLifecycleState.paused: case AppLifecycleState.paused:
print("Paused"); dev.log("Paused");
if (!_wasRenderingOnInactive) { if (!_wasRenderingOnInactive) {
_wasRenderingOnInactive = widget.controller.rendering; _wasRenderingOnInactive = widget.controller.rendering;
} }
await widget.controller.setRendering(false); await widget.controller.setRendering(false);
break; break;
case AppLifecycleState.resumed: case AppLifecycleState.resumed:
print("Resumed"); dev.log("Resumed");
await widget.controller.setRendering(_wasRenderingOnInactive); await widget.controller.setRendering(_wasRenderingOnInactive);
break; break;
} }