(5a377a8ee) Unstable v0.9.1000.0
This commit is contained in:
@@ -52,7 +52,20 @@ namespace Barotrauma
|
||||
|
||||
public GUITextBox InputBox { get; private set; }
|
||||
|
||||
public GUIButton ToggleButton;
|
||||
private GUIButton toggleButton;
|
||||
|
||||
public GUIButton ToggleButton
|
||||
{
|
||||
get => toggleButton;
|
||||
set
|
||||
{
|
||||
if (toggleButton != null)
|
||||
{
|
||||
toggleButton.RectTransform.Parent = null;
|
||||
}
|
||||
toggleButton = value;
|
||||
}
|
||||
}
|
||||
|
||||
private GUIButton showNewMessagesButton;
|
||||
|
||||
@@ -109,7 +122,7 @@ namespace Barotrauma
|
||||
};
|
||||
chatSendButton.RectTransform.AbsoluteOffset = new Point((int)(InputBox.Rect.Height * 0.15f), 0);
|
||||
InputBox.TextBlock.RectTransform.MaxSize
|
||||
= new Point((int)(InputBox.Rect.Width - chatSendButton.Rect.Width * 1.25f - InputBox.TextBlock.Padding.Z), int.MaxValue);
|
||||
= new Point((int)(InputBox.Rect.Width - chatSendButton.Rect.Width * 1.25f - InputBox.TextBlock.Padding.X - chatSendButton.RectTransform.AbsoluteOffset.X), int.MaxValue);
|
||||
|
||||
showNewMessagesButton = new GUIButton(new RectTransform(new Vector2(1f, 0.075f), GUIFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, 0.125f) }, TextManager.Get("chat.shownewmessages"));
|
||||
showNewMessagesButton.OnClicked += (GUIButton btn, object userdata) =>
|
||||
@@ -190,22 +203,49 @@ namespace Barotrauma
|
||||
var msgHolder = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.0f), chatBox.Content.RectTransform, Anchor.TopCenter), style: null,
|
||||
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f);
|
||||
|
||||
GUITextBlock senderNameBlock = new GUITextBlock(new RectTransform(new Vector2(0.98f, 0.0f), msgHolder.RectTransform) { AbsoluteOffset = new Point((int)(5 * GUI.Scale), 0) },
|
||||
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)
|
||||
{
|
||||
CanBeFocused = true
|
||||
};
|
||||
if (!string.IsNullOrEmpty(senderName))
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.8f, 1.0f), senderNameBlock.RectTransform) { AbsoluteOffset = new Point((int)(senderNameBlock.TextSize.X), 0) },
|
||||
senderName, textColor: senderColor, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null)
|
||||
var senderNameBlock = new GUIButton(new RectTransform(new Vector2(0.8f, 1.0f), senderNameTimestamp.RectTransform) { AbsoluteOffset = new Point((int)(senderNameTimestamp.TextSize.X), 0) },
|
||||
senderName, textAlignment: Alignment.TopLeft, style: null, color: Color.Transparent)
|
||||
{
|
||||
CanBeFocused = true
|
||||
TextBlock =
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
},
|
||||
Font = GUI.SmallFont,
|
||||
CanBeFocused = true,
|
||||
ForceUpperCase = false,
|
||||
UserData = message.SenderClient,
|
||||
OnClicked = (_, o) =>
|
||||
{
|
||||
if (!(o is Client client)) { return false; }
|
||||
GameMain.NetLobbyScreen?.SelectPlayer(client);
|
||||
return true;
|
||||
},
|
||||
OnSecondaryClicked = (_, o) =>
|
||||
{
|
||||
if (!(o is Client client)) { return false; }
|
||||
GameMain.GameSession?.CrewManager?.CreateModerationContextMenu(PlayerInput.MousePosition.ToPoint(), client);
|
||||
return true;
|
||||
},
|
||||
Text = senderName
|
||||
};
|
||||
|
||||
senderNameBlock.RectTransform.NonScaledSize = senderNameBlock.TextBlock.TextSize.ToPoint();
|
||||
senderNameBlock.TextBlock.OverrideTextColor(senderColor);
|
||||
if (senderNameBlock.UserData != null)
|
||||
{
|
||||
senderNameBlock.TextBlock.HoverTextColor = Color.White;
|
||||
}
|
||||
}
|
||||
|
||||
var msgText =new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform)
|
||||
{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameBlock == null ? 0 : senderNameBlock.Rect.Height) },
|
||||
{ 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)
|
||||
{
|
||||
@@ -230,7 +270,7 @@ namespace Barotrauma
|
||||
msgHolder.RectTransform.SizeChanged -= Recalculate;
|
||||
//resize the holder to match the size of the message and add some spacing
|
||||
msgText.RectTransform.MaxSize = new Point(msgHolder.Rect.Width - msgText.RectTransform.AbsoluteOffset.X, int.MaxValue);
|
||||
senderNameBlock.RectTransform.MaxSize = new Point(msgHolder.Rect.Width - senderNameBlock.RectTransform.AbsoluteOffset.X, int.MaxValue);
|
||||
senderNameTimestamp.RectTransform.MaxSize = new Point(msgHolder.Rect.Width - senderNameTimestamp.RectTransform.AbsoluteOffset.X, int.MaxValue);
|
||||
msgHolder.Children.ForEach(c => (c as GUITextBlock)?.CalculateHeightFromText());
|
||||
msgHolder.RectTransform.Resize(new Point(msgHolder.Rect.Width, msgHolder.Children.Sum(c => c.Rect.Height) + (int)(10 * GUI.Scale)), resizeChildren: false);
|
||||
msgHolder.RectTransform.SizeChanged += Recalculate;
|
||||
@@ -247,6 +287,11 @@ namespace Barotrauma
|
||||
showNewMessagesButton.Visible = true;
|
||||
}
|
||||
|
||||
if (message.Type == ChatMessageType.Server && message.ChangeType != PlayerConnectionChangeType.None)
|
||||
{
|
||||
TabMenu.StorePlayerConnectionChangeMessage(message);
|
||||
}
|
||||
|
||||
if (!ToggleOpen)
|
||||
{
|
||||
var popupMsg = new GUIFrame(new RectTransform(Vector2.One, GUIFrame.RectTransform), style: "GUIToolTip")
|
||||
@@ -339,17 +384,6 @@ namespace Barotrauma
|
||||
prevUIScale = GUI.Scale;
|
||||
}
|
||||
|
||||
//hide chatbox when accessing the inventory of another character to prevent overlaps
|
||||
if (Character.Controlled?.SelectedCharacter?.Inventory != null &&
|
||||
Character.Controlled.SelectedCharacter.CanInventoryBeAccessed)
|
||||
{
|
||||
SetVisibility(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVisibility(true);
|
||||
}
|
||||
|
||||
if (showNewMessagesButton.Visible && chatBox.ScrollBar.BarScroll == 1f)
|
||||
{
|
||||
showNewMessagesButton.Visible = false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Barotrauma
|
||||
private static GUIDropDown fileTypeDropdown;
|
||||
private static GUIButton openButton;
|
||||
|
||||
private static FileSystemWatcher fileSystemWatcher;
|
||||
private static System.IO.FileSystemWatcher fileSystemWatcher;
|
||||
|
||||
private static string currentFileTypePattern;
|
||||
|
||||
@@ -78,10 +78,10 @@ namespace Barotrauma
|
||||
currentDirectory += "/";
|
||||
}
|
||||
fileSystemWatcher?.Dispose();
|
||||
fileSystemWatcher = new FileSystemWatcher(currentDirectory)
|
||||
fileSystemWatcher = new System.IO.FileSystemWatcher(currentDirectory)
|
||||
{
|
||||
Filter = "*",
|
||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName
|
||||
NotifyFilter = System.IO.NotifyFilters.LastWrite | System.IO.NotifyFilters.FileName | System.IO.NotifyFilters.DirectoryName
|
||||
};
|
||||
fileSystemWatcher.Created += OnFileSystemChanges;
|
||||
fileSystemWatcher.Deleted += OnFileSystemChanges;
|
||||
@@ -97,11 +97,11 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
private static void OnFileSystemChanges(object sender, FileSystemEventArgs e)
|
||||
private static void OnFileSystemChanges(object sender, System.IO.FileSystemEventArgs e)
|
||||
{
|
||||
switch (e.ChangeType)
|
||||
{
|
||||
case WatcherChangeTypes.Created:
|
||||
case System.IO.WatcherChangeTypes.Created:
|
||||
{
|
||||
var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), e.Name)
|
||||
{
|
||||
@@ -114,15 +114,15 @@ namespace Barotrauma
|
||||
fileList.Content.RectTransform.SortChildren(SortFiles);
|
||||
}
|
||||
break;
|
||||
case WatcherChangeTypes.Deleted:
|
||||
case System.IO.WatcherChangeTypes.Deleted:
|
||||
{
|
||||
var itemFrame = fileList.Content.FindChild(c => (c is GUITextBlock tb) && (tb.Text == e.Name || tb.Text == e.Name + "/"));
|
||||
if (itemFrame != null) { fileList.RemoveChild(itemFrame); }
|
||||
}
|
||||
break;
|
||||
case WatcherChangeTypes.Renamed:
|
||||
case System.IO.WatcherChangeTypes.Renamed:
|
||||
{
|
||||
RenamedEventArgs renameArgs = e as RenamedEventArgs;
|
||||
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;
|
||||
@@ -156,7 +156,7 @@ namespace Barotrauma
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
backgroundFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: null)
|
||||
backgroundFrame = new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas), style: null)
|
||||
{
|
||||
Color = Color.Black * 0.5f,
|
||||
HoverColor = Color.Black * 0.5f,
|
||||
@@ -169,10 +169,10 @@ namespace Barotrauma
|
||||
var horizontalLayout = new GUILayoutGroup(new RectTransform(Vector2.One * 0.9f, window.RectTransform, Anchor.Center), true);
|
||||
sidebar = new GUIListBox(new RectTransform(new Vector2(0.29f, 1.0f), horizontalLayout.RectTransform));
|
||||
|
||||
var drives = DriveInfo.GetDrives();
|
||||
var drives = System.IO.DriveInfo.GetDrives();
|
||||
foreach (var drive in drives)
|
||||
{
|
||||
if (drive.DriveType == DriveType.Ram) { continue; }
|
||||
if (drive.DriveType == System.IO.DriveType.Ram) { continue; }
|
||||
if (ignoredDrivePrefixes.Any(p => drive.Name.StartsWith(p))) { continue; }
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), sidebar.Content.RectTransform), drive.Name.Replace('\\','/'));
|
||||
}
|
||||
@@ -348,17 +348,24 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
IEnumerable<string> files = null;
|
||||
foreach (string pattern in currentFileTypePattern.Split(','))
|
||||
if (currentFileTypePattern == null)
|
||||
{
|
||||
string patternTrimmed = pattern.Trim();
|
||||
patternTrimmed = "*" + filterBox.Text + "*" + patternTrimmed;
|
||||
if (files == null)
|
||||
files = Directory.GetFiles(currentDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string pattern in currentFileTypePattern.Split(','))
|
||||
{
|
||||
files = Directory.EnumerateFiles(currentDirectory, patternTrimmed);
|
||||
}
|
||||
else
|
||||
{
|
||||
files = files.Concat(Directory.EnumerateFiles(currentDirectory, patternTrimmed));
|
||||
string patternTrimmed = pattern.Trim();
|
||||
patternTrimmed = "*" + filterBox.Text + "*" + patternTrimmed;
|
||||
if (files == null)
|
||||
{
|
||||
files = Directory.EnumerateFiles(currentDirectory, patternTrimmed);
|
||||
}
|
||||
else
|
||||
{
|
||||
files = files.Concat(Directory.EnumerateFiles(currentDirectory, patternTrimmed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.CharacterEditor;
|
||||
@@ -80,13 +80,33 @@ namespace Barotrauma
|
||||
public static readonly string[] colorComponentLabels = { "R", "G", "B", "A" };
|
||||
|
||||
public static Vector2 ReferenceResolution => new Vector2(1920f, 1080f);
|
||||
public static float Scale => (GameMain.GraphicsWidth / ReferenceResolution.X + GameMain.GraphicsHeight / ReferenceResolution.Y) / 2.0f * GameSettings.HUDScale;
|
||||
public static float xScale => GameMain.GraphicsWidth / ReferenceResolution.X * GameSettings.HUDScale;
|
||||
public static float Scale => (UIWidth / ReferenceResolution.X + GameMain.GraphicsHeight / ReferenceResolution.Y) / 2.0f * GameSettings.HUDScale;
|
||||
public static float xScale => UIWidth / ReferenceResolution.X * GameSettings.HUDScale;
|
||||
public static float yScale => GameMain.GraphicsHeight / ReferenceResolution.Y * GameSettings.HUDScale;
|
||||
public static int IntScale(float f) => (int)(f * Scale);
|
||||
public static int IntScaleFloor(float f) => (int)Math.Floor(f * Scale);
|
||||
public static int IntScaleCeiling(float f) => (int) Math.Ceiling(f * Scale);
|
||||
public static float HorizontalAspectRatio => GameMain.GraphicsWidth / (float)GameMain.GraphicsHeight;
|
||||
public static float VerticalAspectRatio => GameMain.GraphicsHeight / (float)GameMain.GraphicsWidth;
|
||||
public static float RelativeHorizontalAspectRatio => HorizontalAspectRatio / (ReferenceResolution.X / ReferenceResolution.Y);
|
||||
public static float RelativeVerticalAspectRatio => VerticalAspectRatio / (ReferenceResolution.Y / ReferenceResolution.X);
|
||||
public static bool IsUltrawide => HorizontalAspectRatio > 2.0f;
|
||||
|
||||
public static int UIWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
// Ultrawide
|
||||
if (IsUltrawide)
|
||||
{
|
||||
return (int)(GameMain.GraphicsHeight * ReferenceResolution.X / ReferenceResolution.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GameMain.GraphicsWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static float SlicedSpriteScale
|
||||
{
|
||||
@@ -496,9 +516,58 @@ namespace Barotrauma
|
||||
|
||||
if (MouseOn != null)
|
||||
{
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 500, 20),
|
||||
$"Selected UI Element: {MouseOn.GetType().Name} ({ (MouseOn.Style?.Element.Name.LocalName ?? "no style") }, {MouseOn.Rect})",
|
||||
Color.LightGreen, Color.Black * 0.5f, 0, SmallFont);
|
||||
RectTransform mouseOnRect = MouseOn.RectTransform;
|
||||
bool isAbsoluteOffsetInUse = mouseOnRect.AbsoluteOffset != Point.Zero || mouseOnRect.RelativeOffset == Vector2.Zero;
|
||||
|
||||
string selectedString = $"Selected UI Element: {MouseOn.GetType().Name} ({ MouseOn.Style?.Element.Name.LocalName ?? "no style" }, {MouseOn.Rect}";
|
||||
string offsetString = $"Relative Offset: {mouseOnRect.RelativeOffset} | Absolute Offset: {(isAbsoluteOffsetInUse ? mouseOnRect.AbsoluteOffset : mouseOnRect.ParentRect.MultiplySize(mouseOnRect.RelativeOffset))}{(isAbsoluteOffsetInUse ? "" : " (Calculated from RelativeOffset)")}";
|
||||
string anchorPivotString = $"Anchor: {mouseOnRect.Anchor} | Pivot: {mouseOnRect.Pivot}";
|
||||
Vector2 selectedStringSize = SmallFont.MeasureString(selectedString);
|
||||
Vector2 offsetStringSize = SmallFont.MeasureString(offsetString);
|
||||
Vector2 anchorPivotStringSize = SmallFont.MeasureString(anchorPivotString);
|
||||
|
||||
int padding = IntScale(10);
|
||||
int yPos = padding;
|
||||
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)selectedStringSize.X - padding, yPos), selectedString, Color.LightGreen, Color.Black, 0, SmallFont);
|
||||
yPos += (int)selectedStringSize.Y + padding / 2;
|
||||
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)offsetStringSize.X - padding, yPos), offsetString, Color.LightGreen, Color.Black, 0, SmallFont);
|
||||
yPos += (int)offsetStringSize.Y + padding / 2;
|
||||
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)anchorPivotStringSize.X - padding, yPos), anchorPivotString, Color.LightGreen, Color.Black, 0, SmallFont);
|
||||
yPos += (int)anchorPivotStringSize.Y + padding / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
string guiScaleString = $"GUI.Scale: {Scale}";
|
||||
string guixScaleString = $"GUI.xScale: {xScale}";
|
||||
string guiyScaleString = $"GUI.yScale: {yScale}";
|
||||
string relativeHorizontalAspectRatioString = $"RelativeHorizontalAspectRatio: {RelativeHorizontalAspectRatio}";
|
||||
string relativeVerticalAspectRatioString = $"RelativeVerticalAspectRatio: {RelativeVerticalAspectRatio}";
|
||||
Vector2 guiScaleStringSize = SmallFont.MeasureString(guiScaleString);
|
||||
Vector2 guixScaleStringSize = SmallFont.MeasureString(guixScaleString);
|
||||
Vector2 guiyScaleStringSize = SmallFont.MeasureString(guiyScaleString);
|
||||
Vector2 relativeHorizontalAspectRatioStringSize = SmallFont.MeasureString(relativeHorizontalAspectRatioString);
|
||||
Vector2 relativeVerticalAspectRatioStringSize = SmallFont.MeasureString(relativeVerticalAspectRatioString);
|
||||
|
||||
int padding = IntScale(10);
|
||||
int yPos = padding;
|
||||
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)guiScaleStringSize.X - padding, yPos), guiScaleString, Color.LightGreen, Color.Black, 0, SmallFont);
|
||||
yPos += (int)guiScaleStringSize.Y + padding / 2;
|
||||
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)guixScaleStringSize.X - padding, yPos), guixScaleString, Color.LightGreen, Color.Black, 0, SmallFont);
|
||||
yPos += (int)guixScaleStringSize.Y + padding / 2;
|
||||
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)guiyScaleStringSize.X - padding, yPos), guiyScaleString, Color.LightGreen, Color.Black, 0, SmallFont);
|
||||
yPos += (int)guiyScaleStringSize.Y + padding / 2;
|
||||
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)relativeHorizontalAspectRatioStringSize.X - padding, yPos), relativeHorizontalAspectRatioString, Color.LightGreen, Color.Black, 0, SmallFont);
|
||||
yPos += (int)relativeHorizontalAspectRatioStringSize.Y + padding / 2;
|
||||
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)relativeVerticalAspectRatioStringSize.X - padding, yPos), relativeVerticalAspectRatioString, Color.LightGreen, Color.Black, 0, SmallFont);
|
||||
yPos += (int)relativeVerticalAspectRatioStringSize.Y + padding / 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,6 +590,34 @@ namespace Barotrauma
|
||||
MouseOn.DrawToolTip(spriteBatch);
|
||||
}
|
||||
|
||||
if (SubEditorScreen.IsSubEditor())
|
||||
{
|
||||
// Draw our "infinite stack" on the cursor
|
||||
switch (SubEditorScreen.DraggedItemPrefab)
|
||||
{
|
||||
case ItemPrefab itemPrefab:
|
||||
{
|
||||
var sprite = itemPrefab.InventoryIcon ?? itemPrefab.sprite;
|
||||
sprite?.Draw(spriteBatch, PlayerInput.MousePosition, scale: Math.Min(64 / sprite.size.X, 64 / sprite.size.Y) * Scale);
|
||||
break;
|
||||
}
|
||||
case ItemAssemblyPrefab iPrefab:
|
||||
{
|
||||
var (x, y) = PlayerInput.MousePosition;
|
||||
foreach (var pair in iPrefab.DisplayEntities)
|
||||
{
|
||||
Rectangle dRect = pair.Second;
|
||||
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));
|
||||
pair.First.DrawPlacing(spriteBatch, dRect, pair.First.Scale * iPrefab.Scale);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.WindowActive && !HideCursor)
|
||||
{
|
||||
spriteBatch.End();
|
||||
@@ -541,6 +638,10 @@ namespace Barotrauma
|
||||
GameMain.GameScreen.PostProcessEffect.Parameters["blurDistance"].SetValue(0.001f * aberrationStrength);
|
||||
GameMain.GameScreen.PostProcessEffect.Parameters["chromaticAberrationStrength"].SetValue(new Vector3(-0.025f, -0.01f, -0.05f) *
|
||||
(float)(PerlinNoise.CalculatePerlin(aberrationT, aberrationT, 0) + 0.5f) * aberrationStrength);
|
||||
|
||||
Matrix.CreateOrthographicOffCenter(0, GameMain.GraphicsWidth, GameMain.GraphicsHeight, 0, 0, -1, out Matrix projection);
|
||||
|
||||
GameMain.GameScreen.PostProcessEffect.Parameters["MatrixTransform"].SetValue(projection);
|
||||
GameMain.GameScreen.PostProcessEffect.CurrentTechnique = GameMain.GameScreen.PostProcessEffect.Techniques["BlurChromaticAberration"];
|
||||
GameMain.GameScreen.PostProcessEffect.CurrentTechnique.Passes[0].Apply();
|
||||
|
||||
@@ -780,6 +881,8 @@ namespace Barotrauma
|
||||
if (MouseCursor == CursorState.Waiting) { return CursorState.Waiting; }
|
||||
if (GUIScrollBar.DraggingBar != null) { return GUIScrollBar.DraggingBar.Bar.HoverCursor; }
|
||||
|
||||
if (SubEditorScreen.IsSubEditor() && SubEditorScreen.DraggedItemPrefab != null) { return CursorState.Hand; }
|
||||
|
||||
// Wire cursors
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
@@ -816,8 +919,7 @@ namespace Barotrauma
|
||||
case SubEditorScreen editor:
|
||||
{
|
||||
// Portrait area
|
||||
if ((editor.CharacterMode || editor.WiringMode) &&
|
||||
HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition))
|
||||
if (editor.WiringMode && HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
return CursorState.Hand;
|
||||
}
|
||||
@@ -1137,7 +1239,7 @@ namespace Barotrauma
|
||||
font.DrawString(sb, text, pos, color);
|
||||
}
|
||||
|
||||
public static void DrawStringWithColors(SpriteBatch sb, Vector2 pos, string text, Color color, List<ColorData> colorData, Color? backgroundColor = null, int backgroundPadding = 0, ScalableFont font = null, float depth = 0.0f)
|
||||
public static void DrawStringWithColors(SpriteBatch sb, Vector2 pos, string text, Color color, List<RichTextData> richTextData, Color? backgroundColor = null, int backgroundPadding = 0, ScalableFont font = null, float depth = 0.0f)
|
||||
{
|
||||
if (font == null) font = Font;
|
||||
if (backgroundColor != null)
|
||||
@@ -1146,7 +1248,7 @@ namespace Barotrauma
|
||||
DrawRectangle(sb, pos - Vector2.One * backgroundPadding, textSize + Vector2.One * 2.0f * backgroundPadding, (Color)backgroundColor, true, depth, 5);
|
||||
}
|
||||
|
||||
font.DrawStringWithColors(sb, text, pos, color, 0.0f, Vector2.Zero, 1f, SpriteEffects.None, depth, colorData);
|
||||
font.DrawStringWithColors(sb, text, pos, color, 0.0f, Vector2.Zero, 1f, SpriteEffects.None, depth, richTextData);
|
||||
}
|
||||
|
||||
public static void DrawRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, bool isFilled = false, float depth = 0.0f, int thickness = 1)
|
||||
@@ -1863,8 +1965,9 @@ namespace Barotrauma
|
||||
Inventory.draggingItem = null;
|
||||
Inventory.DraggingInventory = null;
|
||||
|
||||
PauseMenu = new GUIFrame(new RectTransform(Vector2.One, Canvas), style: null, color: Color.Black * 0.5f);
|
||||
|
||||
PauseMenu = new GUIFrame(new RectTransform(Vector2.One, Canvas, Anchor.Center), style: null);
|
||||
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, PauseMenu.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||
|
||||
var pauseMenuInner = new GUIFrame(new RectTransform(new Vector2(0.13f, 0.3f), PauseMenu.RectTransform, Anchor.Center) { MinSize = new Point(250, 300) });
|
||||
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 0.6f), pauseMenuInner.RectTransform, Anchor.Center))
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Barotrauma
|
||||
{
|
||||
public class GUICanvas : RectTransform
|
||||
{
|
||||
protected GUICanvas() : base(Vector2.One, parent: null) { }
|
||||
protected GUICanvas() : base(size, parent: null) { }
|
||||
|
||||
private static GUICanvas _instance;
|
||||
public static GUICanvas Instance
|
||||
@@ -22,15 +22,63 @@ namespace Barotrauma
|
||||
{
|
||||
GameMain.Instance.OnResolutionChanged += RecalculateSize;
|
||||
}
|
||||
_instance.ItemComponentHolder = new GUIFrame(new RectTransform(Vector2.One, _instance, Anchor.Center)).RectTransform;
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public RectTransform ItemComponentHolder;
|
||||
|
||||
private static Vector2 size => new Vector2(GameMain.GraphicsWidth / (float)GUI.UIWidth, 1f);
|
||||
|
||||
protected override Rectangle NonScaledUIRect => UIRect;
|
||||
|
||||
private enum ResizeAxis { Both = 0, X = 1, Y = 2 }
|
||||
|
||||
// Turn public, if there is a need to call this manually.
|
||||
private static void RecalculateSize()
|
||||
{
|
||||
Instance.Resize(Vector2.One, resizeChildren: true);
|
||||
Vector2 recalculatedSize = size;
|
||||
|
||||
// Scale children that are supposed to encompass the whole screen so that they are properly scaled on ultrawide as well
|
||||
for (int i = 0; i < Instance.Children.Count(); i++)
|
||||
{
|
||||
RectTransform target = Instance.GetChild(i);
|
||||
if (target == null || target.RelativeSize.X < 1 && target.RelativeSize.Y < 1) continue;
|
||||
|
||||
ResizeAxis axis;
|
||||
|
||||
if (target.RelativeSize.X >= 1 && target.RelativeSize.Y >= 1)
|
||||
{
|
||||
axis = ResizeAxis.Both;
|
||||
}
|
||||
else if (target.RelativeSize.X >= 1)
|
||||
{
|
||||
axis = ResizeAxis.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
axis = ResizeAxis.Y;
|
||||
}
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case ResizeAxis.Both:
|
||||
target.RelativeSize = recalculatedSize;
|
||||
break;
|
||||
|
||||
case ResizeAxis.X:
|
||||
target.RelativeSize = new Vector2(recalculatedSize.X, target.RelativeSize.Y);
|
||||
break;
|
||||
|
||||
case ResizeAxis.Y:
|
||||
target.RelativeSize = new Vector2(target.RelativeSize.X, recalculatedSize.Y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Instance.Resize(size, resizeChildren: true);
|
||||
Instance.GetAllChildren().Select(c => c.GUIComponent as GUITextBlock).ForEach(t => t?.SetTextPos());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using RestSharp;
|
||||
using System.Net;
|
||||
|
||||
@@ -18,6 +18,9 @@ namespace Barotrauma
|
||||
|
||||
public CursorState HoverCursor = CursorState.Default;
|
||||
|
||||
public delegate bool SecondaryButtonDownHandler(GUIComponent component, object userData);
|
||||
public SecondaryButtonDownHandler OnSecondaryClicked;
|
||||
|
||||
public IEnumerable<GUIComponent> Children => RectTransform.Children.Select(c => c.GUIComponent);
|
||||
|
||||
public T GetChild<T>() where T : GUIComponent
|
||||
@@ -202,12 +205,12 @@ namespace Barotrauma
|
||||
set
|
||||
{
|
||||
RawToolTip = value;
|
||||
TooltipColorData = ColorData.GetColorData(value, out value);
|
||||
TooltipRichTextData = RichTextData.GetRichTextData(value, out value);
|
||||
toolTip = value;
|
||||
}
|
||||
}
|
||||
|
||||
public List<ColorData> TooltipColorData = null;
|
||||
public List<RichTextData> TooltipRichTextData = null;
|
||||
|
||||
public GUIComponentStyle Style
|
||||
{
|
||||
@@ -451,6 +454,15 @@ namespace Barotrauma
|
||||
protected virtual void Update(float deltaTime)
|
||||
{
|
||||
if (!Visible) return;
|
||||
|
||||
if (CanBeFocused && OnSecondaryClicked != null)
|
||||
{
|
||||
if (GUI.IsMouseOn(this) && PlayerInput.SecondaryMouseButtonClicked())
|
||||
{
|
||||
OnSecondaryClicked?.Invoke(this, userData);
|
||||
}
|
||||
}
|
||||
|
||||
if (flashTimer > 0.0f)
|
||||
{
|
||||
flashTimer -= deltaTime;
|
||||
@@ -638,10 +650,10 @@ namespace Barotrauma
|
||||
public void DrawToolTip(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!Visible) return;
|
||||
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipColorData);
|
||||
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
|
||||
}
|
||||
|
||||
public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle targetElement, List<ColorData> colorData = null)
|
||||
public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle targetElement, List<RichTextData> richTextData = null)
|
||||
{
|
||||
if (Tutorials.Tutorial.ContentRunning) { return; }
|
||||
|
||||
@@ -651,7 +663,7 @@ namespace Barotrauma
|
||||
|
||||
if (toolTipBlock == null || (string)toolTipBlock.userData != toolTip)
|
||||
{
|
||||
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), colorData, toolTip, font: GUI.SmallFont, wrap: true, style: "GUIToolTip");
|
||||
toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), richTextData, toolTip, font: GUI.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));
|
||||
|
||||
@@ -394,7 +394,7 @@ namespace Barotrauma
|
||||
|
||||
if (Dropped)
|
||||
{
|
||||
listBox.AddToGUIUpdateList(false, UpdateOrder);
|
||||
listBox.AddToGUIUpdateList(false, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class GUIImage : GUIComponent
|
||||
{
|
||||
//paths of the textures that are being loaded asynchronously
|
||||
private static readonly List<string> activeTextureLoads = new List<string>();
|
||||
|
||||
private static bool loadingTextures;
|
||||
|
||||
public static bool LoadingTextures
|
||||
{
|
||||
get
|
||||
{
|
||||
return loadingTextures;
|
||||
}
|
||||
}
|
||||
|
||||
public float Rotation;
|
||||
|
||||
private Sprite sprite;
|
||||
@@ -15,8 +30,12 @@ namespace Barotrauma
|
||||
|
||||
private bool crop;
|
||||
|
||||
private bool scaleToFit;
|
||||
|
||||
private readonly bool scaleToFit;
|
||||
|
||||
private bool lazyLoaded, loading;
|
||||
|
||||
public bool LoadAsynchronously;
|
||||
|
||||
public bool Crop
|
||||
{
|
||||
get
|
||||
@@ -75,7 +94,6 @@ namespace Barotrauma
|
||||
private GUIImage(RectTransform rectT, Sprite sprite, Rectangle? sourceRect, bool scaleToFit, string style) : base(style, rectT)
|
||||
{
|
||||
this.scaleToFit = scaleToFit;
|
||||
sprite?.EnsureLazyLoaded();
|
||||
Sprite = sprite;
|
||||
if (sourceRect.HasValue)
|
||||
{
|
||||
@@ -95,18 +113,45 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
rectT.SizeChanged += RecalculateScale;
|
||||
if (Sprite != null && !Sprite.LazyLoad)
|
||||
{
|
||||
rectT.SizeChanged += RecalculateScale;
|
||||
}
|
||||
}
|
||||
Enabled = true;
|
||||
}
|
||||
|
||||
protected override void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!Visible) return;
|
||||
if (!Visible || loading) { return; }
|
||||
|
||||
if (Parent != null) { State = Parent.State; }
|
||||
if (OverrideState != null) { State = OverrideState.Value; }
|
||||
|
||||
if (Sprite != null && Sprite.LazyLoad && !lazyLoaded)
|
||||
{
|
||||
if (LoadAsynchronously)
|
||||
{
|
||||
loadingTextures = true;
|
||||
loading = true;
|
||||
TaskPool.Add(LoadTextureAsync(), (Task) =>
|
||||
{
|
||||
loading = false;
|
||||
lazyLoaded = true;
|
||||
RectTransform.SizeChanged += RecalculateScale;
|
||||
RecalculateScale();
|
||||
});
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Sprite.EnsureLazyLoaded();
|
||||
RectTransform.SizeChanged += RecalculateScale;
|
||||
RecalculateScale();
|
||||
lazyLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
Color currentColor = GetColor(State);
|
||||
|
||||
if (BlendState != null)
|
||||
@@ -146,9 +191,53 @@ namespace Barotrauma
|
||||
|
||||
private void RecalculateScale()
|
||||
{
|
||||
if (sourceRect == Rectangle.Empty && sprite != null)
|
||||
{
|
||||
sourceRect = sprite.SourceRect;
|
||||
}
|
||||
|
||||
Scale = sprite == null || sprite.SourceRect.Width == 0 || sprite.SourceRect.Height == 0 ?
|
||||
1.0f :
|
||||
Math.Min(RectTransform.Rect.Width / (float)sprite.SourceRect.Width, RectTransform.Rect.Height / (float)sprite.SourceRect.Height);
|
||||
}
|
||||
|
||||
private async Task<bool> LoadTextureAsync()
|
||||
{
|
||||
await Task.Yield();
|
||||
bool wait = true;
|
||||
{
|
||||
//if another GUIImage is already loading the same texture, wait for it to finish
|
||||
while (wait)
|
||||
{
|
||||
await Task.Delay(5);
|
||||
lock (activeTextureLoads)
|
||||
{
|
||||
wait = activeTextureLoads.Contains(Sprite.FullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
lock (activeTextureLoads)
|
||||
{
|
||||
activeTextureLoads.Add(Sprite.FullPath);
|
||||
}
|
||||
Sprite.EnsureLazyLoaded();
|
||||
}
|
||||
finally
|
||||
{
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 10);
|
||||
while (!Sprite.Loaded && DateTime.Now < timeOut)
|
||||
{
|
||||
await Task.Delay(5);
|
||||
}
|
||||
lock (activeTextureLoads)
|
||||
{
|
||||
activeTextureLoads.Remove(Sprite.FullPath);
|
||||
loadingTextures = activeTextureLoads.Count > 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,6 @@ namespace Barotrauma
|
||||
public GUILayoutGroup(RectTransform rectT, bool isHorizontal = false, Anchor childAnchor = Anchor.TopLeft) : base(null, rectT)
|
||||
{
|
||||
CanBeFocused = false;
|
||||
|
||||
this.isHorizontal = isHorizontal;
|
||||
this.childAnchor = childAnchor;
|
||||
rectT.ChildrenChanged += (child) => needsToRecalculate = true;
|
||||
|
||||
@@ -70,6 +70,11 @@ namespace Barotrauma
|
||||
scrollBarNeedsRecalculation = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// true if mouse down should select elements instead of mouse up
|
||||
/// </summary>
|
||||
private bool useMouseDownToSelect = false;
|
||||
|
||||
private Vector4? overridePadding;
|
||||
public Vector4 Padding
|
||||
@@ -80,7 +85,11 @@ namespace Barotrauma
|
||||
if (Style == null) { return Vector4.Zero; }
|
||||
return Style.Padding;
|
||||
}
|
||||
set { overridePadding = value; }
|
||||
set
|
||||
{
|
||||
dimensionsNeedsRecalculation = true;
|
||||
overridePadding = value;
|
||||
}
|
||||
}
|
||||
|
||||
public GUIComponent SelectedComponent
|
||||
@@ -182,10 +191,11 @@ namespace Barotrauma
|
||||
public GUIComponent DraggedElement => draggedElement;
|
||||
|
||||
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
||||
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true) : base(style, rectT)
|
||||
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
|
||||
{
|
||||
CanBeFocused = true;
|
||||
selected = new List<GUIComponent>();
|
||||
this.useMouseDownToSelect = useMouseDownToSelect;
|
||||
ContentBackground = new GUIFrame(new RectTransform(Vector2.One, rectT), style)
|
||||
{
|
||||
CanBeFocused = false
|
||||
@@ -237,7 +247,7 @@ namespace Barotrauma
|
||||
UpdateDimensions();
|
||||
}
|
||||
|
||||
private void UpdateDimensions()
|
||||
public void UpdateDimensions()
|
||||
{
|
||||
dimensionsNeedsRecalculation = false;
|
||||
ContentBackground.RectTransform.Resize(Rect.Size);
|
||||
@@ -403,7 +413,10 @@ namespace Barotrauma
|
||||
if (Enabled && CanBeFocused && child.CanBeFocused && (GUI.IsMouseOn(child)) && child.Rect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
child.State = ComponentState.Hover;
|
||||
if (PlayerInput.PrimaryMouseButtonClicked())
|
||||
|
||||
var mouseDown = useMouseDownToSelect ? PlayerInput.PrimaryMouseButtonDown() : PlayerInput.PrimaryMouseButtonClicked();
|
||||
|
||||
if (mouseDown)
|
||||
{
|
||||
Select(i, autoScroll: false);
|
||||
}
|
||||
@@ -426,7 +439,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
child.State = ComponentState.None;
|
||||
child.State = !child.ExternalHighlight ? ComponentState.None : ComponentState.Hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Barotrauma
|
||||
public static List<GUIComponent> MessageBoxes = new List<GUIComponent>();
|
||||
private static int DefaultWidth
|
||||
{
|
||||
get { return Math.Max(400, 400 * (GameMain.GraphicsWidth / 1920)); }
|
||||
get { return Math.Max(400, (int)(400 * (GameMain.GraphicsWidth / GUI.ReferenceResolution.X))); }
|
||||
}
|
||||
|
||||
private float inGameCloseTimer = 0.0f;
|
||||
@@ -63,7 +63,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
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)
|
||||
: base(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
|
||||
: base(new RectTransform(GUI.Canvas.RelativeSize, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
|
||||
{
|
||||
int width = (int)(DefaultWidth * (type == Type.Default ? 1.0f : 1.5f)), height = 0;
|
||||
if (relativeSize.HasValue)
|
||||
@@ -249,7 +249,10 @@ namespace Barotrauma
|
||||
InnerFrame.RectTransform.AbsoluteOffset = Vector2.SmoothStep(initialPos, defaultPos, openState).ToPoint();
|
||||
openState = Math.Min(openState + deltaTime * 2.0f, 1.0f);
|
||||
|
||||
inGameCloseTimer += deltaTime;
|
||||
if (GUI.MouseOn != InnerFrame && !InnerFrame.IsParentOf(GUI.MouseOn))
|
||||
{
|
||||
inGameCloseTimer += deltaTime;
|
||||
}
|
||||
|
||||
if (inGameCloseTimer >= inGameCloseTime)
|
||||
{
|
||||
|
||||
@@ -59,6 +59,11 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public Color Blue { get; private set; } = Color.Blue;
|
||||
|
||||
/// <summary>
|
||||
/// General yellow color used for elements whose colors are set from code
|
||||
/// </summary>
|
||||
public Color Yellow { get; private set; } = Color.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;
|
||||
@@ -128,6 +133,9 @@ namespace Barotrauma
|
||||
case "blue":
|
||||
Blue = subElement.GetAttributeColor("color", Blue);
|
||||
break;
|
||||
case "yellow":
|
||||
Yellow = subElement.GetAttributeColor("color", Yellow);
|
||||
break;
|
||||
case "colorinventoryempty":
|
||||
ColorInventoryEmpty = subElement.GetAttributeColor("color", ColorInventoryEmpty);
|
||||
break;
|
||||
|
||||
@@ -238,9 +238,40 @@ namespace Barotrauma
|
||||
get { return censoredText; }
|
||||
}
|
||||
|
||||
private List<ColorData> colorData = null;
|
||||
private bool hasColorHighlight = false;
|
||||
|
||||
public class StrikethroughSettings
|
||||
{
|
||||
private Color color = GUI.Style.Red;
|
||||
private int thickness;
|
||||
private int expand;
|
||||
|
||||
public StrikethroughSettings(Color? color = null, int thickness = 1, int expand = 0)
|
||||
{
|
||||
if (color != null) this.color = color.Value;
|
||||
this.thickness = thickness;
|
||||
this.expand = expand;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, float textSizeHalf, float xPos, float yPos)
|
||||
{
|
||||
ShapeExtensions.DrawLine(spriteBatch, new Vector2(xPos - textSizeHalf - expand, yPos), new Vector2(xPos + textSizeHalf + expand, yPos), color, thickness);
|
||||
}
|
||||
}
|
||||
|
||||
public StrikethroughSettings Strikethrough = null;
|
||||
|
||||
private readonly List<RichTextData> richTextData = null;
|
||||
|
||||
private readonly bool hasColorHighlight = false;
|
||||
|
||||
public struct ClickableArea
|
||||
{
|
||||
public RichTextData Data;
|
||||
|
||||
public delegate void OnClickDelegate(GUITextBlock textBlock, ClickableArea area);
|
||||
public OnClickDelegate OnClick;
|
||||
}
|
||||
public List<ClickableArea> ClickableAreas { get; private set; } = new List<ClickableArea>();
|
||||
|
||||
/// <summary>
|
||||
/// This is the new constructor.
|
||||
/// If the rectT height is set 0, the height is calculated from the text.
|
||||
@@ -282,11 +313,11 @@ namespace Barotrauma
|
||||
Enabled = true;
|
||||
Censor = false;
|
||||
}
|
||||
public GUITextBlock(RectTransform rectT, List<ColorData> colorData, string text, Color? textColor = null, ScalableFont font = null, Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = 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.colorData = colorData;
|
||||
hasColorHighlight = colorData != null;
|
||||
this.richTextData = richTextData;
|
||||
hasColorHighlight = richTextData != null;
|
||||
}
|
||||
|
||||
public void CalculateHeightFromText(int padding = 0)
|
||||
@@ -427,6 +458,131 @@ namespace Barotrauma
|
||||
disabledTextColor = color;
|
||||
}
|
||||
|
||||
protected List<Tuple<Vector2, int>> GetAllPositions()
|
||||
{
|
||||
float halfHeight = Font.MeasureString("T").Y * 0.5f;
|
||||
string textDrawn = Censor ? CensoredText : WrappedText;
|
||||
var positions = new List<Tuple<Vector2, int>>();
|
||||
if (textDrawn.Contains("\n"))
|
||||
{
|
||||
string[] lines = textDrawn.Split('\n');
|
||||
int index = 0;
|
||||
int totalIndex = 0;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i];
|
||||
totalIndex += line.Length;
|
||||
float totalTextHeight = Font.MeasureString(textDrawn.Substring(0, totalIndex)).Y;
|
||||
for (int j = 0; j <= line.Length; j++)
|
||||
{
|
||||
Vector2 lineTextSize = Font.MeasureString(line.Substring(0, j));
|
||||
Vector2 indexPos = new Vector2(lineTextSize.X + Padding.X, totalTextHeight + Padding.Y - halfHeight);
|
||||
//DebugConsole.NewMessage($"index: {index}, pos: {indexPos}", Color.AliceBlue);
|
||||
positions.Add(new Tuple<Vector2, int>(indexPos, index + j));
|
||||
}
|
||||
index = totalIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textDrawn = Censor ? CensoredText : Text;
|
||||
for (int i = 0; i <= Text.Length; i++)
|
||||
{
|
||||
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, i));
|
||||
Vector2 indexPos = new Vector2(textSize.X + Padding.X, textSize.Y + Padding.Y - halfHeight) + TextPos - Origin;
|
||||
//DebugConsole.NewMessage($"index: {i}, pos: {indexPos}", Color.WhiteSmoke);
|
||||
positions.Add(new Tuple<Vector2, int>(indexPos, i));
|
||||
}
|
||||
}
|
||||
return positions;
|
||||
}
|
||||
|
||||
public int GetCaretIndexFromScreenPos(Vector2 pos)
|
||||
{
|
||||
return GetCaretIndexFromLocalPos(pos - Rect.Location.ToVector2());
|
||||
}
|
||||
|
||||
public int GetCaretIndexFromLocalPos(Vector2 pos)
|
||||
{
|
||||
var positions = GetAllPositions();
|
||||
if (positions.Count == 0) { return 0; }
|
||||
float halfHeight = Font.MeasureString("T").Y * 0.5f;
|
||||
|
||||
var currPosition = positions[0];
|
||||
|
||||
float topY = positions.Min(p => p.Item1.Y);
|
||||
|
||||
for (int i = 1; i < positions.Count; i++)
|
||||
{
|
||||
var p1 = positions[i];
|
||||
var p2 = currPosition;
|
||||
|
||||
float diffY = Math.Abs(p1.Item1.Y - pos.Y) - Math.Abs(p2.Item1.Y - pos.Y);
|
||||
if (diffY < -3.0f)
|
||||
{
|
||||
currPosition = p1; continue;
|
||||
}
|
||||
else if (diffY > 3.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
diffY = Math.Abs(p1.Item1.Y - pos.Y);
|
||||
if (diffY < halfHeight || (p1.Item1.Y == topY && pos.Y < topY))
|
||||
{
|
||||
//we are on this line, select the nearest character
|
||||
float diffX = Math.Abs(p1.Item1.X - pos.X) - Math.Abs(p2.Item1.X - pos.X);
|
||||
if (diffX < -1.0f)
|
||||
{
|
||||
currPosition = p1; continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//we are on a different line, preserve order
|
||||
if (p1.Item2 < p2.Item2)
|
||||
{
|
||||
if (p1.Item1.Y > pos.Y) { currPosition = p1; }
|
||||
}
|
||||
else if (p1.Item2 > p2.Item2)
|
||||
{
|
||||
if (p1.Item1.Y < pos.Y) { currPosition = p1; }
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
//GUI.AddMessage($"index: {posIndex.Item2}, pos: {posIndex.Item1}", Color.WhiteSmoke);
|
||||
return currPosition != null ? currPosition.Item2 : Text.Length;
|
||||
}
|
||||
|
||||
protected override void Update(float deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
if (ClickableAreas.Any() && (GUI.MouseOn?.IsParentOf(this) ?? true) && Rect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
int index = GetCaretIndexFromScreenPos(PlayerInput.MousePosition);
|
||||
foreach (ClickableArea clickableArea in ClickableAreas)
|
||||
{
|
||||
if (clickableArea.Data.StartIndex <= index && index <= clickableArea.Data.EndIndex)
|
||||
{
|
||||
GUI.MouseCursor = CursorState.Hand;
|
||||
if (PlayerInput.PrimaryMouseButtonClicked())
|
||||
{
|
||||
clickableArea.OnClick?.Invoke(this, clickableArea);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!Visible) { return; }
|
||||
@@ -480,7 +636,12 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos,
|
||||
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, colorData);
|
||||
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, richTextData);
|
||||
}
|
||||
|
||||
if (Strikethrough != null)
|
||||
{
|
||||
Strikethrough.Draw(spriteBatch, (int)Math.Ceiling(TextSize.X / 2f), pos.X, ForceUpperCase ? pos.Y : pos.Y + GUI.Scale * 2f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,12 @@ namespace Barotrauma
|
||||
private Vector2 selectionEndPos;
|
||||
private Vector2 selectionRectSize;
|
||||
|
||||
private bool mouseHeldInside;
|
||||
|
||||
private readonly Memento<string> memento = new Memento<string>();
|
||||
|
||||
// Skip one update cycle, fixes Enter key instantly deselecting the chatbox
|
||||
private bool skipUpdate;
|
||||
|
||||
public GUIFrame Frame
|
||||
{
|
||||
@@ -362,114 +367,14 @@ namespace Barotrauma
|
||||
caretPosDirty = false;
|
||||
}
|
||||
|
||||
protected List<Tuple<Vector2, int>> GetAllPositions()
|
||||
{
|
||||
float halfHeight = Font.MeasureString("T").Y * 0.5f;
|
||||
string textDrawn = Censor ? textBlock.CensoredText : textBlock.WrappedText;
|
||||
var positions = new List<Tuple<Vector2, int>>();
|
||||
if (textDrawn.Contains("\n"))
|
||||
{
|
||||
string[] lines = textDrawn.Split('\n');
|
||||
int index = 0;
|
||||
int totalIndex = 0;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i];
|
||||
totalIndex += line.Length;
|
||||
float totalTextHeight = Font.MeasureString(textDrawn.Substring(0, totalIndex)).Y;
|
||||
for (int j = 0; j <= line.Length; j++)
|
||||
{
|
||||
Vector2 lineTextSize = Font.MeasureString(line.Substring(0, j));
|
||||
Vector2 indexPos = new Vector2(lineTextSize.X + textBlock.Padding.X, totalTextHeight + textBlock.Padding.Y - halfHeight);
|
||||
//DebugConsole.NewMessage($"index: {index}, pos: {indexPos}", Color.AliceBlue);
|
||||
positions.Add(new Tuple<Vector2, int>(indexPos, index + j));
|
||||
}
|
||||
index = totalIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textDrawn = Censor ? textBlock.CensoredText : textBlock.Text;
|
||||
for (int i = 0; i <= textBlock.Text.Length; i++)
|
||||
{
|
||||
Vector2 textSize = Font.MeasureString(textDrawn.Substring(0, i));
|
||||
Vector2 indexPos = new Vector2(textSize.X + textBlock.Padding.X, textSize.Y + textBlock.Padding.Y - halfHeight) + textBlock.TextPos - textBlock.Origin;
|
||||
//DebugConsole.NewMessage($"index: {i}, pos: {indexPos}", Color.WhiteSmoke);
|
||||
positions.Add(new Tuple<Vector2, int>(indexPos, i));
|
||||
}
|
||||
}
|
||||
return positions;
|
||||
}
|
||||
|
||||
public int GetCaretIndexFromScreenPos(Vector2 pos)
|
||||
{
|
||||
return GetCaretIndexFromLocalPos(pos - textBlock.Rect.Location.ToVector2());
|
||||
}
|
||||
|
||||
public int GetCaretIndexFromLocalPos(Vector2 pos)
|
||||
{
|
||||
var positions = GetAllPositions();
|
||||
if (positions.Count==0) { return 0; }
|
||||
float halfHeight = Font.MeasureString("T").Y * 0.5f;
|
||||
|
||||
var currPosition = positions[0];
|
||||
|
||||
for (int i=1;i<positions.Count;i++)
|
||||
{
|
||||
var p1 = positions[i];
|
||||
var p2 = currPosition;
|
||||
|
||||
float diffY = Math.Abs(p1.Item1.Y - pos.Y) - Math.Abs(p2.Item1.Y - pos.Y);
|
||||
if (diffY < -3.0f)
|
||||
{
|
||||
currPosition = p1; continue;
|
||||
}
|
||||
else if (diffY > 3.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
diffY = Math.Abs(p1.Item1.Y - pos.Y);
|
||||
if (diffY < halfHeight)
|
||||
{
|
||||
//we are on this line, select the nearest character
|
||||
float diffX = Math.Abs(p1.Item1.X - pos.X) - Math.Abs(p2.Item1.X - pos.X);
|
||||
if (diffX < -1.0f)
|
||||
{
|
||||
currPosition = p1; continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//we are on a different line, preserve order
|
||||
if (p1.Item2 < p2.Item2)
|
||||
{
|
||||
if (p1.Item1.Y > pos.Y) { currPosition = p1; }
|
||||
}
|
||||
else if (p1.Item2 > p2.Item2)
|
||||
{
|
||||
if (p1.Item1.Y < pos.Y) { currPosition = p1; }
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
//GUI.AddMessage($"index: {posIndex.Item2}, pos: {posIndex.Item1}", Color.WhiteSmoke);
|
||||
return currPosition != null ? currPosition.Item2 : textBlock.Text.Length;
|
||||
}
|
||||
|
||||
public void Select(int forcedCaretIndex = -1)
|
||||
{
|
||||
skipUpdate = true;
|
||||
if (memento.Current == null)
|
||||
{
|
||||
memento.Store(Text);
|
||||
}
|
||||
CaretIndex = forcedCaretIndex == - 1 ? GetCaretIndexFromScreenPos(PlayerInput.MousePosition) : forcedCaretIndex;
|
||||
CaretIndex = forcedCaretIndex == - 1 ? textBlock.GetCaretIndexFromScreenPos(PlayerInput.MousePosition) : forcedCaretIndex;
|
||||
ClearSelection();
|
||||
selected = true;
|
||||
GUI.KeyboardDispatcher.Subscriber = this;
|
||||
@@ -499,11 +404,19 @@ namespace Barotrauma
|
||||
|
||||
if (flashTimer > 0.0f) flashTimer -= deltaTime;
|
||||
if (!Enabled) { return; }
|
||||
|
||||
if (skipUpdate)
|
||||
{
|
||||
skipUpdate = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (MouseRect.Contains(PlayerInput.MousePosition) && (GUI.MouseOn == null || (!(GUI.MouseOn is GUIButton) && GUI.IsMouseOn(this))))
|
||||
{
|
||||
State = ComponentState.Hover;
|
||||
if (PlayerInput.PrimaryMouseButtonDown())
|
||||
{
|
||||
mouseHeldInside = true;
|
||||
Select();
|
||||
}
|
||||
else
|
||||
@@ -518,7 +431,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!MathUtils.NearlyEqual(PlayerInput.MouseSpeed.X, 0))
|
||||
{
|
||||
CaretIndex = GetCaretIndexFromScreenPos(PlayerInput.MousePosition);
|
||||
CaretIndex = textBlock.GetCaretIndexFromScreenPos(PlayerInput.MousePosition);
|
||||
CalculateCaretPos();
|
||||
CalculateSelection();
|
||||
}
|
||||
@@ -526,7 +439,11 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((PlayerInput.LeftButtonClicked() || PlayerInput.RightButtonClicked()) && selected) Deselect();
|
||||
if ((PlayerInput.LeftButtonClicked() || PlayerInput.RightButtonClicked()) && selected)
|
||||
{
|
||||
if (!mouseHeldInside) { Deselect(); }
|
||||
mouseHeldInside = false;
|
||||
}
|
||||
isSelecting = false;
|
||||
State = ComponentState.None;
|
||||
}
|
||||
@@ -793,7 +710,7 @@ namespace Barotrauma
|
||||
InitSelectionStart();
|
||||
}
|
||||
float lineHeight = Font.MeasureString("T").Y;
|
||||
int newIndex = GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y-lineHeight));
|
||||
int newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y-lineHeight));
|
||||
CaretIndex = newIndex;
|
||||
caretTimer = 0;
|
||||
HandleSelection();
|
||||
@@ -804,7 +721,7 @@ namespace Barotrauma
|
||||
InitSelectionStart();
|
||||
}
|
||||
lineHeight = Font.MeasureString("T").Y;
|
||||
newIndex = GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y+lineHeight));
|
||||
newIndex = textBlock.GetCaretIndexFromLocalPos(new Vector2(caretPos.X, caretPos.Y+lineHeight));
|
||||
CaretIndex = newIndex;
|
||||
caretTimer = 0;
|
||||
HandleSelection();
|
||||
|
||||
@@ -50,10 +50,6 @@ namespace Barotrauma
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*public static Rectangle HealthBarAreaRight
|
||||
{
|
||||
get; private set;
|
||||
}*/
|
||||
public static Rectangle HealthBarArea
|
||||
{
|
||||
get; private set;
|
||||
@@ -120,17 +116,11 @@ namespace Barotrauma
|
||||
|
||||
//horizontal slices at the corners of the screen for health bar and affliction icons
|
||||
int afflictionAreaHeight = (int)(50 * GUI.Scale);
|
||||
int healthBarWidth = BottomRightInfoArea.Width + CharacterInventory.SlotSize.X + CharacterInventory.Spacing * 2 + CharacterInventory.HideButtonWidth;
|
||||
int healthBarWidth = (int)(BottomRightInfoArea.Width * 1.58f);
|
||||
int healthBarHeight = (int)(50f * GUI.Scale);
|
||||
HealthBarArea = new Rectangle(BottomRightInfoArea.X - (healthBarWidth - BottomRightInfoArea.Width) + (int)(2 * GUI.Scale), BottomRightInfoArea.Y - healthBarHeight + (int)(10 * GUI.Scale), healthBarWidth, healthBarHeight);
|
||||
AfflictionAreaLeft = new Rectangle(HealthBarArea.X, HealthBarArea.Y - Padding - afflictionAreaHeight, HealthBarArea.Width, afflictionAreaHeight);
|
||||
|
||||
//HealthBarAreaRight = new Rectangle(Padding, GameMain.GraphicsHeight - healthBarHeight - Padding, healthBarWidth, healthBarHeight);
|
||||
/*if (HealthBarAreaRight.Y + healthBarHeight * 0.75f < PortraitArea.Y)
|
||||
{
|
||||
HealthBarAreaRight = new Rectangle(GameMain.GraphicsWidth - Padding - healthBarWidth, HealthBarAreaRight.Y, HealthBarAreaRight.Width, HealthBarAreaRight.Height);
|
||||
}*/
|
||||
//AfflictionAreaRight = new Rectangle(HealthBarAreaRight.X, HealthBarAreaRight.Y + healthBarHeight + Padding, healthBarWidth, afflictionAreaHeight);
|
||||
HealthBarArea = new Rectangle(BottomRightInfoArea.Right - healthBarWidth + (int)Math.Floor(1 / GUI.Scale), BottomRightInfoArea.Y - healthBarHeight + GUI.IntScale(10), healthBarWidth, healthBarHeight);
|
||||
AfflictionAreaLeft = new Rectangle(HealthBarArea.X, HealthBarArea.Y - Padding - afflictionAreaHeight, HealthBarArea.Width, afflictionAreaHeight);
|
||||
|
||||
|
||||
int messageAreaWidth = GameMain.GraphicsWidth / 3;
|
||||
MessageAreaTop = new Rectangle((GameMain.GraphicsWidth - messageAreaWidth) / 2, ButtonAreaTop.Bottom, messageAreaWidth, ButtonAreaTop.Height);
|
||||
@@ -146,7 +136,7 @@ namespace Barotrauma
|
||||
|
||||
CrewArea = new Rectangle(Padding, Padding, (int)Math.Max(400 * GUI.Scale, 220), ObjectiveAnchor.Top - Padding * 2);
|
||||
|
||||
InventoryAreaLower = new Rectangle(Padding, inventoryTopY, GameMain.GraphicsWidth - Padding * 2, GameMain.GraphicsHeight - inventoryTopY);
|
||||
InventoryAreaLower = new Rectangle(ChatBoxArea.Right + Padding * 7, inventoryTopY, GameMain.GraphicsWidth - Padding * 9 - ChatBoxArea.Width, GameMain.GraphicsHeight - inventoryTopY);
|
||||
|
||||
int healthWindowWidth = (int)(GameMain.GraphicsWidth * 0.5f);
|
||||
int healthWindowHeight = (int)(GameMain.GraphicsWidth * 0.5f * 0.65f);
|
||||
|
||||
@@ -338,6 +338,8 @@ namespace Barotrauma
|
||||
PendingSplashScreens.Clear();
|
||||
currSplashScreen = null;
|
||||
}
|
||||
|
||||
if (currSplashScreen == null) { return; }
|
||||
}
|
||||
|
||||
if (currSplashScreen.IsPlaying)
|
||||
|
||||
@@ -253,11 +253,12 @@ namespace Barotrauma
|
||||
return _rect;
|
||||
}
|
||||
}
|
||||
public Rectangle ParentRect => Parent != null ? Parent.Rect : ScreenRect;
|
||||
|
||||
public Rectangle ParentRect => Parent != null ? Parent.Rect : UIRect;
|
||||
protected Rectangle NonScaledRect => new Rectangle(NonScaledTopLeft, NonScaledSize);
|
||||
protected Rectangle NonScaledParentRect => parent != null ? Parent.NonScaledRect : ScreenRect;
|
||||
protected Rectangle ScreenRect => new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
protected virtual Rectangle NonScaledUIRect => NonScaledRect;
|
||||
protected Rectangle NonScaledParentRect => parent != null ? Parent.NonScaledRect : UIRect;
|
||||
protected Rectangle NonScaledParentUIRect => parent != null ? Parent.NonScaledUIRect : UIRect;
|
||||
protected Rectangle UIRect => new Rectangle(0, 0, GUI.UIWidth, GameMain.GraphicsHeight);
|
||||
|
||||
private Pivot pivot;
|
||||
/// <summary>
|
||||
@@ -444,14 +445,14 @@ namespace Barotrauma
|
||||
|
||||
protected void RecalculateRelativeSize()
|
||||
{
|
||||
relativeSize = new Vector2(NonScaledSize.X, NonScaledSize.Y) / new Vector2(NonScaledParentRect.Width, NonScaledParentRect.Height);
|
||||
relativeSize = new Vector2(NonScaledSize.X, NonScaledSize.Y) / new Vector2(NonScaledParentUIRect.Width, NonScaledParentUIRect.Height);
|
||||
recalculateRect = true;
|
||||
SizeChanged?.Invoke();
|
||||
}
|
||||
|
||||
protected void RecalculateAbsoluteSize()
|
||||
{
|
||||
Point size = NonScaledParentRect.Size;
|
||||
Point size = NonScaledParentUIRect.Size;
|
||||
switch (ScaleBasis)
|
||||
{
|
||||
case ScaleBasis.BothWidth:
|
||||
@@ -651,6 +652,13 @@ namespace Barotrauma
|
||||
Parent.ChildrenChanged?.Invoke(this);
|
||||
}
|
||||
|
||||
public void ReverseChildren()
|
||||
{
|
||||
children.Reverse();
|
||||
RecalculateAll(false, false, true);
|
||||
Parent.ChildrenChanged?.Invoke(this);
|
||||
}
|
||||
|
||||
public void SetAsLastChild()
|
||||
{
|
||||
if (IsLastChild) { return; }
|
||||
|
||||
@@ -0,0 +1,941 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Linq;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class TabMenu
|
||||
{
|
||||
public static bool PendingChanges = false;
|
||||
|
||||
private static bool initialized = false;
|
||||
|
||||
private static UISprite spectateIcon, deadIcon, disconnectedIcon;
|
||||
private static Sprite ownerIcon, moderatorIcon;
|
||||
|
||||
private enum InfoFrameTab { Crew, Mission, MyCharacter, Traitor };
|
||||
private static InfoFrameTab selectedTab;
|
||||
private GUIFrame infoFrame, contentFrame;
|
||||
|
||||
private readonly List<GUIButton> tabButtons = new List<GUIButton>();
|
||||
private GUIFrame infoFrameHolder;
|
||||
private List<LinkedGUI> linkedGUIList;
|
||||
private GUIListBox logList;
|
||||
private GUIListBox[] crewListArray;
|
||||
private float sizeMultiplier = 1f;
|
||||
|
||||
private IEnumerable<Character> crew;
|
||||
private List<Character.TeamType> teamIDs;
|
||||
private const string inLobbyString = "\u2022 \u2022 \u2022";
|
||||
|
||||
private static Color ownCharacterBGColor = Color.Gold * 0.7f;
|
||||
|
||||
private class LinkedGUI
|
||||
{
|
||||
private const ushort lowPingThreshold = 100;
|
||||
private const ushort mediumPingThreshold = 200;
|
||||
|
||||
private ushort currentPing;
|
||||
private Client client;
|
||||
private Character character;
|
||||
private bool hasCharacter;
|
||||
private GUITextBlock textBlock;
|
||||
private GUIFrame frame;
|
||||
|
||||
public LinkedGUI(Client client, GUIFrame frame, bool hasCharacter, GUITextBlock textBlock)
|
||||
{
|
||||
this.client = client;
|
||||
this.textBlock = textBlock;
|
||||
this.frame = frame;
|
||||
this.hasCharacter = hasCharacter;
|
||||
}
|
||||
|
||||
public LinkedGUI(Character character, GUIFrame frame, bool hasCharacter, GUITextBlock textBlock)
|
||||
{
|
||||
this.character = character;
|
||||
this.textBlock = textBlock;
|
||||
this.frame = frame;
|
||||
this.hasCharacter = hasCharacter;
|
||||
}
|
||||
|
||||
public bool HasMultiplayerCharacterChanged()
|
||||
{
|
||||
if (client == null) return false;
|
||||
bool characterState = client.Character != null;
|
||||
if (characterState && client.Character.IsDead) characterState = false;
|
||||
return hasCharacter != characterState;
|
||||
}
|
||||
|
||||
public bool HasMultiplayerCharacterDied()
|
||||
{
|
||||
if (client == null || !hasCharacter || client.Character == null) return false;
|
||||
return client.Character.IsDead;
|
||||
}
|
||||
|
||||
public bool HasAICharacterDied()
|
||||
{
|
||||
if (character == null) return false;
|
||||
return character.IsDead;
|
||||
}
|
||||
|
||||
public void TryPingRefresh()
|
||||
{
|
||||
if (client == null) return;
|
||||
if (currentPing == client.Ping) return;
|
||||
currentPing = client.Ping;
|
||||
textBlock.Text = currentPing.ToString();
|
||||
textBlock.TextColor = GetPingColor();
|
||||
}
|
||||
|
||||
private Color GetPingColor()
|
||||
{
|
||||
if (currentPing < lowPingThreshold)
|
||||
{
|
||||
return GUI.Style.Green;
|
||||
}
|
||||
else if (currentPing < mediumPingThreshold)
|
||||
{
|
||||
return GUI.Style.Yellow;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GUI.Style.Red;
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(GUIFrame parent)
|
||||
{
|
||||
parent.RemoveChild(frame);
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
spectateIcon = GUI.Style.GetComponentStyle("SpectateIcon").Sprites[GUIComponent.ComponentState.None][0];
|
||||
deadIcon = GUI.Style.GetComponentStyle("DeadIcon").Sprites[GUIComponent.ComponentState.None][0];
|
||||
disconnectedIcon = GUI.Style.GetComponentStyle("DisconnectedIcon").Sprites[GUIComponent.ComponentState.None][0];
|
||||
ownerIcon = GUI.Style.GetComponentStyle("OwnerIcon").Sprites[GUIComponent.ComponentState.None][0].Sprite;
|
||||
moderatorIcon = GUI.Style.GetComponentStyle("ModeratorIcon").Sprites[GUIComponent.ComponentState.None][0].Sprite;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public TabMenu()
|
||||
{
|
||||
if (!initialized) Initialize();
|
||||
|
||||
CreateInfoFrame(selectedTab);
|
||||
SelectInfoFrameTab(null, selectedTab);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (selectedTab != InfoFrameTab.Crew) return;
|
||||
if (linkedGUIList == null) return;
|
||||
|
||||
if (GameMain.IsMultiplayer)
|
||||
{
|
||||
for (int i = 0; i < linkedGUIList.Count; i++)
|
||||
{
|
||||
linkedGUIList[i].TryPingRefresh();
|
||||
if (linkedGUIList[i].HasMultiplayerCharacterChanged() || linkedGUIList[i].HasMultiplayerCharacterDied() || linkedGUIList[i].HasAICharacterDied())
|
||||
{
|
||||
RemoveCurrentElements();
|
||||
CreateMultiPlayerList(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < linkedGUIList.Count; i++)
|
||||
{
|
||||
if (linkedGUIList[i].HasAICharacterDied())
|
||||
{
|
||||
RemoveCurrentElements();
|
||||
CreateSinglePlayerList(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddToGUIUpdateList()
|
||||
{
|
||||
infoFrame?.AddToGUIUpdateList();
|
||||
NetLobbyScreen.JobInfoFrame?.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public static void OnRoundEnded()
|
||||
{
|
||||
storedMessages.Clear();
|
||||
PendingChanges = false;
|
||||
}
|
||||
|
||||
private void CreateInfoFrame(InfoFrameTab selectedTab)
|
||||
{
|
||||
tabButtons.Clear();
|
||||
|
||||
infoFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
|
||||
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||
|
||||
switch (selectedTab)
|
||||
{
|
||||
case InfoFrameTab.Crew:
|
||||
case InfoFrameTab.Mission:
|
||||
case InfoFrameTab.Traitor:
|
||||
default:
|
||||
contentFrame = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.667f), infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { /*MinSize = new Point(width, height),*/ RelativeOffset = new Vector2(0.025f, 0.12f) });
|
||||
break;
|
||||
case InfoFrameTab.MyCharacter:
|
||||
contentFrame = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.5f), infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { /*MinSize = new Point(width, height),*/ RelativeOffset = new Vector2(0.025f, 0.12f) });
|
||||
break;
|
||||
}
|
||||
|
||||
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(17.5f)) }, style: null);
|
||||
var buttonArea = new GUILayoutGroup(new RectTransform(new Point(innerFrame.Rect.Width, GUI.IntScale(25f)), innerFrame.RectTransform) { AbsoluteOffset = new Point(2, 0) }, isHorizontal: true)
|
||||
{
|
||||
RelativeSpacing = 0.01f
|
||||
};
|
||||
|
||||
infoFrameHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.926f), innerFrame.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter), style: null);
|
||||
|
||||
var crewButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("Crew"), style: "GUITabButton")
|
||||
{
|
||||
UserData = InfoFrameTab.Crew,
|
||||
OnClicked = SelectInfoFrameTab
|
||||
};
|
||||
tabButtons.Add(crewButton);
|
||||
|
||||
var missionButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("Mission"), style: "GUITabButton")
|
||||
{
|
||||
UserData = InfoFrameTab.Mission,
|
||||
OnClicked = SelectInfoFrameTab
|
||||
};
|
||||
tabButtons.Add(missionButton);
|
||||
|
||||
bool isTraitor = GameMain.Client?.Character?.IsTraitor ?? false;
|
||||
if (isTraitor && GameMain.Client.TraitorMission != null)
|
||||
{
|
||||
var traitorButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("tabmenu.traitor"), style: "GUITabButton")
|
||||
{
|
||||
UserData = InfoFrameTab.Traitor,
|
||||
OnClicked = SelectInfoFrameTab
|
||||
};
|
||||
tabButtons.Add(traitorButton);
|
||||
}
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
var myCharacterButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("tabmenu.character"), style: "GUITabButton")
|
||||
{
|
||||
UserData = InfoFrameTab.MyCharacter,
|
||||
OnClicked = SelectInfoFrameTab
|
||||
};
|
||||
tabButtons.Add(myCharacterButton);
|
||||
}
|
||||
}
|
||||
|
||||
private bool SelectInfoFrameTab(GUIButton button, object userData)
|
||||
{
|
||||
selectedTab = (InfoFrameTab)userData;
|
||||
|
||||
CreateInfoFrame(selectedTab);
|
||||
tabButtons.ForEach(tb => tb.Selected = (InfoFrameTab)tb.UserData == selectedTab);
|
||||
|
||||
switch (selectedTab)
|
||||
{
|
||||
case InfoFrameTab.Crew:
|
||||
CreateCrewListFrame(infoFrameHolder);
|
||||
break;
|
||||
case InfoFrameTab.Mission:
|
||||
CreateMissionInfo(infoFrameHolder);
|
||||
break;
|
||||
case InfoFrameTab.Traitor:
|
||||
TraitorMissionPrefab traitorMission = GameMain.Client.TraitorMission;
|
||||
Character traitor = GameMain.Client.Character;
|
||||
if (traitor == null || traitorMission == null) return false;
|
||||
CreateTraitorInfo(infoFrameHolder, traitorMission, traitor);
|
||||
break;
|
||||
case InfoFrameTab.MyCharacter:
|
||||
if (GameMain.NetworkMember == null) { return false; }
|
||||
GameMain.NetLobbyScreen.CreatePlayerFrame(infoFrameHolder);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private const float jobColumnWidthPercentage = 0.138f;
|
||||
private const float characterColumnWidthPercentage = 0.656f;
|
||||
private const float pingColumnWidthPercentage = 0.206f;
|
||||
|
||||
private int jobColumnWidth, characterColumnWidth, pingColumnWidth;
|
||||
|
||||
private void CreateCrewListFrame(GUIFrame crewFrame)
|
||||
{
|
||||
crew = GameMain.GameSession.CrewManager.GetCharacters();
|
||||
teamIDs = crew.Select(c => c.TeamID).Distinct().ToList();
|
||||
|
||||
// Show own team first when there's more than one team
|
||||
if (teamIDs.Count > 1 && GameMain.Client.Character != null)
|
||||
{
|
||||
Character.TeamType ownTeam = GameMain.Client.Character.TeamID;
|
||||
teamIDs = teamIDs.OrderBy(i => i != ownTeam).ThenBy(i => i).ToList();
|
||||
}
|
||||
|
||||
if (!teamIDs.Any()) teamIDs.Add(Character.TeamType.None);
|
||||
|
||||
var content = new GUILayoutGroup(new RectTransform(Vector2.One, crewFrame.RectTransform));
|
||||
|
||||
crewListArray = new GUIListBox[teamIDs.Count];
|
||||
GUILayoutGroup[] headerFrames = new GUILayoutGroup[teamIDs.Count];
|
||||
|
||||
float nameHeight = 0.075f;
|
||||
|
||||
Vector2 crewListSize = new Vector2(1f, 1f / teamIDs.Count - (teamIDs.Count > 1 ? nameHeight * 1.1f : 0f));
|
||||
for (int i = 0; i < teamIDs.Count; i++)
|
||||
{
|
||||
if (teamIDs.Count > 1)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, nameHeight), content.RectTransform), CombatMission.GetTeamName(teamIDs[i]), textColor: i == 0 ? GUI.Style.Green : GUI.Style.Orange) { ForceUpperCase = true };
|
||||
}
|
||||
|
||||
headerFrames[i] = new GUILayoutGroup(new RectTransform(Vector2.Zero, content.RectTransform, Anchor.TopLeft, Pivot.BottomLeft) { AbsoluteOffset = new Point(2, -1) }, isHorizontal: true)
|
||||
{
|
||||
AbsoluteSpacing = 2,
|
||||
UserData = i
|
||||
};
|
||||
|
||||
GUIListBox crewList = new GUIListBox(new RectTransform(crewListSize, content.RectTransform))
|
||||
{
|
||||
Padding = new Vector4(2, 5, 0, 0),
|
||||
AutoHideScrollBar = false
|
||||
};
|
||||
crewList.UpdateDimensions();
|
||||
|
||||
if (teamIDs.Count > 1)
|
||||
{
|
||||
crewList.OnSelected = (component, obj) =>
|
||||
{
|
||||
for (int i = 0; i < crewListArray.Length; i++)
|
||||
{
|
||||
if (crewListArray[i] == crewList) continue;
|
||||
crewListArray[i].Deselect();
|
||||
}
|
||||
SelectElement(component.UserData, crewList);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
crewList.OnSelected = (component, obj) =>
|
||||
{
|
||||
SelectElement(component.UserData, crewList);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
crewListArray[i] = crewList;
|
||||
}
|
||||
|
||||
for (int i = 0; i < teamIDs.Count; i++)
|
||||
{
|
||||
headerFrames[i].RectTransform.RelativeSize = new Vector2(1f - crewListArray[i].ScrollBar.Rect.Width / (float)crewListArray[i].Rect.Width, GUI.HotkeyFont.Size / (float)crewFrame.RectTransform.Rect.Height * 1.5f);
|
||||
|
||||
if (!GameMain.IsMultiplayer)
|
||||
{
|
||||
CreateSinglePlayerListContentHolder(headerFrames[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateMultiPlayerListContentHolder(headerFrames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
crewFrame.RectTransform.AbsoluteOffset = new Point(0, (int)(headerFrames[0].Rect.Height * headerFrames.Length) - (teamIDs.Count > 1 ? GUI.IntScale(10f) : 0));
|
||||
|
||||
if (GameMain.IsMultiplayer)
|
||||
{
|
||||
CreateMultiPlayerList(false);
|
||||
CreateMultiPlayerLogContent(crewFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateSinglePlayerList(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateSinglePlayerListContentHolder(GUILayoutGroup headerFrame)
|
||||
{
|
||||
GUIButton jobButton = new GUIButton(new RectTransform(new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get("tabmenu.job"), style: "GUIButtonSmallFreeScale");
|
||||
GUIButton characterButton = new GUIButton(new RectTransform(new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get("name"), style: "GUIButtonSmallFreeScale");
|
||||
|
||||
sizeMultiplier = (headerFrame.Rect.Width - headerFrame.AbsoluteSpacing * (headerFrame.CountChildren - 1)) / (float)headerFrame.Rect.Width;
|
||||
|
||||
jobButton.RectTransform.RelativeSize = new Vector2(jobColumnWidthPercentage * sizeMultiplier, 1f);
|
||||
characterButton.RectTransform.RelativeSize = new Vector2((1f - jobColumnWidthPercentage * sizeMultiplier) * sizeMultiplier, 1f);
|
||||
|
||||
jobButton.TextBlock.Font = characterButton.TextBlock.Font = GUI.HotkeyFont;
|
||||
jobButton.CanBeFocused = characterButton.CanBeFocused = false;
|
||||
jobButton.TextBlock.ForceUpperCase = characterButton.TextBlock.ForceUpperCase = true;
|
||||
|
||||
jobColumnWidth = jobButton.Rect.Width;
|
||||
characterColumnWidth = characterButton.Rect.Width;
|
||||
}
|
||||
|
||||
private void CreateSinglePlayerList(bool refresh)
|
||||
{
|
||||
if (refresh)
|
||||
{
|
||||
crew = GameMain.GameSession.CrewManager.GetCharacters();
|
||||
}
|
||||
|
||||
linkedGUIList = new List<LinkedGUI>();
|
||||
|
||||
for (int i = 0; i < teamIDs.Count; i++)
|
||||
{
|
||||
foreach (Character character in crew.Where(c => c.TeamID == teamIDs[i]))
|
||||
{
|
||||
CreateSinglePlayerCharacterElement(character, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateSinglePlayerCharacterElement(Character character, int i)
|
||||
{
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(crewListArray[i].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[i].Content.RectTransform), style: "ListBoxElement")
|
||||
{
|
||||
UserData = character,
|
||||
Color = (Character.Controlled == character) ? ownCharacterBGColor : Color.Transparent
|
||||
};
|
||||
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||
{
|
||||
AbsoluteSpacing = 2
|
||||
};
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center), onDraw: (sb, component) => character.Info.DrawJobIcon(sb, component.Rect))
|
||||
{
|
||||
CanBeFocused = false,
|
||||
HoverColor = Color.White,
|
||||
SelectedColor = Color.White
|
||||
};
|
||||
|
||||
GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
|
||||
ToolBox.LimitString(character.Info.Name, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: character.Info.Job.Prefab.UIColor);
|
||||
|
||||
linkedGUIList.Add(new LinkedGUI(character, frame, !character.IsDead, null));
|
||||
}
|
||||
|
||||
private void CreateMultiPlayerListContentHolder(GUILayoutGroup headerFrame)
|
||||
{
|
||||
GUIButton jobButton = new GUIButton(new RectTransform(new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get("tabmenu.job"), style: "GUIButtonSmallFreeScale");
|
||||
GUIButton characterButton = new GUIButton(new RectTransform(new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get("name"), style: "GUIButtonSmallFreeScale");
|
||||
GUIButton pingButton = new GUIButton(new RectTransform(new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get("serverlistping"), style: "GUIButtonSmallFreeScale");
|
||||
|
||||
sizeMultiplier = (headerFrame.Rect.Width - headerFrame.AbsoluteSpacing * (headerFrame.CountChildren - 1)) / (float)headerFrame.Rect.Width;
|
||||
|
||||
jobButton.RectTransform.RelativeSize = new Vector2(jobColumnWidthPercentage * sizeMultiplier, 1f);
|
||||
characterButton.RectTransform.RelativeSize = new Vector2(characterColumnWidthPercentage * sizeMultiplier, 1f);
|
||||
pingButton.RectTransform.RelativeSize = new Vector2(pingColumnWidthPercentage * sizeMultiplier, 1f);
|
||||
|
||||
jobButton.TextBlock.Font = characterButton.TextBlock.Font = pingButton.TextBlock.Font = GUI.HotkeyFont;
|
||||
jobButton.CanBeFocused = characterButton.CanBeFocused = pingButton.CanBeFocused = false;
|
||||
jobButton.TextBlock.ForceUpperCase = characterButton.TextBlock.ForceUpperCase = pingButton.ForceUpperCase = true;
|
||||
|
||||
jobColumnWidth = jobButton.Rect.Width;
|
||||
characterColumnWidth = characterButton.Rect.Width;
|
||||
pingColumnWidth = pingButton.Rect.Width;
|
||||
}
|
||||
|
||||
private void CreateMultiPlayerList(bool refresh)
|
||||
{
|
||||
if (refresh)
|
||||
{
|
||||
crew = GameMain.GameSession.CrewManager.GetCharacters();
|
||||
}
|
||||
|
||||
linkedGUIList = new List<LinkedGUI>();
|
||||
|
||||
List<Client> connectedClients = GameMain.Client.ConnectedClients;
|
||||
|
||||
for (int i = 0; i < teamIDs.Count; i++)
|
||||
{
|
||||
foreach (Character character in crew.Where(c => c.TeamID == teamIDs[i]))
|
||||
{
|
||||
if (!(character is AICharacter) && connectedClients.Find(c => c.Character == null && c.Name == character.Name) != null) continue;
|
||||
CreateMultiPlayerCharacterElement(character, GameMain.Client.ConnectedClients.Find(c => c.Character == character), i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < connectedClients.Count; j++)
|
||||
{
|
||||
Client client = connectedClients[j];
|
||||
|
||||
if (!client.InGame || client.Character == null || client.Character.IsDead)
|
||||
{
|
||||
CreateMultiPlayerClientElement(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateMultiPlayerCharacterElement(Character character, Client client, int i)
|
||||
{
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(crewListArray[i].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[i].Content.RectTransform), style: "ListBoxElement")
|
||||
{
|
||||
UserData = character,
|
||||
Color = (GameMain.NetworkMember != null && GameMain.Client.Character == character) ? ownCharacterBGColor : Color.Transparent
|
||||
};
|
||||
|
||||
frame.OnSecondaryClicked += (component, data) =>
|
||||
{
|
||||
GameMain.GameSession?.CrewManager?.CreateModerationContextMenu(PlayerInput.MousePosition.ToPoint(), client);
|
||||
return true;
|
||||
};
|
||||
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||
{
|
||||
AbsoluteSpacing = 2
|
||||
};
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center), onDraw: (sb, component) => character.Info.DrawJobIcon(sb, component.Rect))
|
||||
{
|
||||
CanBeFocused = false,
|
||||
HoverColor = Color.White,
|
||||
SelectedColor = Color.White
|
||||
};
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
CreateNameWithPermissionIcon(client, paddedFrame);
|
||||
linkedGUIList.Add(new LinkedGUI(client, frame, true, new GUITextBlock(new RectTransform(new Point(pingColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), client.Ping.ToString(), textAlignment: Alignment.Center)));
|
||||
}
|
||||
else
|
||||
{
|
||||
GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
|
||||
ToolBox.LimitString(character.Info.Name, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: character.Info.Job.Prefab.UIColor);
|
||||
|
||||
if (character is AICharacter)
|
||||
{
|
||||
linkedGUIList.Add(new LinkedGUI(character, frame, !character.IsDead, new GUITextBlock(new RectTransform(new Point(pingColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), TextManager.Get("tabmenu.bot"), textAlignment: Alignment.Center) { ForceUpperCase = true }));
|
||||
}
|
||||
else
|
||||
{
|
||||
linkedGUIList.Add(new LinkedGUI(client: null, frame, true, null));
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Point(pingColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center), onDraw: (sb, component) => DrawDisconnectedIcon(sb, component.Rect))
|
||||
{
|
||||
CanBeFocused = false,
|
||||
HoverColor = Color.White,
|
||||
SelectedColor = Color.White
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateMultiPlayerClientElement(Client client)
|
||||
{
|
||||
int teamIndex = GetTeamIndex(client);
|
||||
if (teamIndex == -1) teamIndex = 0;
|
||||
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(crewListArray[teamIndex].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[teamIndex].Content.RectTransform), style: "ListBoxElement")
|
||||
{
|
||||
UserData = client,
|
||||
Color = Color.Transparent
|
||||
};
|
||||
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
|
||||
{
|
||||
AbsoluteSpacing = 2
|
||||
};
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center),
|
||||
onDraw: (sb, component) => DrawNotInGameIcon(sb, component.Rect, client))
|
||||
{
|
||||
CanBeFocused = false,
|
||||
HoverColor = Color.White,
|
||||
SelectedColor = Color.White
|
||||
};
|
||||
|
||||
CreateNameWithPermissionIcon(client, paddedFrame);
|
||||
linkedGUIList.Add(new LinkedGUI(client, frame, false, new GUITextBlock(new RectTransform(new Point(pingColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), client.Ping.ToString(), textAlignment: Alignment.Center)));
|
||||
}
|
||||
|
||||
private int GetTeamIndex(Client client)
|
||||
{
|
||||
if (teamIDs.Count <= 1) return 0;
|
||||
|
||||
if (client.Character != null)
|
||||
{
|
||||
return teamIDs.IndexOf(client.Character.TeamID);
|
||||
}
|
||||
|
||||
if (client.CharacterID != 0)
|
||||
{
|
||||
foreach (Character c in crew)
|
||||
{
|
||||
if (client.CharacterID == c.ID)
|
||||
{
|
||||
return teamIDs.IndexOf(c.TeamID);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Character c in crew)
|
||||
{
|
||||
if (client.Name == c.Name)
|
||||
{
|
||||
return teamIDs.IndexOf(c.TeamID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void CreateNameWithPermissionIcon(Client client, GUILayoutGroup paddedFrame)
|
||||
{
|
||||
GUITextBlock characterNameBlock;
|
||||
Sprite permissionIcon = GetPermissionIcon(client);
|
||||
JobPrefab prefab = client.Character?.Info?.Job?.Prefab;
|
||||
Color nameColor = prefab != null ? prefab.UIColor : Color.White;
|
||||
|
||||
if (permissionIcon != null)
|
||||
{
|
||||
Point iconSize = permissionIcon.SourceRect.Size;
|
||||
float characterNameWidthAdjustment = (iconSize.X + paddedFrame.AbsoluteSpacing) / characterColumnWidth;
|
||||
|
||||
characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
|
||||
ToolBox.LimitString(client.Name, GUI.Font, (int)(characterColumnWidth - paddedFrame.Rect.Width * characterNameWidthAdjustment)), textAlignment: Alignment.Center, textColor: nameColor);
|
||||
|
||||
float iconWidth = iconSize.X / (float)characterColumnWidth;
|
||||
int xOffset = (int)(jobColumnWidth + characterNameBlock.TextPos.X - GUI.Font.MeasureString(characterNameBlock.Text).X / 2f - paddedFrame.AbsoluteSpacing - iconWidth * paddedFrame.Rect.Width);
|
||||
new GUIImage(new RectTransform(new Vector2(iconWidth, 1f), paddedFrame.RectTransform) { AbsoluteOffset = new Point(xOffset + 2, 0) }, permissionIcon) { IgnoreLayoutGroups = true };
|
||||
}
|
||||
else
|
||||
{
|
||||
characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
|
||||
ToolBox.LimitString(client.Name, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: nameColor);
|
||||
}
|
||||
|
||||
if (client.Character != null && client.Character.IsDead)
|
||||
{
|
||||
characterNameBlock.Strikethrough = new GUITextBlock.StrikethroughSettings(null, GUI.IntScale(1f), GUI.IntScale(5f));
|
||||
}
|
||||
}
|
||||
|
||||
private Sprite GetPermissionIcon(Client client)
|
||||
{
|
||||
if (GameMain.NetworkMember == null || client == null || !client.HasPermissions) return null;
|
||||
|
||||
if (!client.AllowKicking) // Owner cannot be kicked
|
||||
{
|
||||
return ownerIcon;
|
||||
}
|
||||
else
|
||||
{
|
||||
return moderatorIcon;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawNotInGameIcon(SpriteBatch spriteBatch, Rectangle area, Client client)
|
||||
{
|
||||
if (client.Spectating)
|
||||
{
|
||||
spectateIcon.Draw(spriteBatch, area, Color.White);
|
||||
}
|
||||
else if (client.Character != null && client.Character.IsDead)
|
||||
{
|
||||
client.Character.Info.DrawJobIcon(spriteBatch, area);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 stringOffset = GUI.GlobalFont.MeasureString(inLobbyString) / 2f;
|
||||
GUI.GlobalFont.DrawString(spriteBatch, inLobbyString, area.Center.ToVector2() - stringOffset, Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawDisconnectedIcon(SpriteBatch spriteBatch, Rectangle area)
|
||||
{
|
||||
disconnectedIcon.Draw(spriteBatch, area, GUI.Style.Red);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Select an element from CrewListFrame
|
||||
/// </summary>
|
||||
private bool SelectElement(object userData, GUIComponent crewList)
|
||||
{
|
||||
Character character = userData as Character;
|
||||
Client client = userData as Client;
|
||||
|
||||
GUIComponent existingPreview = infoFrameHolder.FindChild("SelectedCharacter");
|
||||
if (existingPreview != null) infoFrameHolder.RemoveChild(existingPreview);
|
||||
|
||||
GUIFrame background = new GUIFrame(new RectTransform(new Vector2(0.543f, 0.717f), infoFrameHolder.RectTransform, Anchor.TopLeft, Pivot.TopRight) { RelativeOffset = new Vector2(-0.061f, 0) })
|
||||
{
|
||||
UserData = "SelectedCharacter"
|
||||
};
|
||||
|
||||
if (character != null)
|
||||
{
|
||||
if (GameMain.NetworkMember == null)
|
||||
{
|
||||
GUIComponent preview = character.Info.CreateInfoFrame(background, false, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIComponent preview = character.Info.CreateInfoFrame(background, false, GetPermissionIcon(GameMain.Client.ConnectedClients.Find(c => c.Character == character)));
|
||||
GameMain.Client.SelectCrewCharacter(character, preview);
|
||||
}
|
||||
}
|
||||
else if (client != null)
|
||||
{
|
||||
GUIComponent preview = CreateClientInfoFrame(background, client, GetPermissionIcon(client));
|
||||
if (GameMain.NetworkMember != null) GameMain.Client.SelectCrewClient(client, preview);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private GUIComponent CreateClientInfoFrame(GUIFrame frame, Client client, Sprite permissionIcon = null)
|
||||
{
|
||||
GUIComponent paddedFrame;
|
||||
|
||||
if (client.Character == null)
|
||||
{
|
||||
paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.874f, 0.58f), frame.RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) })
|
||||
{
|
||||
RelativeSpacing = 0.05f
|
||||
//Stretch = true
|
||||
};
|
||||
|
||||
var headerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.322f), paddedFrame.RectTransform), isHorizontal: true);
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.425f, 1.0f), headerArea.RectTransform),
|
||||
onDraw: (sb, component) => DrawNotInGameIcon(sb, component.Rect, client));
|
||||
|
||||
ScalableFont font = paddedFrame.Rect.Width < 280 ? GUI.SmallFont : GUI.Font;
|
||||
|
||||
var headerTextArea = new GUILayoutGroup(new RectTransform(new Vector2(0.575f, 1.0f), headerArea.RectTransform))
|
||||
{
|
||||
RelativeSpacing = 0.02f,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
GUITextBlock clientNameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), ToolBox.LimitString(client.Name, GUI.Font, headerTextArea.Rect.Width), textColor: Color.White, font: GUI.Font)
|
||||
{
|
||||
ForceUpperCase = true,
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
|
||||
if (permissionIcon != null)
|
||||
{
|
||||
Point iconSize = permissionIcon.SourceRect.Size;
|
||||
int iconWidth = (int)((float)clientNameBlock.Rect.Height / iconSize.Y * iconSize.X);
|
||||
new GUIImage(new RectTransform(new Point(iconWidth, clientNameBlock.Rect.Height), clientNameBlock.RectTransform) { AbsoluteOffset = new Point(-iconWidth - 2, 0) }, permissionIcon) { IgnoreLayoutGroups = true };
|
||||
}
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), client.Spectating ? TextManager.Get("playingasspectator") : TextManager.Get("tabmenu.inlobby"), textColor: Color.White, font: font, wrap: true)
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
paddedFrame = client.Character.Info.CreateInfoFrame(frame, false, permissionIcon);
|
||||
}
|
||||
|
||||
return paddedFrame;
|
||||
}
|
||||
|
||||
private void CreateMultiPlayerLogContent(GUIFrame crewFrame)
|
||||
{
|
||||
var logContainer = new GUIFrame(new RectTransform(new Vector2(0.543f, 0.717f), crewFrame.RectTransform, Anchor.TopRight, Pivot.TopLeft) { RelativeOffset = new Vector2(-0.061f, 0) });
|
||||
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.900f, 0.900f), logContainer.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0f, 0.0475f) }, style: null);
|
||||
var content = new GUILayoutGroup(new RectTransform(Vector2.One, innerFrame.RectTransform))
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
logList = new GUIListBox(new RectTransform(Vector2.One, content.RectTransform))
|
||||
{
|
||||
Padding = new Vector4(0, 10 * GUI.Scale, 0, 10 * GUI.Scale),
|
||||
UserData = crewFrame,
|
||||
AutoHideScrollBar = false,
|
||||
Spacing = (int)(5 * GUI.Scale)
|
||||
};
|
||||
|
||||
foreach (Pair<string, PlayerConnectionChangeType> pair in storedMessages)
|
||||
{
|
||||
AddLineToLog(pair.First, pair.Second);
|
||||
}
|
||||
|
||||
logList.BarScroll = 1f;
|
||||
}
|
||||
|
||||
private static readonly List<Pair<string, PlayerConnectionChangeType>> storedMessages = new List<Pair<string, PlayerConnectionChangeType>>();
|
||||
|
||||
public static void StorePlayerConnectionChangeMessage(ChatMessage message)
|
||||
{
|
||||
if (!GameMain.GameSession?.GameMode?.IsRunning ?? true) { return; }
|
||||
|
||||
string msg = ChatMessage.GetTimeStamp() + message.TextWithSender;
|
||||
storedMessages.Add(new Pair<string, PlayerConnectionChangeType>(msg, message.ChangeType));
|
||||
|
||||
if (GameSession.IsTabMenuOpen)
|
||||
{
|
||||
TabMenu instance = GameSession.TabMenuInstance;
|
||||
instance.AddLineToLog(msg, message.ChangeType);
|
||||
|
||||
// Update crew
|
||||
if (selectedTab == InfoFrameTab.Crew)
|
||||
{
|
||||
instance.RemoveCurrentElements();
|
||||
instance.CreateMultiPlayerList(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveCurrentElements()
|
||||
{
|
||||
for (int i = 0; i < crewListArray.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < linkedGUIList.Count; j++)
|
||||
{
|
||||
linkedGUIList[j].Remove(crewListArray[i].Content);
|
||||
}
|
||||
}
|
||||
|
||||
linkedGUIList.Clear();
|
||||
}
|
||||
|
||||
private void AddLineToLog(string line, PlayerConnectionChangeType type)
|
||||
{
|
||||
Color textColor = Color.White;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PlayerConnectionChangeType.Joined:
|
||||
textColor = GUI.Style.Green;
|
||||
break;
|
||||
case PlayerConnectionChangeType.Kicked:
|
||||
textColor = GUI.Style.Orange;
|
||||
break;
|
||||
case PlayerConnectionChangeType.Disconnected:
|
||||
textColor = GUI.Style.Yellow;
|
||||
break;
|
||||
case PlayerConnectionChangeType.Banned:
|
||||
textColor = GUI.Style.Red;
|
||||
break;
|
||||
}
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), logList.Content.RectTransform), line, wrap: true, font: GUI.SmallFont)
|
||||
{
|
||||
TextColor = textColor,
|
||||
CanBeFocused = false,
|
||||
UserData = line
|
||||
}.CalculateHeightFromText();
|
||||
|
||||
//if ((prevSize == 1.0f && listBox.BarScroll == 0.0f) || (prevSize < 1.0f && listBox.BarScroll == 1.0f)) listBox.BarScroll = 1.0f;
|
||||
}
|
||||
|
||||
private void CreateMissionInfo(GUIFrame infoFrame)
|
||||
{
|
||||
infoFrame.ClearChildren();
|
||||
GUIFrame missionFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||
int padding = (int)(0.0245f * missionFrame.Rect.Height);
|
||||
Location endLocation = GameMain.GameSession.EndLocation;
|
||||
Sprite portrait = endLocation.Type.GetPortrait(endLocation.PortraitId);
|
||||
bool hasPortrait = portrait != null && portrait.SourceRect.Width > 0 && portrait.SourceRect.Height > 0;
|
||||
int contentWidth = hasPortrait ? (int)(missionFrame.Rect.Width * 0.951f) : missionFrame.Rect.Width - padding * 2;
|
||||
|
||||
Vector2 locationNameSize = GUI.LargeFont.MeasureString(endLocation.Name);
|
||||
Vector2 locationTypeSize = GUI.SubHeadingFont.MeasureString(endLocation.Name);
|
||||
GUITextBlock locationNameText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationNameSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, padding) }, endLocation.Name, font: GUI.LargeFont);
|
||||
GUITextBlock locationTypeText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationTypeSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationNameText.Rect.Height + padding) }, endLocation.Type.Name, font: GUI.SubHeadingFont);
|
||||
|
||||
int locationInfoYOffset = locationNameText.Rect.Height + locationTypeText.Rect.Height + padding * 2;
|
||||
|
||||
GUIFrame missionDescriptionHolder;
|
||||
|
||||
if (hasPortrait)
|
||||
{
|
||||
GUIFrame missionImageHolder = new GUIFrame(new RectTransform(new Point(contentWidth, (int)(missionFrame.Rect.Height * 0.588f)), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
|
||||
float portraitAspectRatio = portrait.SourceRect.Width / portrait.SourceRect.Height;
|
||||
GUIImage portraitImage = new GUIImage(new RectTransform(new Vector2(1.0f, 1f), missionImageHolder.RectTransform), portrait, scaleToFit: true);
|
||||
missionImageHolder.RectTransform.NonScaledSize = new Point(portraitImage.Rect.Size.X, (int)(portraitImage.Rect.Size.X / portraitAspectRatio));
|
||||
missionDescriptionHolder = new GUIFrame(new RectTransform(new Point(contentWidth, 0), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, missionImageHolder.RectTransform.AbsoluteOffset.Y + missionImageHolder.Rect.Height + padding) }, style: null);
|
||||
}
|
||||
else
|
||||
{
|
||||
missionDescriptionHolder = new GUIFrame(new RectTransform(new Point(contentWidth, 0), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) }, style: null);
|
||||
}
|
||||
|
||||
Mission mission = GameMain.GameSession?.Mission;
|
||||
if (mission != null)
|
||||
{
|
||||
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.744f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.225f, 0f) }, false, childAnchor: Anchor.TopLeft);
|
||||
|
||||
string missionNameString = ToolBox.WrapText(mission.Name, missionTextGroup.Rect.Width, GUI.LargeFont);
|
||||
string missionDescriptionString = ToolBox.WrapText(mission.Description, missionTextGroup.Rect.Width, GUI.Font);
|
||||
string missionRewardString = ToolBox.WrapText(TextManager.GetWithVariable("MissionReward", "[reward]", mission.Reward.ToString()), missionTextGroup.Rect.Width, GUI.Font);
|
||||
|
||||
Vector2 missionNameSize = GUI.LargeFont.MeasureString(missionNameString);
|
||||
Vector2 missionDescriptionSize = GUI.Font.MeasureString(missionDescriptionString);
|
||||
Vector2 missionRewardSize = GUI.Font.MeasureString(missionRewardString);
|
||||
|
||||
missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)(missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y));
|
||||
missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y);
|
||||
|
||||
float iconAspectRatio = mission.Prefab.Icon.SourceRect.Width / mission.Prefab.Icon.SourceRect.Height;
|
||||
int iconWidth = (int)(0.225f * missionDescriptionHolder.RectTransform.NonScaledSize.X);
|
||||
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio));
|
||||
Point iconSize = new Point(iconWidth, iconHeight);
|
||||
|
||||
new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true) { Color = mission.Prefab.IconColor };
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameString, font: GUI.LargeFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionRewardString);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft), false, childAnchor: Anchor.TopLeft);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), TextManager.Get("NoMission"), font: GUI.LargeFont);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateTraitorInfo(GUIFrame infoFrame, TraitorMissionPrefab traitorMission, Character traitor)
|
||||
{
|
||||
GUIFrame missionFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||
|
||||
int padding = (int)(0.0245f * missionFrame.Rect.Height);
|
||||
|
||||
GUIFrame missionDescriptionHolder = new GUIFrame(new RectTransform(new Point(missionFrame.Rect.Width - padding * 2, 0), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, padding) }, style: null);
|
||||
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.65f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.319f, 0f) }, false, childAnchor: Anchor.TopLeft);
|
||||
|
||||
string missionNameString = ToolBox.WrapText(TextManager.Get("tabmenu.traitor"), missionTextGroup.Rect.Width, GUI.LargeFont);
|
||||
string missionDescriptionString = ToolBox.WrapText(traitor.TraitorCurrentObjective, missionTextGroup.Rect.Width, GUI.Font);
|
||||
|
||||
Vector2 missionNameSize = GUI.LargeFont.MeasureString(missionNameString);
|
||||
Vector2 missionDescriptionSize = GUI.Font.MeasureString(missionDescriptionString);
|
||||
|
||||
missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)(missionNameSize.Y + missionDescriptionSize.Y));
|
||||
missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y);
|
||||
|
||||
float aspectRatio = traitorMission.Icon.SourceRect.Width / traitorMission.Icon.SourceRect.Height;
|
||||
|
||||
int iconWidth = (int)(0.319f * missionDescriptionHolder.RectTransform.NonScaledSize.X);
|
||||
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * aspectRatio));
|
||||
Point iconSize = new Point(iconWidth, iconHeight);
|
||||
|
||||
new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), traitorMission.Icon, null, true) { Color = traitorMission.IconColor };
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameString, font: GUI.LargeFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Media;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -56,7 +56,7 @@ namespace Barotrauma
|
||||
|
||||
public VideoPlayer() // GUI elements with size set to Point.Zero are resized based on content
|
||||
{
|
||||
int screenWidth = (int)(GameMain.GraphicsWidth * 0.55f);
|
||||
int screenWidth = (int)(GameMain.GraphicsWidth * 0.65f);
|
||||
scaledVideoResolution = new Point(screenWidth, (int)(screenWidth / 16f * 9f));
|
||||
|
||||
int width = scaledVideoResolution.X;
|
||||
@@ -178,6 +178,7 @@ namespace Barotrauma
|
||||
|
||||
videoFrame.RectTransform.NonScaledSize = scaledVideoResolution + new Point(scaledBorderSize, scaledBorderSize);
|
||||
videoView.RectTransform.NonScaledSize = scaledVideoResolution;
|
||||
videoFrame.RectTransform.AbsoluteOffset = new Point(0, videoFrame.RectTransform.NonScaledSize.Y);
|
||||
|
||||
title.RectTransform.NonScaledSize = new Point(scaledTextWidth, scaledTitleHeight);
|
||||
title.RectTransform.AbsoluteOffset = new Point((int)(5 * GUI.Scale), (int)(10 * GUI.Scale));
|
||||
@@ -247,7 +248,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
videoFrame.RectTransform.AbsoluteOffset = new Point(0, (int)(100 * GUI.Scale));
|
||||
videoFrame.RectTransform.AbsoluteOffset = new Point(0, 0);
|
||||
|
||||
okButton = new GUIButton(new RectTransform(scaledButtonSize, videoFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(scaledBorderSize, scaledBorderSize) }, TextManager.Get("Back"))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user