Skip to content

Commit

Permalink
Merge pull request slothsoft#60 from slothsoft/feature/more-info
Browse files Browse the repository at this point in the history
More Info
  • Loading branch information
slothsoft authored Nov 13, 2022
2 parents c1f6f3f + 663902f commit 43023c3
Show file tree
Hide file tree
Showing 22 changed files with 514 additions and 49 deletions.
168 changes: 168 additions & 0 deletions Informant.Test/Api/PositionTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
using Microsoft.Xna.Framework;
using NUnit.Framework;
using Slothsoft.Informant.Api;

namespace InformantTest.Api;

public class PositionTest {

[Test]
[TestCaseSource(nameof(_bigTooltipSmallIconCases))]
public void CalculatePosition(string displayName, IPosition position, Rectangle tooltipBounds, Vector2 iconSize, Rectangle expectedPosition) {
Assert.AreEqual(expectedPosition, position.CalculateIconPosition(tooltipBounds, iconSize), $"Position was wrong for {displayName}");
}

private static object[] _bigTooltipSmallIconCases =
{
new object[] {
"TopLeft",
IPosition.TopLeft,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 200, 5, 10)
},
new object[] {
"TopCenter",
IPosition.TopCenter,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(117, 200, 5, 10)
},
new object[] {
"TopRight",
IPosition.TopRight,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(135, 200, 5, 10)
},
new object[] {
"CenterLeft",
IPosition.CenterLeft,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 210, 5, 10)
},
new object[] {
"Center",
IPosition.Center,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(117, 210, 5, 10)
},
new object[] {
"CenterRight",
IPosition.CenterRight,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(135, 210, 5, 10)
},
new object[] {
"BottomLeft",
IPosition.BottomLeft,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 220, 5, 10)
},
new object[] {
"BottomCenter",
IPosition.BottomCenter,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(117, 220, 5, 10)
},
new object[] {
"BottomRight",
IPosition.BottomRight,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(135, 220, 5, 10)
},
new object[] {
"Fill",
IPosition.Fill,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 200, 40, 30)
},
};

[Test]
[TestCaseSource(nameof(_tooltipPosition))]
public void CalculateTooltipPosition(string displayName, IPosition position, Rectangle tooltipBounds, Vector2 iconSize, Rectangle expectedPosition) {
Assert.AreEqual(expectedPosition, position.CalculateTooltipPosition(tooltipBounds, iconSize), $"Position was wrong for {displayName}");
}

private static object[] _tooltipPosition =
{
new object[] {
"TopLeft",
IPosition.TopLeft,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(95, 200, 45, 30)
},
new object[] {
"TopCenter",
IPosition.TopCenter,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 190, 40, 40),
},
new object[] {
"TopRight",
IPosition.TopRight,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 200, 45, 30)
},
new object[] {
"CenterLeft",
IPosition.CenterLeft,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(95, 200, 45, 30)
},
new object[] {
"Center",
IPosition.Center,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 200, 40, 30),
},
new object[] {
"CenterRight",
IPosition.CenterRight,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 200, 45, 30)
},
new object[] {
"BottomLeft",
IPosition.BottomLeft,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(95, 200, 45, 30)
},
new object[] {
"BottomCenter",
IPosition.BottomCenter,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 200, 40, 40),
},
new object[] {
"BottomRight",
IPosition.BottomRight,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 200, 45, 30)
},
new object[] {
"Fill",
IPosition.Fill,
new Rectangle(100, 200, 40, 30),
new Vector2(5, 10),
new Rectangle(100, 200, 40, 30)
},
};
}
2 changes: 1 addition & 1 deletion Informant.Test/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"Name": "Informant.Test",
"Author": "Slothsoft",
"Version": "1.2.2",
"Version": "1.3.0",
"Description": "Test Project.",
"UniqueID": "Slothsoft.Informant.Test",
"EntryDll": "Informant.Test.dll",
Expand Down
108 changes: 108 additions & 0 deletions Informant/Api/IPosition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using Microsoft.Xna.Framework;
using Vector2 = Microsoft.Xna.Framework.Vector2;

