summaryrefslogtreecommitdiff
path: root/source/ui/elements/game
diff options
context:
space:
mode:
Diffstat (limited to 'source/ui/elements/game')
-rw-r--r--source/ui/elements/game/CraftingRecipeSlot.cs173
-rw-r--r--source/ui/elements/game/CraftingWindow.cs62
-rw-r--r--source/ui/elements/game/InventorySlot.cs191
-rw-r--r--source/ui/elements/game/InventoryWindow.cs56
-rw-r--r--source/ui/elements/game/PauseMenu.cs74
-rw-r--r--source/ui/elements/game/controls/ControlTips.cs51
-rw-r--r--source/ui/elements/game/tooltips/CraftingTooltipDisplay.cs97
-rw-r--r--source/ui/elements/game/tooltips/ItemDisplay.cs21
-rw-r--r--source/ui/elements/game/tooltips/ItemTooltipDisplay.cs62
-rw-r--r--source/ui/elements/game/tooltips/TooltipDisplay.cs8
10 files changed, 795 insertions, 0 deletions
diff --git a/source/ui/elements/game/CraftingRecipeSlot.cs b/source/ui/elements/game/CraftingRecipeSlot.cs
new file mode 100644
index 0000000..72101d8
--- /dev/null
+++ b/source/ui/elements/game/CraftingRecipeSlot.cs
@@ -0,0 +1,173 @@
+using System;
+using Celesteia.Game.Components.Items;
+using Celesteia.Resources.Types;
+using Celesteia.UI.Properties;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using MonoGame.Extended.Input;
+using MonoGame.Extended.TextureAtlases;
+
+namespace Celesteia.UI.Elements.Game {
+ public class CraftingRecipeSlot : Clickable {
+ public const float SLOT_SIZE = 64f;
+ public const float SLOT_SPACING = 16f;
+
+ public Inventory referenceInv;
+
+ public CraftingRecipeSlot(Rect rect) {
+ SetRect(rect);
+ }
+
+ public CraftingRecipeSlot SetNewRect(Rect rect) {
+ SetRect(rect);
+ return this;
+ }
+
+ // RECIPE REFERENCE PROPERTIES
+ private Recipe _recipe;
+ public CraftingRecipeSlot SetRecipe(Recipe recipe) {
+ _recipe = recipe;
+ return this;
+ }
+
+ // DRAWING PROPERTIES
+
+ private Texture2D _texture;
+ private TextureAtlas _patches;
+ private int _patchSize;
+
+ public CraftingRecipeSlot SetTexture(Texture2D texture) {
+ _texture = texture;
+ return this;
+ }
+
+ public CraftingRecipeSlot SetPatches(TextureAtlas patches, int size) {
+ if (_texture != null) {
+ _patchSize = size;
+ _patches = patches;
+ }
+ return this;
+ }
+
+ // TEXT PROPERTIES
+
+ private TextProperties _text;
+
+ public CraftingRecipeSlot SetTextProperties(TextProperties text) {
+ _text = text;
+ return this;
+ }
+
+ public CraftingRecipeSlot SetText(string text) {
+ _text.SetText(text);
+ return this;
+ }
+
+ // CLICKING PROPERTIES
+
+ private ClickEvent _onMouseDown = null;
+ private ClickEvent _onMouseUp = null;
+ public delegate void CraftHoverEvent(Recipe recipe);
+ private CraftHoverEvent _onMouseIn = null;
+ private HoverEvent _onMouseOut = null;
+
+ public CraftingRecipeSlot SetOnMouseDown(ClickEvent func) {
+ _onMouseDown = func;
+ return this;
+ }
+
+ public CraftingRecipeSlot SetOnMouseUp(ClickEvent func) {
+ _onMouseUp = func;
+ return this;
+ }
+
+ public CraftingRecipeSlot SetOnMouseIn(CraftHoverEvent func) {
+ _onMouseIn = func;
+ return this;
+ }
+
+ public CraftingRecipeSlot SetOnMouseOut(HoverEvent func) {
+ _onMouseOut = func;
+ return this;
+ }
+
+ public override void OnMouseDown(MouseButton button, Point position) {
+ base.OnMouseDown(button, position);
+ _onMouseDown?.Invoke(button, position);
+ }
+
+ public override void OnMouseUp(MouseButton button, Point position) {
+ base.OnMouseUp(button, position);
+ _onMouseUp?.Invoke(button, position);
+ }
+
+ public override void OnMouseIn() {
+ base.OnMouseIn();
+ if (_recipe != null) _onMouseIn?.Invoke(_recipe);
+ }
+
+ public override void OnMouseOut() {
+ base.OnMouseOut();
+ _onMouseOut?.Invoke();
+ }
+
+ private Rectangle GetScaledTriangle(Rectangle r, float scale) {
+ int newWidth = (int)Math.Round(r.Width * scale);
+ int newHeight = (int)Math.Round(r.Height * scale);
+ return new Rectangle(
+ (int)Math.Round(r.X + ((r.Width - newWidth) / 2f)),
+ (int)Math.Round(r.Y + ((r.Height - newHeight) / 2f)),
+ newWidth,
+ newHeight
+ );
+ }
+
+ Color color;
+ public override void Update(GameTime gameTime, out bool clickedAnything) {
+ base.Update(gameTime, out clickedAnything);
+
+ if (!this.GetEnabled()) return;
+ color = _recipe.Craftable(referenceInv) ? Color.White : Color.Gray;
+ }
+
+ Rectangle rectangle;
+ Rectangle itemRectangle;
+ Rectangle textRectangle;
+ public override void Draw(SpriteBatch spriteBatch)
+ {
+ if (_recipe == null) return;
+
+ rectangle = GetRectangle();
+ itemRectangle = GetScaledTriangle(rectangle, .6f);
+ textRectangle = GetScaledTriangle(rectangle, .4f);
+
+ // Draw the slot's texture.
+ if (_patches != null) ImageUtilities.DrawPatched(spriteBatch, rectangle, _patches, _patchSize, color);
+ else spriteBatch.Draw(GetTexture(spriteBatch), rectangle, null, color);
+
+ spriteBatch.Draw(_recipe.Result.GetItemType().Sprite, itemRectangle, color);
+ TextUtilities.DrawAlignedText(spriteBatch, textRectangle, _text.GetFont(), _recipe.Result.Amount + "", _text.GetColor(), _text.GetAlignment(), _text.GetFontSize());
+ }
+
+ public Texture2D GetTexture(SpriteBatch spriteBatch) {
+ if (_texture == null) {
+ _texture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1);
+ _texture.SetData(new[] { Color.Gray });
+ }
+
+ return _texture;
+ }
+
+ public CraftingRecipeSlot Clone() {
+ return new CraftingRecipeSlot(GetRect())
+ .SetRecipe(_recipe)
+ .SetOnMouseDown(_onMouseDown)
+ .SetOnMouseUp(_onMouseUp)
+ .SetOnMouseIn(_onMouseIn)
+ .SetOnMouseOut(_onMouseOut)
+ .SetTextProperties(_text)
+ .SetTexture(_texture)
+ .SetPatches(_patches, _patchSize);
+ }
+ }
+} \ No newline at end of file
diff --git a/source/ui/elements/game/CraftingWindow.cs b/source/ui/elements/game/CraftingWindow.cs
new file mode 100644
index 0000000..e5bcc71
--- /dev/null
+++ b/source/ui/elements/game/CraftingWindow.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using Celesteia.Game.Components.Items;
+using Celesteia.GUIs.Game;
+using Celesteia.Resources;
+using Celesteia.Resources.Management;
+using Celesteia.Resources.Types;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace Celesteia.UI.Elements.Game {
+ public class CraftingWindow : Container {
+ private Inventory _referenceInventory;
+ private Image background;
+ private GameGUI _gameGui;
+
+ public CraftingWindow(GameGUI gameGui, Rect rect, Texture2D backgroundImage, Inventory inventory, CraftingRecipeSlot template) : base(rect) {
+ _gameGui = gameGui;
+
+ _referenceInventory = inventory;
+
+ background = new Image(Rect.RelativeFull(rect)).SetTexture(backgroundImage).MakePatches(4).SetColor(Color.White);
+ AddChild(background);
+
+ AddRecipes(27, template);
+ }
+
+ int columns = 9;
+ private void AddRecipes(int amountPerPage, CraftingRecipeSlot template) {
+ int rows = (int)Math.Ceiling(amountPerPage / (double)columns);
+
+ float o = CraftingRecipeSlot.SLOT_SPACING;
+ int index = 0;
+ int i = 0;
+ for (int row = 0; row < rows; row++)
+ for (int column = 0; column < columns; column++) {
+ if (i >= ResourceManager.Recipes.Recipes.Count) break;
+
+ int slotNumber = i;
+ Recipe recipe = ResourceManager.Recipes.Recipes[index];
+ CraftingRecipeSlot slot = template.Clone()
+ .SetNewRect(template.GetRect()
+ .SetX(AbsoluteUnit.WithValue(column * CraftingRecipeSlot.SLOT_SIZE + (column * CraftingRecipeSlot.SLOT_SPACING) + o))
+ .SetY(AbsoluteUnit.WithValue(row * CraftingRecipeSlot.SLOT_SIZE + (row * CraftingRecipeSlot.SLOT_SPACING) + o))
+ )
+ .SetRecipe(recipe)
+ .SetOnMouseUp((button, point) => {
+ if (button == MonoGame.Extended.Input.MouseButton.Left) {
+ recipe.Craft(_referenceInventory);
+ }
+ });
+ slot.referenceInv = _referenceInventory;
+ slot.SetPivot(new Vector2(0f, 0f));
+
+ index++;
+ i++;
+
+ AddChild(slot);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/source/ui/elements/game/InventorySlot.cs b/source/ui/elements/game/InventorySlot.cs
new file mode 100644
index 0000000..01663b4
--- /dev/null
+++ b/source/ui/elements/game/InventorySlot.cs
@@ -0,0 +1,191 @@
+using System;
+using Celesteia.Game.Components.Items;
+using Celesteia.Resources.Types;
+using Celesteia.UI.Properties;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using MonoGame.Extended.Input;
+using MonoGame.Extended.TextureAtlases;
+
+namespace Celesteia.UI.Elements.Game {
+ public class InventorySlot : Clickable {
+ public const float SLOT_SIZE = 64f;
+ public const float SLOT_SPACING = 16f;
+
+ public InventorySlot(Rect rect) {
+ SetRect(rect);
+ }
+
+ public InventorySlot SetNewRect(Rect rect) {
+ SetRect(rect);
+ return this;
+ }
+
+ // SELECTION
+
+ private bool _selected = false;
+ public InventorySlot SetSelected(bool selected) {
+ _selected = selected;
+ return this;
+ }
+
+ public bool GetSelected() {
+ return _selected;
+ }
+
+
+ // INVENTORY REFERENCE PROPERTIES
+
+ private Inventory _inventory;
+ private int _slot;
+
+ public InventorySlot SetReferenceInventory(Inventory inventory) {
+ _inventory = inventory;
+ return this;
+ }
+
+ public InventorySlot SetSlot(int slot) {
+ _slot = slot;
+ return this;
+ }
+
+ // DRAWING PROPERTIES
+
+ private Texture2D _texture;
+ private TextureAtlas _patches;
+ private int _patchSize;
+
+ public InventorySlot SetTexture(Texture2D texture) {
+ _texture = texture;
+ return this;
+ }
+
+ public InventorySlot SetPatches(TextureAtlas patches, int size) {
+ if (_texture != null) {
+ _patchSize = size;
+ _patches = patches;
+ }
+ return this;
+ }
+
+ // TEXT PROPERTIES
+
+ private TextProperties _text;
+
+ public InventorySlot SetTextProperties(TextProperties text) {
+ _text = text;
+ return this;
+ }
+
+ public InventorySlot SetText(string text) {
+ _text.SetText(text);
+ return this;
+ }
+
+ // CLICKING PROPERTIES
+
+ private ClickEvent _onMouseDown = null;
+ private ClickEvent _onMouseUp = null;
+ public delegate void ItemHoverEvent(ItemType type);
+ private ItemHoverEvent _onMouseIn = null;
+ private HoverEvent _onMouseOut = null;
+
+ public InventorySlot SetOnMouseDown(ClickEvent func) {
+ _onMouseDown = func;
+ return this;
+ }
+
+ public InventorySlot SetOnMouseUp(ClickEvent func) {
+ _onMouseUp = func;
+ return this;
+ }
+
+ public InventorySlot SetOnMouseIn(ItemHoverEvent func) {
+ _onMouseIn = func;
+ return this;
+ }
+
+ public InventorySlot SetOnMouseOut(HoverEvent func) {
+ _onMouseOut = func;
+ return this;
+ }
+
+ public override void OnMouseDown(MouseButton button, Point position) {
+ base.OnMouseDown(button, position);
+ _onMouseDown?.Invoke(button, position);
+ }
+
+ public override void OnMouseUp(MouseButton button, Point position) {
+ base.OnMouseUp(button, position);
+ _onMouseUp?.Invoke(button, position);
+ }
+
+ public override void OnMouseIn() {
+ base.OnMouseIn();
+ if (_inventory.GetSlot(_slot) != null) _onMouseIn?.Invoke(_inventory.GetSlot(_slot).Type);
+ }
+
+ public override void OnMouseOut() {
+ base.OnMouseOut();
+ _onMouseOut?.Invoke();
+ }
+
+ private Rectangle GetScaledTriangle(Rectangle r, float scale) {
+ int newWidth = (int)Math.Round(r.Width * scale);
+ int newHeight = (int)Math.Round(r.Height * scale);
+ return new Rectangle(
+ (int)Math.Round(r.X + ((r.Width - newWidth) / 2f)),
+ (int)Math.Round(r.Y + ((r.Height - newHeight) / 2f)),
+ newWidth,
+ newHeight
+ );
+ }
+
+ Rectangle rectangle;
+ Rectangle itemRectangle;
+ Rectangle textRectangle;
+ ItemStack inSlot;
+ Color slightlyTransparent = new Color(255, 255, 255, 100);
+ public override void Draw(SpriteBatch spriteBatch)
+ {
+ if (_inventory == null) return;
+
+ rectangle = GetRectangle();
+ itemRectangle = GetScaledTriangle(rectangle, .6f);
+ textRectangle = GetScaledTriangle(rectangle, .4f);
+
+ // Draw the slot's texture.
+ if (_patches != null) ImageUtilities.DrawPatched(spriteBatch, rectangle, _patches, _patchSize, _selected ? Color.DarkViolet : Color.White);
+ else spriteBatch.Draw(GetTexture(spriteBatch), rectangle, null, Color.White);
+
+ // Draw item if present.
+ inSlot = _inventory.GetSlot(_slot);
+ if (inSlot != null) {
+ spriteBatch.Draw(inSlot.Type.Sprite, itemRectangle, Color.White);
+ if (inSlot.Amount > 1) TextUtilities.DrawAlignedText(spriteBatch, textRectangle, _text.GetFont(), $"{inSlot.Amount}", _text.GetColor(), _text.GetAlignment(), _text.GetFontSize());
+ } else TextUtilities.DrawAlignedText(spriteBatch, rectangle, _text.GetFont(), $"{_slot + 1}", slightlyTransparent, TextAlignment.Center, 24f);
+ }
+
+ public Texture2D GetTexture(SpriteBatch spriteBatch) {
+ if (_texture == null) {
+ _texture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1);
+ _texture.SetData(new[] { Color.Gray });
+ }
+
+ return _texture;
+ }
+
+ public InventorySlot Clone() {
+ return new InventorySlot(GetRect())
+ .SetReferenceInventory(_inventory)
+ .SetOnMouseDown(_onMouseDown)
+ .SetOnMouseUp(_onMouseUp)
+ .SetOnMouseIn(_onMouseIn)
+ .SetOnMouseOut(_onMouseOut)
+ .SetSlot(_slot)
+ .SetTextProperties(_text)
+ .SetTexture(_texture)
+ .SetPatches(_patches, _patchSize);
+ }
+ }
+} \ No newline at end of file
diff --git a/source/ui/elements/game/InventoryWindow.cs b/source/ui/elements/game/InventoryWindow.cs
new file mode 100644
index 0000000..c8dba41
--- /dev/null
+++ b/source/ui/elements/game/InventoryWindow.cs
@@ -0,0 +1,56 @@
+using System;
+using Celesteia.Game.Components.Items;
+using Celesteia.GUIs.Game;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace Celesteia.UI.Elements.Game {
+ public class InventoryWindow : Container {
+ private Inventory _referenceInventory;
+ private Image background;
+ private GameGUI _gameGui;
+
+ public InventoryWindow(GameGUI gameGui, Rect rect, Texture2D backgroundImage, Inventory inventory, int slots, int offset, InventorySlot template) : base(rect) {
+ _gameGui = gameGui;
+
+ background = new Image(Rect.RelativeFull(rect)).SetTexture(backgroundImage).MakePatches(4).SetColor(Color.White);
+ AddChild(background);
+
+ _referenceInventory = inventory;
+
+ AddSlots(slots, offset, template);
+ }
+
+ int columns = 9;
+ private void AddSlots(int amount, int offset, InventorySlot template) {
+ int rows = (int)Math.Ceiling(amount / (double)columns);
+
+ float o = InventorySlot.SLOT_SPACING;
+ int i = 0;
+ for (int row = 0; row < rows; row++)
+ for (int column = 0; column < 9; column++) {
+ if (i > amount) break;
+
+ int slotNumber = i + offset;
+ InventorySlot slot = template.Clone()
+ .SetNewRect(template.GetRect()
+ .SetX(AbsoluteUnit.WithValue(column * InventorySlot.SLOT_SIZE + (column * InventorySlot.SLOT_SPACING) + o))
+ .SetY(AbsoluteUnit.WithValue(row * InventorySlot.SLOT_SIZE + (row * InventorySlot.SLOT_SPACING) + o))
+ )
+ .SetSlot(slotNumber)
+ .SetOnMouseUp((button, point) => {
+ ItemStack itemInSlot = _referenceInventory.GetSlot(slotNumber);
+ if ((int)_gameGui.State > 0) {
+ _referenceInventory.SetSlot(slotNumber, _gameGui.CursorItem);
+ _gameGui.CursorItem = itemInSlot;
+ }
+ });
+ slot.SetPivot(new Vector2(0f, 0f));
+
+ i++;
+
+ AddChild(slot);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/source/ui/elements/game/PauseMenu.cs b/source/ui/elements/game/PauseMenu.cs
new file mode 100644
index 0000000..39281ee
--- /dev/null
+++ b/source/ui/elements/game/PauseMenu.cs
@@ -0,0 +1,74 @@
+using Celesteia.Game.Components.Items;
+using Celesteia.GUIs.Game;
+using Celesteia.Resources;
+using Celesteia.Screens;
+using Celesteia.UI.Properties;
+using Microsoft.Xna.Framework;
+
+namespace Celesteia.UI.Elements.Game {
+ public class PauseMenu : Container {
+ private Image background;
+ private IContainer centerMenu;
+ private GameGUI _gameGui;
+
+ private float buttonRow(int number) => number * (buttonHeight + buttonSpacing);
+ private float buttonHeight = 56f;
+ private float buttonSpacing = 10f;
+
+ public PauseMenu(GameGUI gameGui, Rect rect, Button buttonTemplate) : base(rect) {
+ _gameGui = gameGui;
+
+ background = new Image(Rect.RelativeFull(rect)).SetColor(new Color(0, 0, 0, 100));
+ AddChild(background);
+
+ centerMenu = new Container(new Rect(
+ new RelativeUnit(0.5f, GetRect(), RelativeUnit.Orientation.Horizontal),
+ new RelativeUnit(0.5f, GetRect(), RelativeUnit.Orientation.Vertical),
+ AbsoluteUnit.WithValue(350f),
+ AbsoluteUnit.WithValue(2 * (buttonHeight + buttonSpacing) - buttonSpacing)
+ ));
+ AddChild(centerMenu);
+
+ AddButtons(buttonTemplate);
+ }
+
+ private void AddButtons(Button template) {
+ centerMenu.AddChild(new Label(new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(buttonRow(-1)),
+ new RelativeUnit(1f, centerMenu.GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(buttonHeight)
+ ))
+ .SetPivotPoint(new Vector2(0.5f, 0.5f))
+ .SetTextProperties(new TextProperties().SetColor(Color.White).SetFont(ResourceManager.Fonts.GetFontType("Hobo")).SetFontSize(24f).SetTextAlignment(TextAlignment.Center))
+ .SetText("Paused")
+ );
+
+ centerMenu.AddChild(template.Clone()
+ .SetNewRect(new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(buttonRow(0)),
+ new RelativeUnit(1f, centerMenu.GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(buttonHeight)
+ ))
+ .SetText("Back to Game")
+ .SetOnMouseUp((button, point) => {
+ _gameGui.TogglePause();
+ })
+ );
+
+ centerMenu.AddChild(template.Clone()
+ .SetNewRect(new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(buttonRow(1)),
+ new RelativeUnit(1f, centerMenu.GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(buttonHeight)
+ ))
+ .SetText("Return to Title")
+ .SetOnMouseUp((button, point) => {
+ _gameGui.Game.LoadScreen(new MainMenuScreen(_gameGui.Game),new MonoGame.Extended.Screens.Transitions.FadeTransition(_gameGui.Game.GraphicsDevice, Color.Black));
+ })
+ );
+ }
+ }
+} \ No newline at end of file
diff --git a/source/ui/elements/game/controls/ControlTips.cs b/source/ui/elements/game/controls/ControlTips.cs
new file mode 100644
index 0000000..904b3cc
--- /dev/null
+++ b/source/ui/elements/game/controls/ControlTips.cs
@@ -0,0 +1,51 @@
+using System.Collections.Generic;
+using Celesteia.Game.Input;
+using Celesteia.Resources;
+using Celesteia.UI.Properties;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+
+namespace Celesteia.UI.Elements.Game.Controls {
+ public class ControlTips : Container {
+ private TextProperties _properties;
+ private Dictionary<Keys, string> _keyboardControls = new Dictionary<Keys, string>();
+ private List<string> _lines = new List<string>();
+ private List<Label> _labels = new List<Label>();
+
+ public ControlTips(Rect rect) : base(rect) {
+ _properties = new TextProperties()
+ .SetColor(Color.White)
+ .SetFont(ResourceManager.Fonts.DEFAULT)
+ .SetFontSize(12f)
+ .SetTextAlignment(TextAlignment.Left);
+ }
+
+ private int lineHeight = 16;
+ private Rect LineRect(int line) => new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(line * lineHeight),
+ new RelativeUnit(1f, GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(lineHeight)
+ );
+
+ private void UpdateLines() {
+ _labels.Clear();
+
+ foreach (Keys keys in _keyboardControls.Keys) _lines.Add($"[{keys}] {_keyboardControls[keys]}");
+
+ for (int i = 0; i < _lines.Count; i++) {
+ Label label = new Label(LineRect(i - (_lines.Count / 2)))
+ .SetTextProperties(_properties)
+ .SetText(_lines[i]);
+ label.SetParent(this);
+ _labels.Add(label);
+ }
+ }
+
+ public override void Draw(SpriteBatch spriteBatch)
+ {
+ foreach (Label l in _labels) l.Draw(spriteBatch);
+ }
+ }
+} \ No newline at end of file
diff --git a/source/ui/elements/game/tooltips/CraftingTooltipDisplay.cs b/source/ui/elements/game/tooltips/CraftingTooltipDisplay.cs
new file mode 100644
index 0000000..a7c6e2f
--- /dev/null
+++ b/source/ui/elements/game/tooltips/CraftingTooltipDisplay.cs
@@ -0,0 +1,97 @@
+using Celesteia.Resources.Types;
+using Celesteia.UI.Properties;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace Celesteia.UI.Elements.Game.Tooltips {
+ public class CraftingTooltipDisplay : TooltipDisplay
+ {
+ private const float OUTER_SPACING = 16f;
+ private const float INNER_SPACING = 8f;
+ public readonly Container Content;
+ public readonly Label Title;
+ public readonly ItemDisplay Item;
+ public Container Recipe;
+
+ public CraftingTooltipDisplay(Rect rect, Texture2D background) : base(rect) {
+ AddChild(new Image(Rect.RelativeFull(new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(256f + (2 * OUTER_SPACING)),
+ AbsoluteUnit.WithValue(64f + (1 * INNER_SPACING) + (2 * OUTER_SPACING))
+ ))).SetTexture(background).MakePatches(4).SetColor(Color.White));
+
+ Content = new Container(new Rect(
+ AbsoluteUnit.WithValue(OUTER_SPACING),
+ AbsoluteUnit.WithValue(OUTER_SPACING),
+ AbsoluteUnit.WithValue(256f),
+ AbsoluteUnit.WithValue(64f + (1 * INNER_SPACING))
+ ));
+
+ Container titleCard = new Container(new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(0f),
+ new RelativeUnit(1f, Content.GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(32f)
+ ));
+ titleCard.AddChild(Item = new ItemDisplay(new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(32f),
+ AbsoluteUnit.WithValue(32f)
+ )) {
+ Text = new TextProperties().Standard().SetTextAlignment(TextAlignment.Bottom | TextAlignment.Right)
+ });
+ titleCard.AddChild(Title = new Label(new Rect(
+ AbsoluteUnit.WithValue(72f),
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(150f),
+ AbsoluteUnit.WithValue(32f)
+ )).SetTextProperties(new Properties.TextProperties().Standard().SetTextAlignment(TextAlignment.Left)).SetPivotPoint(new Vector2(0f, 0f)));
+ Content.AddChild(titleCard);
+
+ Recipe = new Container(new Rect(
+ new RelativeUnit(.5f, Content.GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(32f + INNER_SPACING),
+ new RelativeUnit(1f, Content.GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(32f)
+ ));
+ Content.AddChild(Recipe);
+
+ AddChild(Content);
+
+ SetEnabled(false);
+ }
+
+ public void SetRecipe(Recipe recipe) {
+ Item.Item = recipe.Result.GetItemType();
+ Title.SetText(recipe.Result.GetItemType().Name);
+
+ if (Recipe != null) Recipe.Dispose();
+ Recipe = new Container(new Rect(
+ new RelativeUnit(0f, Content.GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(32f + INNER_SPACING),
+ new RelativeUnit(1f, Content.GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(32f)
+ ));
+ Recipe.SetPivot(new Vector2(0f, 0f));
+
+ for (int i = 0; i < recipe.Ingredients.Count; i++)
+ Recipe.AddChild(new ItemDisplay(new Rect(
+ AbsoluteUnit.WithValue((i * INNER_SPACING) + (i * 32)),
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(32f),
+ AbsoluteUnit.WithValue(32f)
+ )) {
+ Item = recipe.Ingredients[i].GetItemType(),
+ Amount = recipe.Ingredients[i].Amount,
+ Text = new TextProperties().Standard()
+ .SetTextAlignment(TextAlignment.Bottom | TextAlignment.Right)
+ .SetFontSize(12f)
+ .SetText(recipe.Ingredients[i].Amount.ToString())
+ });
+
+ Content.AddChild(Recipe);
+ }
+ }
+} \ No newline at end of file
diff --git a/source/ui/elements/game/tooltips/ItemDisplay.cs b/source/ui/elements/game/tooltips/ItemDisplay.cs
new file mode 100644
index 0000000..d3b1524
--- /dev/null
+++ b/source/ui/elements/game/tooltips/ItemDisplay.cs
@@ -0,0 +1,21 @@
+using Celesteia.Resources.Types;
+using Celesteia.UI.Properties;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using MonoGame.Extended.TextureAtlases;
+
+namespace Celesteia.UI.Elements.Game.Tooltips {
+ public class ItemDisplay : Element {
+ public ItemType Item;
+ public int Amount;
+ public TextProperties Text;
+
+ public ItemDisplay(Rect rect) => SetRect(rect);
+
+ public override void Draw(SpriteBatch spriteBatch)
+ {
+ spriteBatch.Draw(Item.Sprite, GetRectangle(), Color.White, null);
+ if (Amount > 1) TextUtilities.DrawAlignedText(spriteBatch, GetRectangle(), Text);
+ }
+ }
+} \ No newline at end of file
diff --git a/source/ui/elements/game/tooltips/ItemTooltipDisplay.cs b/source/ui/elements/game/tooltips/ItemTooltipDisplay.cs
new file mode 100644
index 0000000..9b62af4
--- /dev/null
+++ b/source/ui/elements/game/tooltips/ItemTooltipDisplay.cs
@@ -0,0 +1,62 @@
+using Celesteia.Resources.Types;
+using Celesteia.UI.Properties;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace Celesteia.UI.Elements.Game.Tooltips {
+ public class ItemTooltipDisplay : TooltipDisplay
+ {
+ private const float OUTER_SPACING = 16f;
+ private const float INNER_SPACING = 8f;
+ public readonly Container Content;
+ public readonly Label Title;
+ public readonly ItemDisplay Item;
+
+ public ItemTooltipDisplay(Rect rect, Texture2D background) : base(rect) {
+ AddChild(new Image(Rect.RelativeFull(new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(256f + (2 * OUTER_SPACING)),
+ AbsoluteUnit.WithValue(32f + (2 * OUTER_SPACING))
+ ))).SetTexture(background).MakePatches(4).SetColor(Color.White));
+
+ Content = new Container(new Rect(
+ AbsoluteUnit.WithValue(OUTER_SPACING),
+ AbsoluteUnit.WithValue(OUTER_SPACING),
+ AbsoluteUnit.WithValue(256f),
+ AbsoluteUnit.WithValue(32f)
+ ));
+
+ Container titleCard = new Container(new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(0f),
+ new RelativeUnit(1f, Content.GetRect(), RelativeUnit.Orientation.Horizontal),
+ AbsoluteUnit.WithValue(32f)
+ ));
+ titleCard.AddChild(Item = new ItemDisplay(new Rect(
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(32f),
+ AbsoluteUnit.WithValue(32f)
+ )) {
+ Text = new TextProperties().Standard().SetTextAlignment(TextAlignment.Bottom | TextAlignment.Right)
+ });
+ titleCard.AddChild(Title = new Label(new Rect(
+ AbsoluteUnit.WithValue(72f),
+ AbsoluteUnit.WithValue(0f),
+ AbsoluteUnit.WithValue(150f),
+ AbsoluteUnit.WithValue(32f)
+ )).SetTextProperties(new Properties.TextProperties().Standard().SetTextAlignment(TextAlignment.Left)).SetPivotPoint(new Vector2(0f, 0f)));
+ Content.AddChild(titleCard);
+
+ AddChild(Content);
+
+ SetEnabled(false);
+ }
+
+ public void SetItem(ItemType type) {
+ Item.Item = type;
+ Title.SetText(type.Name);
+ }
+ }
+} \ No newline at end of file
diff --git a/source/ui/elements/game/tooltips/TooltipDisplay.cs b/source/ui/elements/game/tooltips/TooltipDisplay.cs
new file mode 100644
index 0000000..2ff051d
--- /dev/null
+++ b/source/ui/elements/game/tooltips/TooltipDisplay.cs
@@ -0,0 +1,8 @@
+using Microsoft.Xna.Framework;
+
+namespace Celesteia.UI.Elements.Game.Tooltips {
+ public class TooltipDisplay : Container
+ {
+ public TooltipDisplay(Rect rect) : base(rect) {}
+ }
+} \ No newline at end of file