private void BuildRecipeMenu(ImGui gui, ref bool closed) { if (gui.BuildButton("Add recipe") && (closed = true)) { SelectObjectPanel.Select(Database.recipes.all, "Select raw recipe", r => AddRecipe(model, r)); } gui.BuildText("Export inputs and outputs to blueprint with constant combinators:", wrap: true); using (gui.EnterRow()) { gui.BuildText("Amount per:"); if (gui.BuildLink("second") && (closed = true)) { ExportIo(1f); } if (gui.BuildLink("minute") && (closed = true)) { ExportIo(60f); } if (gui.BuildLink("hour") && (closed = true)) { ExportIo(3600f); } } }
private void BuildCommon(FactorioObject target, ImGui gui) { BuildHeader(gui); using (gui.EnterGroup(contentPadding)) { if (InputSystem.Instance.control) { gui.BuildText(target.typeDotName); } if (target.locDescr != null) { gui.BuildText(target.locDescr, wrap: true); } if (!target.IsAccessible()) { gui.BuildText("This " + target.type + " is inaccessible, or it is only accessible through mod or map script. Middle click to open dependency analyser to investigate.", wrap: true); } else if (!target.IsAutomatable()) { gui.BuildText("This " + target.type + " cannot be fully automated. This means that it requires either manual crafting, or manual labor such as cutting trees", wrap: true); } else { gui.BuildText(CostAnalysis.GetDisplayCost(target), wrap: true); } } }
private void DrawEntryList(ImGui gui, List <RecipeEntry> entries, bool production) { var footerDrawn = false; var prevEntryStatus = EntryStatus.Normal; FactorioObject prevLatestMilestone = null; foreach (var entry in entries) { var status = entry.entryStatus; if (status < showRecipesRange) { DrawEntryFooter(gui, production); footerDrawn = true; gui.BuildText(entry.entryStatus == EntryStatus.Special ? "Show special recipes (barreling / voiding)" : entry.entryStatus == EntryStatus.NotAccessibleWithCurrentMilestones ? "There are more recipes, but they are locked based on current milestones" : "There are more recipes but they are inaccessible", wrap: true); if (gui.BuildButton("Show more recipes")) { ChangeShowStatus(status); } break; } if (status < prevEntryStatus) { prevEntryStatus = status; using (gui.EnterRow()) { gui.BuildText(status == EntryStatus.Special ? "Special recipes:" : status == EntryStatus.NotAccessibleWithCurrentMilestones ? "Locked recipes:" : "Inaccessible recipes:"); if (gui.BuildLink("hide")) { ChangeShowStatus(status + 1); } } } if (status == EntryStatus.NotAccessibleWithCurrentMilestones) { var latest = Milestones.Instance.GetHighest(entry.recipe, false); if (latest != prevLatestMilestone) { gui.BuildFactorioObjectButtonWithText(latest, size: 3f, display: MilestoneDisplay.None); prevLatestMilestone = latest; } } if (gui.ShouldBuildGroup(entry.recipe, out var group)) { DrawRecipeEntry(gui, entry, production); group.Complete(); } } if (!footerDrawn) { DrawEntryFooter(gui, production); } CheckChanging(); }
private void BuildBeltInserterInfo(ImGui gui, float amount, float buildingCount, ref bool closed) { var prefs = Project.current.preferences; var belt = prefs.defaultBelt; var inserter = prefs.defaultInserter; if (belt == null || inserter == null) { return; } var beltCount = amount / belt.beltItemsPerSecond; var buildingsPerHalfBelt = belt.beltItemsPerSecond * buildingCount / (amount * 2f); var click = false; using (gui.EnterRow()) { click |= gui.BuildFactorioObjectButton(belt); gui.BuildText(DataUtils.FormatAmount(beltCount, UnitOfMeasure.None)); if (buildingsPerHalfBelt > 0f) { gui.BuildText("(Buildings per half belt: " + DataUtils.FormatAmount(buildingsPerHalfBelt, UnitOfMeasure.None) + ")"); } } using (gui.EnterRow()) { var capacity = prefs.inserterCapacity; var inserterBase = inserter.inserterSwingTime * amount / capacity; click |= gui.BuildFactorioObjectButton(inserter); var text = DataUtils.FormatAmount(inserterBase, UnitOfMeasure.None); if (buildingCount > 1) { text += " (" + DataUtils.FormatAmount(inserterBase / buildingCount, UnitOfMeasure.None) + "/building)"; } gui.BuildText(text); if (capacity > 1) { var withBeltSwingTime = inserter.inserterSwingTime + 2f * (capacity - 1.5f) / belt.beltItemsPerSecond; var inserterToBelt = amount * withBeltSwingTime / capacity; click |= gui.BuildFactorioObjectButton(belt); gui.AllocateSpacing(-1.5f); click |= gui.BuildFactorioObjectButton(inserter); text = DataUtils.FormatAmount(inserterToBelt, UnitOfMeasure.None, "~"); if (buildingCount > 1) { text += " (" + DataUtils.FormatAmount(inserterToBelt / buildingCount, UnitOfMeasure.None) + "/b)"; } gui.BuildText(text); } } if (click) { PreferencesScreen.Show(); closed = true; } }
private void BuildIconRow(ImGui gui, IReadOnlyList <FactorioObject> objects, int maxRows) { const int itemsPerRow = 9; var count = objects.Count; if (count == 0) { gui.BuildText("Nothing", color: SchemeColor.BackgroundTextFaint); return; } var arr = new List <FactorioObject>(count); arr.AddRange(objects); arr.Sort(DataUtils.DefaultOrdering); if (count <= maxRows) { for (var i = 0; i < count; i++) { gui.BuildFactorioObjectButtonWithText(arr[i]); } return; } var index = 0; if (count - 1 < (maxRows - 1) * itemsPerRow) { gui.BuildFactorioObjectButtonWithText(arr[0]); index++; } var rows = Math.Min(((count - 1 - index) / itemsPerRow) + 1, maxRows); for (var i = 0; i < rows; i++) { using (gui.EnterRow()) { for (var j = 0; j < itemsPerRow; j++) { if (arr.Count <= index) { return; } gui.BuildFactorioObjectIcon(arr[index++]); } } } if (rows * itemsPerRow < count) { gui.BuildText("... and " + (count - rows * itemsPerRow) + " more"); } }
public override void Build(ImGui gui) { BuildHeader(gui, header); var valid = true; pages[page](gui, ref valid); using (gui.EnterRow(allocator: RectAllocator.RightRow)) { if (gui.BuildButton(page >= pages.Count - 1 ? "Finish" : "Next", active: valid)) { if (page < pages.Count - 1) { page++; } else { Close(); finish(); } } if (page > 0 && gui.BuildButton("Previous")) { page--; } gui.BuildText("Step " + (page + 1) + " of " + pages.Count); } }
private void BuildHeader(ImGui gui) { using (gui.EnterGroup(new Padding(1f, 0.5f), RectAllocator.LeftAlign, spacing: 0f)) { var name = target.text; if (extendHeader && !(target is Goods)) { name = name + " (" + target.target.type + ")"; } gui.BuildText(name, Font.header, true); var milestoneMask = Milestones.Instance.milestoneResult[target.target]; if (milestoneMask > 1) { var spacing = MathF.Min(22f / Milestones.Instance.currentMilestones.Length - 1f, 0f); using (gui.EnterRow(spacing)) { var mask = 2ul; foreach (var milestone in Milestones.Instance.currentMilestones) { if ((milestoneMask & mask) != 0) { gui.BuildIcon(milestone.icon, 1f, SchemeColor.Source); } mask <<= 1; } } } } if (gui.isBuilding) { gui.DrawRectangle(gui.lastRect, SchemeColor.Primary); } }
public override void Build(ImGui gui) { BuildHeader(gui, "Milestone editor"); milestoneList.Build(gui); gui.BuildText( "Hint: You can reorder milestones. When an object is locked behind a milestone, the first inaccessible milestone will be shown. Also when there is a choice between different milestones, first will be chosen", wrap: true, color: SchemeColor.BackgroundTextFaint); using (gui.EnterRow()) { if (gui.BuildButton("Auto sort milestones", SchemeColor.Grey)) { var collector = new ErrorCollector(); Milestones.Instance.ComputeWithParameters(Project.current, collector, Project.current.settings.milestones.ToArray(), true); if (collector.severity > ErrorSeverity.None) { ErrorListPanel.Show(collector); } milestoneList.RebuildContents(); } if (gui.BuildButton("Add milestone")) { if (Project.current.settings.milestones.Count >= 60) { MessageBox.Show(null, "Milestone limit reached", "60 milestones is the limit. You may delete some of the milestones you've already reached.", "Ok"); } else { SelectObjectPanel.Select(Database.objects.all, "Add new milestone", AddMilestone); } } } }
public override void Build(ImGui gui) { BuildHeader(gui, "Never Enough Items Explorer"); using (gui.EnterRow()) { if (recent.Count == 0) { gui.AllocateRect(0f, 3f); } for (var i = recent.Count - 1; i >= 0; i--) { var elem = recent[i]; if (gui.BuildFactorioObjectButton(elem, 3f)) { changing = elem; } } } using (gui.EnterGroup(new Padding(0.5f), RectAllocator.LeftRow)) { gui.spacing = 0.2f; gui.BuildFactorioObjectIcon(current, size: 3f); gui.BuildText(current.locName, Font.subheader); gui.allocator = RectAllocator.RightAlign; gui.BuildText(CostAnalysis.GetDisplayCost(current)); var amount = CostAnalysis.Instance.GetItemAmount(current); if (amount != null) { gui.BuildText(amount, wrap: true); } } if (gui.BuildFactorioObjectButton(gui.lastRect, current, SchemeColor.Grey)) { SelectObjectPanel.Select(Database.goods.all, "Select item", SetItem); } using (var split = gui.EnterHorizontalSplit(2)) { split.Next(); gui.BuildText("Production:", Font.subheader); productionList.Build(gui); split.Next(); gui.BuildText("Usages:", Font.subheader); usageList.Build(gui); } CheckChanging(); using (gui.EnterRow()) { gui.BuildText("Legend:"); gui.BuildText("This color is flow (Estimated fraction of item production/consumption)"); gui.DrawRectangle(gui.lastRect, SchemeColor.Primary); gui.BuildText("This color is estimated recipe efficiency"); gui.DrawRectangle(gui.lastRect, SchemeColor.Secondary); } }
private void BuildItem(ImGui gui, IFactorioObjectWrapper item) { using (gui.EnterRow()) { gui.BuildFactorioObjectIcon(item.target); gui.BuildText(item.text, wrap: true); } }
private void BuildSubHeader(ImGui gui, string text) { using (gui.EnterGroup(contentPadding)) gui.BuildText(text, Font.subheader); if (gui.isBuilding) { gui.DrawRectangle(gui.lastRect, SchemeColor.Grey); } }
public override void Build(ImGui gui) { BuildHeader(gui, "Units of measure"); gui.BuildText("Unit of time:", Font.subheader); var prefs = Project.current.preferences; using (gui.EnterRow()) { if (gui.BuildRadioButton("Second", prefs.time == 1)) { prefs.RecordUndo(true).time = 1; } if (gui.BuildRadioButton("Minute", prefs.time == 60)) { prefs.RecordUndo(true).time = 60; } if (gui.BuildRadioButton("Hour", prefs.time == 3600)) { prefs.RecordUndo(true).time = 3600; } if (gui.BuildRadioButton("Custom", prefs.time != 1 && prefs.time != 60 && prefs.time != 3600)) { prefs.RecordUndo(true).time = 0; } if (gui.BuildTextInput(prefs.time.ToString(), out var newTime, null, delayed: true) && int.TryParse(newTime, out var parsed)) { prefs.RecordUndo(true).time = parsed; } } gui.AllocateSpacing(1f); gui.BuildText("Item production/consumption:", Font.subheader); BuildUnitPerTime(gui, false, prefs); gui.BuildText("Fluid production/consumption:", Font.subheader); BuildUnitPerTime(gui, true, prefs); if (gui.BuildButton("Done")) { Close(); } if (prefs.justChanged) { MainScreen.Instance.RebuildProjectView(); } }
private void BuildUnitPerTime(ImGui gui, bool fluid, ProjectPreferences preferences) { var unit = fluid ? preferences.fluidUnit : preferences.itemUnit; var newUnit = unit; if (gui.BuildRadioButton("Simple Amount" + preferences.GetPerTimeUnit().suffix, unit == 0f)) { newUnit = 0f; } using (gui.EnterRow()) { if (gui.BuildRadioButton("Custom: 1 unit equals", unit != 0f)) { newUnit = 1f; } gui.AllocateSpacing(); gui.allocator = RectAllocator.RightRow; if (!fluid) { if (gui.BuildButton("Set from belt")) { gui.ShowDropDown((ImGui dropGui, ref bool closed) => { closed = dropGui.BuildInlineObejctListAndButton <Entity>(Database.entities.all.Where(x => x.beltItemsPerSecond > 0f).ToArray(), DataUtils.DefaultOrdering, setBelt => { preferences.RecordUndo(true); preferences.itemUnit = setBelt.beltItemsPerSecond; }, "Select belt", extra: b => DataUtils.FormatAmount(b.beltItemsPerSecond, UnitOfMeasure.PerSecond)); gui.Rebuild(); }); } } gui.BuildText("per second"); if (gui.BuildTextInput(DataUtils.FormatAmount(unit, UnitOfMeasure.None), out var updated, null, Icon.None, true) && DataUtils.TryParseAmount(updated, out var parsed, UnitOfMeasure.None)) { newUnit = parsed; } } gui.AllocateSpacing(1f); if (newUnit != unit) { preferences.RecordUndo(true); if (fluid) { preferences.fluidUnit = newUnit; } else { preferences.itemUnit = newUnit; } } }
private void ChoiceObject <T>(ImGui gui, string text, T[] list, T current, Action <T> select) where T : FactorioObject { using (gui.EnterRow()) { gui.BuildText(text, topOffset: 0.5f); if (gui.BuildFactorioObjectButtonWithText(current)) { gui.BuildObjectSelectDropDown(list, DataUtils.DefaultOrdering, select, text); } } }
public override void Build(ImGui gui) { BuildHeader(gui, "Module customisation"); if (recipe.modules == null) { if (gui.BuildButton("Enable custom modules")) { recipe.RecordUndo().modules = new CustomModules(recipe); } } else { gui.BuildText("Internal modules:", Font.subheader); gui.BuildText("Leave zero amount to fill the remainings slots"); DrawRecipeModules(gui, null); gui.BuildText("Beacon modules:", Font.subheader); if (recipe.modules.beacon == null) { gui.BuildText("Use default parameters"); if (gui.BuildButton("Override beacons as well")) { gui.ShowDropDown(SelectBeacon); } } else { if (gui.BuildFactorioObjectButtonWithText(recipe.modules.beacon)) { gui.ShowDropDown(SelectBeacon); } gui.BuildText("Input the amount of modules, not the amount of beacons. Single beacon can hold " + recipe.modules.beacon.moduleSlots + " modules.", wrap: true); DrawRecipeModules(gui, recipe.modules.beacon); } } gui.AllocateSpacing(3f); if (gui.BuildButton("Done")) { Close(); } }
private void BuildModulesMenu(ImGui gui, ref bool closed) { if (model.modules == null) { model.RecordUndo(true).modules = new ModuleFillerParameters(model); } gui.BuildText("Auto modules", Font.subheader); ModuleFillerParametersScreen.BuildSimple(gui, model.modules); if (gui.BuildButton("More settings")) { ModuleFillerParametersScreen.Show(model.modules); closed = true; } }
public override void Build(ImGui gui) { gui.spacing = 1f; BuildHeader(gui, "Milestones"); gui.BuildText("Please select objects that you already have access to:"); gui.AllocateSpacing(2f); MilestonesWidget.Instance.Build(gui); gui.AllocateSpacing(2f); gui.BuildText("For your convinience, YAFC will show objects you DON'T have access to based on this selection", wrap: true); gui.BuildText("These are called 'Milestones'. By default all science packs are added as milestones, but this does not have to be this way! " + "You can define your own milestones: Any item, recipe, entity or technology may be added as a milestone. For example you can add advanced " + "electronic circuits as a milestone, and YAFC will display everything that is locked behind those circuits", wrap: true); using (gui.EnterRow()) { if (gui.BuildButton("Edit milestones", SchemeColor.Grey)) { MilestonesEditor.Show(); } if (gui.RemainingRow().BuildButton("Done")) { Close(); } } }
public static void BuildSimple(ImGui gui, ModuleFillerParameters modules) { var payback = modules.autoFillPayback; var modulesLog = MathUtils.LogarithmicToLinear(payback, ModulesMinPayback, ModulesMaxPayback); if (gui.BuildSlider(modulesLog, out var newValue)) { payback = MathUtils.LinearToLogarithmic(newValue, ModulesMinPayback, ModulesMaxPayback, 0f, float.MaxValue); // JSON can't handle infinities modules.RecordUndo().autoFillPayback = payback; } if (payback <= 0f) { gui.BuildText("Use no modules"); } else if (payback >= float.MaxValue) { gui.BuildText("Use best modules"); } else { gui.BuildText("Modules payback estimate: " + DataUtils.FormatTime(payback), wrap: true); } }
protected void BuildHeader(ImGui gui, string text, bool closeButton = true) { gui.BuildText(text, Font.header, false, RectAlignment.Middle); if (closeButton) { var closeButtonRect = new Rect(width - 3f, 0f, 3f, 2f); if (gui.isBuilding) { var isOver = gui.IsMouseOver(closeButtonRect); var closeButtonCenter = Rect.Square(closeButtonRect.Center, 1f); gui.DrawIcon(closeButtonCenter, Icon.Close, isOver ? SchemeColor.ErrorText : SchemeColor.BackgroundText); } if (gui.BuildButton(closeButtonRect, SchemeColor.None, SchemeColor.Error) == ImGuiUtils.Event.Click) { Close(false); } } }
public override void Build(ImGui gui) { BuildHeader(gui, "Milestone editor"); milestoneList.Build(gui); gui.BuildText( "Hint: You can reorder milestones. When an object is locked behind a milestone, the first inaccessible milestone will be shown. Also when there is a choice between different milestones, first will be chosen", wrap: true, color: SchemeColor.BackgroundTextFaint); if (gui.BuildButton("Add milestone")) { if (Project.current.settings.milestones.Count >= 60) { MessageBox.Show(null, "Milestone limit reached", "60 milestones is the limit. You may delete some of the milestones you've already reached.", "Ok"); } else { SelectObjectPanel.Select(Database.objects.all, "Add new milestone", AddMilestone); } } }
private void BuildRecipeName(ImGui gui, RecipeRow recipe) { gui.spacing = 0.5f; if (gui.BuildFactorioObjectButton(recipe.recipe, 3f)) { gui.ShowDropDown(delegate(ImGui imgui, ref bool closed) { if (recipe.subgroup == null && imgui.BuildButton("Create nested table")) { recipe.RecordUndo().subgroup = new ProductionTable(recipe); closed = true; } if (recipe.subgroup != null && imgui.BuildButton("Unpack nested table")) { var evacuate = recipe.subgroup.recipes; recipe.subgroup.RecordUndo(); recipe.RecordUndo().subgroup = null; var index = recipe.owner.recipes.IndexOf(recipe); foreach (var evacRecipe in evacuate) { evacRecipe.SetOwner(recipe.owner); } recipe.owner.RecordUndo().recipes.InsertRange(index + 1, evacuate); closed = true; } if (recipe.subgroup != null && imgui.BuildRedButton("Remove nested table") == ImGuiUtils.Event.Click) { recipe.owner.RecordUndo().recipes.Remove(recipe); closed = true; } if (recipe.subgroup == null && imgui.BuildRedButton("Delete recipe") == ImGuiUtils.Event.Click) { recipe.owner.RecordUndo().recipes.Remove(recipe); closed = true; } }); } gui.BuildText(recipe.recipe.locName, wrap: true); }
private void MilestoneDrawer(ImGui gui, FactorioObject element, int index) { using (gui.EnterRow()) { var settings = Project.current.settings; gui.BuildFactorioObjectIcon(element, MilestoneDisplay.None, 3f); gui.BuildText(element.locName); gui.allocator = RectAllocator.RightRow; if (gui.BuildButton(Icon.Close, size: 1f)) { settings.RecordUndo().milestones.Remove(element); Rebuild(); milestoneList.data = settings.milestones; } } if (gui.DoListReordering(gui.lastRect, gui.lastRect, index, out var moveFrom)) { Project.current.settings.RecordUndo().milestones.MoveListElementIndex(moveFrom, index); } }
private void DrawEntryList(ImGui gui, List <RecipeEntry> entries, bool production) { foreach (var entry in entries) { if (entry.entryStatus < showRecipesRange) { gui.BuildText(entry.entryStatus == EntryStatus.Wasteful ? "There are more recipes, but they are wasteful" : entry.entryStatus == EntryStatus.NotAccessibleWithCurrentMilestones ? "There are more recipes, but they are locked based on current milestones" : "There are more recipes but they are inaccessible", wrap: true); if (gui.BuildButton("Show more recipes")) { showRecipesRange = entry.entryStatus; Rebuild(); } break; } DrawRecipeEntry(gui, entry, production); } CheckChanging(); }
public override void Build(ImGui gui) { BuildHeader(gui, title); if (message != null) { gui.BuildText(message, wrap: true); } gui.AllocateSpacing(2f); using (gui.EnterRow(allocator: RectAllocator.RightRow)) { if (gui.BuildButton(yes)) { CloseWithResult(true); } if (no != null && gui.BuildButton(no, SchemeColor.Grey)) { CloseWithResult(false); } } }
private void BuildTechnology(Technology technology, ImGui gui) { BuildRecipe(technology, gui); if (technology.hidden && !technology.enabled) { using (gui.EnterGroup(contentPadding)) gui.BuildText("This technology is hidden from the list and cannot be researched.", wrap: true); } if (technology.prerequisites.Length > 0) { BuildSubHeader(gui, "Prerequisites"); using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, technology.prerequisites, 1); } if (technology.unlockRecipes.Length > 0) { BuildSubHeader(gui, "Unlocks recipes"); using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, technology.unlockRecipes, 2); } var packs = TechnologyScienceAnalysis.Instance.allSciencePacks[technology]; if (packs.Length > 0) { BuildSubHeader(gui, "Total science required"); using (gui.EnterGroup(contentPadding)) { using (var grid = gui.EnterInlineGrid(3f)) { foreach (var pack in packs) { grid.Next(); gui.BuildFactorioObjectWithAmount(pack.goods, pack.amount, UnitOfMeasure.None); } } } } }
private void DrawEntryFooter(ImGui gui, bool production) { if (!production && current.fuelFor.Length > 0) { using (gui.EnterGroup(new Padding(0.5f), RectAllocator.LeftAlign)) { gui.BuildText(current.fuelValue > 0f ? "Fuel value " + DataUtils.FormatAmount(current.fuelValue, UnitOfMeasure.Megajoule) + " can be used for:" : "Can be used to fuel:"); using (var grid = gui.EnterInlineGrid(3f)) { foreach (var fuelUsage in current.fuelFor) { grid.Next(); gui.BuildFactorioObjectButton(fuelUsage, 3f, MilestoneDisplay.Contained); } } } if (gui.isBuilding) { gui.DrawRectangle(gui.lastRect, SchemeColor.Primary); } } }
private void DrawRecipeEntry(ImGui gui, RecipeEntry entry, bool production) { var textcolor = SchemeColor.BackgroundText; var bgColor = SchemeColor.Background; var isBuilding = gui.isBuilding; var recipe = entry.recipe; var waste = recipe.RecipeWaste(); if (isBuilding) { if (entry.entryStatus == EntryStatus.NotAccessible) { bgColor = SchemeColor.None; textcolor = SchemeColor.BackgroundTextFaint; } else if (entry.flow > 0f) { bgColor = SchemeColor.Secondary; textcolor = SchemeColor.SecondaryText; } else if (waste > 0.95f) { bgColor = SchemeColor.Error; textcolor = SchemeColor.ErrorText; } } using (gui.EnterGroup(new Padding(0.5f), production ? RectAllocator.LeftRow : RectAllocator.RightRow, textcolor)) { using (gui.EnterFixedPositioning(4f, 0f, default)) { gui.allocator = RectAllocator.Stretch; gui.spacing = 0f; gui.BuildFactorioObjectButton(entry.recipe, 4f, MilestoneDisplay.Contained); gui.BuildText(DataUtils.FormatAmount(recipe.Cost(), UnitOfMeasure.None, "¥"), align: RectAlignment.Middle); } gui.AllocateSpacing(); gui.allocator = production ? RectAllocator.LeftAlign : RectAllocator.RightAlign; gui.BuildText(recipe.locName, wrap: true); if (recipe.ingredients.Length + recipe.products.Length <= 8) { using (gui.EnterRow()) { DrawIngredients(gui, entry.recipe); gui.allocator = RectAllocator.RightRow; DrawProducts(gui, entry.recipe); if (recipe.products.Length < 3 && recipe.ingredients.Length < 5) { gui.AllocateSpacing((3 - entry.recipe.products.Length) * 3f); } else if (recipe.products.Length < 3) { gui.allocator = RectAllocator.RemainigRow; } gui.BuildIcon(Icon.ArrowRight, 3f); } } else { using (gui.EnterRow()) DrawIngredients(gui, entry.recipe); using (gui.EnterRow()) { gui.BuildIcon(Icon.ArrowDownRight, 3f); gui.allocator = RectAllocator.RightRow; DrawProducts(gui, entry.recipe); } } var importance = CostAnalysis.Instance.GetBuildingAmount(recipe, entry.recipeFlow); if (importance != null) { gui.BuildText(importance, wrap: true); } } if (isBuilding) { var rect = gui.lastRect; if (entry.flow > 0f) { var percentFlow = MathUtils.Clamp(entry.flow / currentFlow, 0f, 1f); rect.Width *= percentFlow; gui.DrawRectangle(rect, SchemeColor.Primary); } else if (waste <= 0f) { bgColor = SchemeColor.Secondary; } else { rect.Width *= (1f - entry.recipe.RecipeWaste()); gui.DrawRectangle(rect, SchemeColor.Secondary); } gui.DrawRectangle(gui.lastRect, bgColor); } }
private void BuildGoods(Goods goods, ImGui gui) { BuildCommon(goods, gui); using (gui.EnterGroup(contentPadding)) gui.BuildText("Middle mouse button to open Never Enough Items Explorer for this " + goods.type, wrap: true); if (goods.production.Length > 0) { BuildSubHeader(gui, "Made with"); using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, goods.production, 2); } if (goods.miscSources.Length > 0) { BuildSubHeader(gui, "Sources"); using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, goods.miscSources, 2); } if (goods.usages.Length > 0) { BuildSubHeader(gui, "Needs for"); using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, goods.usages, 4); } if (goods.fuelFor.Length > 0) { if (goods.fuelValue > 0f) { BuildSubHeader(gui, "Fuel value " + DataUtils.FormatAmount(goods.fuelValue, UnitOfMeasure.Megajoule) + " used for:"); } else { BuildSubHeader(gui, "Can be used as fuel for:"); } using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, goods.fuelFor, 2); } if (goods is Item item) { if (goods.fuelValue > 0f && item.fuelResult != null) { using (gui.EnterGroup(contentPadding)) BuildItem(gui, item.fuelResult); } if (item.placeResult != null) { BuildSubHeader(gui, "Place result"); using (gui.EnterGroup(contentPadding)) BuildItem(gui, item.placeResult); } if (item.module != null) { BuildSubHeader(gui, "Module parameters"); using (gui.EnterGroup(contentPadding)) { if (item.module.productivity != 0f) { gui.BuildText(DataUtils.FormatAmount(item.module.productivity, UnitOfMeasure.Percent, "Productivity: ")); } if (item.module.speed != 0f) { gui.BuildText(DataUtils.FormatAmount(item.module.speed, UnitOfMeasure.Percent, "Speed: ")); } if (item.module.consumption != 0f) { gui.BuildText(DataUtils.FormatAmount(item.module.consumption, UnitOfMeasure.Percent, "Consumption: ")); } if (item.module.pollution != 0f) { gui.BuildText(DataUtils.FormatAmount(item.module.consumption, UnitOfMeasure.Percent, "Pollution: ")); } } if (item.module.limitation != null) { BuildSubHeader(gui, "Module limitation"); using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, item.module.limitation, 2); } } using (gui.EnterGroup(contentPadding)) gui.BuildText("Stack size: " + item.stackSize); } }
private void BuildEntity(Entity entity, ImGui gui) { BuildCommon(entity, gui); if (entity.loot.Length > 0) { BuildSubHeader(gui, "Loot"); using (gui.EnterGroup(contentPadding)) { foreach (var product in entity.loot) { BuildItem(gui, product); } } } if (entity.mapGenerated) { using (gui.EnterGroup(contentPadding)) gui.BuildText("Generates on map (estimated density: " + (entity.mapGenDensity <= 0f ? "unknown" : DataUtils.FormatAmount(entity.mapGenDensity, UnitOfMeasure.None)) + ")", wrap: true); } if (!entity.recipes.empty) { BuildSubHeader(gui, "Crafts"); using (gui.EnterGroup(contentPadding)) { BuildIconRow(gui, entity.recipes, 2); if (entity.craftingSpeed != 1f) { gui.BuildText(DataUtils.FormatAmount(entity.craftingSpeed, UnitOfMeasure.Percent, "Crafting speed: ")); } if (entity.productivity != 0f) { gui.BuildText(DataUtils.FormatAmount(entity.productivity, UnitOfMeasure.Percent, "Crafting productivity: ")); } if (entity.allowedEffects != AllowedEffects.None) { gui.BuildText("Module slots: " + entity.moduleSlots); if (entity.allowedEffects != AllowedEffects.All) { gui.BuildText("Only allowed effects: " + entity.allowedEffects, wrap: true); } } } } if (entity.inputs != null) { BuildSubHeader(gui, "Allowed inputs:"); using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, entity.inputs, 2); } if (entity.energy != null) { BuildSubHeader(gui, EnergyDescriptions[entity.energy.type] + DataUtils.FormatAmount(entity.power, UnitOfMeasure.Megawatt)); using (gui.EnterGroup(contentPadding)) { if (entity.energy.type == EntityEnergyType.FluidFuel || entity.energy.type == EntityEnergyType.SolidFuel || entity.energy.type == EntityEnergyType.FluidHeat) { BuildIconRow(gui, entity.energy.fuels, 2); } if (entity.energy.emissions != 0f) { var emissionColor = SchemeColor.BackgroundText; if (entity.energy.emissions < 0f) { emissionColor = SchemeColor.Green; gui.BuildText("This building absorbs pollution", color: emissionColor); } else if (entity.energy.emissions >= 20f) { emissionColor = SchemeColor.Error; gui.BuildText("This building contributes to global warning!", color: emissionColor); } gui.BuildText("Emissions: " + DataUtils.FormatAmount(entity.energy.emissions, UnitOfMeasure.None), color: emissionColor); } } } string miscText = null; switch (entity) { case EntityBelt belt: miscText = "Belt throughput (Items): " + DataUtils.FormatAmount(belt.beltItemsPerSecond, UnitOfMeasure.PerSecond); break; case EntityInserter inserter: miscText = "Swing time: " + DataUtils.FormatAmount(inserter.inserterSwingTime, UnitOfMeasure.Second); break; case EntityBeacon beacon: miscText = "Beacon efficiency: " + DataUtils.FormatAmount(beacon.beaconEfficiency, UnitOfMeasure.Percent); break; case EntityAccumulator accumulator: miscText = "Accumulator charge: " + DataUtils.FormatAmount(accumulator.accumulatorCapacity, UnitOfMeasure.Megajoule); break; default: { if (entity.craftingSpeed > 0f && entity.factorioType == "solar-panel") { miscText = "Power production (average): " + DataUtils.FormatAmount(entity.craftingSpeed, UnitOfMeasure.Megawatt); } break; } } if (miscText != null) { using (gui.EnterGroup(contentPadding)) gui.BuildText(miscText); } }
private void BuildRecipe(RecipeOrTechnology recipe, ImGui gui) { BuildCommon(recipe, gui); using (gui.EnterGroup(contentPadding, RectAllocator.LeftRow)) { gui.BuildIcon(Icon.Time, 2f, SchemeColor.BackgroundText); gui.BuildText(DataUtils.FormatAmount(recipe.time, UnitOfMeasure.Second)); } using (gui.EnterGroup(contentPadding)) { foreach (var ingredient in recipe.ingredients) { BuildItem(gui, ingredient); } if (recipe is Recipe rec) { var waste = rec.RecipeWaste(); if (waste > 0.01f) { var wasteAmount = MathUtils.Round(waste * 100f); var wasteText = ". (Wasting " + wasteAmount + "% of YAFC cost)"; var color = wasteAmount < 90 ? SchemeColor.BackgroundText : SchemeColor.Error; if (recipe.products.Length == 1) { gui.BuildText("YAFC analysis: There are better recipes to create " + recipe.products[0].goods.locName + wasteText, wrap: true, color: color); } else if (recipe.products.Length > 0) { gui.BuildText("YAFC analysis: There are better recipes to create each of the products" + wasteText, wrap: true, color: color); } else { gui.BuildText("YAFC analysis: This recipe wastes useful products. Don't do this recipe.", wrap: true, color: color); } } } if (recipe.flags.HasFlags(RecipeFlags.UsesFluidTemperature)) { gui.BuildText("Uses fluid temperature"); } if (recipe.flags.HasFlags(RecipeFlags.UsesMiningProductivity)) { gui.BuildText("Uses mining productivity"); } if (recipe.flags.HasFlags(RecipeFlags.ScaleProductionWithPower)) { gui.BuildText("Production scaled with power"); } } if (recipe.products.Length > 0 && !(recipe.products.Length == 1 && recipe.products[0].IsSimple && recipe.products[0].goods is Item && recipe.products[0].amount == 1f)) { BuildSubHeader(gui, "Products"); using (gui.EnterGroup(contentPadding)) foreach (var product in recipe.products) { BuildItem(gui, product); } } BuildSubHeader(gui, "Made in"); using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, recipe.crafters, 2); if (recipe.modules.Length > 0) { BuildSubHeader(gui, "Allowed modules"); using (gui.EnterGroup(contentPadding)) BuildIconRow(gui, recipe.modules, 1); } if (recipe is Recipe lockedRecipe && !lockedRecipe.enabled) { BuildSubHeader(gui, "Unlocked by"); using (gui.EnterGroup(contentPadding)) { if (lockedRecipe.technologyUnlock.Count > 2) { BuildIconRow(gui, lockedRecipe.technologyUnlock, 1); } else { foreach (var technology in lockedRecipe.technologyUnlock) { var ingredient = TechnologyScienceAnalysis.Instance.GetMaxTechnologyIngredient(technology); using (gui.EnterRow(allocator: RectAllocator.RightRow)) { gui.spacing = 0f; if (ingredient != null) { gui.BuildFactorioObjectIcon(ingredient.goods); gui.BuildText(DataUtils.FormatAmount(ingredient.amount, UnitOfMeasure.None)); } gui.allocator = RectAllocator.RemainigRow; gui.BuildFactorioObjectButtonWithText(technology); } } } } } }