namespace Slothsoft.Informant.Api;

public interface IPosition {

/// <summary>
/// Displays the icon to the left of the text, aligned at the top.
/// </summary>
public static readonly IPosition TopLeft = new Position(Position.Leading, Position.Leading);
/// <summary>
/// Displays the icon to the left of the text, aligned at the center.
/// </summary>
public static readonly IPosition CenterLeft = new Position(Position.Leading, Position.Middle);
/// <summary>
/// Displays the icon to the left of the text, aligned at the top.
/// </summary>
public static readonly IPosition BottomLeft = new Position(Position.Leading, Position.Trailing);

/// <summary>
/// Displays the icon to the right of the text, aligned at the top.
/// </summary>
public static readonly IPosition TopRight = new Position(Position.Trailing, Position.Leading);
/// <summary>
/// Displays the icon to the right of the text, aligned at the center.
/// </summary>
public static readonly IPosition CenterRight = new Position(Position.Trailing, Position.Middle);
/// <summary>
/// Displays the icon to the right of the text, aligned at the bottom.
/// </summary>
public static readonly IPosition BottomRight = new Position(Position.Trailing, Position.Trailing);

/// <summary>
/// Displays the icon at the top of the text, aligned at the center.
/// </summary>
public static readonly IPosition TopCenter = new Position(Position.Middle, Position.Leading);
/// <summary>
/// Displays the icon centered below the text.
/// </summary>
public static readonly IPosition Center = new Position(Position.Middle, Position.Middle);
/// <summary>
/// Displays the icon at the bottom of the text, aligned at the center.
/// </summary>
public static readonly IPosition BottomCenter = new Position(Position.Middle, Position.Trailing);

/// <summary>
/// Displays the icon filled below the text.
/// </summary>
public static readonly IPosition Fill = new Position(Position.Fill, Position.Fill);

Rectangle CalculateIconPosition(Rectangle tooltipBounds, Vector2 iconSize);

Rectangle CalculateTooltipPosition(Rectangle tooltipBounds, Vector2 iconSize);

private class Position : IPosition {

internal const int Leading = 0;
internal const int Middle = 1;
internal const int Trailing = 2;
internal const int Fill = 3;

private readonly int _horizontalPosition;
private readonly int _verticalPosition;

public Position(int horizontalPosition, int verticalPosition) {
_horizontalPosition = horizontalPosition;
_verticalPosition = verticalPosition;
}

public Rectangle CalculateIconPosition(Rectangle tooltipBounds, Vector2 iconSize) {
var usedIconSizeX = _horizontalPosition == Fill ? tooltipBounds.Width : iconSize.X;
var usedIconSizeY = _verticalPosition == Fill ? tooltipBounds.Height : iconSize.Y;
return new Rectangle(
CalculateIconPosition(_horizontalPosition, tooltipBounds.X, tooltipBounds.Width, iconSize.X),
CalculateIconPosition(_verticalPosition, tooltipBounds.Y, tooltipBounds.Height, iconSize.Y),
(int) usedIconSizeX,
(int) usedIconSizeY
);
}

private int CalculateIconPosition(int position, int tooltipPosition, int tooltipSize, float iconSize) {
return position switch {
Leading => tooltipPosition,
Middle => tooltipPosition + (int) (tooltipSize - iconSize) / 2,
Trailing => tooltipPosition + tooltipSize - (int) iconSize,
_ => tooltipPosition
};
}

public Rectangle CalculateTooltipPosition(Rectangle tooltipBounds, Vector2 iconSize) {
return new Rectangle(
CalculateTooltipPosition(_horizontalPosition is Leading, tooltipBounds.X, iconSize.X),
CalculateTooltipPosition(_horizontalPosition is Middle && _verticalPosition is Leading, tooltipBounds.Y, iconSize.Y),
CalculateTooltipSize(_horizontalPosition is Leading or Trailing, tooltipBounds.Width, iconSize.X),
CalculateTooltipSize(_horizontalPosition is Middle && _verticalPosition is Leading or Trailing, tooltipBounds.Height, iconSize.Y)
);
}

private static int CalculateTooltipPosition(bool expand, int tooltipPosition, float iconSize) {
return expand ? tooltipPosition - (int) iconSize : tooltipPosition;
}

private static int CalculateTooltipSize(bool expand, int tooltipSize, float iconSize) {
return expand ? tooltipSize + (int) iconSize : tooltipSize;
}
}
}
48 changes: 48 additions & 0 deletions Informant/Api/Icon.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Slothsoft.Informant.Api;

