Merge branch 'dev' of https://github.com/Regalis11/Barotrauma.git into unstable-tests

This commit is contained in:
Evil Factory
2022-04-08 12:52:28 -03:00
990 changed files with 44338 additions and 38589 deletions
@@ -25,12 +25,14 @@ namespace Barotrauma
get { return _toggleOpen; }
set
{
_toggleOpen = GameMain.Config.ChatOpen = value;
if (value) hideableElements.Visible = true;
_toggleOpen = PreferChatBoxOpen = value;
if (value) { hideableElements.Visible = true; }
}
}
private float openState;
public static bool PreferChatBoxOpen = true;
public bool CloseAfterMessageSent;
private float prevUIScale;
@@ -99,6 +101,7 @@ namespace Barotrauma
var channelSettingsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), channelSettingsFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true,
CanBeFocused = true,
RelativeSpacing = 0.01f
};
@@ -119,9 +122,9 @@ namespace Barotrauma
Color = new Color(51, 59, 46),
SpriteEffects = Microsoft.Xna.Framework.Graphics.SpriteEffects.FlipHorizontally
};
arrowIcon.HoverColor = arrowIcon.PressedColor = arrowIcon.PressedColor = arrowIcon.Color;
arrowIcon.HoverColor = arrowIcon.PressedColor = arrowIcon.SelectedColor = arrowIcon.Color;
channelText = new GUITextBox(new RectTransform(new Vector2(0.25f, 0.8f), channelSettingsContent.RectTransform), style: "DigitalFrameLight", textAlignment: Alignment.Center, font: GUI.DigitalFont)
channelText = new GUITextBox(new RectTransform(new Vector2(0.25f, 0.8f), channelSettingsContent.RectTransform), style: "DigitalFrameLight", textAlignment: Alignment.Center, font: GUIStyle.DigitalFont)
{
textFilterFunction = text =>
{
@@ -173,7 +176,7 @@ namespace Barotrauma
new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), channelPickerContent.RectTransform), i.ToString(), style: "GUITextBlock")
{
TextColor = new Color(51, 59, 46),
SelectedTextColor = GUI.Style.Green,
SelectedTextColor = GUIStyle.Green,
UserData = i,
OnClicked = (btn, userdata) =>
{
@@ -185,13 +188,13 @@ namespace Barotrauma
int.TryParse(channelText.Text, out int newChannel);
radio.SetChannelMemory(index, newChannel);
btn.ToolTip = TextManager.GetWithVariables("radiochannelpreset",
new string[] { "[index]", "[channel]" },
new string[] { index.ToString(), radio.GetChannelMemory(index).ToString() });
("[index]", index.ToString()),
("[channel]", radio.GetChannelMemory(index).ToString()));
channelMemPending = false;
channelPickerContent.Children.First().CanBeFocused = true;
memButton.Enabled = true;
channelPickerContent.Flash(GUI.Style.Green);
channelText.Flash(GUI.Style.Green);
channelPickerContent.Flash(GUIStyle.Green);
channelText.Flash(GUIStyle.Green);
}
SetChannel(radio.GetChannelMemory(index), setText: true);
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
@@ -224,7 +227,7 @@ namespace Barotrauma
style: "ChatTextBox")
{
OverflowClip = true,
Font = GUI.SmallFont,
Font = GUIStyle.SmallFont,
MaxTextLength = ChatMessage.MaxLength
};
@@ -265,7 +268,7 @@ namespace Barotrauma
};
showNewMessagesButton.Visible = false;
ToggleOpen = GameMain.Config.ChatOpen;
ToggleOpen = PreferChatBoxOpen = GameSettings.CurrentConfig.ChatOpen;
}
public bool TypingChatMessage(GUITextBox textBox, string text)
@@ -337,7 +340,7 @@ namespace Barotrauma
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f);
GUITextBlock senderNameTimestamp = new GUITextBlock(new RectTransform(new Vector2(0.98f, 0.0f), msgHolder.RectTransform) { AbsoluteOffset = new Point((int)(5 * GUI.Scale), 0) },
ChatMessage.GetTimeStamp(), textColor: Color.LightGray, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null)
ChatMessage.GetTimeStamp(), textColor: Color.LightGray, font: GUIStyle.SmallFont, textAlignment: Alignment.TopLeft, style: null)
{
CanBeFocused = true
};
@@ -350,9 +353,9 @@ namespace Barotrauma
{
Padding = Vector4.Zero
},
Font = GUI.SmallFont,
Font = GUIStyle.SmallFont,
CanBeFocused = true,
ForceUpperCase = false,
ForceUpperCase = ForceUpperCase.No,
UserData = message.SenderClient,
OnClicked = (_, o) =>
{
@@ -379,8 +382,8 @@ namespace Barotrauma
var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform)
{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) },
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true,
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, parseRichText: true)
RichString.Rich(displayedText), textColor: message.Color, font: GUIStyle.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true,
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f)
{
UserData = message.SenderName,
CanBeFocused = false
@@ -454,7 +457,7 @@ namespace Barotrauma
if (!string.IsNullOrEmpty(senderName))
{
var senderText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
senderName, textColor: senderColor, style: null, font: GUI.SmallFont)
senderName, textColor: senderColor, style: null, font: GUIStyle.SmallFont)
{
CanBeFocused = false
};
@@ -462,7 +465,7 @@ namespace Barotrauma
senderText.RectTransform.MinSize = new Point(0, senderText.Rect.Height);
}
var msgPopupText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true, parseRichText: true)
RichString.Rich(displayedText), textColor: message.Color, font: GUIStyle.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true)
{
CanBeFocused = false
};
@@ -553,8 +556,8 @@ namespace Barotrauma
{
int index = (int)presetButton.UserData;
presetButton.ToolTip = TextManager.GetWithVariables("radiochannelpreset",
new string[] { "[index]", "[channel]" },
new string[] { index.ToString(), radio.GetChannelMemory(index).ToString() });
("[index]", index.ToString()),
("[channel]", radio.GetChannelMemory(index).ToString()));
}
SetChannel(radio.Channel, setText: true);
prevRadio = radio;
@@ -563,7 +566,7 @@ namespace Barotrauma
{
if (channelPickerContent.FlashTimer <= 0)
{
channelPickerContent.Flash(GUI.Style.Green, flashRectInflate: new Vector2(GUI.Scale * 5.0f));
channelPickerContent.Flash(GUIStyle.Green, flashRectInflate: new Vector2(GUI.Scale * 5.0f));
}
if (PlayerInput.PrimaryMouseButtonClicked() && !GUI.IsMouseOn(channelPickerContent))
{
@@ -671,7 +674,7 @@ namespace Barotrauma
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
{
radio.Channel = channel;
GameMain.Client?.CreateEntityEvent(radio.Item, new object[] { NetEntityEvent.Type.ChangeProperty, radio.SerializableProperties["channel"] });
GameMain.Client?.CreateEntityEvent(radio.Item, new Item.ChangePropertyEventData(radio.SerializableProperties["channel".ToIdentifier()]));
if (setText)
{
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
namespace Barotrauma
{
@@ -16,7 +17,7 @@ namespace Barotrauma
Toggle
}
public class GUIComponentStyle
public class GUIComponentStyle : GUIPrefab
{
public readonly Vector4 Padding;
@@ -35,31 +36,53 @@ namespace Barotrauma
public readonly float ColorCrossFadeTime;
public readonly TransitionMode TransitionMode;
public readonly string Font;
public readonly Identifier Font;
public readonly bool ForceUpperCase;
public readonly Color OutlineColor;
public readonly XElement Element;
public readonly ContentXElement Element;
public readonly Dictionary<GUIComponent.ComponentState, List<UISprite>> Sprites;
public SpriteFallBackState FallBackState;
public Dictionary<string, GUIComponentStyle> ChildStyles;
public readonly GUIStyle Style;
public readonly GUIComponentStyle ParentStyle;
public readonly Dictionary<Identifier, GUIComponentStyle> ChildStyles;
public static GUIComponentStyle FromHierarchy(IReadOnlyList<Identifier> hierarchy)
{
if (hierarchy is null || hierarchy.None()) { return null; }
GUIStyle.ComponentStyles.TryGet(hierarchy[0], out GUIComponentStyle style);
for (int i = 1; i < hierarchy.Count; i++)
{
if (style is null) { return null; }
style.ChildStyles.TryGetValue(hierarchy[i], out style);
}
return style;
}
public static Identifier[] ToHierarchy(GUIComponentStyle style)
{
List<Identifier> ids = new List<Identifier>();
while (style != null)
{
ids.Insert(0, style.Identifier);
style = style.ParentStyle;
}
return ids.ToArray();
}
public readonly string Name;
public int? Width { get; private set; }
public int? Height { get; private set; }
public GUIComponentStyle(XElement element, GUIStyle style)
public GUIComponentStyle(ContentXElement element, UIStyleFile file, GUIComponentStyle parent = null) : base(element, file)
{
Name = element.Name.LocalName;
Style = style;
Element = element;
Sprites = new Dictionary<GUIComponent.ComponentState, List<UISprite>>();
@@ -68,7 +91,8 @@ namespace Barotrauma
Sprites[state] = new List<UISprite>();
}
ChildStyles = new Dictionary<string, GUIComponentStyle>();
ParentStyle = parent;
ChildStyles = new Dictionary<Identifier, GUIComponentStyle>();
Padding = element.GetAttributeVector4("padding", Vector4.Zero);
@@ -95,10 +119,10 @@ namespace Barotrauma
FallBackState = s;
}
Font = element.GetAttributeString("font", "");
Font = element.GetAttributeIdentifier("font", "");
ForceUpperCase = element.GetAttributeBool("forceuppercase", false);
foreach (XElement subElement in element.Elements())
foreach (var subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
@@ -106,7 +130,7 @@ namespace Barotrauma
UISprite newSprite = new UISprite(subElement);
GUIComponent.ComponentState spriteState = GUIComponent.ComponentState.None;
if (subElement.Attribute("state") != null)
if (subElement.GetAttribute("state") != null)
{
string stateStr = subElement.GetAttributeString("state", "None");
Enum.TryParse(stateStr, out spriteState);
@@ -128,15 +152,15 @@ namespace Barotrauma
case "size":
break;
default:
string styleName = subElement.Name.ToString().ToLowerInvariant();
Identifier styleName = subElement.NameAsIdentifier();
if (ChildStyles.ContainsKey(styleName))
{
DebugConsole.ThrowError("UI style \"" + element.Name.ToString() + "\" contains multiple child styles with the same name (\"" + styleName + "\")!");
ChildStyles[styleName] = new GUIComponentStyle(subElement, style);
ChildStyles[styleName] = new GUIComponentStyle(subElement, file, this);
}
else
{
ChildStyles.Add(styleName, new GUIComponentStyle(subElement, style));
ChildStyles.Add(styleName, new GUIComponentStyle(subElement, file, this));
}
break;
}
@@ -157,7 +181,7 @@ namespace Barotrauma
public void GetSize(XElement element)
{
Point size = new Point(0, 0);
foreach (XElement subElement in element.Elements())
foreach (var subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("size", StringComparison.OrdinalIgnoreCase)) { continue; }
Point maxResolution = subElement.GetAttributePoint("maxresolution", new Point(int.MaxValue, int.MaxValue));
@@ -172,5 +196,7 @@ namespace Barotrauma
if (size.X > 0) { Width = size.X; }
if (size.Y > 0) { Height = size.Y; }
}
public override void Dispose() { }
}
}
@@ -22,7 +22,7 @@ namespace Barotrauma
private GUIButton clearAllButton;
private List<CharacterInfo> PendingHires => campaign.Map?.CurrentLocation?.HireManager?.PendingHires;
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign();
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign(ClientPermissions.ManageHires);
private Point resolutionWhenCreated;
@@ -108,10 +108,10 @@ namespace Barotrauma
};
var imageWidth = (float)headerGroup.Rect.Height / headerGroup.Rect.Width;
new GUIImage(new RectTransform(new Vector2(imageWidth, 1.0f), headerGroup.RectTransform), "CrewManagementHeaderIcon");
new GUITextBlock(new RectTransform(new Vector2(1.0f - imageWidth, 1.0f), headerGroup.RectTransform), TextManager.Get("campaigncrew.header"), font: GUI.LargeFont)
new GUITextBlock(new RectTransform(new Vector2(1.0f - imageWidth, 1.0f), headerGroup.RectTransform), TextManager.Get("campaigncrew.header"), font: GUIStyle.LargeFont)
{
CanBeFocused = false,
ForceUpperCase = true
ForceUpperCase = ForceUpperCase.Yes
};
var hireablesGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
@@ -162,17 +162,17 @@ namespace Barotrauma
RelativeSpacing = 0.005f
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
TextManager.Get("campaignstore.balance"), font: GUI.Font, textAlignment: Alignment.BottomRight)
TextManager.Get("campaignstore.balance"), font: GUIStyle.Font, textAlignment: Alignment.BottomRight)
{
AutoScaleVertical = true,
ForceUpperCase = true
ForceUpperCase = ForceUpperCase.Yes
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
"", font: GUI.SubHeadingFont, textAlignment: Alignment.TopRight)
"", font: GUIStyle.SubHeadingFont, textAlignment: Alignment.TopRight)
{
AutoScaleVertical = true,
TextScale = 1.1f,
TextGetter = () => FormatCurrency(campaign.Money)
TextGetter = () => TextManager.FormatCurrency(campaign.Wallet.Balance)
};
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
@@ -182,13 +182,13 @@ namespace Barotrauma
}).RectTransform));
float height = 0.05f;
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaigncrew.pending"), font: GUI.SubHeadingFont);
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaigncrew.pending"), font: GUIStyle.SubHeadingFont);
pendingList = new GUIListBox(new RectTransform(new Vector2(1.0f, 8 * height), pendingAndCrewGroup.RectTransform))
{
Spacing = 1
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaignmenucrew"), font: GUI.SubHeadingFont);
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaignmenucrew"), font: GUIStyle.SubHeadingFont);
crewList = new GUIListBox(new RectTransform(new Vector2(1.0f, 8 * height), pendingAndCrewGroup.RectTransform))
{
Spacing = 1
@@ -196,7 +196,7 @@ namespace Barotrauma
var group = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), isHorizontal: true);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), group.RectTransform), TextManager.Get("campaignstore.total"));
totalBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), group.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
totalBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), group.RectTransform), "", font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right)
{
TextScale = 1.1f
};
@@ -207,12 +207,12 @@ namespace Barotrauma
validateHiresButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaigncrew.validate"))
{
ClickSound = GUISoundType.HireRepairClick,
ForceUpperCase = true,
ForceUpperCase = ForceUpperCase.Yes,
OnClicked = (b, o) => ValidateHires(PendingHires, true)
};
clearAllButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall"))
{
ForceUpperCase = true,
ForceUpperCase = ForceUpperCase.Yes,
Enabled = HasPermission,
OnClicked = (b, o) => RemoveAllPendingHires()
};
@@ -302,30 +302,42 @@ namespace Barotrauma
if (sortingMethod == SortingMethod.AlphabeticalAsc)
{
list.Content.RectTransform.SortChildren((x, y) =>
(x.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Name.CompareTo((y.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Name));
((InfoSkill)x.GUIComponent.UserData).CharacterInfo.Name.CompareTo(((InfoSkill)y.GUIComponent.UserData).CharacterInfo.Name));
}
else if (sortingMethod == SortingMethod.JobAsc)
{
SortCharacters(list, SortingMethod.AlphabeticalAsc);
list.Content.RectTransform.SortChildren((x, y) =>
String.Compare((x.GUIComponent.UserData as Tuple<CharacterInfo, float>)?.Item1.Job.Name, (y.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Job.Name, StringComparison.Ordinal));
String.Compare(((InfoSkill)x.GUIComponent.UserData).CharacterInfo.Job.Name.Value, ((InfoSkill)y.GUIComponent.UserData).CharacterInfo.Job.Name.Value, StringComparison.Ordinal));
}
else if (sortingMethod == SortingMethod.PriceAsc || sortingMethod == SortingMethod.PriceDesc)
{
SortCharacters(list, SortingMethod.AlphabeticalAsc);
list.Content.RectTransform.SortChildren((x, y) =>
(x.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Salary.CompareTo((y.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item1.Salary));
((InfoSkill)x.GUIComponent.UserData).CharacterInfo.Salary.CompareTo(((InfoSkill)y.GUIComponent.UserData).CharacterInfo.Salary));
if (sortingMethod == SortingMethod.PriceDesc) { list.Content.RectTransform.ReverseChildren(); }
}
else if (sortingMethod == SortingMethod.SkillAsc || sortingMethod == SortingMethod.SkillDesc)
{
SortCharacters(list, SortingMethod.AlphabeticalAsc);
list.Content.RectTransform.SortChildren((x, y) =>
(x.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item2.CompareTo((y.GUIComponent.UserData as Tuple<CharacterInfo, float>).Item2));
((InfoSkill)x.GUIComponent.UserData).SkillLevel.CompareTo(((InfoSkill)y.GUIComponent.UserData).SkillLevel));
if (sortingMethod == SortingMethod.SkillDesc) { list.Content.RectTransform.ReverseChildren(); }
}
}
private readonly struct InfoSkill
{
public readonly CharacterInfo CharacterInfo;
public readonly float SkillLevel;
public InfoSkill(CharacterInfo characterInfo, float skillLevel)
{
CharacterInfo = characterInfo;
SkillLevel = skillLevel;
}
}
private void CreateCharacterFrame(CharacterInfo characterInfo, GUIListBox listBox)
{
Skill skill = null;
@@ -338,7 +350,7 @@ namespace Barotrauma
GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.yScale * 55)), parent: listBox.Content.RectTransform), "ListBoxElement")
{
UserData = new Tuple<CharacterInfo, float>(characterInfo, skill?.Level ?? 0.0f)
UserData = new InfoSkill(characterInfo, skill?.Level ?? 0.0f)
};
GUILayoutGroup mainGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), frame.RectTransform, anchor: Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
@@ -363,7 +375,7 @@ namespace Barotrauma
nameBlock.Text = ToolBox.LimitString(nameBlock.Text, nameBlock.Font, nameBlock.Rect.Width);
GUITextBlock jobBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), nameAndJobGroup.RectTransform),
characterInfo.Job.Name, textColor: Color.White, font: GUI.SmallFont, textAlignment: Alignment.TopLeft)
characterInfo.Job.Name, textColor: Color.White, font: GUIStyle.SmallFont, textAlignment: Alignment.TopLeft)
{
CanBeFocused = false
};
@@ -374,7 +386,7 @@ namespace Barotrauma
{
GUILayoutGroup skillGroup = new GUILayoutGroup(new RectTransform(new Vector2(width, 0.6f), mainGroup.RectTransform), isHorizontal: true);
float iconWidth = (float)skillGroup.Rect.Height / skillGroup.Rect.Width;
GUIImage skillIcon = new GUIImage(new RectTransform(new Vector2(iconWidth, 1.0f), skillGroup.RectTransform), skill.Icon)
GUIImage skillIcon = new GUIImage(new RectTransform(Vector2.One, skillGroup.RectTransform, scaleBasis: ScaleBasis.Smallest), skill.Icon, scaleToFit: true)
{
CanBeFocused = false
};
@@ -388,7 +400,7 @@ namespace Barotrauma
if (listBox != crewList)
{
new GUITextBlock(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform),
FormatCurrency(characterInfo.Salary),
TextManager.FormatCurrency(characterInfo.Salary),
textAlignment: Alignment.Center)
{
CanBeFocused = false
@@ -421,7 +433,7 @@ namespace Barotrauma
else if (!btn.Enabled)
{
btn.ToolTip = string.Empty;
btn.Enabled = true;
btn.Enabled = HasPermission;
}
};
@@ -448,7 +460,7 @@ namespace Barotrauma
var confirmDialog = new GUIMessageBox(
TextManager.Get("FireWarningHeader"),
TextManager.GetWithVariable("FireWarningText", "[charactername]", ((CharacterInfo)obj).Name),
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
confirmDialog.Buttons[0].UserData = (CharacterInfo)obj;
confirmDialog.Buttons[0].OnClicked = FireCharacter;
confirmDialog.Buttons[0].OnClicked += confirmDialog.Close;
@@ -510,10 +522,11 @@ namespace Barotrauma
string name = listBox == hireableList ? characterInfo.OriginalName : characterInfo.Name;
nameBlock.Text = ToolBox.LimitString(name, nameBlock.Font, nameBlock.Rect.Width);
if (characterInfo.HasGenders)
if (characterInfo.HasSpecifierTags)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("gender"));
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get(characterInfo.Gender.ToString()));
var menuCategoryVar = characterInfo.Prefab.MenuCategoryVar;
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get(menuCategoryVar));
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get(characterInfo.ReplaceVars($"[{menuCategoryVar}]")));
}
if (characterInfo.Job is Job job)
{
@@ -523,7 +536,7 @@ namespace Barotrauma
if (characterInfo.PersonalityTrait is NPCPersonalityTrait trait)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoLabelGroup.RectTransform), TextManager.Get("PersonalityTrait"));
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get("personalitytrait." + trait.Name.Replace(" ", "")));
new GUITextBlock(new RectTransform(new Vector2(1.0f, blockHeight), infoValueGroup.RectTransform), TextManager.Get("personalitytrait." + trait.Name.Replace(" ".ToIdentifier(), Identifier.Empty)));
}
infoLabelGroup.Recalculate();
infoValueGroup.Recalculate();
@@ -568,7 +581,7 @@ namespace Barotrauma
return false;
}
hireableList.Content.RemoveChild(hireableList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo));
hireableList.Content.RemoveChild(hireableList.Content.FindChild(c => ((InfoSkill)c.UserData).CharacterInfo == characterInfo));
hireableList.UpdateScrollBarSize();
if (!PendingHires.Contains(characterInfo)) { PendingHires.Add(characterInfo); }
CreateCharacterFrame(characterInfo, pendingList);
@@ -582,14 +595,14 @@ namespace Barotrauma
private bool RemovePendingHire(CharacterInfo characterInfo, bool setTotalHireCost = true, bool createNetworkMessage = true)
{
if (PendingHires.Contains(characterInfo)) { PendingHires.Remove(characterInfo); }
pendingList.Content.RemoveChild(pendingList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo));
pendingList.Content.RemoveChild(pendingList.Content.FindChild(c => ((InfoSkill)c.UserData).CharacterInfo == characterInfo));
pendingList.UpdateScrollBarSize();
// Server will reset the names to originals in multiplayer
if (!GameMain.IsMultiplayer) { characterInfo?.ResetName(); }
if (campaign.Map.CurrentLocation.HireManager.AvailableCharacters.Any(info => info.GetIdentifierUsingOriginalName() == characterInfo.GetIdentifierUsingOriginalName()) &&
hireableList.Content.Children.None(c => c.UserData is Tuple<CharacterInfo, float> userData && userData.Item1.GetIdentifierUsingOriginalName() == characterInfo.GetIdentifierUsingOriginalName()))
hireableList.Content.Children.None(c => c.UserData is InfoSkill userData && userData.CharacterInfo.GetIdentifierUsingOriginalName() == characterInfo.GetIdentifierUsingOriginalName()))
{
CreateCharacterFrame(characterInfo, hireableList);
SortCharacters(hireableList, (SortingMethod)sortingDropDown.SelectedItemData);
@@ -603,7 +616,7 @@ namespace Barotrauma
private bool RemoveAllPendingHires(bool createNetworkMessage = true)
{
pendingList.Content.Children.ToList().ForEach(c => RemovePendingHire((c.UserData as Tuple<CharacterInfo, float>).Item1, setTotalHireCost: false, createNetworkMessage));
pendingList.Content.Children.ToList().ForEach(c => RemovePendingHire(((InfoSkill)c.UserData).CharacterInfo, setTotalHireCost: false, createNetworkMessage));
SetTotalHireCost();
return true;
}
@@ -614,12 +627,12 @@ namespace Barotrauma
int total = 0;
pendingList.Content.Children.ForEach(c =>
{
total += (c.UserData as Tuple<CharacterInfo, float>).Item1.Salary;
total += ((InfoSkill)c.UserData).CharacterInfo.Salary;
});
totalBlock.Text = FormatCurrency(total);
bool enoughMoney = campaign != null ? total <= campaign.Money : true;
totalBlock.Text = TextManager.FormatCurrency(total);
bool enoughMoney = campaign == null || campaign.Wallet.CanAfford(total);
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
validateHiresButton.Enabled = enoughMoney && pendingList.Content.RectTransform.Children.Any();
validateHiresButton.Enabled = enoughMoney && HasPermission && pendingList.Content.RectTransform.Children.Any();
}
public bool ValidateHires(List<CharacterInfo> hires, bool createNetworkEvent = false)
@@ -639,7 +652,7 @@ namespace Barotrauma
int total = nonDuplicateHires.Aggregate(0, (total, info) => total + info.Salary);
if (total > campaign.Money) { return false; }
if (!campaign.Wallet.CanAfford(total)) { return false; }
bool atLeastOneHired = false;
foreach (CharacterInfo ci in nonDuplicateHires)
@@ -661,7 +674,7 @@ namespace Barotrauma
var dialog = new GUIMessageBox(
TextManager.Get("newcrewmembers"),
TextManager.GetWithVariable("crewhiredmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.Name),
new string[] { TextManager.Get("Ok") });
new LocalizedString[] { TextManager.Get("Ok") });
dialog.Buttons[0].OnClicked += dialog.Close;
}
@@ -687,7 +700,7 @@ namespace Barotrauma
RelativeSpacing = 0.02f,
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), layoutGroup.RectTransform), TextManager.Get("campaigncrew.givenickname"), font: GUI.SubHeadingFont, textAlignment: Alignment.Center, wrap: true);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), layoutGroup.RectTransform), TextManager.Get("campaigncrew.givenickname"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center, wrap: true);
var groupElementSize = new Vector2(1.0f, 0.25f);
var nameBox = new GUITextBox(new RectTransform(groupElementSize, layoutGroup.RectTransform))
{
@@ -732,7 +745,7 @@ namespace Barotrauma
}
else
{
var crewComponent = crewList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo);
var crewComponent = crewList.Content.FindChild(c => ((InfoSkill)c.UserData).CharacterInfo == characterInfo);
if (crewComponent != null)
{
crewList.Content.RemoveChild(crewComponent);
@@ -742,7 +755,7 @@ namespace Barotrauma
}
else
{
var pendingComponent = pendingList.Content.FindChild(c => (c.UserData as Tuple<CharacterInfo, float>).Item1 == characterInfo);
var pendingComponent = pendingList.Content.FindChild(c => ((InfoSkill)c.UserData).CharacterInfo == characterInfo);
if (pendingComponent != null)
{
pendingList.Content.RemoveChild(pendingComponent);
@@ -821,15 +834,15 @@ namespace Barotrauma
characterPreviewFrame = null;
}
static (GUIComponent, CharacterInfo) FindHighlightedCharacter(GUIComponent c)
static (GUIComponent GuiComponent, CharacterInfo CharacterInfo) FindHighlightedCharacter(GUIComponent c)
{
if (c == null)
{
return default;
}
if (c.UserData is Tuple<CharacterInfo, float> highlightedData)
if (c.UserData is InfoSkill highlightedData)
{
return (c, highlightedData.Item1);
return (c, highlightedData.CharacterInfo);
}
if (c.Parent != null)
{
@@ -912,7 +925,5 @@ namespace Barotrauma
GameMain.Client.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
}
}
private string FormatCurrency(int currency) => TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", currency));
}
}
@@ -1,9 +1,11 @@
using Microsoft.Xna.Framework;
#nullable enable
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using Barotrauma.IO;
using System.Linq;
using System.Text;
using Barotrauma.Extensions;
namespace Barotrauma
{
@@ -18,7 +20,7 @@ namespace Barotrauma
}
set
{
if (value && backgroundFrame == null) { Init(); }
if (value) { InitIfNecessary(); }
if (!value)
{
fileSystemWatcher?.Dispose();
@@ -28,26 +30,31 @@ namespace Barotrauma
}
}
private static GUIFrame backgroundFrame;
private static GUIFrame window;
private static GUIListBox sidebar;
private static GUIListBox fileList;
private static GUITextBox directoryBox;
private static GUITextBox filterBox;
private static GUITextBox fileBox;
private static GUIDropDown fileTypeDropdown;
private static GUIButton openButton;
private static GUIFrame? backgroundFrame;
private static GUIFrame? window;
private static GUIListBox? sidebar;
private static GUIListBox? fileList;
private static GUITextBox? directoryBox;
private static GUITextBox? filterBox;
private static GUITextBox? fileBox;
private static GUIDropDown? fileTypeDropdown;
private static GUIButton? openButton;
private static System.IO.FileSystemWatcher fileSystemWatcher;
private static System.IO.FileSystemWatcher? fileSystemWatcher;
private static string currentFileTypePattern;
private enum ItemIsDirectory
{
Yes, No
}
private static readonly string[] ignoredDrivePrefixes = new string[]
private static string? currentFileTypePattern;
private static readonly string[] ignoredDrivePrefixes =
{
"/sys/", "/snap/"
};
private static string currentDirectory;
private static string currentDirectory = "";
public static string CurrentDirectory
{
get
@@ -91,7 +98,7 @@ namespace Barotrauma
}
}
public static Action<string> OnFileSelected
public static Action<string>? OnFileSelected
{
get;
set;
@@ -99,15 +106,16 @@ namespace Barotrauma
private static void OnFileSystemChanges(object sender, System.IO.FileSystemEventArgs e)
{
if (fileList is null) { return; }
switch (e.ChangeType)
{
case System.IO.WatcherChangeTypes.Created:
{
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), e.Name)
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), e.Name ?? string.Empty)
{
UserData = (bool?)Directory.Exists(e.FullPath)
UserData = Directory.Exists(e.FullPath) ? ItemIsDirectory.Yes : ItemIsDirectory.No
};
if ((itemFrame.UserData as bool?) ?? false)
if (itemFrame.UserData is ItemIsDirectory.Yes)
{
itemFrame.Text += "/";
}
@@ -122,11 +130,13 @@ namespace Barotrauma
break;
case System.IO.WatcherChangeTypes.Renamed:
{
System.IO.RenamedEventArgs renameArgs = e as System.IO.RenamedEventArgs;
var itemFrame = fileList.Content.FindChild(c => (c is GUITextBlock tb) && (tb.Text == renameArgs.OldName || tb.Text == renameArgs.OldName + "/")) as GUITextBlock;
itemFrame.UserData = (bool?)Directory.Exists(e.FullPath);
itemFrame.Text = renameArgs.Name;
if ((itemFrame.UserData as bool?) ?? false)
System.IO.RenamedEventArgs renameArgs = e as System.IO.RenamedEventArgs ?? throw new InvalidCastException($"Unable to cast {nameof(System.IO.FileSystemEventArgs)} to {nameof(System.IO.RenamedEventArgs)}.");
var itemFrame =
fileList.Content.FindChild(c => (c is GUITextBlock tb) && (tb.Text == renameArgs.OldName || tb.Text == renameArgs.OldName + "/")) as GUITextBlock
?? throw new Exception($"Could not find file list item with name \"{renameArgs.OldName}\"");
itemFrame.UserData = Directory.Exists(e.FullPath) ? ItemIsDirectory.Yes : ItemIsDirectory.No;
itemFrame.Text = renameArgs.Name ?? string.Empty;
if (itemFrame.UserData is ItemIsDirectory.Yes)
{
itemFrame.Text += "/";
}
@@ -138,10 +148,10 @@ namespace Barotrauma
private static int SortFiles(RectTransform r1, RectTransform r2)
{
string file1 = (r1.GUIComponent as GUITextBlock)?.Text ?? "";
string file2 = (r2.GUIComponent as GUITextBlock)?.Text ?? "";
bool dir1 = (r1.GUIComponent.UserData as bool?) ?? false;
bool dir2 = (r2.GUIComponent.UserData as bool?) ?? false;
string file1 = (r1.GUIComponent as GUITextBlock)?.Text?.SanitizedValue ?? "";
string file2 = (r2.GUIComponent as GUITextBlock)?.Text?.SanitizedValue ?? "";
bool dir1 = r1.GUIComponent.UserData is ItemIsDirectory.Yes;
bool dir2 = r2.GUIComponent.UserData is ItemIsDirectory.Yes;
if (dir1 && !dir2)
{
return -1;
@@ -154,6 +164,11 @@ namespace Barotrauma
return string.Compare(file1, file2);
}
private static void InitIfNecessary()
{
if (backgroundFrame == null) { Init(); }
}
public static void Init()
{
backgroundFrame = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas), style: null)
@@ -179,7 +194,7 @@ namespace Barotrauma
sidebar.OnSelected = (child, userdata) =>
{
CurrentDirectory = (child as GUITextBlock).Text;
CurrentDirectory = (child as GUITextBlock)?.Text.SanitizedValue ?? throw new Exception("Sidebar selection is invalid");
return false;
};
@@ -228,13 +243,14 @@ namespace Barotrauma
{
OnSelected = (child, userdata) =>
{
if (userdata == null) { return false; }
if (userdata is null) { return false; }
if (fileBox is null) { return false; }
var fileName = (child as GUITextBlock).Text;
var fileName = (child as GUITextBlock)!.Text.SanitizedValue;
fileBox.Text = fileName;
if (PlayerInput.DoubleClicked())
{
bool isDir = (userdata as bool?).Value;
bool isDir = userdata is ItemIsDirectory.Yes;
if (isDir)
{
CurrentDirectory += fileName;
@@ -263,7 +279,7 @@ namespace Barotrauma
{
OnSelected = (child, userdata) =>
{
currentFileTypePattern = (child as GUITextBlock).UserData as string;
currentFileTypePattern = (child as GUITextBlock)!.UserData as string;
RefreshFileList();
return true;
@@ -307,30 +323,31 @@ namespace Barotrauma
public static void ClearFileTypeFilters()
{
if (backgroundFrame == null) { Init(); }
fileTypeDropdown.ClearChildren();
InitIfNecessary();
fileTypeDropdown!.ClearChildren();
}
public static void AddFileTypeFilter(string name, string pattern)
{
if (backgroundFrame == null) { Init(); }
fileTypeDropdown.AddItem(name + " (" + pattern + ")", pattern);
InitIfNecessary();
fileTypeDropdown!.AddItem(name + " (" + pattern + ")", pattern);
}
public static void SelectFileTypeFilter(string pattern)
{
if (backgroundFrame == null) { Init(); }
fileTypeDropdown.SelectItem(pattern);
InitIfNecessary();
fileTypeDropdown!.SelectItem(pattern);
}
public static void RefreshFileList()
{
fileList.Content.ClearChildren();
InitIfNecessary();
fileList!.Content.ClearChildren();
fileList.BarScroll = 0.0f;
try
{
var directories = Directory.EnumerateDirectories(currentDirectory, "*" + filterBox.Text + "*");
var directories = Directory.EnumerateDirectories(currentDirectory, "*" + filterBox!.Text + "*");
foreach (var directory in directories)
{
string txt = directory;
@@ -338,7 +355,7 @@ namespace Barotrauma
if (!txt.EndsWith("/")) { txt += "/"; }
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), txt)
{
UserData = (bool?)true
UserData = ItemIsDirectory.Yes
};
var folderIcon = new GUIImage(new RectTransform(new Point((int)(itemFrame.Rect.Height * 0.8f)), itemFrame.RectTransform, Anchor.CenterLeft)
{
@@ -347,18 +364,18 @@ namespace Barotrauma
itemFrame.Padding = new Vector4(folderIcon.Rect.Width * 1.5f, itemFrame.Padding.Y, itemFrame.Padding.Z, itemFrame.Padding.W);
}
IEnumerable<string> files = null;
if (currentFileTypePattern == null)
IEnumerable<string> files = Enumerable.Empty<string>();
if (currentFileTypePattern.IsNullOrEmpty())
{
files = Directory.GetFiles(currentDirectory);
}
else
{
foreach (string pattern in currentFileTypePattern.Split(','))
foreach (string pattern in currentFileTypePattern!.Split(','))
{
string patternTrimmed = pattern.Trim();
patternTrimmed = "*" + filterBox.Text + "*" + patternTrimmed;
if (files == null)
if (files.None())
{
files = Directory.EnumerateFiles(currentDirectory, patternTrimmed);
}
@@ -375,7 +392,7 @@ namespace Barotrauma
if (txt.StartsWith(currentDirectory)) { txt = txt.Substring(currentDirectory.Length); }
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), txt)
{
UserData = (bool?)false
UserData = ItemIsDirectory.No
};
}
}
@@ -387,8 +404,8 @@ namespace Barotrauma
};
}
directoryBox.Text = currentDirectory;
fileBox.Text = "";
directoryBox!.Text = currentDirectory;
fileBox!.Text = "";
fileList.Deselect();
}
@@ -398,9 +415,9 @@ namespace Barotrauma
if (dir.EndsWith("/")) { dir = dir.Substring(0, dir.Length - 1); }
int index = dir.LastIndexOf("/");
if (index < 0) { return false; }
CurrentDirectory = CurrentDirectory.Substring(0, index+1);
CurrentDirectory = CurrentDirectory.Substring(0, index + 1);
return false;
return true;
}
public static void AddToGUIUpdateList()
File diff suppressed because it is too large Load Diff
@@ -116,32 +116,32 @@ namespace Barotrauma
get { return Frame.FlashTimer; }
}
public override ScalableFont Font
public override GUIFont Font
{
get
{
return (textBlock == null) ? GUI.Font : textBlock.Font;
return (textBlock == null) ? GUIStyle.Font : textBlock.Font;
}
set
{
base.Font = value;
if (textBlock != null) textBlock.Font = value;
if (textBlock != null) { textBlock.Font = value; }
}
}
public string Text
public LocalizedString Text
{
get { return textBlock.Text; }
set { textBlock.Text = value; }
}
public bool ForceUpperCase
public ForceUpperCase ForceUpperCase
{
get { return textBlock.ForceUpperCase; }
set { textBlock.ForceUpperCase = value; }
}
public override string ToolTip
public override RichString ToolTip
{
get
{
@@ -160,39 +160,36 @@ namespace Barotrauma
private bool flashed;
public GUISoundType ClickSound { get; set; } = GUISoundType.Click;
public GUIButton(RectTransform rectT, string text = "", Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : base(style, rectT)
public GUIButton(RectTransform rectT, Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : this(rectT, new RawLString(""), textAlignment, style, color) { }
public GUIButton(RectTransform rectT, LocalizedString text, Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : base(style, rectT)
{
CanBeFocused = true;
HoverCursor = CursorState.Hand;
frame = new GUIFrame(new RectTransform(Vector2.One, rectT), style) { CanBeFocused = false };
if (style != null) { GUI.Style.Apply(frame, style == "" ? "GUIButton" : style); }
if (style != null) { GUIStyle.Apply(frame, style == "" ? "GUIButton" : style); }
if (color.HasValue)
{
this.color = frame.Color = color.Value;
}
var selfStyle = Style;
textBlock = new GUITextBlock(new RectTransform(Vector2.One, rectT, Anchor.Center), text, textAlignment: textAlignment, style: null)
{
TextColor = this.style == null ? Color.Black : this.style.TextColor,
HoverTextColor = this.style == null ? Color.Black : this.style.HoverTextColor,
SelectedTextColor = this.style == null ? Color.Black : this.style.SelectedTextColor,
TextColor = selfStyle?.TextColor ?? Color.Black,
HoverTextColor = selfStyle?.HoverTextColor ?? Color.Black,
SelectedTextColor = selfStyle?.SelectedTextColor ?? Color.Black,
CanBeFocused = false
};
if (rectT.Rect.Height == 0 && !string.IsNullOrEmpty(text))
if (rectT.Rect.Height == 0 && !text.IsNullOrEmpty())
{
RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(textBlock.Text).Y));
RectTransform.MinSize = textBlock.RectTransform.MinSize = new Point(0, System.Math.Max(rectT.MinSize.Y, Rect.Height));
TextBlock.SetTextPos();
}
GUI.Style.Apply(textBlock, "", this);
//if the text is in chinese/korean/japanese and we're not using a CJK-compatible font,
//use the default CJK font as a fallback
if (TextManager.IsCJK(textBlock.Text) && !textBlock.Font.IsCJK)
{
textBlock.Font = GUI.CJKFont;
}
GUIStyle.Apply(textBlock, "", this);
Enabled = true;
}
@@ -217,7 +214,7 @@ namespace Barotrauma
float expand = (pulseExpand * 20.0f) * GUI.Scale;
expandRect.Inflate(expand, expand);
GUI.Style.ButtonPulse.Draw(spriteBatch, expandRect, ToolBox.GradientLerp(pulseExpand, Color.White, Color.White, Color.Transparent));
GUIStyle.EndRoundButtonPulse.Draw(spriteBatch, expandRect, ToolBox.GradientLerp(pulseExpand, Color.White, Color.White, Color.Transparent));
}
}
@@ -5,7 +5,7 @@ using Microsoft.Xna.Framework;
namespace Barotrauma
{
public class GUIColorPicker : GUIComponent
public class GUIColorPicker : GUIComponent, IDisposable
{
public delegate bool OnColorSelectedHandler(GUIColorPicker component, Color color);
public OnColorSelectedHandler? OnColorSelected;
@@ -34,11 +34,6 @@ namespace Barotrauma
public GUIColorPicker(RectTransform rectT, string? style = null) : base(style, rectT) { }
~GUIColorPicker()
{
DisposeTextures();
}
private void Init()
{
int tWidth = Rect.Width;
@@ -170,10 +165,12 @@ namespace Barotrauma
}
}
public void DisposeTextures()
public void Dispose()
{
mainTexture?.Dispose();
mainTexture = null;
hueTexture?.Dispose();
hueTexture = null;
}
public void RefreshHue()
@@ -8,6 +8,7 @@ using System.Xml.Linq;
using Barotrauma.IO;
using RestSharp;
using System.Net;
using System.Collections.Immutable;
namespace Barotrauma
{
@@ -39,7 +40,7 @@ namespace Barotrauma
public IEnumerable<T> GetAllChildren<T>() where T : GUIComponent
{
return GetAllChildren().Where(c => c is T).Select(c => c as T);
return GetAllChildren().OfType<T>();
}
/// <summary>
@@ -66,7 +67,7 @@ namespace Barotrauma
{
foreach (GUIComponent child in Children)
{
if (child.UserData == obj || (child.userData != null && child.userData.Equals(obj))) { return child; }
if (Equals(child.UserData, obj)) { return child; }
}
return null;
}
@@ -107,7 +108,7 @@ namespace Barotrauma
}
public GUIComponent FindChild(object userData, bool recursive = false)
{
var matchingChild = Children.FirstOrDefault(c => c.userData == userData);
var matchingChild = Children.FirstOrDefault(c => Equals(c.UserData, userData));
if (recursive && matchingChild == null)
{
foreach (GUIComponent child in Children)
@@ -122,7 +123,7 @@ namespace Barotrauma
public IEnumerable<GUIComponent> FindChildren(object userData)
{
return Children.Where(c => c.userData == userData);
return Children.Where(c => Equals(c.UserData, userData));
}
public IEnumerable<GUIComponent> FindChildren(Func<GUIComponent, bool> predicate)
@@ -161,9 +162,7 @@ namespace Barotrauma
protected Alignment alignment;
protected GUIComponentStyle style;
protected object userData;
protected Identifier[] styleHierarchy;
public bool CanBeFocused;
@@ -206,16 +205,14 @@ namespace Barotrauma
}
}
public virtual ScalableFont Font
public virtual GUIFont Font
{
get;
set;
}
// Use the rawtooltip when copying displayed tooltips so that any possible color-data related values are translated over as well
public string RawToolTip;
private string toolTip;
public virtual string ToolTip
private RichString toolTip;
public virtual RichString ToolTip
{
get
{
@@ -223,18 +220,12 @@ namespace Barotrauma
}
set
{
RawToolTip = value;
TooltipRichTextData = RichTextData.GetRichTextData(value, out value);
toolTip = value;
}
}
public List<RichTextData> TooltipRichTextData = null;
public GUIComponentStyle Style
{
get { return style; }
}
=> GUIComponentStyle.FromHierarchy(styleHierarchy);
public bool Visible
{
@@ -258,8 +249,8 @@ namespace Barotrauma
protected Rectangle ClampRect(Rectangle r)
{
if (Parent == null || !ClampMouseRectToParent) { return r; }
Rectangle parentRect = Parent.ClampRect(Parent.Rect);
if (Parent is null) { return r; }
Rectangle parentRect = !Parent.ClampMouseRectToParent ? Parent.Rect : Parent.ClampRect(Parent.Rect);
if (parentRect.Width <= 0 || parentRect.Height <= 0) { return Rectangle.Empty; }
if (parentRect.X > r.X)
{
@@ -293,11 +284,13 @@ namespace Barotrauma
}
public bool ClampMouseRectToParent { get; set; } = false;
public virtual Rectangle MouseRect
{
get
{
if (!CanBeFocused) { return Rectangle.Empty; }
return ClampMouseRectToParent ? ClampRect(Rect) : Rect;
}
}
@@ -310,13 +303,13 @@ namespace Barotrauma
protected ComponentState _state;
protected ComponentState _previousState;
protected bool selected;
protected bool isSelected;
public virtual bool Selected
{
get { return selected; }
get { return isSelected; }
set
{
selected = value;
isSelected = value;
foreach (var child in Children)
{
child.Selected = value;
@@ -338,11 +331,8 @@ namespace Barotrauma
}
}
public object UserData
{
get { return userData; }
set { userData = value; }
}
#warning TODO: this is cursed, stop using this
public object UserData;
public int CountChildren
{
@@ -417,20 +407,20 @@ namespace Barotrauma
Visible = true;
OutlineColor = Color.Transparent;
Font = GUI.Font;
Font = GUIStyle.Font;
CanBeFocused = true;
if (style != null) { GUI.Style.Apply(this, style); }
if (style != null) { GUIStyle.Apply(this, style); }
}
protected GUIComponent(string style)
{
Visible = true;
OutlineColor = Color.Transparent;
Font = GUI.Font;
Font = GUIStyle.Font;
CanBeFocused = true;
if (style != null) { GUI.Style.Apply(this, style); }
if (style != null) { GUIStyle.Apply(this, style); }
}
#region Updating
@@ -486,7 +476,7 @@ namespace Barotrauma
{
if (GUI.IsMouseOn(this) && PlayerInput.SecondaryMouseButtonClicked())
{
OnSecondaryClicked?.Invoke(this, userData);
OnSecondaryClicked?.Invoke(this, UserData);
}
}
@@ -704,7 +694,7 @@ namespace Barotrauma
if (GlowOnSelect && State == ComponentState.Selected)
{
GUI.UIGlow.Draw(spriteBatch, Rect, SelectedColor);
GUIStyle.UIGlow.Draw(spriteBatch, Rect, SelectedColor);
}
if (flashTimer > 0.0f)
@@ -724,7 +714,7 @@ namespace Barotrauma
}
else
{
var glow = useCircularFlash ? GUI.UIGlowCircular : GUI.UIGlow;
var glow = useCircularFlash ? GUIStyle.UIGlowCircular : GUIStyle.UIGlow;
glow.Draw(spriteBatch,
flashRect,
flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f));
@@ -738,24 +728,24 @@ namespace Barotrauma
public void DrawToolTip(SpriteBatch spriteBatch)
{
if (!Visible) { return; }
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect);
}
public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Vector2 pos, List<RichTextData> richTextData = null)
public static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Vector2 pos)
{
if (Tutorials.Tutorial.ContentRunning) { return; }
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial.ContentRunning) { return; }
int width = (int)(400 * GUI.Scale);
int height = (int)(18 * GUI.Scale);
Point padding = new Point((int)(10 * GUI.Scale));
if (toolTipBlock == null || (string)toolTipBlock.userData != toolTip)
if (toolTipBlock == null || (RichString)toolTipBlock.UserData != toolTip)
{
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), richTextData, toolTip, font: GUI.SmallFont, wrap: true, style: "GUIToolTip");
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), toolTip, font: GUIStyle.SmallFont, wrap: true, style: "GUIToolTip");
toolTipBlock.RectTransform.NonScaledSize = new Point(
(int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z),
(int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W));
toolTipBlock.userData = toolTip;
(int)(GUIStyle.SmallFont.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z),
(int)(GUIStyle.SmallFont.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W));
toolTipBlock.UserData = toolTip;
}
toolTipBlock.RectTransform.AbsoluteOffset = pos.ToPoint();
@@ -764,21 +754,21 @@ namespace Barotrauma
toolTipBlock.DrawManually(spriteBatch);
}
public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle targetElement, List<RichTextData> richTextData = null)
public static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Rectangle targetElement)
{
if (Tutorials.Tutorial.ContentRunning) { return; }
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial.ContentRunning) { return; }
int width = (int)(400 * GUI.Scale);
int height = (int)(18 * GUI.Scale);
Point padding = new Point((int)(10 * GUI.Scale));
if (toolTipBlock == null || (string)toolTipBlock.userData != toolTip)
if (toolTipBlock == null || (RichString)toolTipBlock.UserData != toolTip)
{
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), richTextData, toolTip, font: GUI.SmallFont, wrap: true, style: "GUIToolTip");
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), toolTip, font: GUIStyle.SmallFont, wrap: true, style: "GUIToolTip");
toolTipBlock.RectTransform.NonScaledSize = new Point(
(int)(toolTipBlock.Font.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z),
(int)(toolTipBlock.Font.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W));
toolTipBlock.userData = toolTip;
toolTipBlock.UserData = toolTip;
}
toolTipBlock.RectTransform.AbsoluteOffset = new Point(targetElement.Center.X, targetElement.Bottom);
@@ -811,7 +801,7 @@ namespace Barotrauma
this.useRectangleFlash = useRectangleFlash;
this.useCircularFlash = useCircularFlash;
this.flashDuration = flashDuration;
flashColor = (color == null) ? GUI.Style.Red : (Color)color;
flashColor = (color == null) ? GUIStyle.Red : (Color)color;
}
public void FadeOut(float duration, bool removeAfter, float wait = 0.0f)
@@ -952,8 +942,7 @@ namespace Barotrauma
ApplySizeRestrictions(style);
}
this.style = style;
styleHierarchy = GUIComponentStyle.ToHierarchy(style);
}
public void ApplySizeRestrictions(GUIComponentStyle style)
@@ -972,11 +961,11 @@ namespace Barotrauma
}
}
public static GUIComponent FromXML(XElement element, RectTransform parent)
public static GUIComponent FromXML(ContentXElement element, RectTransform parent)
{
GUIComponent component = null;
foreach (XElement subElement in element.Elements())
foreach (var subElement in element.Elements())
{
if (subElement.Name.ToString().Equals("conditional", StringComparison.OrdinalIgnoreCase) && !CheckConditional(subElement))
{
@@ -1027,7 +1016,7 @@ namespace Barotrauma
if (component != null)
{
foreach (XElement subElement in element.Elements())
foreach (var subElement in element.Elements())
{
if (subElement.Name.ToString().Equals("conditional", StringComparison.OrdinalIgnoreCase)) { continue; }
FromXML(subElement, component is GUIListBox listBox ? listBox.Content.RectTransform : component.RectTransform);
@@ -1078,8 +1067,9 @@ namespace Barotrauma
switch (attribute.Name.ToString().ToLowerInvariant())
{
case "language":
string[] languages = element.GetAttributeStringArray(attribute.Name.ToString(), new string[0]);
if (!languages.Any(l => GameMain.Config.Language.Equals(l, StringComparison.OrdinalIgnoreCase))) { return false; }
var languages = element.GetAttributeIdentifierArray(attribute.Name.ToString(), Array.Empty<Identifier>())
.Select(s => new LanguageIdentifier(s));
if (!languages.Any(l => GameSettings.CurrentConfig.Language == l)) { return false; }
break;
case "gameversion":
var version = new Version(attribute.Value);
@@ -1136,23 +1126,12 @@ namespace Barotrauma
if (element.Attribute("color") != null) { color = element.GetAttributeColor("color", Color.White); }
float scale = element.GetAttributeFloat("scale", 1.0f);
bool wrap = element.GetAttributeBool("wrap", true);
Alignment alignment = Alignment.Center;
Enum.TryParse(element.GetAttributeString("alignment", "Center"), out alignment);
ScalableFont font = GUI.Font;
switch (element.GetAttributeString("font", "Font").ToLowerInvariant())
Alignment alignment =
element.GetAttributeEnum("alignment", text.Contains('\n') ? Alignment.Left : Alignment.Center);
GUIFont font;
if (!GUIStyle.Fonts.TryGetValue(element.GetAttributeIdentifier("font", "Font"), out font))
{
case "font":
font = GUI.Font;
break;
case "smallfont":
font = GUI.SmallFont;
break;
case "largefont":
font = GUI.LargeFont;
break;
case "subheading":
font = GUI.SubHeadingFont;
break;
font = GUIStyle.Font;
}
var textBlock = new GUITextBlock(RectTransform.Load(element, parent),
@@ -1265,7 +1244,7 @@ namespace Barotrauma
};
}
private static GUIImage LoadGUIImage(XElement element, RectTransform parent)
private static GUIImage LoadGUIImage(ContentXElement element, RectTransform parent)
{
Sprite sprite;
string url = element.GetAttributeString("url", "");
@@ -1298,11 +1277,11 @@ namespace Barotrauma
return new GUIImage(RectTransform.Load(element, parent), sprite, scaleToFit: true);
}
private static GUIButton LoadAccordion(XElement element, RectTransform parent)
private static GUIButton LoadAccordion(ContentXElement element, RectTransform parent)
{
var button = LoadGUIButton(element, parent);
List<GUIComponent> content = new List<GUIComponent>();
foreach (XElement subElement in element.Elements())
foreach (var subElement in element.Elements())
{
var contentElement = FromXML(subElement, parent);
if (contentElement != null)
@@ -9,16 +9,23 @@ namespace Barotrauma
{
struct ContextMenuOption
{
public string Label;
public LocalizedString Label;
public Action OnSelected;
public ContextMenuOption[]? SubOptions;
public bool IsEnabled;
public string Tooltip;
public LocalizedString Tooltip;
// Creates a regular context menu
public ContextMenuOption(string label, bool isEnabled, Action onSelected)
: this(TextManager.Get(label).Fallback(label), isEnabled, onSelected) { }
public ContextMenuOption(Identifier labelTag, bool isEnabled, Action onSelected)
: this(TextManager.Get(labelTag), isEnabled, onSelected) { }
// Creates a regular context menu
public ContextMenuOption(LocalizedString label, bool isEnabled, Action onSelected)
{
Label = TextManager.Get(label, returnNull: true) ?? label;
Label = label;
OnSelected = onSelected;
IsEnabled = isEnabled;
SubOptions = null;
@@ -49,14 +56,14 @@ namespace Barotrauma
/// <param name="header">Header text</param>
/// <param name="style">Background style</param>
/// <param name="options">list of context menu options</param>
public GUIContextMenu(Vector2? position, string header, string style, params ContextMenuOption[] options) : base(style, new RectTransform(Point.Zero, GUI.Canvas))
public GUIContextMenu(Vector2? position, LocalizedString header, string style, params ContextMenuOption[] options) : base(style, new RectTransform(Point.Zero, GUI.Canvas))
{
Vector2 pos = position ?? PlayerInput.MousePosition;
ScalableFont headerFont = GUI.SubHeadingFont;
ScalableFont font = GUI.SmallFont; // font the context menu options use
GUIFont headerFont = GUIStyle.SubHeadingFont;
GUIFont font = GUIStyle.SmallFont; // font the context menu options use
Vector4 padding = new Vector4(4), headerPadding = new Vector4(8);
int horizontalPadding = (int) (padding.X + padding.Z), verticalPadding = (int) (padding.Y + padding.W);
bool hasHeader = !string.IsNullOrWhiteSpace(header);
bool hasHeader = !header.IsNullOrWhiteSpace();
//----------------------------------------------------------------------------------
// Estimate the size of the context menu
@@ -88,14 +95,21 @@ namespace Barotrauma
// Construct the GUI elements
//----------------------------------------------------------------------------------
GUILayoutGroup background = new GUILayoutGroup(new RectTransform(Vector2.One, RectTransform, Anchor.Center));
GUILayoutGroup background = new GUILayoutGroup(new RectTransform(Vector2.One, RectTransform, Anchor.Center))
{
Stretch = true
};
Point listSize = estimatedSize;
if (hasHeader)
{
HeaderLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.2f), background.RectTransform), header, font: headerFont) { Padding = headerPadding };
Point sz = Point.Zero;
InflateSize(ref sz, header, headerFont);
listSize.Y -= sz.Y;
HeaderLabel = new GUITextBlock(new RectTransform(sz, background.RectTransform), header, font: headerFont) { Padding = headerPadding };
}
GUIListBox optionList = new GUIListBox(new RectTransform(new Vector2(1f, hasHeader ? 0.8f : 1f), background.RectTransform), style: null)
GUIListBox optionList = new GUIListBox(new RectTransform(listSize, background.RectTransform), style: null)
{
AutoHideScrollBar = false,
ScrollBarVisible = false,
@@ -111,7 +125,7 @@ namespace Barotrauma
};
Options.Add(option, optionElement);
if (!string.IsNullOrWhiteSpace(option.Tooltip) && optionElement.Enabled)
if (!option.Tooltip.IsNullOrWhiteSpace() && optionElement.Enabled)
{
optionElement.ToolTip = option.Tooltip;
}
@@ -179,7 +193,7 @@ namespace Barotrauma
public static GUIContextMenu CreateContextMenu(params ContextMenuOption[] options) => CreateContextMenu(PlayerInput.MousePosition, string.Empty, null, options);
public static GUIContextMenu CreateContextMenu(Vector2? pos, string header, Color? headerColor, params ContextMenuOption[] options)
public static GUIContextMenu CreateContextMenu(Vector2? pos, LocalizedString header, Color? headerColor, params ContextMenuOption[] options)
{
GUIContextMenu menu = new GUIContextMenu(pos,header, "GUIToolTip", options);
if (headerColor != null)
@@ -209,7 +223,7 @@ namespace Barotrauma
/// <param name="label">String whose size to inflate by</param>
/// <param name="font">What font to use</param>
/// <returns>The size of the text</returns>
private Vector2 InflateSize(ref Point size, string label, ScalableFont font)
private Vector2 InflateSize(ref Point size, LocalizedString label, ScalableFont font)
{
Vector2 textSize = font.MeasureString(label);
size.X = Math.Max((int) Math.Ceiling(textSize.X), size.X);
@@ -55,9 +55,8 @@ namespace Barotrauma
{
get { return listBox.SelectedComponent; }
}
// TODO: fix implicit hiding
public bool Selected
public override bool Selected
{
get
{
@@ -97,7 +96,7 @@ namespace Barotrauma
set { button.TextColor = value; }
}
public override ScalableFont Font
public override GUIFont Font
{
get { return button?.Font ?? base.Font; }
set
@@ -142,13 +141,13 @@ namespace Barotrauma
get { return selectedIndexMultiple; }
}
public string Text
public LocalizedString Text
{
get { return button.Text; }
set { button.Text = value; }
}
public override string ToolTip
public override RichString ToolTip
{
get
{
@@ -162,18 +161,21 @@ namespace Barotrauma
}
}
public GUIDropDown(RectTransform rectT, string text = "", int elementCount = 4, string style = "", bool selectMultiple = false, bool dropAbove = false) : base(style, rectT)
public GUIDropDown(RectTransform rectT, LocalizedString text = null, int elementCount = 4, string style = "", bool selectMultiple = false, bool dropAbove = false, Alignment textAlignment = Alignment.CenterLeft) : base(style, rectT)
{
text ??= new RawLString("");
HoverCursor = CursorState.Hand;
CanBeFocused = true;
this.selectMultiple = selectMultiple;
button = new GUIButton(new RectTransform(Vector2.One, rectT), text, Alignment.CenterLeft, style: "GUIDropDown")
button = new GUIButton(new RectTransform(Vector2.One, rectT), text, textAlignment, style: "GUIDropDown")
{
OnClicked = OnClicked
OnClicked = OnClicked,
TextBlock = { OverflowClip = true }
};
GUI.Style.Apply(button, "", this);
GUIStyle.Apply(button, "", this);
button.TextBlock.SetTextPos();
Anchor listAnchor = dropAbove ? Anchor.TopCenter : Anchor.BottomCenter;
@@ -184,13 +186,13 @@ namespace Barotrauma
Enabled = !selectMultiple
};
if (!selectMultiple) { listBox.OnSelected = SelectItem; }
GUI.Style.Apply(listBox, "GUIListBox", this);
GUI.Style.Apply(listBox.ContentBackground, "GUIListBox", this);
GUIStyle.Apply(listBox, "GUIListBox", this);
GUIStyle.Apply(listBox.ContentBackground, "GUIListBox", this);
if (button.Style.ChildStyles.ContainsKey("dropdownicon"))
if (button.Style.ChildStyles.ContainsKey("dropdownicon".ToIdentifier()))
{
icon = new GUIImage(new RectTransform(new Vector2(0.6f, 0.6f), button.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point(5, 0) }, null, scaleToFit: true);
icon.ApplyStyle(button.Style.ChildStyles["dropdownicon"]);
icon.ApplyStyle(button.Style.ChildStyles["dropdownicon".ToIdentifier()]);
}
currentHighestParent = FindHighestParent();
@@ -244,8 +246,9 @@ namespace Barotrauma
return parentHierarchy.Last();
}
public void AddItem(string text, object userData = null, string toolTip = "")
public void AddItem(LocalizedString text, object userData = null, LocalizedString toolTip = null)
{
toolTip ??= "";
if (selectMultiple)
{
var frame = new GUIFrame(new RectTransform(new Point(button.Rect.Width, button.Rect.Height), listBox.Content.RectTransform)
@@ -261,7 +264,7 @@ namespace Barotrauma
ToolTip = toolTip,
OnSelected = (GUITickBox tb) =>
{
List<string> texts = new List<string>();
List<LocalizedString> texts = new List<LocalizedString>();
selectedDataMultiple.Clear();
selectedIndexMultiple.Clear();
int i = 0;
@@ -276,7 +279,7 @@ namespace Barotrauma
}
i++;
}
button.Text = string.Join(", ", texts);
button.Text = LocalizedString.Join(", ", texts);
// TODO: The callback is called at least twice, remove this?
OnSelected?.Invoke(tb.Parent, tb.Parent.UserData);
return true;
@@ -311,13 +314,12 @@ namespace Barotrauma
foreach (GUIComponent child in ListBox.Content.Children)
{
var tickBox = child.GetChild<GUITickBox>();
if (obj == child.UserData) { tickBox.Selected = true; }
if (Equals(obj, child.UserData)) { tickBox.Selected = true; }
}
}
else
{
GUITextBlock textBlock = component as GUITextBlock;
if (textBlock == null)
if (!(component is GUITextBlock textBlock))
{
textBlock = component.GetChild<GUITextBlock>();
if (textBlock is null && !AllowNonText) { return false; }
@@ -368,8 +370,9 @@ namespace Barotrauma
Dropped = !Dropped;
if (Dropped && Enabled)
{
OnDropped?.Invoke(this, userData);
OnDropped?.Invoke(this, UserData);
listBox.UpdateScrollBarSize();
listBox.UpdateDimensions();
GUI.KeyboardDispatcher.Subscriber = this;
}
@@ -177,6 +177,7 @@ namespace Barotrauma
spriteBatch.Begin(blendState: BlendState, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
}
var style = Style;
if (style != null)
{
foreach (UISprite uiSprite in style.Sprites[State])
@@ -193,7 +194,7 @@ namespace Barotrauma
}
}
}
else if (sprite?.Texture != null)
else if (sprite?.Texture is { IsDisposed: false })
{
spriteBatch.Draw(sprite.Texture, Rect.Center.ToVector2(), sourceRect, currentColor * (currentColor.A / 255.0f), Rotation, origin,
Scale, SpriteEffects, 0.0f);
@@ -92,29 +92,19 @@ namespace Barotrauma
foreach (RectTransform child in RectTransform.Children)
{
if (child.GUIComponent.IgnoreLayoutGroups) { continue; }
if (child.ScaleBasis == ScaleBasis.BothHeight) { child.MinSize = new Point(child.Rect.Height, child.MinSize.Y); }
if (child.ScaleBasis == ScaleBasis.BothWidth) { child.MinSize = new Point(child.MinSize.X, child.Rect.Width); }
if (child.ScaleBasis == ScaleBasis.Smallest)
switch (child.ScaleBasis)
{
if (Rect.Width < Rect.Height)
{
child.MinSize = new Point(child.MinSize.X, child.Rect.Width);
}
else
{
child.MinSize = new Point(child.Rect.Height, child.MinSize.Y);
}
}
if (child.ScaleBasis == ScaleBasis.Largest)
{
if (Rect.Width > Rect.Height)
{
child.MinSize = new Point(child.MinSize.X, child.Rect.Width);
}
else
{
child.MinSize = new Point(child.Rect.Height, child.MinSize.Y);
}
case ScaleBasis.BothHeight:
case ScaleBasis.Smallest when Rect.Height <= Rect.Width:
case ScaleBasis.Largest when Rect.Height > Rect.Width:
child.MinSize = new Point((int)((child.Rect.Height * child.RelativeSize.X) / child.RelativeSize.Y), child.MinSize.Y);
break;
case ScaleBasis.BothWidth:
case ScaleBasis.Smallest when Rect.Width <= Rect.Height:
case ScaleBasis.Largest when Rect.Width > Rect.Height:
child.MinSize = new Point(child.MinSize.X, (int)((child.Rect.Width * child.RelativeSize.Y) / child.RelativeSize.X));
break;
}
}
@@ -144,42 +134,65 @@ namespace Barotrauma
foreach (var child in RectTransform.Children)
{
if (child.GUIComponent.IgnoreLayoutGroups) { continue; }
float currentStretchFactor = child.ScaleBasis == ScaleBasis.Normal ? stretchFactor : 1.0f;
child.SetPosition(childAnchor);
void advancePositionsAndCalculateChildSizes(
ref int childNonScaledSize,
ref float childRelativeSize,
int childMinSize,
int childMaxSize,
int childRectSize,
int selfRectSize)
{
if (child.IsFixedSize)
{
absPos += childNonScaledSize + absoluteSpacing;
}
else
{
absPos += (int)Math.Round(MathHelper.Clamp(childRectSize * currentStretchFactor, childMinSize, childMaxSize) + (absoluteSpacing * currentStretchFactor));
if (stretch)
{
float relativeSize =
MathF.Round(childRelativeSize * currentStretchFactor * selfRectSize) / selfRectSize;
childRelativeSize = relativeSize;
}
}
}
Point childNonScaledSize = child.NonScaledSize;
Vector2 childRelativeSize = child.RelativeSize;
if (isHorizontal)
{
child.RelativeOffset = new Vector2(relPos, child.RelativeOffset.Y);
child.AbsoluteOffset = new Point(absPos, child.AbsoluteOffset.Y);
if (child.IsFixedSize)
{
absPos += child.NonScaledSize.X + absoluteSpacing;
}
else
{
absPos += (int)(MathHelper.Clamp(child.Rect.Width * stretchFactor, child.MinSize.X, child.MaxSize.X) + (absoluteSpacing * stretchFactor));
if (stretch)
{
child.RelativeSize = new Vector2(child.RelativeSize.X * stretchFactor, child.RelativeSize.Y);
}
}
advancePositionsAndCalculateChildSizes(
ref childNonScaledSize.X,
ref childRelativeSize.X,
child.MinSize.X,
child.MaxSize.X,
child.Rect.Width,
Rect.Width);
}
else
{
child.RelativeOffset = new Vector2(child.RelativeOffset.X, relPos);
child.AbsoluteOffset = new Point(child.AbsoluteOffset.X, absPos);
if (child.IsFixedSize)
{
absPos += child.NonScaledSize.Y + absoluteSpacing;
}
else
{
absPos += (int)(MathHelper.Clamp(child.Rect.Height * stretchFactor, child.MinSize.Y, child.MaxSize.Y) + (absoluteSpacing * stretchFactor));
if (stretch)
{
child.RelativeSize = new Vector2(child.RelativeSize.X, child.RelativeSize.Y * stretchFactor);
}
}
advancePositionsAndCalculateChildSizes(
ref childNonScaledSize.Y,
ref childRelativeSize.Y,
child.MinSize.Y,
child.MaxSize.Y,
child.Rect.Height,
Rect.Height);
}
child.NonScaledSize = childNonScaledSize;
child.RelativeSize = childRelativeSize;
relPos += relativeSpacing * stretchFactor;
if (isHorizontal) { relPos = MathF.Round(relPos * Rect.Width) / Rect.Width; }
else { relPos = MathF.Round(relPos * Rect.Height) / Rect.Height; }
}
needsToRecalculate = false;
}
@@ -148,7 +148,11 @@ namespace Barotrauma
}
// TODO: fix implicit hiding
public bool Selected { get; set; }
public override bool Selected
{
get { return isSelected; }
set { isSelected = value; }
}
public IReadOnlyList<GUIComponent> AllSelected => selected;
@@ -328,7 +332,7 @@ namespace Barotrauma
};
if (style != null)
{
GUI.Style.Apply(ContentBackground, "", this);
GUIStyle.Apply(ContentBackground, "", this);
}
if (color.HasValue)
{
@@ -398,8 +402,7 @@ namespace Barotrauma
int i = 0;
foreach (GUIComponent child in children)
{
if ((child.UserData != null && child.UserData.Equals(userData)) ||
(child.UserData == null && userData == null))
if (Equals(child.UserData, userData))
{
Select(i, force, autoScroll);
if (!SelectMultiple) { return; }
@@ -435,7 +438,7 @@ namespace Barotrauma
Vector2 topOffset = CalculateTopOffset();
int x = (int)topOffset.X;
int y = (int)topOffset.Y;
for (int i = 0; i < Content.CountChildren; i++)
{
GUIComponent child = Content.GetChild(i);
@@ -509,23 +512,36 @@ namespace Barotrauma
}
/// <summary>
/// Scrolls the list to the specific element, currently only works when smooth scrolling and PadBottom are enabled.
/// Scrolls the list to the specific element.
/// </summary>
/// <param name="component"></param>
public void ScrollToElement(GUIComponent component)
public void ScrollToElement(GUIComponent component, bool playSound = true)
{
SoundPlayer.PlayUISound(GUISoundType.Click);
if (playSound) { SoundPlayer.PlayUISound(GUISoundType.Click); }
List<GUIComponent> children = Content.Children.ToList();
int index = children.IndexOf(component);
if (index < 0) { return; }
void performScroll(GUIComponent c)
{
if (SmoothScroll && PadBottom)
{
scrollToElement = c;
}
else
{
float diff = isHorizontal ? c.Rect.X - Content.Rect.X : c.Rect.Y - Content.Rect.Y;
ScrollBar.BarScroll += diff / TotalSize;
}
}
if (!Content.Children.Contains(component) || !component.Visible)
{
scrollToElement = null;
performScroll(null);
}
else
{
scrollToElement = component;
performScroll(component);
}
}
@@ -1215,6 +1231,20 @@ namespace Barotrauma
i++;
}
if (isDraggingElement && CurrentDragMode == DragMode.DragOutsideBox && HideDraggedElement)
{
Rectangle drawRect = DraggedElement.Rect;
int draggedElementIndex = Content.GetChildIndex(DraggedElement);
CalculateChildrenOffsets((index, point) =>
{
if (draggedElementIndex == index)
{
drawRect.Location = Content.Rect.Location + point;
}
});
GUI.DrawRectangle(spriteBatch, drawRect, Color.White * 0.5f, thickness: 2f);
}
if (HideChildrenOutsideFrame)
{
spriteBatch.End();
@@ -10,7 +10,8 @@ namespace Barotrauma
{
public class GUIMessageBox : GUIFrame
{
public static List<GUIComponent> MessageBoxes = new List<GUIComponent>();
#warning TODO: change this to List<GUIMessageBox> and fix incorrect uses of this list
public readonly static List<GUIComponent> MessageBoxes = new List<GUIComponent>();
private static int DefaultWidth
{
get { return Math.Max(400, (int)(400 * (GameMain.GraphicsWidth / GUI.ReferenceResolution.X))); }
@@ -70,14 +71,14 @@ namespace Barotrauma
public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault();
public GUIMessageBox(string headerText, string text, Vector2? relativeSize = null, Point? minSize = null)
: this(headerText, text, new string[] { "OK" }, relativeSize, minSize)
public GUIMessageBox(LocalizedString headerText, LocalizedString text, Vector2? relativeSize = null, Point? minSize = null)
: this(headerText, text, new LocalizedString[] { "OK" }, relativeSize, minSize)
{
this.Buttons[0].OnClicked = Close;
}
public GUIMessageBox(string headerText, string text, string[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", Sprite icon = null, string iconStyle = "", Sprite backgroundIcon = null, bool parseRichText = false)
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
public GUIMessageBox(RichString headerText, RichString text, LocalizedString[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", Sprite icon = null, string iconStyle = "", Sprite backgroundIcon = null)
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUIStyle.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
{
int width = (int)(DefaultWidth * type switch
{
@@ -125,23 +126,24 @@ namespace Barotrauma
InnerFrame.RectTransform.ScreenSpaceOffset = new Point(-offset, offset);
CanBeFocused = false;
}
GUI.Style.Apply(InnerFrame, "", this);
GUIStyle.Apply(InnerFrame, "", this);
this.type = type;
Tag = tag;
#warning TODO: These should be broken into separate methods at least
if (type == Type.Default || type == Type.Vote)
{
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform),
headerText, font: GUI.SubHeadingFont, textAlignment: Alignment.Center, wrap: true, parseRichText: parseRichText);
GUI.Style.Apply(Header, "", this);
headerText, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center, wrap: true);
GUIStyle.Apply(Header, "", this);
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
if (!string.IsNullOrWhiteSpace(text))
if (!text.IsNullOrWhiteSpace())
{
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true, parseRichText: parseRichText);
GUI.Style.Apply(Text, "", this);
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
GUIStyle.Apply(Text, "", this);
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
new Point(Text.Rect.Width, Text.Rect.Height);
Text.RectTransform.IsFixedSize = true;
@@ -154,7 +156,7 @@ namespace Barotrauma
};
int buttonSize = 35;
var buttonStyle = GUI.Style.GetComponentStyle("GUIButton");
var buttonStyle = GUIStyle.GetComponentStyle("GUIButton");
if (buttonStyle != null && buttonStyle.Height.HasValue)
{
buttonSize = buttonStyle.Height.Value;
@@ -189,7 +191,7 @@ namespace Barotrauma
InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight);
CanBeFocused = false;
AutoClose = true;
GUI.Style.Apply(InnerFrame, "", this);
GUIStyle.Apply(InnerFrame, "", this);
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), InnerFrame.RectTransform, Anchor.Center),
isHorizontal: true, childAnchor: Anchor.CenterLeft)
@@ -219,11 +221,11 @@ namespace Barotrauma
};
InputType? closeInput = null;
if (GameMain.Config.KeyBind(InputType.Use).MouseButton == MouseButton.None)
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Use].MouseButton == MouseButton.None)
{
closeInput = InputType.Use;
}
else if (GameMain.Config.KeyBind(InputType.Select).MouseButton == MouseButton.None)
else if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select].MouseButton == MouseButton.None)
{
closeInput = InputType.Select;
}
@@ -236,24 +238,24 @@ namespace Barotrauma
{
GUIButton btn = component as GUIButton;
btn?.OnClicked(btn, btn.UserData);
btn?.Flash(GUI.Style.Green);
btn?.Flash(GUIStyle.Green);
}
};
}
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true, parseRichText: parseRichText);
GUI.Style.Apply(Header, "", this);
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true);
GUIStyle.Apply(Header, "", this);
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
if (!string.IsNullOrWhiteSpace(text))
if (!text.IsNullOrWhiteSpace())
{
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true, parseRichText: parseRichText);
GUI.Style.Apply(Text, "", this);
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
GUIStyle.Apply(Text, "", this);
Content.Recalculate();
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
new Point(Text.Rect.Width, Text.Rect.Height);
Text.RectTransform.IsFixedSize = true;
if (string.IsNullOrWhiteSpace(headerText))
if (headerText.IsNullOrWhiteSpace())
{
Content.ChildAnchor = Anchor.Center;
}
@@ -275,7 +277,7 @@ namespace Barotrauma
else if (type == Type.Hint)
{
CanBeFocused = false;
GUI.Style.Apply(InnerFrame, "", this);
GUIStyle.Apply(InnerFrame, "", this);
Point absoluteSpacing = GUIStyle.ItemFrameMargin.Multiply(1.0f / 5.0f);
var verticalLayoutGroup = new GUILayoutGroup(new RectTransform(GetVerticalLayoutGroupSize(), parent: InnerFrame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter)
@@ -353,18 +355,18 @@ namespace Barotrauma
};
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true);
GUI.Style.Apply(Header, "", this);
GUIStyle.Apply(Header, "", this);
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
if (!string.IsNullOrWhiteSpace(text))
if (!text.IsNullOrWhiteSpace())
{
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
GUI.Style.Apply(Text, "", this);
GUIStyle.Apply(Text, "", this);
Content.Recalculate();
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
new Point(Text.Rect.Width, Text.Rect.Height);
Text.RectTransform.IsFixedSize = true;
if (string.IsNullOrWhiteSpace(headerText))
if (headerText.IsNullOrWhiteSpace())
{
Header.RectTransform.Parent = null;
Content.ChildAnchor = Anchor.Center;
@@ -410,7 +412,7 @@ namespace Barotrauma
/// <summary>
/// Use to create a message box of Hint type
/// </summary>
public GUIMessageBox(string hintIdentifier, string text, Sprite icon) : this("", text, new string[0], textAlignment: Alignment.CenterLeft, type: Type.Hint, icon: icon)
public GUIMessageBox(Identifier hintIdentifier, LocalizedString text, Sprite icon) : this("", text, Array.Empty<LocalizedString>(), textAlignment: Alignment.CenterLeft, type: Type.Hint, icon: icon)
{
if (InnerFrame.FindChild("dontshowagain", recursive: true) is GUITickBox dontShowAgainTickBox)
{
@@ -12,9 +12,12 @@ namespace Barotrauma
Int, Float
}
public delegate void OnValueEnteredHandler(GUINumberInput numberInput);
public OnValueEnteredHandler OnValueEntered;
public delegate void OnValueChangedHandler(GUINumberInput numberInput);
public OnValueChangedHandler OnValueChanged;
public GUITextBox TextBox { get; private set; }
public GUIButton PlusButton { get; private set; }
@@ -162,7 +165,7 @@ namespace Barotrauma
}
}
public override ScalableFont Font
public override GUIFont Font
{
get
{
@@ -209,6 +212,8 @@ namespace Barotrauma
{
ClampFloatValue();
}
OnValueEntered?.Invoke(this);
};
TextBox.OnEnterPressed += (textBox, text) =>
{
@@ -220,12 +225,14 @@ namespace Barotrauma
{
ClampFloatValue();
}
OnValueEntered?.Invoke(this);
return true;
};
var buttonArea = new GUIFrame(new RectTransform(new Vector2(_relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform, Anchor.CenterRight), style: null);
PlusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), style: null);
GUI.Style.Apply(PlusButton, "PlusButton", this);
GUIStyle.Apply(PlusButton, "PlusButton", this);
PlusButton.OnButtonDown += () =>
{
pressedTimer = pressedDelay;
@@ -246,7 +253,7 @@ namespace Barotrauma
};
MinusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), style: null);
GUI.Style.Apply(MinusButton, "MinusButton", this);
GUIStyle.Apply(MinusButton, "MinusButton", this);
MinusButton.OnButtonDown += () =>
{
pressedTimer = pressedDelay;
@@ -0,0 +1,395 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Barotrauma
{
public abstract class GUIPrefab : Prefab
{
public GUIPrefab(ContentXElement element, UIStyleFile file) : base(file, element) { }
protected override Identifier DetermineIdentifier(XElement element)
{
return element.NameAsIdentifier();
}
}
public abstract class GUISelector<T> where T : GUIPrefab
{
public readonly PrefabSelector<T> Prefabs = new PrefabSelector<T>();
public readonly Identifier Identifier;
public GUISelector(string identifier)
{
Identifier = identifier.ToIdentifier();
}
}
public class GUIFontPrefab : GUIPrefab
{
private readonly ContentXElement element;
private ScalableFont font;
public ScalableFont Font
{
get
{
if (Language != GameSettings.CurrentConfig.Language) { LoadFont(); }
return font;
}
}
private ScalableFont cjkFont;
public ScalableFont CjkFont
{
get
{
if (Language != GameSettings.CurrentConfig.Language) { LoadFont(); }
if (font.IsCJK) { return font; }
return cjkFont;
}
}
public LanguageIdentifier Language { get; private set; }
public GUIFontPrefab(ContentXElement element, UIStyleFile file) : base(element, file)
{
this.element = element;
LoadFont();
}
public void LoadFont()
{
string fontPath = GetFontFilePath(element);
uint size = GetFontSize(element);
bool dynamicLoading = GetFontDynamicLoading(element);
bool isCJK = GetIsCJK(element);
font?.Dispose();
cjkFont?.Dispose();
font = new ScalableFont(fontPath, size, GameMain.Instance.GraphicsDevice, dynamicLoading, isCJK)
{
ForceUpperCase = element.GetAttributeBool("forceuppercase", false)
};
if (!isCJK)
{
cjkFont = ExtractCjkFont(element)
?? new ScalableFont("Content/Fonts/NotoSans/NotoSansCJKsc-Bold.otf",
font.Size, GameMain.Instance.GraphicsDevice, dynamicLoading: true, isCJK: true);
cjkFont.ForceUpperCase = font.ForceUpperCase;
}
Language = GameSettings.CurrentConfig.Language;
}
public override void Dispose()
{
font?.Dispose(); font = null;
cjkFont?.Dispose(); cjkFont = null;
}
private ScalableFont ExtractCjkFont(ContentXElement element)
{
foreach (var subElement in element.Elements().Reverse())
{
if (subElement.NameAsIdentifier() != "override") { continue; }
if (subElement.GetAttributeBool("iscjk", false))
{
return new ScalableFont(subElement, GameMain.Instance.GraphicsDevice);
}
}
return null;
}
private string GetFontFilePath(ContentXElement element)
{
foreach (var subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
{
return subElement.GetAttributeContentPath("file")?.Value;
}
}
return element.GetAttributeContentPath("file")?.Value;
}
private uint GetFontSize(XElement element, uint defaultSize = 14)
{
//check if any of the language override fonts want to override the font size as well
foreach (var subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
{
uint overrideFontSize = GetFontSize(subElement, 0);
if (overrideFontSize > 0) { return (uint)Math.Round(overrideFontSize * GameSettings.CurrentConfig.Graphics.TextScale); }
}
}
foreach (var subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("size", StringComparison.OrdinalIgnoreCase)) { continue; }
Point maxResolution = subElement.GetAttributePoint("maxresolution", new Point(int.MaxValue, int.MaxValue));
if (GameMain.GraphicsWidth <= maxResolution.X && GameMain.GraphicsHeight <= maxResolution.Y)
{
return (uint)Math.Round(subElement.GetAttributeInt("size", 14) * GameSettings.CurrentConfig.Graphics.TextScale);
}
}
return (uint)Math.Round(defaultSize * GameSettings.CurrentConfig.Graphics.TextScale);
}
private bool GetFontDynamicLoading(XElement element)
{
foreach (var subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
{
return subElement.GetAttributeBool("dynamicloading", false);
}
}
return element.GetAttributeBool("dynamicloading", false);
}
private bool GetIsCJK(XElement element)
{
foreach (var subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
{
return subElement.GetAttributeBool("iscjk", false);
}
}
return element.GetAttributeBool("iscjk", false);
}
}
public class GUIFont : GUISelector<GUIFontPrefab>
{
public GUIFont(string identifier) : base(identifier) { }
public bool HasValue => Prefabs.Any();
public ScalableFont Value => Prefabs.ActivePrefab.Font;
public static implicit operator ScalableFont(GUIFont reference) => reference.Value;
public bool ForceUpperCase => HasValue && Value.ForceUpperCase;
public uint Size => HasValue ? Value.Size : 0;
private ScalableFont GetFontForStr(LocalizedString str) => GetFontForStr(str.Value);
private ScalableFont GetFontForStr(string str) =>
TextManager.IsCJK(str) ? Prefabs.ActivePrefab.CjkFont : Prefabs.ActivePrefab.Font;
public void DrawString(SpriteBatch sb, LocalizedString text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth)
{
DrawString(sb, text.Value, position, color, rotation, origin, scale, se, layerDepth);
}
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth)
{
GetFontForStr(text).DrawString(sb, text, position, color, rotation, origin, scale, se, layerDepth);
}
public void DrawString(SpriteBatch sb, LocalizedString text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, Alignment alignment = Alignment.TopLeft)
{
DrawString(sb, text.Value, position, color, rotation, origin, scale, se, layerDepth, alignment);
}
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, Alignment alignment = Alignment.TopLeft, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit)
{
GetFontForStr(text).DrawString(sb, text, position, color, rotation, origin, scale, se, layerDepth, alignment, forceUpperCase);
}
public void DrawString(SpriteBatch sb, LocalizedString text, Vector2 position, Color color, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit, bool italics = false)
{
DrawString(sb, text.Value, position, color, forceUpperCase, italics);
}
public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit, bool italics = false)
{
GetFontForStr(text).DrawString(sb, text, position, color, forceUpperCase, italics);
}
public void DrawStringWithColors(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth, in ImmutableArray<RichTextData>? richTextData, int rtdOffset = 0, Alignment alignment = Alignment.TopLeft, ForceUpperCase forceUpperCase = Barotrauma.ForceUpperCase.Inherit)
{
GetFontForStr(text).DrawStringWithColors(sb, text, position, color, rotation, origin, scale, se, layerDepth, richTextData, rtdOffset, alignment, forceUpperCase);
}
public Vector2 MeasureString(LocalizedString str, bool removeExtraSpacing = false)
{
return GetFontForStr(str).MeasureString(str, removeExtraSpacing);
}
public Vector2 MeasureChar(char c)
{
return GetFontForStr($"{c}").MeasureChar(c);
}
public string WrapText(string text, float width)
=> GetFontForStr(text).WrapText(text, width);
public string WrapText(string text, float width, int requestCharPos, out Vector2 requestedCharPos)
=> GetFontForStr(text).WrapText(text, width, requestCharPos, out requestedCharPos);
public string WrapText(string text, float width, out Vector2[] allCharPositions)
=> GetFontForStr(text).WrapText(text, width, out allCharPositions);
public float LineHeight => Value.LineHeight;
}
public class GUIColorPrefab : GUIPrefab
{
public readonly Color Color;
public GUIColorPrefab(ContentXElement element, UIStyleFile file) : base(element, file)
{
Color = element.GetAttributeColor("color", Color.White);
}
public override void Dispose() { }
}
public class GUIColor : GUISelector<GUIColorPrefab>
{
public GUIColor(string identifier) : base(identifier) { }
public Color Value
{
get
{
return Prefabs.ActivePrefab.Color;
}
}
public static implicit operator Color(GUIColor reference) => reference.Value;
public static Color operator*(GUIColor value, float scale)
{
return value.Value * scale;
}
}
public class GUISpritePrefab : GUIPrefab
{
public readonly UISprite Sprite;
public GUISpritePrefab(ContentXElement element, UIStyleFile file) : base(element, file)
{
Sprite = new UISprite(element);
}
public override void Dispose()
{
Sprite.Sprite.Remove();
}
}
public class GUISprite : GUISelector<GUISpritePrefab>
{
public GUISprite(string identifier) : base(identifier) { }
public UISprite Value
{
get
{
return Prefabs.ActivePrefab.Sprite;
}
}
public static implicit operator UISprite(GUISprite reference) => reference.Value;
public void Draw(SpriteBatch spriteBatch, Rectangle rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None)
{
Value.Draw(spriteBatch, rect, color, spriteEffects);
}
}
public class GUISpriteSheetPrefab : GUIPrefab
{
public readonly SpriteSheet SpriteSheet;
public GUISpriteSheetPrefab(ContentXElement element, UIStyleFile file) : base(element, file)
{
SpriteSheet = new SpriteSheet(element);
}
public override void Dispose()
{
SpriteSheet.Remove();
}
}
public class GUISpriteSheet : GUISelector<GUISpriteSheetPrefab>
{
public GUISpriteSheet(string identifier) : base(identifier) { }
public SpriteSheet Value
{
get
{
return Prefabs.ActivePrefab.SpriteSheet;
}
}
public int FrameCount => Value.FrameCount;
public Point FrameSize => Value.FrameSize;
public void Draw(ISpriteBatch spriteBatch, Vector2 pos, float rotate = 0, float scale = 1, SpriteEffects spriteEffects = SpriteEffects.None)
{
Value.Draw(spriteBatch, pos, rotate, scale, spriteEffects);
}
public void Draw(ISpriteBatch spriteBatch, Vector2 pos, Color color, Vector2 origin, float rotate = 0, float scale = 1, SpriteEffects spriteEffects = SpriteEffects.None, float? depth = null)
{
Value.Draw(spriteBatch, pos, color, origin, rotate, scale, spriteEffects, depth);
}
public void Draw(ISpriteBatch spriteBatch, int spriteIndex, Vector2 pos, Color color, Vector2 origin, float rotate, Vector2 scale, SpriteEffects spriteEffects = SpriteEffects.None, float? depth = null)
{
Value.Draw(spriteBatch, spriteIndex, pos, color, origin, rotate, scale, spriteEffects, depth);
}
public static implicit operator SpriteSheet(GUISpriteSheet reference) => reference.Value;
}
public class GUICursorPrefab : GUIPrefab
{
public readonly Sprite[] Sprites;
public GUICursorPrefab(ContentXElement element, UIStyleFile file) : base(element, file)
{
Sprites = new Sprite[Enum.GetValues(typeof(CursorState)).Length];
foreach (var subElement in element.Elements())
{
CursorState state = subElement.GetAttributeEnum("state", CursorState.Default);
Sprites[(int)state] = new Sprite(subElement);
}
}
public override void Dispose()
{
foreach (var sprite in Sprites)
{
sprite?.Remove();
}
}
}
public class GUICursor : GUISelector<GUICursorPrefab>
{
public GUICursor(string identifier) : base(identifier) { }
public Sprite this[CursorState k] => Prefabs.ActivePrefab.Sprites[(int)k];
}
}
@@ -47,9 +47,9 @@ namespace Barotrauma
}
isHorizontal = (Rect.Width > Rect.Height);
frame = new GUIFrame(new RectTransform(Vector2.One, rectT));
GUI.Style.Apply(frame, "", this);
GUIStyle.Apply(frame, "", this);
slider = new GUIFrame(new RectTransform(Vector2.One, rectT));
GUI.Style.Apply(slider, "Slider", this);
GUIStyle.Apply(slider, "Slider", this);
this.showFrame = showFrame;
this.barSize = barSize;
Enabled = true;
@@ -62,10 +62,10 @@ namespace Barotrauma
public Rectangle GetSliderRect(float fillAmount)
{
Rectangle sliderArea = new Rectangle(
frame.Rect.X + (int)style.Padding.X,
frame.Rect.Y + (int)style.Padding.Y,
(int)(frame.Rect.Width - style.Padding.X - style.Padding.Z),
(int)(frame.Rect.Height - style.Padding.Y - style.Padding.W));
frame.Rect.X + (int)Style.Padding.X,
frame.Rect.Y + (int)Style.Padding.Y,
(int)(frame.Rect.Width - Style.Padding.X - Style.Padding.Z),
(int)(frame.Rect.Height - Style.Padding.Y - Style.Padding.W));
Vector4 sliceBorderSizes = Vector4.Zero;
if (slider.sprites.ContainsKey(slider.State) && (slider.sprites[slider.State].First()?.Slice ?? false))
@@ -116,10 +116,10 @@ namespace Barotrauma
var sliderRect = GetSliderRect(barSize);
slider.RectTransform.AbsoluteOffset = new Point((int)style.Padding.X, (int)style.Padding.Y);
slider.RectTransform.AbsoluteOffset = new Point((int)Style.Padding.X, (int)Style.Padding.Y);
slider.RectTransform.MaxSize = new Point(
(int)(Rect.Width - style.Padding.X + style.Padding.Z),
(int)(Rect.Height - style.Padding.Y + style.Padding.W));
(int)(Rect.Width - Style.Padding.X + Style.Padding.Z),
(int)(Rect.Height - Style.Padding.Y + Style.Padding.W));
frame.Visible = showFrame;
slider.Visible = BarSize > 0.0f;
@@ -1,6 +1,5 @@
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
namespace Barotrauma
@@ -29,7 +28,7 @@ namespace Barotrauma
public bool IsBooleanSwitch;
public override string ToolTip
public override RichString ToolTip
{
get { return base.ToolTip; }
set
@@ -203,7 +202,7 @@ namespace Barotrauma
CanBeFocused = true;
this.isHorizontal = isHorizontal ?? (Rect.Width > Rect.Height);
Frame = new GUIFrame(new RectTransform(Vector2.One, rectT));
GUI.Style.Apply(Frame, IsHorizontal ? "GUIFrameHorizontal" : "GUIFrameVertical", this);
GUIStyle.Apply(Frame, IsHorizontal ? "GUIFrameHorizontal" : "GUIFrameVertical", this);
this.barSize = barSize;
Bar = new GUIButton(new RectTransform(Vector2.One, rectT, IsHorizontal ? Anchor.CenterLeft : Anchor.TopCenter), color: color, style: null);
@@ -224,7 +223,7 @@ namespace Barotrauma
break;
}
GUI.Style.Apply(Bar, IsHorizontal ? "GUIButtonHorizontal" : "GUIButtonVertical", this);
GUIStyle.Apply(Bar, IsHorizontal ? "GUIButtonHorizontal" : "GUIButtonVertical", this);
Bar.OnPressed = SelectBar;
enabled = true;
UpdateRect();
@@ -313,6 +312,7 @@ namespace Barotrauma
MoveButton(new Vector2(
Math.Sign(PlayerInput.MousePosition.X - Bar.Rect.Center.X) * Bar.Rect.Width * barScale,
Math.Sign(PlayerInput.MousePosition.Y - Bar.Rect.Center.Y) * Bar.Rect.Height * barScale));
OnReleased?.Invoke(this, BarScroll);
}
}
}
@@ -1,523 +1,202 @@
using Barotrauma.Extensions;
using System;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
namespace Barotrauma
{
public class GUIStyle
public static class GUIStyle
{
private Dictionary<string, GUIComponentStyle> componentStyles;
private readonly XElement configElement;
private GraphicsDevice graphicsDevice;
private ScalableFont defaultFont;
public ScalableFont Font { get; private set; }
public ScalableFont GlobalFont { get; private set; }
public ScalableFont UnscaledSmallFont { get; private set; }
public ScalableFont SmallFont { get; private set; }
public ScalableFont LargeFont { get; private set; }
public ScalableFont SubHeadingFont { get; private set; }
public ScalableFont DigitalFont { get; private set; }
public ScalableFont HotkeyFont { get; private set; }
public ScalableFont MonospacedFont { get; private set; }
public Dictionary<ScalableFont, bool> ForceFontUpperCase
public readonly static ImmutableDictionary<Identifier, GUIFont> Fonts;
public readonly static ImmutableDictionary<Identifier, GUISprite> Sprites;
public readonly static ImmutableDictionary<Identifier, GUISpriteSheet> SpriteSheets;
public readonly static ImmutableDictionary<Identifier, GUIColor> Colors;
static GUIStyle()
{
get;
private set;
} = new Dictionary<ScalableFont, bool>();
var guiClassProperties = typeof(GUIStyle).GetFields(BindingFlags.Public | BindingFlags.Static);
public readonly Sprite[] CursorSprite = new Sprite[7];
ImmutableDictionary<Identifier, T> getPropertiesOfType<T>() where T : class
{
return guiClassProperties
.Where(p => p.FieldType == typeof(T))
.Select(p => (p.Name.ToIdentifier(), p.GetValue(null) as T))
.ToImmutableDictionary();
}
public UISprite RadiationSprite { get; private set; }
public SpriteSheet RadiationAnimSpriteSheet { get; private set; }
Fonts = getPropertiesOfType<GUIFont>();
Sprites = getPropertiesOfType<GUISprite>();
SpriteSheets = getPropertiesOfType<GUISpriteSheet>();
Colors = getPropertiesOfType<GUIColor>();
}
public SpriteSheet SavingIndicator { get; private set; }
public readonly static PrefabCollection<GUIComponentStyle> ComponentStyles = new PrefabCollection<GUIComponentStyle>();
public UISprite UIGlow { get; private set; }
public readonly static GUIFont Font = new GUIFont("Font");
public readonly static GUIFont GlobalFont = new GUIFont("GlobalFont");
public readonly static GUIFont UnscaledSmallFont = new GUIFont("UnscaledSmallFont");
public readonly static GUIFont SmallFont = new GUIFont("SmallFont");
public readonly static GUIFont LargeFont = new GUIFont("LargeFont");
public readonly static GUIFont SubHeadingFont = new GUIFont("SubHeadingFont");
public readonly static GUIFont DigitalFont = new GUIFont("DigitalFont");
public readonly static GUIFont HotkeyFont = new GUIFont("HotkeyFont");
public readonly static GUIFont MonospacedFont = new GUIFont("MonospacedFont");
public UISprite PingCircle { get; private set; }
public readonly static GUICursor CursorSprite = new GUICursor("Cursor");
public UISprite YouAreHereCircle { get; private set; }
public readonly static GUISprite SubmarineLocationIcon = new GUISprite("SubmarineLocationIcon");
public readonly static GUISprite Arrow = new GUISprite("Arrow");
public readonly static GUISprite SpeechBubbleIcon = new GUISprite("SpeechBubbleIcon");
public readonly static GUISprite BrokenIcon = new GUISprite("BrokenIcon");
public readonly static GUISprite YouAreHereCircle = new GUISprite("YouAreHereCircle");
public UISprite UIGlowCircular { get; private set; }
public readonly static GUISprite Radiation = new GUISprite("Radiation");
public readonly static GUISpriteSheet RadiationAnimSpriteSheet = new GUISpriteSheet("RadiationAnimSpriteSheet");
public UISprite UIGlowSolidCircular { get; private set; }
public UISprite UIThermalGlow { get; private set; }
public readonly static GUISpriteSheet SavingIndicator = new GUISpriteSheet("SavingIndicator");
public readonly static GUISpriteSheet GenericThrobber = new GUISpriteSheet("GenericThrobber");
public UISprite ButtonPulse { get; private set; }
public readonly static GUISprite UIGlow = new GUISprite("UIGlow");
public readonly static GUISprite TalentGlow = new GUISprite("TalentGlow");
public readonly static GUISprite PingCircle = new GUISprite("PingCircle");
public readonly static GUISprite UIGlowCircular = new GUISprite("UIGlowCircular");
public readonly static GUISprite UIGlowSolidCircular = new GUISprite("UIGlowSolidCircular");
public readonly static GUISprite UIThermalGlow = new GUISprite("UIGlowSolidCircular");
public readonly static GUISprite ButtonPulse = new GUISprite("ButtonPulse");
public readonly static GUISprite WalletPortraitBG = new GUISprite("WalletPortraitBG");
public readonly static GUISprite CrewWalletIconSmall = new GUISprite("CrewWalletIconSmall");
public SpriteSheet FocusIndicator { get; private set; }
public readonly static GUISprite EndRoundButtonPulse = new GUISprite("EndRoundButtonPulse");
public UISprite IconOverflowIndicator { get; private set; }
public readonly static GUISpriteSheet FocusIndicator = new GUISpriteSheet("FocusIndicator");
public readonly static GUISprite IconOverflowIndicator = new GUISprite("IconOverflowIndicator");
/// <summary>
/// General green color used for elements whose colors are set from code
/// </summary>
public Color Green { get; private set; } = Color.LightGreen;
public readonly static GUIColor Green = new GUIColor("Green");
/// <summary>
/// General red color used for elements whose colors are set from code
/// </summary>
public Color Orange { get; private set; } = Color.Orange;
public readonly static GUIColor Orange = new GUIColor("Orange");
/// <summary>
/// General red color used for elements whose colors are set from code
/// </summary>
public Color Red { get; private set; } = Color.Red;
public readonly static GUIColor Red = new GUIColor("Red");
/// <summary>
/// General blue color used for elements whose colors are set from code
/// </summary>
public Color Blue { get; private set; } = Color.Blue;
public readonly static GUIColor Blue = new GUIColor("Blue");
/// <summary>
/// General yellow color used for elements whose colors are set from code
/// </summary>
public Color Yellow { get; private set; } = Color.Yellow;
public readonly static GUIColor Yellow = new GUIColor("Yellow");
public Color ColorInventoryEmpty { get; private set; } = Color.Red;
public Color ColorInventoryHalf { get; private set; } = Color.Orange;
public Color ColorInventoryFull { get; private set; } = Color.LightGreen;
public Color ColorInventoryBackground { get; private set; } = Color.Gray;
public Color ColorInventoryEmptyOverlay { get; private set; } = Color.Red;
/// <summary>
/// Color to display the name of modded servers in the server list.
/// </summary>
public readonly static GUIColor ModdedServerColor = new GUIColor("ModdedServerColor");
public Color TextColor { get; private set; } = Color.White * 0.8f;
public Color TextColorBright { get; private set; } = Color.White * 0.9f;
public Color TextColorDark { get; private set; } = Color.Black * 0.9f;
public Color TextColorDim { get; private set; } = Color.White * 0.6f;
public readonly static GUIColor ColorInventoryEmpty = new GUIColor("ColorInventoryEmpty");
public readonly static GUIColor ColorInventoryHalf = new GUIColor("ColorInventoryHalf");
public readonly static GUIColor ColorInventoryFull = new GUIColor("ColorInventoryFull");
public readonly static GUIColor ColorInventoryBackground = new GUIColor("ColorInventoryBackground");
public readonly static GUIColor ColorInventoryEmptyOverlay = new GUIColor("ColorInventoryEmptyOverlay");
public Color ItemQualityColorPoor { get; private set; } = Color.DarkRed;
public Color ItemQualityColorNormal { get; private set; } = Color.Gray;
public Color ItemQualityColorGood { get; private set; } = Color.LightGreen;
public Color ItemQualityColorExcellent { get; private set; } = Color.LightBlue;
public Color ItemQualityColorMasterwork { get; private set; } = Color.MediumPurple;
public readonly static GUIColor TextColorNormal = new GUIColor("TextColorNormal");
public readonly static GUIColor TextColorBright = new GUIColor("TextColorBright");
public readonly static GUIColor TextColorDark = new GUIColor("TextColorDark");
public readonly static GUIColor TextColorDim = new GUIColor("TextColorDim");
public Color ColorReputationVeryLow { get; private set; } = Color.Red;
public Color ColorReputationLow { get; private set; } = Color.Orange;
public Color ColorReputationNeutral { get; private set; } = Color.White * 0.8f;
public Color ColorReputationHigh { get; private set; } = Color.LightBlue;
public Color ColorReputationVeryHigh { get; private set; } = Color.Blue;
public readonly static GUIColor ItemQualityColorPoor = new GUIColor("ItemQualityColorPoor");
public readonly static GUIColor ItemQualityColorNormal = new GUIColor("ItemQualityColorNormal");
public readonly static GUIColor ItemQualityColorGood = new GUIColor("ItemQualityColorGood");
public readonly static GUIColor ItemQualityColorExcellent = new GUIColor("ItemQualityColorExcellent");
public readonly static GUIColor ItemQualityColorMasterwork = new GUIColor("ItemQualityColorMasterwork");
public readonly static GUIColor ColorReputationVeryLow = new GUIColor("ColorReputationVeryLow");
public readonly static GUIColor ColorReputationLow = new GUIColor("ColorReputationLow");
public readonly static GUIColor ColorReputationNeutral = new GUIColor("ColorReputationNeutral");
public readonly static GUIColor ColorReputationHigh = new GUIColor("ColorReputationHigh");
public readonly static GUIColor ColorReputationVeryHigh = new GUIColor("ColorReputationVeryHigh");
// Inventory
public Color EquipmentSlotIconColor { get; private set; } = new Color(99, 70, 64);
public readonly static GUIColor EquipmentSlotIconColor = new GUIColor("EquipmentSlotIconColor");
// Health HUD
public Color BuffColorLow { get; private set; } = Color.LightGreen;
public Color BuffColorMedium { get; private set; } = Color.Green;
public Color BuffColorHigh { get; private set; } = Color.DarkGreen;
public readonly static GUIColor BuffColorLow = new GUIColor("BuffColorLow");
public readonly static GUIColor BuffColorMedium = new GUIColor("BuffColorMedium");
public readonly static GUIColor BuffColorHigh = new GUIColor("BuffColorHigh");
public Color DebuffColorLow { get; private set; } = Color.DarkSalmon;
public Color DebuffColorMedium { get; private set; } = Color.Red;
public Color DebuffColorHigh { get; private set; } = Color.DarkRed;
public readonly static GUIColor DebuffColorLow = new GUIColor("DebuffColorLow");
public readonly static GUIColor DebuffColorMedium = new GUIColor("DebuffColorMedium");
public readonly static GUIColor DebuffColorHigh = new GUIColor("DebuffColorHigh");
public Color HealthBarColorLow { get; private set; } = Color.Red;
public Color HealthBarColorMedium { get; private set; } = Color.Orange;
public Color HealthBarColorHigh { get; private set; } = new Color(78, 114, 88);
public readonly static GUIColor HealthBarColorLow = new GUIColor("HealthBarColorLow");
public readonly static GUIColor HealthBarColorMedium = new GUIColor("HealthBarColorMedium");
public readonly static GUIColor HealthBarColorHigh = new GUIColor("HealthBarColorHigh");
public Color EquipmentIndicatorNotEquipped { get; private set; } = Color.Gray;
public Color EquipmentIndicatorEquipped { get; private set; } = new Color(105, 202, 125);
public Color EquipmentIndicatorRunningOut { get; private set; } = new Color(202, 105, 105);
public readonly static GUIColor EquipmentIndicatorNotEquipped = new GUIColor("EquipmentIndicatorNotEquipped");
public readonly static GUIColor EquipmentIndicatorEquipped = new GUIColor("EquipmentIndicatorEquipped");
public readonly static GUIColor EquipmentIndicatorRunningOut = new GUIColor("EquipmentIndicatorRunningOut");
public static Point ItemFrameMargin => new Point(50, 56).Multiply(GUI.SlicedSpriteScale);
public static Point ItemFrameOffset => new Point(0, 3).Multiply(GUI.SlicedSpriteScale);
public GUIStyle(XElement element, GraphicsDevice graphicsDevice)
public static GUIComponentStyle GetComponentStyle(string name)
=> ComponentStyles.ContainsKey(name) ? ComponentStyles[name] : null;
public static void Apply(GUIComponent targetComponent, string styleName = "", GUIComponent parent = null)
{
this.graphicsDevice = graphicsDevice;
componentStyles = new Dictionary<string, GUIComponentStyle>();
configElement = element;
foreach (XElement subElement in configElement.Elements())
{
var name = subElement.Name.ToString().ToLowerInvariant();
switch (name)
{
case "cursor":
if (subElement.HasElements)
{
foreach (var children in subElement.Descendants())
{
var index = children.GetAttributeInt("state", (int)CursorState.Default);
CursorSprite[index] = new Sprite(children);
}
}
else
{
CursorSprite[(int)CursorState.Default] = new Sprite(subElement);
}
break;
case "green":
Green = subElement.GetAttributeColor("color", Green);
break;
case "orange":
Orange = subElement.GetAttributeColor("color", Orange);
break;
case "red":
Red = subElement.GetAttributeColor("color", Red);
break;
case "blue":
Blue = subElement.GetAttributeColor("color", Blue);
break;
case "yellow":
Yellow = subElement.GetAttributeColor("color", Yellow);
break;
case "colorinventoryempty":
ColorInventoryEmpty = subElement.GetAttributeColor("color", ColorInventoryEmpty);
break;
case "colorinventoryhalf":
ColorInventoryHalf = subElement.GetAttributeColor("color", ColorInventoryHalf);
break;
case "colorinventoryfull":
ColorInventoryFull = subElement.GetAttributeColor("color", ColorInventoryFull);
break;
case "colorinventorybackground":
ColorInventoryBackground = subElement.GetAttributeColor("color", ColorInventoryBackground);
break;
case "colorinventoryemptyoverlay":
ColorInventoryEmptyOverlay = subElement.GetAttributeColor("color", ColorInventoryEmptyOverlay);
break;
case "textcolordark":
TextColorDark = subElement.GetAttributeColor("color", TextColorDark);
break;
case "textcolorbright":
TextColorBright = subElement.GetAttributeColor("color", TextColorBright);
break;
case "textcolordim":
TextColorDim = subElement.GetAttributeColor("color", TextColorDim);
break;
case "textcolornormal":
case "textcolor":
TextColor = subElement.GetAttributeColor("color", TextColor);
break;
case "colorreputationverylow":
ColorReputationVeryLow = subElement.GetAttributeColor("color", TextColor);
break;
case "colorreputationlow":
ColorReputationLow = subElement.GetAttributeColor("color", TextColor);
break;
case "colorreputationneutral":
ColorReputationNeutral = subElement.GetAttributeColor("color", TextColor);
break;
case "colorreputationhigh":
ColorReputationHigh = subElement.GetAttributeColor("color", TextColor);
break;
case "colorreputationveryhigh":
ColorReputationVeryHigh = subElement.GetAttributeColor("color", TextColor);
break;
case "equipmentsloticoncolor":
EquipmentSlotIconColor = subElement.GetAttributeColor("color", EquipmentSlotIconColor);
break;
case "buffcolorlow":
BuffColorLow = subElement.GetAttributeColor("color", BuffColorLow);
break;
case "buffcolormedium":
BuffColorMedium = subElement.GetAttributeColor("color", BuffColorMedium);
break;
case "buffcolorhigh":
BuffColorHigh = subElement.GetAttributeColor("color", BuffColorHigh);
break;
case "debuffcolorlow":
DebuffColorLow = subElement.GetAttributeColor("color", DebuffColorLow);
break;
case "debuffcolormedium":
DebuffColorMedium = subElement.GetAttributeColor("color", DebuffColorMedium);
break;
case "debuffcolorhigh":
DebuffColorHigh = subElement.GetAttributeColor("color", DebuffColorHigh);
break;
case "healthbarcolorlow":
HealthBarColorLow = subElement.GetAttributeColor("color", HealthBarColorLow);
break;
case "healthbarcolormedium":
HealthBarColorMedium = subElement.GetAttributeColor("color", HealthBarColorMedium);
break;
case "healthbarcolorhigh":
HealthBarColorHigh = subElement.GetAttributeColor("color", HealthBarColorHigh);
break;
case "equipmentindicatornotequipped":
EquipmentIndicatorNotEquipped = subElement.GetAttributeColor("color", EquipmentIndicatorNotEquipped);
break;
case "equipmentindicatorequipped":
EquipmentIndicatorEquipped = subElement.GetAttributeColor("color", EquipmentIndicatorEquipped);
break;
case "equipmentindicatorrunningout":
EquipmentIndicatorRunningOut = subElement.GetAttributeColor("color", EquipmentIndicatorRunningOut);
break;
case "uiglow":
UIGlow = new UISprite(subElement);
break;
case "pingcircle":
PingCircle = new UISprite(subElement);
break;
case "youareherecircle":
YouAreHereCircle = new UISprite(subElement);
break;
case "radiation":
RadiationSprite = new UISprite(subElement);
break;
case "radiationanimspritesheet":
RadiationAnimSpriteSheet = new SpriteSheet(subElement);
break;
case "uiglowcircular":
UIGlowCircular = new UISprite(subElement);
break;
case "uiglowsolidcircular":
UIGlowSolidCircular = new UISprite(subElement);
break;
case "uithermalglow":
UIThermalGlow = new UISprite(subElement);
break;
case "endroundbuttonpulse":
ButtonPulse = new UISprite(subElement);
break;
case "iconoverflowindicator":
IconOverflowIndicator = new UISprite(subElement);
break;
case "focusindicator":
FocusIndicator = new SpriteSheet(subElement);
break;
case "savingindicator":
SavingIndicator = new SpriteSheet(subElement);
break;
case "font":
Font = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[Font] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "globalfont":
GlobalFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[GlobalFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "unscaledsmallfont":
UnscaledSmallFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[UnscaledSmallFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "smallfont":
SmallFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[SmallFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "largefont":
LargeFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[LargeFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "digitalfont":
DigitalFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "monospacedfont":
MonospacedFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[MonospacedFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "hotkeyfont":
HotkeyFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[HotkeyFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "objectivetitle":
case "subheading":
SubHeadingFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[SubHeadingFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
default:
GUIComponentStyle componentStyle = new GUIComponentStyle(subElement, this);
componentStyles.Add(subElement.Name.ToString().ToLowerInvariant(), componentStyle);
break;
}
}
if (GlobalFont == null)
{
GlobalFont = Font;
DebugConsole.NewMessage("Global font not defined in the current UI style file. The global font is used to render western symbols when using Chinese/Japanese/Korean localization. Using default font instead...", Color.Orange);
}
// TODO: Needs to unregister if we ever remove GUIStyles.
GameMain.Instance.ResolutionChanged += RescaleElements;
Apply(targetComponent, styleName.ToIdentifier(), parent);
}
/// <summary>
/// Returns the default font of the currently selected language
/// </summary>
public ScalableFont LoadCurrentDefaultFont()
{
defaultFont?.Dispose();
defaultFont = null;
foreach (XElement subElement in configElement.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "font":
defaultFont = LoadFont(subElement, graphicsDevice);
break;
}
}
return defaultFont;
}
private void RescaleElements()
{
if (configElement == null) { return; }
if (configElement.Elements() == null) { return; }
foreach (XElement subElement in configElement.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "font":
if (Font == null) { continue; }
Font.Size = GetFontSize(subElement);
break;
case "smallfont":
if (SmallFont == null) { continue; }
SmallFont.Size = GetFontSize(subElement);
break;
case "largefont":
if (LargeFont == null) { continue; }
LargeFont.Size = GetFontSize(subElement);
break;
case "hotkeyfont":
if (HotkeyFont == null) { continue; }
HotkeyFont.Size = GetFontSize(subElement);
break;
case "objectivetitle":
case "subheading":
if (SubHeadingFont == null) { continue; }
SubHeadingFont.Size = GetFontSize(subElement);
break;
}
}
foreach (var componentStyle in componentStyles.Values)
{
componentStyle.GetSize(componentStyle.Element);
foreach (var childStyle in componentStyle.ChildStyles.Values)
{
childStyle.GetSize(childStyle.Element);
}
}
}
private ScalableFont LoadFont(XElement element, GraphicsDevice graphicsDevice)
{
string file = GetFontFilePath(element);
uint size = GetFontSize(element);
bool dynamicLoading = GetFontDynamicLoading(element);
bool isCJK = GetIsCJK(element);
return new ScalableFont(file, size, graphicsDevice, dynamicLoading, isCJK);
}
private uint GetFontSize(XElement element, uint defaultSize = 14)
{
//check if any of the language override fonts want to override the font size as well
foreach (XElement subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
if (GameMain.Config.Language.Equals(subElement.GetAttributeString("language", ""), StringComparison.OrdinalIgnoreCase))
{
uint overrideFontSize = GetFontSize(subElement, 0);
if (overrideFontSize > 0) { return (uint)Math.Round(overrideFontSize * GameSettings.TextScale); }
}
}
foreach (XElement subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("size", StringComparison.OrdinalIgnoreCase)) { continue; }
Point maxResolution = subElement.GetAttributePoint("maxresolution", new Point(int.MaxValue, int.MaxValue));
if (GameMain.GraphicsWidth <= maxResolution.X && GameMain.GraphicsHeight <= maxResolution.Y)
{
return (uint)Math.Round(subElement.GetAttributeInt("size", 14) * GameSettings.TextScale);
}
}
return (uint)Math.Round(defaultSize * GameSettings.TextScale);
}
private string GetFontFilePath(XElement element)
{
foreach (XElement subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
if (GameMain.Config.Language.Equals(subElement.GetAttributeString("language", ""), StringComparison.OrdinalIgnoreCase))
{
return subElement.GetAttributeString("file", "");
}
}
return element.GetAttributeString("file", "");
}
private bool GetFontDynamicLoading(XElement element)
{
foreach (XElement subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
if (GameMain.Config.Language.Equals(subElement.GetAttributeString("language", ""), StringComparison.OrdinalIgnoreCase))
{
return subElement.GetAttributeBool("dynamicloading", false);
}
}
return element.GetAttributeBool("dynamicloading", false);
}
private bool GetIsCJK(XElement element)
{
foreach (XElement subElement in element.Elements())
{
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
if (GameMain.Config.Language.Equals(subElement.GetAttributeString("language", ""), StringComparison.OrdinalIgnoreCase))
{
return subElement.GetAttributeBool("iscjk", false);
}
}
return element.GetAttributeBool("iscjk", false);
}
public GUIComponentStyle GetComponentStyle(string name)
{
componentStyles.TryGetValue(name.ToLowerInvariant(), out GUIComponentStyle style);
return style;
}
public void Apply(GUIComponent targetComponent, string styleName = "", GUIComponent parent = null)
public static void Apply(GUIComponent targetComponent, Identifier styleName, GUIComponent parent = null)
{
GUIComponentStyle componentStyle = null;
if (parent != null)
{
GUIComponentStyle parentStyle = parent.Style;
if (parent.Style == null)
if (parentStyle == null)
{
string parentStyleName = parent.GetType().Name.ToLowerInvariant();
Identifier parentStyleName = parent.GetType().Name.ToIdentifier();
if (!componentStyles.TryGetValue(parentStyleName, out parentStyle))
if (!ComponentStyles.ContainsKey(parentStyleName))
{
DebugConsole.ThrowError("Couldn't find a GUI style \""+ parentStyleName + "\"");
DebugConsole.ThrowError($"Couldn't find a GUI style \"{parentStyleName}\"");
return;
}
parentStyle = ComponentStyles[parentStyleName];
}
string childStyleName = string.IsNullOrEmpty(styleName) ? targetComponent.GetType().Name : styleName;
parentStyle.ChildStyles.TryGetValue(childStyleName.ToLowerInvariant(), out componentStyle);
Identifier childStyleName = styleName.IsEmpty ? targetComponent.GetType().Name.ToIdentifier() : styleName;
parentStyle.ChildStyles.TryGetValue(childStyleName, out componentStyle);
}
else
{
if (string.IsNullOrEmpty(styleName))
Identifier styleIdentifier = styleName.ToIdentifier();
if (styleIdentifier == Identifier.Empty)
{
styleName = targetComponent.GetType().Name;
styleIdentifier = targetComponent.GetType().Name.ToIdentifier();
}
if (!componentStyles.TryGetValue(styleName.ToLowerInvariant(), out componentStyle))
if (!ComponentStyles.ContainsKey(styleIdentifier))
{
DebugConsole.ThrowError("Couldn't find a GUI style \""+ styleName+"\"");
DebugConsole.ThrowError($"Couldn't find a GUI style \"{styleIdentifier}\"");
return;
}
componentStyle = ComponentStyles[styleIdentifier];
}
targetComponent.ApplyStyle(componentStyle);
}
public Color GetQualityColor(int quality)
public static GUIColor GetQualityColor(int quality)
{
switch (quality)
{
@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
@@ -7,9 +8,16 @@ using System.Linq;
namespace Barotrauma
{
public enum ForceUpperCase
{
Inherit,
No,
Yes
}
public class GUITextBlock : GUIComponent
{
protected string text;
protected RichString text;
protected Alignment textAlignment;
@@ -20,10 +28,10 @@ namespace Barotrauma
protected Color textColor, disabledTextColor, selectedTextColor;
private string wrappedText;
private LocalizedString wrappedText;
private string censoredText;
public delegate string TextGetterHandler();
public delegate LocalizedString TextGetterHandler();
public TextGetterHandler TextGetter;
public bool Wrap;
@@ -41,8 +49,6 @@ namespace Barotrauma
private float textDepth;
private ScalableFont originalFont;
public Vector2 TextOffset { get; set; }
private Vector4 padding;
@@ -56,7 +62,7 @@ namespace Barotrauma
}
}
public override ScalableFont Font
public override GUIFont Font
{
get
{
@@ -65,23 +71,25 @@ namespace Barotrauma
set
{
if (base.Font == value) { return; }
base.Font = originalFont = value;
if (text != null && GUI.Style.ForceFontUpperCase.ContainsKey(Font) && GUI.Style.ForceFontUpperCase[Font])
{
Text = text.ToUpper();
}
base.Font = value;
if (text != null) { Text = text; }
SetTextPos();
}
}
public string Text
public RichString Text
{
get { return text; }
set
{
string newText = forceUpperCase || (GUI.Style.ForceFontUpperCase.ContainsKey(Font) && GUI.Style.ForceFontUpperCase[Font]) || (style != null && style.ForceUpperCase) ?
value?.ToUpper() :
value;
#warning TODO: Remove this eventually. Nobody should want to pass null.
value ??= "";
RichString newText = forceUpperCase switch
{
ForceUpperCase.Inherit => value.CaseTiedToFontAndStyle(Font, Style),
ForceUpperCase.No => value.CaseTiedToFontAndStyle(null, null),
ForceUpperCase.Yes => value.ToUpper()
};
if (Text == newText) { return; }
@@ -89,21 +97,12 @@ namespace Barotrauma
if (autoScaleHorizontal || autoScaleVertical) { textScale = 1.0f; }
text = newText;
wrappedText = newText;
if (TextManager.IsCJK(text))
{
//switch to fallback CJK font
if (!Font.IsCJK) { base.Font = GUI.CJKFont; }
}
else
{
if (Font == GUI.CJKFont) { base.Font = originalFont; }
}
wrappedText = newText.SanitizedString;
SetTextPos();
}
}
public string WrappedText
public LocalizedString WrappedText
{
get { return wrappedText; }
}
@@ -117,7 +116,11 @@ namespace Barotrauma
public Vector2 TextPos
{
get { return textPos; }
set { textPos = value; }
set
{
textPos = value;
ClearCaretPositions();
}
}
public float TextScale
@@ -169,8 +172,8 @@ namespace Barotrauma
}
}
private bool forceUpperCase;
public bool ForceUpperCase
private ForceUpperCase forceUpperCase = ForceUpperCase.Inherit;
public ForceUpperCase ForceUpperCase
{
get { return forceUpperCase; }
set
@@ -178,12 +181,7 @@ namespace Barotrauma
if (forceUpperCase == value) { return; }
forceUpperCase = value;
if (forceUpperCase ||
(style != null && style.ForceUpperCase) ||
(GUI.Style.ForceFontUpperCase.ContainsKey(Font) && GUI.Style.ForceFontUpperCase[Font]))
{
Text = text?.ToUpper();
}
if (text != null) { Text = text; }
}
}
@@ -247,7 +245,7 @@ namespace Barotrauma
public class StrikethroughSettings
{
public Color Color { get; set; } = GUI.Style.Red;
public Color Color { get; set; } = GUIStyle.Red;
private int thickness;
private int expand;
@@ -266,13 +264,9 @@ namespace Barotrauma
public StrikethroughSettings Strikethrough = null;
public List<RichTextData> RichTextData
{
get;
private set;
}
public ImmutableArray<RichTextData>? RichTextData => text.RichTextData;
public bool HasColorHighlight => RichTextData != null;
public bool HasColorHighlight => RichTextData.HasValue;
public bool OverrideRichTextDataAlpha = true;
@@ -292,9 +286,9 @@ namespace Barotrauma
/// This is the new constructor.
/// If the rectT height is set 0, the height is calculated from the text.
/// </summary>
public GUITextBlock(RectTransform rectT, string text, Color? textColor = null, ScalableFont font = null,
public GUITextBlock(RectTransform rectT, RichString text, Color? textColor = null, GUIFont font = null,
Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null,
bool playerInput = false, bool parseRichText = false)
bool playerInput = false)
: base(style, rectT)
{
if (color.HasValue)
@@ -306,28 +300,15 @@ namespace Barotrauma
OverrideTextColor(textColor.Value);
}
if (parseRichText)
{
RichTextData = Barotrauma.RichTextData.GetRichTextData(text, out text);
if (RichTextData != null && RichTextData.Count == 0)
{
RichTextData = null;
}
}
//if the text is in chinese/korean/japanese and we're not using a CJK-compatible font,
//use the default CJK font as a fallback
var selectedFont = originalFont = font ?? GUI.Font;
if (TextManager.IsCJK(text) && !selectedFont.IsCJK)
{
selectedFont = GUI.CJKFont;
}
var selectedFont = font ?? GUIStyle.Font;
this.Font = selectedFont;
this.textAlignment = textAlignment;
this.Wrap = wrap;
this.Text = text ?? "";
this.playerInput = playerInput;
if (rectT.Rect.Height == 0 && !string.IsNullOrEmpty(text))
if (rectT.Rect.Height == 0 && !text.IsNullOrEmpty())
{
CalculateHeightFromText();
}
@@ -339,11 +320,6 @@ namespace Barotrauma
Enabled = true;
Censor = false;
}
public GUITextBlock(RectTransform rectT, List<RichTextData> richTextData, string text, Color? textColor = null, ScalableFont font = null, Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = false)
: this(rectT, text, textColor, font, textAlignment, wrap, style, color, playerInput)
{
this.RichTextData = richTextData;
}
public void CalculateHeightFromText(int padding = 0, bool removeExtraSpacing = false)
{
@@ -351,10 +327,9 @@ namespace Barotrauma
RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(wrappedText, removeExtraSpacing).Y + padding));
}
public void SetRichText(string richText)
public void SetRichText(LocalizedString richText)
{
RichTextData = Barotrauma.RichTextData.GetRichTextData(richText, out string sanitizedText);
Text = sanitizedText;
Text = RichString.Rich(richText);
}
public override void ApplyStyle(GUIComponentStyle componentStyle)
@@ -368,41 +343,34 @@ namespace Barotrauma
disabledTextColor = componentStyle.DisabledTextColor;
selectedTextColor = componentStyle.SelectedTextColor;
switch (componentStyle.Font)
if (Font == null || !componentStyle.Font.IsEmpty)
{
case "font":
Font = componentStyle.Style.Font;
break;
case "smallfont":
Font = componentStyle.Style.SmallFont;
break;
case "largefont":
Font = componentStyle.Style.LargeFont;
break;
case "objectivetitle":
case "subheading":
Font = componentStyle.Style.SubHeadingFont;
break;
Font = GUIStyle.Fonts[componentStyle.Font.AppendIfMissing("Font")];
}
}
public void ClearCaretPositions()
{
cachedCaretPositions = ImmutableArray<Vector2>.Empty;
}
public void SetTextPos()
{
cachedCaretPositions = ImmutableArray<Vector2>.Empty;
ClearCaretPositions();
if (text == null) { return; }
censoredText = string.IsNullOrEmpty(text) ? "" : new string('\u2022', text.Length);
censoredText = text.IsNullOrEmpty() ? "" : new string('\u2022', text.Length);
var rect = Rect;
overflowClipActive = false;
wrappedText = text;
wrappedText = text.SanitizedString;
TextSize = MeasureText(text);
TextSize = MeasureText(text.SanitizedString);
if (Wrap && rect.Width > 0)
{
wrappedText = ToolBox.WrapText(text, rect.Width - padding.X - padding.Z, Font, textScale);
wrappedText = ToolBox.WrapText(text.SanitizedString, rect.Width - padding.X - padding.Z, Font, textScale);
TextSize = MeasureText(wrappedText);
}
else if (OverflowClip)
@@ -426,15 +394,15 @@ namespace Barotrauma
textPos = new Vector2(padding.X + (rect.Width - padding.Z - padding.X) / 2.0f, padding.Y + (rect.Height - padding.Y - padding.W) / 2.0f);
origin = TextSize * 0.5f;
origin.X = 0;
if (textAlignment.HasFlag(Alignment.Left) && !overflowClipActive)
{
textPos.X = padding.X;
origin.X = 0;
}
if (textAlignment.HasFlag(Alignment.Right) || overflowClipActive)
{
textPos.X = rect.Width - padding.Z;
origin.X = TextSize.X;
//origin.X = TextSize.X;
}
if (textAlignment.HasFlag(Alignment.Top))
{
@@ -454,7 +422,12 @@ namespace Barotrauma
textPos.Y = (int)textPos.Y;
}
private Vector2 MeasureText(string text)
private Vector2 MeasureText(LocalizedString text)
{
return MeasureText(text.Value);
}
private Vector2 MeasureText(string text)
{
if (Font == null) return Vector2.Zero;
@@ -498,12 +471,20 @@ namespace Barotrauma
{
return cachedCaretPositions;
}
string textDrawn = Censor ? CensoredText : Text;
string textDrawn = Censor ? CensoredText : Text.SanitizedValue;
float w = Wrap
? (Rect.Width - Padding.X - Padding.Z) / TextScale
: float.PositiveInfinity;
Font.WrapText(textDrawn, w, out Vector2[] positions);
cachedCaretPositions = positions.Select(p => p * TextScale + TextPos - Origin * TextScale).ToImmutableArray();
string wrapped = Font.WrapText(textDrawn, w, out Vector2[] positions);
int textWidth = (int)Font.MeasureString(wrapped).X;
int alignmentXDiff
= textAlignment.HasFlag(Alignment.Right) ? textWidth
: textAlignment.HasFlag(Alignment.Center) ? textWidth / 2
: 0;
cachedCaretPositions = positions
.Select(p => p - new Vector2(alignmentXDiff, 0))
.Select(p => p * TextScale + TextPos - Origin * TextScale)
.ToImmutableArray();
return cachedCaretPositions;
}
@@ -584,7 +565,7 @@ namespace Barotrauma
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
}
if (!string.IsNullOrEmpty(text))
if (!text.IsNullOrEmpty())
{
Vector2 pos = rect.Location.ToVector2() + textPos + TextOffset;
if (RoundToNearestPixel)
@@ -605,28 +586,29 @@ namespace Barotrauma
if (!HasColorHighlight)
{
string textToShow = Censor ? censoredText : (Wrap ? wrappedText : text);
string textToShow = Censor ? censoredText : (Wrap ? wrappedText.Value : text.SanitizedValue);
Color colorToShow = currentTextColor * (currentTextColor.A / 255.0f);
if (Shadow)
{
Vector2 shadowOffset = new Vector2(GUI.IntScale(2));
Font.DrawString(spriteBatch, textToShow, pos + shadowOffset, Color.Black, 0.0f, origin, TextScale, SpriteEffects.None, textDepth);
Font.DrawString(spriteBatch, textToShow, pos + shadowOffset, Color.Black, 0.0f, origin, TextScale, SpriteEffects.None, textDepth, alignment: textAlignment, forceUpperCase: ForceUpperCase);
}
Font.DrawString(spriteBatch, textToShow, pos, colorToShow, 0.0f, origin, TextScale, SpriteEffects.None, textDepth);
Font.DrawString(spriteBatch, textToShow, pos, colorToShow, 0.0f, origin, TextScale, SpriteEffects.None, textDepth, alignment: textAlignment, forceUpperCase: ForceUpperCase);
}
else
{
if (OverrideRichTextDataAlpha)
{
RichTextData.ForEach(rt => rt.Alpha = currentTextColor.A / 255.0f);
RichTextData.Value.ForEach(rt => rt.Alpha = currentTextColor.A / 255.0f);
}
Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos,
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, RichTextData);
Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text.SanitizedString).Value, pos,
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, RichTextData.Value, alignment: textAlignment, forceUpperCase: ForceUpperCase);
}
Strikethrough?.Draw(spriteBatch, (int)Math.Ceiling(TextSize.X / 2f), pos.X, ForceUpperCase ? pos.Y : pos.Y + GUI.Scale * 2f);
Strikethrough?.Draw(spriteBatch, (int)Math.Ceiling(TextSize.X / 2f), pos.X,
/* TODO: ???? */ForceUpperCase == ForceUpperCase.Yes ? pos.Y : pos.Y + GUI.Scale * 2f);
}
if (overflowClipActive)
@@ -76,9 +76,6 @@ namespace Barotrauma
private int selectionStartIndex;
private int selectionEndIndex;
private bool IsLeftToRight => selectionStartIndex <= selectionEndIndex;
private Vector2 selectionStartPos;
private Vector2 selectionEndPos;
private Vector2 selectionRectSize;
private GUICustomComponent caretAndSelectionRenderer;
@@ -151,7 +148,7 @@ namespace Barotrauma
maxTextLength = value;
if (Text.Length > MaxTextLength)
{
SetText(textBlock.Text.Substring(0, (int)maxTextLength));
SetText(Text.Substring(0, (int)maxTextLength));
}
}
}
@@ -182,7 +179,7 @@ namespace Barotrauma
set { textBlock.Censor = value; }
}
public override string ToolTip
public override RichString ToolTip
{
get
{
@@ -194,7 +191,7 @@ namespace Barotrauma
}
}
public override ScalableFont Font
public override GUIFont Font
{
get { return textBlock?.Font ?? base.Font; }
set
@@ -247,7 +244,7 @@ namespace Barotrauma
{
get
{
return textBlock.Text;
return textBlock.Text.SanitizedValue;
}
set
{
@@ -259,12 +256,12 @@ namespace Barotrauma
public string WrappedText
{
get { return textBlock.WrappedText; }
get { return textBlock.WrappedText.Value; }
}
public bool Readonly { get; set; }
public GUITextBox(RectTransform rectT, string text = "", Color? textColor = null, ScalableFont font = null,
public GUITextBox(RectTransform rectT, string text = "", Color? textColor = null, GUIFont font = null,
Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool createClearButton = false, bool createPenIcon = true)
: base(style, rectT)
{
@@ -273,9 +270,10 @@ namespace Barotrauma
this.color = color ?? Color.White;
frame = new GUIFrame(new RectTransform(Vector2.One, rectT, Anchor.Center), style, color);
GUI.Style.Apply(frame, style == "" ? "GUITextBox" : style);
textBlock = new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.CenterLeft), text, textColor, font, textAlignment, wrap, playerInput: true);
GUI.Style.Apply(textBlock, "", this);
GUIStyle.Apply(frame, style == "" ? "GUITextBox" : style);
textBlock = new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.CenterLeft), text ?? "", textColor, font, textAlignment, wrap, playerInput: true);
GUIStyle.Apply(textBlock, "", this);
if (font != null) { textBlock.Font = font; }
CaretEnabled = true;
caretPosDirty = true;
@@ -297,10 +295,11 @@ namespace Barotrauma
clearButtonWidth = (int)(clearButton.Rect.Width * 1.2f);
}
if (this.style != null && this.style.ChildStyles.ContainsKey("textboxicon") && createPenIcon)
var selfStyle = Style;
if (selfStyle != null && selfStyle.ChildStyles.ContainsKey("textboxicon".ToIdentifier()) && createPenIcon)
{
icon = new GUIImage(new RectTransform(new Vector2(0.6f, 0.6f), frame.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point(5 + clearButtonWidth, 0) }, null, scaleToFit: true);
icon.ApplyStyle(this.style.ChildStyles["textboxicon"]);
icon.ApplyStyle(this.Style.ChildStyles["textboxicon".ToIdentifier()]);
textBlock.RectTransform.MaxSize = new Point(frame.Rect.Width - icon.Rect.Height - clearButtonWidth - icon.RectTransform.AbsoluteOffset.X * 2, int.MaxValue);
}
Font = textBlock.Font;
@@ -325,53 +324,39 @@ namespace Barotrauma
{
text = textFilterFunction(text);
}
if (textBlock.Text == text) { return false; }
if (Text == text) { return false; }
textBlock.Text = text;
if (textBlock.Text == null) textBlock.Text = "";
if (textBlock.Text != "" && !Wrap)
ClearSelection();
if (Text == null) textBlock.Text = "";
if (Text != "" && !Wrap)
{
if (maxTextLength != null)
{
if (textBlock.Text.Length > maxTextLength)
{
textBlock.Text = textBlock.Text.Substring(0, (int)maxTextLength);
textBlock.Text = Text.Substring(0, (int)maxTextLength);
}
}
else
{
while (ClampText && textBlock.Text.Length > 0 && Font.MeasureString(textBlock.Text).X * TextBlock.TextScale > (int)(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z))
{
textBlock.Text = textBlock.Text.Substring(0, textBlock.Text.Length - 1);
textBlock.Text = Text.Substring(0, textBlock.Text.Length - 1);
}
}
}
if (store)
{
memento.Store(textBlock.Text);
memento.Store(Text);
}
return true;
}
private void CalculateCaretPos()
{
if (Censor || !Wrap)
{
string textDrawn = textBlock.CensoredText;
CaretIndex = Math.Min(CaretIndex, textDrawn.Length);
textDrawn = Censor ? textBlock.CensoredText : textBlock.Text;
Vector2 textSize = Font.MeasureString(textDrawn[..CaretIndex]) * TextBlock.TextScale;
caretPos = new Vector2(textSize.X, 0) + textBlock.TextPos - textBlock.Origin * TextBlock.TextScale;
}
else
{
CaretIndex = Math.Min(CaretIndex, textBlock.Text.Length);
textBlock.Font.WrapText(
textBlock.Text,
(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z) / TextBlock.TextScale,
CaretIndex,
out Vector2 requestedCharPos);
caretPos = requestedCharPos * TextBlock.TextScale + textBlock.TextPos - textBlock.Origin * TextBlock.TextScale;
}
CaretIndex = Math.Clamp(CaretIndex, 0, textBlock.Text.Length);
var caretPositions = textBlock.GetAllCaretPositions();
caretPos = caretPositions[CaretIndex];
caretPosDirty = false;
}
@@ -470,14 +455,19 @@ namespace Barotrauma
{
if (textBlock.OverflowClipActive)
{
if (CaretScreenPos.X < textBlock.Rect.X + textBlock.Padding.X)
float left = textBlock.Rect.X + textBlock.Padding.X;
if (CaretScreenPos.X < left)
{
textBlock.TextPos = new Vector2(textBlock.TextPos.X + ((textBlock.Rect.X + textBlock.Padding.X) - CaretScreenPos.X), textBlock.TextPos.Y);
float diff = left - CaretScreenPos.X;
textBlock.TextPos = new Vector2(textBlock.TextPos.X + diff, textBlock.TextPos.Y);
CalculateCaretPos();
}
else if (CaretScreenPos.X > textBlock.Rect.Right - textBlock.Padding.Z)
float right = textBlock.Rect.Right - textBlock.Padding.Z;
if (CaretScreenPos.X > right)
{
textBlock.TextPos = new Vector2(textBlock.TextPos.X - (CaretScreenPos.X - (textBlock.Rect.Right - textBlock.Padding.Z)), textBlock.TextPos.Y);
float diff = CaretScreenPos.X - right;
textBlock.TextPos = new Vector2(textBlock.TextPos.X - diff, textBlock.TextPos.Y);
CalculateCaretPos();
}
}
@@ -509,74 +499,57 @@ namespace Barotrauma
private void DrawCaretAndSelection(SpriteBatch spriteBatch, GUICustomComponent customComponent)
{
if (!Visible) { return; }
if (Selected)
if (!Selected) { return; }
if (caretVisible)
{
if (caretVisible )
{
GUI.DrawLine(spriteBatch,
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + 3),
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + Font.MeasureString("I").Y * textBlock.TextScale - 3),
CaretColor ?? textBlock.TextColor * (textBlock.TextColor.A / 255.0f));
}
if (selectedCharacters > 0)
{
DrawSelectionRect(spriteBatch);
}
//GUI.DrawString(spriteBatch, new Vector2(100, 0), selectedCharacters.ToString(), Color.LightBlue, Color.Black);
//GUI.DrawString(spriteBatch, new Vector2(100, 20), selectionStartIndex.ToString(), Color.White, Color.Black);
//GUI.DrawString(spriteBatch, new Vector2(140, 20), selectionEndIndex.ToString(), Color.White, Color.Black);
//GUI.DrawString(spriteBatch, new Vector2(100, 40), selectedText.ToString(), Color.Yellow, Color.Black);
//GUI.DrawString(spriteBatch, new Vector2(100, 60), $"caret index: {CaretIndex.ToString()}", GUI.Style.Red, Color.Black);
//GUI.DrawString(spriteBatch, new Vector2(100, 80), $"caret pos: {caretPos.ToString()}", GUI.Style.Red, Color.Black);
//GUI.DrawString(spriteBatch, new Vector2(100, 100), $"caret screen pos: {CaretScreenPos.ToString()}", GUI.Style.Red, Color.Black);
//GUI.DrawString(spriteBatch, new Vector2(100, 120), $"text start pos: {(textBlock.TextPos - textBlock.Origin).ToString()}", Color.White, Color.Black);
//GUI.DrawString(spriteBatch, new Vector2(100, 140), $"cursor pos: {PlayerInput.MousePosition.ToString()}", Color.White, Color.Black);
GUI.DrawLine(spriteBatch,
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + 3),
new Vector2(Rect.X + (int)caretPos.X + 2, Rect.Y + caretPos.Y + Font.LineHeight * textBlock.TextScale - 3),
CaretColor ?? textBlock.TextColor * (textBlock.TextColor.A / 255.0f));
}
if (selectedCharacters > 0)
{
DrawSelectionRect(spriteBatch);
}
}
private void DrawSelectionRect(SpriteBatch spriteBatch)
{
if (textBlock.WrappedText.Contains("\n"))
{
// Multiline selection
var characterPositions = textBlock.GetAllCaretPositions();
(int startIndex, int endIndex) = selectionStartIndex < selectionEndIndex
? (selectionStartIndex, selectionEndIndex)
: (selectionEndIndex, selectionStartIndex);
endIndex--;
var characterPositions = textBlock.GetAllCaretPositions();
(int startIndex, int endIndex) = IsLeftToRight
? (selectionStartIndex, selectionEndIndex)
: (selectionEndIndex, selectionStartIndex);
endIndex--;
void drawRect(Vector2 topLeft, Vector2 bottomRight)
{
int minWidth = GUI.IntScale(5);
if (bottomRight.X - topLeft.X < minWidth) { bottomRight.X = topLeft.X + minWidth; }
GUI.DrawRectangle(spriteBatch,
Rect.Location.ToVector2() + topLeft,
bottomRight - topLeft,
SelectionColor, isFilled: true);
}
Vector2 topLeft = characterPositions[startIndex];
for (int i = startIndex+1; i <= endIndex; i++)
{
Vector2 currPos = characterPositions[i];
if (!MathUtils.NearlyEqual(topLeft.Y, currPos.Y))
{
Vector2 bottomRight = characterPositions[i - 1];
bottomRight += Font.MeasureChar(Text[i - 1]);
drawRect(topLeft, bottomRight);
topLeft = currPos;
}
}
Vector2 finalBottomRight = characterPositions[endIndex];
finalBottomRight += Font.MeasureChar(Text[endIndex]);
drawRect(topLeft, finalBottomRight);
}
else
void drawRect(Vector2 topLeft, Vector2 bottomRight)
{
// Single line selection
Vector2 topLeft = IsLeftToRight ? selectionStartPos : selectionEndPos;
GUI.DrawRectangle(spriteBatch, Rect.Location.ToVector2() + topLeft, selectionRectSize, SelectionColor, isFilled: true);
int minWidth = GUI.IntScale(5);
if (bottomRight.X - topLeft.X < minWidth) { bottomRight.X = topLeft.X + minWidth; }
GUI.DrawRectangle(spriteBatch,
Rect.Location.ToVector2() + topLeft,
bottomRight - topLeft,
SelectionColor, isFilled: true);
}
Vector2 topLeft = characterPositions[startIndex];
for (int i = startIndex+1; i <= endIndex; i++)
{
Vector2 currPos = characterPositions[i];
if (!MathUtils.NearlyEqual(topLeft.Y, currPos.Y))
{
Vector2 bottomRight = characterPositions[i - 1];
bottomRight += Font.MeasureChar(Text[i - 1]) * TextBlock.TextScale;
drawRect(topLeft, bottomRight);
topLeft = currPos;
}
}
Vector2 finalBottomRight = characterPositions[endIndex];
if (Text.Length > endIndex)
{
finalBottomRight += Font.MeasureChar(Text[endIndex]) * TextBlock.TextScale;
}
drawRect(topLeft, finalBottomRight);
}
public void ReceiveTextInput(char inputChar)
@@ -710,8 +683,8 @@ namespace Barotrauma
float lineHeight = Font.LineHeight * TextBlock.TextScale;
int newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y - lineHeight * 0.5f));
textBlock.Font.WrapText(
textBlock.Text,
(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z) / TextBlock.TextScale,
textBlock.Text.SanitizedValue,
GetWrapWidth(),
newIndex,
out Vector2 requestedCharPos);
requestedCharPos *= TextBlock.TextScale;
@@ -728,8 +701,8 @@ namespace Barotrauma
lineHeight = Font.LineHeight * TextBlock.TextScale;
newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y + lineHeight * 1.5f));
textBlock.Font.WrapText(
textBlock.Text,
(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z) / TextBlock.TextScale,
textBlock.Text.SanitizedValue,
GetWrapWidth(),
newIndex,
out Vector2 requestedCharPos2);
requestedCharPos2 *= TextBlock.TextScale;
@@ -816,7 +789,6 @@ namespace Barotrauma
{
CaretIndex = 0;
CalculateCaretPos();
selectionStartPos = caretPos;
selectionStartIndex = 0;
CaretIndex = Text.Length;
CalculateSelection();
@@ -847,15 +819,18 @@ namespace Barotrauma
{
if (selectedText.Length == 0) { return; }
selectionStartIndex = Math.Max(0, Math.Min(selectionEndIndex, Math.Min(selectionStartIndex, Text.Length - 1)));
int selectionLength = Math.Min(Text.Length - selectionStartIndex, selectedText.Length);
SetText(Text.Remove(selectionStartIndex, selectionLength));
CaretIndex = Math.Min(Text.Length, selectionStartIndex);
int targetCaretIndex = Math.Max(0, Math.Min(selectionEndIndex, Math.Min(selectionStartIndex, Text.Length - 1)));
int selectionLength = Math.Min(Text.Length - targetCaretIndex, selectedText.Length);
SetText(Text.Remove(targetCaretIndex, selectionLength));
CaretIndex = targetCaretIndex;
ClearSelection();
OnTextChanged?.Invoke(this, Text);
}
private float GetWrapWidth()
=> Wrap ? (textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z) / TextBlock.TextScale : float.PositiveInfinity;
private void InitSelectionStart()
{
if (caretPosDirty)
@@ -865,29 +840,20 @@ namespace Barotrauma
if (selectionStartIndex == -1)
{
selectionStartIndex = CaretIndex;
selectionStartPos = caretPos;
}
}
private void CalculateSelection()
{
string textDrawn = Censor ? textBlock.CensoredText : textBlock.WrappedText;
string textDrawn = Censor ? textBlock.CensoredText : WrappedText;
InitSelectionStart();
selectionEndIndex = Math.Min(CaretIndex, textDrawn.Length);
selectionEndPos = caretPos;
selectedCharacters = Math.Abs(selectionStartIndex - selectionEndIndex);
try
{
if (IsLeftToRight)
{
selectedText = Text.Substring(selectionStartIndex, Math.Min(selectedCharacters, Text.Length));
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionStartIndex, Math.Min(selectedCharacters, textDrawn.Length))) * TextBlock.TextScale;
}
else
{
selectedText = Text.Substring(selectionEndIndex, Math.Min(selectedCharacters, Text.Length));
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionEndIndex, Math.Min(selectedCharacters, textDrawn.Length))) * TextBlock.TextScale;
}
selectedText = Text.Substring(
IsLeftToRight ? selectionStartIndex : selectionEndIndex,
Math.Min(selectedCharacters, Text.Length));
}
catch (ArgumentOutOfRangeException exception)
{
@@ -20,18 +20,18 @@ namespace Barotrauma
public override bool Selected
{
get { return selected; }
get { return isSelected; }
set
{
if (value == selected) { return; }
if (value == isSelected) { return; }
if (radioButtonGroup != null && radioButtonGroup.SelectedRadioButton == this)
{
selected = true;
isSelected = true;
return;
}
selected = value;
State = selected ? ComponentState.Selected : ComponentState.None;
isSelected = value;
State = isSelected ? ComponentState.Selected : ComponentState.None;
if (value && radioButtonGroup != null)
{
radioButtonGroup.SelectRadioButton(this);
@@ -88,7 +88,7 @@ namespace Barotrauma
}
}*/
public override ScalableFont Font
public override GUIFont Font
{
get
{
@@ -112,7 +112,7 @@ namespace Barotrauma
get { return text; }
}
public override string ToolTip
public override RichString ToolTip
{
get { return base.ToolTip; }
set
@@ -123,13 +123,13 @@ namespace Barotrauma
}
}
public string Text
public LocalizedString Text
{
get { return text.Text; }
set { text.Text = value; }
}
public GUITickBox(RectTransform rectT, string label, ScalableFont font = null, string style = "") : base(null, rectT)
public GUITickBox(RectTransform rectT, LocalizedString label, GUIFont font = null, string style = "") : base(null, rectT)
{
CanBeFocused = true;
HoverCursor = CursorState.Hand;
@@ -145,7 +145,7 @@ namespace Barotrauma
SelectedColor = Color.DarkGray,
CanBeFocused = false
};
GUI.Style.Apply(box, style == "" ? "GUITickBox" : style);
GUIStyle.Apply(box, style == "" ? "GUITickBox" : style);
if (box.RectTransform.MinSize.Y > 0)
{
RectTransform.MinSize = box.RectTransform.MinSize;
@@ -159,7 +159,7 @@ namespace Barotrauma
{
CanBeFocused = false
};
GUI.Style.Apply(text, "GUITextBlock", this);
GUIStyle.Apply(text, "GUITextBlock", this);
Enabled = true;
ResizeBox();
@@ -205,13 +205,13 @@ namespace Barotrauma
{
Selected = !Selected;
}
else if (!selected)
else if (!isSelected)
{
Selected = true;
}
}
}
else if (selected)
else if (isSelected)
{
State = ComponentState.Selected;
}
@@ -90,7 +90,8 @@ namespace Barotrauma
if (GameMain.Instance != null)
{
GameMain.Instance.ResolutionChanged += CreateAreas;
GameMain.Config.OnHUDScaleChanged += CreateAreas;
#warning TODO: reimplement
//GameSettings.CurrentConfig.OnHUDScaleChanged += CreateAreas;
CreateAreas();
CharacterInfo.Init();
}
@@ -163,7 +164,7 @@ namespace Barotrauma
public static void Draw(SpriteBatch spriteBatch)
{
GUI.DrawRectangle(spriteBatch, ButtonAreaTop, Color.White * 0.5f);
GUI.DrawRectangle(spriteBatch, MessageAreaTop, GUI.Style.Orange * 0.5f);
GUI.DrawRectangle(spriteBatch, MessageAreaTop, GUIStyle.Orange * 0.5f);
GUI.DrawRectangle(spriteBatch, CrewArea, Color.Blue * 0.5f);
GUI.DrawRectangle(spriteBatch, ChatBoxArea, Color.Cyan * 0.5f);
GUI.DrawRectangle(spriteBatch, HealthBarArea, Color.Red * 0.5f);
@@ -7,6 +7,7 @@ using System.Xml.Linq;
using Barotrauma.Media;
using System.Linq;
using Barotrauma.Extensions;
using System.Collections.Immutable;
namespace Barotrauma
{
@@ -69,14 +70,10 @@ namespace Barotrauma
}
}
private string selectedTip;
private List<RichTextData> selectedTipRichTextData;
private bool selectedTipRichTextUnparsed;
private void SetSelectedTip(string tip)
private RichString selectedTip;
private void SetSelectedTip(LocalizedString tip)
{
selectedTip = tip;
selectedTipRichTextData = null;
selectedTipRichTextUnparsed = true;
selectedTip = RichString.Rich(tip);
}
private readonly object loadMutex = new object();
@@ -113,6 +110,8 @@ namespace Barotrauma
set;
}
public LanguageIdentifier[] AvailableLanguages = null;
public LoadingScreen(GraphicsDevice graphics)
{
defaultBackgroundTexture = TextureLoader.FromFile("Content/Map/LocationPortraits/AlienRuins.png");
@@ -123,12 +122,12 @@ namespace Barotrauma
overlay = TextureLoader.FromFile("Content/UI/LoadingScreenOverlay.png");
noiseSprite = new Sprite("Content/UI/noise.png", Vector2.Zero);
DrawLoadingText = true;
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
SetSelectedTip(TextManager.Get("LoadingScreenTip"));
}
public void Draw(SpriteBatch spriteBatch, GraphicsDevice graphics, float deltaTime)
{
if (GameMain.Config.EnableSplashScreen)
if (GameSettings.CurrentConfig.EnableSplashScreen)
{
try
{
@@ -138,11 +137,11 @@ namespace Barotrauma
catch (Exception e)
{
DebugConsole.ThrowError("Playing splash screen video failed", e);
GameMain.Config.EnableSplashScreen = false;
DisableSplashScreen();
}
}
var titleStyle = GUI.Style?.GetComponentStyle("TitleText");
var titleStyle = GUIStyle.GetComponentStyle("TitleText");
Sprite titleSprite = null;
if (!WaitForLanguageSelection && titleStyle != null && titleStyle.Sprites.ContainsKey(GUIComponent.ComponentState.None))
{
@@ -187,67 +186,58 @@ namespace Barotrauma
}
else if (DrawLoadingText)
{
if (TextManager.Initialized)
LocalizedString loadText;
if (LoadState == 100.0f)
{
string loadText;
if (LoadState == 100.0f)
#if DEBUG
if (GameSettings.CurrentConfig.AutomaticQuickStartEnabled || GameSettings.CurrentConfig.AutomaticCampaignLoadEnabled || (GameSettings.CurrentConfig.TestScreenEnabled && GameMain.FirstLoad))
{
#if DEBUG
if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled || GameMain.Config.TestScreenEnabled && GameMain.FirstLoad)
{
loadText = "QUICKSTARTING ...";
}
else
{
#endif
loadText = TextManager.Get("PressAnyKey");
#if DEBUG
}
#endif
loadText = "QUICKSTARTING ...";
}
else
{
loadText = TextManager.Get("Loading");
if (LoadState != null)
{
loadText += " " + (int)LoadState + " %";
#endif
loadText = TextManager.Get("PressAnyKey");
#if DEBUG
}
#endif
}
else
{
loadText = TextManager.Get("Loading");
if (LoadState != null)
{
loadText += " " + (int)LoadState + " %";
#if DEBUG
if (GameMain.FirstLoad && GameMain.CancelQuickStart)
{
loadText += " (Quickstart aborted)";
}
#endif
if (GameMain.FirstLoad && GameMain.CancelQuickStart)
{
loadText += " (Quickstart aborted)";
}
}
if (GUI.LargeFont != null)
{
GUI.LargeFont.DrawString(spriteBatch, loadText.ToUpper(),
new Vector2(GameMain.GraphicsWidth / 2.0f - GUI.LargeFont.MeasureString(loadText.ToUpper()).X / 2.0f, GameMain.GraphicsHeight * 0.75f),
Color.White);
#endif
}
}
if (GUI.Font != null && selectedTip != null)
if (GUIStyle.LargeFont.HasValue)
{
if (selectedTipRichTextUnparsed)
{
selectedTipRichTextData = RichTextData.GetRichTextData(selectedTip, out selectedTip);
selectedTipRichTextUnparsed = false;
}
GUIStyle.LargeFont.DrawString(spriteBatch, loadText.ToUpper(),
new Vector2(GameMain.GraphicsWidth / 2.0f - GUIStyle.LargeFont.MeasureString(loadText.ToUpper()).X / 2.0f, GameMain.GraphicsHeight * 0.75f),
Color.White);
}
string wrappedTip = ToolBox.WrapText(selectedTip, GameMain.GraphicsWidth * 0.5f, GUI.Font);
if (GUIStyle.Font.HasValue && selectedTip != null)
{
string wrappedTip = ToolBox.WrapText(selectedTip.SanitizedValue, GameMain.GraphicsWidth * 0.5f, GUIStyle.Font.Value);
string[] lines = wrappedTip.Split('\n');
float lineHeight = GUI.Font.MeasureString(selectedTip).Y;
float lineHeight = GUIStyle.Font.MeasureString(selectedTip).Y;
if (selectedTipRichTextData != null)
if (selectedTip.RichTextData != null)
{
int rtdOffset = 0;
for (int i = 0; i < lines.Length; i++)
{
GUI.Font.DrawStringWithColors(spriteBatch, lines[i],
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White,
0f, Vector2.Zero, 1f, SpriteEffects.None, 0f, selectedTipRichTextData, rtdOffset);
GUIStyle.Font.DrawStringWithColors(spriteBatch, lines[i],
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUIStyle.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White,
0f, Vector2.Zero, 1f, SpriteEffects.None, 0f, selectedTip.RichTextData.Value, rtdOffset);
rtdOffset += lines[i].Length;
}
}
@@ -255,8 +245,8 @@ namespace Barotrauma
{
for (int i = 0; i < lines.Length; i++)
{
GUI.Font.DrawString(spriteBatch, lines[i],
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White);
GUIStyle.Font.DrawString(spriteBatch, lines[i],
new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUIStyle.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White);
}
}
}
@@ -280,7 +270,7 @@ namespace Barotrauma
if (noiseVal < 0.2f)
{
//SCP-CB reference
randText = (new string[] { "NIL", "black white gray", "Sometimes we would have had time to scream", "e8m106]af", "NO" }).GetRandom();
randText = (new string[] { "NIL", "black white gray", "Sometimes we would have had time to scream", "e8m106]af", "NO" }).GetRandomUnsynced();
}
else if (noiseVal < 0.3f)
{
@@ -295,15 +285,20 @@ namespace Barotrauma
Rand.Int(100).ToString().PadLeft(2, '0');
}
GUI.LargeFont?.DrawString(spriteBatch, randText,
new Vector2(GameMain.GraphicsWidth - decorativeMap.FrameSize.X * decorativeScale.X * 0.8f, GameMain.GraphicsHeight * 0.57f),
Color.White * (1.0f - noiseVal));
if (GUIStyle.LargeFont.HasValue)
{
GUIStyle.LargeFont.DrawString(spriteBatch, randText,
new Vector2(GameMain.GraphicsWidth - decorativeMap.FrameSize.X * decorativeScale.X * 0.8f, GameMain.GraphicsHeight * 0.57f),
Color.White * (1.0f - noiseVal));
}
spriteBatch.End();
}
private void DrawLanguageSelectionPrompt(SpriteBatch spriteBatch, GraphicsDevice graphicsDevice)
{
if (AvailableLanguages is null) { return; }
if (languageSelectionFont == null)
{
languageSelectionFont = new ScalableFont("Content/Fonts/NotoSans/NotoSans-Bold.ttf",
@@ -320,8 +315,8 @@ namespace Barotrauma
}
Vector2 textPos = new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight * 0.3f);
Vector2 textSpacing = new Vector2(0.0f, (GameMain.GraphicsHeight * 0.5f) / TextManager.AvailableLanguages.Count());
foreach (string language in TextManager.AvailableLanguages)
Vector2 textSpacing = new Vector2(0.0f, (GameMain.GraphicsHeight * 0.5f) / AvailableLanguages.Length);
foreach (LanguageIdentifier language in AvailableLanguages)
{
string localizedLanguageName = TextManager.GetTranslatedLanguageName(language);
var font = TextManager.IsCJK(localizedLanguageName) ? languageSelectionFontCJK : languageSelectionFont;
@@ -335,11 +330,11 @@ namespace Barotrauma
hover ? Color.White : Color.White * 0.6f);
if (hover && PlayerInput.PrimaryMouseButtonClicked())
{
GameMain.Config.Language = language;
var config = GameSettings.CurrentConfig;
config.Language = language;
GameSettings.SetCurrentConfig(config);
//reload tip in the selected language
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
GameMain.Config.SetDefaultBindings(legacy: false);
GameMain.Config.CheckBindings(useDefaults: true);
SetSelectedTip(TextManager.Get("LoadingScreenTip"));
WaitForLanguageSelection = false;
languageSelectionFont?.Dispose(); languageSelectionFont = null;
languageSelectionFontCJK?.Dispose(); languageSelectionFontCJK = null;
@@ -368,7 +363,7 @@ namespace Barotrauma
}
catch (Exception e)
{
GameMain.Config.EnableSplashScreen = false;
DisableSplashScreen();
DebugConsole.ThrowError("Playing the splash screen \"" + fileName + "\" failed.", e);
PendingSplashScreens.Clear();
currSplashScreen = null;
@@ -425,13 +420,20 @@ namespace Barotrauma
}
}
private void DisableSplashScreen()
{
var config = GameSettings.CurrentConfig;
config.EnableSplashScreen = false;
GameSettings.SetCurrentConfig(config);
}
bool drawn;
public IEnumerable<CoroutineStatus> DoLoading(IEnumerable<CoroutineStatus> loader)
{
drawn = false;
LoadState = null;
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
currentBackgroundTexture = LocationType.List.GetRandom()?.GetPortrait(Rand.Int(int.MaxValue))?.Texture;
SetSelectedTip(TextManager.Get("LoadingScreenTip"));
currentBackgroundTexture = LocationType.Prefabs.GetRandomUnsynced()?.GetPortrait(Rand.Int(int.MaxValue))?.Texture;
while (!drawn)
{
@@ -50,7 +50,7 @@ namespace Barotrauma
Afflictions = new List<PendingAfflictionElement>();
}
public PendingAfflictionElement? FindAfflictionElement(MedicalClinic.NetAffliction target) => Afflictions.FirstOrNull(element => element.Target.Identifier.Equals(target.Identifier, StringComparison.OrdinalIgnoreCase));
public PendingAfflictionElement? FindAfflictionElement(MedicalClinic.NetAffliction target) => Afflictions.FirstOrNull(element => element.Target.Identifier == target.Identifier);
}
// Represents an affliction on the left side crew entry
@@ -268,12 +268,12 @@ namespace Barotrauma
}
int totalCost = medicalClinic.GetTotalCost();
healList.PriceBlock.Text = UpgradeStore.FormatCurrency(totalCost);
healList.PriceBlock.TextColor = GUI.Style.Red;
healList.PriceBlock.Text = TextManager.FormatCurrency(totalCost);
healList.PriceBlock.TextColor = GUIStyle.Red;
healList.HealButton.Enabled = false;
if (medicalClinic.GetMoney() > totalCost)
if (medicalClinic.GetWallet().CanAfford(totalCost))
{
healList.PriceBlock.TextColor = GUI.Style.TextColor;
healList.PriceBlock.TextColor = GUIStyle.TextColorNormal;
if (medicalClinic.PendingHeals.Any())
{
healList.HealButton.Enabled = true;
@@ -288,7 +288,7 @@ namespace Barotrauma
{
if (element.FindAfflictionElement(affliction) is { } existingAffliction)
{
existingAffliction.Price.Text = UpgradeStore.FormatCurrency(affliction.Strength);
existingAffliction.Price.Text = TextManager.FormatCurrency(affliction.Strength);
continue;
}
@@ -443,7 +443,7 @@ namespace Barotrauma
GUILayoutGroup clinicLabelLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), clinicContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
GUIImage clinicIcon = new GUIImage(new RectTransform(Vector2.One, clinicLabelLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "CrewManagementHeaderIcon", scaleToFit: true);
GUITextBlock clinicLabel = new GUITextBlock(new RectTransform(Vector2.One, clinicLabelLayout.RectTransform), TextManager.Get("medicalclinic.medicalclinic"), font: GUI.LargeFont);
GUITextBlock clinicLabel = new GUITextBlock(new RectTransform(Vector2.One, clinicLabelLayout.RectTransform), TextManager.Get("medicalclinic.medicalclinic"), font: GUIStyle.LargeFont);
GUIFrame clinicBackground = new GUIFrame(new RectTransform(Vector2.One, clinicContent.RectTransform));
@@ -459,15 +459,15 @@ namespace Barotrauma
};
GUILayoutGroup balanceLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), crewContent.RectTransform));
GUITextBlock balanceLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), TextManager.Get("campaignstore.balance"), textAlignment: Alignment.BottomRight, font: GUI.Font)
GUITextBlock balanceLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), TextManager.Get("campaignstore.balance"), textAlignment: Alignment.BottomRight, font: GUIStyle.Font)
{
AutoScaleVertical = true,
ForceUpperCase = true
ForceUpperCase = ForceUpperCase.Yes
};
GUITextBlock moneyLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), string.Empty, textAlignment: Alignment.TopRight, font: GUI.Style.SubHeadingFont)
GUITextBlock moneyLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), string.Empty, textAlignment: Alignment.TopRight, font: GUIStyle.SubHeadingFont)
{
TextGetter = () => UpgradeStore.FormatCurrency(medicalClinic.GetMoney()),
TextGetter = () => TextManager.FormatCurrency(medicalClinic.GetWallet().Balance),
AutoScaleVertical = true,
TextScale = 1.1f
};
@@ -519,18 +519,18 @@ namespace Barotrauma
GUILayoutGroup healthLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.1f, 1f), crewLayout.RectTransform), isHorizontal: true, Anchor.Center);
new GUITextBlock(new RectTransform(Vector2.One, healthLayout.RectTransform), string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont)
new GUITextBlock(new RectTransform(Vector2.One, healthLayout.RectTransform), string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont)
{
TextGetter = () => $"{(int)(info.Character?.HealthPercentage ?? 100f)}%",
TextColor = GUI.Style.Green
TextGetter = () => TextManager.GetWithVariable("percentageformat", "[value]", $"{(int)(info.Character?.HealthPercentage ?? 100f)}"),
TextColor = GUIStyle.Green
};
GUITextBlock overflowIndicator =
new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), afflictionList.Content.RectTransform, scaleBasis: ScaleBasis.BothHeight), text: "+", textAlignment: Alignment.Center, font: GUI.LargeFont)
new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), afflictionList.Content.RectTransform, scaleBasis: ScaleBasis.BothHeight), text: "+", textAlignment: Alignment.Center, font: GUIStyle.LargeFont)
{
Visible = false,
CanBeFocused = false,
TextColor = GUI.Style.Red
TextColor = GUIStyle.Red
};
MedicalClinic.NetCrewMember member = new MedicalClinic.NetCrewMember { CharacterInfo = info, Afflictions = Array.Empty<MedicalClinic.NetAffliction>() };
@@ -552,13 +552,13 @@ namespace Barotrauma
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(1f, 0.05f), pendingHealContainer.RectTransform), TextManager.Get("medicalclinic.pendingheals"), font: GUI.SubHeadingFont);
new GUITextBlock(new RectTransform(new Vector2(1f, 0.05f), pendingHealContainer.RectTransform), TextManager.Get("medicalclinic.pendingheals"), font: GUIStyle.SubHeadingFont);
GUIFrame healListContainer = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), pendingHealContainer.RectTransform), style: null);
GUITextBlock? errorBlock = null;
if (!GameMain.IsSingleplayer)
{
errorBlock = new GUITextBlock(new RectTransform(Vector2.One, healListContainer.RectTransform), text: TextManager.Get("pleasewaitupnp"), font: GUI.LargeFont, textAlignment: Alignment.Center);
errorBlock = new GUITextBlock(new RectTransform(Vector2.One, healListContainer.RectTransform), text: TextManager.Get("pleasewaitupnp"), font: GUIStyle.LargeFont, textAlignment: Alignment.Center);
}
GUIListBox healList = new GUIListBox(new RectTransform(Vector2.One, healListContainer.RectTransform))
@@ -571,13 +571,13 @@ namespace Barotrauma
GUILayoutGroup priceLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true);
GUITextBlock priceLabelBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), priceLayout.RectTransform), TextManager.Get("campaignstore.total"));
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), priceLayout.RectTransform), UpgradeStore.FormatCurrency(medicalClinic.GetTotalCost()), font: GUI.SubHeadingFont,
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), priceLayout.RectTransform), TextManager.FormatCurrency(medicalClinic.GetTotalCost()), font: GUIStyle.SubHeadingFont,
textAlignment: Alignment.Right);
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterRight);
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.33f, 1f), buttonLayout.RectTransform), TextManager.Get("medicalclinic.heal"))
{
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetTotalCost() < medicalClinic.GetMoney(),
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetWallet().CanAfford(medicalClinic.GetTotalCost()),
OnClicked = (button, _) =>
{
button.Enabled = false;
@@ -679,12 +679,12 @@ namespace Barotrauma
GUILayoutGroup textLayout = new GUILayoutGroup(new RectTransform(Vector2.One, parentLayout.RectTransform), isHorizontal: true);
string name = prefab.Name;
LocalizedString name = prefab.Name;
GUIFrame textContainer = new GUIFrame(new RectTransform(new Vector2(0.6f, 1f), textLayout.RectTransform), style: null);
GUITextBlock afflictionName = new GUITextBlock(new RectTransform(Vector2.One, textContainer.RectTransform), name, font: GUI.SubHeadingFont);
GUITextBlock afflictionName = new GUITextBlock(new RectTransform(Vector2.One, textContainer.RectTransform), name, font: GUIStyle.SubHeadingFont);
GUITextBlock healCost = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), textLayout.RectTransform), UpgradeStore.FormatCurrency(affliction.Price), textAlignment: Alignment.Center, font: GUI.LargeFont)
GUITextBlock healCost = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), textLayout.RectTransform), TextManager.FormatCurrency(affliction.Price), textAlignment: Alignment.Center, font: GUIStyle.LargeFont)
{
Padding = Vector4.Zero
};
@@ -702,7 +702,7 @@ namespace Barotrauma
}
};
EnsureTextDoesntOverflow(name, afflictionName, textContainer.Rect, ImmutableArray.Create(textLayout, parentLayout));
EnsureTextDoesntOverflow(name.Value, afflictionName, textContainer.Rect, ImmutableArray.Create(textLayout, parentLayout));
healElement.Afflictions.Add(new PendingAfflictionElement(affliction, backgroundFrame, healCost));
@@ -720,8 +720,8 @@ namespace Barotrauma
GUILayoutGroup textGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.8f), parent.RectTransform));
string? characterName = info.Name,
jobName = null;
string? characterName = info.Name;
LocalizedString? jobName = null;
GUITextBlock? nameBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), textGroup.RectTransform), characterName),
jobBlock = null;
@@ -741,7 +741,7 @@ namespace Barotrauma
if (jobBlock is null) { return; }
EnsureTextDoesntOverflow(jobName, jobBlock, parent.Rect, layoutGroups);
EnsureTextDoesntOverflow(jobName?.Value, jobBlock, parent.Rect, layoutGroups);
}
}
@@ -766,14 +766,14 @@ namespace Barotrauma
mainFrame.RectTransform.ScreenSpaceOffset = new Point((int)location.X, GameMain.GraphicsHeight - mainFrame.Rect.Height);
}
GUITextBlock feedbackBlock = new GUITextBlock(new RectTransform(Vector2.One, mainFrame.RectTransform), TextManager.Get("pleasewaitupnp"), textAlignment: Alignment.Center, font: GUI.LargeFont, wrap: true)
GUITextBlock feedbackBlock = new GUITextBlock(new RectTransform(Vector2.One, mainFrame.RectTransform), TextManager.Get("pleasewaitupnp"), textAlignment: Alignment.Center, font: GUIStyle.LargeFont, wrap: true)
{
Visible = true
};
GUIButton treatAllButton = new GUIButton(new RectTransform(new Vector2(1f, 0.2f), mainLayout.RectTransform), TextManager.Get("medicalclinic.treatall"))
{
Font = GUI.SubHeadingFont,
Font = GUIStyle.SubHeadingFont,
Visible = false
};
@@ -793,7 +793,7 @@ namespace Barotrauma
if (request.Result != MedicalClinic.RequestResult.Success)
{
feedbackBlock.Text = GetErrorText(request.Result);
feedbackBlock.TextColor = GUI.Style.Red;
feedbackBlock.TextColor = GUIStyle.Red;
return;
}
@@ -844,11 +844,11 @@ namespace Barotrauma
GUILayoutGroup topTextLayout = new GUILayoutGroup(new RectTransform(Vector2.One, topLayout.RectTransform), isHorizontal: true);
GUITextBlock prefabBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), topTextLayout.RectTransform), prefab.Name, font: GUI.SubHeadingFont);
GUITextBlock prefabBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), topTextLayout.RectTransform), prefab.Name, font: GUIStyle.SubHeadingFont);
Color textColor = Color.Lerp(GUI.Style.Orange, GUI.Style.Red, (int)affliction.AfflictionSeverity / 2f);
Color textColor = Color.Lerp(GUIStyle.Orange, GUIStyle.Red, (int)affliction.AfflictionSeverity / 2f);
string vitalityText = TextManager.GetWithVariable("medicalclinic.vitalitydifference", "[amount]", (-affliction.Strength).ToString());
LocalizedString vitalityText = TextManager.GetWithVariable("medicalclinic.vitalitydifference", "[amount]", (-affliction.Strength).ToString());
GUITextBlock vitalityBlock = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), topTextLayout.RectTransform), vitalityText, textAlignment: Alignment.Center)
{
TextColor = textColor,
@@ -857,8 +857,8 @@ namespace Barotrauma
AutoScaleHorizontal = true
};
string severityText = TextManager.Get($"AfflictionStrength{affliction.AfflictionSeverity}");
GUITextBlock severityBlock = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), topTextLayout.RectTransform), severityText, textAlignment: Alignment.Center, font: GUI.SubHeadingFont)
LocalizedString severityText = TextManager.Get($"AfflictionStrength{affliction.AfflictionSeverity}");
GUITextBlock severityBlock = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1f), topTextLayout.RectTransform), severityText, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont)
{
TextColor = textColor,
DisabledTextColor = textColor * 0.5f,
@@ -866,17 +866,17 @@ namespace Barotrauma
AutoScaleHorizontal = true
};
EnsureTextDoesntOverflow(prefab.Name, prefabBlock, prefabBlock.Rect, ImmutableArray.Create(mainLayout, topLayout, topTextLayout));
EnsureTextDoesntOverflow(prefab.Name.Value, prefabBlock, prefabBlock.Rect, ImmutableArray.Create(mainLayout, topLayout, topTextLayout));
GUILayoutGroup bottomLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.66f), mainLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
GUILayoutGroup bottomTextLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1f), bottomLayout.RectTransform));
GUITextBlock descriptionBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), ToolBox.LimitString(prefab.Description, GUI.IntScale(64)), wrap: true)
GUITextBlock descriptionBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), ToolBox.LimitString(prefab.Description, GUIStyle.Font, GUI.IntScale(64)), wrap: true)
{
ToolTip = prefab.Description
};
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), UpgradeStore.FormatCurrency(affliction.Price), font: GUI.LargeFont);
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), TextManager.FormatCurrency(affliction.Price), font: GUIStyle.LargeFont);
GUIButton buyButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.75f), bottomLayout.RectTransform), style: "CrewManagementAddButton");
@@ -931,7 +931,7 @@ namespace Barotrauma
});
}
private static void EnsureTextDoesntOverflow(string? text, GUITextBlock textBlock, Rectangle bounds, ImmutableArray<GUILayoutGroup>? layoutGroups = null)
public static void EnsureTextDoesntOverflow(string? text, GUITextBlock textBlock, Rectangle bounds, ImmutableArray<GUILayoutGroup>? layoutGroups = null)
{
if (string.IsNullOrWhiteSpace(text)) { return; }
@@ -968,7 +968,7 @@ namespace Barotrauma
if (GameMain.IsSingleplayer || !(pendingHealList is { ErrorBlock: { } errorBlock, HealList: { } healList })) { return; }
errorBlock.Visible = true;
errorBlock.TextColor = GUI.Style.TextColor;
errorBlock.TextColor = GUIStyle.TextColorNormal;
errorBlock.Text = TextManager.Get("pleasewaitupnp");
healList.Visible = false;
@@ -983,7 +983,7 @@ namespace Barotrauma
if (request.Result != MedicalClinic.RequestResult.Success)
{
errorBlock.Text = GetErrorText(request.Result);
errorBlock.TextColor = GUI.Style.Red;
errorBlock.TextColor = GUIStyle.Red;
return;
}
@@ -1011,7 +1011,7 @@ namespace Barotrauma
selectedCrewAfflictionList = null;
}
private static string GetErrorText(MedicalClinic.RequestResult result)
private static LocalizedString GetErrorText(MedicalClinic.RequestResult result)
{
return result switch
{
File diff suppressed because it is too large Load Diff
@@ -31,19 +31,12 @@ namespace Barotrauma
private readonly List<SubmarineInfo> subsToShow;
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
private SubmarineInfo selectedSubmarine = null;
private string purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyShorthandText, currencyLongText;
private LocalizedString purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyName;
private readonly RectTransform parent;
private readonly Action closeAction;
private Sprite pageIndicator;
public static readonly string[] DeliveryTextVariables = new string[] { "[submarinename1]", "[location1]", "[location2]", "[submarinename2]", "[amount]", "[currencyname]" };
public static readonly string[] SwitchTextVariables = new string[] { "[submarinename1]", "[submarinename2]" };
public static readonly string[] PurchaseAndSwitchTextVariables = new string[] { "[submarinename1]", "[amount]", "[currencyname]", "[submarinename2]" };
public static readonly string[] PurchaseTextVariables = new string[] { "[submarinename]", "[amount]", "[currencyname]" };
private static readonly string[] notEnoughCreditsDeliveryTextVariables = new string[] { "[currencyname]", "[submarinename]", "[location1]", "[location2]" };
private static readonly string[] notEnoughCreditsPurchaseTextVariables = new string[] { "[currencyname]", "[submarinename]" };
private readonly string[] messageBoxOptions;
private readonly LocalizedString[] messageBoxOptions;
public const int DeliveryFeePerDistanceTravelled = 1000;
public static bool ContentRefreshRequired = false;
@@ -77,11 +70,11 @@ namespace Barotrauma
if (GameMain.Client == null)
{
messageBoxOptions = new string[2] { TextManager.Get("Yes"), TextManager.Get("Cancel") };
messageBoxOptions = new LocalizedString[2] { TextManager.Get("Yes"), TextManager.Get("Cancel") };
}
else
{
messageBoxOptions = new string[2] { TextManager.Get("Yes") + " " + TextManager.Get("initiatevoting"), TextManager.Get("Cancel") };
messageBoxOptions = new LocalizedString[2] { TextManager.Get("Yes") + " " + TextManager.Get("initiatevoting"), TextManager.Get("Cancel") };
}
if (Submarine.MainSub?.Info == null) { return; }
@@ -91,23 +84,19 @@ namespace Barotrauma
private void Initialize()
{
initialized = true;
currentSubText = TextManager.Get("currentsub");
deliveryFeeText = TextManager.Get("deliveryfee");
deliveryText = TextManager.Get("requestdeliverybutton");
switchText = TextManager.Get("switchtosubmarinebutton");
purchaseAndSwitchText = TextManager.Get("purchaseandswitch");
purchaseOnlyText = TextManager.Get("purchase");
priceText = TextManager.Get("price");
if (transferService)
{
deliveryFee = CalculateDeliveryFee();
currentSubText = TextManager.Get("currentsub");
deliveryFeeText = TextManager.Get("deliveryfee");
deliveryText = TextManager.Get("requestdeliverybutton");
switchText = TextManager.Get("switchtosubmarinebutton");
}
else
{
purchaseAndSwitchText = TextManager.Get("purchaseandswitch");
purchaseOnlyText = TextManager.Get("purchase");
priceText = TextManager.Get("price");
}
currencyShorthandText = TextManager.Get("currencyformat");
currencyLongText = TextManager.Get("credit").ToLower();
currencyName = TextManager.Get("credit").Value.ToLowerInvariant();
UpdateSubmarines();
missingPreviewText = TextManager.Get("SubPreviewImageNotFound");
@@ -135,9 +124,9 @@ namespace Barotrauma
};
content = new GUILayoutGroup(new RectTransform(new Point(background.Rect.Width - HUDLayoutSettings.Padding * 4, background.Rect.Height - HUDLayoutSettings.Padding * 4), background.RectTransform, Anchor.Center)) { AbsoluteSpacing = (int)(HUDLayoutSettings.Padding * 1.5f) };
GUITextBlock header = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), content.RectTransform), transferService ? TextManager.Get("switchsubmarineheader") : TextManager.GetWithVariable("outpostshipyard", "[location]", GameMain.GameSession.Map.CurrentLocation.Name), font: GUI.LargeFont);
GUITextBlock header = new GUITextBlock(new RectTransform(new Vector2(1f, 0.0f), content.RectTransform), transferService ? TextManager.Get("switchsubmarineheader") : TextManager.GetWithVariable("outpostshipyard", "[location]", GameMain.GameSession.Map.CurrentLocation.Name), font: GUIStyle.LargeFont);
header.CalculateHeightFromText(0, true);
GUITextBlock credits = new GUITextBlock(new RectTransform(Vector2.One, header.RectTransform), "", font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight)
GUITextBlock credits = new GUITextBlock(new RectTransform(Vector2.One, header.RectTransform), "", font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterRight)
{
TextGetter = CampaignUI.GetMoney
};
@@ -159,7 +148,7 @@ namespace Barotrauma
specsFrame = new GUIListBox(new RectTransform(new Vector2(0.39f, 1f), infoFrame.RectTransform), style: null) { Spacing = GUI.IntScale(5), Padding = new Vector4(HUDLayoutSettings.Padding / 2f, HUDLayoutSettings.Padding, 0, 0) };
new GUIFrame(new RectTransform(new Vector2(0.02f, 0.8f), infoFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.1f) }, style: "VerticalLine");
GUIListBox descriptionFrame = new GUIListBox(new RectTransform(new Vector2(0.59f, 1f), infoFrame.RectTransform), style: null) { Padding = new Vector4(HUDLayoutSettings.Padding / 2f, HUDLayoutSettings.Padding * 1.5f, HUDLayoutSettings.Padding * 1.5f, HUDLayoutSettings.Padding / 2f) };
descriptionTextBlock = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionFrame.Content.RectTransform), string.Empty, font: GUI.Font, wrap: true) { CanBeFocused = false };
descriptionTextBlock = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionFrame.Content.RectTransform), string.Empty, font: GUIStyle.Font, wrap: true) { CanBeFocused = false };
GUILayoutGroup buttonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.075f), content.RectTransform), childAnchor: Anchor.CenterRight) { IsHorizontal = true, AbsoluteSpacing = HUDLayoutSettings.Padding };
@@ -180,7 +169,7 @@ namespace Barotrauma
SetConfirmButtonState(false);
pageIndicatorHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.5f), submarineControlsGroup.RectTransform), style: null);
pageIndicator = GUI.Style.GetComponentStyle("GUIPageIndicator").GetDefaultSprite();
pageIndicator = GUIStyle.GetComponentStyle("GUIPageIndicator").GetDefaultSprite();
UpdatePaging();
for (int i = 0; i < submarineDisplays.Length; i++)
@@ -191,9 +180,9 @@ namespace Barotrauma
};
submarineDisplayElement.submarineImage = new GUIImage(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), null, true);
submarineDisplayElement.middleTextBlock = new GUITextBlock(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), string.Empty, textAlignment: Alignment.Center);
submarineDisplayElement.submarineName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUI.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Center);
submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
submarineDisplayElement.submarineName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont);
submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUIStyle.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Center);
submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont);
submarineDisplayElement.selectSubmarineButton = new GUIButton(new RectTransform(Vector2.One, submarineDisplayElement.background.RectTransform), style: null);
submarineDisplayElement.previewButton = new GUIButton(new RectTransform(Vector2.One * 0.12f, submarineDisplayElement.background.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point((int)(0.03f * background.Rect.Height)) }, style: "ExpandButton")
{
@@ -342,7 +331,7 @@ namespace Barotrauma
if (!GameMain.GameSession.IsSubmarineOwned(subToDisplay))
{
string amountString = currencyShorthandText.Replace("[credits]", subToDisplay.Price.ToString());
LocalizedString amountString = TextManager.FormatCurrency(subToDisplay.Price);
submarineDisplays[i].submarineFee.Text = priceText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
}
else
@@ -351,7 +340,7 @@ namespace Barotrauma
{
if (deliveryFee > 0)
{
string amountString = currencyShorthandText.Replace("[credits]", deliveryFee.ToString());
LocalizedString amountString = TextManager.FormatCurrency(deliveryFee);
submarineDisplays[i].submarineFee.Text = deliveryFeeText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
}
else
@@ -535,7 +524,7 @@ namespace Barotrauma
listBackground.Sprite = previewImage;
listBackground.SetCrop(true);
ScalableFont font = GUI.Font;
GUIFont font = GUIStyle.Font;
info.CreateSpecsWindow(specsFrame, font);
descriptionTextBlock.Text = info.Description;
descriptionTextBlock.CalculateHeightFromText();
@@ -588,10 +577,13 @@ namespace Barotrauma
private void ShowTransferPrompt()
{
if (GameMain.GameSession.Campaign.Money < deliveryFee && deliveryFee > 0)
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(deliveryFee) && deliveryFee > 0)
{
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext", notEnoughCreditsDeliveryTextVariables,
new string[] { currencyLongText, selectedSubmarine.DisplayName, deliveryLocationName, GameMain.GameSession.Map.CurrentLocation.Name }));
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext",
("[currencyname]", currencyName),
("[submarinename]", selectedSubmarine.DisplayName),
("[location1]", deliveryLocationName),
("[location2]", GameMain.GameSession.Map.CurrentLocation.Name)));
return;
}
@@ -599,13 +591,19 @@ namespace Barotrauma
if (deliveryFee > 0)
{
msgBox = new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("deliveryrequesttext", DeliveryTextVariables,
new string[6] { selectedSubmarine.DisplayName, deliveryLocationName, GameMain.GameSession.Map.CurrentLocation.Name, CurrentOrPendingSubmarine().DisplayName, deliveryFee.ToString(), currencyLongText }), messageBoxOptions);
msgBox = new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("deliveryrequesttext",
("[submarinename1]", selectedSubmarine.DisplayName),
("[location1]", deliveryLocationName),
("[location2]", GameMain.GameSession.Map.CurrentLocation.Name),
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName),
("[amount]", deliveryFee.ToString()),
("[currencyname]", currencyName)), messageBoxOptions);
}
else
{
msgBox = new GUIMessageBox(TextManager.Get("switchsubmarineheader"), TextManager.GetWithVariables("switchsubmarinetext", SwitchTextVariables,
new string[2] { CurrentOrPendingSubmarine().DisplayName, selectedSubmarine.DisplayName }), messageBoxOptions);
msgBox = new GUIMessageBox(TextManager.Get("switchsubmarineheader"), TextManager.GetWithVariables("switchsubmarinetext",
("[submarinename1]", CurrentOrPendingSubmarine().DisplayName),
("[submarinename2]", selectedSubmarine.DisplayName)), messageBoxOptions);
}
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
@@ -627,10 +625,11 @@ namespace Barotrauma
private void ShowBuyPrompt(bool purchaseOnly)
{
if (GameMain.GameSession.Campaign.Money < selectedSubmarine.Price)
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(selectedSubmarine.Price))
{
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext", notEnoughCreditsPurchaseTextVariables,
new string[2] { currencyLongText, selectedSubmarine.DisplayName }));
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext",
("[currencyname]", currencyName),
("[submarinename]", selectedSubmarine.DisplayName)));
return;
}
@@ -638,8 +637,11 @@ namespace Barotrauma
if (!purchaseOnly)
{
msgBox = new GUIMessageBox(TextManager.Get("purchaseandswitchsubmarineheader"), TextManager.GetWithVariables("purchaseandswitchsubmarinetext", PurchaseAndSwitchTextVariables,
new string[4] { selectedSubmarine.DisplayName, selectedSubmarine.Price.ToString(), currencyLongText, CurrentOrPendingSubmarine().DisplayName }), messageBoxOptions);
msgBox = new GUIMessageBox(TextManager.Get("purchaseandswitchsubmarineheader"), TextManager.GetWithVariables("purchaseandswitchsubmarinetext",
("[submarinename1]", selectedSubmarine.DisplayName),
("[amount]", selectedSubmarine.Price.ToString()),
("[currencyname]", currencyName),
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName)), messageBoxOptions);
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
{
@@ -658,8 +660,10 @@ namespace Barotrauma
}
else
{
msgBox = new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("purchasesubmarinetext", PurchaseTextVariables,
new string[3] { selectedSubmarine.DisplayName, selectedSubmarine.Price.ToString(), currencyLongText }), messageBoxOptions);
msgBox = new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("purchasesubmarinetext",
("[submarinename]", selectedSubmarine.DisplayName),
("[amount]", selectedSubmarine.Price.ToString()),
("[currencyname]", currencyName)), messageBoxOptions);
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
{
File diff suppressed because it is too large Load Diff
@@ -19,11 +19,7 @@ namespace Barotrauma
private set;
}
public bool Slice
{
get;
set;
}
public bool Slice => Slices != null;
public Rectangle[] Slices
{
@@ -54,7 +50,7 @@ namespace Barotrauma
public TransitionMode TransitionMode { get; private set; }
public UISprite(XElement element)
public UISprite(ContentXElement element)
{
Sprite = new Sprite(element);
MaintainAspectRatio = element.GetAttributeBool("maintainaspectratio", false);
@@ -69,6 +65,7 @@ namespace Barotrauma
}
Vector4 sliceVec = element.GetAttributeVector4("slice", Vector4.Zero);
Slices = null;
if (sliceVec != Vector4.Zero)
{
minBorderScale = element.GetAttributeFloat("minborderscale", 0.1f);
@@ -76,7 +73,6 @@ namespace Barotrauma
Rectangle slice = new Rectangle((int)sliceVec.X, (int)sliceVec.Y, (int)(sliceVec.Z - sliceVec.X), (int)(sliceVec.W - sliceVec.Y));
Slice = true;
Slices = new Rectangle[9];
//top-left
@@ -41,7 +41,7 @@ namespace Barotrauma
private readonly CampaignUI campaignUI;
private CampaignMode? Campaign => campaignUI.Campaign;
private int AvailableMoney => Campaign?.Money ?? 0;
private Wallet PlayerWallet => Campaign?.Wallet ?? Wallet.Invalid;
private UpgradeTab selectedUpgradeTab = UpgradeTab.Upgrade;
private GUIMessageBox? currectConfirmation;
@@ -61,7 +61,7 @@ namespace Barotrauma
private Vector2[][] subHullVertices = new Vector2[0][];
private List<Structure> submarineWalls = new List<Structure>();
public MapEntity? HoveredItem;
public MapEntity? HoveredEntity;
private bool highlightWalls;
private UpgradeCategory? currentUpgradeCategory;
@@ -73,6 +73,8 @@ namespace Barotrauma
private Point screenResolution;
private bool needsRefresh = true;
/// <summary>
/// While set to true any call to <see cref="RefreshUpgradeList"/> will cause the buy button to be disabled and to not update the prices.
/// This is to prevent us from buying another upgrade before the server has given us the new prices and causing potential syncing issues.
@@ -102,12 +104,18 @@ namespace Barotrauma
CreateUI(upgradeFrame);
if (Campaign == null) { return; }
Campaign.UpgradeManager.OnUpgradesChanged += RefreshAll;
Campaign.CargoManager.OnPurchasedItemsChanged += RefreshAll;
Campaign.CargoManager.OnSoldItemsChanged += RefreshAll;
Campaign.UpgradeManager.OnUpgradesChanged += RequestRefresh;
Campaign.CargoManager.OnPurchasedItemsChanged += RequestRefresh;
Campaign.CargoManager.OnSoldItemsChanged += RequestRefresh;
Campaign.OnMoneyChanged.RegisterOverwriteExisting(nameof(UpgradeStore).ToIdentifier(), e => { RequestRefresh(); } );
}
public void RefreshAll()
public void RequestRefresh()
{
needsRefresh = true;
}
private void RefreshAll()
{
switch (selectedUpgradeTab)
{
@@ -130,6 +138,7 @@ namespace Barotrauma
}
break;
}
needsRefresh = false;
}
private void RefreshUpgradeList()
@@ -184,7 +193,7 @@ namespace Barotrauma
}
// reset the order first
foreach (UpgradeCategory category in UpgradeCategory.Categories)
foreach (UpgradeCategory category in UpgradeCategory.Categories.OrderBy(c => c.Name))
{
GUIComponent component = categoryList.Content.FindChild(c => c.UserData is CategoryData categoryData && categoryData.Category == category);
component?.SetAsLastChild();
@@ -245,7 +254,7 @@ namespace Barotrauma
* |----------------------------|
*/
GUILayoutGroup tooltipLayout = new GUILayoutGroup(rectT(0.95f,0.95f, ItemInfoFrame, Anchor.Center)) { Stretch = true };
new GUITextBlock(rectT(1, 0, tooltipLayout), string.Empty, font: GUI.SubHeadingFont) { UserData = "itemname" };
new GUITextBlock(rectT(1, 0, tooltipLayout), string.Empty, font: GUIStyle.SubHeadingFont) { UserData = "itemname" };
new GUITextBlock(rectT(1, 0, tooltipLayout), TextManager.Get("UpgradeUITooltip.UpgradeListHeader"));
new GUIListBox(rectT(1, 0.5f, tooltipLayout), style: null) { ScrollBarVisible = false, AutoHideScrollBar = false, SmoothScroll = true, UserData = "upgradelist"};
new GUITextBlock(rectT(1, 0, tooltipLayout), string.Empty) { UserData = "moreindicator" };
@@ -268,7 +277,7 @@ namespace Barotrauma
GUILayoutGroup leftLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout)) { RelativeSpacing = 0.05f };
GUILayoutGroup locationLayout = new GUILayoutGroup(rectT(1, 0.5f, leftLayout), isHorizontal: true);
GUIImage submarineIcon = new GUIImage(rectT(new Point(locationLayout.Rect.Height, locationLayout.Rect.Height), locationLayout), style: "SubmarineIcon", scaleToFit: true);
new GUITextBlock(rectT(1.0f - submarineIcon.RectTransform.RelativeSize.X, 1, locationLayout), TextManager.Get("UpgradeUI.Title"), font: GUI.LargeFont);
new GUITextBlock(rectT(1.0f - submarineIcon.RectTransform.RelativeSize.X, 1, locationLayout), TextManager.Get("UpgradeUI.Title"), font: GUIStyle.LargeFont);
categoryButtonLayout = new GUILayoutGroup(rectT(0.4f, 0.3f, leftLayout), isHorizontal: true) { Stretch = true };
GUIButton upgradeButton = new GUIButton(rectT(1, 1f, categoryButtonLayout), TextManager.Get("UICategory.Upgrades"), style: "GUITabButton") { UserData = UpgradeTab.Upgrade, Selected = selectedUpgradeTab == UpgradeTab.Upgrade };
GUIButton repairButton = new GUIButton(rectT(1, 1f, categoryButtonLayout), TextManager.Get("UICategory.Maintenance"), style: "GUITabButton") { UserData = UpgradeTab.Repairs, Selected = selectedUpgradeTab == UpgradeTab.Repairs };
@@ -285,9 +294,9 @@ namespace Barotrauma
*/
GUILayoutGroup rightLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout), childAnchor: Anchor.TopRight);
GUILayoutGroup priceLayout = new GUILayoutGroup(rectT(1, 0.8f, rightLayout), childAnchor: Anchor.Center) { RelativeSpacing = 0.08f };
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.Get("CampaignStore.Balance"), font: GUI.SubHeadingFont, textAlignment: Alignment.Right);
new GUITextBlock(rectT(1f, 0f, priceLayout), FormatCurrency(AvailableMoney, format: true), font: GUI.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => FormatCurrency(AvailableMoney, format: true) };
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.Get("CampaignStore.Balance"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.FormatCurrency(PlayerWallet.Balance), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => TextManager.FormatCurrency(PlayerWallet.Balance) };
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
repairButton.OnClicked = upgradeButton.OnClicked = (button, o) =>
{
@@ -343,15 +352,15 @@ namespace Barotrauma
private void DrawItemSwapPreview(SpriteBatch spriteBatch, GUICustomComponent component)
{
var selectedItem = customizeTabOpen ?
activeItemSwapSlideDown?.UserData as Item ?? HoveredItem as Item :
HoveredItem as Item;
activeItemSwapSlideDown?.UserData as Item ?? HoveredEntity as Item :
HoveredEntity as Item;
if (selectedItem?.Prefab.SwappableItem == null) { return; }
Sprite schematicsSprite = selectedItem.Prefab.SwappableItem.SchematicSprite;
if (schematicsSprite == null) { return; }
float schematicsScale = Math.Min(component.Rect.Width / 2 / schematicsSprite.size.X, component.Rect.Height / schematicsSprite.size.Y);
Vector2 center = new Vector2(component.Rect.Center.X, component.Rect.Center.Y);
schematicsSprite.Draw(spriteBatch, new Vector2(component.Rect.X, center.Y), GUI.Style.Green, new Vector2(0, schematicsSprite.size.Y / 2),
schematicsSprite.Draw(spriteBatch, new Vector2(component.Rect.X, center.Y), GUIStyle.Green, new Vector2(0, schematicsSprite.size.Y / 2),
scale: schematicsScale);
var swappableItemList = selectedUpgradeCategoryLayout?.FindChild("prefablist", true) as GUIListBox;
@@ -359,10 +368,10 @@ namespace Barotrauma
ItemPrefab swapTo = highlightedElement?.UserData as ItemPrefab ?? selectedItem.PendingItemSwap;
if (swapTo?.SwappableItem == null) { return; }
Sprite? schematicsSprite2 = swapTo.SwappableItem?.SchematicSprite;
schematicsSprite2?.Draw(spriteBatch, new Vector2(component.Rect.Right, center.Y), GUI.Style.Orange, new Vector2(schematicsSprite2.size.X, schematicsSprite2.size.Y / 2),
schematicsSprite2?.Draw(spriteBatch, new Vector2(component.Rect.Right, center.Y), GUIStyle.Orange, new Vector2(schematicsSprite2.size.X, schematicsSprite2.size.Y / 2),
scale: Math.Min(component.Rect.Width / 2 / schematicsSprite2.size.X, component.Rect.Height / schematicsSprite2.size.Y));
var arrowSprite = GUI.Style?.GetComponentStyle("GUIButtonToggleRight")?.GetDefaultSprite();
var arrowSprite = GUIStyle.GetComponentStyle("GUIButtonToggleRight")?.GetDefaultSprite();
if (arrowSprite != null)
{
arrowSprite.Draw(spriteBatch, center, scale: GUI.Scale);
@@ -426,14 +435,14 @@ namespace Barotrauma
return false;
}
if (AvailableMoney >= hullRepairCost)
if (PlayerWallet.CanAfford(hullRepairCost))
{
string body = TextManager.GetWithVariable("WallRepairs.PurchasePromptBody", "[amount]", hullRepairCost.ToString());
LocalizedString body = TextManager.GetWithVariable("WallRepairs.PurchasePromptBody", "[amount]", hullRepairCost.ToString());
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
{
if (AvailableMoney >= hullRepairCost)
if (PlayerWallet.Balance >= hullRepairCost)
{
Campaign.Money -= hullRepairCost;
PlayerWallet.TryDeduct(hullRepairCost);
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
Campaign.PurchasedHullRepairs = true;
button.Enabled = false;
@@ -461,14 +470,14 @@ namespace Barotrauma
CreateRepairEntry(currentStoreLayout.Content, TextManager.Get("repairallitems"), "RepairItemsButton", itemRepairCost, (button, o) =>
{
if (AvailableMoney >= itemRepairCost && !Campaign.PurchasedItemRepairs)
if (PlayerWallet.Balance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
{
string body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString());
LocalizedString body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString());
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
{
if (AvailableMoney >= itemRepairCost && !Campaign.PurchasedItemRepairs)
if (PlayerWallet.Balance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
{
Campaign.Money -= itemRepairCost;
PlayerWallet.TryDeduct(itemRepairCost);
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
Campaign.PurchasedItemRepairs = true;
button.Enabled = false;
@@ -493,7 +502,7 @@ namespace Barotrauma
{
foreach (var (item, itemFrame) in itemPreviews)
{
itemFrame.OutlineColor = itemFrame.Color = isHovered && item.GetComponent<DockingPort>() == null ? GUI.Style.Orange : previewWhite;
itemFrame.OutlineColor = itemFrame.Color = isHovered && item.GetComponent<DockingPort>() == null ? GUIStyle.Orange : previewWhite;
}
return true;
});
@@ -507,14 +516,14 @@ namespace Barotrauma
return false;
}
if (AvailableMoney >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
if (PlayerWallet.CanAfford(shuttleRetrieveCost) && !Campaign.PurchasedLostShuttles)
{
string body = TextManager.GetWithVariable("ReplaceLostShuttles.PurchasePromptBody", "[amount]", shuttleRetrieveCost.ToString());
LocalizedString body = TextManager.GetWithVariable("ReplaceLostShuttles.PurchasePromptBody", "[amount]", shuttleRetrieveCost.ToString());
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
{
if (AvailableMoney >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
if (PlayerWallet.Balance >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
{
Campaign.Money -= shuttleRetrieveCost;
PlayerWallet.TryDeduct(shuttleRetrieveCost);
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
Campaign.PurchasedLostShuttles = true;
button.Enabled = false;
@@ -540,7 +549,7 @@ namespace Barotrauma
{
if (subInfo.LeftBehindDockingPortIDs.Contains(item.ID))
{
itemFrame.OutlineColor = itemFrame.Color = subInfo.BlockedDockingPortIDs.Contains(item.ID) ? GUI.Style.Red : GUI.Style.Green;
itemFrame.OutlineColor = itemFrame.Color = subInfo.BlockedDockingPortIDs.Contains(item.ID) ? GUIStyle.Red : GUIStyle.Green;
}
else
{
@@ -551,7 +560,7 @@ namespace Barotrauma
}, disableElement: true);
}
private void CreateRepairEntry(GUIComponent parent, string title, string imageStyle, int price, GUIButton.OnClickedHandler onPressed, bool isDisabled, Func<bool, bool>? onHover = null, bool disableElement = false)
private void CreateRepairEntry(GUIComponent parent, LocalizedString title, string imageStyle, int price, GUIButton.OnClickedHandler onPressed, bool isDisabled, Func<bool, bool>? onHover = null, bool disableElement = false)
{
GUIFrame frameChild = new GUIFrame(rectT(new Point(parent.Rect.Width, (int) (96 * GUI.Scale)), parent), style: "UpgradeUIFrame");
frameChild.SelectedColor = frameChild.Color;
@@ -569,16 +578,16 @@ namespace Barotrauma
GUILayoutGroup contentLayout = new GUILayoutGroup(rectT(0.9f, 0.85f, frameChild, Anchor.Center), isHorizontal: true);
var repairIcon = new GUIFrame(rectT(new Point(contentLayout.Rect.Height, contentLayout.Rect.Height), contentLayout), style: imageStyle);
GUILayoutGroup textLayout = new GUILayoutGroup(rectT(0.8f - repairIcon.RectTransform.RelativeSize.X, 1, contentLayout)) { Stretch = true };
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUI.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
new GUITextBlock(rectT(1, 0, textLayout), FormatCurrency(price));
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUIStyle.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
new GUITextBlock(rectT(1, 0, textLayout), TextManager.FormatCurrency(price));
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = AvailableMoney >= price && !isDisabled, OnClicked = onPressed };
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = PlayerWallet.Balance >= price && !isDisabled, OnClicked = onPressed };
contentLayout.Recalculate();
buyButtonLayout.Recalculate();
if (disableElement)
{
frameChild.Enabled = AvailableMoney >= price && !isDisabled;
frameChild.Enabled = PlayerWallet.Balance >= price && !isDisabled;
}
if (!HasPermission)
@@ -610,9 +619,9 @@ namespace Barotrauma
Dictionary<UpgradeCategory, List<UpgradePrefab>> upgrades = new Dictionary<UpgradeCategory, List<UpgradePrefab>>();
foreach (UpgradeCategory category in UpgradeCategory.Categories)
foreach (UpgradeCategory category in UpgradeCategory.Categories.OrderBy(c => c.Name))
{
foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs)
foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs.OrderBy(p => p.Name))
{
if (prefab.UpgradeCategories.Contains(category))
{
@@ -661,7 +670,7 @@ namespace Barotrauma
* |-----------------------------|--------------------------|
*/
GUILayoutGroup contentLayout = new GUILayoutGroup(rectT(0.9f, 0.85f, frameChild, Anchor.Center));
var itemCategoryLabel = new GUITextBlock(rectT(1, 1, contentLayout), category.Name, font: GUI.SubHeadingFont) { CanBeFocused = false };
var itemCategoryLabel = new GUITextBlock(rectT(1, 1, contentLayout), category.Name, font: GUIStyle.SubHeadingFont) { CanBeFocused = false };
GUILayoutGroup indicatorLayout = new GUILayoutGroup(rectT(0.5f, 0.25f, contentLayout, Anchor.BottomRight), isHorizontal: true, childAnchor: Anchor.TopRight) { UserData = "indicators", IgnoreLayoutGroups = true, RelativeSpacing = 0.01f };
foreach (var prefab in prefabs)
@@ -742,7 +751,7 @@ namespace Barotrauma
GUIComponent[] categoryFrames = GetFrames(category);
foreach (GUIComponent itemFrame in itemPreviews.Values)
{
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUI.Style.Orange : previewWhite;
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUIStyle.Orange : previewWhite;
itemFrame.Children.ForEach(c => c.Color = itemFrame.Color);
}
@@ -790,7 +799,7 @@ namespace Barotrauma
GUIComponent[] categoryFrames = GetFrames(category);
foreach (GUIComponent itemFrame in itemPreviews.Values)
{
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUI.Style.Orange : previewWhite;
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUIStyle.Orange : previewWhite;
itemFrame.Children.ForEach(c => c.Color = itemFrame.Color);
}
return true;
@@ -851,8 +860,8 @@ namespace Barotrauma
if (linkedItems.Min(it => it.ID) < item.ID) { return; }
var currentOrPending = item.PendingItemSwap ?? item.Prefab;
string name = currentOrPending.Name;
string nameWithQuantity = "";
LocalizedString name = currentOrPending.Name;
LocalizedString nameWithQuantity = "";
if (linkedItems.Count > 1)
{
foreach (ItemPrefab distinctItem in linkedItems.Select(it => it.Prefab).Distinct())
@@ -881,7 +890,7 @@ namespace Barotrauma
};
GUILayoutGroup buttonLayout = new GUILayoutGroup(rectT(1f, 1f, toggleButton.Frame), isHorizontal: true);
string slotText = "";
LocalizedString slotText = "";
if (linkedItems.Count > 1)
{
slotText = TextManager.GetWithVariable("weaponslot", "[number]", string.Join(", ", linkedItems.Select(it => (swappableEntities.IndexOf(it) + 1).ToString())));
@@ -891,13 +900,13 @@ namespace Barotrauma
slotText = TextManager.GetWithVariable("weaponslot", "[number]", (swappableEntities.IndexOf(item) + 1).ToString());
}
new GUITextBlock(rectT(0.3f, 1f, buttonLayout), text: slotText, font: GUI.SubHeadingFont);
new GUITextBlock(rectT(0.3f, 1f, buttonLayout), text: slotText, font: GUIStyle.SubHeadingFont);
GUILayoutGroup group = new GUILayoutGroup(rectT(0.7f, 1f, buttonLayout), isHorizontal: true) { Stretch = true };
string title = item.PendingItemSwap != null ? TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", name) : nameWithQuantity;
GUITextBlock text = new GUITextBlock(rectT(0.7f, 1f, group), text: title, font: GUI.SubHeadingFont, textAlignment: Alignment.Right, parseRichText: true)
var title = item.PendingItemSwap != null ? TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", name) : nameWithQuantity;
GUITextBlock text = new GUITextBlock(rectT(0.7f, 1f, group), text: RichString.Rich(title), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right)
{
TextColor = GUI.Style.Orange
TextColor = GUIStyle.Orange
};
GUIImage arrowImage = new GUIImage(rectT(0.5f, 1f, group, scaleBasis: ScaleBasis.BothHeight), style: "SlideDownArrow", scaleToFit: true);
@@ -911,7 +920,7 @@ namespace Barotrauma
List<GUIFrame> frames = new List<GUIFrame>();
if (currentOrPending != null)
{
bool canUninstall = item.PendingItemSwap != null || !string.IsNullOrEmpty(currentOrPending.SwappableItem?.ReplacementOnUninstall);
bool canUninstall = item.PendingItemSwap != null || !(currentOrPending.SwappableItem?.ReplacementOnUninstall.IsEmpty ?? true);
bool isUninstallPending = item.Prefab.SwappableItem != null && item.PendingItemSwap?.Identifier == item.Prefab.SwappableItem.ReplacementOnUninstall;
if (isUninstallPending) { canUninstall = false; }
@@ -928,9 +937,7 @@ namespace Barotrauma
{
string textTag = item.PendingItemSwap != null ? "upgrades.cancelitemswappromptbody" : "upgrades.itemuninstallpromptbody";
if (isUninstallPending) { textTag = "upgrades.cancelitemuninstallpromptbody"; }
string promptBody = TextManager.GetWithVariables(textTag,
new[] { "[itemtouninstall]" },
new[] { isUninstallPending ? item.Name : currentOrPending.Name });
LocalizedString promptBody = TextManager.GetWithVariable(textTag, "[itemtouninstall]", isUninstallPending ? item.Name : currentOrPending.Name);
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("upgrades.refundprompttitle"), promptBody, () =>
{
if (GameMain.NetworkMember != null)
@@ -965,14 +972,14 @@ namespace Barotrauma
buttonStyle: isPurchased ? "WeaponInstallButton" : "StoreAddToCrateButton"));
if (!(frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton buyButton)) { continue; }
if (Campaign.Money >= price)
if (PlayerWallet.CanAfford(price))
{
buyButton.Enabled = true;
buyButton.OnClicked += (button, o) =>
{
string promptBody = TextManager.GetWithVariables(isPurchased ? "upgrades.itemswappromptbody" : "upgrades.purchaseitemswappromptbody",
new[] { "[itemtoinstall]", "[amount]" },
new[] { replacement.Name, (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count).ToString() });
LocalizedString promptBody = TextManager.GetWithVariables(isPurchased ? "upgrades.itemswappromptbody" : "upgrades.purchaseitemswappromptbody",
("[itemtoinstall]", replacement.Name),
("[amount]", (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count).ToString()));
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
{
if (GameMain.NetworkMember != null)
@@ -1019,7 +1026,7 @@ namespace Barotrauma
var linkedItems = Campaign.UpgradeManager.GetLinkedItemsToSwap(item);
foreach (var itemPreview in itemPreviews)
{
itemPreview.Value.OutlineColor = itemPreview.Value.Color = linkedItems.Contains(itemPreview.Key) ? GUI.Style.Orange : previewWhite;
itemPreview.Value.OutlineColor = itemPreview.Value.Color = linkedItems.Contains(itemPreview.Key) ? GUIStyle.Orange : previewWhite;
}
foreach (GUIComponent otherComponent in toggleButton.Parent.Children)
{
@@ -1041,7 +1048,7 @@ namespace Barotrauma
foreach (var itemPreview in itemPreviews)
{
if (currentStoreLayout?.SelectedData is CategoryData categoryData && !categoryData.Category.ItemTags.Any(t => itemPreview.Key.HasTag(t))) { continue; }
itemPreview.Value.OutlineColor = itemPreview.Value.Color = GUI.Style.Orange;
itemPreview.Value.OutlineColor = itemPreview.Value.Color = GUIStyle.Orange;
}
}
activeItemSwapSlideDown = toggleButton.Selected ? toggleButton : null;
@@ -1058,7 +1065,7 @@ namespace Barotrauma
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton, upgradePrefab: prefab, currentLevel: campaign.UpgradeManager.GetUpgradeLevel(prefab, category));
}
public static GUIFrame CreateUpgradeEntry(RectTransform parent, Sprite sprite, string title, string body, int price, object? userData, bool addBuyButton = true, bool addProgressBar = true, string buttonStyle = "UpgradeBuyButton", UpgradePrefab upgradePrefab = null, int currentLevel = 0)
public static GUIFrame CreateUpgradeEntry(RectTransform parent, Sprite sprite, LocalizedString title, LocalizedString body, int price, object? userData, bool addBuyButton = true, bool addProgressBar = true, string buttonStyle = "UpgradeBuyButton", UpgradePrefab? upgradePrefab = null, int currentLevel = 0)
{
float progressBarHeight = 0.25f;
@@ -1080,29 +1087,29 @@ namespace Barotrauma
GUILayoutGroup imageLayout = new GUILayoutGroup(rectT(new Point(prefabLayout.Rect.Height, prefabLayout.Rect.Height), prefabLayout), childAnchor: Anchor.Center);
var icon = new GUIImage(rectT(0.9f, 0.9f, imageLayout, scaleBasis: ScaleBasis.BothHeight), sprite, scaleToFit: true) { CanBeFocused = false };
GUILayoutGroup textLayout = new GUILayoutGroup(rectT(0.8f - imageLayout.RectTransform.RelativeSize.X, 1, prefabLayout));
var name = new GUITextBlock(rectT(1, 0.25f, textLayout), title, font: GUI.SubHeadingFont, parseRichText: true) { AutoScaleHorizontal = true, AutoScaleVertical = true, Padding = Vector4.Zero };
var name = new GUITextBlock(rectT(1, 0.25f, textLayout), RichString.Rich(title), font: GUIStyle.SubHeadingFont) { AutoScaleHorizontal = true, AutoScaleVertical = true, Padding = Vector4.Zero };
GUILayoutGroup descriptionLayout = new GUILayoutGroup(rectT(1, 0.75f - progressBarHeight, textLayout));
var description = new GUITextBlock(rectT(1, 1, descriptionLayout), body, font: GUI.SmallFont, wrap: true, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero };
var description = new GUITextBlock(rectT(1, 1, descriptionLayout), body, font: GUIStyle.SmallFont, wrap: true, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero };
GUILayoutGroup? progressLayout = null;
GUILayoutGroup? buyButtonLayout = null;
if (addProgressBar)
{
progressLayout = new GUILayoutGroup(rectT(1, 0.25f, textLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft) { UserData = "progressbar" };
new GUIProgressBar(rectT(0.8f, 0.75f, progressLayout), 0.0f, GUI.Style.Orange);
new GUITextBlock(rectT(0.2f, 1, progressLayout), string.Empty, font: GUI.SmallFont, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
new GUIProgressBar(rectT(0.8f, 0.75f, progressLayout), 0.0f, GUIStyle.Orange);
new GUITextBlock(rectT(0.2f, 1, progressLayout), string.Empty, font: GUIStyle.SmallFont, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
}
if (addBuyButton)
{
string formattedPrice = FormatCurrency(Math.Abs(price));
var formattedPrice = TextManager.FormatCurrency(Math.Abs(price));
//negative price = refund
if (price < 0) { formattedPrice = "+" + formattedPrice; }
buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
var priceText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), formattedPrice, textAlignment: Alignment.Center);
if (price < 0)
{
priceText.TextColor = GUI.Style.Green;
priceText.TextColor = GUIStyle.Green;
}
else if (price == 0)
{
@@ -1120,8 +1127,8 @@ namespace Barotrauma
// cut the description if it overflows and add a tooltip to it
for (int i = 100; i > 0 && description.Rect.Height > descriptionLayout.Rect.Height; i--)
{
string[] lines = description.WrappedText.Split('\n');
var newString = string.Join('\n', lines.Take(lines.Length - 1));
var lines = description.WrappedText.Split('\n');
var newString = string.Join('\n', lines.Take(lines.Count - 1));
if (0 >= newString.Length - 4) { break; }
description.Text = newString.Substring(0, newString.Length - 4) + "...";
@@ -1185,7 +1192,9 @@ namespace Barotrauma
buyButton.OnClicked += (button, o) =>
{
string promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody", new []{ "[upgradename]", "[amount]"}, new []{ prefab.Name, prefab.Price.GetBuyprice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation).ToString() });
LocalizedString promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody",
("[upgradename]", prefab.Name),
("[amount]", prefab.Price.GetBuyprice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation).ToString()));
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
{
if (GameMain.NetworkMember != null)
@@ -1225,7 +1234,7 @@ namespace Barotrauma
itemName.Text = entity is Item ? entity.Name : TextManager.Get("upgradecategory.walls");
if (slotIndex > -1)
{
itemName.Text = TextManager.GetWithVariables("weaponslotwithname", new string[] { "[number]", "[weaponname]" }, new string[] { slotIndex.ToString(), itemName.Text });
itemName.Text = TextManager.GetWithVariables("weaponslotwithname", ("[number]", slotIndex.ToString()), ("[weaponname]", itemName.Text));
}
upgradeList.Content.ClearChildren();
for (var i = 0; i < upgrades.Count && i < maxUpgrades; i++)
@@ -1246,7 +1255,7 @@ namespace Barotrauma
{
if (textBlock.UserData is Tuple<int, UpgradePrefab> tuple && tuple.Item2 == prefab)
{
string tooltip = CreateListEntry(tuple.Item2.Name, level + tuple.Item1);
var tooltip = CreateListEntry(tuple.Item2.Name, level + tuple.Item1);
textBlock.Text = tooltip;
found = true;
break;
@@ -1275,7 +1284,7 @@ namespace Barotrauma
moreIndicator.CalculateHeightFromText();
layout.Recalculate();
static string CreateListEntry(string name, int level) => TextManager.GetWithVariables("upgradeuitooltip.upgradelistelement", new[] { "[upgradename]", "[level]" }, new[] { name, $"{level}" });
static LocalizedString CreateListEntry(LocalizedString name, int level) => TextManager.GetWithVariables("upgradeuitooltip.upgradelistelement", ("[upgradename]", name), ("[level]", $"{level}"));
}
public static IEnumerable<UpgradeCategory> GetApplicableCategories(Submarine drawnSubmarine)
@@ -1294,7 +1303,9 @@ namespace Barotrauma
{
if (Campaign == null) { return; }
if (!parent.Children.Any() || Submarine.MainSub != null && Submarine.MainSub != drawnSubmarine || GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y)
if (!parent.Children.Any() ||
Submarine.MainSub != null && Submarine.MainSub != drawnSubmarine ||
GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y)
{
GameMain.GameSession?.SubmarineInfo?.CheckSubsLeftBehind();
drawnSubmarine = Submarine.MainSub;
@@ -1312,6 +1323,10 @@ namespace Barotrauma
// we also need this when we first load in so we know which category entries to disable since the CampaignUI is created before the submarine is loaded in.
RefreshAll();
}
if (needsRefresh)
{
RefreshAll();
}
// accept an active confirmation popup if any
if (PlayerInput.KeyHit(Keys.Enter) && GUIMessageBox.MessageBoxes.Any())
@@ -1334,16 +1349,16 @@ namespace Barotrauma
{
if (GUI.MouseOn == frame)
{
if (HoveredItem != item) { CreateItemTooltip(item); }
HoveredItem = item;
if (HoveredEntity != item) { CreateItemTooltip(item); }
HoveredEntity = item;
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradeTab == UpgradeTab.Upgrade && currentStoreLayout != null)
{
if (customizeTabOpen)
{
if (selectedUpgradeCategoryLayout != null)
{
var linkedItems = HoveredItem is Item ? Campaign.UpgradeManager.GetLinkedItemsToSwap((Item)HoveredItem) : new List<Item>();
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData as Item == HoveredItem || linkedItems.Contains(c.UserData as Item), recursive: true) is GUIButton itemElement)
var linkedItems = HoveredEntity is Item hoveredItem ? Campaign.UpgradeManager.GetLinkedItemsToSwap(hoveredItem) : new List<Item>();
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData is Item item && (item == HoveredEntity || linkedItems.Contains(item)), recursive: true) is GUIButton itemElement)
{
if (!itemElement.Selected) { itemElement.OnClicked(itemElement, itemElement.UserData); }
(itemElement.Parent?.Parent?.Parent as GUIListBox)?.ScrollToElement(itemElement);
@@ -1370,8 +1385,8 @@ namespace Barotrauma
// use pnpoly algorithm to detect if our mouse is within any of the hull polygons
if (subHullVertices.Any(hullVertex => ToolBox.PointIntersectsWithPolygon(PlayerInput.MousePosition, hullVertex)))
{
if (HoveredItem != firstStructure && !(firstStructure is null)) { CreateItemTooltip(firstStructure); }
HoveredItem = firstStructure;
if (HoveredEntity != firstStructure && !(firstStructure is null)) { CreateItemTooltip(firstStructure); }
HoveredEntity = firstStructure;
isMouseOnStructure = true;
GUI.MouseCursor = CursorState.Hand;
@@ -1382,7 +1397,7 @@ namespace Barotrauma
}
}
if (!isMouseOnStructure) { HoveredItem = null; }
if (!isMouseOnStructure) { HoveredEntity = null; }
}
// flip the tooltip if it is outside of the screen
@@ -1417,9 +1432,9 @@ namespace Barotrauma
*/
submarineInfoFrame = new GUILayoutGroup(rectT(0.25f, 0.2f, mainStoreLayout, Anchor.TopRight)) { IgnoreLayoutGroups = true };
// submarine name
new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.DisplayName, textAlignment: Alignment.Right, font: GUI.LargeFont);
new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.DisplayName, textAlignment: Alignment.Right, font: GUIStyle.LargeFont);
// submarine class
new GUITextBlock(rectT(1, 0, submarineInfoFrame), $"{TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}"))}", textAlignment: Alignment.Right, font: GUI.Font);
new GUITextBlock(rectT(1, 0, submarineInfoFrame), $"{TextManager.GetWithVariable("submarineclass.classsuffixformat", "[type]", TextManager.Get($"submarineclass.{submarine.Info.SubmarineClass}"))}", textAlignment: Alignment.Right, font: GUIStyle.Font);
var description = new GUITextBlock(rectT(1, 0, submarineInfoFrame), submarine.Info.Description, textAlignment: Alignment.Right, wrap: true);
submarineInfoFrame.RectTransform.ScreenSpaceOffset = new Point(0, (int)(16 * GUI.Scale));
@@ -1448,7 +1463,7 @@ namespace Barotrauma
Point size = new Point((int) (spriteSize * item.Scale / dockedBorders.Width * hullContainer.Rect.Width));
itemFrame = new GUIImage(rectT(size, component, Anchor.Center), icon, scaleToFit: true)
{
SelectedColor = GUI.Style.Orange,
SelectedColor = GUIStyle.Orange,
Color = previewWhite,
HoverCursor = CursorState.Hand,
SpriteEffects = item.Rotation > 90.0f && item.Rotation < 270.0f ? SpriteEffects.FlipVertically : SpriteEffects.None
@@ -1457,7 +1472,7 @@ namespace Barotrauma
{
new GUIImage(new RectTransform(new Vector2(0.8f), itemFrame.RectTransform, Anchor.TopLeft) { RelativeOffset = new Vector2(-0.2f) }, "WeaponSwitchIcon.DropShadow", scaleToFit: true)
{
SelectedColor = GUI.Style.Orange,
SelectedColor = GUIStyle.Orange,
Color = previewWhite,
CanBeFocused = false
};
@@ -1468,7 +1483,7 @@ namespace Barotrauma
Point size = new Point((int) (item.Rect.Width * item.Scale / dockedBorders.Width * hullContainer.Rect.Width), (int) (item.Rect.Height * item.Scale / dockedBorders.Height * hullContainer.Rect.Height));
itemFrame = new GUIFrame(rectT(size, component, Anchor.Center), style: "ScanLines")
{
SelectedColor = GUI.Style.Orange,
SelectedColor = GUIStyle.Orange,
OutlineColor = previewWhite,
Color = previewWhite,
OutlineThickness = 2,
@@ -1540,7 +1555,7 @@ namespace Barotrauma
// calculate the center point so we can draw a line from X to Y instead of drawing a rotated rectangle that is filled
Vector2 point1 = hullVertex[1] + (hullVertex[2] - hullVertex[1]) / 2;
Vector2 point2 = hullVertex[0] + (hullVertex[3] - hullVertex[0]) / 2;
GUI.DrawLine(spriteBatch, point1, point2, (highlightWalls ? GUI.Style.Orange * 0.6f : Color.DarkCyan * 0.3f), width: 10);
GUI.DrawLine(spriteBatch, point1, point2, (highlightWalls ? GUIStyle.Orange * 0.6f : Color.DarkCyan * 0.3f), width: 10);
if (GameMain.DebugDraw)
{
// the "collision box" is a bit bigger than the line we draw so this can be useful data (maybe)
@@ -1553,14 +1568,14 @@ namespace Barotrauma
{
int currentLevel = campaign.UpgradeManager.GetUpgradeLevel(prefab, category);
string progressText = TextManager.GetWithVariables("upgrades.progressformat", new[] { "[level]", "[maxlevel]" }, new[] { currentLevel.ToString(), prefab.MaxLevel.ToString() });
LocalizedString progressText = TextManager.GetWithVariables("upgrades.progressformat", ("[level]", currentLevel.ToString()), ("[maxlevel]", prefab.MaxLevel.ToString()));
if (prefabFrame.FindChild("progressbar", true) is { } progressParent)
{
GUIProgressBar bar = progressParent.GetChild<GUIProgressBar>();
if (bar != null)
{
bar.BarSize = currentLevel / (float) prefab.MaxLevel;
bar.Color = currentLevel >= prefab.MaxLevel ? GUI.Style.Green : GUI.Style.Orange;
bar.Color = currentLevel >= prefab.MaxLevel ? GUIStyle.Green : GUIStyle.Orange;
}
GUITextBlock block = progressParent.GetChild<GUITextBlock>();
@@ -1576,18 +1591,18 @@ namespace Barotrauma
if (priceLabel != null && !WaitForServerUpdate)
{
priceLabel.Text = FormatCurrency(price);
priceLabel.Text = TextManager.FormatCurrency(price);
if (currentLevel >= prefab.MaxLevel)
{
priceLabel.Text = TextManager.Get("Upgrade.MaxedUpgrade");
}
}
GUIButton button = buttonParent.GetChild<GUIButton>();
if (button != null)
{
button.Enabled = currentLevel < prefab.MaxLevel;
if (WaitForServerUpdate || !campaign.AllowedToManageCampaign() || price > campaign.Money)
if (WaitForServerUpdate || !campaign.Wallet.CanAfford(price))
{
button.Enabled = false;
}
@@ -1620,7 +1635,7 @@ namespace Barotrauma
else
{
parent.Enabled = false;
parent.SelectedColor = GUI.Style.Red * 0.5f;
parent.SelectedColor = GUIStyle.Red * 0.5f;
}
}
@@ -1632,12 +1647,12 @@ namespace Barotrauma
{
if (component.UserData != prefab) { continue; }
Dictionary<string, GUIComponentStyle> styles = GUI.Style.GetComponentStyle("upgradeindicator").ChildStyles;
Dictionary<Identifier, GUIComponentStyle> styles = GUIStyle.GetComponentStyle("upgradeindicator").ChildStyles;
if (!styles.ContainsKey("upgradeindicatoron") || !styles.ContainsKey("upgradeindicatordim") || !styles.ContainsKey("upgradeindicatoroff")) { continue; }
GUIComponentStyle onStyle = styles["upgradeindicatoron"];
GUIComponentStyle dimStyle = styles["upgradeindicatordim"];
GUIComponentStyle offStyle = styles["upgradeindicatoroff"];
GUIComponentStyle onStyle = styles["upgradeindicatoron".ToIdentifier()];
GUIComponentStyle dimStyle = styles["upgradeindicatordim".ToIdentifier()];
GUIComponentStyle offStyle = styles["upgradeindicatoroff".ToIdentifier()];
if (campaign.UpgradeManager.GetUpgradeLevel(prefab, category) >= prefab.MaxLevel)
{
@@ -1692,12 +1707,7 @@ namespace Barotrauma
return frames.ToArray();
}
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign();
public static string FormatCurrency(int money, bool format = true)
{
return TextManager.GetWithVariable("CurrencyFormat", "[credits]", format ? string.Format(CultureInfo.InvariantCulture, "{0:N0}", money) : money.ToString());
}
private bool HasPermission => true;
// just a shortcut to create new RectTransforms since all the new RectTransform and new Vector2 confuses my IDE (and me)
private static RectTransform rectT(float x, float y, GUIComponent parentComponent, Anchor anchor = Anchor.TopLeft, ScaleBasis scaleBasis = ScaleBasis.Normal)
@@ -34,23 +34,29 @@ namespace Barotrauma
public class TextSettings
{
public string Text;
public LocalizedString Text;
public int Width;
public TextSettings(Identifier textTag, int width)
{
Text = TextManager.GetFormatted(textTag);
Width = width;
}
public TextSettings(XElement element)
{
Text = TextManager.GetFormatted(element.GetAttributeString("text", string.Empty), true);
Text = TextManager.GetFormatted(element.GetAttributeIdentifier("text", Identifier.Empty));
Width = element.GetAttributeInt("width", 450);
}
}
public class VideoSettings
{
public string File;
public readonly string File;
public VideoSettings(XElement element)
public VideoSettings(string file)
{
File = element.GetAttributeString("file", string.Empty);
File = file;
}
}
@@ -75,13 +81,13 @@ namespace Barotrauma
}
videoView = new GUICustomComponent(new RectTransform(Point.Zero, videoFrame.RectTransform, Anchor.Center), (spriteBatch, guiCustomComponent) => { DrawVideo(spriteBatch, guiCustomComponent.Rect); });
title = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUI.LargeFont, textColor: new Color(253, 174, 0), textAlignment: Alignment.Left);
title = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUIStyle.LargeFont, textColor: new Color(253, 174, 0), textAlignment: Alignment.Left);
textContent = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUI.Font, textAlignment: Alignment.TopLeft);
textContent = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUIStyle.Font, textAlignment: Alignment.TopLeft);
objectiveTitle = new GUITextBlock(new RectTransform(new Vector2(1f, 0f), textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight, textColor: Color.White);
objectiveTitle = new GUITextBlock(new RectTransform(new Vector2(1f, 0f), textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterRight, textColor: Color.White);
objectiveTitle.Text = TextManager.Get("Tutorial.NewObjective");
objectiveText = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.SubHeadingFont, textColor: new Color(4, 180, 108), textAlignment: Alignment.CenterRight);
objectiveText = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUIStyle.SubHeadingFont, textColor: new Color(4, 180, 108), textAlignment: Alignment.CenterRight);
objectiveTitle.Visible = objectiveText.Visible = false;
}
@@ -120,7 +126,12 @@ namespace Barotrauma
background.AddToGUIUpdateList(ignoreChildren, order);
}
public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, string contentId, bool startPlayback, string objective = "", Action callback = null)
public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, Identifier contentId, bool startPlayback)
{
LoadContent(contentPath, videoSettings, textSettings, contentId, startPlayback, new RawLString(""), null);
}
public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, Identifier contentId, bool startPlayback, LocalizedString objective, Action callback = null)
{
callbackOnStop = callback;
filePath = contentPath + videoSettings.File;
@@ -183,10 +194,10 @@ namespace Barotrauma
title.RectTransform.NonScaledSize = new Point(scaledTextWidth, scaledTitleHeight);
title.RectTransform.AbsoluteOffset = new Point((int)(5 * GUI.Scale), (int)(10 * GUI.Scale));
if (textSettings != null && !string.IsNullOrEmpty(textSettings.Text))
if (textSettings != null && !textSettings.Text.IsNullOrEmpty())
{
textSettings.Text = ToolBox.WrapText(textSettings.Text, scaledTextWidth, GUI.Font);
int wrappedHeight = textSettings.Text.Split('\n').Length * scaledTextHeight;
textSettings.Text = ToolBox.WrapText(textSettings.Text, scaledTextWidth, GUIStyle.Font);
int wrappedHeight = textSettings.Text.Value.Split('\n').Length * scaledTextHeight;
textFrame.RectTransform.NonScaledSize = new Point(scaledTextWidth + scaledBorderSize, wrappedHeight + scaledBorderSize + scaledButtonSize.Y + scaledTitleHeight);
@@ -203,7 +214,7 @@ namespace Barotrauma
textContent.RectTransform.AbsoluteOffset = new Point(0, scaledBorderSize + scaledTitleHeight);
}
if (!string.IsNullOrEmpty(objectiveText.Text))
if (!objectiveText.Text.IsNullOrEmpty())
{
int scaledXOffset = (int)(-10 * GUI.Scale);
@@ -1,5 +1,5 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
@@ -19,32 +19,54 @@ namespace Barotrauma
private Func<int> getYesVotes, getNoVotes, getMaxVotes;
private bool votePassed;
private string votingOnText;
private List<RichTextData> votingOnTextData;
private RichString votingOnText;
private float votingTime = 100f;
private float timer;
private VoteType currentVoteType;
private Color submarineColor => GUI.Style.Orange;
private Color SubmarineColor => GUIStyle.Orange;
private Point createdForResolution;
public VotingInterface(Client starter, SubmarineInfo info, VoteType type, float votingTime)
public static VotingInterface CreateSubmarineVotingInterface(Client starter, SubmarineInfo info, VoteType type, float votingTime)
{
if (starter == null || info == null) return;
SetSubmarineVotingText(starter, info, type);
this.votingTime = votingTime;
getYesVotes = SubmarineYesVotes;
getNoVotes = SubmarineNoVotes;
getMaxVotes = SubmarineMaxVotes;
onVoteEnd = () => SendSubmarineVoteEndMessage(info, type);
if (starter == null || info == null) { return null; }
Initialize(starter, type);
var subVoting = new VotingInterface()
{
votingTime = votingTime,
getYesVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountYes(type) ?? 0,
getNoVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountNo(type) ?? 0,
getMaxVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountMax(type) ?? 0,
};
subVoting.onVoteEnd = () => subVoting.SendSubmarineVoteEndMessage(info, type);
subVoting.SetSubmarineVotingText(starter, info, type);
subVoting.Initialize(starter, type);
return subVoting;
}
public static VotingInterface CreateMoneyTransferVotingInterface(Client starter, Client from, Client to, int amount, float votingTime)
{
if (starter == null) { return null; }
if (from == null && to == null) { return null; }
var transferVoting = new VotingInterface()
{
votingTime = votingTime,
getYesVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountYes(VoteType.TransferMoney) ?? 0,
getNoVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountNo(VoteType.TransferMoney) ?? 0,
getMaxVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountMax(VoteType.TransferMoney) ?? 0,
};
transferVoting.onVoteEnd = () => transferVoting.SendMoneyTransferVoteEndMessage(from, to, amount);
transferVoting.SetMoneyTransferVotingText(starter, from, to, amount);
transferVoting.Initialize(starter, VoteType.TransferMoney);
return transferVoting;
}
private void Initialize(Client starter, VoteType type)
{
currentVoteType = type;
CreateVotingGUI();
if (starter.ID == GameMain.Client.ID) SetGUIToVotedState(2);
if (starter.ID == GameMain.Client.ID) { SetGUIToVotedState(2); }
VoteRunning = true;
}
@@ -52,7 +74,7 @@ namespace Barotrauma
{
createdForResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
if (frame != null) frame.Parent.RemoveChild(frame);
frame?.Parent.RemoveChild(frame);
frame = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.VotingArea, GameMain.Client.InGameHUD.RectTransform), style: "");
int padding = HUDLayoutSettings.Padding * 2;
@@ -60,14 +82,14 @@ namespace Barotrauma
int yOffset = padding;
int paddedWidth = frame.Rect.Width - padding * 2;
votingTextBlock = new GUITextBlock(new RectTransform(new Point(paddedWidth, 0), frame.RectTransform), votingOnTextData, votingOnText, wrap: true);
votingTextBlock = new GUITextBlock(new RectTransform(new Point(paddedWidth, 0), frame.RectTransform), votingOnText, wrap: true);
votingTextBlock.RectTransform.NonScaledSize = votingTextBlock.RectTransform.MinSize = votingTextBlock.RectTransform.MaxSize = new Point(votingTextBlock.Rect.Width, votingTextBlock.Rect.Height);
votingTextBlock.RectTransform.IsFixedSize = true;
votingTextBlock.RectTransform.AbsoluteOffset = new Point(padding, yOffset);
yOffset += votingTextBlock.Rect.Height + spacing;
voteCounter = new GUITextBlock(new RectTransform(new Point(paddedWidth, 0), frame.RectTransform), "(0/0)", GUI.Style.Green, textAlignment: Alignment.Center);
voteCounter = new GUITextBlock(new RectTransform(new Point(paddedWidth, 0), frame.RectTransform), "(0/0)", GUIStyle.Green, textAlignment: Alignment.Center);
voteCounter.RectTransform.NonScaledSize = voteCounter.RectTransform.MinSize = voteCounter.RectTransform.MaxSize = new Point(voteCounter.Rect.Width, voteCounter.Rect.Height);
voteCounter.RectTransform.IsFixedSize = true;
voteCounter.RectTransform.AbsoluteOffset = new Point(padding, yOffset);
@@ -118,8 +140,8 @@ namespace Barotrauma
public void Update(float deltaTime)
{
if (!VoteRunning) return;
if (GameMain.GraphicsWidth != createdForResolution.X || GameMain.GraphicsHeight != createdForResolution.Y) CreateVotingGUI();
if (!VoteRunning) { return; }
if (GameMain.GraphicsWidth != createdForResolution.X || GameMain.GraphicsHeight != createdForResolution.Y) { CreateVotingGUI(); }
yesVotes = getYesVotes();
noVotes = getNoVotes();
maxVotes = getMaxVotes();
@@ -128,7 +150,6 @@ namespace Barotrauma
votingTimer.BarSize = timer / votingTime;
}
public void EndVote(bool passed, int yesVoteFinal, int noVoteFinal)
{
VoteRunning = false;
@@ -145,75 +166,94 @@ namespace Barotrauma
JobPrefab prefab = starter?.Character?.Info?.Job?.Prefab;
Color nameColor = prefab != null ? prefab.UIColor : Color.White;
string characterRichString = $"‖color:{nameColor.R},{nameColor.G},{nameColor.B}‖{name}‖color:end‖";
string submarineRichString = $"‖color:{submarineColor.R},{submarineColor.G},{submarineColor.B}‖{info.DisplayName}‖color:end‖";
string submarineRichString = $"‖color:{SubmarineColor.R},{SubmarineColor.G},{SubmarineColor.B}‖{info.DisplayName}‖color:end‖";
LocalizedString text = string.Empty;
switch (type)
{
case VoteType.PurchaseAndSwitchSub:
votingOnText = TextManager.GetWithVariables("submarinepurchaseandswitchvote", new string[] { "[playername]", "[submarinename]", "[amount]", "[currencyname]" }, new string[] { characterRichString, submarineRichString, info.Price.ToString(), TextManager.Get("credit").ToLower() });
text = TextManager.GetWithVariables("submarinepurchaseandswitchvote",
("[playername]", characterRichString),
("[submarinename]", submarineRichString),
("[amount]", info.Price.ToString()),
("[currencyname]", TextManager.Get("credit").ToLower()));
break;
case VoteType.PurchaseSub:
votingOnText = TextManager.GetWithVariables("submarinepurchasevote", new string[] { "[playername]", "[submarinename]", "[amount]", "[currencyname]" }, new string[] { characterRichString, submarineRichString, info.Price.ToString(), TextManager.Get("credit").ToLower() });
text = TextManager.GetWithVariables("submarinepurchasevote",
("[playername]", characterRichString),
("[submarinename]", submarineRichString),
("[amount]", info.Price.ToString()),
("[currencyname]", TextManager.Get("credit").ToLower()));
break;
case VoteType.SwitchSub:
int deliveryFee = SubmarineSelection.DeliveryFeePerDistanceTravelled * GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation);
if (deliveryFee > 0)
{
votingOnText = TextManager.GetWithVariables("submarineswitchfeevote", new string[] { "[playername]", "[submarinename]", "[locationname]", "[amount]", "[currencyname]" }, new string[] { characterRichString, submarineRichString, endLocation.Name, deliveryFee.ToString(), TextManager.Get("credit").ToLower() });
text = TextManager.GetWithVariables("submarineswitchfeevote",
("[playername]", characterRichString),
("[submarinename]", submarineRichString),
("[locationname]", endLocation.Name),
("[amount]", deliveryFee.ToString()),
("[currencyname]", TextManager.Get("credit").ToLower()));
}
else
{
votingOnText = TextManager.GetWithVariables("submarineswitchnofeevote", new string[] { "[playername]", "[submarinename]" }, new string[] { characterRichString, submarineRichString });
text = TextManager.GetWithVariables("submarineswitchnofeevote",
("[playername]", characterRichString),
("[submarinename]", submarineRichString));
}
break;
}
votingOnTextData = RichTextData.GetRichTextData(votingOnText, out votingOnText);
}
private int SubmarineYesVotes()
{
return GameMain.NetworkMember.SubmarineVoteYesCount;
}
private int SubmarineNoVotes()
{
return GameMain.NetworkMember.SubmarineVoteNoCount;
}
private int SubmarineMaxVotes()
{
return GameMain.NetworkMember.SubmarineVoteMax;
votingOnText = RichString.Rich(text);
}
private void SendSubmarineVoteEndMessage(SubmarineInfo info, VoteType type)
{
GameMain.NetworkMember.AddChatMessage(GetSubmarineVoteResultMessage(info, type, yesVotes.ToString(), noVotes.ToString(), votePassed), ChatMessageType.Server);
GameMain.NetworkMember.AddChatMessage(GetSubmarineVoteResultMessage(info, type, yesVotes, noVotes, votePassed).Value, ChatMessageType.Server);
}
public static string GetSubmarineVoteResultMessage(SubmarineInfo info, VoteType type, string yesVoteString, string noVoteString, bool votePassed)
private LocalizedString GetSubmarineVoteResultMessage(SubmarineInfo info, VoteType type, int yesVoteCount, int noVoteCount, bool votePassed)
{
string result = string.Empty;
LocalizedString result = string.Empty;
switch (type)
{
case VoteType.PurchaseAndSwitchSub:
result = TextManager.GetWithVariables(votePassed ? "submarinepurchaseandswitchvotepassed" : "submarinepurchaseandswitchvotefailed", new string[] { "[submarinename]", "[amount]", "[currencyname]", "[yesvotecount]", "[novotecount]" }, new string[] { info.DisplayName, info.Price.ToString(), TextManager.Get("credit").ToLower(), yesVoteString, noVoteString });
result = TextManager.GetWithVariables(votePassed ? "submarinepurchaseandswitchvotepassed" : "submarinepurchaseandswitchvotefailed",
("[submarinename]", info.DisplayName),
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", info.Price)),
("[currencyname]", TextManager.Get("credit").ToLower()),
("[yesvotecount]", yesVoteCount.ToString()),
("[novotecount]" , noVoteCount.ToString()));
break;
case VoteType.PurchaseSub:
result = TextManager.GetWithVariables(votePassed ? "submarinepurchasevotepassed" : "submarinepurchasevotefailed", new string[] { "[submarinename]", "[amount]", "[currencyname]", "[yesvotecount]", "[novotecount]" }, new string[] { info.DisplayName, info.Price.ToString(), TextManager.Get("credit").ToLower(), yesVoteString, noVoteString });
result = TextManager.GetWithVariables(votePassed ? "submarinepurchasevotepassed" : "submarinepurchasevotefailed",
("[submarinename]", info.DisplayName),
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", info.Price)),
("[currencyname]", TextManager.Get("credit").ToLower()),
("[yesvotecount]", yesVoteCount.ToString()),
("[novotecount]", noVoteCount.ToString()));
break;
case VoteType.SwitchSub:
int deliveryFee = SubmarineSelection.DeliveryFeePerDistanceTravelled * GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation);
if (deliveryFee > 0)
{
result = TextManager.GetWithVariables(votePassed ? "submarineswitchfeevotepassed" : "submarineswitchfeevotefailed", new string[] { "[submarinename]", "[locationname]", "[amount]", "[currencyname]", "[yesvotecount]", "[novotecount]" }, new string[] { info.DisplayName, endLocation.Name, deliveryFee.ToString(), TextManager.Get("credit").ToLower(), yesVoteString, noVoteString });
result = TextManager.GetWithVariables(votePassed ? "submarineswitchfeevotepassed" : "submarineswitchfeevotefailed",
("[submarinename]", info.DisplayName),
("[locationname]", endLocation.Name),
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", deliveryFee)),
("[currencyname]", TextManager.Get("credit").ToLower()),
("[yesvotecount]", yesVoteCount.ToString()),
("[novotecount]", noVoteCount.ToString()));
}
else
{
result = TextManager.GetWithVariables(votePassed ? "submarineswitchnofeevotepassed" : "submarineswitchnofeevotefailed", new string[] { "[submarinename]", "[yesvotecount]", "[novotecount]" }, new string[] { info.DisplayName, yesVoteString, noVoteString });
result = TextManager.GetWithVariables(votePassed ? "submarineswitchnofeevotepassed" : "submarineswitchnofeevotefailed",
("[submarinename]", info.DisplayName),
("[yesvotecount]", yesVoteCount.ToString()),
("[novotecount]", noVoteCount.ToString()));
}
break;
default:
@@ -223,6 +263,58 @@ namespace Barotrauma
}
#endregion
private void SetMoneyTransferVotingText(Client starter, Client from, Client to, int amount)
{
string name = starter.Name;
JobPrefab prefab = starter?.Character?.Info?.Job?.Prefab;
Color nameColor = prefab != null ? prefab.UIColor : Color.White;
string characterRichString = $"‖color:{nameColor.R},{nameColor.G},{nameColor.B}‖{name}‖color:end‖";
LocalizedString text = string.Empty;
if (from == null && to != null)
{
text = TextManager.GetWithVariables("crewwallet.requestbanktoselfvote",
("[requester]", characterRichString),
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", amount)));
}
else if (from != null && to == null)
{
text = TextManager.GetWithVariables("crewwallet.requestselftobankvote",
("[requester]", characterRichString),
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", amount)));
}
else
{
//not supported atm: clients can only requests transfers between their own wallet and the bank
LocalizedString bankName = TextManager.Get("crewwallet.bank");
text = TextManager.GetWithVariables("crewwallet.requesttransfervote",
("[requester]", characterRichString),
("[player1]", from?.Character == null ? bankName : from.Character.Name),
("[player2]", to?.Character == null ? bankName : to.Character.Name),
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", amount)));
}
votingOnText = RichString.Rich(text);
}
private void SendMoneyTransferVoteEndMessage(Client from, Client to, int amount)
{
GameMain.NetworkMember.AddChatMessage(GetMoneyTransferVoteResultMessage(from, to, amount, yesVotes, noVotes, votePassed).Value, ChatMessageType.Server);
}
public static LocalizedString GetMoneyTransferVoteResultMessage(Client from, Client to, int transferAmount, int yesVoteCount, int noVoteCount, bool votePassed)
{
LocalizedString result = string.Empty;
if (from == null && to != null)
{
result = TextManager.GetWithVariables(votePassed ? "crewwallet.banktoplayer.votepassed" : "crewwallet.banktoplayer.votefailed",
("[playername]", to.Name),
("[amount]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", transferAmount)),
("[yesvotecount]", yesVoteCount.ToString()),
("[novotecount]", noVoteCount.ToString()));
}
return result;
}
public void Remove()
{
if (frame != null)
@@ -17,7 +17,7 @@ namespace Barotrauma
}
public Shape shape;
public string tooltip;
public LocalizedString tooltip;
public bool showTooltip = true;
public Rectangle DrawRect => new Rectangle((int)(DrawPos.X - (float)size / 2), (int)(DrawPos.Y - (float)size / 2), size, size);
public Rectangle InputRect
@@ -42,7 +42,7 @@ namespace Barotrauma
/// </summary>
public bool isFilled;
public int inputAreaMargin;
public Color color = GUI.Style.Red;
public Color color = GUIStyle.Red;
public Color? secondaryColor;
public Color textColor = Color.White;
public Color textBackgroundColor = Color.Black * 0.5f;
@@ -183,7 +183,7 @@ namespace Barotrauma
}
if (IsSelected)
{
if (showTooltip && !string.IsNullOrEmpty(tooltip))
if (showTooltip && !tooltip.IsNullOrEmpty())
{
var offset = tooltipOffset ?? new Vector2(size, -size / 2f);
GUI.DrawString(spriteBatch, DrawPos + offset, tooltip, textColor, textBackgroundColor);