chore: rearrange library/export structure
This commit is contained in:
@@ -8,7 +8,7 @@ import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dar
|
||||
/// Handles all platform-specific initialization to create a backing rendering
|
||||
/// surface in a Flutter application and lifecycle listeners to pause rendering
|
||||
/// when the app is inactive or in the background.
|
||||
/// Call [createViewer] to create an instance of [ThermionViewer].
|
||||
/// Call [createViewerWithOptions] to create an instance of [ThermionViewer].
|
||||
///
|
||||
class ThermionFlutterPlugin {
|
||||
ThermionFlutterPlugin._();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';import 'package:flutter/material.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../utils/camera_orientation.dart';
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// import 'package:flutter/widgets.dart';
|
||||
// import 'package:thermion_dart/thermion_dart/input/input_handler.dart';
|
||||
|
||||
// class MobileGestureHandlerSelectorWidget extends StatelessWidget {
|
||||
// final InputHandler handler;
|
||||
|
||||
// const MobileGestureHandlerSelectorWidget({super.key, required this.handler});
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// throw Exception("TODO");
|
||||
// // return GestureDetector(
|
||||
// // onTap: () {
|
||||
|
||||
// // var curIdx =
|
||||
// // InputType.values.indexOf(handler.gestureType);
|
||||
// // var nextIdx =
|
||||
// // curIdx == InputType.values.length - 1 ? 0 : curIdx + 1;
|
||||
// // handler.setInputType(InputType.values[nextIdx]);
|
||||
// // });
|
||||
// // },
|
||||
// // child: Container(
|
||||
// // padding: const EdgeInsets.all(50),
|
||||
// // child: Icon(_icons[widget.gestureHandler.gestureType],
|
||||
// // color: Colors.green),
|
||||
// // ),
|
||||
// // );
|
||||
// }
|
||||
// }
|
||||
@@ -1,86 +0,0 @@
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
///
|
||||
/// A widget that translates finger/mouse gestures to zoom/pan/rotate actions.
|
||||
///
|
||||
@Deprecated("Use ThermionListenerWidget instead")
|
||||
class ThermionGestureDetector extends StatelessWidget {
|
||||
///
|
||||
/// The content to display below the gesture detector/listener widget.
|
||||
/// This will usually be a ThermionWidget (so you can navigate by directly interacting with the viewport), but this is not necessary.
|
||||
/// It is equally possible to render the viewport/gesture controls elsewhere in the widget hierarchy. The only requirement is that they share the same [FilamentController].
|
||||
///
|
||||
final Widget? child;
|
||||
|
||||
///
|
||||
/// The [controller] attached to the [ThermionWidget] you wish to control.
|
||||
///
|
||||
final ThermionViewer controller;
|
||||
|
||||
///
|
||||
/// If true, an overlay will be shown with buttons to toggle whether pointer movements are interpreted as:
|
||||
/// 1) rotate or a pan (mobile only),
|
||||
/// 2) moving the camera or the background image (TODO).
|
||||
///
|
||||
final bool showControlOverlay;
|
||||
|
||||
///
|
||||
/// If false, gestures will not manipulate the active camera.
|
||||
///
|
||||
final bool enableCamera;
|
||||
|
||||
///
|
||||
/// If false, pointer down events will not trigger hit-testing (picking).
|
||||
///
|
||||
final bool enablePicking;
|
||||
|
||||
final void Function(ScaleStartDetails)? onScaleStart;
|
||||
final void Function(ScaleUpdateDetails)? onScaleUpdate;
|
||||
final void Function(ScaleEndDetails)? onScaleEnd;
|
||||
|
||||
const ThermionGestureDetector(
|
||||
{Key? key,
|
||||
required this.controller,
|
||||
this.child,
|
||||
this.showControlOverlay = false,
|
||||
this.enableCamera = true,
|
||||
this.enablePicking = false,
|
||||
this.onScaleStart,
|
||||
this.onScaleUpdate,
|
||||
this.onScaleEnd})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
throw Exception("TODO");
|
||||
// return FutureBuilder(
|
||||
// future: controller.initialized,
|
||||
// builder: (_, initialized) {
|
||||
// if (initialized.data != true) {
|
||||
// return child ?? Container();
|
||||
// }
|
||||
// if (kIsWeb || Platform.isLinux ||
|
||||
// Platform.isWindows ||
|
||||
// Platform.isMacOS) {
|
||||
// return ThermionGestureDetectorDesktop(
|
||||
// controller: controller,
|
||||
// child: child,
|
||||
// showControlOverlay: showControlOverlay,
|
||||
// enableCamera: enableCamera,
|
||||
// enablePicking: enablePicking,
|
||||
// );
|
||||
// } else {
|
||||
// return ThermionGestureDetectorMobile(
|
||||
// controller: controller,
|
||||
// child: child,
|
||||
// showControlOverlay: showControlOverlay,
|
||||
// enableCamera: enableCamera,
|
||||
// enablePicking: enablePicking,
|
||||
// onScaleStart: onScaleStart,
|
||||
// onScaleUpdate: onScaleUpdate,
|
||||
// onScaleEnd: onScaleEnd);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
// import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
// import 'package:flutter/gestures.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
|
||||
// import 'package:vector_math/vector_math_64.dart';
|
||||
// import 'dart:ui' show Offset;
|
||||
|
||||
// extension OffsetExtension on Offset {
|
||||
// Vector2 toVector2() {
|
||||
// return Vector2(dx, dy);
|
||||
// }
|
||||
// }
|
||||
|
||||
// class ThermionGestureDetectorDesktop extends StatefulWidget {
|
||||
// final Widget? child;
|
||||
// final InputHandler gestureHandler;
|
||||
// final bool showControlOverlay;
|
||||
// final bool enableCamera;
|
||||
// final bool enablePicking;
|
||||
|
||||
// const ThermionGestureDetectorDesktop({
|
||||
// Key? key,
|
||||
// required this.gestureHandler,
|
||||
// this.child,
|
||||
// this.showControlOverlay = false,
|
||||
// this.enableCamera = true,
|
||||
// this.enablePicking = true,
|
||||
// }) : super(key: key);
|
||||
|
||||
// @override
|
||||
// State<StatefulWidget> createState() => _ThermionGestureDetectorDesktopState();
|
||||
// }
|
||||
|
||||
// class _ThermionGestureDetectorDesktopState
|
||||
// extends State<ThermionGestureDetectorDesktop> {
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Listener(
|
||||
// onPointerHover: (event) =>
|
||||
// widget.gestureHandler.onPointerHover(event.localPosition.toVector2(), event.delta.toVector2()),
|
||||
// onPointerSignal: (PointerSignalEvent pointerSignal) {
|
||||
// if (pointerSignal is PointerScrollEvent) {
|
||||
// widget.gestureHandler.onPointerScroll(
|
||||
// pointerSignal.localPosition.toVector2(), pointerSignal.scrollDelta.dy);
|
||||
// }
|
||||
// },
|
||||
// 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: (PointerMoveEvent d) =>
|
||||
// widget.gestureHandler.onPointerMove(d.localPosition.toVector2(), d.delta.toVector2(), d.buttons & kMiddleMouseButton != 0),
|
||||
// onPointerUp: (d) => widget.gestureHandler.onPointerUp(d.buttons),
|
||||
// child: widget.child,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
@@ -1,234 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum InputType { rotateCamera, panCamera, panBackground }
|
||||
|
||||
///
|
||||
/// A widget that translates finger/mouse gestures to zoom/pan/rotate actions.
|
||||
///
|
||||
class ThermionGestureDetectorMobile extends StatefulWidget {
|
||||
///
|
||||
/// The content to display below the gesture detector/listener widget.
|
||||
/// This will usually be a ThermionWidget (so you can navigate by directly interacting with the viewport), but this is not necessary.
|
||||
/// It is equally possible to render the viewport/gesture controls elsewhere in the widget hierarchy. The only requirement is that they share the same [Filamentviewer].
|
||||
///
|
||||
final Widget? child;
|
||||
|
||||
///
|
||||
/// The [viewer] attached to the [ThermionWidget] you wish to control.
|
||||
///
|
||||
final ThermionViewer viewer;
|
||||
|
||||
///
|
||||
/// If true, an overlay will be shown with buttons to toggle whether pointer movements are interpreted as:
|
||||
/// 1) rotate or a pan (mobile only),
|
||||
/// 2) moving the camera or the background image (TODO).
|
||||
///
|
||||
final bool showControlOverlay;
|
||||
|
||||
///
|
||||
/// If false, gestures will not manipulate the active camera.
|
||||
///
|
||||
final bool enableCamera;
|
||||
|
||||
///
|
||||
/// If false, pointer down events will not trigger hit-testing (picking).
|
||||
///
|
||||
final bool enablePicking;
|
||||
|
||||
final double zoomDelta;
|
||||
|
||||
final void Function(ScaleStartDetails)? onScaleStart;
|
||||
final void Function(ScaleUpdateDetails)? onScaleUpdate;
|
||||
final void Function(ScaleEndDetails)? onScaleEnd;
|
||||
|
||||
const ThermionGestureDetectorMobile(
|
||||
{Key? key,
|
||||
required this.viewer,
|
||||
this.child,
|
||||
this.showControlOverlay = false,
|
||||
this.enableCamera = true,
|
||||
this.enablePicking = true,
|
||||
this.onScaleStart,
|
||||
this.onScaleUpdate,
|
||||
this.onScaleEnd,
|
||||
this.zoomDelta = 1})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ThermionGestureDetectorMobileState();
|
||||
}
|
||||
|
||||
class _ThermionGestureDetectorMobileState
|
||||
extends State<ThermionGestureDetectorMobile> {
|
||||
InputType gestureType = InputType.panCamera;
|
||||
|
||||
final _icons = {
|
||||
InputType.panBackground: Icons.image,
|
||||
InputType.panCamera: Icons.pan_tool,
|
||||
InputType.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
|
||||
// we allow the user to toggle between panning and rotating by double-tapping the widget
|
||||
bool _rotateOnPointerMove = false;
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
bool _scaling = false;
|
||||
|
||||
// to avoid duplicating code for pan/rotate (panStart, panUpdate, panEnd, rotateStart, rotateUpdate etc)
|
||||
// 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.
|
||||
// ignore: unused_field
|
||||
late Function(double x, double y) _functionStart;
|
||||
// ignore: unused_field
|
||||
late Function(double x, double y) _functionUpdate;
|
||||
// ignore: unused_field
|
||||
late Function() _functionEnd;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_setFunction();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _setFunction() {
|
||||
switch (gestureType) {
|
||||
case InputType.rotateCamera:
|
||||
_functionStart = widget.viewer.rotateStart;
|
||||
_functionUpdate = widget.viewer.rotateUpdate;
|
||||
_functionEnd = widget.viewer.rotateEnd;
|
||||
break;
|
||||
case InputType.panCamera:
|
||||
_functionStart = widget.viewer.panStart;
|
||||
_functionUpdate = widget.viewer.panUpdate;
|
||||
_functionEnd = widget.viewer.panEnd;
|
||||
break;
|
||||
// TODO
|
||||
case InputType.panBackground:
|
||||
_functionStart = (x, y) async {};
|
||||
_functionUpdate = (x, y) async {};
|
||||
_functionEnd = () async {};
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(ThermionGestureDetectorMobile oldWidget) {
|
||||
if (widget.showControlOverlay != oldWidget.showControlOverlay ||
|
||||
widget.enableCamera != oldWidget.enableCamera ||
|
||||
widget.enablePicking != oldWidget.enablePicking) {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
// ignore: unused_field
|
||||
Timer? _scrollTimer;
|
||||
double _lastScale = 0;
|
||||
|
||||
// pinch zoom on mobile
|
||||
// couldn't find any equivalent for pointerCount in Listener (?) so we use a GestureDetector
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTapDown: (d) {
|
||||
if (!widget.enablePicking) {
|
||||
return;
|
||||
}
|
||||
|
||||
widget.viewer.pick(
|
||||
d.globalPosition.dx.toInt(), d.globalPosition.dy.toInt());
|
||||
},
|
||||
onDoubleTap: () {
|
||||
setState(() {
|
||||
_rotateOnPointerMove = !_rotateOnPointerMove;
|
||||
});
|
||||
},
|
||||
onScaleStart: (d) async {
|
||||
if (widget.onScaleStart != null) {
|
||||
widget.onScaleStart!.call(d);
|
||||
return;
|
||||
}
|
||||
if (d.pointerCount == 2 && widget.enableCamera) {
|
||||
_scaling = true;
|
||||
await widget.viewer.zoomBegin();
|
||||
} else if (!_scaling && widget.enableCamera) {
|
||||
if (_rotateOnPointerMove) {
|
||||
widget.viewer.rotateStart(
|
||||
d.localFocalPoint.dx, d.localFocalPoint.dy);
|
||||
} else {
|
||||
widget.viewer
|
||||
.panStart(d.localFocalPoint.dx, d.localFocalPoint.dy);
|
||||
}
|
||||
}
|
||||
},
|
||||
onScaleUpdate: (ScaleUpdateDetails d) async {
|
||||
if (widget.onScaleUpdate != null) {
|
||||
widget.onScaleUpdate!.call(d);
|
||||
return;
|
||||
}
|
||||
if (d.pointerCount == 2 && widget.enableCamera) {
|
||||
if (d.horizontalScale != _lastScale) {
|
||||
widget.viewer.zoomUpdate(
|
||||
d.localFocalPoint.dx,
|
||||
d.localFocalPoint.dy,
|
||||
d.horizontalScale > _lastScale ? 0.1 : -0.1);
|
||||
_lastScale = d.horizontalScale;
|
||||
}
|
||||
} else if (!_scaling && widget.enableCamera) {
|
||||
if (_rotateOnPointerMove) {
|
||||
widget.viewer
|
||||
.rotateUpdate(d.focalPoint.dx, d.focalPoint.dy);
|
||||
} else {
|
||||
widget.viewer
|
||||
.panUpdate(d.focalPoint.dx, d.focalPoint.dy);
|
||||
}
|
||||
}
|
||||
},
|
||||
onScaleEnd: (d) async {
|
||||
if (widget.onScaleEnd != null) {
|
||||
widget.onScaleEnd!.call(d);
|
||||
return;
|
||||
}
|
||||
|
||||
if (d.pointerCount == 2 && widget.enableCamera) {
|
||||
widget.viewer.zoomEnd();
|
||||
} else if (!_scaling && widget.enableCamera) {
|
||||
if (_rotateOnPointerMove) {
|
||||
widget.viewer.rotateEnd();
|
||||
} else {
|
||||
widget.viewer.panEnd();
|
||||
}
|
||||
}
|
||||
_scaling = false;
|
||||
},
|
||||
child: widget.child)),
|
||||
widget.showControlOverlay
|
||||
? Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
var curIdx = InputType.values.indexOf(gestureType);
|
||||
var nextIdx = curIdx == InputType.values.length - 1
|
||||
? 0
|
||||
: curIdx + 1;
|
||||
gestureType = InputType.values[nextIdx];
|
||||
_setFunction();
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(50),
|
||||
child: Icon(_icons[gestureType], color: Colors.green)),
|
||||
))
|
||||
: Container()
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:math';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'dart:math';
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' as v;
|
||||
|
||||
class IblRotationSliderWidget extends StatefulWidget {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library;
|
||||
|
||||
export 'src/thermion_widget.dart';
|
||||
export 'src/camera/gestures/thermion_listener_widget.dart';
|
||||
export 'src/thermion_listener_widget.dart';
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'dart:async';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'dart:ffi';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:thermion_dart/thermion_dart/viewer/ffi/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'thermion_flutter_texture.dart';
|
||||
|
||||
class ThermionFlutterOptions {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
import 'package:thermion_dart/thermion_dart/viewer/web_wasm/src/thermion_viewer_wasm.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
|
||||
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
||||
|
||||
Reference in New Issue
Block a user