mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-22 12:58:33 +01:00
added the ability to transform the entire ui
This commit is contained in:
parent
64eefedac0
commit
0dff0e275d
7 changed files with 41 additions and 19 deletions
|
@ -139,12 +139,21 @@ namespace Demos {
|
||||||
root.AddChild(new Paragraph(Anchor.AutoLeft, 1, paragraph => "Slider is at " + (slider.CurrentValue * 100).Floor() + "%") {PositionOffset = new Vector2(0, 1)});
|
root.AddChild(new Paragraph(Anchor.AutoLeft, 1, paragraph => "Slider is at " + (slider.CurrentValue * 100).Floor() + "%") {PositionOffset = new Vector2(0, 1)});
|
||||||
root.AddChild(slider);
|
root.AddChild(slider);
|
||||||
|
|
||||||
// This button uses a coroutine from my Coroutine NuGet package (which is included with MLEM.Startup)
|
// Check the WobbleButton method for an explanation of how this button works
|
||||||
// but the important thing it does is change its visual scale and offset (check the method below for more info)
|
root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Wobble Me", "This button wobbles around visually when clicked, but this doesn't affect its actual size and positioning") {
|
||||||
root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Wobble", "This button wobbles around visually when clicked, but this doesn't affect its actual size and positioning") {
|
|
||||||
OnPressed = element => CoroutineHandler.Start(this.WobbleButton(element)),
|
OnPressed = element => CoroutineHandler.Start(this.WobbleButton(element)),
|
||||||
PositionOffset = new Vector2(0, 1)
|
PositionOffset = new Vector2(0, 1)
|
||||||
});
|
});
|
||||||
|
root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Transform Ui", "This button causes the entire ui to be transformed (both in positioning, rotation and scale). As this is an easily pulled off operation, it can be used for animations and other gimmicks.") {
|
||||||
|
OnPressed = element => {
|
||||||
|
if (element.Root.Transform == Matrix.Identity) {
|
||||||
|
element.Root.Transform = Matrix.CreateScale(0.75F) * Matrix.CreateRotationZ(0.25F) * Matrix.CreateTranslation(50, -10, 0);
|
||||||
|
} else {
|
||||||
|
element.Root.Transform = Matrix.Identity;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PositionOffset = new Vector2(0, 1)
|
||||||
|
});
|
||||||
|
|
||||||
root.AddChild(new VerticalSpace(3));
|
root.AddChild(new VerticalSpace(3));
|
||||||
root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "There are also some additional \"components\" which are created as combinations of other components. You can find all of them in the ElementHelper class. Here are some examples:"));
|
root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "There are also some additional \"components\" which are created as combinations of other components. You can find all of them in the ElementHelper class. Here are some examples:"));
|
||||||
|
@ -183,7 +192,7 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method is used by the wobbling button (see above)
|
// This method is used by the wobbling button (see above)
|
||||||
// Note that this particular example makes use of the Coroutine package
|
// Note that this particular example makes use of the Coroutine package, which is not required but makes demonstration easier
|
||||||
private IEnumerator<Wait> WobbleButton(Element button) {
|
private IEnumerator<Wait> WobbleButton(Element button) {
|
||||||
var counter = 0F;
|
var counter = 0F;
|
||||||
while (counter < 4 * Math.PI) {
|
while (counter < 4 * Math.PI) {
|
||||||
|
|
|
@ -436,10 +436,10 @@ namespace MLEM.Ui.Elements {
|
||||||
this.System.OnSelectedElementDrawn?.Invoke(this, time, batch, alpha, offset);
|
this.System.OnSelectedElementDrawn?.Invoke(this, time, batch, alpha, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void DrawEarly(GameTime time, SpriteBatch batch, float alpha, BlendState blendState = null, SamplerState samplerState = null) {
|
public virtual void DrawEarly(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
|
||||||
foreach (var child in this.SortedChildren) {
|
foreach (var child in this.SortedChildren) {
|
||||||
if (!child.IsHidden)
|
if (!child.IsHidden)
|
||||||
child.DrawEarly(time, batch, alpha * child.DrawAlpha, blendState, samplerState);
|
child.DrawEarly(time, batch, alpha * child.DrawAlpha, blendState, samplerState, matrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,11 +103,12 @@ namespace MLEM.Ui.Elements {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawEarly(GameTime time, SpriteBatch batch, float alpha, BlendState blendState = null, SamplerState samplerState = null) {
|
public override void DrawEarly(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
|
||||||
if (this.scrollOverflow && this.renderTarget != null) {
|
if (this.scrollOverflow && this.renderTarget != null) {
|
||||||
// draw children onto the render target
|
// draw children onto the render target
|
||||||
batch.GraphicsDevice.SetRenderTarget(this.renderTarget);
|
batch.GraphicsDevice.SetRenderTarget(this.renderTarget);
|
||||||
batch.GraphicsDevice.Clear(Color.Transparent);
|
batch.GraphicsDevice.Clear(Color.Transparent);
|
||||||
|
// we don't apply the matrix here because it's already applied when drawing the render target
|
||||||
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState);
|
batch.Begin(SpriteSortMode.Deferred, blendState, samplerState);
|
||||||
// offset children by the render target's location
|
// offset children by the render target's location
|
||||||
var area = this.GetRenderTargetArea();
|
var area = this.GetRenderTargetArea();
|
||||||
|
@ -115,7 +116,7 @@ namespace MLEM.Ui.Elements {
|
||||||
batch.End();
|
batch.End();
|
||||||
batch.GraphicsDevice.SetRenderTarget(null);
|
batch.GraphicsDevice.SetRenderTarget(null);
|
||||||
}
|
}
|
||||||
base.DrawEarly(time, batch, alpha, blendState, samplerState);
|
base.DrawEarly(time, batch, alpha, blendState, samplerState, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Element GetElementUnderPos(Point position) {
|
public override Element GetElementUnderPos(Point position) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace MLEM.Ui.Elements {
|
||||||
this.isMouseHeld = false;
|
this.isMouseHeld = false;
|
||||||
}
|
}
|
||||||
if (this.isMouseHeld)
|
if (this.isMouseHeld)
|
||||||
this.ScrollToPos(this.Input.MousePosition);
|
this.ScrollToPos(this.Input.MousePosition.Transform(this.Root.InvTransform));
|
||||||
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)
|
||||||
|
@ -79,7 +79,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(drag.Position.ToPoint());
|
var touched = this.Parent.GetElementUnderPos(drag.Position.ToPoint().Transform(this.Root.InvTransform));
|
||||||
if (touched != null && touched != this)
|
if (touched != null && touched != this)
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
|
|
||||||
|
@ -95,14 +95,15 @@ 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);
|
||||||
// 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(loc.Position) && !loc.TryGetPreviousLocation(out _)) {
|
if (this.DisplayArea.Contains(pos) && !loc.TryGetPreviousLocation(out _)) {
|
||||||
this.isTouchHeld = true;
|
this.isTouchHeld = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// scroll no matter if we're on the scroller right now
|
// scroll no matter if we're on the scroller right now
|
||||||
if (this.isTouchHeld)
|
if (this.isTouchHeld)
|
||||||
this.ScrollToPos(loc.Position.ToPoint());
|
this.ScrollToPos(pos.ToPoint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
using Microsoft.Xna.Framework.Input.Touch;
|
using Microsoft.Xna.Framework.Input.Touch;
|
||||||
|
using MLEM.Extensions;
|
||||||
using MLEM.Input;
|
using MLEM.Input;
|
||||||
using MLEM.Ui.Elements;
|
using MLEM.Ui.Elements;
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ namespace MLEM.Ui {
|
||||||
this.MousedElement = mousedNow;
|
this.MousedElement = mousedNow;
|
||||||
this.system.ApplyToAll(e => e.OnMousedElementChanged?.Invoke(e, mousedNow));
|
this.system.ApplyToAll(e => e.OnMousedElementChanged?.Invoke(e, mousedNow));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.Input.IsMouseButtonPressed(MouseButton.Left)) {
|
if (this.Input.IsMouseButtonPressed(MouseButton.Left)) {
|
||||||
var selectedNow = mousedNow != null && mousedNow.CanBeSelected ? mousedNow : null;
|
var selectedNow = mousedNow != null && mousedNow.CanBeSelected ? mousedNow : null;
|
||||||
this.SelectElement(selectedNow, true);
|
this.SelectElement(selectedNow, true);
|
||||||
|
@ -50,7 +51,7 @@ namespace MLEM.Ui {
|
||||||
if (mousedNow != null)
|
if (mousedNow != null)
|
||||||
mousedNow.OnSecondaryPressed?.Invoke(mousedNow);
|
mousedNow.OnSecondaryPressed?.Invoke(mousedNow);
|
||||||
}
|
}
|
||||||
|
|
||||||
// KEYBOARD INPUT
|
// KEYBOARD INPUT
|
||||||
else if (this.Input.IsKeyPressed(Keys.Enter) || this.Input.IsKeyPressed(Keys.Space)) {
|
else if (this.Input.IsKeyPressed(Keys.Enter) || this.Input.IsKeyPressed(Keys.Space)) {
|
||||||
if (this.SelectedElement != null) {
|
if (this.SelectedElement != null) {
|
||||||
|
@ -66,7 +67,7 @@ namespace MLEM.Ui {
|
||||||
// tab or shift-tab to next or previous element
|
// tab or shift-tab to next or previous element
|
||||||
this.SelectElement(this.GetNextElement(this.Input.IsModifierKeyDown(ModifierKey.Shift)), false);
|
this.SelectElement(this.GetNextElement(this.Input.IsModifierKeyDown(ModifierKey.Shift)), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOUCH INPUT
|
// TOUCH INPUT
|
||||||
else if (this.Input.GetGesture(GestureType.Tap, out var tap)) {
|
else if (this.Input.GetGesture(GestureType.Tap, out var tap)) {
|
||||||
var tapped = this.GetElementUnderPos(tap.Position.ToPoint());
|
var tapped = this.GetElementUnderPos(tap.Position.ToPoint());
|
||||||
|
@ -94,9 +95,10 @@ namespace MLEM.Ui {
|
||||||
this.system.ApplyToAll(e => e.OnSelectedElementChanged?.Invoke(e, element));
|
this.system.ApplyToAll(e => e.OnSelectedElementChanged?.Invoke(e, element));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Element GetElementUnderPos(Point position) {
|
public Element GetElementUnderPos(Point position, bool transform = true) {
|
||||||
foreach (var root in this.system.GetRootElements()) {
|
foreach (var root in this.system.GetRootElements()) {
|
||||||
var moused = root.Element.GetElementUnderPos(position);
|
var pos = transform ? position.Transform(root.InvTransform) : position;
|
||||||
|
var moused = root.Element.GetElementUnderPos(pos);
|
||||||
if (moused != null)
|
if (moused != null)
|
||||||
return moused;
|
return moused;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace MLEM.Ui {
|
||||||
public void DrawEarly(GameTime time, SpriteBatch batch) {
|
public void DrawEarly(GameTime time, SpriteBatch batch) {
|
||||||
foreach (var root in this.rootElements) {
|
foreach (var root in this.rootElements) {
|
||||||
if (!root.Element.IsHidden)
|
if (!root.Element.IsHidden)
|
||||||
root.Element.DrawEarly(time, batch, this.DrawAlpha * root.Element.DrawAlpha, this.BlendState, this.SamplerState);
|
root.Element.DrawEarly(time, batch, this.DrawAlpha * root.Element.DrawAlpha, this.BlendState, this.SamplerState, root.Transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ namespace MLEM.Ui {
|
||||||
foreach (var root in this.rootElements) {
|
foreach (var root in this.rootElements) {
|
||||||
if (root.Element.IsHidden)
|
if (root.Element.IsHidden)
|
||||||
continue;
|
continue;
|
||||||
batch.Begin(SpriteSortMode.Deferred, this.BlendState, this.SamplerState);
|
batch.Begin(SpriteSortMode.Deferred, this.BlendState, this.SamplerState, null, null, null, root.Transform);
|
||||||
root.Element.Draw(time, batch, this.DrawAlpha * root.Element.DrawAlpha, Point.Zero);
|
root.Element.Draw(time, batch, this.DrawAlpha * root.Element.DrawAlpha, Point.Zero);
|
||||||
batch.End();
|
batch.End();
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,9 @@ namespace MLEM.Ui {
|
||||||
public float ActualScale => this.System.GlobalScale * this.Scale;
|
public float ActualScale => this.System.GlobalScale * this.Scale;
|
||||||
public bool CanSelectContent = true;
|
public bool CanSelectContent = true;
|
||||||
|
|
||||||
|
public Matrix Transform = Matrix.Identity;
|
||||||
|
public Matrix InvTransform => Matrix.Invert(this.Transform);
|
||||||
|
|
||||||
public RootElement(string name, Element element, UiSystem system) {
|
public RootElement(string name, Element element, UiSystem system) {
|
||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.Element = element;
|
this.Element = element;
|
||||||
|
|
|
@ -32,6 +32,12 @@ namespace MLEM.Extensions {
|
||||||
return new Point((point.X / f).Floor(), (point.Y / f).Floor());
|
return new Point((point.X / f).Floor(), (point.Y / f).Floor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Point Transform(this Point position, Matrix matrix) {
|
||||||
|
return new Point(
|
||||||
|
(position.X * matrix.M11 + position.Y * matrix.M21 + matrix.M41).Floor(),
|
||||||
|
(position.X * matrix.M12 + position.Y * matrix.M22 + matrix.M42).Floor());
|
||||||
|
}
|
||||||
|
|
||||||
public static Rectangle OffsetCopy(this Rectangle rect, Point offset) {
|
public static Rectangle OffsetCopy(this Rectangle rect, Point offset) {
|
||||||
rect.X += offset.X;
|
rect.X += offset.X;
|
||||||
rect.Y += offset.Y;
|
rect.Y += offset.Y;
|
||||||
|
|
Loading…
Reference in a new issue