add implementations to FFI viewer
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user