gizmo & picking improvements
This commit is contained in:
@@ -6,10 +6,14 @@ class _Gizmo {
|
||||
bool isVisible = false;
|
||||
|
||||
final ThermionViewer viewer;
|
||||
final nonPickable = <ThermionEntity>{};
|
||||
final GizmoAsset _asset;
|
||||
final GizmoAsset _gizmo;
|
||||
|
||||
_Gizmo(this._asset, this.viewer);
|
||||
ThermionEntity? _attachedTo;
|
||||
|
||||
_Gizmo(this._gizmo, this.viewer);
|
||||
|
||||
final _onEntityTransformUpdated = StreamController<
|
||||
({ThermionEntity entity, Matrix4 transform})>.broadcast();
|
||||
|
||||
Axis? _active;
|
||||
Axis? get active => _active;
|
||||
@@ -17,10 +21,10 @@ class _Gizmo {
|
||||
Vector3? _activeCords;
|
||||
|
||||
void checkHover(int x, int y) async {
|
||||
_asset.pick(x, y, handler: (result, coords) async {
|
||||
_gizmo.pick(x, y, handler: (result, coords) async {
|
||||
switch (result) {
|
||||
case GizmoPickResultType.None:
|
||||
await _asset.unhighlight();
|
||||
await _gizmo.unhighlight();
|
||||
_active = null;
|
||||
break;
|
||||
case GizmoPickResultType.AxisX:
|
||||
@@ -43,29 +47,35 @@ class _Gizmo {
|
||||
Matrix4? gizmoTransform;
|
||||
|
||||
Future attach(ThermionEntity entity) async {
|
||||
if (_asset.nonPickableEntities.contains(entity)) {
|
||||
return;
|
||||
print("Attached to ${entity}");
|
||||
|
||||
if (_attachedTo != null && entity != _attachedTo) {
|
||||
await viewer.setParent(_attachedTo!, 0);
|
||||
}
|
||||
final transform = await viewer.getWorldTransform(entity);
|
||||
transform.setRotation(Matrix3.identity());
|
||||
transform.setDiagonal(Vector4.all(1.0));
|
||||
await viewer.setTransform(_asset.entity, transform);
|
||||
await viewer.setParent(entity, _asset.entity);
|
||||
|
||||
_attachedTo = entity;
|
||||
|
||||
await viewer.setParent(_gizmo.entity, entity);
|
||||
await viewer.setTransform(_gizmo.entity, Matrix4.identity());
|
||||
|
||||
if (!isVisible) {
|
||||
await _asset.addToScene();
|
||||
await _gizmo.addToScene();
|
||||
isVisible = true;
|
||||
}
|
||||
gizmoTransform = await viewer.getWorldTransform(_asset.entity);
|
||||
gizmoTransform = await viewer.getWorldTransform(entity);
|
||||
}
|
||||
|
||||
Future detach() async {
|
||||
await _asset.removeFromScene();
|
||||
await _gizmo.removeFromScene();
|
||||
if (_attachedTo != null) {
|
||||
await viewer.setParent(_attachedTo!, 0);
|
||||
}
|
||||
_active = null;
|
||||
isVisible = false;
|
||||
}
|
||||
|
||||
void _updateTransform(Vector2 currentPosition, Vector2 delta) async {
|
||||
if (gizmoTransform == null) {
|
||||
if (_attachedTo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,9 +114,13 @@ class _Gizmo {
|
||||
Vector3 worldSpaceDelta = newPosition - gizmoTransform!.getTranslation();
|
||||
worldSpaceDelta.multiply(_active!.asVector());
|
||||
|
||||
gizmoTransform!.setTranslation(gizmoTransform!.getTranslation() + worldSpaceDelta);
|
||||
gizmoTransform!
|
||||
.setTranslation(gizmoTransform!.getTranslation() + worldSpaceDelta);
|
||||
|
||||
await viewer.setTransform(_asset.entity, gizmoTransform!);
|
||||
await viewer.setTransform(_attachedTo!, gizmoTransform!);
|
||||
|
||||
_onEntityTransformUpdated
|
||||
.add((entity: _attachedTo!, transform: gizmoTransform!));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,11 +129,16 @@ class GizmoInputHandler extends InputHandler {
|
||||
final ThermionViewer viewer;
|
||||
late final _Gizmo translationGizmo;
|
||||
|
||||
Stream<({ThermionEntity entity, Matrix4 transform})>
|
||||
get onEntityTransformUpdated =>
|
||||
translationGizmo._onEntityTransformUpdated.stream;
|
||||
|
||||
GizmoInputHandler({required this.wrapped, required this.viewer}) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
final _initialized = Completer<bool>();
|
||||
|
||||
Future initialize() async {
|
||||
if (_initialized.isCompleted) {
|
||||
throw Exception("Already initialized");
|
||||
@@ -137,7 +156,7 @@ class GizmoInputHandler extends InputHandler {
|
||||
|
||||
@override
|
||||
Future dispose() async {
|
||||
await viewer.removeEntity(translationGizmo._asset);
|
||||
await viewer.removeEntity(translationGizmo._gizmo);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -166,9 +185,21 @@ class GizmoInputHandler extends InputHandler {
|
||||
if (!_initialized.isCompleted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isMiddle) {
|
||||
return;
|
||||
}
|
||||
|
||||
await viewer.pick(localPosition.x.toInt(), localPosition.y.toInt(),
|
||||
(result) {
|
||||
translationGizmo.attach(result.entity);
|
||||
(result) async {
|
||||
if (translationGizmo._gizmo.isNonPickable(result.entity) ||
|
||||
result.entity == FILAMENT_ENTITY_NULL) {
|
||||
await translationGizmo.detach();
|
||||
return;
|
||||
}
|
||||
if (!translationGizmo._gizmo.isGizmoEntity(result.entity)) {
|
||||
translationGizmo.attach(result.entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -235,4 +266,25 @@ class GizmoInputHandler extends InputHandler {
|
||||
void setActionForType(InputType gestureType, InputAction gestureAction) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
Future detach(ThermionAsset asset) async {
|
||||
|
||||
if (translationGizmo._attachedTo == asset.entity) {
|
||||
await translationGizmo.detach();
|
||||
return;
|
||||
}
|
||||
final childEntities = await asset.getChildEntities();
|
||||
for(final childEntity in childEntities) {
|
||||
if(translationGizmo._attachedTo == childEntity) {
|
||||
await translationGizmo.detach();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// @override
|
||||
// Future setCamera(Camera camera) async {
|
||||
// await wrapped.setCamera(camera);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
enum InputType {
|
||||
@@ -37,8 +38,17 @@ abstract class InputHandler {
|
||||
Future<void> onPointerMove(
|
||||
Vector2 localPosition, Vector2 delta, bool isMiddle);
|
||||
Future<void> onPointerUp(bool isMiddle);
|
||||
Future<void> onScaleStart(Vector2 focalPoint, int pointerCount, Duration? sourceTimestamp);
|
||||
Future<void> onScaleUpdate(Vector2 focalPoint, Vector2 focalPointDelta, double horizontalScale, double verticalScale, double scale, int pointerCount, double rotation, Duration? sourceTimestamp);
|
||||
Future<void> onScaleStart(
|
||||
Vector2 focalPoint, int pointerCount, Duration? sourceTimestamp);
|
||||
Future<void> onScaleUpdate(
|
||||
Vector2 focalPoint,
|
||||
Vector2 focalPointDelta,
|
||||
double horizontalScale,
|
||||
double verticalScale,
|
||||
double scale,
|
||||
int pointerCount,
|
||||
double rotation,
|
||||
Duration? sourceTimestamp);
|
||||
Future<void> onScaleEnd(int pointerCount, double velocity);
|
||||
Future<bool> get initialized;
|
||||
Future dispose();
|
||||
@@ -48,4 +58,6 @@ abstract class InputHandler {
|
||||
|
||||
void keyDown(PhysicalKey key);
|
||||
void keyUp(PhysicalKey key);
|
||||
|
||||
// Future setCamera(Camera camera);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'ffi_view.dart';
|
||||
|
||||
class FFIGizmo extends FFIAsset implements GizmoAsset {
|
||||
final Set<ThermionEntity> nonPickableEntities;
|
||||
final Set<ThermionEntity> gizmoEntities;
|
||||
late NativeCallable<GizmoPickCallbackFunction> _nativeCallback;
|
||||
|
||||
void Function(GizmoPickResultType axis, Vector3 coords)? _callback;
|
||||
@@ -19,14 +20,18 @@ class FFIGizmo extends FFIAsset implements GizmoAsset {
|
||||
_callback?.call(GizmoPickResultType.values[resultType], Vector3(x, y, z));
|
||||
}
|
||||
|
||||
bool isNonPickable(ThermionEntity entity) =>
|
||||
nonPickableEntities.contains(entity);
|
||||
bool isGizmoEntity(ThermionEntity entity) => gizmoEntities.contains(entity);
|
||||
|
||||
FFIGizmo(
|
||||
this._view,
|
||||
super.pointer,
|
||||
super.sceneManager,
|
||||
super.renderableManager,
|
||||
super.unlitMaterialProvider,
|
||||
this.nonPickableEntities
|
||||
) {
|
||||
this._view,
|
||||
super.pointer,
|
||||
super.sceneManager,
|
||||
super.renderableManager,
|
||||
super.unlitMaterialProvider,
|
||||
this.nonPickableEntities,
|
||||
this.gizmoEntities) {
|
||||
_nativeCallback =
|
||||
NativeCallable<GizmoPickCallbackFunction>.listener(_onPickResult);
|
||||
}
|
||||
|
||||
@@ -81,5 +81,6 @@ abstract class GizmoAsset extends ThermionAsset {
|
||||
{Future Function(GizmoPickResultType axis, Vector3 coords)? handler});
|
||||
Future highlight(Axis axis);
|
||||
Future unhighlight();
|
||||
Set<ThermionEntity> get nonPickableEntities;
|
||||
bool isNonPickable(ThermionEntity entity);
|
||||
bool isGizmoEntity(ThermionEntity entity);
|
||||
}
|
||||
|
||||
@@ -28,11 +28,12 @@ namespace thermion
|
||||
|
||||
auto parent = entityManager.create();
|
||||
|
||||
auto *parentMaterialInstance = _material->createInstance();
|
||||
parentMaterialInstance->setParameter("baseColorFactor", math::float4{0.0f, 1.0f, 1.0f, 1.0f});
|
||||
parentMaterialInstance->setParameter("scale", 4.0f);
|
||||
// auto *parentMaterialInstance = _material->createInstance();
|
||||
// parentMaterialInstance->setParameter("baseColorFactor", math::float4{1.0f, 1.0f, 1.0f, 0.0f});
|
||||
// parentMaterialInstance->setParameter("scale", 4.0f);
|
||||
// parentMaterialInstance->setDoubleSided(false);
|
||||
|
||||
_materialInstances.push_back(parentMaterialInstance);
|
||||
// _materialInstances.push_back(parentMaterialInstance);
|
||||
|
||||
// Create center cube vertices
|
||||
float centerCubeSize = 0.1f;
|
||||
@@ -73,11 +74,11 @@ namespace thermion
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-centerCubeSize, -centerCubeSize, -centerCubeSize},
|
||||
{centerCubeSize, centerCubeSize, centerCubeSize}})
|
||||
.material(0, parentMaterialInstance)
|
||||
// .material(0, parentMaterialInstance)
|
||||
.layerMask(0xFF, 1u << SceneManager::LAYERS::OVERLAY)
|
||||
.priority(7)
|
||||
.priority(0)
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, centerCubeVb, centerCubeIb, 0, 36)
|
||||
.culling(false)
|
||||
.culling(true)
|
||||
.build(*_engine, parent);
|
||||
|
||||
auto parentTransformInstance = transformManager.getInstance(parent);
|
||||
@@ -265,6 +266,7 @@ namespace thermion
|
||||
_materialInstances.push_back(materialInstance);
|
||||
materialInstance->setParameter("baseColorFactor", math::float4{0.0f, 0.0f, 0.0f, 0.0f});
|
||||
materialInstance->setParameter("scale", 4.0f);
|
||||
materialInstance->setDepthFunc(MaterialInstance::DepthFunc::A);
|
||||
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-volumeWidth / 2, -volumeDepth / 2, 0}, {volumeWidth / 2, volumeDepth / 2, volumeLength}})
|
||||
|
||||
Reference in New Issue
Block a user