1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-05-23 17:13:38 +02:00
MLEM/MLEM.Ui/UiSystem.cs

160 lines
5.8 KiB
C#
Raw Normal View History

2019-08-09 18:26:28 +02:00
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Extensions;
2019-08-09 19:28:48 +02:00
using MLEM.Font;
using MLEM.Input;
2019-08-09 18:26:28 +02:00
using MLEM.Ui.Elements;
2019-08-10 21:37:10 +02:00
using MLEM.Ui.Style;
2019-08-09 18:26:28 +02:00
namespace MLEM.Ui {
public class UiSystem {
2019-08-10 18:41:56 +02:00
public readonly GraphicsDevice GraphicsDevice;
2019-08-09 18:26:28 +02:00
private readonly List<RootElement> rootElements = new List<RootElement>();
2019-08-10 18:41:56 +02:00
public readonly InputHandler InputHandler;
private readonly bool isInputOurs;
2019-08-09 18:26:28 +02:00
2019-08-09 23:43:50 +02:00
private float globalScale;
public float GlobalScale {
get => this.globalScale;
set {
this.globalScale = value;
foreach (var root in this.rootElements)
root.Element.ForceUpdateArea();
}
}
2019-08-09 18:26:28 +02:00
public Rectangle ScaledViewport {
get {
2019-08-10 18:41:56 +02:00
var bounds = this.GraphicsDevice.Viewport.Bounds;
2019-08-09 23:43:50 +02:00
return new Rectangle(bounds.X, bounds.Y, (bounds.Width / this.globalScale).Floor(), (bounds.Height / this.globalScale).Floor());
2019-08-09 18:26:28 +02:00
}
}
2019-08-10 18:41:56 +02:00
public Vector2 MousePos => this.InputHandler.MousePosition.ToVector2() / this.globalScale;
public Element MousedElement { get; private set; }
2019-08-10 18:41:56 +02:00
public Element SelectedElement { get; private set; }
2019-08-10 21:37:10 +02:00
private UiStyle style;
public UiStyle Style {
get => this.style;
set {
this.style = value;
foreach (var root in this.rootElements) {
root.Element.PropagateUiSystem(this);
root.Element.SetDirty();
}
}
}
2019-08-10 13:42:18 +02:00
public float DrawAlpha = 1;
2019-08-09 23:43:50 +02:00
public BlendState BlendState;
public SamplerState SamplerState = SamplerState.PointClamp;
2019-08-09 18:26:28 +02:00
2019-08-10 21:37:10 +02:00
public UiSystem(GameWindow window, GraphicsDevice device, UiStyle style, InputHandler inputHandler = null) {
2019-08-10 18:41:56 +02:00
this.GraphicsDevice = device;
this.InputHandler = inputHandler ?? new InputHandler();
this.isInputOurs = inputHandler == null;
2019-08-10 21:37:10 +02:00
this.style = style;
2019-08-09 19:28:48 +02:00
2019-08-09 18:26:28 +02:00
window.ClientSizeChanged += (sender, args) => {
foreach (var root in this.rootElements)
root.Element.ForceUpdateArea();
};
2019-08-10 18:41:56 +02:00
window.TextInput += (sender, args) => {
foreach (var root in this.rootElements)
root.Element.PropagateInput(args.Key, args.Character);
};
2019-08-09 18:26:28 +02:00
}
public void Update(GameTime time) {
if (this.isInputOurs)
2019-08-10 18:41:56 +02:00
this.InputHandler.Update();
var mousedNow = this.GetMousedElement();
if (mousedNow != this.MousedElement) {
if (this.MousedElement != null)
this.MousedElement.OnMouseExit?.Invoke(this.MousedElement, this.MousePos);
if (mousedNow != null)
mousedNow.OnMouseEnter?.Invoke(mousedNow, this.MousePos);
this.MousedElement = mousedNow;
}
2019-08-10 18:41:56 +02:00
if (this.SelectedElement != mousedNow && this.InputHandler.IsMouseButtonPressed(MouseButton.Left)) {
if (this.SelectedElement != null)
this.SelectedElement.OnDeselected?.Invoke(this.SelectedElement);
if (mousedNow != null)
mousedNow.OnSelected?.Invoke(mousedNow);
this.SelectedElement = mousedNow;
}
if (mousedNow?.OnClicked != null) {
foreach (var button in InputHandler.MouseButtons) {
2019-08-10 18:41:56 +02:00
if (this.InputHandler.IsMouseButtonPressed(button))
mousedNow.OnClicked(mousedNow, this.MousePos, button);
}
}
2019-08-09 18:26:28 +02:00
foreach (var root in this.rootElements)
root.Element.Update(time);
}
2019-08-09 23:43:50 +02:00
public void Draw(GameTime time, SpriteBatch batch) {
batch.Begin(SpriteSortMode.Deferred, this.BlendState, this.SamplerState, transformMatrix: Matrix.CreateScale(this.globalScale));
2019-08-09 19:39:51 +02:00
foreach (var root in this.rootElements) {
if (!root.Element.IsHidden)
2019-08-10 13:42:18 +02:00
root.Element.Draw(time, batch, this.DrawAlpha * root.Element.DrawAlpha);
2019-08-09 19:39:51 +02:00
}
2019-08-09 18:26:28 +02:00
batch.End();
2019-08-09 19:28:48 +02:00
2019-08-09 19:39:51 +02:00
foreach (var root in this.rootElements) {
if (!root.Element.IsHidden)
2019-08-10 13:42:18 +02:00
root.Element.DrawUnbound(time, batch, this.DrawAlpha * root.Element.DrawAlpha, this.BlendState, this.SamplerState);
2019-08-09 19:39:51 +02:00
}
2019-08-09 18:26:28 +02:00
}
public void Add(string name, Element root) {
if (this.IndexOf(name) >= 0)
throw new ArgumentException($"There is already a root element with name {name}");
this.rootElements.Add(new RootElement(name, root));
2019-08-10 21:37:10 +02:00
root.PropagateUiSystem(this);
2019-08-09 18:26:28 +02:00
}
public void Remove(string name) {
var index = this.IndexOf(name);
if (index < 0)
return;
this.rootElements.RemoveAt(index);
}
public Element Get(string name) {
var index = this.IndexOf(name);
return index < 0 ? null : this.rootElements[index].Element;
}
private int IndexOf(string name) {
return this.rootElements.FindIndex(element => element.Name == name);
}
private Element GetMousedElement() {
foreach (var root in this.rootElements) {
var moused = root.Element.GetMousedElement(this.MousePos);
if (moused != null)
return moused;
}
return null;
}
2019-08-09 18:26:28 +02:00
}
public struct RootElement {
public readonly string Name;
public readonly Element Element;
public RootElement(string name, Element element) {
this.Name = name;
this.Element = element;
}
}
}