1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-25 22:18:34 +01:00

Fixed some inconsistencies with element transformations and mouse interaction

This commit is contained in:
Ell 2021-11-22 15:13:08 +01:00
parent 5c8ef3d254
commit 5b99f29490
6 changed files with 34 additions and 13 deletions

View file

@ -40,6 +40,7 @@ Fixes
- Fixed VerticalSpace height parameter being an integer - 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 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 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 Removals
- *Removed ScrollBar ScrollerOffset* - *Removed ScrollBar ScrollerOffset*

View file

@ -956,8 +956,7 @@ namespace MLEM.Ui.Elements {
public virtual Element GetElementUnderPos(Vector2 position) { public virtual Element GetElementUnderPos(Vector2 position) {
if (this.IsHidden) if (this.IsHidden)
return null; return null;
if (this.Transform != Matrix.Identity) position = this.TransformInverse(position);
position = Vector2.Transform(position, Matrix.Invert(this.Transform));
var relevant = this.GetRelevantChildren(); var relevant = this.GetRelevantChildren();
for (var i = relevant.Count - 1; i >= 0; i--) { for (var i = relevant.Count - 1; i >= 0; i--) {
var element = relevant[i].GetElementUnderPos(position); var element = relevant[i].GetElementUnderPos(position);
@ -1019,6 +1018,28 @@ namespace MLEM.Ui.Elements {
this.SecondActionSound.SetFromStyle(style.ActionSound); this.SecondActionSound.SetFromStyle(style.ActionSound);
} }
/// <summary>
/// Transforms the given <paramref name="position"/> by the inverse of this element's <see cref="Transform"/> matrix.
/// </summary>
/// <param name="position">The position to transform</param>
/// <returns>The transformed position</returns>
protected Vector2 TransformInverse(Vector2 position) {
return this.Transform != Matrix.Identity ? Vector2.Transform(position, Matrix.Invert(this.Transform)) : position;
}
/// <summary>
/// Transforms the given <paramref name="position"/> by this element's <see cref="Root"/>'s <see cref="RootElement.InvTransform"/>, the inverses of all of the <see cref="Transform"/> matrices of this element's parent tree (<see cref="GetParentTree"/>), and the inverse of this element's <see cref="Transform"/> matrix.
/// Note that, when using <see cref="UiControls.GetElementUnderPos"/>, this operation is done recursively, which is more efficient.
/// </summary>
/// <param name="position">The position to transform</param>
/// <returns>The transformed position</returns>
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);
}
/// <summary> /// <summary>
/// A delegate used for the <see cref="Element.OnTextInput"/> event. /// A delegate used for the <see cref="Element.OnTextInput"/> event.
/// </summary> /// </summary>

View file

@ -189,8 +189,9 @@ namespace MLEM.Ui.Elements {
/// <inheritdoc /> /// <inheritdoc />
public override Element GetElementUnderPos(Vector2 position) { public override Element GetElementUnderPos(Vector2 position) {
// if overflow is handled, don't propagate mouse checks to hidden children // if overflow is handled, don't propagate mouse checks to hidden children
if (this.scrollOverflow && !this.GetRenderTargetArea().Contains(position)) var transformed = this.TransformInverse(position);
return !this.IsHidden && this.CanBeMoused && this.DisplayArea.Contains(position) ? this : null; if (this.scrollOverflow && !this.GetRenderTargetArea().Contains(transformed))
return !this.IsHidden && this.CanBeMoused && this.DisplayArea.Contains(transformed) ? this : null;
return base.GetElementUnderPos(position); return base.GetElementUnderPos(position);
} }

View file

@ -251,7 +251,7 @@ namespace MLEM.Ui.Elements {
return ret; return ret;
// check if any of our token's parts are hovered // 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)) { 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 this;
} }
return null; return null;

View file

@ -137,15 +137,14 @@ namespace MLEM.Ui.Elements {
// MOUSE INPUT // MOUSE INPUT
var moused = this.Controls.MousedElement; 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)) { if (moused == this && this.Controls.Input.IsMouseButtonPressed(MouseButton.Left)) {
this.isMouseHeld = true; 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)) { } else if (this.isMouseHeld && !this.Controls.Input.IsMouseButtonDown(MouseButton.Left)) {
this.isMouseHeld = false; this.isMouseHeld = false;
} }
if (this.isMouseHeld) 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))) { if (!this.Horizontal && moused != null && (moused == this.Parent || moused.GetParentTree().Contains(this.Parent))) {
var scroll = this.Input.LastScrollWheel - this.Input.ScrollWheel; var scroll = this.Input.LastScrollWheel - this.Input.ScrollWheel;
if (scroll != 0) if (scroll != 0)
@ -157,7 +156,7 @@ namespace MLEM.Ui.Elements {
// are we dragging on top of the panel? // are we dragging on top of the panel?
if (this.Input.GetGesture(GestureType.VerticalDrag, out var drag)) { 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 // 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) if (touched != null && touched != this)
this.isDragging = true; this.isDragging = true;
@ -173,7 +172,7 @@ namespace MLEM.Ui.Elements {
this.isTouchHeld = false; this.isTouchHeld = false;
} else { } else {
foreach (var loc in this.Input.TouchState) { 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 we just started touching and are on top of the scroller, then we should start scrolling
if (this.DisplayArea.Contains(pos) && !loc.TryGetPreviousLocation(out _)) { if (this.DisplayArea.Contains(pos) && !loc.TryGetPreviousLocation(out _)) {
this.isTouchHeld = true; this.isTouchHeld = true;

View file

@ -237,11 +237,10 @@ namespace MLEM.Ui {
/// Throughout the ui system, this is used for mouse input querying. /// Throughout the ui system, this is used for mouse input querying.
/// </summary> /// </summary>
/// <param name="position">The position to query</param> /// <param name="position">The position to query</param>
/// <param name="transform">If this value is true, the <see cref="RootElement.Transform"/> will be applied.</param>
/// <returns>The element under the position, or null if there isn't one</returns> /// <returns>The element under the position, or null if there isn't one</returns>
public virtual Element GetElementUnderPos(Vector2 position, bool transform = true) { public virtual Element GetElementUnderPos(Vector2 position) {
foreach (var root in this.System.GetRootElements()) { 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); var moused = root.Element.GetElementUnderPos(pos);
if (moused != null) if (moused != null)
return moused; return moused;