Skip to content

Commit

Permalink
[UI] Show warnings for goods on hover in addition to on click (shpaas…
Browse files Browse the repository at this point in the history
…s#279)

Closes shpaass#271. When creating a FactorioObjectButton, the caller can ask to
draw extra information below the header. The production table uses this
to display the link warnings.
  • Loading branch information
shpaass authored Sep 9, 2024
2 parents 79a40a4 + 3d1c00a commit 21cc8f9
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 37 deletions.
29 changes: 29 additions & 0 deletions Yafc.Model/Model/ProductionTableContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,35 @@ public enum Flags {
[SkipSerialization] public HashSet<RecipeRow> capturedRecipes { get; } = [];
internal int solverIndex;
public float dualValue { get; internal set; }

public IEnumerable<string> LinkWarnings {
get {
if (!flags.HasFlags(Flags.HasProduction)) {
yield return "This link has no production (Link ignored)";
}

if (!flags.HasFlags(Flags.HasConsumption)) {
yield return "This link has no consumption (Link ignored)";
}

if (flags.HasFlags(Flags.ChildNotMatched)) {
yield return "Nested table link has unmatched production/consumption. These unmatched products are not captured by this link.";
}

if (!flags.HasFlags(Flags.HasProductionAndConsumption) && owner.owner is RecipeRow recipeRow && recipeRow.FindLink(goods, out _)) {
yield return "Nested tables have their own set of links that DON'T connect to parent links. To connect this product to the outside, remove this link.";
}

if (flags.HasFlags(Flags.LinkRecursiveNotMatched)) {
if (notMatchedFlow <= 0f) {
yield return "YAFC was unable to satisfy this link (Negative feedback loop). This doesn't mean that this link is the problem, but it is part of the loop.";
}
else {
yield return "YAFC was unable to satisfy this link (Overproduction). You can allow overproduction for this link to solve the error.";
}
}
}
}
}

public record RecipeRowIngredient(Goods? Goods, float Amount, ProductionLink? Link, Goods[]? Variants) {
Expand Down
16 changes: 14 additions & 2 deletions Yafc/Widgets/ObjectTooltip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public ObjectTooltip() : base(new Padding(0f, 0f, 0f, 0.5f), 25f) { }
private void BuildHeader(ImGui gui) {
using (gui.EnterGroup(new Padding(1f, 0.5f), RectAllocator.LeftAlign, spacing: 0f)) {
string name = target.text;
if (tooltipOptions.ExtendHeader && target is not Goods) {
if (tooltipOptions.ShowTypeInHeader && target is not Goods) {
name = name + " (" + target.target.type + ")";
}

Expand Down Expand Up @@ -145,6 +145,8 @@ protected override void BuildContents(ImGui gui) {
private void BuildCommon(FactorioObject target, ImGui gui) {
BuildHeader(gui);
using (gui.EnterGroup(contentPadding)) {
tooltipOptions.DrawBelowHeader?.Invoke(gui);

if (InputSystem.Instance.control) {
gui.BuildText(target.typeDotName);
}
Expand Down Expand Up @@ -540,13 +542,23 @@ public struct ObjectTooltipOptions {
/// If <see langword="true"/> and the target object is not a <see cref="Goods"/>, this tooltip will specify the type of object.
/// e.g. "Radar" is the item, "Radar (Recipe)" is the recipe, and "Radar (Entity)" is the building.
/// </summary>
public bool ExtendHeader { get; set; }
public bool ShowTypeInHeader { get; set; }
/// <summary>
/// Gets or sets flags indicating where hints should be displayed in the tooltip.
/// </summary>
public HintLocations HintLocations { get; set; }
/// <summary>
/// Gets or sets a value that, if not null, will be called after drawing the tooltip header.
/// </summary>
public DrawBelowHeader? DrawBelowHeader { get; set; }

// Reduce boilerplate by permitting unambiguous and relatively obvious implicit conversions.
public static implicit operator ObjectTooltipOptions(HintLocations hintLocations) => new() { HintLocations = hintLocations };
public static implicit operator ObjectTooltipOptions(DrawBelowHeader drawBelowHeader) => new() { DrawBelowHeader = drawBelowHeader };
}

/// <summary>
/// Called to draw additional information in the tooltip after drawing the tooltip header.
/// </summary>
public delegate void DrawBelowHeader(ImGui gui);
}
2 changes: 1 addition & 1 deletion Yafc/Windows/DependencyExplorer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private void DrawFactorioObject(ImGui gui, FactorioId id) {
string text = fobj.locName + " (" + fobj.type + ")";
gui.RemainingRow(0.5f).BuildText(text, TextBlockDisplayStyle.WrappedText with { Color = fobj.IsAccessible() ? SchemeColor.BackgroundText : SchemeColor.BackgroundTextFaint });
}
if (gui.BuildFactorioObjectButtonBackground(gui.lastRect, fobj, tooltipOptions: new() { ExtendHeader = true }) == Click.Left) {
if (gui.BuildFactorioObjectButtonBackground(gui.lastRect, fobj, tooltipOptions: new() { ShowTypeInHeader = true }) == Click.Left) {
Change(fobj);
}
}
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Windows/SelectMultiObjectPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static void Select<T>(IEnumerable<T> list, string header, Action<T> selec

protected override void NonNullElementDrawer(ImGui gui, FactorioObject element) {
SchemeColor bgColor = results.Contains(element) ? SchemeColor.Primary : SchemeColor.None;
Click click = gui.BuildFactorioObjectButton(element, ButtonDisplayStyle.SelectObjectPanel(bgColor), new() { ExtendHeader = extendHeader });
Click click = gui.BuildFactorioObjectButton(element, ButtonDisplayStyle.SelectObjectPanel(bgColor), new() { ShowTypeInHeader = showTypeInHeader });

if (checkMark(element)) {
gui.DrawIcon(Rect.SideRect(gui.lastRect.TopLeft + new Vector2(1, 0), gui.lastRect.BottomRight - new Vector2(0, 1)), Icon.Check, SchemeColor.Green);
Expand Down
6 changes: 3 additions & 3 deletions Yafc/Windows/SelectObjectPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ public abstract class SelectObjectPanel<T> : PseudoScreenWithResult<T> {
private string? noneTooltip;
/// <summary>
/// If <see langword="true"/> and the object being hovered is not a <see cref="Goods"/>, the <see cref="ObjectTooltip"/> should specify the type of object.
/// See also <see cref="ObjectTooltipOptions.ExtendHeader"/>.
/// See also <see cref="ObjectTooltipOptions.ShowTypeInHeader"/>.
/// </summary>
protected bool extendHeader { get; private set; }
protected bool showTypeInHeader { get; private set; }

protected SelectObjectPanel() : base(40f) => list = new SearchableList<FactorioObject?>(30, new Vector2(2.5f, 2.5f), ElementDrawer, ElementFilter);

Expand All @@ -39,7 +39,7 @@ public abstract class SelectObjectPanel<T> : PseudoScreenWithResult<T> {
protected void Select<U>(IEnumerable<U> list, string header, Action<U?> selectItem, IComparer<U>? ordering, Action<T?, Action<FactorioObject?>> mapResult, bool allowNone, string? noneTooltip = null) where U : FactorioObject {
_ = MainScreen.Instance.ShowPseudoScreen(this);
this.noneTooltip = noneTooltip;
extendHeader = typeof(U) == typeof(FactorioObject);
showTypeInHeader = typeof(U) == typeof(FactorioObject);
List<U?> data = new List<U?>(list);
ordering ??= DataUtils.DefaultOrdering;
data.Sort(ordering!); // null-forgiving: We don't have any nulls in the list yet.
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Windows/SelectSingleObjectPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static void SelectWithNone<T>(IEnumerable<T> list, string header, Action<
=> Instance.Select(list, header, selectItem, ordering, (obj, mappedAction) => mappedAction(obj), true, noneTooltip);

protected override void NonNullElementDrawer(ImGui gui, FactorioObject element) {
if (gui.BuildFactorioObjectButton(element, ButtonDisplayStyle.SelectObjectPanel(SchemeColor.None), tooltipOptions: new() { ExtendHeader = extendHeader }) == Click.Left) {
if (gui.BuildFactorioObjectButton(element, ButtonDisplayStyle.SelectObjectPanel(SchemeColor.None), tooltipOptions: new() { ShowTypeInHeader = showTypeInHeader }) == Click.Left) {
CloseWithResult(element);
}
}
Expand Down
41 changes: 18 additions & 23 deletions Yafc/Workspace/ProductionTable/ProductionTableView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -777,29 +777,8 @@ void dropDownContent(ImGui gui) {
}

if (link != null) {
if (!link.flags.HasFlags(ProductionLink.Flags.HasProduction)) {
gui.BuildText("This link has no production (Link ignored)", TextBlockDisplayStyle.ErrorText);
}

if (!link.flags.HasFlags(ProductionLink.Flags.HasConsumption)) {
gui.BuildText("This link has no consumption (Link ignored)", TextBlockDisplayStyle.ErrorText);
}

if (link.flags.HasFlags(ProductionLink.Flags.ChildNotMatched)) {
gui.BuildText("Nested table link have unmatched production/consumption. These unmatched products are not captured by this link.", TextBlockDisplayStyle.ErrorText);
}

if (!link.flags.HasFlags(ProductionLink.Flags.HasProductionAndConsumption) && link.owner.owner is RecipeRow recipeRow && recipeRow.FindLink(link.goods, out _)) {
gui.BuildText("Nested tables have their own set of links that DON'T connect to parent links. To connect this product to the outside, remove this link", TextBlockDisplayStyle.ErrorText);
}

if (link.flags.HasFlags(ProductionLink.Flags.LinkRecursiveNotMatched)) {
if (link.notMatchedFlow <= 0f) {
gui.BuildText("YAFC was unable to satisfy this link (Negative feedback loop). This doesn't mean that this link is the problem, but it is part of the loop.", TextBlockDisplayStyle.ErrorText);
}
else {
gui.BuildText("YAFC was unable to satisfy this link (Overproduction). You can allow overproduction for this link to solve the error.", TextBlockDisplayStyle.ErrorText);
}
foreach (string warning in link.LinkWarnings) {
gui.BuildText(warning, TextBlockDisplayStyle.ErrorText);
}
}

Expand Down Expand Up @@ -1017,6 +996,14 @@ private void DrawDesiredProduct(ImGui gui, ProductionLink element) {
}

ObjectTooltipOptions tooltipOptions = element.amount < 0 ? HintLocations.OnConsumingRecipes : HintLocations.OnProducingRecipes;
if (element.LinkWarnings is IEnumerable<string> warnings) {
tooltipOptions.DrawBelowHeader = gui => {
foreach (string warning in warnings) {
gui.BuildText(warning, TextBlockDisplayStyle.ErrorText);
}
};
}

DisplayAmount amount = new(element.amount, element.goods.flowUnitOfMeasure);
switch (gui.BuildFactorioObjectWithEditableAmount(element.goods, amount, ButtonDisplayStyle.ProductionTableScaled(iconColor), tooltipOptions: tooltipOptions)) {
case GoodsWithAmountEvent.LeftButtonClick:
Expand Down Expand Up @@ -1075,6 +1062,14 @@ private void BuildGoodsIcon(ImGui gui, Goods? goods, ProductionLink? link, float
GoodsWithAmountEvent evt;
DisplayAmount displayAmount = new(amount, goods?.flowUnitOfMeasure ?? UnitOfMeasure.None);

if (link?.LinkWarnings is IEnumerable<string> warnings) {
tooltipOptions.DrawBelowHeader += gui => {
foreach (string warning in warnings) {
gui.BuildText(warning, TextBlockDisplayStyle.ErrorText);
}
};
}

if (recipe != null && recipe.fixedBuildings > 0
&& ((dropdownType == ProductDropdownType.Fuel && recipe.fixedFuel)
|| (dropdownType == ProductDropdownType.Ingredient && recipe.fixedIngredient == goods)
Expand Down
10 changes: 4 additions & 6 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@
// Internal changes:
// Changes to the code that do not affect the behavior of the program.
----------------------------------------------------------------------------------------------------------------------
Version: 0.10.1
Date:
Bugfixes:
- Fixed recipes now become accessible when their crafter does.
----------------------------------------------------------------------------------------------------------------------
Version: 0.10.0
Date:
Feature:
Features:
- Add OSX-arm64 build.
- Display link warnings in both the tooltips and the dropdowns.
Bugfixes:
- Fixed recipes now become accessible when their crafter does.
----------------------------------------------------------------------------------------------------------------------
Version: 0.9.1
Date: September 8th 2024
Expand Down

0 comments on commit 21cc8f9

Please sign in to comment.