Skip to content

Commit

Permalink
Add per-recipe setting to show/hide the total I/O (#340)
Browse files Browse the repository at this point in the history
As discussed in #338 it might be more convenient to make the recipe
total I/O configurable per recipe, sicne we cannot figure out a 'catch
all' that covers all of the seablock, py and space-age, etc. mods...

The screenshot shows the same recipe twice, one with I/O enabled and one
disabled:

![image](https://github.com/user-attachments/assets/4f62fd0c-e65a-4f8a-be28-6c94331d6e91)
*Note that the label is renamed to "Show total Input/Output"*
  • Loading branch information
shpaass authored Oct 31, 2024
2 parents 40a3b3b + 8b23f88 commit 6afd3de
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 37 deletions.
1 change: 1 addition & 0 deletions Yafc.Model/Data/DataClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ public static bool CanAcceptModule(ModuleSpecification module, AllowedEffects ef
public class EntityCrafter : EntityWithModules {
public int itemInputs { get; internal set; }
public int fluidInputs { get; internal set; } // fluid inputs for recipe, not including power
public bool hasVectorToPlaceResult { get; internal set; }
public Goods[]? inputs { get; internal set; }
public RecipeOrTechnology[] recipes { get; internal set; } = null!; // null-forgiving: Set in the first step of CalculateMaps
private float _craftingSpeed = 1;
Expand Down
24 changes: 20 additions & 4 deletions Yafc.Model/Model/ProductionTableContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,21 @@ public class RecipeRow : ModelObject<ProductionTable>, IGroupedElement<Productio
public EntityCrafter? entity {
get => _entity;
set {
if (SerializationMap.IsDeserializing || fixedBuildings == 0 || _entity == value) {
if (_entity == value) {
// Nothing to do
return;
}

if (SerializationMap.IsDeserializing) {
// Just apply the deserialized entity and stop further processing
_entity = value;
return;
}
else if (fixedFuel && !(value?.energy.fuels ?? []).Contains(_fuel)) {
// We're changing both the entity and the fuel (changing between electric, fluid-burning, item-burning, heat-powered, and steam-powered crafter categories)
// Don't try to preserve fuel consumption in this case.

if (fixedBuildings == 0 || (fixedFuel && !(value?.energy.fuels ?? []).Contains(_fuel))) {
// We're either changing both the entity and the fuel (changing between electric, fluid-burning, item-burning, heat-powered, and steam-powered crafter categories),
// or fixedBuilding is zero.
// Don't try to preserve fuel consumption in these cases.
fixedBuildings = 0;
_entity = value;
}
Expand All @@ -264,6 +273,9 @@ public EntityCrafter? entity {
_entity = value;
}
}

// By default show the total item consumption and production signals for unloading crafters (miners, recyclers, etc) when they output multiple products.
showTotalIO |= value?.hasVectorToPlaceResult == true && recipe.products.Length > 1;
}
}
public Goods? fuel {
Expand Down Expand Up @@ -356,6 +368,10 @@ public Goods? fixedProduct {
}
public int? builtBuildings { get; set; }
/// <summary>
/// If <see langword="true"/>, the total item consumption and production signals are shown.
/// </summary>
public bool showTotalIO { get; set; } = false;
/// <summary>
/// If <see langword="true"/>, the enabled checkbox for this recipe is checked.
/// </summary>
public bool enabled { get; set; } = true;
Expand Down
4 changes: 0 additions & 4 deletions Yafc.Model/Model/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,6 @@ public class ProjectPreferences(Project owner) : ModelObject<Project>(owner) {
/// 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;
/// <summary>
/// The <see cref="Database.itemInput"/> and <see cref="Database.itemOutput"/> pseudo-items will be displayed at or above this ingredient/product count.
/// </summary>
public int minForTotalItems { get; set; } = 3;

protected internal override void AfterDeserialize() {
base.AfterDeserialize();
Expand Down
7 changes: 7 additions & 0 deletions Yafc.Parser/Data/FactorioDataDeserializer_Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
crafter.fluidInputs = CountFluidBoxes(fluidBoxes, true);
}

if (table.Get("vector_to_place_result", out LuaTable? hasVectorToPlaceResult)) {
crafter.hasVectorToPlaceResult = hasVectorToPlaceResult != null;
}

Recipe? fixedRecipe = null;

if (table.Get("fixed_recipe", out string? fixedRecipeName)) {
Expand Down Expand Up @@ -360,6 +364,9 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) {
drill.fluidInputs = 1;
}

// All drills have/require the vector_to_place_result to drop their items
drill.hasVectorToPlaceResult = true;

foreach (string resource in resourceCategories.ArrayElements<string>()) {
recipeCrafters.Add(drill, SpecialNames.MiningRecipe + resource);
}
Expand Down
27 changes: 0 additions & 27 deletions Yafc/Windows/PreferencesScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ private static void DrawGeneral(ImGui gui) {
}
}

float textBoxHeight; // measure the height of a text box, for use when drawing the minForTotalItems input box.
using (gui.EnterRow()) {
gui.BuildText("Reactor layout:", topOffset: 0.5f);
if (gui.BuildTextInput(settings.reactorSizeX + "x" + settings.reactorSizeY, out string newSize, null, delayed: true)) {
Expand All @@ -156,32 +155,6 @@ private static void DrawGeneral(ImGui gui) {
settings.reactorSizeY = sizeY;
}
}
textBoxHeight = gui.lastRect.Height;
}

string ioItemMessage = "The I and O items represent the total item input or item output of a recipe row.\nRecipes with at least this many item ingredients or item products will show the pseudo-items after all their real ingredients/products.";
using (gui.EnterRowWithHelpIcon(ioItemMessage)) {
float captionWidth = gui.GetTextDimensions(out _, "Minimum recipe ingredients or products").X;
using (gui.EnterFixedPositioning(captionWidth, 0, new())) { // the height will grow to fit the controls
gui.BuildText("Minimum recipe ingredients or products");
using (gui.EnterRow(0)) {
// Allocate the horizontal space now but draw the icons first, so the text can be drawn vertically centered.
Rect textRect = gui.AllocateTextRect(out _, "to display the ", TextBlockDisplayStyle.Default());
gui.BuildFactorioObjectButton(Database.itemInput, ButtonDisplayStyle.Default);
gui.BuildFactorioObjectButton(Database.itemOutput, ButtonDisplayStyle.Default);
textRect.Height = gui.lastRect.Height;
gui.DrawText(textRect, "to display the ");
gui.BuildText(" summary items");
}
}
float spacing = (gui.lastRect.Height - textBoxHeight) / 2;
using (gui.RemainingRow().EnterFixedPositioning(0, gui.lastRect.Height, new())) {
gui.AllocateSpacing(spacing - .5f); // draw the box vertically centered, rather than top-aligned (without this) or full height (without EnterFixedPositioning)
if (gui.BuildIntegerInput(prefs.minForTotalItems, out int newValue2)) {
prefs.RecordUndo().minForTotalItems = newValue2;
gui.Rebuild();
}
}
}

gui.AllocateSpacing();
Expand Down
8 changes: 6 additions & 2 deletions Yafc/Workspace/ProductionTable/ProductionTableView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ public override void BuildElement(ImGui gui, RecipeRow recipe) {
view.BuildShoppingList(recipe);
}

if (imgui.BuildCheckBox("Show total Input/Output", recipe.showTotalIO, out bool newShowTotalIO)) {
recipe.RecordUndo().showTotalIO = newShowTotalIO;
}

if (imgui.BuildCheckBox("Enabled", recipe.enabled, out bool newEnabled)) {
recipe.RecordUndo().enabled = newEnabled;
}
Expand Down Expand Up @@ -538,7 +542,7 @@ public override void BuildElement(ImGui gui, RecipeRow recipe) {
grid.Next();
view.BuildGoodsIcon(gui, goods, link, amount, ProductDropdownType.Ingredient, recipe, recipe.linkRoot, HintLocations.OnProducingRecipes, variants);
}
if (recipe.fixedIngredient == Database.itemInput || recipe.Ingredients.Count() >= Project.current.preferences.minForTotalItems) {
if (recipe.fixedIngredient == Database.itemInput || recipe.showTotalIO) {
grid.Next();
view.BuildGoodsIcon(gui, recipe.hierarchyEnabled ? Database.itemInput : null, null, recipe.Ingredients.Where(i => i.Goods is Item).Sum(i => i.Amount),
ProductDropdownType.Ingredient, recipe, recipe.linkRoot, HintLocations.None);
Expand All @@ -559,7 +563,7 @@ public override void BuildElement(ImGui gui, RecipeRow recipe) {
grid.Next();
view.BuildGoodsIcon(gui, goods, link, amount, ProductDropdownType.Product, recipe, recipe.linkRoot, HintLocations.OnConsumingRecipes);
}
if (recipe.fixedProduct == Database.itemOutput || recipe.Products.Count() >= Project.current.preferences.minForTotalItems) {
if (recipe.fixedProduct == Database.itemOutput || recipe.showTotalIO) {
grid.Next();
view.BuildGoodsIcon(gui, recipe.hierarchyEnabled ? Database.itemOutput : null, null, recipe.Products.Where(i => i.Goods is Item).Sum(i => i.Amount),
ProductDropdownType.Product, recipe, recipe.linkRoot, HintLocations.None);
Expand Down
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Version:
Date:
Features:
- Add pseudo-items representing a recipe's total sushi-inputs and sushi-outputs.
They can be toggled on/off in the LMB of the recipe.
Bugfixes:
- Fixed counts are hidden on disabled recipes, since editing them won't work properly.
----------------------------------------------------------------------------------------------------------------------
Expand Down

0 comments on commit 6afd3de

Please sign in to comment.