forked from slothsoft/stardew-informant
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request slothsoft#60 from slothsoft/feature/more-info
More Info
- Loading branch information
Showing
22 changed files
with
514 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
Informant/Implementation/Decorator/ShippingBinDecorator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!); | ||
} | ||
} |
Oops, something went wrong.