/// <summary>
/// All information needed to display an icon somewhere.
/// </summary>
/// <param name="Texture">the texture to display.</param>
public record Icon(Texture2D Texture) {
public static Icon ForObject(SObject obj, IPosition? position = null, Vector2? iconSize = null) {
return ForParentSheetIndex(obj.ParentSheetIndex, obj.bigCraftable.Value, position, iconSize);
}

public static Icon ForParentSheetIndex(int parentSheetIndex, bool bigCraftable, IPosition? position = null, Vector2? iconSize = null) {
position ??= IPosition.TopRight;
iconSize ??= new Vector2(Game1.tileSize, Game1.tileSize);

if (bigCraftable) {
return new Icon(Game1.bigCraftableSpriteSheet) {
SourceRectangle = SObject.getSourceRectForBigCraftable(parentSheetIndex),
Position = position,
IconSize = iconSize,
};
}
return new Icon(Game1.objectSpriteSheet) {
SourceRectangle = Game1.getSourceRectForStandardTileSheet(Game1.objectSpriteSheet, parentSheetIndex, 16, 16),
Position = position,
IconSize = iconSize,
};
}

public Rectangle? SourceRectangle { get; init; }
public IPosition? Position { get; init; }
public Vector2? IconSize { get; init; }

internal Rectangle NullSafeSourceRectangle => SourceRectangle ?? new Rectangle(0, 0, Texture.Width, Texture.Height);
private IPosition NullSafePosition => Position ?? IPosition.TopLeft;
private Vector2 NullSafeIconSize => IconSize ?? new Vector2(NullSafeSourceRectangle.Width, NullSafeSourceRectangle.Height);

internal Rectangle CalculateIconPosition(Rectangle tooltipBounds) {
return NullSafePosition.CalculateIconPosition(tooltipBounds, NullSafeIconSize);
}

internal Rectangle CalculateTooltipPosition(Rectangle tooltipBounds) {
return NullSafePosition.CalculateTooltipPosition(tooltipBounds, NullSafeIconSize);
}
}
2 changes: 1 addition & 1 deletion Informant/Api/Tooltip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
/// </summary>
/// <param name="Text">the multiline text to display.</param>
public record Tooltip(string Text) {

public Icon? Icon { get; init; }
}
32 changes: 32 additions & 0 deletions Informant/Implementation/Decorator/ShippingBinDecorator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Microsoft.Xna.Framework.Graphics;
using Slothsoft.Informant.Api;

namespace Slothsoft.Informant.Implementation.Decorator;

internal class ShippingBinDecorator : IDecorator<Item> {

private static Texture2D? _shippingBin;

private readonly IModHelper _modHelper;

public ShippingBinDecorator(IModHelper modHelper) {
_modHelper = modHelper;
_shippingBin ??= modHelper.ModContent.Load<Texture2D>("assets/shipping_bin.png");
}

public string Id => "shipping";
public string DisplayName => _modHelper.Translation.Get("ShippingBinDecorator");
public string Description => _modHelper.Translation.Get("ShippingBinDecorator.Description");

public bool HasDecoration(Item input) {
if (_shippingBin != null && input is SObject obj && !obj.bigCraftable.Value) {
return obj.countsForShippedCollection() &&
(!Game1.player.basicShipped.ContainsKey(obj.ParentSheetIndex) || Game1.player.basicShipped[obj.ParentSheetIndex] == 0);
}
return false;
}

public Decoration Decorate(Item input) {
return new Decoration(_shippingBin!);
}
}
Loading

0 comments on commit 43023c3

Please sign in to comment.