Skip to content

Commit

Permalink
Draw smaller icons over variable backgrounds. (ShadowTheAge#144)
Browse files Browse the repository at this point in the history
This adds a new preference (and alters the UI for an existing one) to
allow you to choose how much to scale down certain icons:

![image](https://github.com/have-fun-was-taken/yafc-ce/assets/21223975/b2335234-4ef0-41c9-ae27-7822cd9113b4)
The default is 90%, which is the middle size in this gif. The other two
sizes shown are 80% and 100%; 100% shows the issue where the background
color is not visible, hiding the link information.

![Untitled](https://github.com/have-fun-was-taken/yafc-ce/assets/21223975/48b36706-b765-4f38-bb71-6463d02676af)

The Desired products, Summary ingredients, and Extra products icons all
scale too.
  • Loading branch information
shpaass authored Jun 6, 2024
2 parents 3da3827 + c498c0e commit 9edb974
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 24 deletions.
4 changes: 4 additions & 0 deletions Yafc.Model/Model/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ public class ProjectPreferences(Project owner) : ModelObject<Project>(owner) {
public HashSet<FactorioObject> favorites { get; } = [];
/// <summary> Target technology for cost analysis - required item counts are estimated for researching this. If null, the is to research all finite technologies. </summary>
public Technology? targetTechnology { get; set; }
/// <summary>
/// The scale to use when drawing icons that have information stored in their background color, stored as a ratio from 0 to 1.
/// </summary>
public float iconScale { get; set; } = .9f;

protected internal override void AfterDeserialize() {
base.AfterDeserialize();
Expand Down
4 changes: 2 additions & 2 deletions Yafc.UI/ImGui/ImGuiUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,9 @@ public static ButtonEvent BuildButton(this ImGui gui, Icon icon, string text, Sc
return gui.BuildButton(gui.lastRect, normal, over, down);
}

public static bool WithTooltip(this ButtonEvent evt, ImGui gui, string tooltip) {
public static bool WithTooltip(this ButtonEvent evt, ImGui gui, string tooltip, Rect? rect = null) {
if (evt == ButtonEvent.MouseOver) {
gui.ShowTooltip(gui.lastRect, tooltip);
gui.ShowTooltip(rect ?? gui.lastRect, tooltip);
}

return evt;
Expand Down
41 changes: 33 additions & 8 deletions Yafc/Widgets/ImmediateWidgets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,23 @@ public enum GoodsWithAmountEvent {
}

public static class ImmediateWidgets {
public static void BuildFactorioObjectIcon(this ImGui gui, FactorioObject? obj, MilestoneDisplay display = MilestoneDisplay.Normal, float size = 2f) {
/// <summary>Draws the icon belonging to a <see cref="FactorioObject"/>, or an empty box as a placeholder if no object is available.</summary>
/// <param name="obj">Draw the icon for this object, or an empty box if this is <see langword="null"/>.</param>
/// <param name="useScale">If <see langword="true"/>, this icon will be displayed at <see cref="ProjectPreferences.iconScale"/>, instead of at 100% scale.</param>
public static void BuildFactorioObjectIcon(this ImGui gui, FactorioObject? obj, MilestoneDisplay display = MilestoneDisplay.Normal, float size = 2f, bool useScale = false) {
if (obj == null) {
gui.BuildIcon(Icon.Empty, size, SchemeColor.BackgroundTextFaint);
return;
}

var color = obj.IsAccessible() ? SchemeColor.Source : SchemeColor.SourceFaint;
gui.BuildIcon(obj.icon, size, color);
if (useScale) {
Rect rect = gui.AllocateRect(size, size, RectAlignment.Middle);
gui.DrawIcon(rect.Expand(size * (Project.current.preferences.iconScale - 1) / 2), obj.icon, color);
}
else {
gui.BuildIcon(obj.icon, size, color);
}
if (gui.isBuilding && display != MilestoneDisplay.None) {
bool contain = (display & MilestoneDisplay.Contained) != 0;
var milestone = Milestones.Instance.GetHighest(obj, display >= MilestoneDisplay.All);
Expand Down Expand Up @@ -85,8 +94,11 @@ public static bool BuildFactorioObjectButton(this ImGui gui, Rect rect, Factorio
return false;
}

public static bool BuildFactorioObjectButton(this ImGui gui, FactorioObject? obj, float size = 2f, MilestoneDisplay display = MilestoneDisplay.Normal, SchemeColor bgColor = SchemeColor.None, bool extendHeader = false) {
gui.BuildFactorioObjectIcon(obj, display, size);
/// <summary>Draws a button displaying the icon belonging to a <see cref="FactorioObject"/>, or an empty box as a placeholder if no object is available.</summary>
/// <param name="obj">Draw the icon for this object, or an empty box if this is <see langword="null"/>.</param>
/// <param name="useScale">If <see langword="true"/>, this icon will be displayed at <see cref="ProjectPreferences.iconScale"/>, instead of at 100% scale.</param>
public static bool BuildFactorioObjectButton(this ImGui gui, FactorioObject? obj, float size = 2f, MilestoneDisplay display = MilestoneDisplay.Normal, SchemeColor bgColor = SchemeColor.None, bool extendHeader = false, bool useScale = false) {
gui.BuildFactorioObjectIcon(obj, display, size, useScale);
return gui.BuildFactorioObjectButton(gui.lastRect, obj, bgColor, extendHeader);
}

Expand Down Expand Up @@ -175,11 +187,17 @@ public static void BuildInlineObjectListAndButtonWithNone<T>(this ImGui gui, ICo
}
}

public static bool BuildFactorioObjectWithAmount(this ImGui gui, FactorioObject? goods, float amount, UnitOfMeasure unit, SchemeColor bgColor = SchemeColor.None, SchemeColor textColor = SchemeColor.None) {
/// <summary>Draws a button displaying the icon belonging to a <see cref="FactorioObject"/>, or an empty box as a placeholder if no object is available.
/// Also draws a label under the button, containing the supplied <paramref name="amount"/>.</summary>
/// <param name="goods">Draw the icon for this object, or an empty box if this is <see langword="null"/>.</param>
/// <param name="amount">Display this value, formatted appropriately for <paramref name="unit"/>.</param>
/// <param name="unit">Use this unit of measure when formatting <paramref name="amount"/> for display.</param>
/// <param name="useScale">If <see langword="true"/>, this icon will be displayed at <see cref="ProjectPreferences.iconScale"/>, instead of at 100% scale.</param>
public static bool BuildFactorioObjectWithAmount(this ImGui gui, FactorioObject? goods, float amount, UnitOfMeasure unit, SchemeColor bgColor = SchemeColor.None, SchemeColor textColor = SchemeColor.None, bool useScale = true) {
using (gui.EnterFixedPositioning(3f, 3f, default)) {
gui.allocator = RectAllocator.Stretch;
gui.spacing = 0f;
bool clicked = gui.BuildFactorioObjectButton(goods, 3f, MilestoneDisplay.Contained, bgColor);
bool clicked = gui.BuildFactorioObjectButton(goods, 3f, MilestoneDisplay.Contained, bgColor, useScale: useScale);
if (goods != null) {
gui.BuildText(DataUtils.FormatAmount(amount, unit), Font.text, false, RectAlignment.Middle, textColor);
if (InputSystem.Instance.control && gui.BuildButton(gui.lastRect, SchemeColor.None, SchemeColor.Grey) == ButtonEvent.MouseOver) {
Expand Down Expand Up @@ -227,12 +245,19 @@ public static void BuildObjectSelectDropDown<T>(this ImGui gui, ICollection<T> l
public static void BuildObjectSelectDropDownWithNone<T>(this ImGui gui, ICollection<T> list, IComparer<T> ordering, Action<T?> selectItem, string header, float width = 20f, int count = 6, Func<T, string>? extra = null) where T : FactorioObject
=> gui.ShowDropDown(imGui => imGui.BuildInlineObjectListAndButtonWithNone(list, ordering, selectItem, header, count, extra), width);

public static GoodsWithAmountEvent BuildFactorioObjectWithEditableAmount(this ImGui gui, FactorioObject? obj, float amount, UnitOfMeasure unit, out float newAmount, SchemeColor color = SchemeColor.None) {
/// <summary>Draws a button displaying the icon belonging to a <see cref="FactorioObject"/>, or an empty box as a placeholder if no object is available.
/// Also draws an editable textbox under the button, containing the supplied <paramref name="amount"/>.</summary>
/// <param name="obj">Draw the icon for this object, or an empty box if this is <see langword="null"/>.</param>
/// <param name="useScale">If <see langword="true"/>, this icon will be displayed at <see cref="ProjectPreferences.iconScale"/>, instead of at 100% scale.</param>
/// <param name="amount">Display this value, formatted appropriately for <paramref name="unit"/>.</param>
/// <param name="unit">Use this unit of measure when formatting <paramref name="amount"/> for display.</param>
/// <param name="newAmount">The new value entered by the user, if this returns <see cref="GoodsWithAmountEvent.TextEditing"/>. Otherwise, the original <paramref name="amount"/>.</param>
public static GoodsWithAmountEvent BuildFactorioObjectWithEditableAmount(this ImGui gui, FactorioObject? obj, float amount, UnitOfMeasure unit, out float newAmount, SchemeColor color = SchemeColor.None, bool useScale = true) {
using var group = gui.EnterGroup(default, RectAllocator.Stretch, spacing: 0f);
group.SetWidth(3f);
newAmount = amount;
var evt = GoodsWithAmountEvent.None;
if (gui.BuildFactorioObjectButton(obj, 3f, MilestoneDisplay.Contained, color)) {
if (gui.BuildFactorioObjectButton(obj, 3f, MilestoneDisplay.Contained, color, useScale: useScale)) {
evt = GoodsWithAmountEvent.ButtonClick;
}

Expand Down
35 changes: 28 additions & 7 deletions Yafc/Windows/PreferencesScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,21 @@ public override void Build(ImGui gui) {
gui.BuildText("Fluid production/consumption:", Font.subheader);
BuildUnitPerTime(gui, true, prefs);

using (gui.EnterRow()) {
gui.BuildText("Pollution cost modifier (0 for off, 100% for old default)", Font.text, topOffset: 0.5f); ;
if (gui.BuildFloatInput(settings.PollutionCostModifier, out var pollutionCostModifier, UnitOfMeasure.Percent, new Padding(0.5f))) {
settings.RecordUndo().PollutionCostModifier = pollutionCostModifier;
gui.Rebuild();
}
}
drawInputRowWithTooltip(gui, "Pollution cost modifier", "0 for off, 100% for old default",
gui => {
if (gui.BuildFloatInput(settings.PollutionCostModifier, out float pollutionCostModifier, UnitOfMeasure.Percent, new Padding(0.5f))) {
settings.RecordUndo().PollutionCostModifier = pollutionCostModifier;
gui.Rebuild();
}
});

drawInputRowWithTooltip(gui, "Display scale for linkable icons", "Some mod icons have little or no transparency, hiding the background color. This setting reduces the size of icons that could hide link information.",
gui => {
if (gui.BuildFloatInput(prefs.iconScale, out float iconScale, UnitOfMeasure.Percent, new Padding(0.5f)) && iconScale > 0 && iconScale <= 1) {
prefs.RecordUndo().iconScale = iconScale;
gui.Rebuild();
}
});

ChooseObject(gui, "Default belt:", Database.allBelts, prefs.defaultBelt, s => {
prefs.RecordUndo().defaultBelt = s;
Expand Down Expand Up @@ -92,6 +100,19 @@ public override void Build(ImGui gui) {
if (settings.justChanged) {
Project.current.RecalculateDisplayPages();
}

static void drawInputRowWithTooltip(ImGui gui, string text, string tooltip, Action<ImGui> handleInput) {
using (gui.EnterRow()) {
gui.BuildText(text, topOffset: 0.5f);
gui.AllocateSpacing();
gui.allocator = RectAllocator.RightRow;
var rect = gui.AllocateRect(1, 1);
handleInput(gui);
rect = new Rect(rect.Center.X, gui.lastRect.Center.Y, 0, 0).Expand(.625f);
gui.DrawIcon(rect, Icon.Help, SchemeColor.BackgroundText);
gui.BuildButton(rect, SchemeColor.None, SchemeColor.Grey).WithTooltip(gui, tooltip, rect);
}
}
}

/// <summary>Add a GUI element that opens a popup to allow the user to choose from the <paramref name="list"/>, which triggers <paramref name="selectItem"/>.</summary>
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Windows/SelectMultiObjectPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static void Select<T>(IEnumerable<T> list, string header, Action<T> selec
}

protected override void NonNullElementDrawer(ImGui gui, FactorioObject element, int index) {
bool click = gui.BuildFactorioObjectButton(element, display: MilestoneDisplay.Contained, bgColor: results.Contains(element) ? SchemeColor.Primary : SchemeColor.None, extendHeader: extendHeader);
bool click = gui.BuildFactorioObjectButton(element, 2.5f, MilestoneDisplay.Contained, results.Contains(element) ? SchemeColor.Primary : SchemeColor.None, extendHeader, true);

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
2 changes: 1 addition & 1 deletion Yafc/Windows/SelectSingleObjectPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static void SelectWithNone<T>(IEnumerable<T> list, string header, Action<
=> Instance.Select(list, header, selectItem, ordering, (obj, mappedAction) => mappedAction(obj), true);

protected override void NonNullElementDrawer(ImGui gui, FactorioObject element, int index) {
if (gui.BuildFactorioObjectButton(element, display: MilestoneDisplay.Contained, extendHeader: extendHeader)) {
if (gui.BuildFactorioObjectButton(element, 2.5f, MilestoneDisplay.Contained, extendHeader: extendHeader, useScale: true)) {
CloseWithResult(element);
}
}
Expand Down
10 changes: 5 additions & 5 deletions Yafc/Workspace/ProductionTable/ProductionTableView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,15 +252,15 @@ public override void BuildElement(ImGui gui, RecipeRow recipe) {
using (var group = gui.EnterGroup(default, RectAllocator.Stretch, spacing: 0f)) {
group.SetWidth(3f);
if (recipe.fixedBuildings > 0) {
var evt = gui.BuildFactorioObjectWithEditableAmount(recipe.entity, recipe.fixedBuildings, UnitOfMeasure.None, out float newAmount);
var evt = gui.BuildFactorioObjectWithEditableAmount(recipe.entity, recipe.fixedBuildings, UnitOfMeasure.None, out float newAmount, useScale: false);
if (evt == GoodsWithAmountEvent.TextEditing) {
recipe.RecordUndo().fixedBuildings = newAmount;
}

clicked = evt == GoodsWithAmountEvent.ButtonClick;
}
else {
clicked = gui.BuildFactorioObjectWithAmount(recipe.entity, recipe.buildingCount, UnitOfMeasure.None) && recipe.recipe.crafters.Length > 0;
clicked = gui.BuildFactorioObjectWithAmount(recipe.entity, recipe.buildingCount, UnitOfMeasure.None, useScale: false) && recipe.recipe.crafters.Length > 0;
}

if (recipe.builtBuildings != null) {
Expand Down Expand Up @@ -480,7 +480,7 @@ public override void BuildElement(ImGui gui, RecipeRow recipe) {
using var grid = gui.EnterInlineGrid(3f);
if (recipe.parameters.modules.modules == null || recipe.parameters.modules.modules.Length == 0) {
grid.Next();
if (gui.BuildFactorioObjectWithAmount(null, 0, UnitOfMeasure.None) && recipe.hierarchyEnabled) {
if (gui.BuildFactorioObjectWithAmount(null, 0, UnitOfMeasure.None, useScale: false) && recipe.hierarchyEnabled) {
ShowModuleDropDown(gui, recipe);
}
}
Expand All @@ -491,13 +491,13 @@ public override void BuildElement(ImGui gui, RecipeRow recipe) {
wasBeacon = true;
if (recipe.parameters.modules.beacon != null) {
grid.Next();
if (gui.BuildFactorioObjectWithAmount(recipe.parameters.modules.beacon, recipe.parameters.modules.beaconCount, UnitOfMeasure.None)) {
if (gui.BuildFactorioObjectWithAmount(recipe.parameters.modules.beacon, recipe.parameters.modules.beaconCount, UnitOfMeasure.None, useScale: false)) {
ShowModuleDropDown(gui, recipe);
}
}
}
grid.Next();
if (gui.BuildFactorioObjectWithAmount(module, count, UnitOfMeasure.None)) {
if (gui.BuildFactorioObjectWithAmount(module, count, UnitOfMeasure.None, useScale: false)) {
ShowModuleDropDown(gui, recipe);
}
}
Expand Down
3 changes: 3 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
----------------------------------------------------------------------------------------------------------------------
Version: 0.7.1
Date: soon
Features:
- Allow configuring the size of icons that have backgrounds, since the icon may cover the entire
background area.
Changes:
- Update the detection of special recipes and items, to detect stacking from Deadlock's Beltboxes, caging
from Pyanodon, and pressurization from Pressurized Fluids.
Expand Down

0 comments on commit 9edb974

Please sign in to comment.