1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-12-24 01:09:23 +01:00

better styling

This commit is contained in:
Ellpeck 2019-08-10 21:37:10 +02:00
parent 15081a8fe0
commit 0c8af5b9bf
13 changed files with 210 additions and 46 deletions

View file

@ -4,6 +4,7 @@ using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using MLEM.Input;
using MLEM.Ui;
using MLEM.Ui.Style;
using MonoGame.Extended;
namespace MLEM.Startup {
@ -40,7 +41,7 @@ namespace MLEM.Startup {
protected override void LoadContent() {
this.SpriteBatch = new SpriteBatch(this.GraphicsDevice);
this.InputHandler = new InputHandler();
this.UiSystem = new UiSystem(this.Window, this.GraphicsDevice, this.InputHandler);
this.UiSystem = new UiSystem(this.Window, this.GraphicsDevice, new UntexturedStyle(this.SpriteBatch), this.InputHandler);
}
protected override void Initialize() {

View file

@ -3,11 +3,12 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Extensions;
using MLEM.Font;
using MLEM.Ui.Style;
namespace MLEM.Ui.Elements {
public class AutoScaledText : Element {
private readonly IGenericFont font;
private IGenericFont font;
private float scale;
private string text;
@ -22,7 +23,7 @@ namespace MLEM.Ui.Elements {
public AutoScaledText(Anchor anchor, Vector2 size, string text, IGenericFont font = null) : base(anchor, size) {
this.Text = text;
this.font = font ?? Paragraph.DefaultFont;
this.font = font;
this.IgnoresMouse = true;
}
@ -43,5 +44,10 @@ namespace MLEM.Ui.Elements {
base.Draw(time, batch, alpha);
}
protected override void InitStyle(UiStyle style) {
base.InitStyle(style);
this.font = style.Font;
}
}
}

View file

@ -2,17 +2,14 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Extensions;
using MLEM.Textures;
using MLEM.Ui.Style;
namespace MLEM.Ui.Elements {
public class Button : Element {
public static NinePatch DefaultTexture;
public static NinePatch DefaultHoveredTexture;
public static Color DefaultHoveredColor = Color.LightGray;
public NinePatch Texture = DefaultTexture;
public NinePatch HoveredTexture = DefaultHoveredTexture;
public Color HoveredColor = DefaultHoveredColor;
public NinePatch Texture;
public NinePatch HoveredTexture;
public Color HoveredColor;
public AutoScaledText Text;
public Button(Anchor anchor, Vector2 size, string text = null) : base(anchor, size) {
@ -36,5 +33,12 @@ namespace MLEM.Ui.Elements {
base.Draw(time, batch, alpha);
}
protected override void InitStyle(UiStyle style) {
base.InitStyle(style);
this.Texture = style.ButtonTexture;
this.HoveredTexture = style.ButtonHoveredTexture;
this.HoveredColor = style.ButtonHoveredColor;
}
}
}

View file

@ -5,6 +5,7 @@ using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using MLEM.Extensions;
using MLEM.Input;
using MLEM.Ui.Style;
namespace MLEM.Ui.Elements {
public abstract class Element {
@ -68,7 +69,15 @@ namespace MLEM.Ui.Elements {
public MouseCallback OnMouseExit;
public TextInputCallback OnTextInput;
public UiSystem System { get; private set; }
private UiSystem system;
public UiSystem System {
get => this.system;
set {
this.system = value;
if (this.system != null && !this.HasCustomStyle)
this.InitStyle(this.system.Style);
}
}
protected InputHandler Input => this.System.InputHandler;
public Element Parent { get; private set; }
public bool IsMouseOver { get; private set; }
@ -85,6 +94,7 @@ namespace MLEM.Ui.Elements {
}
public bool IgnoresMouse;
public float DrawAlpha = 1;
public bool HasCustomStyle;
private Rectangle area;
public Rectangle Area {
@ -122,7 +132,7 @@ namespace MLEM.Ui.Elements {
index = this.children.Count;
this.children.Insert(index, element);
element.Parent = this;
element.System = this.System;
element.PropagateUiSystem(this.System);
this.SetDirty();
return element;
}
@ -130,7 +140,7 @@ namespace MLEM.Ui.Elements {
public void RemoveChild(Element element) {
this.children.Remove(element);
element.Parent = null;
element.System = null;
element.PropagateUiSystem(this.System);
this.SetDirty();
}
@ -307,6 +317,9 @@ namespace MLEM.Ui.Elements {
return this;
}
protected virtual void InitStyle(UiStyle style) {
}
public delegate void MouseClickCallback(Element element, Vector2 mousePos, MouseButton button);
public delegate void MouseCallback(Element element, Vector2 mousePos);
@ -315,10 +328,10 @@ namespace MLEM.Ui.Elements {
public delegate void GenericCallback(Element element);
internal void SetUiSystem(UiSystem system) {
internal void PropagateUiSystem(UiSystem system) {
this.System = system;
foreach (var child in this.children)
child.SetUiSystem(system);
child.PropagateUiSystem(system);
}
internal void PropagateInput(Keys key, char character) {

View file

@ -1,24 +1,28 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Textures;
using MLEM.Ui.Style;
namespace MLEM.Ui.Elements {
public class Panel : Element {
public static NinePatch DefaultTexture;
private readonly NinePatch texture;
public NinePatch Texture;
public Panel(Anchor anchor, Vector2 size, Point positionOffset, NinePatch texture = null) : base(anchor, size) {
this.texture = texture ?? DefaultTexture;
this.Texture = texture;
this.PositionOffset = positionOffset;
this.ChildPadding = new Point(5);
}
public override void Draw(GameTime time, SpriteBatch batch, float alpha) {
batch.Draw(this.texture, this.DisplayArea, Color.White * alpha);
batch.Draw(this.Texture, this.DisplayArea, Color.White * alpha);
base.Draw(time, batch, alpha);
}
protected override void InitStyle(UiStyle style) {
base.InitStyle(style);
this.Texture = style.PanelTexture;
}
}
}

View file

@ -5,20 +5,18 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Extensions;
using MLEM.Font;
using MLEM.Ui.Style;
namespace MLEM.Ui.Elements {
public class Paragraph : Element {
public static IGenericFont DefaultFont;
public static float DefaultTextScale = 1;
private string text;
private float lineHeight;
private string[] splitText;
private readonly IGenericFont font;
private IGenericFont font;
private readonly bool centerText;
public float TextScale = DefaultTextScale;
public float TextScale;
public string Text {
get => this.text;
set {
@ -29,7 +27,7 @@ namespace MLEM.Ui.Elements {
public Paragraph(Anchor anchor, float width, string text, bool centerText = false, IGenericFont font = null) : base(anchor, new Vector2(width, 0)) {
this.text = text;
this.font = font ?? DefaultFont;
this.font = font;
this.centerText = centerText;
}
@ -63,6 +61,12 @@ namespace MLEM.Ui.Elements {
}
}
protected override void InitStyle(UiStyle style) {
base.InitStyle(style);
this.TextScale = style.TextScale;
this.font = style.Font;
}
}
}

View file

@ -5,28 +5,24 @@ using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using MLEM.Font;
using MLEM.Textures;
using MLEM.Ui.Style;
namespace MLEM.Ui.Elements {
public class TextField : Element {
public static NinePatch DefaultTexture;
public static NinePatch DefaultHoveredTexture;
public static Color DefaultHoveredColor = Color.LightGray;
public NinePatch Texture = DefaultTexture;
public NinePatch HoveredTexture = DefaultHoveredTexture;
public Color HoveredColor = DefaultHoveredColor;
public NinePatch Texture;
public NinePatch HoveredTexture;
public Color HoveredColor;
public float TextScale;
public readonly StringBuilder Text = new StringBuilder();
public TextChanged OnTextChange;
public int MaxTextLength = int.MaxValue;
public float TextOffsetX = 4;
private readonly IGenericFont font;
private IGenericFont font;
private double caretBlinkTimer;
public TextField(Anchor anchor, Vector2 size, IGenericFont font = null) : base(anchor, size) {
this.font = font ?? Paragraph.DefaultFont;
this.TextScale = Paragraph.DefaultTextScale;
this.font = font;
this.OnTextInput += (element, key, character) => {
if (!this.IsSelected)
return;
@ -69,6 +65,15 @@ namespace MLEM.Ui.Elements {
base.Draw(time, batch, alpha);
}
protected override void InitStyle(UiStyle style) {
base.InitStyle(style);
this.TextScale = style.TextScale;
this.font = style.Font;
this.Texture = style.TextFieldTexture;
this.HoveredTexture = style.TextFieldHoveredTexture;
this.HoveredColor = style.TextFieldHoveredColor;
}
public delegate void TextChanged(TextField field, string text);
}

19
MLEM.Ui/Style/UiStyle.cs Normal file
View file

@ -0,0 +1,19 @@
using Microsoft.Xna.Framework;
using MLEM.Font;
using MLEM.Textures;
namespace MLEM.Ui.Style {
public class UiStyle {
public NinePatch ButtonTexture;
public NinePatch ButtonHoveredTexture;
public Color ButtonHoveredColor;
public NinePatch PanelTexture;
public NinePatch TextFieldTexture;
public NinePatch TextFieldHoveredTexture;
public Color TextFieldHoveredColor;
public IGenericFont Font;
public float TextScale = 1;
}
}

View file

@ -0,0 +1,74 @@
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Font;
using MLEM.Textures;
namespace MLEM.Ui.Style {
public class UntexturedStyle : UiStyle {
public UntexturedStyle(SpriteBatch batch) {
this.ButtonTexture = GenerateTexture(batch, Color.CadetBlue);
this.ButtonHoveredColor = Color.LightGray;
this.PanelTexture = GenerateTexture(batch, Color.Gray);
this.TextFieldTexture = GenerateTexture(batch, Color.MediumBlue);
this.TextFieldHoveredColor = Color.LightGray;
this.Font = new EmptyFont();
}
private static NinePatch GenerateTexture(SpriteBatch batch, Color color) {
var tex = new Texture2D(batch.GraphicsDevice, 3, 3);
tex.SetData(new[] {
Color.Black, Color.Black, Color.Black,
Color.Black, color, Color.Black,
Color.Black, Color.Black, Color.Black
});
batch.Disposing += (sender, args) => {
if (tex != null) {
tex.Dispose();
tex = null;
}
};
return new NinePatch(tex, 1);
}
private class EmptyFont : IGenericFont {
public Vector2 MeasureString(string text) {
return Vector2.One;
}
public Vector2 MeasureString(StringBuilder text) {
return Vector2.One;
}
public void DrawString(SpriteBatch batch, string text, Vector2 position, Color color) {
}
public void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) {
}
public void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) {
}
public void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color) {
}
public void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) {
}
public void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) {
}
public void DrawCenteredString(SpriteBatch batch, string text, Vector2 position, float scale, Color color, bool horizontal = true, bool vertical = false, float addedScale = 0) {
}
public IEnumerable<string> SplitString(string text, float width, float scale) {
yield break;
}
}
}
}

View file

@ -6,6 +6,7 @@ using MLEM.Extensions;
using MLEM.Font;
using MLEM.Input;
using MLEM.Ui.Elements;
using MLEM.Ui.Style;
namespace MLEM.Ui {
public class UiSystem {
@ -33,14 +34,26 @@ namespace MLEM.Ui {
public Vector2 MousePos => this.InputHandler.MousePosition.ToVector2() / this.globalScale;
public Element MousedElement { get; private set; }
public Element SelectedElement { get; private set; }
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();
}
}
}
public float DrawAlpha = 1;
public BlendState BlendState;
public SamplerState SamplerState = SamplerState.PointClamp;
public UiSystem(GameWindow window, GraphicsDevice device, InputHandler inputHandler = null) {
public UiSystem(GameWindow window, GraphicsDevice device, UiStyle style, InputHandler inputHandler = null) {
this.GraphicsDevice = device;
this.InputHandler = inputHandler ?? new InputHandler();
this.isInputOurs = inputHandler == null;
this.style = style;
window.ClientSizeChanged += (sender, args) => {
foreach (var root in this.rootElements)
@ -103,7 +116,7 @@ namespace MLEM.Ui {
throw new ArgumentException($"There is already a root element with name {name}");
this.rootElements.Add(new RootElement(name, root));
root.SetUiSystem(this);
root.PropagateUiSystem(this);
}
public void Remove(string name) {

View file

@ -8,7 +8,7 @@ namespace MLEM.Extensions {
public static Texture2D GetBlankTexture(this SpriteBatch batch) {
if (blankTexture == null) {
blankTexture = new Texture2D(batch.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
blankTexture = new Texture2D(batch.GraphicsDevice, 1, 1);
blankTexture.SetData(new[] {Color.White});
batch.Disposing += (sender, args) => {
if (blankTexture != null) {

View file

@ -27,6 +27,9 @@ namespace MLEM.Textures {
this(new TextureRegion(texture), paddingLeft, paddingRight, paddingTop, paddingBottom) {
}
public NinePatch(Texture2D texture, int padding) : this(new TextureRegion(texture), padding) {
}
public NinePatch(TextureRegion texture, int padding) : this(texture, padding, padding, padding, padding) {
}

View file

@ -9,6 +9,7 @@ using MLEM.Startup;
using MLEM.Textures;
using MLEM.Ui;
using MLEM.Ui.Elements;
using MLEM.Ui.Style;
namespace Tests {
public class GameImpl : MlemGame {
@ -21,17 +22,26 @@ namespace Tests {
}
protected override void LoadContent() {
base.LoadContent();
this.testTexture = LoadContent<Texture2D>("Textures/Test");
this.testPatch = new NinePatch(new TextureRegion(this.testTexture, 0, 8, 24, 24), 8);
base.LoadContent();
Paragraph.DefaultFont = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont"));
Paragraph.DefaultTextScale = 0.2F;
Button.DefaultTexture = new NinePatch(new TextureRegion(this.testTexture, 24, 8, 16, 16), 4);
TextField.DefaultTexture = Button.DefaultTexture;
var style = new UiStyle {
Font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont")),
TextScale = 0.2F,
PanelTexture = this.testPatch,
ButtonTexture = new NinePatch(new TextureRegion(this.testTexture, 24, 8, 16, 16), 4),
TextFieldTexture = new NinePatch(new TextureRegion(this.testTexture, 24, 8, 16, 16), 4),
ButtonHoveredColor = Color.LightGray,
TextFieldHoveredColor = Color.LightGray
};
var untexturedStyle = this.UiSystem.Style;
this.UiSystem.Style = style;
this.UiSystem.GlobalScale = 5;
var root = new Panel(Anchor.BottomLeft, new Vector2(100, 100), new Point(5, 5), this.testPatch);
var root = new Panel(Anchor.BottomLeft, new Vector2(100, 120), new Point(5, 5));
this.UiSystem.Add("Test", root);
root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "This is a test text that is hopefully long enough to cover at least a few lines, otherwise it would be very sad."));
var image = root.AddChild(new Image(Anchor.AutoCenter, new Vector2(20, 20), new TextureRegion(this.testTexture, 0, 0, 8, 8)) {IsHidden = true});
root.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 15), "Test Button") {
@ -40,8 +50,16 @@ namespace Tests {
image.IsHidden = !image.IsHidden;
}
});
root.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 15), "Change Style") {
OnClicked = (element, pos, button) => {
if (button == MouseButton.Left)
this.UiSystem.Style = this.UiSystem.Style is UntexturedStyle ? style : untexturedStyle;
},
HasCustomStyle = true,
Texture = this.testPatch,
HoveredColor = Color.LightGray
});
root.AddChild(new TextField(Anchor.AutoLeft, new Vector2(1, 15)));
this.UiSystem.Add("Test", root);
}
protected override void Draw(GameTime gameTime) {