Skip to content

Commit 1454982

Browse files
authored
Auto apply module templates (#487)
This a step toward #472, and I'm going to say it closes #218, unless someone is working on a system where Py can explicitly specify which modules go with which recipes/buildings.
2 parents 977cc81 + dc3e7f5 commit 1454982

File tree

9 files changed

+88
-1
lines changed

9 files changed

+88
-1
lines changed

Yafc.Model.Tests/Serialization/SerializationTreeChangeDetection.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ public class SerializationTreeChangeDetection {
116116
[nameof(ProjectModuleTemplate.icon)] = typeof(FactorioObject),
117117
[nameof(ProjectModuleTemplate.name)] = typeof(string),
118118
[nameof(ProjectModuleTemplate.filterEntities)] = typeof(List<Entity>),
119+
[nameof(ProjectModuleTemplate.autoApplyToNewRows)] = typeof(bool),
120+
[nameof(ProjectModuleTemplate.autoApplyIfIncompatible)] = typeof(bool),
119121
},
120122
[typeof(ProjectPage)] = new() {
121123
[nameof(ProjectPage.icon)] = typeof(FactorioObject),

Yafc.Model/Model/ProductionTable.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ public void AddRecipe(IObjectWithQuality<RecipeOrTechnology> recipe, IComparer<G
274274
_ = recipeRow.variants.Add(variants.AutoSelect(ingredientVariantComparer)!); // null-forgiving: variants is never empty, and AutoSelect never returns null from a non-empty collection (of non-null items).
275275
}
276276
}
277+
278+
recipeRow.AutoApplyModuleTemplate(Project.current.sharedModuleTemplates);
277279
}
278280

279281
private static EntityCrafter? GetSelectedFuelCrafter(RecipeOrTechnology recipe, IObjectWithQuality<Goods>? selectedFuel) =>

Yafc.Model/Model/ProductionTableContent.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,21 @@ public void Dispose() {
756756
}
757757
}
758758

759+
/// <summary>
760+
/// Search through <paramref name="moduleTemplates"/> to find a module template that can be used on this recipe. Apply the first one found.
761+
/// </summary>
762+
/// <param name="moduleTemplates">The templates to potentially use for this row.</param>
763+
public void AutoApplyModuleTemplate(List<ProjectModuleTemplate> moduleTemplates) {
764+
foreach (ProjectModuleTemplate template in moduleTemplates) {
765+
if (template.autoApplyToNewRows && template.AcceptsEntity(entity?.target)) {
766+
if (template.autoApplyIfIncompatible || template.template.IsCompatibleWith(this)) {
767+
modules = template.template;
768+
return;
769+
}
770+
}
771+
}
772+
}
773+
759774
// To avoid leaking these variables/methods (or just the setter, for recipesPerSecond) into public context,
760775
// these explicit interface implementations connect to internal members, instead of using implicit implementation via public members
761776
RecipeParameters IRecipeRow.parameters { get => parameters; set => parameters = value; }

Yafc.Model/Model/ProjectModuleTemplate.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,16 @@ public ProjectModuleTemplate(Project owner, string name) : base(owner) {
1212
public FactorioObject? icon { get; set; }
1313
public string name { get; set; }
1414
public List<Entity> filterEntities { get; } = [];
15+
/// <summary>
16+
/// If <see langword="true"/>, this template is a candidate for being applied to newly added recipe rows.
17+
/// </summary>
18+
public bool autoApplyToNewRows { get; set; }
19+
/// <summary>
20+
/// If this and <see cref="autoApplyToNewRows"/> are both <see langword="true"/>, this template is a candidate for being applied to newly
21+
/// added recipe rows, even if it contains modules that are not compatible with that row (e.g. prod modules in a non-prod recipe)
22+
/// </summary>
23+
public bool autoApplyIfIncompatible { get; set; }
24+
25+
// null-forgiving: non-nullable collections are happy to report they don't contain null values.
26+
internal bool AcceptsEntity(EntityCrafter? target) => filterEntities.Count == 0 || filterEntities.Contains(target!);
1527
}

Yafc.UI/ImGui/ImGuiUtils.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,21 @@ public static bool WithTooltip(this ButtonEvent evt, ImGui gui, string tooltip,
226226
return evt;
227227
}
228228

