refactor: gizmo/input handler improvements
This commit is contained in:
@@ -12,8 +12,8 @@ class DelegateInputHandler implements InputHandler {
|
|||||||
Stream<List<InputType>> get gestures => _gesturesController.stream;
|
Stream<List<InputType>> get gestures => _gesturesController.stream;
|
||||||
final _gesturesController = StreamController<List<InputType>>.broadcast();
|
final _gesturesController = StreamController<List<InputType>>.broadcast();
|
||||||
|
|
||||||
Stream get cameraUpdated => _cameraUpdatedController.stream;
|
Stream<Matrix4> get cameraUpdated => _cameraUpdatedController.stream;
|
||||||
final _cameraUpdatedController = StreamController.broadcast();
|
final _cameraUpdatedController = StreamController<Matrix4>.broadcast();
|
||||||
|
|
||||||
final _logger = Logger("DelegateInputHandler");
|
final _logger = Logger("DelegateInputHandler");
|
||||||
|
|
||||||
@@ -172,11 +172,13 @@ class DelegateInputHandler implements InputHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await transformDelegate?.execute();
|
var transform = await transformDelegate?.execute();
|
||||||
var updates = _inputDeltas.keys.followedBy(keyTypes).toList();
|
var updates = _inputDeltas.keys.followedBy(keyTypes).toList();
|
||||||
if (updates.isNotEmpty) {
|
if (updates.isNotEmpty) {
|
||||||
_gesturesController.add(updates);
|
_gesturesController.add(updates);
|
||||||
_cameraUpdatedController.add(true);
|
}
|
||||||
|
if (transform != null) {
|
||||||
|
_cameraUpdatedController.add(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
_inputDeltas.clear();
|
_inputDeltas.clear();
|
||||||
@@ -310,4 +312,7 @@ class DelegateInputHandler implements InputHandler {
|
|||||||
throw UnimplementedError("Only pointerCount <= 2 supported");
|
throw UnimplementedError("Only pointerCount <= 2 supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<Matrix4> get transformUpdated => cameraUpdated;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import 'input_handler.dart';
|
|||||||
|
|
||||||
abstract class InputHandlerDelegate {
|
abstract class InputHandlerDelegate {
|
||||||
Future queue(InputAction action, Vector3? delta);
|
Future queue(InputAction action, Vector3? delta);
|
||||||
Future execute();
|
Future<Matrix4?> execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class VelocityDelegate {
|
abstract class VelocityDelegate {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
|||||||
late Future<Camera> _camera;
|
late Future<Camera> _camera;
|
||||||
final double minimumDistance;
|
final double minimumDistance;
|
||||||
late final Vector3 target;
|
late final Vector3 target;
|
||||||
|
|
||||||
final double rotationSensitivity;
|
final double rotationSensitivity;
|
||||||
final double zoomSensitivity;
|
final double zoomSensitivity;
|
||||||
|
|
||||||
@@ -70,13 +70,13 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
|||||||
bool _executing = false;
|
bool _executing = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> execute() async {
|
Future<Matrix4?> execute() async {
|
||||||
if (_queuedRotationDelta.length2 == 0.0 && _queuedZoomDelta == 0.0) {
|
if (_queuedRotationDelta.length2 == 0.0 && _queuedZoomDelta == 0.0) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_executing) {
|
if (_executing) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_executing = true;
|
_executing = true;
|
||||||
@@ -97,6 +97,8 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
|||||||
currentPosition = Vector3(0, 0, minimumDistance);
|
currentPosition = Vector3(0, 0, minimumDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Matrix4? updatedModelMatrix = null;
|
||||||
|
|
||||||
// Zoom
|
// Zoom
|
||||||
if (_queuedZoomDelta != 0.0) {
|
if (_queuedZoomDelta != 0.0) {
|
||||||
var newPosition = currentPosition +
|
var newPosition = currentPosition +
|
||||||
@@ -116,6 +118,7 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
|||||||
newViewMatrix.invert();
|
newViewMatrix.invert();
|
||||||
|
|
||||||
await (await _camera).setModelMatrix(newViewMatrix);
|
await (await _camera).setModelMatrix(newViewMatrix);
|
||||||
|
updatedModelMatrix = newViewMatrix;
|
||||||
}
|
}
|
||||||
} else if (_queuedRotationDelta.length != 0) {
|
} else if (_queuedRotationDelta.length != 0) {
|
||||||
double rotateX = _queuedRotationDelta.x * rotationSensitivity;
|
double rotateX = _queuedRotationDelta.x * rotationSensitivity;
|
||||||
@@ -134,6 +137,7 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
|||||||
|
|
||||||
modelMatrix = rot1 * rot2 * modelMatrix;
|
modelMatrix = rot1 * rot2 * modelMatrix;
|
||||||
await (await _camera).setModelMatrix(modelMatrix);
|
await (await _camera).setModelMatrix(modelMatrix);
|
||||||
|
updatedModelMatrix = modelMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset queued deltas
|
// Reset queued deltas
|
||||||
@@ -141,5 +145,6 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
|||||||
_queuedZoomDelta = 0.0;
|
_queuedZoomDelta = 0.0;
|
||||||
|
|
||||||
_executing = false;
|
_executing = false;
|
||||||
|
return updatedModelMatrix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
|||||||
bool _executing = false;
|
bool _executing = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> execute() async {
|
Future<Matrix4?> execute() async {
|
||||||
if (_executing) {
|
if (_executing) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_executing = true;
|
_executing = true;
|
||||||
@@ -73,7 +73,7 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
|||||||
_queuedZoomDelta == 0.0 &&
|
_queuedZoomDelta == 0.0 &&
|
||||||
_queuedMoveDelta.length2 == 0.0) {
|
_queuedMoveDelta.length2 == 0.0) {
|
||||||
_executing = false;
|
_executing = false;
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final activeCamera = await viewer.getActiveCamera();
|
final activeCamera = await viewer.getActiveCamera();
|
||||||
@@ -128,12 +128,12 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
|||||||
relativeTranslation = modelMatrix.getRotation() * relativeTranslation;
|
relativeTranslation = modelMatrix.getRotation() * relativeTranslation;
|
||||||
}
|
}
|
||||||
|
|
||||||
await viewer.setTransform(
|
var updated = Matrix4.compose(
|
||||||
await entity,
|
relativeTranslation, relativeRotation, Vector3(1, 1, 1)) *
|
||||||
Matrix4.compose(
|
current;
|
||||||
relativeTranslation, relativeRotation, Vector3(1, 1, 1)) *
|
await viewer.setTransform(await entity, updated);
|
||||||
current);
|
|
||||||
|
|
||||||
_executing = false;
|
_executing = false;
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,27 +4,35 @@ import 'package:thermion_dart/thermion_dart.dart';
|
|||||||
import 'package:vector_math/vector_math_64.dart';
|
import 'package:vector_math/vector_math_64.dart';
|
||||||
|
|
||||||
class _Gizmo {
|
class _Gizmo {
|
||||||
bool isVisible = false;
|
|
||||||
final ThermionViewer viewer;
|
final ThermionViewer viewer;
|
||||||
|
|
||||||
final GizmoAsset _gizmo;
|
final GizmoAsset _gizmo;
|
||||||
ThermionEntity? _attachedTo;
|
|
||||||
|
|
||||||
final attachedTo = StreamController<ThermionEntity?>.broadcast();
|
final transformUpdates = StreamController<({Matrix4 transform})>.broadcast();
|
||||||
|
|
||||||
final GizmoType _gizmoType;
|
Axis? _active;
|
||||||
|
final GizmoType type;
|
||||||
|
|
||||||
_Gizmo(this._gizmo, this.viewer, this._gizmoType);
|
_Gizmo(this._gizmo, this.viewer, this.type);
|
||||||
|
|
||||||
static Future<_Gizmo> forType(ThermionViewer viewer, GizmoType type) async {
|
static Future<_Gizmo> forType(ThermionViewer viewer, GizmoType type) async {
|
||||||
final view = await viewer.getViewAt(0);
|
final view = await viewer.getViewAt(0);
|
||||||
return _Gizmo(await viewer.createGizmo(view, type), viewer, type);
|
return _Gizmo(await viewer.createGizmo(view, type), viewer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
final _onEntityTransformUpdated = StreamController<
|
Future dispose() async {
|
||||||
({ThermionEntity entity, Matrix4 transform})>.broadcast();
|
await transformUpdates.close();
|
||||||
|
await viewer.removeAsset(_gizmo);
|
||||||
|
}
|
||||||
|
|
||||||
Axis? _active;
|
Future hide() async {
|
||||||
Axis? get active => _active;
|
await _gizmo.removeFromScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future reveal() async {
|
||||||
|
await _gizmo.addToScene();
|
||||||
|
gizmoTransform = await viewer.getWorldTransform(_gizmo.entity);
|
||||||
|
}
|
||||||
|
|
||||||
double _getAngleBetweenVectors(Vector2 v1, Vector2 v2) {
|
double _getAngleBetweenVectors(Vector2 v1, Vector2 v2) {
|
||||||
// Normalize vectors to ensure consistent rotation regardless of distance from center
|
// Normalize vectors to ensure consistent rotation regardless of distance from center
|
||||||
@@ -61,49 +69,16 @@ class _Gizmo {
|
|||||||
|
|
||||||
Matrix4? gizmoTransform;
|
Matrix4? gizmoTransform;
|
||||||
|
|
||||||
Future attach(ThermionEntity entity) async {
|
|
||||||
print("Attached to ${entity}");
|
|
||||||
|
|
||||||
if (_attachedTo != null && entity != _attachedTo) {
|
|
||||||
await viewer.setParent(_attachedTo!, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_attachedTo = entity;
|
|
||||||
attachedTo.add(_attachedTo);
|
|
||||||
|
|
||||||
await viewer.setParent(_gizmo.entity, entity);
|
|
||||||
await viewer.setTransform(_gizmo.entity, Matrix4.identity());
|
|
||||||
|
|
||||||
if (!isVisible) {
|
|
||||||
await _gizmo.addToScene();
|
|
||||||
isVisible = true;
|
|
||||||
}
|
|
||||||
gizmoTransform = await viewer.getWorldTransform(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future detach() async {
|
|
||||||
await _gizmo.removeFromScene();
|
|
||||||
if (_attachedTo != null) {
|
|
||||||
await viewer.setParent(_attachedTo!, 0);
|
|
||||||
}
|
|
||||||
attachedTo.add(null);
|
|
||||||
_active = null;
|
|
||||||
isVisible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _updateTransform(Vector2 currentPosition, Vector2 delta) async {
|
void _updateTransform(Vector2 currentPosition, Vector2 delta) async {
|
||||||
if (_attachedTo == null) {
|
if (type == GizmoType.translation) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_gizmoType == GizmoType.translation) {
|
|
||||||
await _updateTranslation(currentPosition, delta);
|
await _updateTranslation(currentPosition, delta);
|
||||||
} else if (_gizmoType == GizmoType.rotation) {
|
} else if (type == GizmoType.rotation) {
|
||||||
await _updateRotation(currentPosition, delta);
|
await _updateRotation(currentPosition, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onEntityTransformUpdated
|
await viewer.setTransform(_gizmo.entity, gizmoTransform!);
|
||||||
.add((entity: _attachedTo!, transform: gizmoTransform!));
|
|
||||||
|
transformUpdates.add((transform: gizmoTransform!));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateTranslation(
|
Future<void> _updateTranslation(
|
||||||
@@ -143,8 +118,6 @@ class _Gizmo {
|
|||||||
|
|
||||||
gizmoTransform!
|
gizmoTransform!
|
||||||
.setTranslation(gizmoTransform!.getTranslation() + worldSpaceDelta);
|
.setTranslation(gizmoTransform!.getTranslation() + worldSpaceDelta);
|
||||||
|
|
||||||
await viewer.setTransform(_attachedTo!, gizmoTransform!);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateRotation(Vector2 currentPosition, Vector2 delta) async {
|
Future<void> _updateRotation(Vector2 currentPosition, Vector2 delta) async {
|
||||||
@@ -210,7 +183,6 @@ class _Gizmo {
|
|||||||
|
|
||||||
// Apply rotation to the current transform
|
// Apply rotation to the current transform
|
||||||
gizmoTransform = gizmoTransform! * rotationMatrix;
|
gizmoTransform = gizmoTransform! * rotationMatrix;
|
||||||
await viewer.setTransform(_attachedTo!, gizmoTransform!);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,56 +193,60 @@ class GizmoInputHandler extends InputHandler {
|
|||||||
|
|
||||||
late final _gizmos = <GizmoType, _Gizmo>{};
|
late final _gizmos = <GizmoType, _Gizmo>{};
|
||||||
|
|
||||||
_Gizmo? active;
|
_Gizmo? _active;
|
||||||
|
|
||||||
StreamSubscription? _entityTransformUpdatedListener;
|
ThermionEntity? _attached;
|
||||||
StreamSubscription? _attachedToListener;
|
|
||||||
|
|
||||||
final _attachedTo = StreamController<ThermionEntity?>.broadcast();
|
Future attach(ThermionEntity entity) async {
|
||||||
Stream<ThermionEntity?> get attachedTo => _attachedTo.stream;
|
if (_attached != null) {
|
||||||
|
await detach();
|
||||||
GizmoType? getGizmoType() {
|
}
|
||||||
return active?._gizmoType;
|
_attached = entity;
|
||||||
|
if (_active != null) {
|
||||||
|
await viewer.setParent(_attached!, _active!._gizmo.entity);
|
||||||
|
await _active!.reveal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future setGizmoType(GizmoType? type) async {
|
Future detach() async {
|
||||||
if (type == null) {
|
if (_attached == null) {
|
||||||
await active?.detach();
|
|
||||||
active = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
await viewer.setParent(_attached!, 0);
|
||||||
var target = _gizmos[type]!;
|
await _active?.hide();
|
||||||
if (target != active) {
|
_attached = null;
|
||||||
await _entityTransformUpdatedListener?.cancel();
|
|
||||||
await _attachedToListener?.cancel();
|
|
||||||
if (active?._attachedTo != null) {
|
|
||||||
var attachedTo = active!._attachedTo!;
|
|
||||||
await active!.detach();
|
|
||||||
await target.attach(attachedTo);
|
|
||||||
}
|
|
||||||
active = target;
|
|
||||||
_entityTransformUpdatedListener =
|
|
||||||
active!._onEntityTransformUpdated.stream.listen((event) {
|
|
||||||
_transformUpdatedController.add(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
_attachedToListener = active!.attachedTo.stream.listen((entity) {
|
|
||||||
_attachedTo.add(entity);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final _transformUpdatedController =
|
final _initialized = Completer<bool>();
|
||||||
StreamController<({ThermionEntity entity, Matrix4 transform})>();
|
|
||||||
Stream<({ThermionEntity entity, Matrix4 transform})>
|
final _transformController = StreamController<Matrix4>.broadcast();
|
||||||
get onEntityTransformUpdated => _transformUpdatedController.stream;
|
Stream<Matrix4> get transformUpdated => _transformController.stream;
|
||||||
|
|
||||||
|
final _pickResultController = StreamController<ThermionEntity?>.broadcast();
|
||||||
|
Stream<ThermionEntity?> get onPickResult => _pickResultController.stream;
|
||||||
|
|
||||||
GizmoInputHandler({required this.wrapped, required this.viewer}) {
|
GizmoInputHandler({required this.wrapped, required this.viewer}) {
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
final _initialized = Completer<bool>();
|
GizmoType? getGizmoType() {
|
||||||
|
return _active?.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future setGizmoType(GizmoType? type) async {
|
||||||
|
if (type == null) {
|
||||||
|
await detach();
|
||||||
|
_active?.hide();
|
||||||
|
_active = null;
|
||||||
|
} else {
|
||||||
|
_active?.hide();
|
||||||
|
_active = _gizmos[type]!;
|
||||||
|
_active!.reveal();
|
||||||
|
if (_attached != null) {
|
||||||
|
await attach(_attached!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future initialize() async {
|
Future initialize() async {
|
||||||
if (_initialized.isCompleted) {
|
if (_initialized.isCompleted) {
|
||||||
@@ -283,16 +259,19 @@ class GizmoInputHandler extends InputHandler {
|
|||||||
_gizmos[GizmoType.rotation] =
|
_gizmos[GizmoType.rotation] =
|
||||||
await _Gizmo.forType(viewer, GizmoType.rotation);
|
await _Gizmo.forType(viewer, GizmoType.rotation);
|
||||||
await setGizmoType(GizmoType.translation);
|
await setGizmoType(GizmoType.translation);
|
||||||
|
for (final gizmo in _gizmos.values) {
|
||||||
|
gizmo.transformUpdates.stream.listen((update) {
|
||||||
|
_transformController.add(update.transform);
|
||||||
|
});
|
||||||
|
}
|
||||||
_initialized.complete(true);
|
_initialized.complete(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Stream get cameraUpdated => throw UnimplementedError();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future dispose() async {
|
Future dispose() async {
|
||||||
await viewer.removeEntity(_gizmos[GizmoType.rotation]!._gizmo);
|
_gizmos[GizmoType.rotation]!.dispose();
|
||||||
await viewer.removeEntity(_gizmos[GizmoType.translation]!._gizmo);
|
_gizmos[GizmoType.translation]!.dispose();
|
||||||
|
_gizmos.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -328,13 +307,13 @@ class GizmoInputHandler extends InputHandler {
|
|||||||
|
|
||||||
await viewer.pick(localPosition.x.toInt(), localPosition.y.toInt(),
|
await viewer.pick(localPosition.x.toInt(), localPosition.y.toInt(),
|
||||||
(result) async {
|
(result) async {
|
||||||
if (active?._gizmo.isNonPickable(result.entity) == true ||
|
if (_active?._gizmo.isNonPickable(result.entity) == true ||
|
||||||
result.entity == FILAMENT_ENTITY_NULL) {
|
result.entity == FILAMENT_ENTITY_NULL) {
|
||||||
await active!.detach();
|
_pickResultController.add(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (active?._gizmo.isGizmoEntity(result.entity) != true) {
|
if (_active?._gizmo.isGizmoEntity(result.entity) != true) {
|
||||||
active!.attach(result.entity);
|
_pickResultController.add(result.entity);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -344,18 +323,18 @@ class GizmoInputHandler extends InputHandler {
|
|||||||
if (!_initialized.isCompleted) {
|
if (!_initialized.isCompleted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
active?.checkHover(localPosition.x.floor(), localPosition.y.floor());
|
_active?.checkHover(localPosition.x.floor(), localPosition.y.floor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onPointerMove(
|
Future<void> onPointerMove(
|
||||||
Vector2 localPosition, Vector2 delta, bool isMiddle) async {
|
Vector2 localPosition, Vector2 delta, bool isMiddle) async {
|
||||||
if (!isMiddle && active?._active != null) {
|
if (!isMiddle && _active?._active != null) {
|
||||||
final scaledDelta = Vector2(
|
final scaledDelta = Vector2(
|
||||||
delta.x,
|
delta.x,
|
||||||
delta.y,
|
delta.y,
|
||||||
);
|
);
|
||||||
active!._updateTransform(localPosition, scaledDelta);
|
_active!._updateTransform(localPosition, scaledDelta);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return wrapped.onPointerMove(localPosition, delta, isMiddle);
|
return wrapped.onPointerMove(localPosition, delta, isMiddle);
|
||||||
@@ -401,18 +380,4 @@ class GizmoInputHandler extends InputHandler {
|
|||||||
void setActionForType(InputType gestureType, InputAction gestureAction) {
|
void setActionForType(InputType gestureType, InputAction gestureAction) {
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future detach(ThermionAsset asset) async {
|
|
||||||
if (active?._attachedTo == asset.entity) {
|
|
||||||
await active!.detach();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final childEntities = await asset.getChildEntities();
|
|
||||||
for (final childEntity in childEntities) {
|
|
||||||
if (active?._attachedTo == childEntity) {
|
|
||||||
await active!.detach();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Future dispose() async {
|
// Future dispose() async {
|
||||||
// await viewer.removeEntity(_translationGizmo);
|
// await viewer.removeAsset(_translationGizmo);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ class OverTheShoulderCameraDelegate implements InputHandlerDelegate {
|
|||||||
static bool get executing => _executing;
|
static bool get executing => _executing;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> execute() async {
|
Future<Matrix4?> execute() async {
|
||||||
if (_executing) {
|
if (_executing) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_executing = true;
|
_executing = true;
|
||||||
@@ -76,7 +76,7 @@ class OverTheShoulderCameraDelegate implements InputHandlerDelegate {
|
|||||||
_queuedZoomDelta == 0.0 &&
|
_queuedZoomDelta == 0.0 &&
|
||||||
_queuedMoveDelta.length2 == 0.0) {
|
_queuedMoveDelta.length2 == 0.0) {
|
||||||
_executing = false;
|
_executing = false;
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 currentPlayerTransform = await viewer.getWorldTransform(player);
|
Matrix4 currentPlayerTransform = await viewer.getWorldTransform(player);
|
||||||
@@ -97,10 +97,8 @@ class OverTheShoulderCameraDelegate implements InputHandlerDelegate {
|
|||||||
|
|
||||||
// camera is always looking at -Z, whereas models generally face towards +Z
|
// camera is always looking at -Z, whereas models generally face towards +Z
|
||||||
if (_queuedRotationDelta.length2 > 0.0) {
|
if (_queuedRotationDelta.length2 > 0.0) {
|
||||||
double deltaX =
|
double deltaX = _queuedRotationDelta.x * rotationSensitivity;
|
||||||
_queuedRotationDelta.x * rotationSensitivity;
|
double deltaY = _queuedRotationDelta.y * rotationSensitivity;
|
||||||
double deltaY =
|
|
||||||
_queuedRotationDelta.y * rotationSensitivity;
|
|
||||||
|
|
||||||
cameraLookAt = Matrix4.rotationY(-deltaX) *
|
cameraLookAt = Matrix4.rotationY(-deltaX) *
|
||||||
Matrix4.rotationX(-deltaY) *
|
Matrix4.rotationX(-deltaY) *
|
||||||
@@ -118,5 +116,6 @@ class OverTheShoulderCameraDelegate implements InputHandlerDelegate {
|
|||||||
[camera.getEntity(), player], [newCameraTransform, newPlayerTransform]);
|
[camera.getEntity(), player], [newCameraTransform, newPlayerTransform]);
|
||||||
onUpdate?.call(newPlayerTransform);
|
onUpdate?.call(newPlayerTransform);
|
||||||
_executing = false;
|
_executing = false;
|
||||||
|
return newCameraTransform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:thermion_dart/thermion_dart.dart';
|
|
||||||
import 'package:vector_math/vector_math_64.dart';
|
import 'package:vector_math/vector_math_64.dart';
|
||||||
|
|
||||||
enum InputType {
|
enum InputType {
|
||||||
@@ -30,7 +28,11 @@ enum PhysicalKey { W, A, S, D }
|
|||||||
enum InputAction { TRANSLATE, ROTATE, PICK, ZOOM, NONE }
|
enum InputAction { TRANSLATE, ROTATE, PICK, ZOOM, NONE }
|
||||||
|
|
||||||
abstract class InputHandler {
|
abstract class InputHandler {
|
||||||
Stream get cameraUpdated;
|
|
||||||
|
@Deprecated("Use @transformUpdated instead")
|
||||||
|
Stream get cameraUpdated => transformUpdated;
|
||||||
|
|
||||||
|
Stream<Matrix4> get transformUpdated;
|
||||||
|
|
||||||
Future<void> onPointerHover(Vector2 localPosition, Vector2 delta);
|
Future<void> onPointerHover(Vector2 localPosition, Vector2 delta);
|
||||||
Future<void> onPointerScroll(Vector2 localPosition, double scrollDelta);
|
Future<void> onPointerScroll(Vector2 localPosition, double scrollDelta);
|
||||||
@@ -59,5 +61,4 @@ abstract class InputHandler {
|
|||||||
void keyDown(PhysicalKey key);
|
void keyDown(PhysicalKey key);
|
||||||
void keyUp(PhysicalKey key);
|
void keyUp(PhysicalKey key);
|
||||||
|
|
||||||
// Future setCamera(Camera camera);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user