diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c40423..9389be8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,6 +40,7 @@ Fixes
- Fixed VerticalSpace height parameter being an integer
- Fixed text not being pasted into a text field at all if it contains characters that don't match the input rule
- Fixed panels that don't auto-hide their scroll bars ignoring their width for child padding
+- Fixed some inconsistencies with element transformations and mouse interaction
Removals
- *Removed ScrollBar ScrollerOffset*
diff --git a/MLEM.Ui/Elements/Element.cs b/MLEM.Ui/Elements/Element.cs
index 3115916..9e439bd 100644
--- a/MLEM.Ui/Elements/Element.cs
+++ b/MLEM.Ui/Elements/Element.cs
@@ -956,8 +956,7 @@ namespace MLEM.Ui.Elements {
public virtual Element GetElementUnderPos(Vector2 position) {
if (this.IsHidden)
return null;
- if (this.Transform != Matrix.Identity)
- position = Vector2.Transform(position, Matrix.Invert(this.Transform));
+ position = this.TransformInverse(position);
var relevant = this.GetRelevantChildren();
for (var i = relevant.Count - 1; i >= 0; i--) {
var element = relevant[i].GetElementUnderPos(position);
@@ -1019,6 +1018,28 @@ namespace MLEM.Ui.Elements {
this.SecondActionSound.SetFromStyle(style.ActionSound);
}
+ ///
+ /// Transforms the given by the inverse of this element's matrix.
+ ///
+ /// The position to transform
+ /// The transformed position
+ protected Vector2 TransformInverse(Vector2 position) {
+ return this.Transform != Matrix.Identity ? Vector2.Transform(position, Matrix.Invert(this.Transform)) : position;
+ }
+
+ ///
+ /// Transforms the given by this element's 's , the inverses of all of the matrices of this element's parent tree (), and the inverse of this element's matrix.
+ /// Note that, when using , this operation is done recursively, which is more efficient.
+ ///
+ /// The position to transform
+ /// The transformed position
+ protected Vector2 TransformInverseAll(Vector2 position) {
+ position = Vector2.Transform(position, this.Root.InvTransform);
+ foreach (var parent in this.GetParentTree().Reverse())
+ position = parent.TransformInverse(position);
+ return this.TransformInverse(position);
+ }
+
///
/// A delegate used for the event.
///
diff --git a/MLEM.Ui/Elements/Panel.cs b/MLEM.Ui/Elements/Panel.cs
index 173a656..089cf60 100644
--- a/MLEM.Ui/Elements/Panel.cs
+++ b/MLEM.Ui/Elements/Panel.cs
@@ -189,8 +189,9 @@ namespace MLEM.Ui.Elements {
///
public override Element GetElementUnderPos(Vector2 position) {
// if overflow is handled, don't propagate mouse checks to hidden children
- if (this.scrollOverflow && !this.GetRenderTargetArea().Contains(position))
- return !this.IsHidden && this.CanBeMoused && this.DisplayArea.Contains(position) ? this : null;
+ var transformed = this.TransformInverse(position);
+ if (this.scrollOverflow && !this.GetRenderTargetArea().Contains(transformed))
+ return !this.IsHidden && this.CanBeMoused && this.DisplayArea.Contains(transformed) ? this : null;
return base.GetElementUnderPos(position);
}
diff --git a/MLEM.Ui/Elements/Paragraph.cs b/MLEM.Ui/Elements/Paragraph.cs
index adedcd0..a781446 100644
--- a/MLEM.Ui/Elements/Paragraph.cs
+++ b/MLEM.Ui/Elements/Paragraph.cs
@@ -251,7 +251,7 @@ namespace MLEM.Ui.Elements {
return ret;
// check if any of our token's parts are hovered
foreach (var rect in this.Token.GetArea(this.Parent.DisplayArea.Location, this.Scale * this.textScale)) {
- if (rect.Contains(position))
+ if (rect.Contains(this.TransformInverse(position)))
return this;
}
return null;
diff --git a/MLEM.Ui/Elements/ScrollBar.cs b/MLEM.Ui/Elements/ScrollBar.cs
index f97bec9..63d90d2 100644
--- a/MLEM.Ui/Elements/ScrollBar.cs
+++ b/MLEM.Ui/Elements/ScrollBar.cs
@@ -137,15 +137,14 @@ namespace MLEM.Ui.Elements {
// MOUSE INPUT
var moused = this.Controls.MousedElement;
- var mousedPos = Vector2.Transform(this.Input.MousePosition.ToVector2(), this.Root.InvTransform);
if (moused == this && this.Controls.Input.IsMouseButtonPressed(MouseButton.Left)) {
this.isMouseHeld = true;
- this.scrollStartOffset = mousedPos - this.ScrollerPosition;
+ this.scrollStartOffset = this.TransformInverseAll(this.Input.MousePosition.ToVector2()) - this.ScrollerPosition;
} else if (this.isMouseHeld && !this.Controls.Input.IsMouseButtonDown(MouseButton.Left)) {
this.isMouseHeld = false;
}
if (this.isMouseHeld)
- this.ScrollToPos(mousedPos);
+ this.ScrollToPos(this.TransformInverseAll(this.Input.MousePosition.ToVector2()));
if (!this.Horizontal && moused != null && (moused == this.Parent || moused.GetParentTree().Contains(this.Parent))) {
var scroll = this.Input.LastScrollWheel - this.Input.ScrollWheel;
if (scroll != 0)
@@ -157,7 +156,7 @@ namespace MLEM.Ui.Elements {
// are we dragging on top of the panel?
if (this.Input.GetGesture(GestureType.VerticalDrag, out var drag)) {
// if the element under the drag's start position is on top of the panel, start dragging
- var touched = this.Parent.GetElementUnderPos(Vector2.Transform(drag.Position, this.Root.InvTransform));
+ var touched = this.Parent.GetElementUnderPos(this.TransformInverseAll(drag.Position));
if (touched != null && touched != this)
this.isDragging = true;
@@ -173,7 +172,7 @@ namespace MLEM.Ui.Elements {
this.isTouchHeld = false;
} else {
foreach (var loc in this.Input.TouchState) {
- var pos = Vector2.Transform(loc.Position, this.Root.InvTransform);
+ var pos = this.TransformInverseAll(loc.Position);
// if we just started touching and are on top of the scroller, then we should start scrolling
if (this.DisplayArea.Contains(pos) && !loc.TryGetPreviousLocation(out _)) {
this.isTouchHeld = true;
diff --git a/MLEM.Ui/UiControls.cs b/MLEM.Ui/UiControls.cs
index f8f5ebb..e376503 100644
--- a/MLEM.Ui/UiControls.cs
+++ b/MLEM.Ui/UiControls.cs
@@ -237,11 +237,10 @@ namespace MLEM.Ui {
/// Throughout the ui system, this is used for mouse input querying.
///
/// The position to query
- /// If this value is true, the will be applied.
/// The element under the position, or null if there isn't one
- public virtual Element GetElementUnderPos(Vector2 position, bool transform = true) {
+ public virtual Element GetElementUnderPos(Vector2 position) {
foreach (var root in this.System.GetRootElements()) {
- var pos = transform ? Vector2.Transform(position, root.InvTransform) : position;
+ var pos = Vector2.Transform(position, root.InvTransform);
var moused = root.Element.GetElementUnderPos(pos);
if (moused != null)
return moused;