v1.4.4.1 (Blood in the Water Update)

This commit is contained in:
Regalis11
2024-04-24 18:09:05 +03:00
parent 89b91d1c3e
commit ff1b8951a7
397 changed files with 15250 additions and 6479 deletions
@@ -128,6 +128,11 @@ namespace Barotrauma
{
case "sprite":
UISprite newSprite = new UISprite(subElement);
Rectangle sourceRect = newSprite.Sprite.SourceRect;
if ((sourceRect.Width <= 1 || sourceRect.Height <= 1) && newSprite.Tile)
{
DebugConsole.AddWarning($"Sprite \"{subElement.GetAttributeString("name", Name)}\" has a size of 1 or less which may cause performance problems.", contentPackage: element.ContentPackage);
}
GUIComponent.ComponentState spriteState = GUIComponent.ComponentState.None;
if (subElement.GetAttribute("state") != null)
@@ -187,7 +187,16 @@ namespace Barotrauma
Spacing = 1
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaignmenucrew"), font: GUIStyle.SubHeadingFont);
var crewHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, height), pendingAndCrewGroup.RectTransform), TextManager.Get("campaignmenucrew"), font: GUIStyle.SubHeadingFont);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), crewHeader.RectTransform, Anchor.CenterRight), string.Empty, textAlignment: Alignment.CenterRight)
{
TextGetter = () =>
{
int crewSize = campaign?.CrewManager?.GetCharacterInfos()?.Count() ?? 0;
return $"{crewSize}/{CrewManager.MaxCrewSize}";
}
};
crewList = new GUIListBox(new RectTransform(new Vector2(1.0f, 8 * height), pendingAndCrewGroup.RectTransform))
{
Spacing = 1
@@ -207,7 +216,7 @@ namespace Barotrauma
{
ClickSound = GUISoundType.ConfirmTransaction,
ForceUpperCase = ForceUpperCase.Yes,
OnClicked = (b, o) => ValidateHires(PendingHires, true)
OnClicked = (b, o) => ValidateHires(PendingHires, createNetworkEvent: true)
};
clearAllButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall"))
{
@@ -647,7 +656,7 @@ namespace Barotrauma
private bool AddPendingHire(CharacterInfo characterInfo, bool createNetworkMessage = true)
{
if (PendingHires.Count + campaign.CrewManager.GetCharacters().Count() >= CrewManager.MaxCrewSize)
if (PendingHires.Count + campaign.CrewManager.GetCharacterInfos().Count() >= CrewManager.MaxCrewSize)
{
return false;
}
@@ -703,7 +712,7 @@ namespace Barotrauma
validateHiresButton.Enabled = enoughMoney && HasPermission && pendingList.Content.RectTransform.Children.Any();
}
public bool ValidateHires(List<CharacterInfo> hires, bool createNetworkEvent = false)
public bool ValidateHires(List<CharacterInfo> hires, bool takeMoney = true, bool createNetworkEvent = false)
{
if (hires == null || hires.None()) { return false; }
@@ -718,14 +727,16 @@ namespace Barotrauma
if (nonDuplicateHires.None()) { return false; }
int total = HireManager.GetSalaryFor(nonDuplicateHires);
if (!campaign.CanAfford(total)) { return false; }
if (takeMoney)
{
int total = HireManager.GetSalaryFor(nonDuplicateHires);
if (!campaign.CanAfford(total)) { return false; }
}
bool atLeastOneHired = false;
foreach (CharacterInfo ci in nonDuplicateHires)
{
if (campaign.TryHireCharacter(campaign.Map.CurrentLocation, ci, Character.Controlled))
if (campaign.TryHireCharacter(campaign.Map.CurrentLocation, ci, takeMoney: takeMoney))
{
atLeastOneHired = true;
}
@@ -951,8 +962,8 @@ namespace Barotrauma
CharacterInfo match = location.HireManager.AvailableCharacters.Find(info => info.GetIdentifierUsingOriginalName() == identifier);
if (match != null)
{
PendingHires.Add(match);
AddPendingHire(match, createNetworkMessage: false);
System.Diagnostics.Debug.Assert(PendingHires.Contains(match));
}
else
{
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Barotrauma.IO;
@@ -641,19 +641,9 @@ namespace Barotrauma
sprite?.Draw(spriteBatch, PlayerInput.MousePosition, scale: Math.Min(64 / sprite.size.X, 64 / sprite.size.Y) * Scale);
break;
}
case ItemAssemblyPrefab iPrefab:
case ItemAssemblyPrefab itemAssemblyPrefab:
{
var (x, y) = PlayerInput.MousePosition;
foreach (var pair in iPrefab.DisplayEntities)
{
Rectangle dRect = pair.Item2;
dRect = new Rectangle(x: (int)(dRect.X * iPrefab.Scale + x),
y: (int)(dRect.Y * iPrefab.Scale - y),
width: (int)(dRect.Width * iPrefab.Scale),
height: (int)(dRect.Height * iPrefab.Scale));
MapEntityPrefab prefab = MapEntityPrefab.Find("", pair.Item1);
prefab.DrawPlacing(spriteBatch, dRect, prefab.Scale * iPrefab.Scale);
}
itemAssemblyPrefab.Draw(spriteBatch, PlayerInput.MousePosition.FlipY());
break;
}
}
@@ -716,7 +706,7 @@ namespace Barotrauma
spriteBatch.Draw(backgroundSprite.Texture,
area.Center.ToVector2() + pos,
null, color, 0.0f, backgroundSprite.size / 2,
backgroundSprite.SourceRect, color, 0.0f, backgroundSprite.size / 2,
scale, spriteEffects, 0.0f);
}
@@ -1050,12 +1040,31 @@ namespace Barotrauma
{
return dragHandle.Dragging ? CursorState.Dragging : CursorState.Hand;
}
//do not show the hover cursor when the cursor is on a listbox (on the listbox itself, not any of elements inside it!)
if (c is GUIListBox && (parent == null || parent == c))
{
return CursorState.Default;
}
// Some parent elements take priority
// but not when the child is a GUIButton or GUITickBox
if (!(parent is GUIButton) && !(parent is GUIListBox) ||
if (parent is not GUIButton && parent is not GUIListBox ||
(c is GUIButton) || (c is GUITickBox))
{
if (!c.Rect.Equals(monitorRect)) { return c.HoverCursor; }
if (!c.Rect.Equals(monitorRect))
{
if (c is GUITickBox)
{
//tickboxes have some special logic: not all of the component is hoverable (just the box and the text area)
if (c.State is GUIComponent.ComponentState.Hover or GUIComponent.ComponentState.HoverSelected)
{
return c.HoverCursor;
}
}
else
{
return c.HoverCursor;
}
}
}
}
@@ -2399,30 +2408,31 @@ namespace Barotrauma
}
iterations++;
}
static Vector2 ClampMoveAmount(Rectangle Rect, Rectangle clampTo, Vector2 moveAmount)
{
if (Rect.Y < clampTo.Y)
{
moveAmount.Y = Math.Max(moveAmount.Y, 0.0f);
}
else if (Rect.Bottom > clampTo.Bottom)
{
moveAmount.Y = Math.Min(moveAmount.Y, 0.0f);
}
if (Rect.X < clampTo.X)
{
moveAmount.X = Math.Max(moveAmount.X, 0.0f);
}
else if (Rect.Right > clampTo.Right)
{
moveAmount.X = Math.Min(moveAmount.X, 0.0f);
}
return moveAmount;
}
}
#endregion
private static Vector2 ClampMoveAmount(Rectangle rect, Rectangle clampTo, Vector2 moveAmount)
{
if (rect.Y < clampTo.Y)
{
moveAmount.Y = Math.Max(moveAmount.Y, 0.0f);
}
else if (rect.Bottom > clampTo.Bottom)
{
moveAmount.Y = Math.Min(moveAmount.Y, 0.0f);
}
if (rect.X < clampTo.X)
{
moveAmount.X = Math.Max(moveAmount.X, 0.0f);
}
else if (rect.Right > clampTo.Right)
{
moveAmount.X = Math.Min(moveAmount.X, 0.0f);
}
return moveAmount;
}
#endregion
#region Misc
public static void TogglePauseMenu()
@@ -2477,7 +2487,7 @@ namespace Barotrauma
GameMain.GameSession.LoadPreviousSave();
});
if (IsFriendlyOutpostLevel())
if (IsFriendlyOutpostLevel() && !spMode.CrewDead)
{
CreateButton("PauseMenuSaveQuit", buttonContainer, verificationTextTag: "PauseMenuSaveAndReturnToMainMenuVerification", action: () =>
{
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using System.Linq;
@@ -734,7 +734,7 @@ namespace Barotrauma
DrawToolTip(spriteBatch, ToolTip, Rect);
}
public static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Vector2 pos)
public static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Vector2 pos, Color? textColor = null, Color? backgroundColor = null)
{
if (ObjectiveManager.ContentRunning) { return; }
@@ -745,6 +745,8 @@ namespace Barotrauma
if (toolTipBlock == null || (RichString)toolTipBlock.UserData != toolTip)
{
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), toolTip, font: GUIStyle.SmallFont, wrap: true, style: "GUIToolTip");
if (textColor != null) { toolTipBlock.TextColor = textColor.Value; }
if (backgroundColor != null) { toolTipBlock.Color = backgroundColor.Value; }
toolTipBlock.RectTransform.NonScaledSize = new Point(
(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));
@@ -754,6 +756,15 @@ namespace Barotrauma
toolTipBlock.RectTransform.AbsoluteOffset = pos.ToPoint();
toolTipBlock.SetTextPos();
if (toolTipBlock.Rect.Right > GameMain.GraphicsWidth - 10)
{
toolTipBlock.RectTransform.AbsoluteOffset -= new Point(toolTipBlock.Rect.Width,0);
}
if (toolTipBlock.Rect.Bottom > GameMain.GraphicsHeight - 10)
{
toolTipBlock.RectTransform.AbsoluteOffset -= new Point(0, toolTipBlock.Rect.Height);
}
toolTipBlock.DrawManually(spriteBatch);
}
@@ -982,6 +993,24 @@ namespace Barotrauma
}
}
/// <summary>
/// Sets the minimum height of the transfrom to equal to the sum of the minimum heights of the children
/// (i.e. makes the element at least large enough to fit all the children vertically)
/// </summary>
public void InheritTotalChildrenMinHeight()
{
RectTransform.InheritTotalChildrenMinHeight();
}
/// <summary>
/// Sets the minimum height of the transfrom to equal to the sum of the heights of the children
/// (i.e. makes the element at least large enough to fit all the children vertically)
/// </summary>
public void InheritTotalChildrenHeight()
{
RectTransform.InheritTotalChildrenHeight();
}
public static GUIComponent FromXML(ContentXElement element, RectTransform parent)
{
GUIComponent component = null;
@@ -15,20 +15,73 @@ namespace Barotrauma
public GUITextBox TextBox { get; private set; }
public override RichString ToolTip
{
get
{
return base.ToolTip;
}
set
{
base.ToolTip = value;
TextBox.ToolTip = value;
}
}
public GUIButton PlusButton { get; private set; }
public GUIButton MinusButton { get; private set; }
public enum ButtonVisibility { Automatic, Manual, ForceVisible, ForceHidden }
private ButtonVisibility _plusMinusButtonVisibility;
/// <summary>
/// Whether or not the default +- buttons should be shown. Defaults to Automatic,
/// which enables it for all integers and for those floats that have a defined
/// range, because for these it is implicitly more obvious how to increment them.
/// </summary>
public ButtonVisibility PlusMinusButtonVisibility
{
get { return _plusMinusButtonVisibility; }
set
{
if (_plusMinusButtonVisibility != value)
{
_plusMinusButtonVisibility = value;
UpdatePlusMinusButtonVisibility();
}
}
}
private void UpdatePlusMinusButtonVisibility()
{
if (ForceShowPlusMinusButtons
|| inputType == NumberType.Int
|| (inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue))
switch (PlusMinusButtonVisibility)
{
ShowPlusMinusButtons();
}
else
{
HidePlusMinusButtons();
case ButtonVisibility.ForceHidden:
{
HidePlusMinusButtons();
break;
}
case ButtonVisibility.ForceVisible:
{
ShowPlusMinusButtons();
break;
}
case ButtonVisibility.Automatic:
{
if (inputType == NumberType.Int
|| (inputType == NumberType.Float
&& MinValueFloat > float.MinValue
&& MaxValueFloat < float.MaxValue))
{
ShowPlusMinusButtons();
}
else
{
HidePlusMinusButtons();
}
break;
}
case ButtonVisibility.Manual:
return;
}
}
@@ -86,19 +139,6 @@ namespace Barotrauma
}
}
private bool forceShowPlusMinusButtons;
public bool ForceShowPlusMinusButtons
{
get { return forceShowPlusMinusButtons; }
set
{
if (forceShowPlusMinusButtons == value) { return; }
forceShowPlusMinusButtons = value;
UpdatePlusMinusButtonVisibility();
}
}
private int decimalsToDisplay = 1;
public int DecimalsToDisplay
{
@@ -162,6 +202,17 @@ namespace Barotrauma
}
}
}
public bool Readonly
{
get { return TextBox.Readonly; }
set
{
TextBox.Readonly = value;
PlusButton.Enabled = !value;
MinusButton.Enabled = !value;
}
}
public override GUIFont Font
{
@@ -189,11 +240,19 @@ namespace Barotrauma
public float ValueStep;
// Enable holding to scroll through values faster
private float pressedTimer;
private readonly float pressedDelay = 0.5f;
private bool IsPressedTimerRunning { get { return pressedTimer > 0; } }
public GUINumberInput(RectTransform rectT, NumberType inputType, string style = "", Alignment textAlignment = Alignment.Center, float? relativeButtonAreaWidth = null, bool hidePlusMinusButtons = false) : base(style, rectT)
public GUINumberInput(
RectTransform rectT,
NumberType inputType,
string style = "",
Alignment textAlignment = Alignment.Center,
float? relativeButtonAreaWidth = null,
ButtonVisibility buttonVisibility = ButtonVisibility.Automatic,
(GUIButton PlusButton, GUIButton MinusButton)? customPlusMinusButtons = null) : base(style, rectT)
{
LayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
@@ -233,9 +292,23 @@ namespace Barotrauma
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);
GUIStyle.Apply(PlusButton, "PlusButton", this);
if (customPlusMinusButtons.HasValue)
{
PlusButton = customPlusMinusButtons.Value.PlusButton;
MinusButton = customPlusMinusButtons.Value.MinusButton;
}
else // generate the default +- buttons
{
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);
GUIStyle.Apply(PlusButton, "PlusButton", this);
MinusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), style: null);
GUIStyle.Apply(MinusButton, "MinusButton", this);
}
// Set up default and custom +- buttons the same way to ensure uniform functionality
PlusButton.ClickSound = GUISoundType.Increase;
PlusButton.OnButtonDown += () =>
{
@@ -255,9 +328,6 @@ namespace Barotrauma
}
return true;
};
MinusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), style: null);
GUIStyle.Apply(MinusButton, "MinusButton", this);
MinusButton.ClickSound = GUISoundType.Decrease;
MinusButton.OnButtonDown += () =>
{
@@ -278,10 +348,7 @@ namespace Barotrauma
return true;
};
if (inputType != NumberType.Int || hidePlusMinusButtons)
{
HidePlusMinusButtons();
}
PlusMinusButtonVisibility = buttonVisibility;
if (inputType == NumberType.Int)
{
@@ -324,16 +391,16 @@ namespace Barotrauma
private void HidePlusMinusButtons()
{
PlusButton.Parent.Visible = false;
PlusButton.Parent.IgnoreLayoutGroups = true;
PlusButton.Parent.Visible = MinusButton.Parent.Visible = false;
PlusButton.Parent.IgnoreLayoutGroups = MinusButton.Parent.IgnoreLayoutGroups = true;
TextBox.RectTransform.RelativeSize = Vector2.One;
LayoutGroup.Recalculate();
}
private void ShowPlusMinusButtons()
{
PlusButton.Parent.Visible = true;
PlusButton.Parent.IgnoreLayoutGroups = false;
PlusButton.Parent.Visible = MinusButton.Parent.Visible = true;
PlusButton.Parent.IgnoreLayoutGroups = MinusButton.Parent.IgnoreLayoutGroups = false;
TextBox.RectTransform.RelativeSize = new Vector2(1.0f - PlusButton.Parent.RectTransform.RelativeSize.X, 1.0f);
LayoutGroup.Recalculate();
}
@@ -427,6 +494,11 @@ namespace Barotrauma
Math.Min(floatValue, MaxValueFloat.Value);
PlusButton.Enabled = WrapAround || floatValue < MaxValueFloat;
}
if (Readonly)
{
PlusButton.Enabled = MinusButton.Enabled = false;
}
}
private void ClampIntValue()
@@ -441,8 +513,16 @@ namespace Barotrauma
intValue = WrapAround && MinValueInt.HasValue ? MinValueInt.Value : Math.Min(intValue, MaxValueInt.Value);
UpdateText();
}
PlusButton.Enabled = WrapAround || MaxValueInt == null || intValue < MaxValueInt;
MinusButton.Enabled = WrapAround || MinValueInt == null || intValue > MinValueInt;
if (Readonly)
{
PlusButton.Enabled = MinusButton.Enabled = false;
}
else
{
PlusButton.Enabled = WrapAround || MaxValueInt == null || intValue < MaxValueInt;
MinusButton.Enabled = WrapAround || MinValueInt == null || intValue > MinValueInt;
}
}
private void UpdateText()
@@ -135,7 +135,8 @@ namespace Barotrauma
if (subElement.NameAsIdentifier() != "override") { continue; }
if (ScalableFont.ExtractShccFromXElement(subElement).HasFlag(flag))
{
return new ScalableFont(subElement, font?.Size ?? 14, GameMain.Instance.GraphicsDevice);
uint overrideFontSize = GetFontSize(subElement, defaultSize: font?.Size ?? 14);
return new ScalableFont(subElement, overrideFontSize, GameMain.Instance.GraphicsDevice);
}
}
@@ -380,6 +381,11 @@ namespace Barotrauma
public static implicit operator UISprite?(GUISprite reference) => reference.Value;
public void Draw(SpriteBatch spriteBatch, RectangleF rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None)
{
Value?.Draw(spriteBatch, rect, color, spriteEffects);
}
public void Draw(SpriteBatch spriteBatch, Rectangle rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None)
{
Value?.Draw(spriteBatch, rect, color, spriteEffects);
@@ -214,7 +214,7 @@ namespace Barotrauma
Bar.HoverCursor = CursorState.Default;
break;
case "GUISlider":
HoverCursor = CursorState.Default;
HoverCursor = CursorState.Hand;
Bar.HoverCursor = CursorState.Hand;
break;
default:
@@ -0,0 +1,191 @@
#nullable enable
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
/// <summary>
/// Allows accessing the element selected in the carousel in contexts where the type of T isn't known.
/// Pretty hacky, but I could not think of a better way to do this (<see cref="Networking.ServerSettings.NetPropertyData"/> in which this is used).
/// </summary>
public interface IGUISelectionCarouselAccessor
{
object? GetSelectedElement();
void SelectElement(object? value);
}
/// <summary>
/// An UI element that allows toggling through a set of options with buttons to the left and right
/// </summary>
public class GUISelectionCarousel<T> : GUIComponent, IGUISelectionCarouselAccessor
{
public record class Element(T value, LocalizedString text, LocalizedString toolTip);
public delegate void OnValueChangedHandler(GUISelectionCarousel<T> carousel);
public OnValueChangedHandler? OnValueChanged;
public GUITextBlock TextBlock { get; private set; }
public GUIButton RightButton { get; private set; }
public GUIButton LeftButton { get; private set; }
private readonly List<Element> elements = new List<Element>();
private readonly GUILayoutGroup layoutGroup;
public Element? SelectedElement { get; private set; }
public T? SelectedValue => SelectedElement == null ? default : SelectedElement.value;
public LocalizedString SelectedText => SelectedElement?.text ?? string.Empty;
public override bool Enabled
{
get => base.Enabled;
set
{
base.Enabled = RightButton.Enabled = LeftButton.Enabled = TextBlock.Enabled = value;
}
}
public override Color Color
{
get { return color; }
set
{
color = value;
TextBlock.Color = color;
}
}
public Color TextColor
{
get { return TextBlock.TextColor; }
set { TextBlock.TextColor = value; }
}
public override Color HoverColor
{
get => base.HoverColor;
set
{
base.HoverColor = value;
TextBlock.HoverColor = value;
}
}
public GUISelectionCarousel(RectTransform rectT, string style = "", params (T value, LocalizedString text)[] newElements) : base(style, rectT)
{
layoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
RelativeSpacing = 0.05f,
Stretch = true
};
LeftButton = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), layoutGroup.RectTransform), style: "GUIButtonToggleLeft");
GUIStyle.Apply(LeftButton, "LeftButton", this);
TextBlock = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), layoutGroup.RectTransform), "", textAlignment: Alignment.Center, style: "GUITextBox");
GUIStyle.Apply(TextBlock, "TextBlock", this);
RightButton = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), layoutGroup.RectTransform), style: "GUIButtonToggleRight");
GUIStyle.Apply(RightButton, "RightButton", this);
RightButton.OnClicked += (btn, userData) =>
{
if (elements.Count < 2) { return false; }
if (SelectedElement == null)
{
SelectElement(elements.First());
}
else
{
int newIndex = (elements.IndexOf(SelectedElement) + 1) % elements.Count;
SelectElement(elements[newIndex]);
}
return true;
};
LeftButton.OnClicked += (btn, userData) =>
{
if (elements.Count < 2) { return false; }
if (SelectedElement == null)
{
SelectElement(elements.First());
}
else
{
int newIndex = MathUtils.PositiveModulo((elements.IndexOf(SelectedElement) - 1), elements.Count);
SelectElement(elements[newIndex]);
}
return true;
};
if (newElements != null && newElements.Any())
{
SetElements(newElements);
}
}
public object? GetSelectedElement()
{
return SelectedValue;
}
/// <summary>
/// Select the element whose value matches the specified value. If null, deselects the currently selected element.
/// </summary>
public void SelectElement(object? value)
{
if (value == null)
{
SelectElement(null);
return;
}
if (elements.FirstOrDefault(e => value.Equals(e.value)) is { } element)
{
SelectElement(element);
}
}
public void SelectElement(Element? element)
{
SelectedElement = element;
TextBlock.Text = element?.text ?? string.Empty;
TextBlock.ToolTip = element?.toolTip ?? string.Empty;
OnValueChanged?.Invoke(this);
}
/// <summary>
/// Clears all existing elements from the carousels and adds the specified new elements to it
/// </summary>
public void SetElements(params (T value, LocalizedString text)[] elements)
{
this.elements.Clear();
foreach ((T value, LocalizedString text) in elements)
{
AddElement(value, text);
}
}
/// <summary>
/// Clears all existing elements from the carousels and adds the specified new elements to it
/// </summary>
public void SetElements(params (T value, LocalizedString text, LocalizedString toolTip)[] elements)
{
this.elements.Clear();
foreach ((T value, LocalizedString text, LocalizedString toolTip) in elements)
{
AddElement(value, text, toolTip);
}
}
public void AddElement(T value, LocalizedString text, LocalizedString? tooltip = null)
{
var newElement = new Element(value, text, tooltip ?? string.Empty);
elements.Add(newElement);
if (SelectedElement == null)
{
SelectElement(newElement);
}
}
}
}
@@ -1,6 +1,6 @@
using System;
using Barotrauma.Extensions;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
@@ -47,6 +47,8 @@ namespace Barotrauma
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 SpeechBubbleIconSliced = new GUISprite("SpeechBubbleIconSliced");
public readonly static GUISprite InteractionLabelBackground = new GUISprite("InteractionLabelBackground");
public readonly static GUISprite BrokenIcon = new GUISprite("BrokenIcon");
public readonly static GUISprite YouAreHereCircle = new GUISprite("YouAreHereCircle");
@@ -124,6 +126,9 @@ namespace Barotrauma
public readonly static GUIColor ColorReputationNeutral = new GUIColor("ColorReputationNeutral", new Color(228, 217, 167, 255));
public readonly static GUIColor ColorReputationHigh = new GUIColor("ColorReputationHigh", new Color(51, 152, 64, 255));
public readonly static GUIColor ColorReputationVeryHigh = new GUIColor("ColorReputationVeryHigh", new Color(71, 160, 164, 255));
public readonly static GUIColor InteractionLabelColor = new GUIColor("InteractionLabelColor", new Color(255, 255, 255, 255));
public readonly static GUIColor InteractionLabelHoverColor = new GUIColor("InteractionLabelHoverColor", new Color(0, 255, 255, 255));
// Inventory
public readonly static GUIColor EquipmentSlotIconColor = new GUIColor("EquipmentSlotIconColor", new Color(99, 70, 64, 255));
@@ -195,8 +200,7 @@ namespace Barotrauma
if (parentStyle == null)
{
Identifier parentStyleName = parent.GetType().Name.ToIdentifier();
Identifier parentStyleName = ReflectionUtils.GetTypeNameWithoutGenericArity(parent.GetType());
if (!ComponentStyles.ContainsKey(parentStyleName))
{
DebugConsole.ThrowError($"Couldn't find a GUI style \"{parentStyleName}\"");
@@ -204,7 +208,7 @@ namespace Barotrauma
}
parentStyle = ComponentStyles[parentStyleName];
}
Identifier childStyleName = styleName.IsEmpty ? targetComponent.GetType().Name.ToIdentifier() : styleName;
Identifier childStyleName = styleName.IsEmpty ? ReflectionUtils.GetTypeNameWithoutGenericArity(targetComponent.GetType()) : styleName;
parentStyle.ChildStyles.TryGetValue(childStyleName, out componentStyle);
}
else
@@ -212,7 +216,7 @@ namespace Barotrauma
Identifier styleIdentifier = styleName.ToIdentifier();
if (styleIdentifier == Identifier.Empty)
{
styleIdentifier = targetComponent.GetType().Name.ToIdentifier();
styleIdentifier = ReflectionUtils.GetTypeNameWithoutGenericArity(targetComponent.GetType());
}
if (!ComponentStyles.ContainsKey(styleIdentifier))
{
@@ -143,6 +143,9 @@ namespace Barotrauma
}
}
/// <summary>
/// When enabled, clips the left side of the text if it's too long to fit in the box (i.e. allows you to enter longer texts without the text overflowing from the box).
/// </summary>
public bool OverflowClip
{
get { return textBlock.OverflowClip; }
@@ -325,7 +328,7 @@ namespace Barotrauma
textBlock.Text = text;
ClearSelection();
if (Text == null) textBlock.Text = "";
if (Text != "" && !Wrap)
if (Text != "")
{
if (maxTextLength != null)
{
@@ -334,7 +337,7 @@ namespace Barotrauma
textBlock.Text = Text.Substring(0, (int)maxTextLength);
}
}
else
else if (!Wrap)
{
while (ClampText && textBlock.Text.Length > 0 && Font.MeasureString(textBlock.Text).X * TextBlock.TextScale > (int)(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z))
{
@@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using System;
namespace Barotrauma
@@ -198,7 +198,9 @@ namespace Barotrauma
base.Update(deltaTime);
if (GUI.MouseOn == this && Enabled)
if (GUI.MouseOn == this && Enabled &&
//allow clicking on the text area, but not further to the right (the dimensions of the component itself can extend further than the text)
PlayerInput.MousePosition.X < Rect.X + ContentWidth)
{
State = Selected ?
ComponentState.HoverSelected :
@@ -779,6 +779,24 @@ namespace Barotrauma
NonScaledSize = targetSize;
yield return CoroutineStatus.Success;
}
/// <summary>
/// Sets the minimum height of the transfrom to equal to the sum of the minimum heights of the children
/// (i.e. makes the rect at least large enough to fit all the children vertically)
/// </summary>
public void InheritTotalChildrenMinHeight()
{
MinSize = new Point(MinSize.X, children.Sum(c => c.MinSize.Y));
}
/// <summary>
/// Sets the minimum height of the transfrom to equal to the sum of the heights of the children
/// (i.e. makes the rect at least large enough to fit all the children vertically)
/// </summary>
public void InheritTotalChildrenHeight()
{
MinSize = new Point(MinSize.X, children.Sum(c => c.Rect.Height));
}
#endregion
#region Static methods
@@ -1733,6 +1733,9 @@ namespace Barotrauma
if (!subItem.Components.All(c => c is not Holdable h || !h.Attachable || !h.Attached)) { continue; }
if (!subItem.Components.All(c => c is not Wire w || w.Connections.All(c => c == null))) { continue; }
if (!ItemAndAllContainersInteractable(subItem)) { continue; }
//don't list items in a character inventory (the ones in a crew member's inventory are counted below)
var rootInventoryOwner = subItem.GetRootInventoryOwner();
if (rootInventoryOwner != null) { continue; }
AddOwnedItem(subItem);
}
}
@@ -1066,7 +1066,7 @@ namespace Barotrauma
GUIButton centerButton = new GUIButton(new RectTransform(new Vector2(1f), centerLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight, anchor: Anchor.Center), style: "GUIButtonTransferArrow");
GUILayoutGroup inputLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), paddedTransferMenuLayout.RectTransform), childAnchor: Anchor.Center);
GUINumberInput transferAmountInput = new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), inputLayout.RectTransform), NumberType.Int, hidePlusMinusButtons: true)
GUINumberInput transferAmountInput = new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), inputLayout.RectTransform), NumberType.Int, buttonVisibility: GUINumberInput.ButtonVisibility.ForceHidden)
{
MinValueInt = 0
};
@@ -131,7 +131,7 @@ namespace Barotrauma
GUIFrame characterSettingsFrame = new GUIFrame(new RectTransform(Vector2.One, parent.RectTransform), style: null) { Visible = false };
GUILayoutGroup characterLayout = new GUILayoutGroup(new RectTransform(Vector2.One, characterSettingsFrame.RectTransform));
GUIFrame containerFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), characterLayout.RectTransform), style: null);
GUIFrame playerFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.7f), containerFrame.RectTransform, Anchor.Center), style: null);
GUILayoutGroup playerFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), containerFrame.RectTransform, Anchor.TopCenter));
GameMain.NetLobbyScreen.CreatePlayerFrame(playerFrame, alwaysAllowEditing: true, createPendingText: false);
GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), skillLayout.RectTransform, Anchor.BottomRight),
@@ -423,7 +423,7 @@ namespace Barotrauma
GUIFrame croppedTalentFrame = new GUIFrame(new RectTransform(Vector2.One, talentFrame.RectTransform, anchor: Anchor.Center, scaleBasis: ScaleBasis.BothHeight), style: null);
GUIButton talentButton = new GUIButton(new RectTransform(Vector2.One, croppedTalentFrame.RectTransform, anchor: Anchor.Center), style: null)
{
ToolTip = RichString.Rich($"‖color:{Color.White.ToStringHex()}‖{talent.DisplayName}‖color:end‖" + "\n\n" + ToolBox.ExtendColorToPercentageSigns(talent.Description.Value)),
ToolTip = CreateTooltip(talent, characterInfo),
UserData = talent.Identifier,
PressedColor = pressedColor,
Enabled = info.Character != null,
@@ -489,6 +489,24 @@ namespace Barotrauma
},
};
static RichString CreateTooltip(TalentPrefab talent, CharacterInfo? character)
{
LocalizedString progress = string.Empty;
if (character is not null && talent.TrackedStat.TryUnwrap(out var stat))
{
var statValue = character.GetSavedStatValue(StatTypes.None, stat.PermanentStatIdentifier);
var intValue = (int)MathF.Round(statValue);
progress = "\n\n";
progress += statValue < stat.Max
? TextManager.GetWithVariables("talentprogress", ("[amount]", intValue.ToString()), ("[max]", stat.Max.ToString()))
: TextManager.Get("talentprogresscompleted");
}
RichString tooltip = RichString.Rich($"‖color:{Color.White.ToStringHex()}‖{talent.DisplayName}‖color:end‖\n\n{ToolBox.ExtendColorToPercentageSigns(talent.Description.Value)}{progress}");
return tooltip;
}
talentButton.Color = talentButton.HoverColor = talentButton.PressedColor = talentButton.SelectedColor = talentButton.DisabledColor = Color.Transparent;
GUIComponent iconImage;
@@ -1305,7 +1305,7 @@ namespace Barotrauma
const int maxUpgrades = 4;
Item? item = entity as Item;
itemName.Text = item?.Name ?? TextManager.Get("upgradecategory.walls");
itemName.Text = item?.Prefab.Name ?? TextManager.Get("upgradecategory.walls");
if (slotIndex > -1)
{
itemName.Text = TextManager.GetWithVariables("weaponslotwithname", ("[number]", slotIndex.ToString()), ("[weaponname]", itemName.Text));
@@ -7,46 +7,46 @@ using Barotrauma.Extensions;
namespace Barotrauma
{
class Widget
public enum WidgetShape
{
public enum Shape
{
Rectangle,
Circle,
Cross
}
Rectangle,
Circle,
Cross
}
public Shape shape;
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);
internal class Widget
{
public WidgetShape Shape;
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
{
get
{
var inputRect = DrawRect;
inputRect.Inflate(inputAreaMargin, inputAreaMargin);
inputRect.Inflate(InputAreaMargin, InputAreaMargin);
return inputRect;
}
}
public Vector2 DrawPos { get; set; }
public int size = 10;
public float thickness = 1f;
public int Size = 10;
public float Thickness = 1f;
/// <summary>
/// Used only for circles.
/// </summary>
public int sides = 40;
public int Sides = 40;
/// <summary>
/// Currently used only for rectangles.
/// </summary>
public bool isFilled;
public int inputAreaMargin;
public Color color = GUIStyle.Red;
public Color? secondaryColor;
public Color textColor = Color.White;
public Color textBackgroundColor = Color.Black * 0.5f;
public readonly string id;
public bool IsFilled;
public int InputAreaMargin;
public Color Color = GUIStyle.Red;
public Color? SecondaryColor;
public Color TextColor = Color.White;
public Color TextBackgroundColor = Color.Black * 0.5f;
public readonly string Id;
public event Action Selected;
public event Action Deselected;
@@ -61,11 +61,11 @@ namespace Barotrauma
public bool RequireMouseOn = true;
public Action refresh;
public Action Refresh;
public object data;
public object Data;
public bool IsSelected => enabled && selectedWidgets.Contains(this);
public bool IsSelected => enabled && SelectedWidgets.Contains(this);
public bool IsControlled => IsSelected && PlayerInput.PrimaryMouseButtonHeld();
public bool IsMouseOver => GUI.MouseOn == null && InputRect.Contains(PlayerInput.MousePosition);
private bool enabled = true;
@@ -75,9 +75,9 @@ namespace Barotrauma
set
{
enabled = value;
if (!enabled && selectedWidgets.Contains(this))
if (!enabled && SelectedWidgets.Contains(this))
{
selectedWidgets.Remove(this);
SelectedWidgets.Remove(this);
}
}
}
@@ -89,46 +89,46 @@ namespace Barotrauma
set
{
multiselect = value;
if (!multiselect && selectedWidgets.Multiple())
if (!multiselect && SelectedWidgets.Multiple())
{
selectedWidgets = selectedWidgets.Take(1).ToList();
SelectedWidgets = SelectedWidgets.Take(1).ToList();
}
}
}
public Vector2? tooltipOffset;
public Vector2? TooltipOffset;
public Widget linkedWidget;
public Widget LinkedWidget;
public static List<Widget> selectedWidgets = new List<Widget>();
public static List<Widget> SelectedWidgets = new List<Widget>();
public Widget(string id, int size, Shape shape)
public Widget(string id, int size, WidgetShape shape)
{
this.id = id;
this.size = size;
this.shape = shape;
Id = id;
Size = size;
Shape = shape;
}
public virtual void Update(float deltaTime)
{
PreUpdate?.Invoke(deltaTime);
if (!enabled) { return; }
if (IsMouseOver || (!RequireMouseOn && selectedWidgets.Contains(this) && PlayerInput.PrimaryMouseButtonHeld()))
if (IsMouseOver || (!RequireMouseOn && SelectedWidgets.Contains(this) && PlayerInput.PrimaryMouseButtonHeld()))
{
Hovered?.Invoke();
System.Diagnostics.Debug.WriteLine("hovered");
if (RequireMouseOn || PlayerInput.PrimaryMouseButtonDown())
{
if ((multiselect && !selectedWidgets.Contains(this)) || selectedWidgets.None())
if ((multiselect && !SelectedWidgets.Contains(this)) || SelectedWidgets.None())
{
selectedWidgets.Add(this);
SelectedWidgets.Add(this);
Selected?.Invoke();
}
}
}
else if (selectedWidgets.Contains(this))
else if (SelectedWidgets.Contains(this))
{
System.Diagnostics.Debug.WriteLine("selectedWidgets.Contains(this) -> remove");
selectedWidgets.Remove(this);
SelectedWidgets.Remove(this);
Deselected?.Invoke();
}
if (IsSelected)
@@ -153,40 +153,40 @@ namespace Barotrauma
{
PreDraw?.Invoke(spriteBatch, deltaTime);
var drawRect = DrawRect;
switch (shape)
switch (Shape)
{
case Shape.Rectangle:
if (secondaryColor.HasValue)
case WidgetShape.Rectangle:
if (SecondaryColor.HasValue)
{
GUI.DrawRectangle(spriteBatch, drawRect, secondaryColor.Value, isFilled, thickness: 2);
GUI.DrawRectangle(spriteBatch, drawRect, SecondaryColor.Value, IsFilled, thickness: 2);
}
GUI.DrawRectangle(spriteBatch, drawRect, color, isFilled, thickness: IsSelected ? (int)(thickness * 3) : (int)thickness);
GUI.DrawRectangle(spriteBatch, drawRect, Color, IsFilled, thickness: IsSelected ? (int)(Thickness * 3) : (int)Thickness);
break;
case Shape.Circle:
if (secondaryColor.HasValue)
case WidgetShape.Circle:
if (SecondaryColor.HasValue)
{
ShapeExtensions.DrawCircle(spriteBatch, DrawPos, size / 2, sides, secondaryColor.Value, thickness: 2);
ShapeExtensions.DrawCircle(spriteBatch, DrawPos, Size / 2, Sides, SecondaryColor.Value, thickness: 2);
}
ShapeExtensions.DrawCircle(spriteBatch, DrawPos, size / 2, sides, color, thickness: IsSelected ? 3 : 1);
ShapeExtensions.DrawCircle(spriteBatch, DrawPos, Size / 2, Sides, Color, thickness: IsSelected ? 3 : 1);
break;
case Shape.Cross:
float halfSize = size / 2;
if (secondaryColor.HasValue)
case WidgetShape.Cross:
float halfSize = Size / 2;
if (SecondaryColor.HasValue)
{
GUI.DrawLine(spriteBatch, DrawPos + Vector2.UnitY * halfSize, DrawPos - Vector2.UnitY * halfSize, secondaryColor.Value, width: 2);
GUI.DrawLine(spriteBatch, DrawPos + Vector2.UnitX * halfSize, DrawPos - Vector2.UnitX * halfSize, secondaryColor.Value, width: 2);
GUI.DrawLine(spriteBatch, DrawPos + Vector2.UnitY * halfSize, DrawPos - Vector2.UnitY * halfSize, SecondaryColor.Value, width: 2);
GUI.DrawLine(spriteBatch, DrawPos + Vector2.UnitX * halfSize, DrawPos - Vector2.UnitX * halfSize, SecondaryColor.Value, width: 2);
}
GUI.DrawLine(spriteBatch, DrawPos + Vector2.UnitY * halfSize, DrawPos - Vector2.UnitY * halfSize, color, width: IsSelected ? 3 : 1);
GUI.DrawLine(spriteBatch, DrawPos + Vector2.UnitX * halfSize, DrawPos - Vector2.UnitX * halfSize, color, width: IsSelected ? 3 : 1);
GUI.DrawLine(spriteBatch, DrawPos + Vector2.UnitY * halfSize, DrawPos - Vector2.UnitY * halfSize, Color, width: IsSelected ? 3 : 1);
GUI.DrawLine(spriteBatch, DrawPos + Vector2.UnitX * halfSize, DrawPos - Vector2.UnitX * halfSize, Color, width: IsSelected ? 3 : 1);
break;
default: throw new NotImplementedException(shape.ToString());
default: throw new NotImplementedException(Shape.ToString());
}
if (IsSelected)
{
if (showTooltip && !tooltip.IsNullOrEmpty())
if (ShowTooltip && !Tooltip.IsNullOrEmpty())
{
var offset = tooltipOffset ?? new Vector2(size, -size / 2f);
GUI.DrawString(spriteBatch, DrawPos + offset, tooltip, textColor, textBackgroundColor);
var offset = TooltipOffset ?? new Vector2(Size, -Size / 2f);
GUIComponent.DrawToolTip(spriteBatch, Tooltip, DrawPos + offset, TextColor, TextBackgroundColor);
}
}
PostDraw?.Invoke(spriteBatch, deltaTime);