Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Yafc.Model/Data/DataClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Linq;
using System.Runtime.CompilerServices;
using Yafc.I18n;
using Yafc.UI;
[assembly: InternalsVisibleTo("Yafc.Parser")]

namespace Yafc.Model;
Expand Down Expand Up @@ -39,7 +38,12 @@ public abstract class FactorioObject : IFactorioObjectWrapper, IComparable<Facto
public string locName { get; internal set; } = null!; // null-forgiving: Copied from name if still null at the end of CalculateMaps
public string? locDescr { get; internal set; }
internal FactorioIconPart[]? iconSpec { get; set; }
public Icon icon { get; internal set; }
/// <summary>
/// Integer icon handle assigned during data loading.
/// This value matches the numeric value of <c>Yafc.UI.Icon</c>
/// and should only be interpreted in the UI layer via <c>GetIcon()</c>.
/// </summary>
public int iconId { get; internal set; }
public FactorioId id { get; internal set; }
internal abstract FactorioObjectSortOrder sortingOrder { get; }
public FactorioObjectSpecialType specialType { get; internal set; }
Expand Down
3 changes: 0 additions & 3 deletions Yafc.Model/Data/DataUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,6 @@ public int Compare(T? x, T? y) {
/// but will appear as only producing U-235 and consuming U-238 when <see langword="true"/>.
/// </summary>
public static bool netProduction { get; internal set; }
public static Icon NoFuelIcon { get; internal set; }
public static Icon WarningIcon { get; internal set; }
public static Icon HandIcon { get; internal set; }

public static readonly Random random = new Random();

Expand Down
17 changes: 4 additions & 13 deletions Yafc.Model/Model/ProductionSummary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,10 @@ protected internal override void AfterDeserialize() {
[SkipSerialization] public Dictionary<IObjectWithQuality<Goods>, float> flow { get; } = [];
private bool needRefreshFlow = true;

public Icon icon {
get {
if (subgroup != null) {
return Icon.Folder;
}

if (page?.page == null) {
return Icon.Warning;
}

return page.page.icon?.icon ?? Icon.None;
}
}
/// <summary>True when this entry represents a folder/subgroup rather than a project page.</summary>
public bool IsSubgroup => subgroup != null;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public bool IsSubgroup => subgroup != null;
[MemberNotNullWhen(true, nameof(subgroup))]
public bool IsSubgroup => subgroup != null;

(Note that this also needs an additional using directive.)

/// <summary>True when this entry's referenced page has been removed or could not be found.</summary>
public bool IsMissingPage => !IsSubgroup && page?.page == null;

public string name {
get {
Expand Down
15 changes: 8 additions & 7 deletions Yafc.Parser/Data/FactorioDataDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,10 @@ private void RenderIcons() {
cache[(".", digit.ToString())] = SDL_image.IMG_Load("Data/Digits/" + digit + ".png");
}

DataUtils.NoFuelIcon = CreateSimpleIcon(cache, "fuel-icon-red");
DataUtils.WarningIcon = CreateSimpleIcon(cache, "warning-icon");
DataUtils.HandIcon = CreateSimpleIcon(cache, "hand");
SystemIcons.Initialize(
noFuelIcon: CreateSimpleIcon(cache, "fuel-icon-red"),
warningIcon: CreateSimpleIcon(cache, "warning-icon"),
handIcon: CreateSimpleIcon(cache, "hand"));

Dictionary<string, Icon> simpleSpritesCache = [];
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Dictionary<string, Icon> simpleSpritesCache = [];
Dictionary<string, int> simpleSpritesCache = [];

int rendered = 0;
Expand All @@ -246,23 +247,23 @@ private void RenderIcons() {
bool simpleSprite = o.iconSpec.Length == 1 && o.iconSpec[0].IsSimple();

if (simpleSprite && simpleSpritesCache.TryGetValue(o.iconSpec[0].path, out var icon)) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (simpleSprite && simpleSpritesCache.TryGetValue(o.iconSpec[0].path, out var icon)) {
if (simpleSprite && simpleSpritesCache.TryGetValue(o.iconSpec[0].path, out int iconId)) {

o.icon = icon;
o.iconId = (int)icon;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
o.iconId = (int)icon;
o.iconId = iconId;

continue;
}

try {
o.icon = CreateIconFromSpec(cache, o.iconSpec);
o.iconId = (int)CreateIconFromSpec(cache, o.iconSpec);

if (simpleSprite) {
simpleSpritesCache[o.iconSpec[0].path] = o.icon;
simpleSpritesCache[o.iconSpec[0].path] = (Icon)o.iconId;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
simpleSpritesCache[o.iconSpec[0].path] = (Icon)o.iconId;
simpleSpritesCache[o.iconSpec[0].path] = o.iconId;

}
}
catch (Exception ex) {
Console.Error.WriteException(ex);
}
}
else if (o is Recipe recipe && recipe.mainProduct != null) {
o.icon = recipe.mainProduct.icon;
o.iconId = recipe.mainProduct.iconId;
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions Yafc.UI/Core/SystemIcons.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace Yafc.UI;

/// <summary>
/// Holds the set of game-sourced system icons (e.g. fuel, warning, hand) that are
/// rendered from Factorio's own sprite files during the data loading phase.
/// These are distinct from the built-in YAFC vector icons defined in <see cref="Icon"/>.
/// </summary>
public static class SystemIcons {
/// <summary>
/// The icon used to indicate a missing or invalid fuel source.
/// Set during data loading; no UI consumer yet (pre-existing).
/// </summary>
public static Icon NoFuelIcon { get; private set; }

/// <summary>
/// The icon used to display a general warning.
/// Set during data loading; no UI consumer yet (pre-existing).
/// </summary>
public static Icon WarningIcon { get; private set; }

/// <summary>The hand/grab icon used to mark certain special goods (e.g. void energy).</summary>
public static Icon HandIcon { get; private set; }

/// <summary>
/// Initializes the set of game-sourced system icons after they are rendered from Factorio assets.
/// </summary>
public static void Initialize(Icon noFuelIcon, Icon warningIcon, Icon handIcon) {
NoFuelIcon = noFuelIcon;
WarningIcon = warningIcon;
HandIcon = handIcon;
}
}

19 changes: 19 additions & 0 deletions Yafc/Widgets/FactorioObjectIconExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Yafc.Model;
using Yafc.UI;

namespace Yafc;

/// <summary>
/// Extension methods that bridge domain objects (<see cref="FactorioObject"/>) to their
/// UI representation (<see cref="Icon"/>), keeping the domain layer free of UI concerns.
/// This bridge currently lives in the app layer because <c>Yafc.UI</c> does not reference
/// <c>Yafc.Model</c>; move it once dependency boundaries are reworked.
/// </summary>
public static class FactorioObjectIconExtensions {
/// <summary>
/// Returns the <see cref="Icon"/> value associated with this <see cref="FactorioObject"/>.
/// The domain object stores this as an integer handle (<see cref="FactorioObject.iconId"/>);
/// this method converts it to the <see cref="Icon"/> enum for rendering.
/// </summary>
public static Icon GetIcon(this FactorioObject obj) => (Icon)obj.iconId;
}
8 changes: 4 additions & 4 deletions Yafc/Widgets/ImmediateWidgets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ public static void BuildFactorioObjectIcon(this ImGui gui, IFactorioObjectWrappe
SchemeColor color = (obj.target.IsAccessible() || displayStyle.AlwaysAccessible) ? SchemeColor.Source : SchemeColor.SourceFaint;
if (displayStyle.UseScaleSetting) {
Rect rect = gui.AllocateRect(displayStyle.Size, displayStyle.Size, RectAlignment.Middle);
gui.DrawIcon(rect.Expand(displayStyle.Size * (Project.current.preferences.iconScale - 1) / 2), obj.target.icon, color);
gui.DrawIcon(rect.Expand(displayStyle.Size * (Project.current.preferences.iconScale - 1) / 2), obj.target.GetIcon(), color);
}
else {
gui.BuildIcon(obj.target.icon, displayStyle.Size, color);
gui.BuildIcon(obj.target.GetIcon(), displayStyle.Size, color);
}
if (gui.isBuilding && displayStyle.MilestoneDisplay != MilestoneDisplay.None
&& (obj.target.IsAccessible() || Project.current.preferences.showMilestoneOnInaccessible)) {
Expand All @@ -86,7 +86,7 @@ public static void BuildFactorioObjectIcon(this ImGui gui, IFactorioObjectWrappe
Vector2 size = new Vector2(displayStyle.Size / 2f);
var delta = contain ? size : size / 2f;
Rect milestoneIcon = new Rect(gui.lastRect.BottomRight - delta, size);
var icon = milestone == Database.voidEnergy.target ? DataUtils.HandIcon : milestone.icon;
var icon = milestone == Database.voidEnergy.target ? SystemIcons.HandIcon : milestone.GetIcon();
gui.DrawIcon(milestoneIcon, icon, color);
}
}
Expand All @@ -97,7 +97,7 @@ public static void BuildFactorioObjectIcon(this ImGui gui, IFactorioObjectWrappe
Vector2 delta = new(0, size.Y);
Rect qualityRect = new Rect(gui.lastRect.BottomLeft - delta, size);

gui.DrawIcon(qualityRect, quality.icon, SchemeColor.Source);
gui.DrawIcon(qualityRect, quality.GetIcon(), SchemeColor.Source);
}
if (gui.isBuilding && obj.target is Item { baseSpoilTime: > 0 } or Entity { baseSpoilTime: > 0 }) {
Vector2 size = new Vector2(displayStyle.Size / 2.5f);
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Widgets/MainScreenTabBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private void BuildContents(ImGui gui) {
using (gui.EnterGroup(new Padding(0.5f, 0.2f, 0.2f, 0.5f))) {
gui.spacing = 0.2f;
if (page.icon != null) {
gui.BuildIcon(page.icon.icon);
gui.BuildIcon(page.icon.GetIcon());
}
else {
_ = gui.AllocateRect(0f, 1.5f);
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Widgets/ObjectTooltip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ private void BuildHeader(ImGui gui) {
goto doneDrawing;
}
if (milestoneMask[maskBit]) {
gui.BuildIcon(milestones.Current.icon, 1f, SchemeColor.Source);
gui.BuildIcon(milestones.Current.GetIcon(), 1f, SchemeColor.Source);
j++;
}

Expand Down
4 changes: 2 additions & 2 deletions Yafc/Windows/MainScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private void ReRunAnalysis() {
private void BuildPage(ImGui gui, ProjectPage element, int index) {
using (gui.EnterGroup(new Padding(1f, 0.25f), RectAllocator.LeftRow)) {
if (element.icon != null) {
gui.BuildIcon(element.icon.icon);
gui.BuildIcon(element.icon.GetIcon());
}

gui.RemainingRow().BuildText(element.name, TextBlockDisplayStyle.Default(element.visible ? SchemeColor.BackgroundText : SchemeColor.BackgroundTextFaint));
Expand Down Expand Up @@ -301,7 +301,7 @@ private void BuildPage(ImGui gui) {
else {
if (gui.isBuilding && Database.objectsByTypeName.TryGetValue("Entity.compilatron", out var compilatron)) {
gui.AllocateSpacing((pageVisibleSize.Y - 3f) / 2);
gui.BuildIcon(compilatron.icon, 3f);
gui.BuildIcon(compilatron.GetIcon(), 3f);
}
}
}
Expand Down
26 changes: 14 additions & 12 deletions Yafc/Workspace/ProductionSummary/ProductionSummaryView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ public override void BuildHeader(ImGui gui) { }
public override void BuildElement(ImGui gui, ProductionSummaryEntry row) {
gui.allocator = RectAllocator.Center;
gui.spacing = 0f;
if (row.subgroup != null) {
if (gui.BuildButton(row.subgroup.expanded ? Icon.ChevronDown : Icon.ChevronRight)) {
row.subgroup.RecordChange().expanded = !row.subgroup.expanded;
if (row.IsSubgroup) {
var subgroup = row.subgroup!; // IsSubgroup guarantees subgroup != null
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var subgroup = row.subgroup!; // IsSubgroup guarantees subgroup != null
var subgroup = row.subgroup;

if (gui.BuildButton(subgroup.expanded ? Icon.ChevronDown : Icon.ChevronRight)) {
subgroup.RecordChange().expanded = !subgroup.expanded;
view.flatHierarchy.SetData(view.model.group);
}
}
Expand Down Expand Up @@ -75,21 +76,22 @@ private GuiBuilder AddProductionTableDropdown(SearchableList<ProjectPage> pagesD
public override void BuildElement(ImGui gui, ProductionSummaryEntry entry) {
gui.allocator = RectAllocator.LeftAlign;

if (entry.subgroup != null) {
if (entry.subgroup.expanded) {
BuildButtons(gui, 1.5f, entry.subgroup);
if (entry.IsSubgroup) {
var subgroup = entry.subgroup!; // IsSubgroup guarantees subgroup != null
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var subgroup = entry.subgroup!; // IsSubgroup guarantees subgroup != null
var subgroup = entry.subgroup;

if (subgroup.expanded) {
BuildButtons(gui, 1.5f, subgroup);
}
else {
if (gui.BuildTextInput(entry.subgroup.name, out string newText, LSs.LegacySummaryGroupNameHint, delayed: true)) {
entry.subgroup.RecordUndo().name = newText;
if (gui.BuildTextInput(subgroup.name, out string newText, LSs.LegacySummaryGroupNameHint, delayed: true)) {
subgroup.RecordUndo().name = newText;
}
}
}
else if (entry.page != null) { // The constructor should have thrown if this check fails, but it helps the nullability analysis
using (gui.EnterGroup(new Padding(0.3f), RectAllocator.LeftRow, SchemeColor.None, 0.2f)) {
var icon = entry.icon;
Icon icon = entry.IsMissingPage ? Icon.Warning : entry.page.page!.icon?.GetIcon() ?? Icon.None;
if (icon != Icon.None) {
gui.BuildIcon(entry.icon);
gui.BuildIcon(icon);
}

gui.BuildText(entry.name);
Expand Down Expand Up @@ -129,7 +131,7 @@ public override void BuildElement(ImGui gui, ProductionSummaryEntry entry) {
private static VirtualScrollList<ProjectPage>.Drawer PagesDropdownDrawer(ProductionSummaryGroup group) => (gui, element, _) => {
using (gui.EnterGroup(new Padding(1f, 0.25f), RectAllocator.LeftRow)) {
if (element.icon != null) {
gui.BuildIcon(element.icon.icon);
gui.BuildIcon(element.icon.GetIcon());
}

gui.RemainingRow().BuildText(element.name, TextBlockDisplayStyle.Default(element.visible ? SchemeColor.BackgroundText : SchemeColor.BackgroundTextFaint));
Expand Down Expand Up @@ -189,7 +191,7 @@ public override void BuildElement(ImGui gui, ProductionSummaryEntry data) {

if (!view.model.columnsExist.Contains(goods)) {
grid.Next();
var evt = gui.BuildButton(goods.target.icon, amount > 0f ? SchemeColor.Green : SchemeColor.None, size: 1.5f);
var evt = gui.BuildButton(goods.target.GetIcon(), amount > 0f ? SchemeColor.Green : SchemeColor.None, size: 1.5f);
if (evt == ButtonEvent.Click) {
view.AddOrRemoveColumn(goods);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ private void ListDrawer(ImGui gui, KeyValuePair<EntityCrafter, BeaconOverrideCon
}
}
});
gui.DrawIcon(new(gui.lastRect.X, gui.lastRect.Y, 1.25f, 1.25f), config.beacon.target.icon, SchemeColor.Source);
gui.DrawIcon(new(gui.lastRect.TopRight - new Vector2(1.25f, 0), new Vector2(1.25f, 1.25f)), config.beaconModule.target.icon, SchemeColor.Source);
gui.DrawIcon(new(gui.lastRect.X, gui.lastRect.Y, 1.25f, 1.25f), config.beacon.target.GetIcon(), SchemeColor.Source);
gui.DrawIcon(new(gui.lastRect.TopRight - new Vector2(1.25f, 0), new Vector2(1.25f, 1.25f)), config.beaconModule.target.GetIcon(), SchemeColor.Source);
switch (click) {
case GoodsWithAmountEvent.LeftButtonClick:
SelectSingleObjectPanel.SelectQualityWithNone(Database.usableBeacons,
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Workspace/ProductionTable/ProductionTableView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ public ModulesColumn(ProductionTableView view) : base(view, LSs.ProductionTableH
=> moduleTemplateList = new VirtualScrollList<ProjectModuleTemplate>(15f, new Vector2(20f, 2.5f), ModuleTemplateDrawer, collapsible: true);

private void ModuleTemplateDrawer(ImGui gui, ProjectModuleTemplate element, int index) {
var evt = gui.BuildContextMenuButton(element.name, icon: element.icon?.icon ?? default, disabled: !element.template.IsCompatibleWith(editingRecipeModules));
var evt = gui.BuildContextMenuButton(element.name, icon: element.icon?.GetIcon() ?? default, disabled: !element.template.IsCompatibleWith(editingRecipeModules));

if (evt == ButtonEvent.Click && gui.CloseDropdown()) {
var copied = JsonUtils.Copy(element.template, editingRecipeModules, null);
Expand Down
2 changes: 1 addition & 1 deletion Yafc/Workspace/SummaryView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public override void BuildElement(ImGui gui, ProjectPage page) {
gui.spacing = 0.2f;

if (page.icon != null) {
gui.BuildIcon(page.icon.icon, FirstColumnIconSize);
gui.BuildIcon(page.icon.GetIcon(), FirstColumnIconSize);
}
else {
_ = gui.AllocateRect(0f, FirstColumnIconSize);
Expand Down