mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-15 02:29:10 +01:00
138 lines
No EOL
5.9 KiB
C#
138 lines
No EOL
5.9 KiB
C#
using System;
|
|
using System.Linq;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using Microsoft.Xna.Framework.Input.Touch;
|
|
using MLEM.Extensions;
|
|
using MLEM.Input;
|
|
using MLEM.Ui.Elements;
|
|
|
|
namespace MLEM.Ui {
|
|
public class UiControls {
|
|
|
|
public readonly InputHandler Input;
|
|
private readonly bool isInputOurs;
|
|
private readonly UiSystem system;
|
|
|
|
public Element MousedElement { get; private set; }
|
|
public Element SelectedElement { get; private set; }
|
|
public bool SelectedLastElementWithMouse { get; private set; }
|
|
|
|
public UiControls(UiSystem system, InputHandler inputHandler = null) {
|
|
this.system = system;
|
|
this.Input = inputHandler ?? new InputHandler();
|
|
this.isInputOurs = inputHandler == null;
|
|
|
|
// enable all required gestures
|
|
InputHandler.EnableGestures(GestureType.Tap, GestureType.Hold);
|
|
}
|
|
|
|
public void Update() {
|
|
if (this.isInputOurs)
|
|
this.Input.Update();
|
|
|
|
// MOUSE INPUT
|
|
var mousedNow = this.GetElementUnderPos(this.Input.MousePosition);
|
|
if (mousedNow != this.MousedElement) {
|
|
if (this.MousedElement != null)
|
|
this.MousedElement.OnMouseExit?.Invoke(this.MousedElement);
|
|
if (mousedNow != null)
|
|
mousedNow.OnMouseEnter?.Invoke(mousedNow);
|
|
this.MousedElement = mousedNow;
|
|
this.system.ApplyToAll(e => e.OnMousedElementChanged?.Invoke(e, mousedNow));
|
|
}
|
|
|
|
if (this.Input.IsMouseButtonPressed(MouseButton.Left)) {
|
|
var selectedNow = mousedNow != null && mousedNow.CanBeSelected ? mousedNow : null;
|
|
this.SelectElement(selectedNow, true);
|
|
if (mousedNow != null)
|
|
mousedNow.OnPressed?.Invoke(mousedNow);
|
|
} else if (this.Input.IsMouseButtonPressed(MouseButton.Right)) {
|
|
if (mousedNow != null)
|
|
mousedNow.OnSecondaryPressed?.Invoke(mousedNow);
|
|
}
|
|
|
|
// KEYBOARD INPUT
|
|
else if (this.Input.IsKeyPressed(Keys.Enter) || this.Input.IsKeyPressed(Keys.Space)) {
|
|
if (this.SelectedElement?.Root != null) {
|
|
if (this.Input.IsModifierKeyDown(ModifierKey.Shift)) {
|
|
// secondary action on element using space or enter
|
|
this.SelectedElement.OnSecondaryPressed?.Invoke(this.SelectedElement);
|
|
} else {
|
|
// first action on element using space or enter
|
|
this.SelectedElement.OnPressed?.Invoke(this.SelectedElement);
|
|
}
|
|
}
|
|
} else if (this.Input.IsKeyPressed(Keys.Tab)) {
|
|
// tab or shift-tab to next or previous element
|
|
this.SelectElement(this.GetNextElement(this.Input.IsModifierKeyDown(ModifierKey.Shift)), false);
|
|
}
|
|
|
|
// TOUCH INPUT
|
|
else if (this.Input.GetGesture(GestureType.Tap, out var tap)) {
|
|
var tapped = this.GetElementUnderPos(tap.Position.ToPoint());
|
|
this.SelectElement(tapped, true);
|
|
if (tapped != null)
|
|
tapped.OnPressed?.Invoke(tapped);
|
|
} else if (this.Input.GetGesture(GestureType.Hold, out var hold)) {
|
|
var held = this.GetElementUnderPos(hold.Position.ToPoint());
|
|
this.SelectElement(held, true);
|
|
if (held != null)
|
|
held.OnSecondaryPressed?.Invoke(held);
|
|
}
|
|
}
|
|
|
|
public void SelectElement(Element element, bool mouse) {
|
|
if (this.SelectedElement == element)
|
|
return;
|
|
|
|
if (this.SelectedElement != null)
|
|
this.SelectedElement.OnDeselected?.Invoke(this.SelectedElement);
|
|
if (element != null)
|
|
element.OnSelected?.Invoke(element);
|
|
this.SelectedElement = element;
|
|
this.SelectedLastElementWithMouse = mouse;
|
|
this.system.ApplyToAll(e => e.OnSelectedElementChanged?.Invoke(e, element));
|
|
}
|
|
|
|
public Element GetElementUnderPos(Point position, bool transform = true) {
|
|
foreach (var root in this.system.GetRootElements()) {
|
|
var pos = transform ? position.Transform(root.InvTransform) : position;
|
|
var moused = root.Element.GetElementUnderPos(pos);
|
|
if (moused != null)
|
|
return moused;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private Element GetNextElement(bool backward) {
|
|
var currRoot = this.system.GetRootElements().FirstOrDefault(root => root.CanSelectContent);
|
|
if (currRoot == null)
|
|
return null;
|
|
var children = currRoot.Element.GetChildren(regardChildrensChildren: true).Append(currRoot.Element);
|
|
if (this.SelectedElement?.Root != currRoot) {
|
|
return backward ? children.LastOrDefault(c => c.CanBeSelected) : children.FirstOrDefault(c => c.CanBeSelected);
|
|
} else {
|
|
var foundCurr = false;
|
|
Element lastFound = null;
|
|
foreach (var child in children) {
|
|
if (!child.CanBeSelected)
|
|
continue;
|
|
if (child == this.SelectedElement) {
|
|
// when going backwards, return the last element found before the current one
|
|
if (backward)
|
|
return lastFound;
|
|
foundCurr = true;
|
|
} else {
|
|
// when going forwards, return the element after the current one
|
|
if (!backward && foundCurr)
|
|
return child;
|
|
}
|
|
lastFound = child;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
}
|
|
} |