public static void BuildFactorioObjectIcon(this ImGui gui, FactorioObject obj, MilestoneDisplay display = MilestoneDisplay.Normal, float size = 2f) { 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 (gui.isBuilding && display != MilestoneDisplay.None) { var contain = (display & MilestoneDisplay.Contained) != 0; var milestone = Milestones.Instance.GetHighest(obj, display >= MilestoneDisplay.All); if (milestone != null) { var psize = new Vector2(size / 2f); var delta = contain ? psize : psize / 2f; var milestoneIcon = new Rect(gui.lastRect.BottomRight - delta, psize); var icon = milestone == Database.voidEnergy ? DataUtils.HandIcon : milestone.icon; gui.DrawIcon(milestoneIcon, icon, color); } } }
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); } }
private void BuildRecipePad(ImGui gui, RecipeRow row) { gui.allocator = RectAllocator.Center; gui.spacing = 0f; if (row.subgroup != null) { if (gui.BuildButton(row.subgroup.expanded ? Icon.ShevronDown : Icon.ShevronRight)) { row.subgroup.RecordUndo(true).expanded = !row.subgroup.expanded; flatHierarchyBuilder.SetData(model); } } if (row.parameters.warningFlags != 0) { var isError = row.parameters.warningFlags >= WarningFlags.EntityNotSpecified; bool hover; if (isError) { hover = gui.BuildRedButton(Icon.Error) == ImGuiUtils.Event.MouseOver; } else { using (gui.EnterGroup(ImGuiUtils.DefaultIconPadding)) gui.BuildIcon(Icon.Help); hover = gui.BuildButton(gui.lastRect, SchemeColor.None, SchemeColor.Grey) == ImGuiUtils.Event.MouseOver; } if (hover) { gui.ShowTooltip(g => { if (isError) { g.boxColor = SchemeColor.Error; g.textColor = SchemeColor.ErrorText; } foreach (var(flag, text) in WarningsMeaning) { if ((row.parameters.warningFlags & flag) != 0) { g.BuildText(text, wrap: true); } } }); } } else { //gui.BuildText((index+1).ToString()); TODO } }
private void DrawRecipeTagSelect(ImGui gui, RecipeRow recipe) { using (gui.EnterRow()) { for (var i = 0; i < tagIcons.Length; i++) { var(icon, color) = tagIcons[i]; var selected = i == recipe.tag; gui.BuildIcon(icon, color: selected ? SchemeColor.Background : color); if (selected) { gui.DrawRectangle(gui.lastRect, color); } else { var evt = gui.BuildButton(gui.lastRect, SchemeColor.None, SchemeColor.BackgroundAlt, SchemeColor.BackgroundAlt); if (evt == ImGuiUtils.Event.Click) { recipe.RecordUndo(true).tag = i; } } } } }
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); } } } } } }
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 BuildRecipe(RecipeOrTechnology recipe, ImGui gui) { BuildCommon(recipe, gui); using (gui.EnterGroup(contentPadding, RectAllocator.LeftRow)) { gui.BuildIcon(Icon.Time, 2f, SchemeColor.BackgroundText); gui.BuildText(recipe.time.ToString(CultureInfo.InvariantCulture)); } 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].rawAmount == 1 && recipe.products[0].goods is Item && recipe.products[0].probability == 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.enabled) { BuildSubHeader(gui, "Unlocked by"); using (gui.EnterGroup(contentPadding)) { BuildIconRow(gui, recipe.technologyUnlock, 1); } } }
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(atCurrentMilestones); if (isBuilding) { if (entry.entryStatus == EntryStatus.NotAccessible) { bgColor = SchemeColor.None; textcolor = SchemeColor.BackgroundTextFaint; } else if (entry.flow > 0f) { bgColor = SchemeColor.Secondary; textcolor = SchemeColor.SecondaryText; } } using (gui.EnterGroup(new Padding(0.5f), production ? RectAllocator.LeftRow : RectAllocator.RightRow, textcolor)) { using (gui.EnterFixedPositioning(4f, 0f, default)) { gui.allocator = RectAllocator.Stretch; gui.BuildFactorioObjectButton(entry.recipe, 4f, MilestoneDisplay.Contained); using (gui.EnterRow()) { gui.BuildIcon(Icon.Time); gui.BuildText(DataUtils.FormatAmount(entry.recipe.time, UnitOfMeasure.Second), align: RectAlignment.Middle); } var bh = CostAnalysis.Instance.GetBuildingHours(recipe, entry.recipeFlow); if (bh > 20) { gui.BuildText(DataUtils.FormatAmount(bh, UnitOfMeasure.None, suffix: "bh"), align: RectAlignment.Middle); if (gui.BuildButton(gui.lastRect, SchemeColor.None, SchemeColor.Grey) == ImGuiUtils.Event.MouseOver) { gui.ShowTooltip(g => g.BuildText("Building-hours.\nAmount of building-hours required for all researches", wrap: true)); } } } 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); } } } 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 - waste); gui.DrawRectangle(rect, SchemeColor.Secondary); } gui.DrawRectangle(gui.lastRect, bgColor); } }