-
Notifications
You must be signed in to change notification settings - Fork 510
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Port Food Recipe Guidebook (EE#783) (#2138)
* Port EE#783 (Thank you, Mnemotechnician) * Revert machine type changes to meal recipes * Unneeded dependencies, show search bar * Remove yet more microwave recipe machine types * Food recipe guidebook: cleanup, style consistency * Frontier comment cleanup --------- Co-authored-by: Dvir <39403717+dvir001@users.noreply.github.com>
- Loading branch information
Showing
15 changed files
with
916 additions
and
1 deletion.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
Content.Client/_EE/Guidebook/Controls/GuideFoodComposition.xaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<BoxContainer xmlns="https://spacestation14.io" | ||
Orientation="Horizontal" | ||
HorizontalAlignment="Stretch" | ||
HorizontalExpand="True" | ||
Margin="0 0 0 5"> | ||
<BoxContainer Name="ReactantsContainer" Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center"> | ||
<Label Name="ReagentLabel" | ||
HorizontalExpand="True" | ||
HorizontalAlignment="Left" | ||
VerticalAlignment="Center" | ||
Access="Public" | ||
Margin="25 0 0 0"/> <!-- Frontier: left margin 2<25 - matches reagent plant metabolism's stacked margins with GuideFoodEmbed --> | ||
</BoxContainer> | ||
<BoxContainer Orientation="Vertical" VerticalAlignment="Center"> | ||
<Label Name="AmountLabel" | ||
HorizontalAlignment="Right" | ||
VerticalAlignment="Center" | ||
Access="Public" | ||
Margin="10 0 0 0"/> <!-- Frontier: left margin 2<10 --> | ||
</BoxContainer> | ||
</BoxContainer> |
32 changes: 32 additions & 0 deletions
32
Content.Client/_EE/Guidebook/Controls/GuideFoodComposition.xaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using Content.Client.Guidebook.Controls; | ||
using Content.Client.UserInterface.ControlExtensions; | ||
using Content.Shared.Chemistry.Reagent; | ||
using Content.Shared.FixedPoint; | ||
using JetBrains.Annotations; | ||
using Robust.Client.AutoGenerated; | ||
using Robust.Client.UserInterface.Controls; | ||
using Robust.Client.UserInterface.XAML; | ||
|
||
namespace Content.Client._EE.Guidebook.Controls; // Frontier: add _EE | ||
|
||
[UsedImplicitly, GenerateTypedNameReferences] | ||
public sealed partial class GuideFoodComposition : BoxContainer, ISearchableControl | ||
{ | ||
public GuideFoodComposition(ReagentPrototype proto, FixedPoint2 quantity) | ||
{ | ||
RobustXamlLoader.Load(this); | ||
|
||
ReagentLabel.Text = proto.LocalizedName; | ||
AmountLabel.Text = quantity.ToString(); | ||
} | ||
|
||
public bool CheckMatchesSearch(string query) | ||
{ | ||
return this.ChildrenContainText(query); | ||
} | ||
|
||
public void SetHiddenState(bool state, string query) | ||
{ | ||
Visible = CheckMatchesSearch(query) ? state : !state; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<BoxContainer xmlns="https://spacestation14.io" | ||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client" | ||
Orientation="Vertical" | ||
Margin="5 5 5 5"> | ||
<PanelContainer HorizontalExpand="True"> | ||
<PanelContainer.PanelOverride> | ||
<gfx:StyleBoxFlat BorderThickness="1" BorderColor="#777777"/> | ||
</PanelContainer.PanelOverride> | ||
<BoxContainer Orientation="Vertical"> | ||
<PanelContainer Name="NameBackground" HorizontalExpand="True" VerticalExpand="False"> | ||
<RichTextLabel Name="FoodName" HorizontalAlignment="Center"/> | ||
</PanelContainer> | ||
<!-- Frontier: separate recipes from sources --> | ||
<BoxContainer Name="RecipesContainer" HorizontalExpand="True" Visible="false"> | ||
<Collapsible HorizontalExpand="True"> | ||
<CollapsibleHeading Title="{Loc 'guidebook-food-recipes-header'}"/> | ||
<CollapsibleBody> | ||
<GridContainer Name="RecipesDescriptionContainer" | ||
Margin="10 0 10 0" | ||
Columns="1" | ||
HSeparationOverride="0" | ||
HorizontalAlignment="Stretch" | ||
HorizontalExpand="True"/> | ||
</CollapsibleBody> | ||
</Collapsible> | ||
</BoxContainer> | ||
<!-- End Frontier: separate recipes from sources --> | ||
<BoxContainer Name="SourcesContainer" HorizontalExpand="True" Visible="false"> <!-- Frontier: add Visible --> | ||
<Collapsible HorizontalExpand="True"> | ||
<CollapsibleHeading Title="{Loc 'guidebook-food-sources-header'}"/> | ||
<CollapsibleBody> | ||
<GridContainer Name="SourcesDescriptionContainer" | ||
Margin="10 0 10 0" | ||
Columns="1" | ||
HSeparationOverride="5" | ||
HorizontalAlignment="Stretch" | ||
HorizontalExpand="True"/> | ||
</CollapsibleBody> | ||
</Collapsible> | ||
</BoxContainer> | ||
<BoxContainer Name="CompositionContainer" HorizontalExpand="True"> | ||
<Collapsible> | ||
<CollapsibleHeading Title="{Loc 'guidebook-food-reagents-header'}"/> | ||
<CollapsibleBody> | ||
<BoxContainer Name="CompositionDescriptionContainer" | ||
Orientation="Vertical" | ||
Margin="10 0 10 0" | ||
HorizontalExpand="True"/> | ||
</CollapsibleBody> | ||
</Collapsible> | ||
</BoxContainer> | ||
<BoxContainer Margin="10 5 10 10" HorizontalExpand="True"> | ||
<!-- The troublemaker !--> | ||
<RichTextLabel Name="FoodDescription" HorizontalAlignment="Left"/> | ||
</BoxContainer> | ||
</BoxContainer> | ||
</PanelContainer> | ||
</BoxContainer> |
178 changes: 178 additions & 0 deletions
178
Content.Client/_EE/Guidebook/Controls/GuideFoodEmbed.xaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using Content.Client._EE.Nutrition.EntitySystems; | ||
using Content.Client.Chemistry.EntitySystems; | ||
using Content.Client.Guidebook.Controls; | ||
using Content.Client.Guidebook.Richtext; | ||
using Content.Client.Message; | ||
using Content.Shared.Chemistry.Reagent; | ||
using Content.Shared.FixedPoint; | ||
using JetBrains.Annotations; | ||
using Robust.Client.AutoGenerated; | ||
using Robust.Client.Graphics; | ||
using Robust.Client.UserInterface; | ||
using Robust.Client.UserInterface.Controls; | ||
using Robust.Client.UserInterface.XAML; | ||
using Robust.Shared.Prototypes; | ||
using Robust.Shared.Utility; | ||
|
||
namespace Content.Client._EE.Guidebook.Controls; // Frontier: add _EE | ||
|
||
/// <summary> | ||
/// Control for embedding a food recipe into a guidebook. | ||
/// </summary> | ||
[UsedImplicitly, GenerateTypedNameReferences] | ||
public sealed partial class GuideFoodEmbed : BoxContainer, IDocumentTag, ISearchableControl | ||
{ | ||
[Dependency] private readonly IEntitySystemManager _systemManager = default!; | ||
[Dependency] private readonly IPrototypeManager _prototype = default!; | ||
|
||
private readonly FoodGuideDataSystem _foodGuideData; | ||
private readonly ISawmill _logger = default!; | ||
|
||
public GuideFoodEmbed() | ||
{ | ||
RobustXamlLoader.Load(this); | ||
IoCManager.InjectDependencies(this); | ||
_foodGuideData = _systemManager.GetEntitySystem<FoodGuideDataSystem>(); | ||
_logger = Logger.GetSawmill("food guide"); | ||
MouseFilter = MouseFilterMode.Stop; | ||
} | ||
|
||
public GuideFoodEmbed(FoodGuideEntry entry) : this() | ||
{ | ||
GenerateControl(entry); | ||
} | ||
|
||
public bool CheckMatchesSearch(string query) | ||
{ | ||
return FoodName.GetMessage()?.Contains(query, StringComparison.InvariantCultureIgnoreCase) == true | ||
|| FoodDescription.GetMessage()?.Contains(query, StringComparison.InvariantCultureIgnoreCase) == true; | ||
} | ||
|
||
public void SetHiddenState(bool state, string query) | ||
{ | ||
Visible = CheckMatchesSearch(query) ? state : !state; | ||
} | ||
|
||
public bool TryParseTag(Dictionary<string, string> args, [NotNullWhen(true)] out Control? control) | ||
{ | ||
control = null; | ||
if (!args.TryGetValue("Food", out var id)) | ||
{ | ||
_logger.Error("Food embed tag is missing food prototype argument."); | ||
return false; | ||
} | ||
|
||
if (!_foodGuideData.TryGetData(id, out var data)) | ||
{ | ||
_logger.Warning($"Specified food prototype \"{id}\" does not have any known sources."); | ||
return false; | ||
} | ||
|
||
GenerateControl(data); | ||
|
||
control = this; | ||
return true; | ||
} | ||
|
||
private void GenerateControl(FoodGuideEntry data) | ||
{ | ||
_prototype.TryIndex(data.Result, out var proto); | ||
if (proto == null) | ||
{ | ||
FoodName.SetMarkup(Loc.GetString("guidebook-food-unknown-proto", ("id", data.Result))); | ||
return; | ||
} | ||
|
||
var composition = data.Composition | ||
.Select(it => _prototype.TryIndex<ReagentPrototype>(it.Reagent.Prototype, out var reagent) ? (reagent, it.Quantity) : (null, 0)) | ||
.Where(it => it.reagent is not null) | ||
.Cast<(ReagentPrototype, FixedPoint2)>() | ||
.ToList(); | ||
|
||
#region Colors | ||
|
||
CalculateColors(composition, out var textColor, out var backgroundColor); | ||
|
||
NameBackground.PanelOverride = new StyleBoxFlat | ||
{ | ||
BackgroundColor = backgroundColor | ||
}; | ||
FoodName.SetMarkup(Loc.GetString("guidebook-food-name", ("color", textColor), ("name", proto.Name))); | ||
|
||
#endregion | ||
|
||
// Frontier: separate Recipes from Sources | ||
#region Recipes | ||
if (data.Recipes.Length > 0) | ||
RecipesContainer.Visible = true; | ||
|
||
foreach (var recipe in data.Recipes.OrderBy(it => it.OutputCount)) | ||
{ | ||
var control = new GuideFoodSource(proto, recipe, _prototype); | ||
RecipesDescriptionContainer.AddChild(control); | ||
} | ||
|
||
#endregion | ||
// End Frontier | ||
|
||
#region Sources | ||
if (data.Sources.Length > 0) // Frontier | ||
SourcesContainer.Visible = true; // Frontier | ||
|
||
foreach (var source in data.Sources.OrderBy(it => it.OutputCount)) | ||
{ | ||
var control = new GuideFoodSource(proto, source, _prototype); | ||
SourcesDescriptionContainer.AddChild(control); | ||
} | ||
|
||
#endregion | ||
|
||
#region Composition | ||
|
||
foreach (var (reagent, quantity) in composition) | ||
{ | ||
var control = new GuideFoodComposition(reagent, quantity); | ||
CompositionDescriptionContainer.AddChild(control); | ||
} | ||
|
||
#endregion | ||
|
||
FormattedMessage description = new(); | ||
description.AddText(proto?.Description ?? string.Empty); | ||
// Cannot describe food flavor or smth beause food is entirely server-side | ||
|
||
FoodDescription.SetMessage(description); | ||
} | ||
|
||
private void CalculateColors(List<(ReagentPrototype, FixedPoint2)> composition, out Color text, out Color background) | ||
{ | ||
// Background color is calculated as the weighted average of the colors of the composition. | ||
// Text color is determined based on background luminosity. | ||
float r = 0, g = 0, b = 0; | ||
FixedPoint2 weight = 0; | ||
|
||
foreach (var (proto, quantity) in composition) | ||
{ | ||
var tcolor = proto.SubstanceColor; | ||
var prevalence = | ||
quantity <= 0 ? 0f | ||
: weight == 0f ? 1f | ||
: (quantity / (weight + quantity)).Float(); | ||
|
||
r = r * (1 - prevalence) + tcolor.R * prevalence; | ||
g = g * (1 - prevalence) + tcolor.G * prevalence; | ||
b = b * (1 - prevalence) + tcolor.B * prevalence; | ||
|
||
if (quantity > 0) | ||
weight += quantity; | ||
} | ||
|
||
// Copied from GuideReagentEmbed which was probably copied from stackoverflow. This is the formula for color luminosity. | ||
var lum = 0.2126f * r + 0.7152f * g + 0.0722f; | ||
|
||
background = new Color(r, g, b); | ||
text = lum > 0.5f ? Color.Black : Color.White; | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
Content.Client/_EE/Guidebook/Controls/GuideFoodGroupEmbed.xaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<BoxContainer xmlns="https://spacestation14.io" | ||
Orientation="Vertical"> | ||
<BoxContainer Name="GroupContainer" Orientation="Vertical"/> | ||
</BoxContainer> |
38 changes: 38 additions & 0 deletions
38
Content.Client/_EE/Guidebook/Controls/GuideFoodGroupEmbed.xaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using Content.Client._EE.Nutrition.EntitySystems; | ||
using Content.Client.Guidebook.Richtext; | ||
using JetBrains.Annotations; | ||
using Robust.Client.AutoGenerated; | ||
using Robust.Client.UserInterface; | ||
using Robust.Client.UserInterface.Controls; | ||
using Robust.Client.UserInterface.XAML; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Client._EE.Guidebook.Controls; // Frontier: add _EE | ||
|
||
[UsedImplicitly, GenerateTypedNameReferences] | ||
public sealed partial class GuideFoodGroupEmbed : BoxContainer, IDocumentTag | ||
{ | ||
[Dependency] private readonly IEntitySystemManager _sysMan = default!; | ||
[Dependency] private readonly IPrototypeManager _prototype = default!; | ||
|
||
public GuideFoodGroupEmbed() | ||
{ | ||
RobustXamlLoader.Load(this); | ||
IoCManager.InjectDependencies(this); | ||
MouseFilter = MouseFilterMode.Stop; | ||
|
||
foreach (var data in _sysMan.GetEntitySystem<FoodGuideDataSystem>().Registry.OrderBy(it => it.Identifier)) | ||
{ | ||
var embed = new GuideFoodEmbed(data); | ||
GroupContainer.AddChild(embed); | ||
} | ||
} | ||
|
||
public bool TryParseTag(Dictionary<string, string> args, [NotNullWhen(true)] out Control? control) | ||
{ | ||
control = this; | ||
return true; | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
Content.Client/_EE/Guidebook/Controls/GuideFoodSource.xaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<BoxContainer xmlns="https://spacestation14.io" | ||
Orientation="Horizontal" | ||
HorizontalAlignment="Stretch" | ||
HorizontalExpand="True" | ||
Margin="0 0 0 5"> | ||
<BoxContainer Name="ReactantsContainer" Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center"> <!-- Frontier: add HorizontalExpand --> | ||
<TextureRect HorizontalAlignment="Center" | ||
Name="SourceTexture" | ||
Access="Public"/> | ||
<!-- Using rich label here because apparently normal labels do not support soft wrap --> | ||
<RichTextLabel Name="SourceLabel" | ||
HorizontalAlignment="Center" | ||
VerticalAlignment="Center" | ||
Access="Public" | ||
Margin="2 0 0 0"/> <!-- Frontier: Label<RichTextLabel --> | ||
</BoxContainer> | ||
<BoxContainer Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center"> <!-- Frontier: remove HorizontalExpand --> | ||
<TextureRect HorizontalAlignment="Center" | ||
Name="ProcessingTexture" | ||
Access="Public"/> | ||
<RichTextLabel Name="ProcessingLabel" | ||
HorizontalAlignment="Center" | ||
VerticalAlignment="Center" | ||
Access="Public" | ||
Margin="2 0 0 0"/> <!-- Frontier: Label<RichTextLabel --> | ||
</BoxContainer> | ||
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center"> <!-- Frontier: add HorizontalExpand --> | ||
<TextureRect HorizontalAlignment="Center" | ||
Name="OutputsTexture" | ||
Access="Public"/> | ||
<RichTextLabel Name="OutputsLabel" | ||
HorizontalAlignment="Center" | ||
VerticalAlignment="Center" | ||
Access="Public" | ||
Margin="2 0 0 0"/> <!-- Frontier: Label<RichTextLabel --> | ||
</BoxContainer> | ||
</BoxContainer> |
Oops, something went wrong.