229-
public static bool BuildCheckBox(this ImGui gui, string text, bool value, out bool newValue, SchemeColor color = SchemeColor.None, RectAllocator allocator = RectAllocator.LeftRow) {
229+
public static bool BuildCheckBox(this ImGui gui, string text, bool value, out bool newValue, SchemeColor color = SchemeColor.None,
230+
RectAllocator allocator = RectAllocator.LeftRow, string? tooltip = null) {
231+
230232
using (gui.EnterRow(allocator: allocator)) {
231233
gui.BuildIcon(value ? Icon.CheckBoxCheck : Icon.CheckBoxEmpty, 1.5f, color);
232234
gui.BuildText(text, TextBlockDisplayStyle.Default(color));
233235
}
234236

237+
if (tooltip != null) {
238+
bool wasOver = gui.IsMouseOver(gui.lastContentRect);
239+
if (gui.ConsumeMouseOver(gui.lastContentRect, RenderingUtils.cursorArrow) && !wasOver) {
240+
gui.ShowTooltip(gui.lastContentRect, tooltip);
241+
}
242+
}
243+
235244
if (gui.enableDrawing && gui.OnClick(gui.lastRect)) {
236245
newValue = !value;
237246
return true;

Yafc/Data/locale/en/yafc.cfg

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,11 +671,18 @@ module-customization-energy-cost-per-output=Energy cost per recipe output: __1__
671671
module-customization-energy-usage-per-building=Energy usage: __1__ (__2__ per building)
672672
partial-cancel=Cancel (partial)
673673
module-customization-remove=Remove module customization
674+
; In English, these two are drawn on the same line. They will be placed on separate lines if the text is too long to fit on a single line.
675+
module-customization-auto-apply=Apply automatically
676+
module-customization-auto-incompatible=Even if incompatible
677+
module-customization-auto-apply-hint=If checked, newly added recipes may have this template automatically applied to them, provided the recipe and crafter are compatible.
678+
module-customization-auto-incompatible-hint=If checked, this template will be used even if one or more modules can't be used.\nFor example, a template containing productivity modules can be selected for a recipe that disallows them.
674679
select-beacon=Select beacon
675680
select-module=Select module
676681

677682
; ModuleFillerParametersScreen.cs
683+
; The icon for the selected beacon (with quality and milestone overlays) appears after this string
678684
affected-by-M-beacons=Affected by __1__
685+
; The icon for the selected module (with quality and milestone overlays) appears after this string
679686
each-containing-N-modules=each containing __1__
680687
module-filler-remove-current-override-hint=Click here to remove the current override.
681688
select-beacon-module=Select beacon module
@@ -700,6 +707,9 @@ module-filler-select-overridden-crafter=Add exception(s) for:
700707
; ModuleTemplateConfiguration.cs
701708
module-templates=Module templates
702709
create-new-template-hint=Create new template
710+
module-templates-auto=Auto
711+
module-templates-auto-enabled-hint=This template may be automatically applied to new recipes.
712+
module-templates-auto-disabled-hint=This template will not be automatically applied to new recipes.
703713

704714
; ProductionLinkSummaryScreen.cs
705715
link-summary-production=Production: __1__

Yafc/Workspace/ProductionTable/ModuleCustomizationScreen.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,33 @@ public override void Build(ImGui gui) {
5454
}
5555
}
5656

57+
float textLength = gui.GetTextDimensions(out _, LSs.ModuleCustomizationAutoApply).X
58+
+ gui.GetTextDimensions(out _, LSs.ModuleCustomizationAutoIncompatible).X;
59+
// 3 for the two checkboxes, and 1.3 for various extra padding:
60+
bool singleRow = textLength < contents.width - 4.3f;
61+
62+
ImGui.Context row = default;
63+
if (singleRow) {
64+
// The text is short enough to draw in one row
65+
row = gui.EnterRow();
66+
}
67+
if (gui.BuildCheckBox(LSs.ModuleCustomizationAutoApply, template.autoApplyToNewRows, out bool newValue,
68+
tooltip: LSs.ModuleCustomizationAutoApplyHint)) {
69+
template.RecordUndo().autoApplyToNewRows = newValue;
70+
}
71+
if (!singleRow) {
72+
// Draw in two rows, nested
73+
row = gui.EnterRow(1);
74+
gui.AllocateSpacing();
75+
}
76+
if (gui.BuildCheckBox(LSs.ModuleCustomizationAutoIncompatible, template.autoApplyIfIncompatible, out newValue,
77+
template.autoApplyToNewRows ? SchemeColor.None : SchemeColor.GreyAlt, tooltip: LSs.ModuleCustomizationAutoIncompatibleHint)
78+
&& template.autoApplyToNewRows) {
79+
80+
template.RecordUndo().autoApplyIfIncompatible = newValue;
81+
}
82+
row.Dispose();
83+
5784
gui.BuildText(LSs.ModuleCustomizationFilterBuildings);
5885
using var grid = gui.EnterInlineGrid(2f, 1f);
5986

Yafc/Workspace/ProductionTable/ModuleTemplateConfiguration.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ private void Drawer(ImGui gui, ProjectModuleTemplate element, int index) {
4242
ModuleCustomizationScreen.Show(element);
4343
}
4444

45+
SchemeColor textColor = element.autoApplyToNewRows ? SchemeColor.PrimaryText : SchemeColor.PrimaryTextFaint;
46+
using (gui.EnterGroup(ImGuiUtils.DefaultButtonPadding, textColor)) {
47+
gui.BuildText(LSs.ModuleTemplatesAuto, TextBlockDisplayStyle.Centered);
48+
}
49+
LocalizableString0 tooltip = element.autoApplyToNewRows ? LSs.ModuleTemplatesAutoEnabledHint : LSs.ModuleTemplatesAutoDisabledHint;
50+
if (gui.BuildButton(gui.lastRect, SchemeColor.None, SchemeColor.Grey).WithTooltip(gui, tooltip)) {
51+
element.RecordUndo().autoApplyToNewRows = !element.autoApplyToNewRows;
52+
}
53+
4554
gui.allocator = RectAllocator.LeftRow;
4655
if (element.icon != null) {
4756
gui.BuildFactorioObjectIcon(element.icon);

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
Version:
1919
Date:
2020
Features:
21+
- Module templates can be automatically applied to new recipe rows, on a per-template basis.
2122
Fixes:
2223
- Personal equipment names are localized again.
2324
----------------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)