add implementations to FFI viewer

This commit is contained in:
Nick Fisher
2024-08-24 16:24:59 +08:00
parent f1a2926bdf
commit 3c05cc6a43
3 changed files with 80 additions and 55 deletions

View File

@@ -1,6 +1,3 @@
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
import 'package:vector_math/vector_math_64.dart';
@@ -15,9 +12,7 @@ abstract class AbstractGizmo {
void detach();
Aabb2 boundingBox = Aabb2();
Stream<Aabb2> get boundingBox;
void checkHover(double x, double y) {
if(boundingBox.containsVector2(Vector2(x, y)));
}
void checkHover(double x, double y);
}

View File

@@ -1,15 +1,13 @@
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'dart:async';
import 'package:thermion_dart/thermion_dart/entities/abstract_gizmo.dart';
import 'package:vector_math/vector_math_64.dart';
import '../thermion_viewer.dart';
class Gizmo extends AbstractGizmo {
final ThermionEntity x;
final ThermionEntity y;
final ThermionEntity z;
final ThermionEntity center;
final ThermionViewer _viewer;
@@ -20,11 +18,14 @@ class Gizmo extends AbstractGizmo {
final Set<ThermionEntity> ignore;
Aabb2 boundingBox = Aabb2();
Stream<Aabb2> get boundingBox => _boundingBoxController.stream;
final _boundingBoxController = StreamController<Aabb2>.broadcast();
Gizmo(this.x, this.y, this.z, this.center, this._viewer,
{this.ignore = const <ThermionEntity>{}}) {
_viewer.pickResult.listen(_onPickResult);
}
Future _reveal() async {
@@ -42,19 +43,19 @@ class Gizmo extends AbstractGizmo {
if (!_stopwatch.isRunning) {
_stopwatch.start();
}
if (_activeAxis == x) {
_translation += Vector3(transX, 0.0, 0.0);
} else {
_translation += Vector3(0.0, transY, 0.0);
}
if (_stopwatch.elapsedMilliseconds > 16) {
await _viewer.queuePositionUpdate(
_activeEntity!, _translation.x, _translation.y, _translation.z,
relative: true);
_stopwatch.reset();
_translation = Vector3.zero();
}
_translation = Vector3(_activeAxis == x ? 1.0 : 0.0,
_activeAxis == y ? 1.0 : 0.0, _activeAxis == z ? 1.0 : 0.0);
await _viewer.queueRelativePositionUpdateWorldAxis(
_activeEntity!,
transX * _viewer.pixelRatio,
-transY * _viewer.pixelRatio,
_translation.x,
_translation.y,
_translation.z);
_stopwatch.reset();
_translation = Vector3.zero();
}
void reset() {
@@ -62,14 +63,19 @@ class Gizmo extends AbstractGizmo {
}
void _onPickResult(FilamentPickResult result) async {
if (ignore.contains(result)) {
detach();
return;
}
// print(
// "Pick result ${result}, x is ${x}, y is $y, z is $z, ignore is $ignore");
// if (ignore.contains(result)) {
// print("Ignore/detach");
// detach();
// return;
// }
if (result.entity == x || result.entity == y || result.entity == z) {
_activeAxis = result.entity;
print("Set active axis to $_activeAxis");
} else {
attach(result.entity);
print("Attaching to ${result.entity}");
}
}
@@ -78,21 +84,21 @@ class Gizmo extends AbstractGizmo {
_activeEntity = entity;
await _reveal();
await _viewer.setParent(x, entity);
await _viewer.setParent(y, entity);
await _viewer.setParent(z, entity);
await _viewer.setParent(center, entity);
boundingBox = await _viewer.getBoundingBox(x);
_boundingBoxController.sink.add(await _viewer.getBoundingBox(x));
}
void detach() async {
await _viewer.setParent(x, 0);
await _viewer.setParent(y, 0);
await _viewer.setParent(z, 0);
await _viewer.setParent(center, 0);
await _viewer.hide(x, null);
await _viewer.hide(y, null);
await _viewer.hide(z, null);
await _viewer.hide(center, null);
}
@override
void checkHover(double x, double y) {
_viewer.pick(x.toInt(), y.toInt());
}
}

View File

@@ -24,7 +24,7 @@ class ThermionViewerFFI extends ThermionViewer {
SceneImpl? _scene;
Scene get scene => _scene!;
double _pixelRatio = 1.0;
double pixelRatio = 1.0;
Pointer<Void>? _sceneManager;
@@ -85,6 +85,7 @@ class ThermionViewerFFI extends ThermionViewer {
}
Future updateViewportAndCameraProjection(double width, double height) async {
viewportDimensions = (width * pixelRatio, height * pixelRatio);
await withVoidCallback((callback) {
update_viewport_and_camera_projection_ffi(
_viewer!, width.toInt(), height.toInt(), 1.0, callback);
@@ -128,11 +129,11 @@ class ThermionViewerFFI extends ThermionViewer {
await setCameraManipulatorOptions(zoomSpeed: 1.0);
final out = allocator<EntityId>(4);
get_gizmo(_sceneManager!, out);
_gizmo = Gizmo(out[0], out[1], out[2], out[3], this);
allocator.free(out);
final gizmoEntities = allocator<Int32>(4);
get_gizmo(_sceneManager!, gizmoEntities);
_gizmo = Gizmo(gizmoEntities[0], gizmoEntities[1], gizmoEntities[2],
gizmoEntities[3], this);
allocator.free(gizmoEntities);
this._initialized.complete(true);
}
@@ -466,7 +467,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future panStart(double x, double y) async {
grab_begin(_viewer!, x * _pixelRatio, y * _pixelRatio, true);
grab_begin(_viewer!, x * pixelRatio, y * pixelRatio, true);
}
///
@@ -474,7 +475,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future panUpdate(double x, double y) async {
grab_update(_viewer!, x * _pixelRatio, y * _pixelRatio);
grab_update(_viewer!, x * pixelRatio, y * pixelRatio);
}
///
@@ -490,7 +491,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future rotateStart(double x, double y) async {
grab_begin(_viewer!, x * _pixelRatio, y * _pixelRatio, false);
grab_begin(_viewer!, x * pixelRatio, y * pixelRatio, false);
}
///
@@ -498,7 +499,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future rotateUpdate(double x, double y) async {
grab_update(_viewer!, x * _pixelRatio, y * _pixelRatio);
grab_update(_viewer!, x * pixelRatio, y * pixelRatio);
}
///
@@ -1136,12 +1137,19 @@ class ThermionViewerFFI extends ThermionViewer {
set_camera_focal_length(_viewer!, focalLength);
}
///
///
///
Future<double> getCameraFov(bool horizontal) async {
return get_camera_fov(_viewer!, horizontal);
}
///
///
///
@override
Future setCameraFov(double degrees, double width, double height) async {
set_camera_fov(_viewer!, degrees, width / height);
Future setCameraFov(double degrees, {bool horizontal = true}) async {
set_camera_fov(_viewer!, degrees, horizontal);
}
///
@@ -1319,6 +1327,12 @@ class ThermionViewerFFI extends ThermionViewer {
queue_position_update(_sceneManager!, entity, x, y, z, relative);
}
Future queueRelativePositionUpdateWorldAxis(ThermionEntity entity,
double viewportX, double viewportY, double x, double y, double z) async {
queue_relative_position_update_world_axis(
_sceneManager!, entity, viewportX, viewportY, x, y, z);
}
///
///
///
@@ -1359,8 +1373,8 @@ class ThermionViewerFFI extends ThermionViewer {
void _onPickResult(ThermionEntity entityId, int x, int y) {
_pickResultController.add((
entity: entityId,
x: (x / _pixelRatio).toDouble(),
y: (viewportDimensions.$2 - y) / _pixelRatio
x: (x / pixelRatio).toDouble(),
y: (viewportDimensions.$2 - y) / pixelRatio
));
_scene!.registerSelected(entityId);
}
@@ -1375,11 +1389,10 @@ class ThermionViewerFFI extends ThermionViewer {
void pick(int x, int y) async {
_scene!.unregisterSelected();
filament_pick(
_viewer!,
(x * _pixelRatio).toInt(),
(viewportDimensions.$2 - (y * _pixelRatio)).toInt(),
_onPickResultCallable.nativeFunction);
x = (x * pixelRatio).ceil();
y = (viewportDimensions.$2 - (y * pixelRatio)).ceil();
filament_pick(_viewer!, x, y, _onPickResultCallable.nativeFunction);
}
///
@@ -1700,7 +1713,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
@override
Future setParent(ThermionEntity child, ThermionEntity parent, { bool preserveScaling = false}) async {
Future setParent(ThermionEntity child, ThermionEntity parent,
{bool preserveScaling = false}) async {
if (_sceneManager == null) {
throw Exception("Asset manager must be non-null");
}
@@ -1738,10 +1752,20 @@ class ThermionViewerFFI extends ThermionViewer {
set_priority(_sceneManager!, entityId, priority);
}
///
///
///
@override
Future<v64.Aabb2> getBoundingBox(ThermionEntity entityId) async {
final result = get_bounding_box(_sceneManager!, entityId);
return v64.Aabb2.minMax(v64.Vector2(result.minX, result.minY),
v64.Vector2(result.maxX, result.maxY));
}
///
///
///
Future setLayerEnabled(int layer, bool enabled) async {
set_layer_enabled(_sceneManager!, layer, enabled);
}
}