diff --git a/Barotrauma/BarotraumaClient/ClientSource/Camera.cs b/Barotrauma/BarotraumaClient/ClientSource/Camera.cs index 29bc5fdc9..1afe18bd0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Camera.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Camera.cs @@ -311,7 +311,7 @@ namespace Barotrauma { Freeze = true; } - if (CharacterHealth.OpenHealthWindow != null) + if (CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen) { offset *= 0; Freeze = false; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/EnemyAIController.cs index d190e07af..d33b41d27 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/EnemyAIController.cs @@ -34,7 +34,7 @@ namespace Barotrauma targetPos = attackWorldPos; } targetPos.Y = -targetPos.Y; - GUI.DrawLine(spriteBatch, pos, targetPos, Color.Red * 0.5f, 0, 4); + GUI.DrawLine(spriteBatch, pos, targetPos, GUI.Style.Red * 0.5f, 0, 4); if (wallTarget != null) { Vector2 wallTargetPos = wallTarget.Position; @@ -43,19 +43,19 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Orange, false); GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5); } - GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity.ToString()} ({GetTargetMemory(SelectedAiTarget).Priority.FormatZeroDecimal()})", Color.Red, Color.Black); - GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 40.0f, $"({targetValue.FormatZeroDecimal()})", Color.Red, Color.Black); + GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity.ToString()} ({GetTargetMemory(SelectedAiTarget).Priority.FormatZeroDecimal()})", GUI.Style.Red, Color.Black); + GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 40.0f, $"({targetValue.FormatZeroDecimal()})", GUI.Style.Red, Color.Black); } - /*GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red); - GUI.Font.DrawString(spriteBatch, "updatetargets: " + MathUtils.Round(updateTargetsTimer, 0.1f), pos - Vector2.UnitY * 100.0f, Color.Red); - GUI.Font.DrawString(spriteBatch, "cooldown: " + MathUtils.Round(coolDownTimer, 0.1f), pos - Vector2.UnitY * 120.0f, Color.Red);*/ + /*GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, GUI.Style.Red); + GUI.Font.DrawString(spriteBatch, "updatetargets: " + MathUtils.Round(updateTargetsTimer, 0.1f), pos - Vector2.UnitY * 100.0f, GUI.Style.Red); + GUI.Font.DrawString(spriteBatch, "cooldown: " + MathUtils.Round(coolDownTimer, 0.1f), pos - Vector2.UnitY * 120.0f, GUI.Style.Red);*/ Color stateColor = Color.White; switch (State) { case AIState.Attack: - stateColor = IsCoolDownRunning ? Color.Orange : Color.Red; + stateColor = IsCoolDownRunning ? Color.Orange : GUI.Style.Red; break; case AIState.Escape: stateColor = Color.LightBlue; @@ -75,13 +75,13 @@ namespace Barotrauma { GUI.DrawLine(spriteBatch, ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorA.X, -attachJoint.WorldAnchorA.Y)), - ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), Color.Green, 0, 4); + ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), GUI.Style.Green, 0, 4); } if (LatchOntoAI.WallAttachPos.HasValue) { //GUI.DrawLine(spriteBatch, pos, - // ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.WallAttachPos.Value.X, -LatchOntoAI.WallAttachPos.Value.Y)), Color.Green, 0, 3); + // ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.WallAttachPos.Value.X, -LatchOntoAI.WallAttachPos.Value.Y)), GUI.Style.Green, 0, 3); } } @@ -105,12 +105,12 @@ namespace Barotrauma GUI.DrawLine(spriteBatch, new Vector2(currentNode.DrawPosition.X, -currentNode.DrawPosition.Y), new Vector2(previousNode.DrawPosition.X, -previousNode.DrawPosition.Y), - Color.Red * 0.5f, 0, 3); + GUI.Style.Red * 0.5f, 0, 3); GUI.SmallFont.DrawString(spriteBatch, currentNode.ID.ToString(), new Vector2(currentNode.DrawPosition.X - 10, -currentNode.DrawPosition.Y - 30), - Color.Red); + GUI.Style.Red); } } } @@ -121,7 +121,7 @@ namespace Barotrauma Vector2 hitPos = ConvertUnits.ToDisplayUnits(steeringManager.AvoidRayCastHitPosition); hitPos.Y = -hitPos.Y; - GUI.DrawLine(spriteBatch, hitPos, hitPos + new Vector2(steeringManager.AvoidDir.X, -steeringManager.AvoidDir.Y) * 100, Color.Red, width: 5); + GUI.DrawLine(spriteBatch, hitPos, hitPos + new Vector2(steeringManager.AvoidDir.X, -steeringManager.AvoidDir.Y) * 100, GUI.Style.Red, width: 5); //GUI.DrawLine(spriteBatch, pos, ConvertUnits.ToDisplayUnits(steeringManager.AvoidLookAheadPos.X, -steeringManager.AvoidLookAheadPos.Y), Color.Orange, width: 4); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/HumanAIController.cs index 3e90775da..d904ca184 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/HumanAIController.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/AI/HumanAIController.cs @@ -29,7 +29,7 @@ namespace Barotrauma if (SelectedAiTarget?.Entity != null) { - //GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), Color.Red); + //GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), GUI.Style.Red); //GUI.DrawString(spriteBatch, pos + textOffset, $"AI TARGET: {SelectedAiTarget.Entity.ToString()}", Color.White, Color.Black); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Animation/Ragdoll.cs index e0f5bccc8..63d963175 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Animation/Ragdoll.cs @@ -439,7 +439,7 @@ namespace Barotrauma Color? color = null; if (character.ExternalHighlight) { - color = Color.Lerp(Color.White, Color.OrangeRed, (float)Math.Sin(Timing.TotalTime * 3.5f)); + color = Color.Lerp(Color.White, GUI.Style.Orange, (float)Math.Sin(Timing.TotalTime * 3.5f)); } float depthOffset = GetDepthOffset(); @@ -498,13 +498,13 @@ namespace Barotrauma Vector2 pos = ConvertUnits.ToDisplayUnits(limb.PullJointWorldAnchorA); if (currentHull?.Submarine != null) pos += currentHull.Submarine.DrawPosition; pos.Y = -pos.Y; - GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)pos.Y, 5, 5), Color.Red, true, 0.01f); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)pos.Y, 5, 5), GUI.Style.Red, true, 0.01f); } limb.body.DebugDraw(spriteBatch, inWater ? (currentHull == null ? Color.Blue : Color.Cyan) : Color.White); } - Collider.DebugDraw(spriteBatch, frozen ? Color.Red : (inWater ? Color.SkyBlue : Color.Gray)); + Collider.DebugDraw(spriteBatch, frozen ? GUI.Style.Red : (inWater ? Color.SkyBlue : Color.Gray)); GUI.Font.DrawString(spriteBatch, Collider.LinearVelocity.X.FormatSingleDecimal(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange); foreach (RevoluteJoint joint in LimbJoints) @@ -532,9 +532,9 @@ namespace Barotrauma if (this is HumanoidAnimController humanoid) { Vector2 pos = ConvertUnits.ToDisplayUnits(humanoid.RightHandIKPos); - GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), Color.Green, true); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true); pos = ConvertUnits.ToDisplayUnits(humanoid.LeftHandIKPos); - GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), Color.Green, true); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true); } if (character.MemState.Count > 1) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs index b5cc0d88e..ecc9cb4f6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs @@ -1,3 +1,4 @@ +using Barotrauma.Items.Components; using Barotrauma.Networking; using Barotrauma.Particles; using Barotrauma.Sounds; @@ -58,7 +59,7 @@ namespace Barotrauma CharacterHealth.OpenHealthWindow = null; } } - + private Dictionary hudProgressBars; private readonly List> progressBarRemovals = new List>(); @@ -650,6 +651,34 @@ namespace Barotrauma if (GUI.DisableHUD) return; + if (Controlled != null && + Controlled != this && + Submarine != null && + Controlled.Submarine == Submarine && + GameMain.Config.LosMode != LosMode.None) + { + float yPos = Controlled.AnimController.FloorY - 1.5f; + + if (Controlled.AnimController.Stairs != null) + { + yPos = Controlled.AnimController.Stairs.SimPosition.Y - Controlled.AnimController.Stairs.RectHeight * 0.5f; + } + + foreach (var ladder in Ladder.List) + { + if (CanInteractWith(ladder.Item) && Controlled.CanInteractWith(ladder.Item)) + { + float xPos = ladder.Item.SimPosition.X; + if (Math.Abs(xPos - SimPosition.X) < 3.0) + { + yPos = ladder.Item.SimPosition.Y - ladder.Item.RectHeight * 0.5f; + } + break; + } + } + if (AnimController.FloorY < yPos) { return; } + } + Vector2 pos = DrawPosition; pos.Y += hudInfoHeight; @@ -694,7 +723,7 @@ namespace Barotrauma GUI.DrawLine(spriteBatch, cursorPos, new Vector2(item.First.DrawPosition.X, -item.First.DrawPosition.Y), - ToolBox.GradientLerp(item.Second, Color.Red, Color.Orange, Color.Green), width: 2); + ToolBox.GradientLerp(item.Second, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green), width: 2); } } return; @@ -724,7 +753,7 @@ namespace Barotrauma Color nameColor = Color.White; if (Controlled != null && TeamID != Controlled.TeamID) { - nameColor = TeamID == TeamType.FriendlyNPC ? Color.SkyBlue : Color.Red; + nameColor = TeamID == TeamType.FriendlyNPC ? Color.SkyBlue : GUI.Style.Red; } GUI.Font.DrawString(spriteBatch, name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f); GUI.Font.DrawString(spriteBatch, name, namePos, nameColor * hudInfoAlpha, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f); @@ -744,7 +773,7 @@ namespace Barotrauma Vector2 healthBarPos = new Vector2(pos.X - 50, -pos.Y); GUI.DrawProgressBar(spriteBatch, healthBarPos, new Vector2(100.0f, 15.0f), CharacterHealth.DisplayedVitality / MaxVitality, - Color.Lerp(Color.Red, Color.Green, CharacterHealth.DisplayedVitality / MaxVitality) * 0.8f * hudInfoAlpha, + Color.Lerp(GUI.Style.Red, GUI.Style.Green, CharacterHealth.DisplayedVitality / MaxVitality) * 0.8f * hudInfoAlpha, new Color(0.5f, 0.57f, 0.6f, 1.0f) * hudInfoAlpha); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs index 0f7d039e3..fa96db75a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs @@ -171,6 +171,7 @@ namespace Barotrauma if (GUI.DisableHUD) return; character.CharacterHealth.Alignment = Alignment.Right; + GUI.InfoAreaBackground.Draw(spriteBatch, Vector2.Zero); if (GameMain.GameSession?.CrewManager != null) { @@ -198,54 +199,17 @@ namespace Barotrauma float alpha = Math.Min((1000.0f - dist) / 1000.0f * 2.0f, 1.0f); if (alpha <= 0.0f) continue; GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, GUI.BrokenIcon, - Color.Lerp(Color.DarkRed, Color.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha); + Color.Lerp(GUI.Style.Red, GUI.Style.Orange * 0.5f, brokenItem.Condition / brokenItem.MaxCondition) * alpha); } if (!character.IsUnconscious && character.Stun <= 0.0f) { if (character.FocusedCharacter != null && character.FocusedCharacter.CanBeSelected) { - Vector2 startPos = character.DrawPosition + (character.FocusedCharacter.DrawPosition - character.DrawPosition) * 0.7f; - startPos = cam.WorldToScreen(startPos); - - string focusName = character.FocusedCharacter.DisplayName; - if (character.FocusedCharacter.Info != null) - { - focusName = character.FocusedCharacter.Info.DisplayName; - } - Vector2 textPos = startPos; - Vector2 offset = GUI.Font.MeasureString(focusName); - - textPos -= new Vector2(offset.X / 2, offset.Y); - - Color nameColor = Color.White; - if (character.TeamID != character.FocusedCharacter.TeamID) - { - nameColor = character.FocusedCharacter.TeamID == Character.TeamType.FriendlyNPC ? Color.SkyBlue : Color.Red; - } - - GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2); - textPos.Y += offset.Y; - if (character.FocusedCharacter.CanBeDragged) - { - GUI.DrawString(spriteBatch, textPos, GetCachedHudText("GrabHint", GameMain.Config.KeyBindText(InputType.Grab)), - Color.LightGreen, Color.Black, 2, GUI.SmallFont); - textPos.Y += offset.Y; - } - if (character.FocusedCharacter.CharacterHealth.UseHealthWindow && character.CanInteractWith(character.FocusedCharacter, 160f, false)) - { - GUI.DrawString(spriteBatch, textPos, GetCachedHudText("HealHint", GameMain.Config.KeyBindText(InputType.Health)), - Color.LightGreen, Color.Black, 2, GUI.SmallFont); - textPos.Y += offset.Y; - } - if (!string.IsNullOrEmpty(character.FocusedCharacter.customInteractHUDText)) - { - GUI.DrawString(spriteBatch, textPos, character.FocusedCharacter.customInteractHUDText, Color.LightGreen, Color.Black, 2, GUI.SmallFont); - textPos.Y += offset.Y; - } + DrawCharacterHoverTexts(spriteBatch, cam, character); } - float circleSize = 1.0f; + float circleSize; if (character.FocusedItem != null) { if (focusedItem != character.FocusedItem) @@ -278,9 +242,11 @@ namespace Barotrauma int dir = Math.Sign(focusedItem.WorldPosition.X - character.WorldPosition.X); - Vector2 offset = GUI.Font.MeasureString(focusedItem.Name); + Vector2 textSize = GUI.Font.MeasureString(focusedItem.Name); + Vector2 largeTextSize = GUI.SubHeadingFont.MeasureString(focusedItem.Name); + Vector2 startPos = cam.WorldToScreen(focusedItem.DrawPosition); - startPos.Y -= (hudTexts.Count + 1) * offset.Y; + startPos.Y -= (hudTexts.Count + 1) * textSize.Y; if (focusedItem.Sprite != null) { startPos.X += (int)(circleSize * 0.4f * dir); @@ -288,17 +254,19 @@ namespace Barotrauma } Vector2 textPos = startPos; - if (dir == -1) textPos.X -= offset.X; + if (dir == -1) { textPos.X -= largeTextSize.X; } float alpha = MathHelper.Clamp((focusedItemOverlayTimer - ItemOverlayDelay) * 2.0f, 0.0f, 1.0f); - GUI.DrawString(spriteBatch, textPos, focusedItem.Name, Color.White * alpha, Color.Black * alpha * 0.7f, 2); - textPos.Y += offset.Y; + GUI.DrawString(spriteBatch, textPos, focusedItem.Name, GUI.Style.TextColor * alpha, Color.Black * alpha * 0.7f, 2, font: GUI.SubHeadingFont); + startPos.X += dir * 10.0f * GUI.Scale; + textPos.X += dir * 10.0f * GUI.Scale; + textPos.Y += largeTextSize.Y; foreach (ColoredText coloredText in hudTexts) { if (dir == -1) textPos.X = (int)(startPos.X - GUI.SmallFont.MeasureString(coloredText.Text).X); GUI.DrawString(spriteBatch, textPos, coloredText.Text, coloredText.Color * alpha, Color.Black * alpha * 0.7f, 2, GUI.SmallFont); - textPos.Y += offset.Y; + textPos.Y += textSize.Y; } } } @@ -336,11 +304,12 @@ namespace Barotrauma if (character.Info != null) { character.Info.DrawPortrait(spriteBatch, HUDLayoutSettings.PortraitArea.Location.ToVector2(), targetWidth: HUDLayoutSettings.PortraitArea.Width); + character.Info.DrawJobIcon(spriteBatch); } mouseOnPortrait = HUDLayoutSettings.PortraitArea.Contains(PlayerInput.MousePosition); if (mouseOnPortrait) { - GUI.UIGlow.Draw(spriteBatch, HUDLayoutSettings.PortraitArea, Color.LightGreen * 0.5f); + GUI.UIGlow.Draw(spriteBatch, HUDLayoutSettings.PortraitArea, GUI.Style.Green * 0.5f); } } if (ShouldDrawInventory(character)) @@ -384,7 +353,60 @@ namespace Barotrauma GUIComponent.DrawToolTip( spriteBatch, character.Info?.Job == null ? character.DisplayName : character.Name + " (" + character.Info.Job.Name + ")", - HUDLayoutSettings.PortraitArea); + HUDLayoutSettings.PortraitTooltipArea); + } + } + + private static void DrawCharacterHoverTexts(SpriteBatch spriteBatch, Camera cam, Character character) + { + foreach (Item item in character.Inventory.Items) + { + var statusHUD = item?.GetComponent(); + if (statusHUD != null && statusHUD.IsActive && statusHUD.VisibleCharacters.Contains(character.FocusedCharacter)) + { + return; + } + } + + Vector2 startPos = character.DrawPosition + (character.FocusedCharacter.DrawPosition - character.DrawPosition) * 0.7f; + startPos = cam.WorldToScreen(startPos); + + string focusName = character.FocusedCharacter.DisplayName; + if (character.FocusedCharacter.Info != null) + { + focusName = character.FocusedCharacter.Info.DisplayName; + } + Vector2 textPos = startPos; + Vector2 textSize = GUI.Font.MeasureString(focusName); + Vector2 largeTextSize = GUI.SubHeadingFont.MeasureString(focusName); + + textPos -= new Vector2(textSize.X / 2, textSize.Y); + + Color nameColor = GUI.Style.TextColor; + if (character.TeamID != character.FocusedCharacter.TeamID) + { + nameColor = character.FocusedCharacter.TeamID == Character.TeamType.FriendlyNPC ? Color.SkyBlue : GUI.Style.Red; + } + + GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2, GUI.SubHeadingFont); + textPos.X += 10.0f * GUI.Scale; + textPos.Y += GUI.SubHeadingFont.MeasureString(focusName).Y; + if (character.FocusedCharacter.CanBeDragged) + { + GUI.DrawString(spriteBatch, textPos, GetCachedHudText("GrabHint", GameMain.Config.KeyBindText(InputType.Grab)), + GUI.Style.Green, Color.Black, 2, GUI.SmallFont); + textPos.Y += largeTextSize.Y; + } + if (character.FocusedCharacter.CharacterHealth.UseHealthWindow && character.CanInteractWith(character.FocusedCharacter, 160f, false)) + { + GUI.DrawString(spriteBatch, textPos, GetCachedHudText("HealHint", GameMain.Config.KeyBindText(InputType.Health)), + GUI.Style.Green, Color.Black, 2, GUI.SmallFont); + textPos.Y += textSize.Y; + } + if (!string.IsNullOrEmpty(character.FocusedCharacter.customInteractHUDText)) + { + GUI.DrawString(spriteBatch, textPos, character.FocusedCharacter.customInteractHUDText, GUI.Style.Green, Color.Black, 2, GUI.SmallFont); + textPos.Y += textSize.Y; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs index 49fc72c13..74060629d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs @@ -12,7 +12,7 @@ namespace Barotrauma { public GUIFrame CreateInfoFrame(GUIFrame frame) { - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.7f), frame.RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) }) + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), frame.RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) }) { Stretch = true, RelativeSpacing = 0.03f @@ -103,7 +103,7 @@ namespace Barotrauma { GUI.AddMessage( "+" + ((int)((newLevel - prevLevel) * 100.0f)).ToString() + " XP", - Color.Green, + GUI.Style.Green, textPopupPos, Vector2.UnitY * 10.0f); } @@ -111,7 +111,7 @@ namespace Barotrauma { GUI.AddMessage( "+10 XP", - Color.Green, + GUI.Style.Green, textPopupPos, Vector2.UnitY * 10.0f); } @@ -121,7 +121,7 @@ namespace Barotrauma GUI.AddMessage( TextManager.GetWithVariables("SkillIncreased", new string[3] { "[name]", "[skillname]", "[newlevel]" }, new string[3] { Name, TextManager.Get("SkillName." + skillIdentifier), ((int)newLevel).ToString() }, - new bool[3] { false, true, false }), Color.Green); + new bool[3] { false, true, false }), GUI.Style.Green); } } @@ -160,7 +160,7 @@ namespace Barotrauma sprite.SourceRect = new Rectangle(location, sprite.SourceRect.Size); } - public void DrawPortrait(SpriteBatch spriteBatch, Vector2 screenPos, float targetWidth) + public void DrawPortrait(SpriteBatch spriteBatch, Vector2 screenPos, float targetWidth, bool flip = false) { float backgroundScale = 1; if (PortraitBackground != null) @@ -177,13 +177,13 @@ namespace Barotrauma { Portrait.SourceRect = new Rectangle(CalculateOffset(Portrait, Head.SheetIndex.Value.ToPoint()), Portrait.SourceRect.Size); } - Portrait.Draw(spriteBatch, screenPos + offset, scale: scale, spriteEffect: SpriteEffects.FlipHorizontally); + Portrait.Draw(spriteBatch, screenPos + offset, scale: scale, spriteEffect: flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None); if (AttachmentSprites != null) { float depthStep = 0.000001f; foreach (var attachment in AttachmentSprites) { - DrawAttachmentSprite(spriteBatch, attachment, Portrait, screenPos + offset, scale, depthStep, SpriteEffects.FlipHorizontally); + DrawAttachmentSprite(spriteBatch, attachment, Portrait, screenPos + offset, scale, depthStep, flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None); depthStep += depthStep; } } @@ -213,6 +213,12 @@ namespace Barotrauma } } + public void DrawJobIcon(SpriteBatch spriteBatch) + { + if (jobIcon == null) return; + jobIcon.Draw(spriteBatch, jobIconPos, Job.Prefab.UIColor, scale: .5f * GUI.Scale); + } + private void DrawAttachmentSprite(SpriteBatch spriteBatch, WearableSprite attachment, Sprite head, Vector2 drawPos, float scale, float depthStep, SpriteEffects spriteEffects = SpriteEffects.None) { if (attachment.InheritSourceRect) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs index 3c6a46c0a..f6df55185 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs @@ -288,6 +288,7 @@ namespace Barotrauma GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); //read anyway to prevent messing up reading the rest of the message + UInt16 lastEventID = msg.ReadUInt16(); byte itemCount = msg.ReadByte(); for (int i = 0; i < itemCount; i++) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/HUDProgressBar.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/HUDProgressBar.cs index 6d04c2449..66978830d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/HUDProgressBar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/HUDProgressBar.cs @@ -41,7 +41,7 @@ namespace Barotrauma private Submarine parentSub; public HUDProgressBar(Vector2 worldPosition, Submarine parentSubmarine = null) - : this(worldPosition, parentSubmarine, Color.Red, Color.Green) + : this(worldPosition, parentSubmarine, GUI.Style.Red, GUI.Style.Green) { } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/AfflictionHusk.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/AfflictionHusk.cs index c4e08ceb5..11f03da17 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/AfflictionHusk.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/AfflictionHusk.cs @@ -14,20 +14,20 @@ namespace Barotrauma { if (prevStrength % 10.0f > 0.05f && Strength % 10.0f < 0.05f) { - GUI.AddMessage(TextManager.Get("HuskDormant"), Color.Red); + GUI.AddMessage(TextManager.Get("HuskDormant"), GUI.Style.Red); } } else if (Strength < Prefab.MaxStrength) { if (state == InfectionState.Dormant && Character.Controlled == character) { - GUI.AddMessage(TextManager.Get("HuskCantSpeak"), Color.Red); + GUI.AddMessage(TextManager.Get("HuskCantSpeak"), GUI.Style.Red); } } else if (state != InfectionState.Active && Character.Controlled == character) { GUI.AddMessage(TextManager.GetWithVariable("HuskActivate", "[Attack]", GameMain.Config.KeyBindText(InputType.Attack)), - Color.Red); + GUI.Style.Red); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs index 3dc2aed42..b0e0891e8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs @@ -1,4 +1,5 @@ -using Barotrauma.Items.Components; +using Barotrauma.Extensions; +using Barotrauma.Items.Components; using Barotrauma.Networking; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -19,8 +20,6 @@ namespace Barotrauma private static string[] strengthTexts; - private GUIButton cprButton; - private Point screenResolution; private float uiScale, inventoryScale; @@ -42,42 +41,114 @@ namespace Barotrauma // healthbars private GUIProgressBar healthBar; private GUIProgressBar healthBarShadow; - private GUIProgressBar healthWindowHealthBar; - private GUIProgressBar healthWindowHealthBarShadow; private float healthShadowSize; private float healthShadowDelay; private float healthBarPulsateTimer; private float healthBarPulsatePhase; - private GUITextBlock characterName; - private GUIFrame afflictionInfoFrame; - private GUIListBox afflictionInfoContainer; - private GUIListBox recommendedTreatmentContainer; - private float bloodParticleTimer; + // healing interface + private GUIFrame healthInterfaceFrame; + private GUIFrame healthWindow; private GUIComponent deadIndicator; private GUIComponent lowSkillIndicator; - private SpriteSheet limbIndicatorOverlay; - private float limbIndicatorOverlayAnimState; + private GUILayoutGroup cprLayout; + private GUIFrame cprFrame; + private GUIButton cprButton; - private GUIFrame dropItemArea; + private GUIListBox afflictionTooltip; - private float dropItemAnimDuration = 0.5f; - private float dropItemAnimTimer; - - public Item DroppedItem + private struct HeartratePosition { - get + public float Time; + public float Height; + + public HeartratePosition ScaleHeight(float scale) { - return droppedItem; + return new HeartratePosition + { + Time = this.Time, + Height = this.Height * scale + }; + } + + public HeartratePosition ScaleTime(float scale) + { + return new HeartratePosition + { + Time = this.Time * scale, + Height = this.Height + }; + } + + public HeartratePosition AddTime(float time) + { + return new HeartratePosition + { + Time = this.Time + time, + Height = this.Height + }; + } + + public static IEnumerable ScaleAndDisplace(IEnumerable positions, float heightScale, float timeScale, float timeAdd) + { + HeartratePosition prevPos = new HeartratePosition + { + Time = 0.0f, + Height = 0.0f + }; + bool wrapped = false; + foreach (HeartratePosition pos in positions) + { + HeartratePosition newPos = pos.ScaleHeight(heightScale).ScaleTime(timeScale).AddTime(timeAdd); + if (newPos.Time > 1.0f) + { + if (!wrapped) + { + yield return new HeartratePosition + { + Time = 1.0f, + Height = (newPos.Height - prevPos.Height) / (newPos.Time - prevPos.Time) * (1.0f - prevPos.Time) + prevPos.Height + }; + yield return new HeartratePosition + { + Time = 0.0f, + Height = (newPos.Height - prevPos.Height) / (newPos.Time - prevPos.Time) * (1.0f - prevPos.Time) + prevPos.Height + }; + wrapped = true; + } + newPos.Time -= 1.0f; + } + prevPos = newPos; + yield return newPos; + } } } - private Item droppedItem; + private List heartratePositions; + private float currentHeartrateTime; + private float heartbeatTimer; + private Texture2D heartrateFade; + + private HeartratePosition[] heartbeatPattern = { + new HeartratePosition() { Time = 0.0f, Height = 0.0f }, + new HeartratePosition() { Time = 0.15f, Height = 0.2f }, + new HeartratePosition() { Time = 0.2f, Height = -0.2f }, + new HeartratePosition() { Time = 0.36f, Height = 0.0f }, + new HeartratePosition() { Time = 0.43f, Height = 0.8f }, + new HeartratePosition() { Time = 0.57f, Height = -0.8f }, + new HeartratePosition() { Time = 0.64f, Height = 0.0f }, + new HeartratePosition() { Time = 0.8f, Height = 0.2f }, + new HeartratePosition() { Time = 0.85f, Height = -0.2f }, + new HeartratePosition() { Time = 1.0f, Height = 0.0f }, + }; + + private SpriteSheet limbIndicatorOverlay; + private float limbIndicatorOverlayAnimState; private GUIComponent draggingMed; @@ -85,6 +156,17 @@ namespace Barotrauma private int selectedLimbIndex = -1; private LimbHealth currentDisplayedLimb; + private GUIProgressBar healthWindowHealthBar; + private GUIProgressBar healthWindowHealthBarShadow; + + private GUITextBlock characterName; + private GUIFrame afflictionInfoFrame; + private GUIListBox afflictionIconContainer; + private GUIListBox afflictionInfoContainer; + private GUILayoutGroup treatmentLayout; + private GUIListBox recommendedTreatmentContainer; + private GUITextBlock selectedLimbText; + private float distortTimer; // 0-1 @@ -101,7 +183,7 @@ namespace Barotrauma public bool MouseOnElement { - get { return highlightedLimbIndex > -1 || GUI.MouseOn == dropItemArea; } + get { return highlightedLimbIndex > -1; } } private static CharacterHealth openHealthWindow; @@ -172,95 +254,37 @@ namespace Barotrauma character.OnAttacked += OnAttacked; - bool horizontal = HUDLayoutSettings.HealthBarAreaLeft.Width > HUDLayoutSettings.HealthBarAreaLeft.Height; + bool horizontal = true; healthBar = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas), - barSize: 1.0f, color: Color.Green, style: horizontal ? "GUIProgressBar" : "GUIProgressBarVertical") + barSize: 1.0f, color: GUIColorSettings.HealthBarColorHigh, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical", false) { Enabled = true, HoverCursor = CursorState.Hand, IsHorizontal = horizontal }; healthBarShadow = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas), - barSize: 1.0f, color: Color.Green, style: horizontal ? "GUIProgressBar" : "GUIProgressBarVertical") + barSize: 1.0f, color: Color.Green, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical", false) { IsHorizontal = horizontal }; healthShadowSize = 1.0f; - afflictionInfoFrame = new GUIFrame(new RectTransform(new Point(HUDLayoutSettings.HealthWindowAreaLeft.Width / 2, 200), GUI.Canvas)); - var paddedInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), afflictionInfoFrame.RectTransform, Anchor.Center), style: null); - new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.08f), paddedInfoFrame.RectTransform), "", font: GUI.LargeFont) - { - UserData = "selectedlimbname" - }; + healthInterfaceFrame = new GUIFrame(new RectTransform(new Vector2(0.85f * 1.1f, 0.66f * 0.85f * 1.1f), GUI.Canvas, anchor: Anchor.Center, scaleBasis: ScaleBasis.Smallest), style: "ItemUI"); - afflictionInfoContainer = new GUIListBox(new RectTransform(new Vector2(0.7f, 0.85f), paddedInfoFrame.RectTransform, Anchor.BottomLeft)); + var healthInterfaceLayout = new GUILayoutGroup(new RectTransform(Vector2.One / 1.1f, healthInterfaceFrame.RectTransform, anchor: Anchor.Center), true); - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), paddedInfoFrame.RectTransform, Anchor.TopRight), TextManager.Get("SuitableTreatments"), textAlignment: Alignment.TopRight); - - recommendedTreatmentContainer = new GUIListBox(new RectTransform(new Vector2(0.28f, 0.47f), paddedInfoFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.15f) }); - dropItemArea = new GUIFrame(new RectTransform(new Vector2(0.28f, 0.3f), paddedInfoFrame.RectTransform, Anchor.BottomRight) - { RelativeOffset = new Vector2(0.02f, 0.0f) }, style: null) - { - ToolTip = TextManager.Get("HealthItemUseTip") - }; - dropItemArea.RectTransform.NonScaledSize = new Point(dropItemArea.Rect.Width); + //limb selection frame + healthWindow = new GUIFrame(new RectTransform(new Vector2(0.45f, 1.0f), healthInterfaceLayout.RectTransform), style: null); - lowSkillIndicator = new GUIImage(new RectTransform(new Vector2(0.5f, 0.22f), paddedInfoFrame.RectTransform, Anchor.TopRight, Pivot.Center) { RelativeOffset = new Vector2(0.16f, 0.12f) }, - style: "GUINotificationButton") - { - ToolTip = TextManager.Get("lowmedicalskillwarning"), - Color = Color.OrangeRed, - HoverColor = Color.Orange, - PressedColor = Color.Orange, - Visible = false - }; - lowSkillIndicator.RectTransform.MaxSize = new Point(lowSkillIndicator.Rect.Height); + var healthWindowVerticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One * 0.9f, healthWindow.RectTransform, Anchor.Center)); - string[] healthCircleStyles = new string[] { "HealthCircleInner", "HealthCircleMid", "HealthCircleOuter" }; - foreach (string healthCircleStyle in healthCircleStyles) - { - for (int i = 1; i < 4; i++) - { - var style = GUI.Style.GetComponentStyle(healthCircleStyle + i); - if (style != null) - { - new GUIImage(new RectTransform(Vector2.One, dropItemArea.RectTransform), healthCircleStyle + i) - { - CanBeFocused = false - }; - } - } - } - - new GUIImage(new RectTransform(Vector2.One * 0.2f, dropItemArea.RectTransform, Anchor.Center), "HealthCross") - { - CanBeFocused = false - }; - - healthWindow = new GUIFrame(new RectTransform(new Point(100, 200), GUI.Canvas)); - var paddedHealthWindow = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), healthWindow.RectTransform, Anchor.Center)) + var paddedHealthWindow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.95f), healthWindowVerticalLayout.RectTransform), true) { Stretch = true, RelativeSpacing = 0.03f }; - var nameContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedHealthWindow.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true) - { - Stretch = true - }; - - characterName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) - { - AutoScale = true - }; - new GUICustomComponent(new RectTransform(new Vector2(0.4f, 1.0f), nameContainer.RectTransform), - onDraw: (spriteBatch, component) => - { - character.Info.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), component.Rect.Width); - }); - - new GUICustomComponent(new RectTransform(new Vector2(1.0f, 0.9f), paddedHealthWindow.RectTransform), + var limbSelection = new GUICustomComponent(new RectTransform(new Vector2(0.6f, 1.0f), paddedHealthWindow.RectTransform), (spriteBatch, component) => { DrawHealthWindow(spriteBatch, component.RectTransform.Rect, true, false); @@ -270,24 +294,100 @@ namespace Barotrauma UpdateLimbIndicators(deltaTime, component.RectTransform.Rect); } ); - deadIndicator = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.1f), healthWindow.RectTransform, Anchor.Center), + deadIndicator = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.1f), limbSelection.RectTransform, Anchor.Center), text: TextManager.Get("Deceased"), font: GUI.LargeFont, textAlignment: Alignment.Center, wrap: true, style: "GUIToolTip") { Visible = false, CanBeFocused = false }; - healthWindowHealthBar = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas), - barSize: 1.0f, color: Color.Green, style: "GUIProgressBarVertical") + GUILayoutGroup selectedLimbLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), paddedHealthWindow.RectTransform)); + + selectedLimbText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.08f), selectedLimbLayout.RectTransform), "", font: GUI.LargeFont); + + afflictionIconContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.92f), selectedLimbLayout.RectTransform), style: null); + afflictionIconContainer.KeepSpaceForScrollBar = true; + + var healthBarContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.07f), healthWindowVerticalLayout.RectTransform), style: null); + + var healthBarIcon = new GUIFrame(new RectTransform(new Vector2(0.095f, 1.0f), healthBarContainer.RectTransform), style: "GUIHealthBarIcon"); + + healthWindowHealthBarShadow = new GUIProgressBar(new RectTransform(new Vector2(0.91f, 1.0f), healthBarContainer.RectTransform, Anchor.CenterRight), + barSize: 1.0f, color: GUI.Style.Green, style: "GUIHealthBar") { - IsHorizontal = false + IsHorizontal = true }; - healthWindowHealthBarShadow = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas), - barSize: 1.0f, color: Color.Green, style: "GUIProgressBarVertical") + healthWindowHealthBar = new GUIProgressBar(new RectTransform(new Vector2(0.91f, 1.0f), healthBarContainer.RectTransform, Anchor.CenterRight), + barSize: 1.0f, color: GUI.Style.Green, style: "GUIHealthBar") { - IsHorizontal = false + IsHorizontal = true }; - cprButton = new GUIButton(new RectTransform(new Point((int)(80 * GUI.Scale)), GUI.Canvas), text: "", style: "CPRButton") + + //affliction info frame + afflictionInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.55f, 1.0f), healthInterfaceLayout.RectTransform), style: null); + var paddedInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), afflictionInfoFrame.RectTransform, Anchor.Center), style: null); + + var infoLayout = new GUILayoutGroup(new RectTransform(Vector2.One, paddedInfoFrame.RectTransform)); + + var nameContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), infoLayout.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true) + { + Stretch = true + }; + + new GUICustomComponent(new RectTransform(new Vector2(0.15f, 1.0f), nameContainer.RectTransform), + onDraw: (spriteBatch, component) => + { + character.Info.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), component.Rect.Width); + }); + characterName = new GUITextBlock(new RectTransform(new Vector2(0.85f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) + { + AutoScale = true + }; + + + afflictionInfoContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), infoLayout.RectTransform, Anchor.TopLeft)); + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), infoLayout.RectTransform, Anchor.TopLeft), TextManager.Get("SuitableTreatments"), textAlignment: Alignment.TopLeft); + + treatmentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), infoLayout.RectTransform), true) + { + Stretch = true + }; + + recommendedTreatmentContainer = new GUIListBox(new RectTransform(new Vector2(0.9f, 1.0f), treatmentLayout.RectTransform, Anchor.TopLeft), isHorizontal: true, style: null) + { + KeepSpaceForScrollBar = true + }; + + lowSkillIndicator = new GUIImage(new RectTransform(new Vector2(0.1f, 1.0f), treatmentLayout.RectTransform, Anchor.TopLeft, Pivot.Center), + style: "GUINotificationButton") + { + ToolTip = TextManager.Get("lowmedicalskillwarning"), + Color = GUI.Style.Orange, + HoverColor = Color.Lerp(GUI.Style.Orange, Color.White, 0.5f), + PressedColor = Color.Lerp(GUI.Style.Orange, Color.White, 0.5f), + Visible = false + }; + lowSkillIndicator.RectTransform.MaxSize = new Point(lowSkillIndicator.Rect.Height); + + cprLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), infoLayout.RectTransform), true) + { + Stretch = true + }; + + cprFrame = new GUIFrame(new RectTransform(new Vector2(0.7f, 1.0f), cprLayout.RectTransform), style: "GUIFrameListBox"); + + heartrateFade = TextureLoader.FromFile("Content/UI/Health/HeartrateFade.png"); + + new GUICustomComponent(new RectTransform(Vector2.One * 0.95f, cprFrame.RectTransform, Anchor.Center), DrawHeartrate, UpdateHeartrate); + + heartbeatTimer = 0.46f; + + heartratePositions = new List(); + heartratePositions.Add(heartbeatPattern.First()); + heartratePositions.Add(heartbeatPattern.Last()); + + cprButton = new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), cprLayout.RectTransform, scaleBasis: ScaleBasis.Smallest), text: "", style: "CPRButton") { OnClicked = (button, userData) => { @@ -313,7 +413,7 @@ namespace Barotrauma suicideButton = new GUIButton(new RectTransform(new Vector2(0.06f, 0.02f), GUI.Canvas, Anchor.TopCenter) { MinSize = new Point(120, 20), RelativeOffset = new Vector2(0.0f, 0.01f) }, - TextManager.Get("GiveInButton")) + TextManager.Get("GiveInButton"), style: "GUIButtonLarge") { ToolTip = TextManager.Get(GameMain.NetworkMember == null ? "GiveInHelpSingleplayer" : "GiveInHelpMultiplayer"), OnClicked = (button, userData) => @@ -367,77 +467,22 @@ namespace Barotrauma private void UpdateAlignment() { - healthBar.RectTransform.RelativeOffset = healthBarShadow.RectTransform.RelativeOffset = Vector2.Zero; - healthWindowHealthBar.RectTransform.RelativeOffset = healthWindowHealthBarShadow.RectTransform.RelativeOffset = Vector2.Zero; - - int healthWindowHealthBarWidth = (int)(40 * GUI.Scale); - - if (alignment == Alignment.Left) - { - healthBar.RectTransform.SetPosition(Anchor.BottomLeft); - healthBarShadow.RectTransform.SetPosition(Anchor.BottomLeft); - healthBar.RectTransform.AbsoluteOffset = healthBarShadow.RectTransform.AbsoluteOffset = - new Point(HUDLayoutSettings.HealthBarAreaLeft.X, GameMain.GraphicsHeight - HUDLayoutSettings.HealthBarAreaLeft.Bottom); - healthBar.RectTransform.NonScaledSize = healthBarShadow.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarAreaLeft.Size; - - healthWindow.RectTransform.AbsoluteOffset = HUDLayoutSettings.HealthWindowAreaLeft.Location + new Point(healthWindowHealthBarWidth, 0); - healthWindow.RectTransform.NonScaledSize = new Point( - HUDLayoutSettings.HealthWindowAreaLeft.Width / 3 - healthWindowHealthBarWidth, - HUDLayoutSettings.HealthWindowAreaLeft.Height); - - afflictionInfoFrame.RectTransform.AbsoluteOffset = new Point( - healthWindow.Rect.Right, - HUDLayoutSettings.HealthWindowAreaLeft.Y); - afflictionInfoFrame.RectTransform.NonScaledSize = new Point( - (int)(HUDLayoutSettings.HealthWindowAreaLeft.Width * 0.66f), - (int)(HUDLayoutSettings.HealthWindowAreaLeft.Height)); - - healthWindowHealthBar.RectTransform.NonScaledSize = healthWindowHealthBarShadow.RectTransform.NonScaledSize = - new Point(healthWindowHealthBarWidth, healthWindow.Rect.Height); - healthWindowHealthBar.RectTransform.AbsoluteOffset = healthWindowHealthBarShadow.RectTransform.AbsoluteOffset = - HUDLayoutSettings.HealthWindowAreaLeft.Location; - - int cprButtonSize = (int)(100 * GUI.Scale); - cprButton.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.HealthWindowAreaLeft.Right, dropItemArea.Rect.Center.Y - cprButtonSize / 2); - cprButton.RectTransform.NonScaledSize = new Point(cprButtonSize); - } - else - { - healthBar.RectTransform.SetPosition(Anchor.TopLeft); - healthBarShadow.RectTransform.SetPosition(Anchor.TopLeft); - healthBar.RectTransform.AbsoluteOffset = healthBarShadow.RectTransform.AbsoluteOffset = - HUDLayoutSettings.HealthBarAreaRight.Location; - healthBar.RectTransform.NonScaledSize = healthBarShadow.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarAreaRight.Size; - - healthWindow.RectTransform.AbsoluteOffset = new Point( - HUDLayoutSettings.HealthWindowAreaRight.X + HUDLayoutSettings.HealthWindowAreaRight.Width / 3 * 2, - HUDLayoutSettings.HealthWindowAreaRight.Y); - healthWindow.RectTransform.NonScaledSize = new Point( - HUDLayoutSettings.HealthWindowAreaRight.Width / 3 - healthWindowHealthBarWidth, - HUDLayoutSettings.HealthWindowAreaRight.Height); - - afflictionInfoFrame.RectTransform.AbsoluteOffset = new Point( - HUDLayoutSettings.HealthWindowAreaRight.X, - HUDLayoutSettings.HealthWindowAreaLeft.Y); - afflictionInfoFrame.RectTransform.NonScaledSize = new Point( - (int)(HUDLayoutSettings.HealthWindowAreaLeft.Width * 0.66f), - (int)(HUDLayoutSettings.HealthWindowAreaLeft.Height)); - - healthWindowHealthBar.RectTransform.NonScaledSize = healthWindowHealthBarShadow.RectTransform.NonScaledSize = - new Point(healthWindowHealthBarWidth, healthWindow.Rect.Height); - healthWindowHealthBar.RectTransform.AbsoluteOffset = healthWindowHealthBarShadow.RectTransform.AbsoluteOffset = - new Point(HUDLayoutSettings.HealthWindowAreaRight.Right - healthWindowHealthBarWidth, HUDLayoutSettings.HealthWindowAreaRight.Y); - - int cprButtonSize = (int)(100 * GUI.Scale); - cprButton.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.HealthWindowAreaRight.X - cprButtonSize, dropItemArea.Rect.Center.Y - cprButtonSize / 2); - cprButton.RectTransform.NonScaledSize = new Point(cprButtonSize); - } - - dropItemArea.RectTransform.NonScaledSize = new Point(dropItemArea.Rect.Width); - screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); inventoryScale = Inventory.UIScale; uiScale = GUI.Scale; + + switch (alignment) + { + case Alignment.Left: + healthInterfaceFrame.RectTransform.Anchor = Anchor.CenterLeft; + healthInterfaceFrame.RectTransform.Pivot = Pivot.CenterLeft; + break; + case Alignment.Right: + healthInterfaceFrame.RectTransform.Anchor = Anchor.CenterRight; + healthInterfaceFrame.RectTransform.Pivot = Pivot.CenterRight; + break; + } + healthInterfaceFrame.RectTransform.RecalculateChildren(false); } public void UpdateClientSpecific(float deltaTime) @@ -538,8 +583,6 @@ namespace Barotrauma Math.Max(healthShadowSize - deltaTime, healthBar.BarSize); } - dropItemArea.Visible = !Character.IsDead; - float blurStrength = 0.0f; float distortStrength = 0.0f; float distortSpeed = 0.0f; @@ -607,9 +650,7 @@ namespace Barotrauma } else if (openHealthWindow == this) { - if (Alignment == Alignment.Right ? - HUD.CloseHUD(HUDLayoutSettings.HealthWindowAreaRight) : - HUD.CloseHUD(HUDLayoutSettings.HealthWindowAreaLeft)) + if (HUD.CloseHUD(healthInterfaceFrame.Rect)) { //emulate a Health input to get the character to deselect the item server-side if (GameMain.Client != null) @@ -618,6 +659,34 @@ namespace Barotrauma } OpenHealthWindow = null; } + + if (GUI.MouseOn != null && GUI.MouseOn.UserData is string str && str == "selectaffliction") + { + Affliction affliction = GUI.MouseOn.Parent.UserData as Affliction; + + if (afflictionTooltip == null || afflictionTooltip.UserData != affliction) + { + afflictionTooltip = new GUIListBox(new RectTransform(new Vector2(0.4f, 0.2f), GUI.Canvas, scaleBasis: ScaleBasis.Smallest)); + afflictionTooltip.UserData = affliction; + + afflictionTooltip.CanBeFocused = false; + + CreateAfflictionInfoElements(afflictionTooltip.Content, affliction); + + int height = afflictionTooltip.Content.Children.Sum(c => c.Rect.Height) + 10; + afflictionTooltip.RectTransform.Resize(new Point(afflictionTooltip.Rect.Width, height), true); + afflictionTooltip.RectTransform.AbsoluteOffset = GUI.MouseOn.Rect.Center; + afflictionTooltip.ScrollBarVisible = false; + + var labelContainer = afflictionTooltip.Content.GetChildByUserData("label"); + + labelContainer.RectTransform.Resize(new Point(labelContainer.Rect.Width, (int)(GUI.LargeFont.Size * 1.5f))); + } + } + else + { + afflictionTooltip = null; + } } toggledThisFrame = false; @@ -660,7 +729,7 @@ namespace Barotrauma } else { - healthBar.Color = healthWindowHealthBar.Color = ToolBox.GradientLerp(DisplayedVitality / MaxVitality, Color.Red, Color.Orange, Color.Green); + healthBar.Color = healthWindowHealthBar.Color = ToolBox.GradientLerp(DisplayedVitality / MaxVitality, GUIColorSettings.HealthBarColorLow, GUIColorSettings.HealthBarColorMedium, GUIColorSettings.HealthBarColorHigh); healthBar.HoverColor = healthWindowHealthBar.HoverColor = healthBar.Color * 2.0f; healthBar.BarSize = healthWindowHealthBar.BarSize = (DisplayedVitality > 0.0f) ? @@ -690,41 +759,15 @@ namespace Barotrauma } lowSkillIndicator.Visible = Character.Controlled != null && Character.Controlled.GetSkillLevel("medical") < 50.0f; + lowSkillIndicator.IgnoreLayoutGroups = !lowSkillIndicator.Visible; + + recommendedTreatmentContainer.RectTransform.Resize(new Vector2(0.9f, 1.0f)); + lowSkillIndicator.RectTransform.Resize(new Vector2(0.1f, 1.0f)); + + treatmentLayout.Recalculate(); + lowSkillIndicator.Color = new Color(lowSkillIndicator.Color, MathHelper.Lerp(0.1f, 1.0f, (float)(Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) / 2.0f)); - float rotationSpeed = 0.25f; - int i = 0; - foreach (GUIComponent dropItemIndicator in dropItemArea.Children) - { - GUIImage img = dropItemIndicator as GUIImage; - if (img == null) continue; - - img.State = GUI.MouseOn == dropItemArea ? GUIComponent.ComponentState.Hover : GUIComponent.ComponentState.None; - - byte alpha = img.Color.A; - byte hoverAlpha = img.HoverColor.A; - img.Color = ToolBox.GradientLerp(Vitality / MaxVitality, Color.Red, Color.Orange, Color.Green); - img.Color = new Color(img.Color.R, img.Color.G, img.Color.B, alpha); - img.HoverColor = new Color(img.Color.R, img.Color.G, img.Color.B, hoverAlpha); - img.HoverColor = Color.Lerp(img.HoverColor, Color.White, 0.5f); - - if (img.State == GUIComponent.ComponentState.Hover && droppedItem == null) - { - dropItemAnimTimer = Math.Min(0.3f, dropItemAnimTimer + deltaTime * 0.5f); - } - - if (i < 4) - { - img.Scale = 1.0f - (float)Math.Sin(dropItemAnimTimer / dropItemAnimDuration * MathHelper.TwoPi) * 0.3f; - } - - if (dropItemIndicator == dropItemArea.Children.Last()) break; - img.Rotation = (img.Rotation + (rotationSpeed + dropItemAnimTimer * 10.0f) * deltaTime) % MathHelper.TwoPi; - rotationSpeed = (rotationSpeed + 0.3f) % 1.0f; - - i++; - } - if (Inventory.draggingItem != null) { if (highlightedLimbIndex > -1) @@ -746,12 +789,6 @@ namespace Barotrauma { ShowAfflictionInfo(affliction, afflictionInfoContainer); }*/ - - if (dropItemAnimTimer > 0.0f) - { - dropItemAnimTimer -= deltaTime; - if (dropItemAnimTimer <= 0.0f) droppedItem = null; - } } else { @@ -762,9 +799,7 @@ namespace Barotrauma highlightedLimbIndex = -1; } - Rectangle hoverArea = alignment == Alignment.Left ? - Rectangle.Union(HUDLayoutSettings.AfflictionAreaLeft, HUDLayoutSettings.HealthBarAreaLeft) : - Rectangle.Union(HUDLayoutSettings.AfflictionAreaRight, HUDLayoutSettings.HealthBarAreaRight); + Rectangle hoverArea = Rectangle.Union(HUDLayoutSettings.AfflictionAreaLeft, HUDLayoutSettings.HealthBarAreaLeft); if (Character.AllowInput && UseHealthWindow && Character.SelectedConstruction?.GetComponent()?.User != Character && @@ -788,6 +823,12 @@ namespace Barotrauma && (Character.IsUnconscious || Character.Stun > 0.0f) && !Character.IsDead && openHealthWindow == this; + cprButton.IgnoreLayoutGroups = !cprButton.Visible; + + cprFrame.RectTransform.Resize(new Vector2(0.7f, 1.0f)); + cprButton.RectTransform.Resize(new Vector2(1.0f, 1.0f)); + + cprLayout.Recalculate(); deadIndicator.Visible = Character.IsDead; } @@ -797,11 +838,8 @@ namespace Barotrauma if (GUI.DisableHUD) return; if (OpenHealthWindow == this) { - //afflictionContainer.AddToGUIUpdateList(); - afflictionInfoFrame.AddToGUIUpdateList(); - healthWindow.AddToGUIUpdateList(); - healthWindowHealthBarShadow.AddToGUIUpdateList(); - healthWindowHealthBar.AddToGUIUpdateList(); + healthInterfaceFrame.AddToGUIUpdateList(); + afflictionTooltip?.AddToGUIUpdateList(); } else if (Character.Controlled == Character) { @@ -842,18 +880,7 @@ namespace Barotrauma if (Character.Inventory != null) { - if (Character.Inventory.CurrentLayout == CharacterInventory.Layout.Right) - { - //move the healthbar on top of the inventory slots - healthBar.RectTransform.ScreenSpaceOffset = new Point( - (GameMain.GraphicsWidth - HUDLayoutSettings.Padding) - HUDLayoutSettings.HealthBarAreaRight.Right, - HUDLayoutSettings.HealthBarAreaRight.Y - (int)(Character.Inventory.SlotPositions.Max(s => s.Y) + Inventory.EquipIndicator.size.Y * Inventory.UIScale * 2) - HUDLayoutSettings.HealthBarAreaRight.Height); - healthBarShadow.RectTransform.ScreenSpaceOffset = healthBar.RectTransform.ScreenSpaceOffset; - } - else - { - healthBar.RectTransform.ScreenSpaceOffset = healthBarShadow.RectTransform.ScreenSpaceOffset = Point.Zero; - } + healthBar.RectTransform.ScreenSpaceOffset = healthBarShadow.RectTransform.ScreenSpaceOffset = Point.Zero; } DrawStatusHUD(spriteBatch); @@ -877,7 +904,7 @@ namespace Barotrauma Pair highlightedIcon = null; Vector2 highlightedIconPos = Vector2.Zero; - Rectangle afflictionArea = alignment == Alignment.Left ? HUDLayoutSettings.AfflictionAreaLeft : HUDLayoutSettings.AfflictionAreaRight; + Rectangle afflictionArea = HUDLayoutSettings.AfflictionAreaLeft; Point pos = afflictionArea.Location + healthBar.RectTransform.ScreenSpaceOffset; bool horizontal = afflictionArea.Width > afflictionArea.Height; @@ -885,6 +912,9 @@ namespace Barotrauma foreach (Pair statusIcon in statusIcons) { + Affliction affliction = statusIcon.First; + AfflictionPrefab afflictionPrefab = affliction.Prefab; + Rectangle afflictionIconRect = new Rectangle(pos, new Point(iconSize)); if (afflictionIconRect.Contains(PlayerInput.MousePosition)) { @@ -892,27 +922,30 @@ namespace Barotrauma highlightedIconPos = afflictionIconRect.Center.ToVector2(); } - if (statusIcon.First.DamagePerSecond > 1.0f) + if (affliction.DamagePerSecond > 1.0f) { Rectangle glowRect = afflictionIconRect; glowRect.Inflate((int)(25 * GUI.Scale), (int)(25 * GUI.Scale)); var glow = GUI.Style.GetComponentStyle("OuterGlow"); glow.Sprites[GUIComponent.ComponentState.None][0].Draw( spriteBatch, glowRect, - Color.Red * (float)((Math.Sin(statusIcon.First.DamagePerSecondTimer * MathHelper.TwoPi - MathHelper.PiOver2) + 1.0f) * 0.5f)); + GUI.Style.Red * (float)((Math.Sin(affliction.DamagePerSecondTimer * MathHelper.TwoPi - MathHelper.PiOver2) + 1.0f) * 0.5f)); } - var slot = GUI.Style.GetComponentStyle("AfflictionIconSlot"); + /*var slot = GUI.Style.GetComponentStyle("AfflictionIconSlot"); slot.Sprites[highlightedIcon == statusIcon ? GUIComponent.ComponentState.Hover : GUIComponent.ComponentState.None][0].Draw( spriteBatch, afflictionIconRect, - highlightedIcon == statusIcon ? slot.HoverColor : slot.Color); + highlightedIcon == statusIcon ? slot.HoverColor : slot.Color);*/ - statusIcon.First.Prefab.Icon?.Draw(spriteBatch, + float alphaMultiplier = highlightedIcon == statusIcon ? 1f : 0.8f; + + afflictionPrefab.Icon?.Draw(spriteBatch, pos.ToVector2(), - highlightedIcon == statusIcon ? statusIcon.First.Prefab.IconColor : statusIcon.First.Prefab.IconColor * 0.8f, + /*highlightedIcon == statusIcon ? statusIcon.First.Prefab.IconColor : statusIcon.First.Prefab.IconColor * 0.8f,*/ // OLD IMPLEMENTATION + GetAfflictionIconColor(afflictionPrefab, affliction) * alphaMultiplier, rotate: 0, - scale: iconSize / statusIcon.First.Prefab.Icon.size.X); + scale: iconSize / afflictionPrefab.Icon.size.X); if (horizontal) pos.X += iconSize + (int)(5 * GUI.Scale); @@ -923,7 +956,7 @@ namespace Barotrauma if (highlightedIcon != null) { GUI.DrawString(spriteBatch, - alignment == Alignment.Left ? highlightedIconPos + new Vector2(60 * GUI.Scale, 5) : highlightedIconPos + new Vector2(-10.0f - GUI.Font.MeasureString(highlightedIcon.Second).X, 5), + alignment == Alignment.Left ? highlightedIconPos + new Vector2(60 * GUI.Scale, 5) : highlightedIconPos + new Vector2(-iconSize / 2, iconSize / 2), highlightedIcon.Second, Color.White * 0.8f, Color.Black * 0.5f); } @@ -933,7 +966,7 @@ namespace Barotrauma float currHealth = healthBar.BarSize; Color prevColor = healthBar.Color; healthBarShadow.BarSize = healthShadowSize; - healthBarShadow.Color = Color.Red; + healthBarShadow.Color = GUI.Style.Red; healthBarShadow.Visible = true; healthBar.BarSize = currHealth; healthBar.Color = prevColor; @@ -950,7 +983,7 @@ namespace Barotrauma float currHealth = healthWindowHealthBar.BarSize; Color prevColor = healthWindowHealthBar.Color; healthWindowHealthBarShadow.BarSize = healthShadowSize; - healthWindowHealthBarShadow.Color = Color.Red; + healthWindowHealthBarShadow.Color = GUI.Style.Red; healthWindowHealthBarShadow.Visible = true; healthWindowHealthBar.BarSize = currHealth; healthWindowHealthBar.Color = prevColor; @@ -962,17 +995,37 @@ namespace Barotrauma } } + private Color GetAfflictionIconColor(AfflictionPrefab prefab, Affliction affliction) + { + // No specific colors, use generic + if (prefab.IconColors == null) + { + if (prefab.IsBuff) + { + return ToolBox.GradientLerp(affliction.Strength / prefab.MaxStrength, GUIColorSettings.BuffColorLow, GUIColorSettings.BuffColorMedium, GUIColorSettings.BuffColorHigh); + } + else + { + return ToolBox.GradientLerp(affliction.Strength / prefab.MaxStrength, GUIColorSettings.DebuffColorLow, GUIColorSettings.DebuffColorMedium, GUIColorSettings.DebuffColorHigh); + } + } + else + { + return ToolBox.GradientLerp(affliction.Strength / prefab.MaxStrength, prefab.IconColors); + } + } + private void UpdateAfflictionContainer(LimbHealth selectedLimb) { - ((GUITextBlock)afflictionInfoContainer.Parent.GetChildByUserData("selectedlimbname")).Text = selectedLimb == null ? "" : selectedLimb.Name; + selectedLimbText.Text = selectedLimb == null ? "" : selectedLimb.Name; if (selectedLimb == null) { - afflictionInfoContainer.Content.ClearChildren(); + afflictionIconContainer.Content.ClearChildren(); return; } var currentAfflictions = GetMatchingAfflictions(selectedLimb, a => a.Strength >= a.Prefab.ShowIconThreshold); - var displayedAfflictions = afflictionInfoContainer.Content.Children.Select(c => c.UserData as Affliction); + var displayedAfflictions = afflictionIconContainer.Content.Children.Select(c => c.UserData as Affliction); if (currentAfflictions.Any(a => !displayedAfflictions.Contains(a)) || displayedAfflictions.Any(a => !currentAfflictions.Contains(a))) { @@ -984,7 +1037,9 @@ namespace Barotrauma private void CreateAfflictionInfos(IEnumerable afflictions) { - afflictionInfoContainer.Content.ClearChildren(); + afflictionIconContainer.ClearChildren(); + afflictionInfoContainer.ClearChildren(); + afflictionInfoContainer.UserData = null; recommendedTreatmentContainer.Content.ClearChildren(); float characterSkillLevel = Character.Controlled == null ? 0.0f : Character.Controlled.GetSkillLevel("medical"); @@ -1000,72 +1055,62 @@ namespace Barotrauma foreach (Affliction affliction in afflictions) { - var child = new GUILayoutGroup(new RectTransform(Vector2.One * 0.95f, afflictionInfoContainer.Content.RectTransform, Anchor.TopCenter)) + var child = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), afflictionIconContainer.Content.RectTransform, Anchor.TopCenter)) { - Stretch = true, - RelativeSpacing = 0.02f, UserData = affliction }; - var headerContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), child.RectTransform), isHorizontal: true) + var button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.9f), child.RectTransform), style: null) { - Stretch = true, - UserData = "header" + Color = Color.Gray.Multiply(0.1f), + HoverColor = Color.Gray.Multiply(0.4f), + SelectedColor = Color.Gray.Multiply(0.25f), + PressedColor = Color.Black, + UserData = "selectaffliction", + OnClicked = SelectAffliction }; - new GUIImage(new RectTransform(new Vector2(0.15f, 1.0f), headerContainer.RectTransform), affliction.Prefab.Icon, scaleToFit: true) + new GUIImage(new RectTransform(Vector2.One * 0.9f, button.RectTransform, Anchor.Center), affliction.Prefab.Icon, scaleToFit: true) { - Color = affliction.Prefab.IconColor + Color = GetAfflictionIconColor(affliction.Prefab, affliction), + CanBeFocused = false }; - var labelContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), headerContainer.RectTransform), isHorizontal: true) - { - Stretch = true, - AbsoluteSpacing = 10, - UserData = "label" - }; - var afflictionName = new GUITextBlock(new RectTransform(new Vector2(0.65f, 1.0f), labelContainer.RectTransform), affliction.Prefab.Name, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont); - var afflictionStrength = new GUITextBlock(new RectTransform(new Vector2(0.35f, 0.6f), labelContainer.RectTransform), "", textAlignment: Alignment.TopRight, font: GUI.LargeFont) - { - Padding = Vector4.Zero, - UserData = "strength" - }; - var vitality = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), labelContainer.RectTransform, Anchor.BottomRight), "", textAlignment: Alignment.BottomRight) - { - IgnoreLayoutGroups = true, - UserData = "vitality" - }; + float afflictionVitalityDecrease = affliction.GetVitalityDecrease(this); - var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), child.RectTransform), - affliction.Prefab.Description, textAlignment: Alignment.TopLeft, wrap: true); - if (description.Font.MeasureString(description.WrappedText).Y > description.Rect.Height) + Color afflictionEffectColor = Color.White; + if (afflictionVitalityDecrease > 0.0f) { - description.Font = GUI.SmallFont; + afflictionEffectColor = GUI.Style.Red; } - description.RectTransform.Resize(new Point(description.Rect.Width, (int)(description.TextSize.Y + 10))); - child.RectTransform.Resize(new Point(child.Rect.Width, child.Children.Sum(c => c.Rect.Height))); + else if (afflictionVitalityDecrease < 0.0f) + { + afflictionEffectColor = GUI.Style.Green; + } + + new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.1f), child.RectTransform), 0.0f, afflictionEffectColor) + { + UserData = "afflictionstrength" + }; + child.Recalculate(); - headerContainer.Recalculate(); - labelContainer.Recalculate(); - afflictionStrength.AutoScale = true; - afflictionName.AutoScale = true; - vitality.AutoDraw = true; } + afflictionIconContainer.RecalculateChildren(); + List> treatmentSuitabilities = treatmentSuitability.OrderByDescending(t => t.Value).ToList(); foreach (KeyValuePair treatment in treatmentSuitabilities) { ItemPrefab item = MapEntityPrefab.Find(name: null, identifier: treatment.Key, showErrorMessages: false) as ItemPrefab; if (item == null) continue; - int slotSize = (int)(recommendedTreatmentContainer.Content.Rect.Width * 0.5f); - var itemSlot = new GUIFrame(new RectTransform(new Point(recommendedTreatmentContainer.Content.Rect.Width, slotSize), recommendedTreatmentContainer.Content.RectTransform, Anchor.TopCenter), + var itemSlot = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), recommendedTreatmentContainer.Content.RectTransform, Anchor.TopLeft), style: "InnerGlow") { UserData = item }; - itemSlot.Color = ToolBox.GradientLerp(treatment.Value, Color.Red, Color.Orange, Color.LightGreen); + itemSlot.Color = ToolBox.GradientLerp(treatment.Value, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green); itemSlot.SelectedColor = itemSlot.HoverColor = itemSlot.Color; Sprite itemSprite = item.InventoryIcon ?? item.sprite; @@ -1081,7 +1126,9 @@ namespace Barotrauma itemSlot.ToolTip = item.Name; } - afflictionInfoContainer.Content.RectTransform.SortChildren((r1, r2) => + recommendedTreatmentContainer.RecalculateChildren(); + + afflictionIconContainer.Content.RectTransform.SortChildren((r1, r2) => { var first = r1.GUIComponent.UserData as Affliction; var second = r2.GUIComponent.UserData as Affliction; @@ -1089,44 +1136,271 @@ namespace Barotrauma return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(second.Strength - first.Strength); }); - //afflictionInfoContainer.Content.RectTransform.SortChildren((r1, r2) => + //afflictionIconContainer.Content.RectTransform.SortChildren((r1, r2) => //{ // return Math.Sign(((Affliction)r2.GUIComponent.UserData).GetVitalityDecrease(this) - ((Affliction)r1.GUIComponent.UserData).GetVitalityDecrease(this)); //}); } + private void CreateAfflictionInfoElements(GUIComponent parent, Affliction affliction) + { + var labelContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), parent.RectTransform), isHorizontal: true) + { + Stretch = true, + AbsoluteSpacing = 10, + UserData = "label", + CanBeFocused = false + }; + + var afflictionName = new GUITextBlock(new RectTransform(new Vector2(0.65f, 1.0f), labelContainer.RectTransform), affliction.Prefab.Name, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) + { + CanBeFocused = false + }; + var afflictionStrength = new GUITextBlock(new RectTransform(new Vector2(0.35f, 0.6f), labelContainer.RectTransform), "", textAlignment: Alignment.TopRight, font: GUI.LargeFont) + { + Padding = Vector4.Zero, + UserData = "strength", + CanBeFocused = false + }; + var vitality = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), labelContainer.RectTransform, Anchor.BottomRight), "", textAlignment: Alignment.BottomRight) + { + IgnoreLayoutGroups = true, + UserData = "vitality", + CanBeFocused = false + }; + + var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), parent.RectTransform), + affliction.Prefab.Description, textAlignment: Alignment.TopLeft, wrap: true) + { + CanBeFocused = false + }; + + if (description.Font.MeasureString(description.WrappedText).Y > description.Rect.Height) + { + description.Font = GUI.SmallFont; + } + + Point nameDims = new Point(afflictionName.Rect.Width, (int)(GUI.LargeFont.Size * 1.5f)); + + labelContainer.RectTransform.Resize(new Point(labelContainer.Rect.Width, nameDims.Y)); + afflictionName.RectTransform.Resize(nameDims); + afflictionStrength.RectTransform.Resize(new Point(afflictionStrength.Rect.Width, nameDims.Y)); + + afflictionStrength.Text = strengthTexts[ + MathHelper.Clamp((int)Math.Floor((affliction.Strength / affliction.Prefab.MaxStrength) * strengthTexts.Length), 0, strengthTexts.Length - 1)]; + + afflictionStrength.TextColor = Color.Lerp(GUI.Style.Orange, GUI.Style.Red, + affliction.Strength / affliction.Prefab.MaxStrength); + + description.RectTransform.Resize(new Point(description.Rect.Width, (int)(description.TextSize.Y + 10))); + //labelContainer.Recalculate(); + + int vitalityDecrease = (int)affliction.GetVitalityDecrease(this); + if (vitalityDecrease == 0) + { + vitality.Visible = false; + } + else + { + vitality.Visible = true; + vitality.Text = TextManager.Get("Vitality") + " -" + vitalityDecrease; + vitality.TextColor = vitalityDecrease <= 0 ? GUI.Style.Green : + Color.Lerp(GUI.Style.Orange, GUI.Style.Red, affliction.Strength / affliction.Prefab.MaxStrength); + } + + vitality.AutoDraw = true; + } + + private bool SelectAffliction(GUIButton button, object userData) + { + Affliction affliction = button.Parent.UserData as Affliction; + + bool selected = button.Selected; + + afflictionInfoContainer.UserData = null; + afflictionInfoContainer.ClearChildren(); + if (!selected) + { + afflictionInfoContainer.UserData = affliction; + + CreateAfflictionInfoElements(afflictionInfoContainer.Content, affliction); + + afflictionInfoContainer.RecalculateChildren(); + } + + foreach (var child in afflictionIconContainer.Content.Children) + { + GUIButton btn = child.GetChild(); + if (btn != null) + { + btn.Selected = btn == button && !selected; + } + } + + return false; + } + + private void UpdateHeartrate(float deltaTime, GUICustomComponent component) + { + heartbeatTimer -= deltaTime; + + if (heartbeatTimer <= 0.0f) + { + heartbeatTimer = 0.5f; + + IEnumerable newPositions; + if (Character == null || Character.IsDead || Character.IsUnconscious) + { + newPositions = Enumerable.Repeat(new HeartratePosition { Time = currentHeartrateTime, Height = 0.0f }, 1); + } + else + { + newPositions = HeartratePosition.ScaleAndDisplace(heartbeatPattern, 1.0f, 0.1f, currentHeartrateTime); + } + + float visibleRangeStart = currentHeartrateTime - 0.35f; + if (visibleRangeStart < 0.0f) + { + visibleRangeStart += 1.0f; + } + heartratePositions.RemoveAll(hp => (hp.Time < visibleRangeStart || hp.Time > currentHeartrateTime) && + ((hp.Time < visibleRangeStart && hp.Time > currentHeartrateTime) || visibleRangeStart < currentHeartrateTime)); + + heartratePositions.AddRange(newPositions); + + if (!heartratePositions.Any(hp => hp.Time >= 1.0f)) + { + heartratePositions.Add(new HeartratePosition { Time = 1.0f, Height = 0.0f }); + } + if (!heartratePositions.Any(hp => hp.Time <= 0.0f)) + { + heartratePositions.Add(new HeartratePosition { Time = 0.0f, Height = 0.0f }); + } + } + + currentHeartrateTime += deltaTime; + while (currentHeartrateTime >= 1.0f) + { + currentHeartrateTime -= 1.0f; + } + } + + private void DrawHeartrate(SpriteBatch spriteBatch, GUICustomComponent component) + { + GUI.DrawRectangle(spriteBatch, component.Rect, Color.Black, true); + + bool first = true; + Vector2 prevPos = Vector2.Zero; + foreach (var heartratePosition in heartratePositions.OrderBy(hp => hp.Time)) + { + Vector2 pos = new Vector2(heartratePosition.Time, -heartratePosition.Height * 0.5f + 0.5f) * component.Rect.Size.ToVector2() + component.Rect.Location.ToVector2(); + + if (pos.X < component.Rect.Left + 1) { pos.X = component.Rect.Left + 1; } + if (pos.X > component.Rect.Right - 1) { pos.X = component.Rect.Right - 1; } + + if (first) + { + first = false; + } + else + { + int thickness = (int)(GUI.Scale * 2.5f); + if (thickness < 1) { thickness = 1; } + GUI.DrawLine(spriteBatch, prevPos, pos, Color.Lime, 0, thickness); + GUI.DrawLine(spriteBatch, prevPos + new Vector2(0.0f, 1.0f), pos + new Vector2(0.0f, 1.0f), Color.Lime * 0.5f, 0, thickness); + GUI.DrawLine(spriteBatch, prevPos - new Vector2(0.0f, 1.0f), pos - new Vector2(0.0f, 1.0f), Color.Lime * 0.5f, 0, thickness); + } + + prevPos = pos; + } + + Rectangle sourceRect = heartrateFade.Bounds; + + Rectangle destinationRectangle = new Rectangle(); + destinationRectangle.Location = new Point((int)(currentHeartrateTime * component.Rect.Width) + component.Rect.Left - component.Rect.Height, component.Rect.Top); + destinationRectangle.Size = new Point((int)(component.Rect.Height * ((float)sourceRect.Width / (float)sourceRect.Height)), component.Rect.Height); + + if (destinationRectangle.Left < component.Rect.Left) + { + Rectangle destinationRectangle2 = new Rectangle(); + destinationRectangle2.Location = new Point(component.Rect.Right - (component.Rect.Left - destinationRectangle.Left), component.Rect.Top); + destinationRectangle2.Size = new Point(component.Rect.Right - destinationRectangle2.Left, component.Rect.Height); + + int originalWidth = sourceRect.Width; + sourceRect.Width = (int)(sourceRect.Width * ((float)(destinationRectangle.Right - component.Rect.Left) / (float)component.Rect.Height)); + sourceRect.X += originalWidth - sourceRect.Width; + + Rectangle sourceRect2 = heartrateFade.Bounds; + sourceRect2.Width -= sourceRect.Width; + spriteBatch.Draw(heartrateFade, destinationRectangle2, sourceRect2, Color.White); + + originalWidth = destinationRectangle.Width; + int newWidth = destinationRectangle.Right - component.Rect.Left; + + destinationRectangle.Size = new Point(newWidth, component.Rect.Height); + destinationRectangle.X += originalWidth - newWidth; + + GUI.DrawRectangle(spriteBatch, new Rectangle(destinationRectangle.Right, destinationRectangle.Top, + destinationRectangle2.Left - destinationRectangle.Right, destinationRectangle2.Height), Color.Black, true); + } + else + { + GUI.DrawRectangle(spriteBatch, new Rectangle(destinationRectangle.Right, destinationRectangle.Top, + component.Rect.Right - destinationRectangle.Right, destinationRectangle.Height), Color.Black, true); + GUI.DrawRectangle(spriteBatch, new Rectangle(component.Rect.Left, destinationRectangle.Top, + destinationRectangle.Left - component.Rect.Left, destinationRectangle.Height), Color.Black, true); + } + + spriteBatch.Draw(heartrateFade, destinationRectangle, sourceRect, Color.White); + } + private void UpdateAfflictionInfos(IEnumerable afflictions) { foreach (Affliction affliction in afflictions) { - var child = afflictionInfoContainer.Content.FindChild(affliction); - var headerContainer = child.GetChildByUserData("header"); - var labelContainer = headerContainer.GetChildByUserData("label"); - var strengthText = labelContainer.GetChildByUserData("strength") as GUITextBlock; + var child = afflictionIconContainer.Content.FindChild(affliction); + var afflictionStrengthBar = child.GetChildByUserData("afflictionstrength") as GUIProgressBar; + afflictionStrengthBar.BarSize = affliction.Strength / affliction.Prefab.MaxStrength; - strengthText.Text = strengthTexts[ - MathHelper.Clamp((int)Math.Floor((affliction.Strength / affliction.Prefab.MaxStrength) * strengthTexts.Length), 0, strengthTexts.Length - 1)]; - - strengthText.TextColor = ToolBox.GradientLerp( - affliction.Strength / affliction.Prefab.MaxStrength, - Color.Yellow, Color.Orange, Color.Red); - - var vitalityText = labelContainer.GetChildByUserData("vitality") as GUITextBlock; - int vitalityDecrease = (int)affliction.GetVitalityDecrease(this); - if (vitalityDecrease == 0) + if (afflictionInfoContainer.UserData == affliction) { - vitalityText.Visible = false; + UpdateAfflictionInfo(afflictionInfoContainer.Content, affliction); } - else + + if (afflictionTooltip != null && afflictionTooltip.UserData == affliction) { - vitalityText.Visible = true; - vitalityText.Text = TextManager.Get("Vitality") + " -" + vitalityDecrease; - vitalityText.TextColor = vitalityDecrease <= 0 ? Color.LightGreen : - Color.Lerp(Color.Orange, Color.Red, affliction.Strength / affliction.Prefab.MaxStrength); + UpdateAfflictionInfo(afflictionTooltip.Content, affliction); } } } + private void UpdateAfflictionInfo(GUIComponent parent, Affliction affliction) + { + var labelContainer = parent.GetChildByUserData("label"); + + var strengthText = labelContainer.GetChildByUserData("strength") as GUITextBlock; + + strengthText.Text = strengthTexts[ + MathHelper.Clamp((int)Math.Floor((affliction.Strength / affliction.Prefab.MaxStrength) * strengthTexts.Length), 0, strengthTexts.Length - 1)]; + + strengthText.TextColor = Color.Lerp(GUI.Style.Orange, GUI.Style.Red, + affliction.Strength / affliction.Prefab.MaxStrength); + + var vitalityText = labelContainer.GetChildByUserData("vitality") as GUITextBlock; + int vitalityDecrease = (int)affliction.GetVitalityDecrease(this); + if (vitalityDecrease == 0) + { + vitalityText.Visible = false; + } + else + { + vitalityText.Visible = true; + vitalityText.Text = TextManager.Get("Vitality") + " -" + vitalityDecrease; + vitalityText.TextColor = vitalityDecrease <= 0 ? GUI.Style.Green : + Color.Lerp(GUI.Style.Orange, GUI.Style.Red, affliction.Strength / affliction.Prefab.MaxStrength); + } + } + public bool OnItemDropped(Item item, bool ignoreMousePos) { //items can be dropped outside the health window @@ -1146,18 +1420,12 @@ namespace Barotrauma { selectedLimbIndex = highlightedLimbIndex; } - else if (!dropItemArea.Rect.Contains(PlayerInput.MousePosition)) - { - return true; - } } Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex); item.ApplyTreatment(Character.Controlled, Character, targetLimb); - dropItemAnimTimer = dropItemAnimDuration; - droppedItem = item; return true; } @@ -1222,7 +1490,9 @@ namespace Barotrauma { selectedLimbIndex = highlightedLimbIndex; //afflictionContainer.ClearChildren(); + afflictionIconContainer.ClearChildren(); afflictionInfoContainer.ClearChildren(); + afflictionInfoContainer.UserData = null; } } @@ -1230,30 +1500,92 @@ namespace Barotrauma { if (Character.Removed) { return; } + spriteBatch.End(); + spriteBatch.Begin(SpriteSortMode.Immediate, blendState: BlendState.NonPremultiplied, rasterizerState: GameMain.ScissorTestEnable, effect: GameMain.GameScreen.GradientEffect); + int i = 0; foreach (LimbHealth limbHealth in limbHealths) { if (limbHealth.IndicatorSprite == null) continue; - float damageLerp = limbHealth.TotalDamage > 0.0f ? MathHelper.Lerp(0.2f, 1.0f, limbHealth.TotalDamage / 100.0f) : 0.0f; - Color color = Character.IsDead ? - Color.Lerp(Color.Black, new Color(150, 100, 100), damageLerp) : - ToolBox.GradientLerp(damageLerp, Color.Green, Color.Orange, Color.Red); - float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height); + Rectangle limbEffectiveArea = new Rectangle(limbHealth.IndicatorSprite.SourceRect.X + limbHealth.HighlightArea.X, + limbHealth.IndicatorSprite.SourceRect.Y + limbHealth.HighlightArea.Y, + limbHealth.HighlightArea.Width, + limbHealth.HighlightArea.Height); - if (((i == highlightedLimbIndex || i == selectedLimbIndex) && allowHighlight) || highlightAll) + float damageLerp = limbHealth.TotalDamage > 0.0f ? MathHelper.Lerp(0.2f, 1.0f, limbHealth.TotalDamage / 100.0f) : 0.0f; + + var tempAfflictions = limbHealth.Afflictions.ToList(); + foreach (var a in afflictions) { - color = Color.Lerp(color, Color.White, 0.5f); + Limb indicatorLimb = Character.AnimController.GetLimb(a.Prefab.IndicatorLimb); + if (indicatorLimb != null && indicatorLimb.HealthIndex == i) + { + tempAfflictions.Add(a); + } } + float negativeEffect = tempAfflictions.Where(a => !a.Prefab.IsBuff).Sum(a => a.Strength); + float positiveEffect = tempAfflictions.Where(a => a.Prefab.IsBuff).Sum(a => a.Strength); + + float midPoint = (float)limbEffectiveArea.Center.Y / (float)limbHealth.IndicatorSprite.Texture.Height; + float fadeDist = 0.6f * (float)limbEffectiveArea.Height / (float)limbHealth.IndicatorSprite.Texture.Height; + + Color color1 = Color.Orange; + Color color2 = Color.Orange; + + if (positiveEffect > 0.0f && negativeEffect > 0.0f) + { + color1 = Color.Lime; + color2 = Color.Red; + } + else if (positiveEffect > 0.0f) + { + color1 = Color.Lime; + color2 = Color.Lime; + } + else if (negativeEffect > 0.0f) + { + color1 = Color.Red; + color2 = Color.Red; + } + + if (Character.IsDead) + { + color1 = Color.Lerp(color1, Color.Black, 0.5f); + color2 = Color.Lerp(color2, Color.Black, 0.5f); + } + if (((i == highlightedLimbIndex || i == selectedLimbIndex) && allowHighlight) || highlightAll) + { + color1 = Color.Lerp(color1, Color.White, 0.5f); + color2 = Color.Lerp(color2, Color.White, 0.5f); + } + + GameMain.GameScreen.GradientEffect.Parameters["color1"].SetValue(color1.ToVector4()); + GameMain.GameScreen.GradientEffect.Parameters["color2"].SetValue(color2.ToVector4()); + GameMain.GameScreen.GradientEffect.Parameters["midPoint"].SetValue(midPoint); + GameMain.GameScreen.GradientEffect.Parameters["fadeDist"].SetValue(fadeDist); + + float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height); + limbHealth.IndicatorSprite.Draw(spriteBatch, - drawArea.Center.ToVector2(), color, + drawArea.Center.ToVector2(), Color.White, limbHealth.IndicatorSprite.Origin, 0, scale); + + if (GameMain.DebugDraw) + { + Rectangle highlightArea = GetLimbHighlightArea(limbHealth, drawArea); + + GUI.DrawRectangle(spriteBatch, highlightArea, Color.Red, false); + GUI.DrawRectangle(spriteBatch, drawArea, Color.Red, false); + } + i++; } spriteBatch.End(); + spriteBatch.Begin(SpriteSortMode.Deferred, Lights.CustomBlendStates.Multiplicative); float overlayScale = Math.Min( @@ -1278,38 +1610,17 @@ namespace Barotrauma spriteBatch.End(); spriteBatch.Begin(SpriteSortMode.Deferred, blendState: BlendState.NonPremultiplied, rasterizerState: GameMain.ScissorTestEnable); - i = 0; + /*i = 0; foreach (LimbHealth limbHealth in limbHealths) { if (limbHealth.IndicatorSprite == null) continue; - float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height); - Rectangle highlightArea = new Rectangle( - (int)(drawArea.Center.X - (limbHealth.IndicatorSprite.Texture.Width / 2 - limbHealth.HighlightArea.X) * scale), - (int)(drawArea.Center.Y - (limbHealth.IndicatorSprite.Texture.Height / 2 - limbHealth.HighlightArea.Y) * scale), - (int)(limbHealth.HighlightArea.Width * scale), - (int)(limbHealth.HighlightArea.Height * scale)); - - if (selectedLimbIndex == i) - { - if (alignment == Alignment.Left) - { - GUI.DrawLine(spriteBatch, - highlightArea.Center.ToVector2(), - afflictionInfoContainer.Parent.Rect.Location.ToVector2() + Vector2.UnitY * 20, - Color.LightBlue * 0.3f, 0, 4); - } - else - { - GUI.DrawLine(spriteBatch, - highlightArea.Center.ToVector2(), - new Vector2(afflictionInfoContainer.Parent.Rect.Right, afflictionInfoContainer.Parent.Rect.Y + 20), - Color.LightBlue * 0.3f, 0, 4); - } - } + Rectangle highlightArea = GetLimbHighlightArea(limbHealth, drawArea); var slot = GUI.Style.GetComponentStyle("AfflictionIconSlot"); + float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height); + float iconScale = 0.3f * scale; Vector2 iconPos = highlightArea.Center.ToVector2(); foreach (Affliction affliction in limbHealth.Afflictions) @@ -1326,7 +1637,7 @@ namespace Barotrauma } } i++; - } + }*/ if (draggingMed != null) { @@ -1334,15 +1645,6 @@ namespace Barotrauma float scale = Math.Min(40.0f / itemImage.Sprite.size.X, 40.0f / itemImage.Sprite.size.Y); itemImage.Sprite.Draw(spriteBatch, PlayerInput.MousePosition, itemImage.Color, 0, scale); } - - if (dropItemAnimTimer > 0.0f && droppedItem?.Prefab.InventoryIcon != null) - { - var droppedItemSprite = droppedItem.Prefab.InventoryIcon ?? droppedItem.Sprite; - droppedItemSprite.Draw(spriteBatch, dropItemArea.Rect.Center.ToVector2(), - droppedItemSprite == droppedItem.Sprite ? droppedItem.GetSpriteColor() : droppedItem.GetInventoryIconColor(), - origin: droppedItemSprite.size / 2, - scale: MathHelper.SmoothStep(0.0f, 100.0f / droppedItemSprite.size.Length(), dropItemAnimTimer / dropItemAnimDuration)); - } } private void DrawLimbAfflictionIcon(SpriteBatch spriteBatch, Affliction affliction, GUIComponentStyle slotStyle, float iconScale, ref Vector2 iconPos) @@ -1358,7 +1660,7 @@ namespace Barotrauma spriteBatch, new Rectangle((iconPos - iconSize / 2.0f).ToPoint(), iconSize.ToPoint()), slotStyle.Color * alpha); - affliction.Prefab.Icon.Draw(spriteBatch, iconPos - iconSize / 2.0f, affliction.Prefab.IconColor * alpha, 0, iconScale); + affliction.Prefab.Icon.Draw(spriteBatch, iconPos - iconSize / 2.0f, GetAfflictionIconColor(affliction.Prefab, affliction) * alpha, 0, iconScale); iconPos += new Vector2(10.0f, 20.0f) * iconScale; } @@ -1366,8 +1668,8 @@ namespace Barotrauma { float scale = Math.Min(drawArea.Width / (float)limbHealth.IndicatorSprite.SourceRect.Width, drawArea.Height / (float)limbHealth.IndicatorSprite.SourceRect.Height); return new Rectangle( - (int)(drawArea.Center.X - (limbHealth.IndicatorSprite.Texture.Width / 2 - limbHealth.HighlightArea.X) * scale), - (int)(drawArea.Center.Y - (limbHealth.IndicatorSprite.Texture.Height / 2 - limbHealth.HighlightArea.Y) * scale), + (int)(drawArea.Center.X - (limbHealth.IndicatorSprite.SourceRect.Width / 2 - limbHealth.HighlightArea.X) * scale), + (int)(drawArea.Center.Y - (limbHealth.IndicatorSprite.SourceRect.Height / 2 - limbHealth.HighlightArea.Y) * scale), (int)(limbHealth.HighlightArea.Width * scale), (int)(limbHealth.HighlightArea.Height * scale)); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Jobs/JobPrefab.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Jobs/JobPrefab.cs index dd74bf731..d07677347 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Jobs/JobPrefab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Jobs/JobPrefab.cs @@ -1,6 +1,8 @@ using Microsoft.Xna.Framework; using System.Linq; using System; +using System.Xml.Linq; +using System.Collections.Generic; namespace Barotrauma { @@ -8,7 +10,7 @@ namespace Barotrauma { public GUIButton CreateInfoFrame(int variant) { - int width = 500, height = 400; + int width = 500, height = 450; GUIButton backFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker"); GUIFrame frame = new GUIFrame(new RectTransform(new Point(width, height), backFrame.RectTransform, Anchor.Center)); @@ -48,5 +50,75 @@ namespace Barotrauma return backFrame; } + + + public class OutfitPreview + { + /// + /// Pair.First = sprite, Pair.Second = draw offset + /// + public readonly List> Sprites; + public Vector2 Dimensions; + + public OutfitPreview() + { + Sprites = new List>(); + Dimensions = Vector2.One; + } + + public void AddSprite(Sprite sprite, Vector2 drawOffset) + { + Sprites.Add(new Pair(sprite, drawOffset)); + } + } + + public List GetJobOutfitSprites(Gender gender, bool useInventoryIcon, out Vector2 maxDimensions) + { + List outfitPreviews = new List(); + maxDimensions = Vector2.One; + + var equipIdentifiers = Element.GetChildElements("ItemSet").Elements().Where(e => e.GetAttributeBool("outfit", false)).Select(e => e.GetAttributeString("identifier", "")); + + var outfitPrefabs = ItemPrefab.Prefabs.Where(itemPrefab => equipIdentifiers.Contains(itemPrefab.Identifier)).ToList(); + if (!outfitPrefabs.Any()) { return null; } + + for (int i = 0; i < outfitPrefabs.Count; i++) + { + var outfitPreview = new OutfitPreview(); + + if (!ItemSets.TryGetValue(i, out var itemSetElement)) { continue; } + var previewElement = itemSetElement.GetChildElement("PreviewSprites"); + if (previewElement == null || useInventoryIcon) + { + if (outfitPrefabs[i] is ItemPrefab prefab && prefab.InventoryIcon != null) + { + outfitPreview.AddSprite(prefab.InventoryIcon, Vector2.Zero); + outfitPreview.Dimensions = prefab.InventoryIcon.SourceRect.Size.ToVector2(); + maxDimensions.X = MathHelper.Max(maxDimensions.X, outfitPreview.Dimensions.X); + maxDimensions.Y = MathHelper.Max(maxDimensions.Y, outfitPreview.Dimensions.Y); + } + outfitPreviews.Add(outfitPreview); + continue; + } + + var children = previewElement.Elements().ToList(); + for (int n = 0; n < children.Count; n++) + { + XElement spriteElement = children[n]; + string spriteTexture = spriteElement.GetAttributeString("texture", "").Replace("[GENDER]", (gender == Gender.Female) ? "female" : "male"); + var sprite = new Sprite(spriteElement, file: spriteTexture); + sprite.size = new Vector2(sprite.SourceRect.Width, sprite.SourceRect.Height); + outfitPreview.AddSprite(sprite, children[n].GetAttributeVector2("offset", Vector2.Zero)); + } + + outfitPreview.Dimensions = previewElement.GetAttributeVector2("dims", Vector2.One); + maxDimensions.X = MathHelper.Max(maxDimensions.X, outfitPreview.Dimensions.X); + maxDimensions.Y = MathHelper.Max(maxDimensions.Y, outfitPreview.Dimensions.Y); + + outfitPreviews.Add(outfitPreview); + } + + return outfitPreviews; + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Limb.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Limb.cs index 6b8d43bc1..021685c5d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Limb.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Limb.cs @@ -81,7 +81,7 @@ namespace Barotrauma //{ // var pos = ConvertUnits.ToDisplayUnits(mouthPos.Value); // pos.Y = -pos.Y; - // ShapeExtensions.DrawPoint(spriteBatch, pos, Color.Red, size: 5); + // ShapeExtensions.DrawPoint(spriteBatch, pos, GUI.Style.Red, size: 5); //} return; // A debug visualisation on the bezier curve between limbs. @@ -98,7 +98,7 @@ namespace Barotrauma //GUI.DrawLine(spriteBatch, start, end, Color.White); //GUI.DrawLine(spriteBatch, start, control, Color.Black); //GUI.DrawLine(spriteBatch, control, end, Color.Black); - GUI.DrawBezierWithDots(spriteBatch, start, end, control, 1000, Color.Red); + GUI.DrawBezierWithDots(spriteBatch, start, end, control, 1000, GUI.Style.Red); } } @@ -433,14 +433,17 @@ namespace Barotrauma SoundPlayer.PlayDamageSound(damageSoundType, Math.Max(damage, bleedingDamage), WorldPosition); } - // Always spawn damage particles + // spawn damage particles float damageParticleAmount = Math.Min(damage / 10, 1.0f) * damageMultiplier; - foreach (ParticleEmitter emitter in character.DamageEmitters) + if (damageParticleAmount > 0.001f) { - if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) continue; - if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) continue; + foreach (ParticleEmitter emitter in character.DamageEmitters) + { + if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) continue; + if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) continue; - emitter.Emit(1.0f, WorldPosition, character.CurrentHull, amountMultiplier: damageParticleAmount); + emitter.Emit(1.0f, WorldPosition, character.CurrentHull, amountMultiplier: damageParticleAmount); + } } if (bleedingDamage > 0) @@ -631,7 +634,7 @@ namespace Barotrauma if (pullJoint != null) { Vector2 pos = ConvertUnits.ToDisplayUnits(pullJoint.WorldAnchorB); - GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.Red, true); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), GUI.Style.Red, true); } var bodyDrawPos = body.DrawPosition; bodyDrawPos.Y = -bodyDrawPos.Y; @@ -645,11 +648,11 @@ namespace Barotrauma var front = ConvertUnits.ToDisplayUnits(body.FarseerBody.GetWorldPoint(localFront)); front.Y = -front.Y; GUI.DrawLine(spriteBatch, bodyDrawPos, front, Color.Yellow, width: 2); - GUI.DrawLine(spriteBatch, from, to, Color.Red, width: 1); + GUI.DrawLine(spriteBatch, from, to, GUI.Style.Red, width: 1); GUI.DrawRectangle(spriteBatch, new Rectangle((int)from.X, (int)from.Y, 12, 12), Color.White, true); GUI.DrawRectangle(spriteBatch, new Rectangle((int)to.X, (int)to.Y, 12, 12), Color.White, true); GUI.DrawRectangle(spriteBatch, new Rectangle((int)from.X, (int)from.Y, 10, 10), Color.Blue, true); - GUI.DrawRectangle(spriteBatch, new Rectangle((int)to.X, (int)to.Y, 10, 10), Color.Red, true); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)to.X, (int)to.Y, 10, 10), GUI.Style.Red, true); GUI.DrawRectangle(spriteBatch, new Rectangle((int)front.X, (int)front.Y, 10, 10), Color.Yellow, true); //Vector2 mainLimbFront = ConvertUnits.ToDisplayUnits(ragdoll.MainLimb.body.FarseerBody.GetWorldPoint(ragdoll.MainLimb.body.GetFrontLocal(MathHelper.ToRadians(limbParams.Orientation)))); @@ -748,8 +751,8 @@ namespace Barotrauma //{ // width = (int)Math.Round(width / cam.Zoom); //} - //GUI.DrawLine(spriteBatch, startPos, startPos + Vector2.Normalize(up) * size, Color.Red, width: width); - Color color = modifier.DamageMultiplier > 1 ? Color.Red : Color.GreenYellow; + //GUI.DrawLine(spriteBatch, startPos, startPos + Vector2.Normalize(up) * size, GUI.Style.Red, width: width); + Color color = modifier.DamageMultiplier > 1 ? GUI.Style.Red : GUI.Style.Green; float size = ConvertUnits.ToDisplayUnits(body.GetSize().Length() / 2); if (isScreenSpace) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs index a62eb9fcc..f184736fa 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs @@ -787,12 +787,9 @@ namespace Barotrauma commands.Add(new Command("save|savesub", "save [submarine name]: Save the currently loaded submarine using the specified name.", (string[] args) => { - if (args.Length < 1) return; + if (args.Length < 1) { return; } - if (GameMain.SubEditorScreen.CharacterMode) - { - GameMain.SubEditorScreen.SetCharacterMode(false); - } + GameMain.SubEditorScreen.SetMode(SubEditorScreen.Mode.Default); string fileName = string.Join(" ", args); if (fileName.Contains("../")) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/EventManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/EventManager.cs index 7ef89f21d..c5956c038 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/EventManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/EventManager.cs @@ -27,14 +27,14 @@ namespace Barotrauma { GUI.DrawString(spriteBatch, new Vector2(10, y), "EventManager", Color.White, Color.Black * 0.6f, 0, GUI.SmallFont); GUI.DrawString(spriteBatch, new Vector2(15, y + 20), "Event cooldown: " + eventCoolDown, Color.White, Color.Black * 0.6f, 0, GUI.SmallFont); - GUI.DrawString(spriteBatch, new Vector2(15, y + 35), "Current intensity: " + (int)(currentIntensity * 100), Color.Lerp(Color.White, Color.Red, currentIntensity), Color.Black * 0.6f, 0, GUI.SmallFont); - GUI.DrawString(spriteBatch, new Vector2(15, y + 50), "Target intensity: " + (int)(targetIntensity * 100), Color.Lerp(Color.White, Color.Red, targetIntensity), Color.Black * 0.6f, 0, GUI.SmallFont); + GUI.DrawString(spriteBatch, new Vector2(15, y + 35), "Current intensity: " + (int)(currentIntensity * 100), Color.Lerp(Color.White, GUI.Style.Red, currentIntensity), Color.Black * 0.6f, 0, GUI.SmallFont); + GUI.DrawString(spriteBatch, new Vector2(15, y + 50), "Target intensity: " + (int)(targetIntensity * 100), Color.Lerp(Color.White, GUI.Style.Red, targetIntensity), Color.Black * 0.6f, 0, GUI.SmallFont); - GUI.DrawString(spriteBatch, new Vector2(15, y + 65), "AvgHealth: " + (int)(avgCrewHealth * 100), Color.Lerp(Color.Red, Color.Green, avgCrewHealth), Color.Black * 0.6f, 0, GUI.SmallFont); - GUI.DrawString(spriteBatch, new Vector2(15, y + 80), "AvgHullIntegrity: " + (int)(avgHullIntegrity * 100), Color.Lerp(Color.Red, Color.Green, avgHullIntegrity), Color.Black * 0.6f, 0, GUI.SmallFont); - GUI.DrawString(spriteBatch, new Vector2(15, y + 95), "FloodingAmount: " + (int)(floodingAmount * 100), Color.Lerp(Color.Green, Color.Red, floodingAmount), Color.Black * 0.6f, 0, GUI.SmallFont); - GUI.DrawString(spriteBatch, new Vector2(15, y + 110), "FireAmount: " + (int)(fireAmount * 100), Color.Lerp(Color.Green, Color.Red, fireAmount), Color.Black * 0.6f, 0, GUI.SmallFont); - GUI.DrawString(spriteBatch, new Vector2(15, y + 125), "EnemyDanger: " + (int)(enemyDanger * 100), Color.Lerp(Color.Green, Color.Red, enemyDanger), Color.Black * 0.6f, 0, GUI.SmallFont); + GUI.DrawString(spriteBatch, new Vector2(15, y + 65), "AvgHealth: " + (int)(avgCrewHealth * 100), Color.Lerp(GUI.Style.Red, GUI.Style.Green, avgCrewHealth), Color.Black * 0.6f, 0, GUI.SmallFont); + GUI.DrawString(spriteBatch, new Vector2(15, y + 80), "AvgHullIntegrity: " + (int)(avgHullIntegrity * 100), Color.Lerp(GUI.Style.Red, GUI.Style.Green, avgHullIntegrity), Color.Black * 0.6f, 0, GUI.SmallFont); + GUI.DrawString(spriteBatch, new Vector2(15, y + 95), "FloodingAmount: " + (int)(floodingAmount * 100), Color.Lerp(GUI.Style.Green, GUI.Style.Red, floodingAmount), Color.Black * 0.6f, 0, GUI.SmallFont); + GUI.DrawString(spriteBatch, new Vector2(15, y + 110), "FireAmount: " + (int)(fireAmount * 100), Color.Lerp(GUI.Style.Green, GUI.Style.Red, fireAmount), Color.Black * 0.6f, 0, GUI.SmallFont); + GUI.DrawString(spriteBatch, new Vector2(15, y + 125), "EnemyDanger: " + (int)(enemyDanger * 100), Color.Lerp(GUI.Style.Green, GUI.Style.Red, enemyDanger), Color.Black * 0.6f, 0, GUI.SmallFont); #if DEBUG if (PlayerInput.KeyDown(Microsoft.Xna.Framework.Input.Keys.LeftAlt) && @@ -61,8 +61,8 @@ namespace Barotrauma Rectangle graphRect = new Rectangle(15, y + 150, 150, 50); GUI.DrawRectangle(spriteBatch, graphRect, Color.Black * 0.5f, true); - intensityGraph.Draw(spriteBatch, graphRect, 1.0f, 0.0f, Color.Lerp(Color.White, Color.Red, currentIntensity)); - targetIntensityGraph.Draw(spriteBatch, graphRect, 1.0f, 0.0f, Color.Lerp(Color.White, Color.Red, targetIntensity) * 0.5f); + intensityGraph.Draw(spriteBatch, graphRect, 1.0f, 0.0f, Color.Lerp(Color.White, GUI.Style.Red, currentIntensity)); + targetIntensityGraph.Draw(spriteBatch, graphRect, 1.0f, 0.0f, Color.Lerp(Color.White, GUI.Style.Red, targetIntensity) * 0.5f); GUI.DrawLine(spriteBatch, new Vector2(graphRect.Right, graphRect.Y + graphRect.Height * (1.0f - eventThreshold)), diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs index be16de329..33bf7ab64 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs @@ -30,8 +30,7 @@ namespace Barotrauma _toggleOpen = GameMain.Config.ChatOpen = value; foreach (GUIComponent child in ToggleButton.Children) { - child.SpriteEffects = _toggleOpen == (HUDLayoutSettings.ChatBoxAlignment == Alignment.Right) ? - SpriteEffects.FlipHorizontally : SpriteEffects.None; + child.SpriteEffects = _toggleOpen ? SpriteEffects.FlipHorizontally : SpriteEffects.None; } } } @@ -58,6 +57,11 @@ namespace Barotrauma private GUIButton showNewMessagesButton; + private GUIFrame hideableElements; + + public const int ToggleButtonWidthRaw = 30; + private int popupMessageOffset; + public ChatBox(GUIComponent parent, bool isSinglePlayer) { this.IsSinglePlayer = isSinglePlayer; @@ -69,9 +73,12 @@ namespace Barotrauma screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); - int toggleButtonWidth = (int)(30 * GUI.Scale); + int toggleButtonWidth = (int)(ToggleButtonWidthRaw * GUI.Scale); GUIFrame = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ChatBoxArea, parent.RectTransform), style: null); - var chatBoxHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.875f), GUIFrame.RectTransform), style: "ChatBox"); + + hideableElements = new GUIFrame(new RectTransform(Vector2.One, GUIFrame.RectTransform), style: null); + + var chatBoxHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.875f), hideableElements.RectTransform), style: "ChatBox"); chatBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.95f), chatBoxHolder.RectTransform, Anchor.CenterRight), style: null); ToggleButton = new GUIButton(new RectTransform(new Point(toggleButtonWidth, HUDLayoutSettings.ChatBoxArea.Height), parent.RectTransform), @@ -83,7 +90,7 @@ namespace Barotrauma return true; }; - InputBox = new GUITextBox(new RectTransform(new Vector2(0.925f, 0.125f), GUIFrame.RectTransform, Anchor.BottomLeft), + InputBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.125f), hideableElements.RectTransform, Anchor.BottomLeft), style: "ChatTextBox") { Font = GUI.SmallFont, @@ -98,12 +105,14 @@ namespace Barotrauma //gui.Text = ""; }; - var chatSendButton = new GUIButton(new RectTransform(new Vector2(0.075f, 0.125f), GUIFrame.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.0f, -0.01f) }, ">"); + var chatSendButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.7f), InputBox.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonToggleRight"); chatSendButton.OnClicked += (GUIButton btn, object userdata) => { InputBox.OnEnterPressed(InputBox, InputBox.Text); return true; }; + 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), int.MaxValue); showNewMessagesButton = new GUIButton(new RectTransform(new Vector2(1f, 0.125f), GUIFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, -0.125f) }, TextManager.Get("chat.shownewmessages")); showNewMessagesButton.OnClicked += (GUIButton btn, object userdata) => @@ -278,6 +287,11 @@ namespace Barotrauma GUI.PlayUISound(soundType); } + public void SetVisibility(bool visible) + { + GUIFrame.Parent.Visible = visible; + } + private IEnumerable UpdateMessageAnimation(GUIComponent message, float animDuration) { float timer = 0.0f; @@ -301,18 +315,14 @@ namespace Barotrauma HUDLayoutSettings.ChatBoxArea.Y / (float)GameMain.GraphicsHeight); GUIFrame.RectTransform.NonScaledSize = HUDLayoutSettings.ChatBoxArea.Size; - int toggleButtonWidth = (int)(30 * GUI.Scale); - //make room for the toggle button - if (HUDLayoutSettings.ChatBoxAlignment == Alignment.Left) - { - GUIFrame.RectTransform.AbsoluteOffset += new Point(toggleButtonWidth, 0); - } + int toggleButtonWidth = (int)(ToggleButtonWidthRaw * GUI.Scale); GUIFrame.RectTransform.NonScaledSize -= new Point(toggleButtonWidth, 0); + GUIFrame.RectTransform.AbsoluteOffset += new Point(toggleButtonWidth, 0); ToggleButton.RectTransform.NonScaledSize = new Point(toggleButtonWidth, HUDLayoutSettings.ChatBoxArea.Height); - ToggleButton.RectTransform.AbsoluteOffset = HUDLayoutSettings.ChatBoxAlignment == Alignment.Left ? - new Point(HUDLayoutSettings.ChatBoxArea.X, HUDLayoutSettings.ChatBoxArea.Y) : - new Point(HUDLayoutSettings.ChatBoxArea.Right - toggleButtonWidth, HUDLayoutSettings.ChatBoxArea.Y); + ToggleButton.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.ChatBoxArea.Left - toggleButtonWidth, HUDLayoutSettings.ChatBoxArea.Y); + + popupMessageOffset = ToggleButton.Rect.Width + GameMain.GameSession.CrewManager.ReportButtonFrame.Rect.Width + GUIFrame.Rect.Width; } public void Update(float deltaTime) @@ -347,7 +357,6 @@ namespace Barotrauma var popupMsg = popupMessages.Count > 0 ? popupMessages.Peek() : null; if (popupMsg != null) { - int offset = -popupMsg.Rect.Width - ToggleButton.Rect.Width * 2 - (int)(50 * GUI.Scale) - (GUIFrame.Rect.X - GameMain.GraphicsWidth); popupMsg.Visible = true; //popup messages appear and disappear faster when there's more pending messages popupMessageTimer += deltaTime * popupMessages.Count * popupMessages.Count; @@ -355,7 +364,7 @@ namespace Barotrauma { //move the message out of the screen and delete it popupMsg.RectTransform.ScreenSpaceOffset = - new Point((int)MathHelper.SmoothStep(offset, 10, (popupMessageTimer - PopupMessageDuration) * 5.0f), 0); + new Point((int)MathHelper.SmoothStep(popupMessageOffset, 10, (popupMessageTimer - PopupMessageDuration) * 5.0f), 0); if (popupMessageTimer > PopupMessageDuration + 1.0f) { popupMessageTimer = 0.0f; @@ -366,15 +375,16 @@ namespace Barotrauma else { //move the message on the screen - popupMsg.RectTransform.ScreenSpaceOffset = new Point( - (int)MathHelper.SmoothStep(0, offset, popupMessageTimer * 5.0f), 0); + popupMsg.RectTransform.ScreenSpaceOffset = new Point( + (int)MathHelper.SmoothStep(0, popupMessageOffset, popupMessageTimer * 5.0f), 0); } } } openState = MathHelper.Clamp(openState, 0.0f, 1.0f); - int hiddenBoxOffset = GUIFrame.Rect.Width + ToggleButton.Rect.Width; + int hiddenBoxOffset = -(GUIFrame.Rect.Width); GUIFrame.RectTransform.AbsoluteOffset = - new Point((int)MathHelper.SmoothStep(hiddenBoxOffset * (HUDLayoutSettings.ChatBoxAlignment == Alignment.Left ? -1 : 1), 0, openState), 0); + new Point((int)MathHelper.SmoothStep(hiddenBoxOffset, 0, openState), 0); + hideableElements.Visible = openState > 0.0f; } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs index d9b620849..569346151 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs @@ -5,28 +5,66 @@ using System.Xml.Linq; namespace Barotrauma { + public enum TransitionMode + { + Linear, + Smooth, + Smoother, + EaseIn, + EaseOut, + Exponential + } + + public enum SpriteFallBackState + { + None, + Hover, + Pressed, + Selected, + HoverSelected, + Toggle + } + public class GUIComponentStyle { public readonly Vector4 Padding; public readonly Color Color; - - public readonly Color textColor; - public readonly Color HoverColor; public readonly Color SelectedColor; public readonly Color PressedColor; + public readonly Color DisabledColor; + + public readonly Color TextColor; + public readonly Color HoverTextColor; + public readonly Color SelectedTextColor; + public readonly Color DisabledTextColor; + + public readonly float SpriteCrossFadeTime; + public readonly float ColorCrossFadeTime; + public readonly TransitionMode TransitionMode; + + public readonly string Font; + public readonly bool ForceUpperCase; public readonly Color OutlineColor; - + public readonly XElement Element; public readonly Dictionary> Sprites; + + public SpriteFallBackState FallBackState; public Dictionary ChildStyles; - public GUIComponentStyle(XElement element) + public readonly GUIStyle Style; + + public int? Width { get; private set; } + public int? Height { get; private set; } + + public GUIComponentStyle(XElement element, GUIStyle style) { + Style = style; Element = element; Sprites = new Dictionary>(); @@ -38,14 +76,33 @@ namespace Barotrauma ChildStyles = new Dictionary(); Padding = element.GetAttributeVector4("padding", Vector4.Zero); - + Color = element.GetAttributeColor("color", Color.Transparent); - textColor = element.GetAttributeColor("textcolor", Color.Black); HoverColor = element.GetAttributeColor("hovercolor", Color); SelectedColor = element.GetAttributeColor("selectedcolor", Color); + DisabledColor = element.GetAttributeColor("disabledcolor", Color); PressedColor = element.GetAttributeColor("pressedcolor", Color); OutlineColor = element.GetAttributeColor("outlinecolor", Color.Transparent); + TextColor = element.GetAttributeColor("textcolor", Color.Black); + HoverTextColor = element.GetAttributeColor("hovertextcolor", TextColor); + DisabledTextColor = element.GetAttributeColor("disabledtextcolor", TextColor); + SelectedTextColor = element.GetAttributeColor("selectedtextcolor", TextColor); + SpriteCrossFadeTime = element.GetAttributeFloat("spritefadetime", SpriteCrossFadeTime); + ColorCrossFadeTime = element.GetAttributeFloat("colorfadetime", ColorCrossFadeTime); + + if (Enum.TryParse(element.GetAttributeString("colortransition", string.Empty), ignoreCase: true, out TransitionMode transition)) + { + TransitionMode = transition; + } + if (Enum.TryParse(element.GetAttributeString("fallbackstate", GUIComponent.ComponentState.None.ToString()), ignoreCase: true, out SpriteFallBackState s)) + { + FallBackState = s; + } + + Font = element.GetAttributeString("font", ""); + ForceUpperCase = element.GetAttributeBool("forceuppercase", false); + foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) @@ -59,6 +116,11 @@ namespace Barotrauma string stateStr = subElement.GetAttributeString("state", "None"); Enum.TryParse(stateStr, out spriteState); Sprites[spriteState].Add(newSprite); + //use the same sprite for Hover and HoverSelected if latter is not specified + if (spriteState == GUIComponent.ComponentState.HoverSelected && !Sprites.ContainsKey(GUIComponent.ComponentState.HoverSelected)) + { + Sprites[GUIComponent.ComponentState.HoverSelected].Add(newSprite); + } } else { @@ -68,11 +130,34 @@ namespace Barotrauma } } break; + case "size": + break; default: - ChildStyles.Add(subElement.Name.ToString().ToLowerInvariant(), new GUIComponentStyle(subElement)); + ChildStyles.Add(subElement.Name.ToString().ToLowerInvariant(), new GUIComponentStyle(subElement, style)); break; } } + + GetSize(element); + } + + public void GetSize(XElement element) + { + Point size = new Point(0, 0); + foreach (XElement subElement in element.Elements()) + { + if (subElement.Name.ToString().ToLowerInvariant() != "size") { continue; } + Point maxResolution = subElement.GetAttributePoint("maxresolution", new Point(int.MaxValue, int.MaxValue)); + if (GameMain.GraphicsWidth <= maxResolution.X && GameMain.GraphicsHeight <= maxResolution.Y) + { + size = new Point( + subElement.GetAttributeInt("width", 0), + subElement.GetAttributeInt("height", 0)); + break; + } + } + if (size.X > 0) { Width = size.X; } + if (size.Y > 0) { Height = size.Y; } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/FileSelection.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/FileSelection.cs index e3d39ea7c..b813565e0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/FileSelection.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/FileSelection.cs @@ -32,13 +32,11 @@ namespace Barotrauma private static GUIFrame window; private static GUIListBox sidebar; private static GUIListBox fileList; - private static GUIButton moveToParentButton; private static GUITextBox directoryBox; private static GUITextBox filterBox; private static GUITextBox fileBox; private static GUIDropDown fileTypeDropdown; private static GUIButton openButton; - private static GUIButton cancelButton; private static FileSystemWatcher fileSystemWatcher; @@ -46,7 +44,7 @@ namespace Barotrauma private static readonly string[] ignoredDrivePrefixes = new string[] { - "/sys/","/snap/" + "/sys/", "/snap/" }; private static string currentDirectory; @@ -62,14 +60,14 @@ namespace Barotrauma List dirs = new List(); for (int i = 0; i < dirSplit.Length; i++) { - if (dirSplit[i].Trim()=="..") + if (dirSplit[i].Trim() == "..") { if (dirs.Count > 1) { dirs.RemoveAt(dirs.Count - 1); } } - else if (dirSplit[i].Trim()!=".") + else if (dirSplit[i].Trim() != ".") { dirs.Add(dirSplit[i]); } @@ -80,9 +78,11 @@ namespace Barotrauma currentDirectory += "/"; } fileSystemWatcher?.Dispose(); - fileSystemWatcher = new FileSystemWatcher(currentDirectory); - fileSystemWatcher.Filter = "*"; - fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; + fileSystemWatcher = new FileSystemWatcher(currentDirectory) + { + Filter = "*", + NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName + }; fileSystemWatcher.Created += OnFileSystemChanges; fileSystemWatcher.Deleted += OnFileSystemChanges; fileSystemWatcher.Renamed += OnFileSystemChanges; @@ -103,8 +103,10 @@ namespace Barotrauma { case WatcherChangeTypes.Created: { - var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), e.Name); - itemFrame.UserData = (bool?)Directory.Exists(e.FullPath); + var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), e.Name) + { + UserData = (bool?)Directory.Exists(e.FullPath) + }; if ((itemFrame.UserData as bool?) ?? false) { itemFrame.Text += "/"; @@ -164,7 +166,7 @@ namespace Barotrauma window = new GUIFrame(new RectTransform(Vector2.One * 0.8f, backgroundFrame.RectTransform, Anchor.Center)); - var horizontalLayout = new GUILayoutGroup(new RectTransform(Vector2.One*0.9f, window.RectTransform, Anchor.Center), true); + 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(); @@ -186,8 +188,8 @@ namespace Barotrauma new GUIFrame(new RectTransform(new Vector2(0.01f, 1.0f), horizontalLayout.RectTransform), style: null); var fileListLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 1.0f), horizontalLayout.RectTransform)); - var firstRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), fileListLayout.RectTransform), true); - moveToParentButton = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), firstRow.RectTransform), "^") + var firstRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), fileListLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft); + new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), firstRow.RectTransform), "^") { OnClicked = MoveToParentDirectory }; @@ -212,6 +214,8 @@ namespace Barotrauma { OverflowClip = true }; + firstRow.RectTransform.MinSize = new Point(0, firstRow.RectTransform.Children.Max(c => c.MinSize.Y)); + filterBox.OnTextChanged += (txtbox, txt) => { RefreshFileList(); @@ -220,50 +224,54 @@ namespace Barotrauma //spacing between rows new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), fileListLayout.RectTransform), style: null); - fileList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.85f), fileListLayout.RectTransform)); - - fileList.OnSelected = (child, userdata) => + fileList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.85f), fileListLayout.RectTransform)) { - if (userdata == null) { return false; } - - fileBox.Text = (child as GUITextBlock).Text; - if (PlayerInput.DoubleClicked()) + OnSelected = (child, userdata) => { - bool isDir = (userdata as bool?).Value; - if (isDir) - { - CurrentDirectory += (child as GUITextBlock).Text; - } - else - { - OnFileSelected?.Invoke(CurrentDirectory + (child as GUITextBlock).Text); - Open = false; - } - } + if (userdata == null) { return false; } - return true; + var fileName = (child as GUITextBlock).Text; + fileBox.Text = fileName; + if (PlayerInput.DoubleClicked()) + { + bool isDir = (userdata as bool?).Value; + if (isDir) + { + CurrentDirectory += fileName; + } + else + { + OnFileSelected?.Invoke(CurrentDirectory + fileName); + Open = false; + } + } + + return true; + } }; //spacing between rows new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), fileListLayout.RectTransform), style: null); var thirdRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), fileListLayout.RectTransform), true); - fileBox = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), thirdRow.RectTransform)); - fileBox.OnEnterPressed = (tb, txt) => openButton?.OnClicked?.Invoke(openButton, null) ?? false; - - fileTypeDropdown = new GUIDropDown(new RectTransform(new Vector2(0.3f, 1.0f), thirdRow.RectTransform), dropAbove: true); - - fileTypeDropdown.OnSelected = (child, userdata) => + fileBox = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), thirdRow.RectTransform)) { - currentFileTypePattern = (child as GUITextBlock).UserData as string; - RefreshFileList(); + OnEnterPressed = (tb, txt) => openButton?.OnClicked?.Invoke(openButton, null) ?? false + }; - return true; + fileTypeDropdown = new GUIDropDown(new RectTransform(new Vector2(0.3f, 1.0f), thirdRow.RectTransform), dropAbove: true) + { + OnSelected = (child, userdata) => + { + currentFileTypePattern = (child as GUITextBlock).UserData as string; + RefreshFileList(); + + return true; + } }; fileTypeDropdown.Select(4); - //spacing between rows new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), fileListLayout.RectTransform), style: null); var fourthRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), fileListLayout.RectTransform), true); @@ -271,7 +279,7 @@ namespace Barotrauma //padding for open/cancel buttons new GUIFrame(new RectTransform(new Vector2(0.7f, 1.0f), fourthRow.RectTransform), style: null); - openButton = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), fourthRow.RectTransform), "Open") + openButton = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), fourthRow.RectTransform), TextManager.Get("opensubbutton")) { OnClicked = (btn, obj) => { @@ -279,13 +287,13 @@ namespace Barotrauma { CurrentDirectory += fileBox.Text; } - if (!File.Exists(CurrentDirectory+fileBox.Text)) { return false; } + if (!File.Exists(CurrentDirectory + fileBox.Text)) { return false; } OnFileSelected?.Invoke(CurrentDirectory + fileBox.Text); Open = false; return false; } }; - cancelButton = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), fourthRow.RectTransform), "Cancel") + new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), fourthRow.RectTransform), TextManager.Get("cancel")) { OnClicked = (btn, obj) => { @@ -306,7 +314,7 @@ namespace Barotrauma public static void AddFileTypeFilter(string name, string pattern) { if (backgroundFrame == null) { Init(); } - fileTypeDropdown.AddItem(name + " ("+pattern+")", pattern); + fileTypeDropdown.AddItem(name + " (" + pattern + ")", pattern); } public static void SelectFileTypeFilter(string pattern) @@ -322,21 +330,28 @@ namespace Barotrauma try { - var directories = Directory.EnumerateDirectories(currentDirectory, "*"+filterBox.Text+"*"); + var directories = Directory.EnumerateDirectories(currentDirectory, "*" + filterBox.Text + "*"); foreach (var directory in directories) { string txt = directory; if (txt.StartsWith(currentDirectory)) { txt = txt.Substring(currentDirectory.Length); } if (!txt.EndsWith("/")) { txt += "/"; } - var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), txt); - itemFrame.UserData = (bool?)true; + var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), txt) + { + UserData = (bool?)true + }; + var folderIcon = new GUIImage(new RectTransform(new Point((int)(itemFrame.Rect.Height * 0.8f)), itemFrame.RectTransform, Anchor.CenterLeft) + { + AbsoluteOffset = new Point((int)(itemFrame.Rect.Height * 0.25f), 0) + }, style: "OpenButton", scaleToFit: true); + itemFrame.Padding = new Vector4(folderIcon.Rect.Width * 1.5f, itemFrame.Padding.Y, itemFrame.Padding.Z, itemFrame.Padding.W); } IEnumerable files = null; foreach (string pattern in currentFileTypePattern.Split(',')) { string patternTrimmed = pattern.Trim(); - patternTrimmed = "*"+filterBox.Text+"*"+patternTrimmed; + patternTrimmed = "*" + filterBox.Text + "*" + patternTrimmed; if (files == null) { files = Directory.EnumerateFiles(currentDirectory, patternTrimmed); @@ -351,8 +366,10 @@ namespace Barotrauma { string txt = file; if (txt.StartsWith(currentDirectory)) { txt = txt.Substring(currentDirectory.Length); } - var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), txt); - itemFrame.UserData = (bool?)false; + var itemFrame = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), fileList.Content.RectTransform), txt) + { + UserData = (bool?)false + }; } } catch (Exception e) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs index 42c2c4ab2..8e0484b13 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs @@ -124,12 +124,13 @@ namespace Barotrauma public static ScalableFont UnscaledSmallFont => Style?.UnscaledSmallFont; public static ScalableFont SmallFont => Style?.SmallFont; public static ScalableFont LargeFont => Style?.LargeFont; - public static ScalableFont VideoTitleFont => Style?.VideoTitleFont; - public static ScalableFont ObjectiveTitleFont => Style?.ObjectiveTitleFont; - public static ScalableFont ObjectiveNameFont => Style?.ObjectiveNameFont; + public static ScalableFont SubHeadingFont => Style?.SubHeadingFont; + public static ScalableFont DigitalFont => Style?.DigitalFont; + public static ScalableFont CJKFont { get; private set; } public static UISprite UIGlow => Style.UIGlow; + public static UISprite UIGlowCircular => Style.UIGlowCircular; public static Sprite SubmarineIcon { @@ -169,6 +170,8 @@ namespace Barotrauma get { return timerIcon; } } + public static Sprite InfoAreaBackground; + public static bool SettingsMenuOpen { get { return settingsMenuOpen; } @@ -267,6 +270,7 @@ namespace Barotrauma lockIcon = new Sprite("Content/UI/UI_Atlas.png", new Rectangle(996, 677, 21, 25), new Vector2(0.5f, 0.5f)); checkmarkIcon = new Sprite("Content/UI/UI_Atlas.png", new Rectangle(932, 398, 33, 28), new Vector2(0.5f, 0.5f)); timerIcon = new Sprite("Content/UI/UI_Atlas.png", new Rectangle(997, 653, 18, 21), new Vector2(0.5f, 0.5f)); + InfoAreaBackground = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(290, 320, 400, 300), new Vector2(0.0f, 0.0f)); } /// @@ -329,9 +333,9 @@ namespace Barotrauma DrawString(spriteBatch, new Vector2(300, y), "Draw - Avg: " + GameMain.PerformanceCounter.DrawTimeGraph.Average().ToString("0.00") + " ms" + " Max: " + GameMain.PerformanceCounter.DrawTimeGraph.LargestValue().ToString("0.00") + " ms", - Color.Green, Color.Black * 0.8f, font: SmallFont); + GUI.Style.Green, Color.Black * 0.8f, font: SmallFont); y += 15; - GameMain.PerformanceCounter.DrawTimeGraph.Draw(spriteBatch, new Rectangle(300, y, 170, 50), null, 0, Color.Green); + GameMain.PerformanceCounter.DrawTimeGraph.Draw(spriteBatch, new Rectangle(300, y, 170, 50), null, 0, GUI.Style.Green); y += 50; DrawString(spriteBatch, new Vector2(300, y), @@ -340,26 +344,26 @@ namespace Barotrauma Color.LightBlue, Color.Black * 0.8f, font: SmallFont); y += 15; GameMain.PerformanceCounter.UpdateTimeGraph.Draw(spriteBatch, new Rectangle(300, y, 170, 50), null, 0, Color.LightBlue); - GameMain.PerformanceCounter.UpdateIterationsGraph.Draw(spriteBatch, new Rectangle(300, y, 170, 50), 20, 0, Color.Red); + GameMain.PerformanceCounter.UpdateIterationsGraph.Draw(spriteBatch, new Rectangle(300, y, 170, 50), 20, 0, GUI.Style.Red); y += 50; foreach (string key in GameMain.PerformanceCounter.GetSavedIdentifiers) { float elapsedMillisecs = GameMain.PerformanceCounter.GetAverageElapsedMillisecs(key); DrawString(spriteBatch, new Vector2(300, y), key + ": " + elapsedMillisecs.ToString("0.00"), - Color.Lerp(Color.LightGreen, Color.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, SmallFont); + Color.Lerp(Color.LightGreen, GUI.Style.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, SmallFont); y += 15; } if (Settings.EnableDiagnostics) { - DrawString(spriteBatch, new Vector2(320, y), "ContinuousPhysicsTime: " + GameMain.World.ContinuousPhysicsTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, Color.Red, (float)GameMain.World.ContinuousPhysicsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); - DrawString(spriteBatch, new Vector2(320, y + 15), "ControllersUpdateTime: " + GameMain.World.ControllersUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, Color.Red, (float)GameMain.World.ControllersUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); - DrawString(spriteBatch, new Vector2(320, y + 30), "AddRemoveTime: " + GameMain.World.AddRemoveTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, Color.Red, (float)GameMain.World.AddRemoveTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); - DrawString(spriteBatch, new Vector2(320, y + 45), "NewContactsTime: " + GameMain.World.NewContactsTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, Color.Red, (float)GameMain.World.NewContactsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); - DrawString(spriteBatch, new Vector2(320, y + 60), "ContactsUpdateTime: " + GameMain.World.ContactsUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, Color.Red, (float)GameMain.World.ContactsUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); - DrawString(spriteBatch, new Vector2(320, y + 75), "SolveUpdateTime: " + GameMain.World.SolveUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, Color.Red, (float)GameMain.World.SolveUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); + DrawString(spriteBatch, new Vector2(320, y), "ContinuousPhysicsTime: " + GameMain.World.ContinuousPhysicsTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUI.Style.Red, (float)GameMain.World.ContinuousPhysicsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); + DrawString(spriteBatch, new Vector2(320, y + 15), "ControllersUpdateTime: " + GameMain.World.ControllersUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUI.Style.Red, (float)GameMain.World.ControllersUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); + DrawString(spriteBatch, new Vector2(320, y + 30), "AddRemoveTime: " + GameMain.World.AddRemoveTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUI.Style.Red, (float)GameMain.World.AddRemoveTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); + DrawString(spriteBatch, new Vector2(320, y + 45), "NewContactsTime: " + GameMain.World.NewContactsTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUI.Style.Red, (float)GameMain.World.NewContactsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); + DrawString(spriteBatch, new Vector2(320, y + 60), "ContactsUpdateTime: " + GameMain.World.ContactsUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUI.Style.Red, (float)GameMain.World.ContactsUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); + DrawString(spriteBatch, new Vector2(320, y + 75), "SolveUpdateTime: " + GameMain.World.SolveUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUI.Style.Red, (float)GameMain.World.SolveUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, SmallFont); } } @@ -389,7 +393,7 @@ namespace Barotrauma DrawString(spriteBatch, new Vector2(10, 90), "Particle count: " + GameMain.ParticleManager.ParticleCount + "/" + GameMain.ParticleManager.MaxParticles, - Color.Lerp(Color.Green, Color.Red, (GameMain.ParticleManager.ParticleCount / (float)GameMain.ParticleManager.MaxParticles)), Color.Black * 0.5f, 0, SmallFont); + Color.Lerp(GUI.Style.Green, GUI.Style.Red, (GameMain.ParticleManager.ParticleCount / (float)GameMain.ParticleManager.MaxParticles)), Color.Black * 0.5f, 0, SmallFont); DrawString(spriteBatch, new Vector2(10, 115), "Loaded sprites: " + Sprite.LoadedSprites.Count() + "\n(" + Sprite.LoadedSprites.Select(s => s.FilePath).Distinct().Count() + " unique textures)", @@ -472,10 +476,6 @@ namespace Barotrauma "Ctrl+S to show sound debug info", Color.White, Color.Black * 0.5f, 0, SmallFont); } - if (PlayerInput.KeyDown(Keys.LeftControl) && PlayerInput.KeyHit(Keys.S)) - { - debugDrawSounds = !debugDrawSounds; - } if (debugDrawEvents) { @@ -488,13 +488,12 @@ namespace Barotrauma DrawString(spriteBatch, new Vector2(10, 300), "Ctrl+E to show EventManager debug info", Color.White, Color.Black * 0.5f, 0, SmallFont); } - if (PlayerInput.KeyDown(Keys.LeftControl) && PlayerInput.KeyHit(Keys.E)) - { - debugDrawEvents = !debugDrawEvents; - } + if (MouseOn != null) { - DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 500, 20), $"Selected UI Element: {MouseOn.GetType().ToString()}", Color.LightGreen, Color.Black * 0.5f, 0, SmallFont); + 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); } } @@ -744,19 +743,27 @@ namespace Barotrauma { inventoryIndex = updateList.IndexOf(CharacterHUD.HUDFrame); } - for (var i = updateList.Count - 1; i > inventoryIndex; i--) + + if (!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) { - var c = updateList[i]; - if (!c.CanBeFocused) { continue; } - if (c.MouseRect.Contains(PlayerInput.MousePosition)) + for (var i = updateList.Count - 1; i > inventoryIndex; i--) { - if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn) + var c = updateList[i]; + if (!c.CanBeFocused) { continue; } + if (c.MouseRect.Contains(PlayerInput.MousePosition)) { - MouseOn = c; + if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn) + { + MouseOn = c; + } + break; } - break; } } + else + { + MouseOn = prevMouseOn; + } MouseCursor = UpdateMouseCursorState(MouseOn); return MouseOn; @@ -845,8 +852,11 @@ namespace Barotrauma // Children in list boxes can be interacted with despite not having // a GUIButton inside of them so instead of hard coding we check if // the children can be interacted with by checking their hover state - if (parent is GUIListBox) + if (parent is GUIListBox listBox) { + if (listBox.DraggedElement != null) { return CursorState.Dragging; } + if (listBox.CanDragElements) { return CursorState.Move; } + var hoverParent = c; while (true) { @@ -958,6 +968,15 @@ namespace Barotrauma public static void Update(float deltaTime) { + if (PlayerInput.KeyDown(Keys.LeftControl) && PlayerInput.KeyHit(Keys.S)) + { + debugDrawSounds = !debugDrawSounds; + } + if (PlayerInput.KeyDown(Keys.LeftControl) && PlayerInput.KeyHit(Keys.E)) + { + debugDrawEvents = !debugDrawEvents; + } + HandlePersistingElements(deltaTime); RefreshUpdateList(); UpdateMouseOn(); @@ -1279,7 +1298,7 @@ namespace Barotrauma public static void DrawSineWithDots(SpriteBatch spriteBatch, Vector2 from, Vector2 dir, float amplitude, float length, float scale, int pointCount, Color color, int dotSize = 2) { Vector2 up = dir.Right(); - //DrawLine(spriteBatch, from, from + dir, Color.Red); + //DrawLine(spriteBatch, from, from + dir, GUI.Style.Red); //DrawLine(spriteBatch, from, from + up * dir.Length(), Color.Blue); for (int i = 0; i < pointCount; i++) { @@ -1814,15 +1833,15 @@ namespace Barotrauma PauseMenu = new GUIFrame(new RectTransform(Vector2.One, Canvas), style: null, color: Color.Black * 0.5f); - var pauseMenuInner = new GUIFrame(new RectTransform(new Vector2(0.13f, 0.35f), PauseMenu.RectTransform, Anchor.Center) { MinSize = new Point(200, 300) }); + 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.85f, 0.8f), pauseMenuInner.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.05f) }) + var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 0.6f), pauseMenuInner.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.05f }; - var button = new GUIButton(new RectTransform(new Vector2(0.12f, 0.12f), buttonContainer.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(-0.05f, -0.13f) }, + var button = new GUIButton(new RectTransform(new Vector2(0.1f, 0.1f), pauseMenuInner.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point((int)(15 * GUI.Scale)) }, "", style: "GUIBugButton") { IgnoreLayoutGroups = true, @@ -1830,12 +1849,12 @@ namespace Barotrauma OnClicked = (btn, userdata) => { GameMain.Instance.ShowBugReporter(); return true; } }; - button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuResume"), style: "GUIButtonLarge") + button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuResume")) { OnClicked = TogglePauseMenu }; - button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSettings"), style: "GUIButtonLarge") + button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSettings")) { OnClicked = (btn, userData) => { @@ -1849,7 +1868,7 @@ namespace Barotrauma { if (GameMain.GameSession.GameMode is SinglePlayerCampaign spMode) { - button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuRetry"), style: "GUIButtonLarge"); + button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuRetry")); button.OnClicked += (btn, userData) => { var msgBox = new GUIMessageBox("", TextManager.Get("PauseMenuRetryVerification"), new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") }) @@ -1875,7 +1894,7 @@ namespace Barotrauma } else if (!GameMain.GameSession.GameMode.IsSinglePlayer && GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.ManageRound)) { - new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), text: TextManager.Get("EndRound"), style: "GUIButtonLarge") + new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), text: TextManager.Get("EndRound")) { OnClicked = (btn, userdata) => { @@ -1910,7 +1929,7 @@ namespace Barotrauma { if (GameMain.GameSession.GameMode is SinglePlayerCampaign spMode) { - button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSaveQuit"), style: "GUIButtonLarge") + button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSaveQuit")) { UserData = "save" }; @@ -1919,7 +1938,7 @@ namespace Barotrauma } } - button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuQuit"), style: "GUIButtonLarge"); + button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuQuit")); button.OnClicked += (btn, userData) => { var quitButton = button; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIButton.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIButton.cs index 354caa070..f866a16b6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIButton.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIButton.cs @@ -20,9 +20,7 @@ namespace Barotrauma public OnButtonDownHandler OnButtonDown; public bool CanBeSelected = true; - - private Color? defaultTextColor; - + public override bool Enabled { get @@ -33,13 +31,7 @@ namespace Barotrauma set { if (value == enabled) { return; } - enabled = value; - if (color.A == 0) - { - if (defaultTextColor == null) { defaultTextColor = TextBlock.TextColor; } - TextBlock.TextColor = enabled ? defaultTextColor.Value : defaultTextColor.Value * 0.5f; - } - frame.Color = enabled ? color : Color.Gray * 0.7f; + enabled = frame.Enabled = textBlock.Enabled = value; } } @@ -105,6 +97,11 @@ namespace Barotrauma set { textBlock.TextColor = value; } } + public Color HoverTextColor + { + get { return textBlock.HoverTextColor; } + set { textBlock.HoverTextColor = value; } + } public override float FlashTimer { @@ -115,12 +112,12 @@ namespace Barotrauma { get { - return (textBlock==null) ? GUI.Font : textBlock.Font; + return (textBlock == null) ? GUI.Font : textBlock.Font; } set { base.Font = value; - if (textBlock != null) textBlock.Font = value; + if (textBlock != null) textBlock.Font = value; } } @@ -149,28 +146,28 @@ namespace Barotrauma } } - public bool Selected { get; set; } - - public GUIButton(RectTransform rectT, string text = "", Alignment textAlignment = Alignment.Center, string style = "", Color? color = null, ScalableFont font = null) : base(style, rectT) + public GUIButton(RectTransform rectT, string text = "", Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : base(style, rectT) { CanBeFocused = true; HoverCursor = CursorState.Hand; + frame = new GUIFrame(new RectTransform(Vector2.One, rectT), style) { CanBeFocused = false }; + if (style != null) { GUI.Style.Apply(frame, style == "" ? "GUIButton" : style); } if (color.HasValue) { - this.color = color.Value; + this.color = frame.Color = color.Value; } - frame = new GUIFrame(new RectTransform(Vector2.One, rectT), style) { CanBeFocused = false }; - if (style != null) GUI.Style.Apply(frame, style == "" ? "GUIButton" : style); - textBlock = new GUITextBlock(new RectTransform(Vector2.One, rectT), text, textAlignment: textAlignment, style: null, font: font) + textBlock = new GUITextBlock(new RectTransform(Vector2.One, rectT, Anchor.Center), text, textAlignment: textAlignment, style: null) { - TextColor = this.style == null ? Color.Black : this.style.textColor, + TextColor = this.style == null ? Color.Black : this.style.TextColor, + HoverTextColor = this.style == null ? Color.Black : this.style.HoverTextColor, + SelectedTextColor = this.style == null ? Color.Black : this.style.SelectedTextColor, CanBeFocused = false }; if (rectT.Rect.Height == 0 && !string.IsNullOrEmpty(text)) { RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(textBlock.Text).Y)); - RectTransform.MinSize = textBlock.RectTransform.MinSize = new Point(0, Rect.Height); + RectTransform.MinSize = textBlock.RectTransform.MinSize = new Point(0, System.Math.Max(rectT.MinSize.Y, Rect.Height)); TextBlock.SetTextPos(); } GUI.Style.Apply(textBlock, "", this); @@ -181,12 +178,12 @@ namespace Barotrauma { base.ApplyStyle(style); - if (frame != null) frame.ApplyStyle(style); + if (frame != null) { frame.ApplyStyle(style); } } - public override void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, Vector2? flashRectInflate = null) + public override void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, bool useCircularFlash = false, Vector2? flashRectInflate = null) { - Frame.Flash(color, flashDuration, useRectangleFlash, flashRectInflate); + Frame.Flash(color, flashDuration, useRectangleFlash, useCircularFlash, flashRectInflate); } protected override void Draw(SpriteBatch spriteBatch) @@ -200,7 +197,9 @@ namespace Barotrauma base.Update(deltaTime); if (Rect.Contains(PlayerInput.MousePosition) && CanBeSelected && CanBeFocused && Enabled && GUI.IsMouseOn(this)) { - state = ComponentState.Hover; + State = Selected ? + ComponentState.HoverSelected : + ComponentState.Hover; if (PlayerInput.PrimaryMouseButtonDown()) { OnButtonDown?.Invoke(); @@ -211,12 +210,12 @@ namespace Barotrauma { if (OnPressed()) { - state = ComponentState.Pressed; + State = ComponentState.Pressed; } } else { - state = ComponentState.Pressed; + State = ComponentState.Pressed; } } else if (PlayerInput.PrimaryMouseButtonClicked()) @@ -224,28 +223,26 @@ namespace Barotrauma GUI.PlayUISound(GUISoundType.Click); if (OnClicked != null) { - if (OnClicked(this, UserData) && CanBeSelected) + if (OnClicked(this, UserData)) { - state = ComponentState.Selected; + State = ComponentState.Selected; } } else { Selected = !Selected; - // state = state == ComponentState.Selected ? ComponentState.None : ComponentState.Selected; - } + } } } else { - state = Selected ? ComponentState.Selected : ComponentState.None; + State = Selected ? ComponentState.Selected : ComponentState.None; } foreach (GUIComponent child in Children) { - child.State = state; + child.State = State; } - //frame.State = state; } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIColorSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIColorSettings.cs new file mode 100644 index 000000000..4f509c3ee --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIColorSettings.cs @@ -0,0 +1,26 @@ +using Microsoft.Xna.Framework; + +namespace Barotrauma +{ + public class GUIColorSettings + { + // Inventory + public static Color InventorySlotColor = new Color(78, 114, 88); + public static Color EquipmentSlotColor = new Color(72, 58, 25); + public static Color EquipmentSlotIconColor = new Color(99, 70, 64); + + // Health HUD + public static Color BuffColorLow = Color.LightGreen; + public static Color BuffColorMedium = Color.Green; + public static Color BuffColorHigh = Color.DarkGreen; + + public static Color DebuffColorLow = Color.DarkSalmon; + public static Color DebuffColorMedium = Color.Red; + public static Color DebuffColorHigh = Color.DarkRed; + + public static Color HealthBarColorLow = Color.Red; + public static Color HealthBarColorMedium = Color.Orange; + public static Color HealthBarColorHigh = new Color(78, 114, 88); + + } +} diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs index fc1c67567..032830d2e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs @@ -15,11 +15,11 @@ namespace Barotrauma { #region Hierarchy public GUIComponent Parent => RectTransform.Parent?.GUIComponent; - + public CursorState HoverCursor = CursorState.Default; public IEnumerable Children => RectTransform.Children.Select(c => c.GUIComponent); - + public T GetChild() where T : GUIComponent { return Children.FirstOrDefault(c => c is T) as T; @@ -30,6 +30,19 @@ namespace Barotrauma return GetAllChildren().FirstOrDefault(c => c is T) as T; } + public IEnumerable GetAllChildren() where T : GUIComponent + { + return GetAllChildren().Where(c => c is T).Select(c => c as T); + } + + /// + /// Returns all child elements in the hierarchy. + /// + public IEnumerable GetAllChildren() + { + return RectTransform.GetAllChildren().Select(c => c.GUIComponent); + } + public GUIComponent GetChild(int index) { if (index < 0 || index >= CountChildren) return null; @@ -51,15 +64,6 @@ namespace Barotrauma return null; } - /// - /// Returns all child elements in the hierarchy. - /// If the component has RectTransform, it's more efficient to use RectTransform.GetChildren and access the GUIComponent property directly. - /// - public IEnumerable GetAllChildren() - { - return RectTransform.GetAllChildren().Select(c => c.GUIComponent); - } - public bool IsParentOf(GUIComponent component, bool recursive = true) { if (component == null) { return false; } @@ -134,31 +138,30 @@ namespace Barotrauma public int UpdateOrder { get; set; } public Action OnAddedToGUIUpdateList; - /// - /// Launched at the beginning of the Draw method. Note: if the method is overridden, the event might not be called! - - public enum ComponentState { None, Hover, Pressed, Selected }; + + public enum ComponentState { None, Hover, Pressed, Selected, HoverSelected }; protected Alignment alignment; protected GUIComponentStyle style; protected object userData; - + public bool CanBeFocused; - + protected Color color; protected Color hoverColor; protected Color selectedColor; + protected Color disabledColor; protected Color pressedColor; private CoroutineHandle pulsateCoroutine; - protected ComponentState state; - protected Color flashColor; protected float flashDuration = 1.5f; + // TODO: We should use an enum for the flash modes, but it would require a bit of refactoring, because Flash method is use in so many places. private bool useRectangleFlash; + private bool useCircularFlash; public virtual float FlashTimer { get { return flashTimer; } @@ -166,7 +169,20 @@ namespace Barotrauma protected float flashTimer; private Vector2 flashRectInflate; - public bool IgnoreLayoutGroups; + private bool ignoreLayoutGroups; + public bool IgnoreLayoutGroups + { + get { return ignoreLayoutGroups; } + set + { + if (ignoreLayoutGroups == value) { return; } + ignoreLayoutGroups = value; + if (Parent is GUILayoutGroup layoutGroup) + { + layoutGroup.NeedsToRecalculate = true; + } + } + } public virtual ScalableFont Font { @@ -210,7 +226,7 @@ namespace Barotrauma get { return enabled; } set { enabled = value; } } - + private static GUITextBlock toolTipBlock; public Vector2 Center @@ -270,10 +286,31 @@ namespace Barotrauma public virtual Color OutlineColor { get; set; } - public ComponentState State + protected ComponentState _state; + protected ComponentState _previousState; + protected bool selected; + public virtual bool Selected { - get { return state; } - set { state = value; } + get { return selected; } + set + { + selected = value; + Children.ForEach(c => c.Selected = value); + } + } + public virtual ComponentState State + { + get { return _state; } + set + { + if (_state != value) + { + spriteFadeTimer = SpriteCrossFadeTime; + colorFadeTimer = ColorCrossFadeTime; + _previousState = _state; + } + _state = value; + } } public object UserData @@ -304,6 +341,11 @@ namespace Barotrauma get { return selectedColor; } set { selectedColor = value; } } + public virtual Color DisabledColor + { + get { return disabledColor; } + set { disabledColor = value; } + } public virtual Color PressedColor { @@ -311,6 +353,14 @@ namespace Barotrauma set { pressedColor = value; } } + public TransitionMode ColorTransition { get; private set; } + public SpriteFallBackState FallBackState { get; private set; } + public float SpriteCrossFadeTime { get; private set; } + public float ColorCrossFadeTime { get; private set; } + + private float spriteFadeTimer; + private float colorFadeTimer; + public bool ExternalHighlight = false; private RectTransform rectTransform; @@ -331,23 +381,26 @@ namespace Barotrauma /// /// This is the new constructor. /// - protected GUIComponent(string style, RectTransform rectT) : this(style) + protected GUIComponent(string style, RectTransform rectT) { RectTransform = rectT; + + Visible = true; + OutlineColor = Color.Transparent; + Font = GUI.Font; + CanBeFocused = true; + + if (style != null) { GUI.Style.Apply(this, style); } } protected GUIComponent(string style) { Visible = true; - OutlineColor = Color.Transparent; - Font = GUI.Font; + CanBeFocused = true; - CanBeFocused = true; //TODO: change default to false? - - if (style != null) - GUI.Style.Apply(this, style); + if (style != null) { GUI.Style.Apply(this, style); } } #region Updating @@ -402,6 +455,14 @@ namespace Barotrauma { flashTimer -= deltaTime; } + if (spriteFadeTimer > 0) + { + spriteFadeTimer -= deltaTime; + } + if (colorFadeTimer > 0) + { + colorFadeTimer -= deltaTime; + } } /// @@ -448,34 +509,114 @@ namespace Barotrauma RectTransform.Children.ForEach(c => c.GUIComponent.DrawManually(spriteBatch, recursive, recursive)); } - protected virtual Color GetCurrentColor(ComponentState state) + protected Color _currentColor; + + protected virtual Color GetColor(ComponentState state) { - switch (state) + if (!Enabled) { return DisabledColor; } + return state switch { - case ComponentState.Hover: - return HoverColor; - case ComponentState.Pressed: - return PressedColor; - case ComponentState.Selected: - return SelectedColor; - default: - return Color; - } + ComponentState.Hover => HoverColor, + ComponentState.Pressed => PressedColor, + ComponentState.Selected => SelectedColor, + _ => Color, + }; + } + + private float GetEasing(TransitionMode easing, float t) + { + return easing switch + { + TransitionMode.Smooth => MathUtils.SmoothStep(t), + TransitionMode.Smoother => MathUtils.SmootherStep(t), + TransitionMode.EaseIn => MathUtils.EaseIn(t), + TransitionMode.EaseOut => MathUtils.EaseOut(t), + TransitionMode.Exponential => t * t, + TransitionMode.Linear => t, + _ => t, + }; + } + + protected Color GetBlendedColor(Color targetColor, ref Color blendedColor) + { + blendedColor = ColorCrossFadeTime > 0 ? Color.Lerp(blendedColor, targetColor, MathUtils.InverseLerp(ColorCrossFadeTime, 0, GetEasing(ColorTransition, colorFadeTimer))) : targetColor; + return blendedColor; } protected virtual void Draw(SpriteBatch spriteBatch) { if (!Visible) return; var rect = Rect; - - Color currColor = GetCurrentColor(state); - if (currColor.A > 0.0f && (sprites == null || !sprites.Any())) GUI.DrawRectangle(spriteBatch, rect, currColor * (currColor.A / 255.0f), true); - if (sprites != null && sprites[state] != null && currColor.A > 0.0f) + GetBlendedColor(GetColor(State), ref _currentColor); + + if (_currentColor.A > 0.0f && (sprites == null || !sprites.Any())) { - foreach (UISprite uiSprite in sprites[state]) + GUI.DrawRectangle(spriteBatch, rect, _currentColor * (_currentColor.A / 255.0f), true); + } + + if (sprites != null && _currentColor.A > 0) + { + if (!sprites.TryGetValue(_previousState, out List previousSprites) || previousSprites.None()) { - uiSprite.Draw(spriteBatch, rect, currColor * (currColor.A / 255.0f), SpriteEffects); + switch (FallBackState) + { + case SpriteFallBackState.Toggle: + sprites.TryGetValue(Selected ? ComponentState.Selected : ComponentState.None, out previousSprites); + break; + default: + if (Enum.TryParse(FallBackState.ToString(), ignoreCase: true, out ComponentState fallBackState)) + { + sprites.TryGetValue(fallBackState, out previousSprites); + } + break; + } + } + // Handle fallbacks when some of the sprites are not defined + if (!sprites.TryGetValue(State, out List currentSprites) || currentSprites.None()) + { + switch (FallBackState) + { + case SpriteFallBackState.Toggle: + sprites.TryGetValue(Selected ? ComponentState.Selected : ComponentState.None, out currentSprites); + break; + default: + if (Enum.TryParse(FallBackState.ToString(), ignoreCase: true, out ComponentState fallBackState)) + { + sprites.TryGetValue(fallBackState, out currentSprites); + } + break; + } + } + if (_previousState != State && currentSprites != previousSprites) + { + if (previousSprites != null && previousSprites.Any()) + { + // Draw the previous sprites(s) only while cross fading out + Color previousColor = GetColor(_previousState); + foreach (UISprite uiSprite in previousSprites) + { + float alphaMultiplier = SpriteCrossFadeTime > 0 && (uiSprite.CrossFadeOut || currentSprites != null && currentSprites.Any(s => s.CrossFadeIn)) + ? MathUtils.InverseLerp(0, SpriteCrossFadeTime, GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : 0; + if (alphaMultiplier > 0) + { + uiSprite.Draw(spriteBatch, rect, previousColor * alphaMultiplier, SpriteEffects); + } + } + } + } + if (currentSprites != null && currentSprites.Any()) + { + // Draw the current sprite(s) + foreach (UISprite uiSprite in currentSprites) + { + float alphaMultiplier = SpriteCrossFadeTime > 0 && (uiSprite.CrossFadeIn || previousSprites != null && previousSprites.Any(s => s.CrossFadeOut)) + ? MathUtils.InverseLerp(SpriteCrossFadeTime, 0, GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : (_currentColor.A / 255.0f); + if (alphaMultiplier > 0) + { + uiSprite.Draw(spriteBatch, rect, _currentColor * alphaMultiplier, SpriteEffects); + } + } } } @@ -490,15 +631,16 @@ namespace Barotrauma //MathHelper.Pi * 0.8f -> the curve goes from 144 deg to 0, //i.e. quickly bumps up from almost full brightness to full and then fades out - if (!useRectangleFlash) + if (useRectangleFlash) { - GUI.UIGlow.Draw(spriteBatch, - flashRect, - flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f)); + GUI.DrawRectangle(spriteBatch, flashRect, flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), true); } else { - GUI.DrawRectangle(spriteBatch, flashRect, flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), true); + var glow = useCircularFlash ? GUI.UIGlowCircular : GUI.UIGlow; + glow.Draw(spriteBatch, + flashRect, + flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f)); } } } @@ -551,13 +693,14 @@ namespace Barotrauma color = new Color(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, a); } - public virtual void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, Vector2? flashRectInflate = null) + public virtual void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, bool useCircularFlash = false, Vector2? flashRectInflate = null) { flashTimer = flashDuration; this.flashRectInflate = flashRectInflate ?? Vector2.Zero; this.useRectangleFlash = useRectangleFlash; + this.useCircularFlash = useCircularFlash; this.flashDuration = flashDuration; - flashColor = (color == null) ? Color.Red : (Color)color; + flashColor = (color == null) ? GUI.Style.Red : (Color)color; } public void FadeOut(float duration, bool removeAfter) @@ -611,16 +754,37 @@ namespace Barotrauma public virtual void ApplyStyle(GUIComponentStyle style) { - if (style == null) return; + if (style == null) { return; } color = style.Color; + _currentColor = color; hoverColor = style.HoverColor; selectedColor = style.SelectedColor; pressedColor = style.PressedColor; - + disabledColor = style.DisabledColor; sprites = style.Sprites; - OutlineColor = style.OutlineColor; + SpriteCrossFadeTime = style.SpriteCrossFadeTime; + ColorCrossFadeTime = style.ColorCrossFadeTime; + ColorTransition = style.TransitionMode; + FallBackState = style.FallBackState; + + if (rectTransform != null) + { + if (style.Width.HasValue) + { + RectTransform.MinSize = new Point(style.Width.Value, RectTransform.MinSize.Y); + RectTransform.MaxSize = new Point(style.Width.Value, RectTransform.MaxSize.Y); + if (rectTransform.IsFixedSize) { RectTransform.Resize(new Point(style.Width.Value, rectTransform.NonScaledSize.Y)); } + } + if (style.Height.HasValue) + { + RectTransform.MinSize = new Point(RectTransform.MinSize.X, style.Height.Value); + RectTransform.MaxSize = new Point(RectTransform.MaxSize.X, style.Height.Value); + if (rectTransform.IsFixedSize) { RectTransform.Resize(new Point(rectTransform.NonScaledSize.X, style.Height.Value)); } + } + } + this.style = style; } @@ -779,14 +943,8 @@ namespace Barotrauma case "largefont": font = GUI.LargeFont; break; - case "videotitlefont": - font = GUI.VideoTitleFont; - break; - case "objectivetitlefont": - font = GUI.ObjectiveTitleFont; - break; - case "objectivenamefont": - font = GUI.ObjectiveNameFont; + case "subheading": + font = GUI.SubHeadingFont; break; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs index 0166e3510..0169c7bf5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIDropDown.cs @@ -13,8 +13,9 @@ namespace Barotrauma public OnSelectedHandler OnSelected; public OnSelectedHandler OnDropped; - private GUIButton button; - private GUIListBox listBox; + private readonly GUIButton button; + private readonly GUIImage icon; + private readonly GUIListBox listBox; private RectTransform currentHighestParent; private List parentHierarchy = new List(); @@ -41,7 +42,11 @@ namespace Barotrauma public bool ButtonEnabled { get { return button.Enabled; } - set { button.Enabled = value; } + set + { + button.Enabled = value; + if (icon != null) { icon.Enabled = value; } + } } public GUIComponent SelectedComponent @@ -49,6 +54,7 @@ namespace Barotrauma get { return listBox.SelectedComponent; } } + // TODO: fix implicit hiding public bool Selected { get @@ -157,17 +163,25 @@ namespace Barotrauma OnClicked = OnClicked }; GUI.Style.Apply(button, "", this); + button.TextBlock.SetTextPos(); Anchor listAnchor = dropAbove ? Anchor.TopCenter : Anchor.BottomCenter; Pivot listPivot = dropAbove ? Pivot.BottomCenter : Pivot.TopCenter; - listBox = new GUIListBox(new RectTransform(new Point(Rect.Width, Rect.Height * MathHelper.Clamp(elementCount, 2, 10)), rectT, listAnchor, listPivot) + { IsFixedSize = false }, style: null) { Enabled = !selectMultiple, OnSelected = SelectItem }; - GUI.Style.Apply(listBox.Content, "GUIListBox", this); + GUI.Style.Apply(listBox, "GUIListBox", this); + GUI.Style.Apply(listBox.ContentBackground, "GUIListBox", this); + + if (button.Style.ChildStyles.ContainsKey("dropdownicon")) + { + icon = new GUIImage(new RectTransform(new Vector2(0.6f, 0.6f), button.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point(5, 0) }, null, scaleToFit: true); + icon.ApplyStyle(button.Style.ChildStyles["dropdownicon"]); + } currentHighestParent = FindHighestParent(); currentHighestParent.GUIComponent.OnAddedToGUIUpdateList += AddListBoxToGUIUpdateList; @@ -253,6 +267,7 @@ namespace Barotrauma i++; } button.Text = string.Join(", ", texts); + // TODO: The callback is called at least twice, remove this? OnSelected?.Invoke(tb.Parent, tb.Parent.UserData); return true; } @@ -300,6 +315,7 @@ namespace Barotrauma button.Text = textBlock.Text; } Dropped = false; + // TODO: OnSelected can be called multiple times and when it shouldn't be called -> turn into an event so that nobody else can call it. OnSelected?.Invoke(component, component.UserData); return true; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIFrame.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIFrame.cs index 582eb986f..1f56aa1f0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIFrame.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIFrame.cs @@ -8,6 +8,7 @@ namespace Barotrauma { public GUIFrame(RectTransform rectT, string style = "", Color? color = null) : base(style, rectT) { + Enabled = true; if (color.HasValue) { this.color = color.Value; @@ -18,7 +19,7 @@ namespace Barotrauma { if (!Visible) return; - Color currColor = GetCurrentColor(state); + Color currColor = GetColor(State); if (sprites == null || !sprites.Any(s => s.Value.Any())) GUI.DrawRectangle(spriteBatch, Rect, currColor * (currColor.A/255.0f), true); base.Draw(spriteBatch); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIImage.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIImage.cs index 1f1d54575..9e950e020 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIImage.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIImage.cs @@ -87,7 +87,7 @@ namespace Barotrauma } if (style == null) { - color = hoverColor = selectedColor = pressedColor = Color.White; + color = hoverColor = selectedColor = pressedColor = disabledColor = Color.White; } if (!scaleToFit) { @@ -97,15 +97,17 @@ namespace Barotrauma { rectT.SizeChanged += RecalculateScale; } + Enabled = true; } protected override void Draw(SpriteBatch spriteBatch) { if (!Visible) return; - if (Parent != null) { state = Parent.State; } - if (OverrideState != null) { state = OverrideState.Value; } - Color currColor = GetCurrentColor(state); + if (Parent != null) { State = Parent.State; } + if (OverrideState != null) { State = OverrideState.Value; } + + Color currentColor = GetColor(State); if (BlendState != null) { @@ -115,23 +117,23 @@ namespace Barotrauma if (style != null) { - foreach (UISprite uiSprite in style.Sprites[state]) + foreach (UISprite uiSprite in style.Sprites[State]) { if (Math.Abs(Rotation) > float.Epsilon) { float scale = Math.Min(Rect.Width / uiSprite.Sprite.size.X, Rect.Height / uiSprite.Sprite.size.Y); - spriteBatch.Draw(uiSprite.Sprite.Texture, Rect.Center.ToVector2(), uiSprite.Sprite.SourceRect, currColor * (currColor.A / 255.0f), Rotation, uiSprite.Sprite.size / 2, + spriteBatch.Draw(uiSprite.Sprite.Texture, Rect.Center.ToVector2(), uiSprite.Sprite.SourceRect, currentColor * (currentColor.A / 255.0f), Rotation, uiSprite.Sprite.size / 2, Scale * scale, SpriteEffects, 0.0f); } else { - uiSprite.Draw(spriteBatch, Rect, currColor * (currColor.A / 255.0f), SpriteEffects); + uiSprite.Draw(spriteBatch, Rect, currentColor * (currentColor.A / 255.0f), SpriteEffects); } } } else if (sprite?.Texture != null) { - spriteBatch.Draw(sprite.Texture, Rect.Center.ToVector2(), sourceRect, currColor * (currColor.A / 255.0f), Rotation, sprite.size / 2, + spriteBatch.Draw(sprite.Texture, Rect.Center.ToVector2(), sourceRect, currentColor * (currentColor.A / 255.0f), Rotation, sprite.size / 2, Scale, SpriteEffects, 0.0f); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUILayoutGroup.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUILayoutGroup.cs index 96bc0edd8..7658be341 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUILayoutGroup.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUILayoutGroup.cs @@ -68,6 +68,10 @@ namespace Barotrauma public bool NeedsToRecalculate { get { return needsToRecalculate; } + set + { + if (value) { needsToRecalculate = true; } + } } public GUILayoutGroup(RectTransform rectT, bool isHorizontal = false, Anchor childAnchor = Anchor.TopLeft) : base(null, rectT) @@ -86,20 +90,49 @@ namespace Barotrauma float stretchFactor = 1.0f; if (stretch && RectTransform.Children.Count() > 0) { + foreach (RectTransform child in RectTransform.Children) + { + if (child.GUIComponent.IgnoreLayoutGroups) { continue; } + if (child.ScaleBasis == ScaleBasis.BothHeight) { child.MinSize = new Point(child.Rect.Height, child.MinSize.Y); } + if (child.ScaleBasis == ScaleBasis.BothWidth) { child.MinSize = new Point(child.MinSize.X, child.Rect.Width); } + if (child.ScaleBasis == ScaleBasis.Smallest) + { + if (Rect.Width < Rect.Height) + { + child.MinSize = new Point(child.MinSize.X, child.Rect.Width); + } + else + { + child.MinSize = new Point(child.Rect.Height, child.MinSize.Y); + } + } + if (child.ScaleBasis == ScaleBasis.Largest) + { + if (Rect.Width > Rect.Height) + { + child.MinSize = new Point(child.MinSize.X, child.Rect.Width); + } + else + { + child.MinSize = new Point(child.Rect.Height, child.MinSize.Y); + } + } + } + float minSize = RectTransform.Children .Where(c => !c.GUIComponent.IgnoreLayoutGroups) - .Sum(c => isHorizontal ? c.MinSize.X : c.MinSize.Y); + .Sum(c => isHorizontal ? (c.IsFixedSize ? c.NonScaledSize.X : c.MinSize.X) : (c.IsFixedSize ? c.NonScaledSize.Y : c.MinSize.Y)); float totalSize = RectTransform.Children .Where(c => !c.GUIComponent.IgnoreLayoutGroups) - .Sum(c => isHorizontal ? - MathHelper.Clamp(c.Rect.Width, c.MinSize.X, c.MaxSize.X) : - MathHelper.Clamp(c.Rect.Height, c.MinSize.Y, c.MaxSize.Y)); + .Sum(c => isHorizontal ? + (c.IsFixedSize ? c.Rect.Width : MathHelper.Clamp(c.Rect.Width, c.MinSize.X, c.MaxSize.X)) : + (c.IsFixedSize ? c.Rect.Height : MathHelper.Clamp(c.Rect.Height, c.MinSize.Y, c.MaxSize.Y))); float thisSize = (isHorizontal ? Rect.Width : Rect.Height); - totalSize += - (RectTransform.Children.Count() - 1) * + totalSize += + (RectTransform.Children.Count(c => !c.GUIComponent.IgnoreLayoutGroups) - 1) * (absoluteSpacing + relativeSpacing * thisSize); stretchFactor = totalSize <= 0.0f || minSize >= thisSize ? @@ -117,20 +150,34 @@ namespace Barotrauma { child.RelativeOffset = new Vector2(relPos, child.RelativeOffset.Y); child.AbsoluteOffset = new Point(absPos, child.AbsoluteOffset.Y); - absPos += (int)Math.Max((child.Rect.Width + absoluteSpacing) * stretchFactor, child.MinSize.X); - if (stretch) + if (child.IsFixedSize) { - child.RelativeSize = new Vector2(child.RelativeSize.X * stretchFactor, child.RelativeSize.Y); + absPos += child.NonScaledSize.X + absoluteSpacing; + } + else + { + absPos += (int)(MathHelper.Clamp(child.Rect.Width * stretchFactor, child.MinSize.X, child.MaxSize.X) + (absoluteSpacing * stretchFactor)); + if (stretch) + { + child.RelativeSize = new Vector2(child.RelativeSize.X * stretchFactor, child.RelativeSize.Y); + } } } else { child.RelativeOffset = new Vector2(child.RelativeOffset.X, relPos); child.AbsoluteOffset = new Point(child.AbsoluteOffset.X, absPos); - absPos += (int)Math.Max((child.Rect.Height + absoluteSpacing) * stretchFactor, child.MinSize.Y); - if (stretch) + if (child.IsFixedSize) { - child.RelativeSize = new Vector2(child.RelativeSize.X, child.RelativeSize.Y * stretchFactor); + absPos += child.NonScaledSize.Y + absoluteSpacing; + } + else + { + absPos += (int)(MathHelper.Clamp(child.Rect.Height * stretchFactor, child.MinSize.Y, child.MaxSize.Y) + (absoluteSpacing * stretchFactor)); + if (stretch) + { + child.RelativeSize = new Vector2(child.RelativeSize.X, child.RelativeSize.Y * stretchFactor); + } } } relPos += relativeSpacing * stretchFactor; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs index 7d80ed8d1..a0bbc100c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs @@ -22,8 +22,16 @@ namespace Barotrauma public delegate void OnRearrangedHandler(GUIListBox listBox, object obj); public OnRearrangedHandler OnRearranged; - public GUIScrollBar ScrollBar { get; private set; } + /// + /// A frame drawn behind the content of the listbox + /// + public GUIFrame ContentBackground { get; private set; } + + /// + /// A frame that contains the contents of the listbox. The frame itself is not rendered. + /// public GUIFrame Content { get; private set; } + public GUIScrollBar ScrollBar { get; private set; } private Dictionary childVisible = new Dictionary(); @@ -33,7 +41,7 @@ namespace Barotrauma private bool dimensionsNeedsRecalculation; // TODO: Define in styles? - private int scrollBarSize = 20; + private int scrollBarSize = 25; public bool SelectMultiple; @@ -53,6 +61,18 @@ namespace Barotrauma } } + private Vector4? overridePadding; + public Vector4 Padding + { + get + { + if (overridePadding.HasValue) { return overridePadding.Value; } + if (Style == null) { return Vector4.Zero; } + return Style.Padding; + } + set { overridePadding = value; } + } + public GUIComponent SelectedComponent { get @@ -61,6 +81,7 @@ namespace Barotrauma } } + // TODO: fix implicit hiding public bool Selected { get; set; } public List AllSelected @@ -148,14 +169,20 @@ namespace Barotrauma private Rectangle draggedReferenceRectangle; private Point draggedReferenceOffset; + public GUIComponent DraggedElement => draggedElement; + public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "") : base(style, rectT) { CanBeFocused = true; selected = new List(); - Content = new GUIFrame(new RectTransform(Vector2.One, rectT), style) + ContentBackground = new GUIFrame(new RectTransform(Vector2.One, rectT), style) { CanBeFocused = false }; + Content = new GUIFrame(new RectTransform(Vector2.One, ContentBackground.RectTransform), style: null) + { + CanBeFocused = false + }; Content.RectTransform.ChildrenChanged += (_) => { scrollBarNeedsRecalculation = true; @@ -163,7 +190,7 @@ namespace Barotrauma }; if (style != null) { - GUI.Style.Apply(Content, "", this); + GUI.Style.Apply(ContentBackground, "", this); } if (color.HasValue) { @@ -173,15 +200,17 @@ namespace Barotrauma Anchor anchor; if (isHorizontal) { - size = new Point(Rect.Width, scrollBarSize); - anchor = Anchor.BottomLeft; + size = new Point((int)(Rect.Width - Padding.X - Padding.Z), (int)(scrollBarSize * GUI.Scale)); + anchor = Anchor.BottomCenter; } else { - size = new Point(scrollBarSize, Rect.Height); - anchor = Anchor.TopRight; + size = new Point((int)(scrollBarSize * GUI.Scale), (int)(Rect.Height - Padding.Y - Padding.W)); + anchor = Anchor.CenterRight; } - ScrollBar = new GUIScrollBar(new RectTransform(size, rectT, anchor), isHorizontal: isHorizontal); + ScrollBar = new GUIScrollBar(new RectTransform(size, rectT, anchor) + { AbsoluteOffset = isHorizontal ? new Point(0, (int)Padding.W) : new Point((int)Padding.Z, 0) }, + isHorizontal: isHorizontal); UpdateScrollBarSize(); Enabled = true; ScrollBar.BarScroll = 0.0f; @@ -193,9 +222,18 @@ namespace Barotrauma private void UpdateDimensions() { dimensionsNeedsRecalculation = false; + ContentBackground.RectTransform.Resize(Rect.Size); bool reduceScrollbarSize = KeepSpaceForScrollBar ? ScrollBarEnabled : ScrollBarVisible; - Content.RectTransform.Resize(reduceScrollbarSize ? CalculateFrameSize(ScrollBar.IsHorizontal, scrollBarSize) : Rect.Size); - ScrollBar.RectTransform.Resize(ScrollBar.IsHorizontal ? new Point(Rect.Width, scrollBarSize) : new Point(scrollBarSize, Rect.Height)); + Point contentSize = reduceScrollbarSize ? CalculateFrameSize(ScrollBar.IsHorizontal, scrollBarSize) : Rect.Size; + Content.RectTransform.Resize(new Point((int)(contentSize.X - Padding.X - Padding.Z), (int)(contentSize.Y - Padding.Y - Padding.W))); + Content.RectTransform.AbsoluteOffset = new Point((int)Padding.X, (int)Padding.Y); + ScrollBar.RectTransform.Resize(ScrollBar.IsHorizontal ? + new Point((int)(Rect.Width - Padding.X - Padding.Z), (int)(scrollBarSize * GUI.Scale)) : + new Point((int)(scrollBarSize * GUI.Scale), (int)(Rect.Height - Padding.Y - Padding.W))); + ScrollBar.RectTransform.AbsoluteOffset = ScrollBar.IsHorizontal ? + new Point(0, (int)Padding.W) : + new Point((int)Padding.Z, 0); + UpdateScrollBarSize(); } public void Select(object userData, bool force = false, bool autoScroll = true) @@ -380,7 +418,7 @@ namespace Barotrauma { foreach (GUIComponent child in Children) { - if (child == Content || child == ScrollBar) { continue; } + if (child == Content || child == ScrollBar || child == ContentBackground) { continue; } child.AddToGUIUpdateList(ignoreChildren, order); } } @@ -411,7 +449,7 @@ namespace Barotrauma OnAddedToGUIUpdateList?.Invoke(this); return; } - Content.AddToGUIUpdateList(true, order); + int lastVisible = 0; for (int i = 0; i < Content.CountChildren; i++) { @@ -516,7 +554,11 @@ namespace Barotrauma GUIComponent child = Content.GetChild(childIndex); bool wasSelected = true; - if (OnSelected != null) wasSelected = force || OnSelected(child, child.UserData); + if (OnSelected != null) + { + // TODO: The callback is called twice, fix this! + wasSelected = force || OnSelected(child, child.UserData); + } if (!wasSelected) { return; } @@ -638,10 +680,10 @@ namespace Barotrauma totalSize += Content.CountChildren * Spacing; } - + float minScrollBarSize = 20.0f; ScrollBar.BarSize = ScrollBar.IsHorizontal ? - Math.Max(Math.Min(Content.Rect.Width / (float)totalSize, 1.0f), 5.0f / Content.Rect.Width) : - Math.Max(Math.Min(Content.Rect.Height / (float)totalSize, 1.0f), 5.0f / Content.Rect.Height); + Math.Max(Math.Min(Content.Rect.Width / (float)totalSize, 1.0f), minScrollBarSize / Content.Rect.Width) : + Math.Max(Math.Min(Content.Rect.Height / (float)totalSize, 1.0f), minScrollBarSize / Content.Rect.Height); } public override void ClearChildren() @@ -668,8 +710,8 @@ namespace Barotrauma { if (!Visible) { return; } - Content.DrawManually(spriteBatch, alsoChildren: false); - + ContentBackground.DrawManually(spriteBatch, alsoChildren: false); + Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle; RasterizerState prevRasterizerState = spriteBatch.GraphicsDevice.RasterizerState; if (HideChildrenOutsideFrame) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs index 6f642d799..9eb0be459 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs @@ -90,7 +90,7 @@ namespace Barotrauma Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 }; Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), - headerText, textAlignment: Alignment.Center, wrap: true); + headerText, font: GUI.SubHeadingFont, textAlignment: Alignment.Center, wrap: true); GUI.Style.Apply(Header, "", this); Header.RectTransform.MinSize = new Point(0, Header.Rect.Height); @@ -103,21 +103,28 @@ namespace Barotrauma Text.RectTransform.IsFixedSize = true; } - var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), Content.RectTransform, Anchor.BottomCenter, maxSize: new Point(1000, 50)), - isHorizontal: true, childAnchor: buttons.Length > 1 ? Anchor.BottomLeft : Anchor.Center) + var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), Content.RectTransform, Anchor.BottomCenter), childAnchor: Anchor.TopCenter) { AbsoluteSpacing = 5, IgnoreLayoutGroups = true }; + + int buttonSize = 35; + var buttonStyle = GUI.Style.GetComponentStyle("GUIButton"); + if (buttonStyle != null && buttonStyle.Height.HasValue) + { + buttonSize = buttonStyle.Height.Value; + } + buttonContainer.RectTransform.NonScaledSize = buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.MaxSize = - new Point(buttonContainer.Rect.Width, (int)(30 * GUI.Scale)); + new Point(buttonContainer.Rect.Width, (int)((buttonSize + 5) * buttons.Length)); buttonContainer.RectTransform.IsFixedSize = true; if (height == 0) { height += Header.Rect.Height + Content.AbsoluteSpacing; height += (Text == null ? 0 : Text.Rect.Height) + Content.AbsoluteSpacing; - height += buttonContainer.Rect.Height; + height += buttonContainer.Rect.Height + 20; if (minSize.HasValue) { height = Math.Max(height, minSize.Value.Y); } InnerFrame.RectTransform.NonScaledSize = @@ -129,7 +136,7 @@ namespace Barotrauma Buttons = new List(buttons.Length); for (int i = 0; i < buttons.Length; i++) { - var button = new GUIButton(new RectTransform(new Vector2(Math.Min(0.9f / buttons.Length, 0.5f), 1.0f), buttonContainer.RectTransform), buttons[i], style: "GUIButtonLarge"); + var button = new GUIButton(new RectTransform(new Vector2(0.6f, 1.0f / buttons.Length), buttonContainer.RectTransform), buttons[i]); Buttons.Add(button); } } @@ -157,7 +164,7 @@ namespace Barotrauma Buttons = new List(1) { new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), buttonContainer.RectTransform, Anchor.Center), - style: GUI.Style.GetComponentStyle("GUIButtonSolidHorizontalArrow") != null ? "GUIButtonSolidHorizontalArrow" : "GUIButtonHorizontalArrow") + style: "GUIButtonHorizontalArrow") { OnClicked = Close } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUINumberInput.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUINumberInput.cs index 8b978470c..1dc280621 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUINumberInput.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUINumberInput.cs @@ -16,8 +16,8 @@ namespace Barotrauma public OnValueChangedHandler OnValueChanged; public GUITextBox TextBox { get; private set; } - public GUIButton PlusButton { get; private set; } - public GUIButton MinusButton { get; private set; } + + private GUIButton plusButton, minusButton; private NumberType inputType; public NumberType InputType @@ -25,10 +25,17 @@ namespace Barotrauma get { return inputType; } set { + if (inputType == value) { return; } inputType = value; - PlusButton.Visible = inputType == NumberType.Int || - (inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue); - MinusButton.Visible = PlusButton.Visible; + if (inputType == NumberType.Int || + (inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue)) + { + ShowPlusMinusButtons(); + } + else + { + HidePlusMinusButtons(); + } } } @@ -40,9 +47,15 @@ namespace Barotrauma { minValueFloat = value; ClampFloatValue(); - PlusButton.Visible = inputType == NumberType.Int || - (inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue); - MinusButton.Visible = PlusButton.Visible; + if (inputType == NumberType.Int || + (inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue)) + { + ShowPlusMinusButtons(); + } + else + { + HidePlusMinusButtons(); + } } } public float? MaxValueFloat @@ -52,9 +65,15 @@ namespace Barotrauma { maxValueFloat = value; ClampFloatValue(); - PlusButton.Visible = inputType == NumberType.Int || - (inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue); - MinusButton.Visible = PlusButton.Visible; + if (inputType == NumberType.Int || + (inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue)) + { + ShowPlusMinusButtons(); + } + else + { + HidePlusMinusButtons(); + } } } @@ -124,14 +143,14 @@ namespace Barotrauma get => base.Enabled; set { - PlusButton.Enabled = true; - MinusButton.Enabled = true; + plusButton.Enabled = true; + minusButton.Enabled = true; if (InputType == NumberType.Int) { ClampIntValue(); } else { ClampFloatValue(); } TextBox.Enabled = value; if (!value) { - PlusButton.Enabled = false; - MinusButton.Enabled = false; + plusButton.Enabled = false; + minusButton.Enabled = false; } } } @@ -163,37 +182,31 @@ namespace Barotrauma public GUINumberInput(RectTransform rectT, NumberType inputType, string style = "", Alignment textAlignment = Alignment.Center, float? relativeButtonAreaWidth = null) : base(style, rectT) { - LayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), isHorizontal: true) { Stretch = true }; + LayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true }; - float _relativeButtonAreaWidth = relativeButtonAreaWidth ?? MathHelper.Clamp(Rect.Height / (float)Rect.Width, 0.1f, 0.5f); + float _relativeButtonAreaWidth = relativeButtonAreaWidth ?? MathHelper.Clamp(Rect.Height / (float)Rect.Width, 0.1f, 0.25f); - TextBox = new GUITextBox(new RectTransform(new Vector2(1.0f - _relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform), textAlignment: textAlignment, style: style) + TextBox = new GUITextBox(new RectTransform(new Vector2(1.0f - _relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform), textAlignment: textAlignment, style: "GUITextBoxNoIcon") { - ClampText = false, - // For some reason the caret in the number inputs is dimmer than it should. - // It should not be rendered behind anything, as I first suspected. - // Therefore this hack. - CaretColor = Color.White + ClampText = false }; + TextBox.CaretColor = TextBox.TextColor; TextBox.OnTextChanged += TextChanged; + var buttonArea = new GUIFrame(new RectTransform(new Vector2(_relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform, Anchor.CenterRight), style: null); - /*if (!relativeButtonAreaWidth.HasValue) - { - // Not sure what's the point of this - buttonArea.RectTransform.MinSize = new Point(Rect.Height, 0); - }*/ - PlusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), "+", font: GUI.GlobalFont); - PlusButton.OnButtonDown += () => + plusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), style: null); + GUI.Style.Apply(plusButton, "PlusButton", this); + plusButton.OnButtonDown += () => { pressedTimer = pressedDelay; return true; }; - PlusButton.OnClicked += (button, data) => + plusButton.OnClicked += (button, data) => { IncreaseValue(); return true; }; - PlusButton.OnPressed += () => + plusButton.OnPressed += () => { if (!IsPressedTimerRunning) { @@ -201,20 +214,20 @@ namespace Barotrauma } return true; }; - PlusButton.Visible = inputType == NumberType.Int; - MinusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), "-", font: GUI.GlobalFont); - MinusButton.OnButtonDown += () => + minusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), style: null); + GUI.Style.Apply(minusButton, "MinusButton", this); + minusButton.OnButtonDown += () => { pressedTimer = pressedDelay; return true; }; - MinusButton.OnClicked += (button, data) => + minusButton.OnClicked += (button, data) => { ReduceValue(); return true; }; - MinusButton.OnPressed += () => + minusButton.OnPressed += () => { if (!IsPressedTimerRunning) { @@ -222,7 +235,11 @@ namespace Barotrauma } return true; }; - MinusButton.Visible = inputType == NumberType.Int; + + if (inputType != NumberType.Int) + { + HidePlusMinusButtons(); + } if (inputType == NumberType.Int) { @@ -257,6 +274,23 @@ namespace Barotrauma break; } + RectTransform.MinSize = TextBox.RectTransform.MinSize; + LayoutGroup.Recalculate(); + } + + private void HidePlusMinusButtons() + { + plusButton.Parent.Visible = false; + plusButton.Parent.IgnoreLayoutGroups = true; + TextBox.RectTransform.RelativeSize = Vector2.One; + LayoutGroup.Recalculate(); + } + + private void ShowPlusMinusButtons() + { + plusButton.Parent.Visible = true; + plusButton.Parent.IgnoreLayoutGroups = false; + TextBox.RectTransform.RelativeSize = new Vector2(1.0f - plusButton.Parent.RectTransform.RelativeSize.X, 1.0f); LayoutGroup.Recalculate(); } @@ -336,12 +370,12 @@ namespace Barotrauma if (MinValueFloat != null) { floatValue = Math.Max(floatValue, MinValueFloat.Value); - MinusButton.Enabled = floatValue > MinValueFloat; + minusButton.Enabled = floatValue > MinValueFloat; } if (MaxValueFloat != null) { floatValue = Math.Min(floatValue, MaxValueFloat.Value); - PlusButton.Enabled = floatValue < MaxValueFloat; + plusButton.Enabled = floatValue < MaxValueFloat; } } @@ -350,12 +384,12 @@ namespace Barotrauma if (MinValueInt != null) { intValue = Math.Max(intValue, MinValueInt.Value); - MinusButton.Enabled = intValue > MinValueInt; + minusButton.Enabled = intValue > MinValueInt; } if (MaxValueInt != null) { intValue = Math.Min(intValue, MaxValueInt.Value); - PlusButton.Enabled = intValue < MaxValueInt; + plusButton.Enabled = intValue < MaxValueInt; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIProgressBar.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIProgressBar.cs index b8ea1f87d..a6b66afe2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIProgressBar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIProgressBar.cs @@ -10,6 +10,7 @@ namespace Barotrauma private GUIFrame frame, slider; private float barSize; + private bool showFrame; public delegate float ProgressGetterHandler(); public ProgressGetterHandler ProgressGetter; @@ -38,7 +39,7 @@ namespace Barotrauma } } - public GUIProgressBar(RectTransform rectT, float barSize, Color? color = null, string style = "") : base(style, rectT) + public GUIProgressBar(RectTransform rectT, float barSize, Color? color = null, string style = "", bool showFrame = true) : base(style, rectT) { if (color.HasValue) { @@ -49,12 +50,14 @@ namespace Barotrauma GUI.Style.Apply(frame, "", this); slider = new GUIFrame(new RectTransform(Vector2.One, rectT)); GUI.Style.Apply(slider, "Slider", this); + this.showFrame = showFrame; this.barSize = barSize; + Enabled = true; } protected override void Draw(SpriteBatch spriteBatch) { - if (!Visible) return; + if (!Visible) { return; } if (ProgressGetter != null) { @@ -73,20 +76,31 @@ namespace Barotrauma } Rectangle sliderRect = new Rectangle( - frame.Rect.X, - (int)(frame.Rect.Y + (isHorizontal ? 0 : frame.Rect.Height * (1.0f - barSize))), - isHorizontal ? (int)((frame.Rect.Width) * barSize) : frame.Rect.Width, - isHorizontal ? (int)(frame.Rect.Height) : (int)(frame.Rect.Height * barSize)); - - frame.Visible = true; + frame.Rect.X + (int)style.Padding.X, + (int)(frame.Rect.Y + (int)style.Padding.Y + (isHorizontal ? 0 : frame.Rect.Height * (1.0f - barSize))), + isHorizontal ? (int)((frame.Rect.Width - style.Padding.X - style.Padding.Z) * barSize) : frame.Rect.Width, + isHorizontal ? (int)(frame.Rect.Height - style.Padding.Y - style.Padding.W) : (int)(frame.Rect.Height * barSize)); + + sliderRect.Width = Math.Max(sliderRect.Width, 1); + sliderRect.Height = Math.Max(sliderRect.Height, 1); + + slider.RectTransform.AbsoluteOffset = new Point((int)style.Padding.X, (int)style.Padding.Y); + slider.RectTransform.MaxSize = new Point( + (int)(Rect.Width - style.Padding.X + style.Padding.Z), + (int)(Rect.Height - style.Padding.Y + style.Padding.W)); + frame.Visible = showFrame; slider.Visible = true; - if (AutoDraw) + + if (showFrame) { - frame.DrawAuto(spriteBatch); - } - else - { - frame.DrawManually(spriteBatch); + if (AutoDraw) + { + frame.DrawAuto(spriteBatch); + } + else + { + frame.DrawManually(spriteBatch); + } } Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle; @@ -97,7 +111,7 @@ namespace Barotrauma spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable); } - Color currColor = GetCurrentColor(state); + Color currColor = GetColor(State); slider.Color = currColor; if (AutoDraw) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIRadioButtonGroup.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIRadioButtonGroup.cs index 1ca22acf1..1cda5de9b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIRadioButtonGroup.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIRadioButtonGroup.cs @@ -54,8 +54,9 @@ namespace Barotrauma } } - private int? selected; - public int? Selected + // intentional hiding? + private new int? selected; + public new int? Selected { get { @@ -64,7 +65,7 @@ namespace Barotrauma set { OnSelect?.Invoke(this, value); - if (selected != null && selected.Equals(value)) return; + if (selected != null && selected.Equals(value)) { return; } selected = value; foreach (KeyValuePair radioButton in radioButtons) { @@ -72,7 +73,10 @@ namespace Barotrauma { radioButton.Value.Selected = true; } - else if (radioButton.Value.Selected) radioButton.Value.Selected = false; + else if (radioButton.Value.Selected) + { + radioButton.Value.Selected = false; + } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIScrollBar.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIScrollBar.cs index 1e3d75944..55a2d545f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIScrollBar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIScrollBar.cs @@ -80,7 +80,11 @@ namespace Barotrauma { enabled = value; Bar.Enabled = value; - if (!enabled) Bar.Selected = false; + Children.ForEach(c => c.Enabled = value); + if (!enabled) + { + Bar.Selected = false; + } } } @@ -196,7 +200,8 @@ namespace Barotrauma Frame = new GUIFrame(new RectTransform(Vector2.One, rectT)); GUI.Style.Apply(Frame, IsHorizontal ? "GUIFrameHorizontal" : "GUIFrameVertical", this); this.barSize = barSize; - Bar = new GUIButton(new RectTransform(Vector2.One, rectT, IsHorizontal ? Anchor.CenterLeft : Anchor.TopCenter), color: color); + + Bar = new GUIButton(new RectTransform(Vector2.One, rectT, IsHorizontal ? Anchor.CenterLeft : Anchor.TopCenter), color: color, style: null); switch (style) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs index 8acb44547..d5ccc022b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs @@ -21,16 +21,50 @@ namespace Barotrauma public ScalableFont UnscaledSmallFont { get; private set; } public ScalableFont SmallFont { get; private set; } public ScalableFont LargeFont { get; private set; } - public ScalableFont VideoTitleFont { get; private set; } - public ScalableFont ObjectiveTitleFont { get; private set; } - public ScalableFont ObjectiveNameFont { get; private set; } + public ScalableFont SubHeadingFont { get; private set; } + public ScalableFont DigitalFont { get; private set; } + + public Dictionary ForceFontUpperCase + { + get; + private set; + } = new Dictionary(); public readonly Sprite[] CursorSprite = new Sprite[7]; public UISprite UIGlow { get; private set; } + public UISprite UIGlowCircular { get; private set; } public SpriteSheet FocusIndicator { get; private set; } - + + /// + /// General green color used for elements whose colors are set from code + /// + public Color Green { get; private set; } = Color.LightGreen; + + /// + /// General red color used for elements whose colors are set from code + /// + public Color Orange { get; private set; } = Color.Orange; + + /// + /// General red color used for elements whose colors are set from code + /// + public Color Red { get; private set; } = Color.Red; + + /// + /// General blue color used for elements whose colors are set from code + /// + public Color Blue { get; private set; } = Color.Blue; + + public Color TextColor { get; private set; } = Color.White * 0.8f; + public Color TextColorBright { get; private set; } = Color.White * 0.9f; + public Color TextColorDark { get; private set; } = Color.Black * 0.9f; + public Color TextColorDim { get; private set; } = Color.White * 0.6f; + + public static Point ItemFrameMargin = new Point(50, 56); + public static Point ItemFrameOffset = new Point(0, 3); + public GUIStyle(XElement element, GraphicsDevice graphicsDevice) { this.graphicsDevice = graphicsDevice; @@ -48,38 +82,71 @@ namespace Barotrauma CursorSprite[index] = new Sprite(children); } break; + case "green": + Green = subElement.GetAttributeColor("color", Green); + break; + case "orange": + Orange = subElement.GetAttributeColor("color", Orange); + break; + case "red": + Red = subElement.GetAttributeColor("color", Red); + break; + case "blue": + Blue = subElement.GetAttributeColor("color", Blue); + break; + case "textcolordark": + TextColorDark = subElement.GetAttributeColor("color", TextColorDark); + break; + case "TextColorBright": + TextColorBright = subElement.GetAttributeColor("color", TextColorBright); + break; + case "textcolordim": + TextColorDim = subElement.GetAttributeColor("color", TextColorDim); + break; + case "textcolornormal": + case "textcolor": + TextColor = subElement.GetAttributeColor("color", TextColor); + break; case "uiglow": UIGlow = new UISprite(subElement); break; + case "uiglowcircular": + UIGlowCircular = new UISprite(subElement); + break; case "focusindicator": FocusIndicator = new SpriteSheet(subElement); break; case "font": Font = LoadFont(subElement, graphicsDevice); + ForceFontUpperCase[Font] = subElement.GetAttributeBool("forceuppercase", false); break; case "globalfont": GlobalFont = LoadFont(subElement, graphicsDevice); + ForceFontUpperCase[GlobalFont] = subElement.GetAttributeBool("forceuppercase", false); break; case "unscaledsmallfont": UnscaledSmallFont = LoadFont(subElement, graphicsDevice); + ForceFontUpperCase[UnscaledSmallFont] = subElement.GetAttributeBool("forceuppercase", false); break; case "smallfont": SmallFont = LoadFont(subElement, graphicsDevice); + ForceFontUpperCase[SmallFont] = subElement.GetAttributeBool("forceuppercase", false); break; case "largefont": LargeFont = LoadFont(subElement, graphicsDevice); + ForceFontUpperCase[LargeFont] = subElement.GetAttributeBool("forceuppercase", false); + break; + case "digitalfont": + DigitalFont = LoadFont(subElement, graphicsDevice); + ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false); break; case "objectivetitle": - ObjectiveTitleFont = LoadFont(subElement, graphicsDevice); - break; - case "objectivename": - ObjectiveNameFont = LoadFont(subElement, graphicsDevice); - break; - case "videotitle": - VideoTitleFont = LoadFont(subElement, graphicsDevice); + case "subheading": + SubHeadingFont = LoadFont(subElement, graphicsDevice); + ForceFontUpperCase[SubHeadingFont] = subElement.GetAttributeBool("forceuppercase", false); break; default: - GUIComponentStyle componentStyle = new GUIComponentStyle(subElement); + GUIComponentStyle componentStyle = new GUIComponentStyle(subElement, this); componentStyles.Add(subElement.Name.ToString().ToLowerInvariant(), componentStyle); break; } @@ -91,7 +158,7 @@ namespace Barotrauma DebugConsole.NewMessage("Global font not defined in the current UI style file. The global font is used to render western symbols when using Chinese/Japanese/Korean localization. Using default font instead...", Color.Orange); } - GameMain.Instance.OnResolutionChanged += () => { RescaleFonts(); }; + GameMain.Instance.OnResolutionChanged += () => { RescaleElements(); }; } /// @@ -114,7 +181,7 @@ namespace Barotrauma } - private void RescaleFonts() + private void RescaleElements() { if (configElement == null) { return; } if (configElement.Elements() == null) { return; } @@ -135,19 +202,21 @@ namespace Barotrauma LargeFont.Size = GetFontSize(subElement); break; case "objectivetitle": - if (ObjectiveTitleFont == null) { continue; } - ObjectiveTitleFont.Size = GetFontSize(subElement); - break; - case "objectivename": - if (ObjectiveNameFont == null) { continue; } - ObjectiveNameFont.Size = GetFontSize(subElement); - break; - case "videotitle": - if (VideoTitleFont == null) { continue; } - VideoTitleFont.Size = GetFontSize(subElement); + case "subheading": + if (SubHeadingFont == null) { continue; } + SubHeadingFont.Size = GetFontSize(subElement); break; } } + + foreach (var componentStyle in componentStyles.Values) + { + componentStyle.GetSize(componentStyle.Element); + foreach (var childStyle in componentStyle.ChildStyles.Values) + { + childStyle.GetSize(childStyle.Element); + } + } } private ScalableFont LoadFont(XElement element, GraphicsDevice graphicsDevice) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs index d6a293311..13ba4cbe6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs @@ -16,8 +16,8 @@ namespace Barotrauma protected Vector2 textPos; protected Vector2 origin; - - protected Color textColor; + + protected Color textColor, disabledTextColor, selectedTextColor; private string wrappedText; private string censoredText; @@ -63,8 +63,12 @@ namespace Barotrauma } set { - if (base.Font == value) return; + if (base.Font == value) { return; } base.Font = originalFont = value; + if (text != null && GUI.Style.ForceFontUpperCase.ContainsKey(Font) && GUI.Style.ForceFontUpperCase[Font]) + { + Text = text.ToUpper(); + } SetTextPos(); } } @@ -74,11 +78,12 @@ namespace Barotrauma get { return text; } set { - string newText = forceUpperCase ? value?.ToUpper() : value; + string newText = forceUpperCase || (GUI.Style.ForceFontUpperCase.ContainsKey(Font) && GUI.Style.ForceFontUpperCase[Font]) || (style != null && style.ForceUpperCase) ? + value?.ToUpper() : + value; if (Text == newText) { return; } - //reset scale, it gets recalculated in SetTextPos if (autoScale) { textScale = 1.0f; } @@ -155,7 +160,9 @@ namespace Barotrauma if (forceUpperCase == value) { return; } forceUpperCase = value; - if (forceUpperCase) + if (forceUpperCase || + (style != null && style.ForceUpperCase) || + (GUI.Style.ForceFontUpperCase.ContainsKey(Font) && GUI.Style.ForceFontUpperCase[Font])) { Text = text?.ToUpper(); } @@ -179,6 +186,19 @@ namespace Barotrauma set { textColor = value; } } + private Color? hoverTextColor; + public Color HoverTextColor + { + get { return hoverTextColor ?? textColor; } + set { hoverTextColor = value; } + } + + public Color SelectedTextColor + { + get { return selectedTextColor; } + set { selectedTextColor = value; } + } + public Alignment TextAlignment { get { return textAlignment; } @@ -218,7 +238,7 @@ namespace Barotrauma } if (textColor.HasValue) { - this.textColor = textColor.Value; + OverrideTextColor(textColor.Value); } //if the text is in chinese/korean/japanese and we're not using a CJK-compatible font, @@ -242,6 +262,7 @@ namespace Barotrauma RectTransform.ScaleChanged += SetTextPos; RectTransform.SizeChanged += SetTextPos; + Enabled = true; Censor = false; } public GUITextBlock(RectTransform rectT, List colorData, string text, Color? textColor = null, ScalableFont font = null, Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = false) @@ -257,13 +278,33 @@ namespace Barotrauma RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(wrappedText).Y + padding)); } - public override void ApplyStyle(GUIComponentStyle style) + public override void ApplyStyle(GUIComponentStyle componentStyle) { - if (style == null) return; - base.ApplyStyle(style); - padding = style.Padding; + if (componentStyle == null) { return; } + base.ApplyStyle(componentStyle); + padding = componentStyle.Padding; - textColor = style.textColor; + textColor = componentStyle.TextColor; + hoverTextColor = componentStyle.HoverTextColor; + disabledTextColor = componentStyle.DisabledTextColor; + selectedTextColor = componentStyle.SelectedTextColor; + + switch (componentStyle.Font) + { + case "font": + Font = componentStyle.Style.Font; + break; + case "smallfont": + Font = componentStyle.Style.SmallFont; + break; + case "largefont": + Font = componentStyle.Style.LargeFont; + break; + case "objectivetitle": + case "subheading": + Font = componentStyle.Style.SubHeadingFont; + break; + } } public void SetTextPos() @@ -293,11 +334,14 @@ namespace Barotrauma overflowClipActive = TextSize.X > rect.Width - padding.X - padding.Z; } + Vector2 minSize = new Vector2( + Math.Max(rect.Width - padding.X - padding.Z, 5.0f), + Math.Max(rect.Height - padding.Y - padding.W, 5.0f)); if (autoScale && textScale > 0.1f && - (TextSize.X * textScale > rect.Width - padding.X - padding.Z || TextSize.Y * textScale > rect.Height - padding.Y - padding.W)) + (TextSize.X * textScale > minSize.X || TextSize.Y * textScale > minSize.Y)) { TextScale = Math.Max(0.1f, Math.Min( - (rect.Width - padding.X - padding.Z) / TextSize.X, + (rect.Width - padding.X - padding.Z) / TextSize.X, (rect.Height - padding.Y - padding.W) / TextSize.Y)) - 0.01f; return; } @@ -358,17 +402,28 @@ namespace Barotrauma textColor = new Color(textColor.R, textColor.G, textColor.B, a); } + /// + /// Overrides the color for all the states. + /// + public void OverrideTextColor(Color color) + { + textColor = color; + hoverTextColor = color; + selectedTextColor = color; + disabledTextColor = color; + } + protected override void Draw(SpriteBatch spriteBatch) { - if (!Visible) return; + if (!Visible) { return; } - Color currColor = GetCurrentColor(state); + Color currColor = GetColor(State); var rect = Rect; base.Draw(spriteBatch); - if (TextGetter != null) Text = TextGetter(); + if (TextGetter != null) { Text = TextGetter(); } Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle; if (overflowClipActive) @@ -388,19 +443,29 @@ namespace Barotrauma pos.Y = (int)pos.Y; } + Color currentTextColor = State == ComponentState.Hover || State == ComponentState.HoverSelected ? HoverTextColor : TextColor; + if (!enabled) + { + currentTextColor = disabledTextColor; + } + else if (State == ComponentState.Selected) + { + currentTextColor = selectedTextColor; + } + if (!hasColorHighlight) { Font.DrawString(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos, - textColor * (textColor.A / 255.0f), + currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth); } else { - Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos, - textColor * (textColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, colorData); + Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos, + currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, colorData); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs index 5c90c1f8f..dbb21079c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs @@ -21,6 +21,7 @@ namespace Barotrauma private readonly GUIFrame frame; private readonly GUITextBlock textBlock; + private readonly GUIImage icon; public Func textFilterFunction; @@ -74,6 +75,7 @@ namespace Barotrauma set { textBlock.TextGetter = value; } } + // TODO: fix implicit hiding private bool selected; public bool Selected { @@ -103,6 +105,11 @@ namespace Barotrauma } } + public GUITextBlock TextBlock + { + get { return textBlock; } + } + //should the text be limited to the size of the box //ignored when MaxTextLength is set or text wrapping is enabled public bool ClampText @@ -132,7 +139,8 @@ namespace Barotrauma get { return enabled; } set { - enabled = value; + enabled = frame.Enabled = textBlock.Enabled = value; + if (icon != null) { icon.Enabled = value; } if (!enabled && Selected) { Deselect(); @@ -228,25 +236,58 @@ namespace Barotrauma } public GUITextBox(RectTransform rectT, string text = "", Color? textColor = null, ScalableFont font = null, - Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null) + Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool createClearButton = false) : base(style, rectT) { HoverCursor = CursorState.IBeam; CanBeFocused = true; - Enabled = true; this.color = color ?? Color.White; frame = new GUIFrame(new RectTransform(Vector2.One, rectT, Anchor.Center), style, color); GUI.Style.Apply(frame, style == "" ? "GUITextBox" : style); - textBlock = new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.Center), text, textColor, font, textAlignment, wrap, playerInput: true); + textBlock = new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.CenterLeft), text, textColor, font, textAlignment, wrap, playerInput: true); GUI.Style.Apply(textBlock, "", this); CaretEnabled = true; caretPosDirty = true; + new GUICustomComponent(new RectTransform(Vector2.One, frame.RectTransform), onDraw: DrawCaretAndSelection); + + int clearButtonWidth = 0; + if (createClearButton) + { + var clearButton = new GUIButton(new RectTransform(new Vector2(0.6f, 0.6f), frame.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point(5, 0) }, style: "GUICancelButton") + { + OnClicked = (bt, userdata) => + { + Text = ""; + frame.Flash(Color.White); + return true; + } + }; + textBlock.RectTransform.MaxSize = new Point(frame.Rect.Width - clearButton.Rect.Height - clearButton.RectTransform.AbsoluteOffset.X * 2, int.MaxValue); + clearButtonWidth = (int)(clearButton.Rect.Width * 1.2f); + } + + if (this.style != null && this.style.ChildStyles.ContainsKey("textboxicon")) + { + icon = new GUIImage(new RectTransform(new Vector2(0.6f, 0.6f), frame.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point(5 + clearButtonWidth, 0) }, null, scaleToFit: true); + icon.ApplyStyle(this.style.ChildStyles["textboxicon"]); + textBlock.RectTransform.MaxSize = new Point(frame.Rect.Width - icon.Rect.Height - clearButtonWidth - icon.RectTransform.AbsoluteOffset.X * 2, int.MaxValue); + } Font = textBlock.Font; - rectT.SizeChanged += () => { caretPosDirty = true; }; - rectT.ScaleChanged += () => { caretPosDirty = true; }; + Enabled = true; + + rectT.SizeChanged += () => + { + if (icon != null) { textBlock.RectTransform.MaxSize = new Point(frame.Rect.Width - icon.Rect.Height - icon.RectTransform.AbsoluteOffset.X * 2, int.MaxValue); } + caretPosDirty = true; + }; + rectT.ScaleChanged += () => + { + if (icon != null) { textBlock.RectTransform.MaxSize = new Point(frame.Rect.Width - icon.Rect.Height - icon.RectTransform.AbsoluteOffset.X * 2, int.MaxValue); } + caretPosDirty = true; + }; } private bool SetText(string text, bool store = true) @@ -441,9 +482,9 @@ namespace Barotrauma OnDeselected?.Invoke(this, Keys.None); } - public override void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, Vector2? flashRectOffset = null) + public override void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, bool useCircularFlash = false, Vector2? flashRectOffset = null) { - textBlock.Flash(color, flashDuration, useRectangleFlash, flashRectOffset); + frame.Flash(color, flashDuration, useRectangleFlash, useCircularFlash, flashRectOffset); } protected override void Update(float deltaTime) @@ -451,10 +492,10 @@ namespace Barotrauma if (!Visible) return; if (flashTimer > 0.0f) flashTimer -= deltaTime; - if (!Enabled) return; - if (MouseRect.Contains(PlayerInput.MousePosition) && (GUI.MouseOn == null || GUI.IsMouseOn(this))) + if (!Enabled) { return; } + if (MouseRect.Contains(PlayerInput.MousePosition) && (GUI.MouseOn == null || (!(GUI.MouseOn is GUIButton) && GUI.IsMouseOn(this)))) { - state = ComponentState.Hover; + State = ComponentState.Hover; if (PlayerInput.PrimaryMouseButtonDown()) { Select(); @@ -481,7 +522,7 @@ namespace Barotrauma { if ((PlayerInput.LeftButtonClicked() || PlayerInput.RightButtonClicked()) && selected) Deselect(); isSelecting = false; - state = ComponentState.None; + State = ComponentState.None; } if (!isSelecting) { @@ -492,14 +533,14 @@ namespace Barotrauma { if (textBlock.OverflowClipActive) { - if (CaretScreenPos.X < Rect.X + textBlock.Padding.X) + if (CaretScreenPos.X < textBlock.Rect.X + textBlock.Padding.X) { - textBlock.TextPos = new Vector2(textBlock.TextPos.X + ((Rect.X + textBlock.Padding.X) - CaretScreenPos.X), textBlock.TextPos.Y); + textBlock.TextPos = new Vector2(textBlock.TextPos.X + ((textBlock.Rect.X + textBlock.Padding.X) - CaretScreenPos.X), textBlock.TextPos.Y); CalculateCaretPos(); } - else if (CaretScreenPos.X > Rect.Right - textBlock.Padding.Z) + else if (CaretScreenPos.X > textBlock.Rect.Right - textBlock.Padding.Z) { - textBlock.TextPos = new Vector2(textBlock.TextPos.X - (CaretScreenPos.X - (Rect.Right - textBlock.Padding.Z)), textBlock.TextPos.Y); + textBlock.TextPos = new Vector2(textBlock.TextPos.X - (CaretScreenPos.X - (textBlock.Rect.Right - textBlock.Padding.Z)), textBlock.TextPos.Y); CalculateCaretPos(); } } @@ -513,7 +554,7 @@ namespace Barotrauma if (GUI.KeyboardDispatcher.Subscriber == this) { - state = ComponentState.Selected; + State = ComponentState.Selected; Character.DisableControls = true; if (OnEnterPressed != null && PlayerInput.KeyHit(Keys.Enter)) { @@ -525,16 +566,12 @@ namespace Barotrauma Deselect(); } - textBlock.State = state; + textBlock.State = State; } - protected override void Draw(SpriteBatch spriteBatch) + private void DrawCaretAndSelection(SpriteBatch spriteBatch, GUICustomComponent customComponent) { - if (!Visible) return; - base.Draw(spriteBatch); - // Frame is not used in the old system. - frame?.DrawManually(spriteBatch); - textBlock.DrawManually(spriteBatch); + if (!Visible) { return; } if (Selected) { if (caretVisible ) @@ -552,9 +589,9 @@ namespace Barotrauma //GUI.DrawString(spriteBatch, new Vector2(100, 20), selectionStartIndex.ToString(), Color.White, Color.Black); //GUI.DrawString(spriteBatch, new Vector2(140, 20), selectionEndIndex.ToString(), Color.White, Color.Black); //GUI.DrawString(spriteBatch, new Vector2(100, 40), selectedText.ToString(), Color.Yellow, Color.Black); - //GUI.DrawString(spriteBatch, new Vector2(100, 60), $"caret index: {CaretIndex.ToString()}", Color.Red, Color.Black); - //GUI.DrawString(spriteBatch, new Vector2(100, 80), $"caret pos: {caretPos.ToString()}", Color.Red, Color.Black); - //GUI.DrawString(spriteBatch, new Vector2(100, 100), $"caret screen pos: {CaretScreenPos.ToString()}", Color.Red, Color.Black); + //GUI.DrawString(spriteBatch, new Vector2(100, 60), $"caret index: {CaretIndex.ToString()}", GUI.Style.Red, Color.Black); + //GUI.DrawString(spriteBatch, new Vector2(100, 80), $"caret pos: {caretPos.ToString()}", GUI.Style.Red, Color.Black); + //GUI.DrawString(spriteBatch, new Vector2(100, 100), $"caret screen pos: {CaretScreenPos.ToString()}", GUI.Style.Red, Color.Black); //GUI.DrawString(spriteBatch, new Vector2(100, 120), $"text start pos: {(textBlock.TextPos - textBlock.Origin).ToString()}", Color.White, Color.Black); //GUI.DrawString(spriteBatch, new Vector2(100, 140), $"cursor pos: {PlayerInput.MousePosition.ToString()}", Color.White, Color.Black); } @@ -805,7 +842,7 @@ namespace Barotrauma } } } - IEnumerable GetAndSortTextBoxes(GUIComponent parent) => parent.GetAllChildren().Select(c => c as GUITextBox).Where(t => t != null).OrderBy(t => t.Rect.Y).ThenBy(t => t.Rect.X); + IEnumerable GetAndSortTextBoxes(GUIComponent parent) => parent.GetAllChildren().OrderBy(t => t.Rect.Y).ThenBy(t => t.Rect.X); GUITextBox SelectNextTextBox(GUIListBox listBox) { var textBoxes = GetAndSortTextBoxes(listBox.SelectedComponent); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITickBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITickBox.cs index 60a43228e..2d589dc6b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITickBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITickBox.cs @@ -18,14 +18,12 @@ namespace Barotrauma private GUIRadioButtonGroup radioButtonGroup; - private bool selected; - - public bool Selected + public override bool Selected { get { return selected; } set - { - if (value == selected) return; + { + if (value == selected) { return; } if (radioButtonGroup != null && radioButtonGroup.SelectedRadioButton == this) { selected = true; @@ -33,8 +31,7 @@ namespace Barotrauma } selected = value; - state = (selected) ? ComponentState.Selected : ComponentState.None; - box.State = state; + State = selected ? ComponentState.Selected : ComponentState.None; if (value && radioButtonGroup != null) { radioButtonGroup.SelectRadioButton(this); @@ -44,7 +41,18 @@ namespace Barotrauma } } - private Color? defaultTextColor; + public override ComponentState State + { + get + { + return base.State; + } + set + { + base.State = value; + box.State = TextBlock.State = value; + } + } public override bool Enabled { @@ -56,12 +64,7 @@ namespace Barotrauma set { if (value == enabled) { return; } - enabled = value; - if (color.A == 0) - { - if (defaultTextColor == null) { defaultTextColor = TextBlock.TextColor; } - TextBlock.TextColor = enabled ? defaultTextColor.Value : defaultTextColor.Value * 0.5f; - } + enabled = box.Enabled = TextBlock.Enabled = value; } } @@ -126,11 +129,6 @@ namespace Barotrauma set { text.Text = value; } } - public Color? DefaultTextColor - { - get { return defaultTextColor; } - } - public GUITickBox(RectTransform rectT, string label, ScalableFont font = null, string style = "") : base(null, rectT) { CanBeFocused = true; @@ -138,9 +136,9 @@ namespace Barotrauma layoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, rectT), true); - box = new GUIFrame(new RectTransform(Vector2.One, layoutGroup.RectTransform, scaleBasis: ScaleBasis.BothHeight) + box = new GUIFrame(new RectTransform(Vector2.One, layoutGroup.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.BothHeight) { - IsFixedSize = false + IsFixedSize = true }, string.Empty, Color.DarkGray) { HoverColor = Color.Gray, @@ -148,12 +146,20 @@ namespace Barotrauma CanBeFocused = false }; GUI.Style.Apply(box, style == "" ? "GUITickBox" : style); + if (box.RectTransform.MinSize.Y > 0) + { + RectTransform.MinSize = box.RectTransform.MinSize; + RectTransform.MaxSize = box.RectTransform.MaxSize; + RectTransform.Resize(new Point(RectTransform.NonScaledSize.X, RectTransform.MinSize.Y)); + box.RectTransform.MinSize = new Point(box.RectTransform.MinSize.Y); + box.RectTransform.Resize(box.RectTransform.MinSize); + } Vector2 textBlockScale = new Vector2((float)(Rect.Width - Rect.Height) / (float)Math.Max(Rect.Width, 1.0), 1.0f); - text = new GUITextBlock(new RectTransform(textBlockScale, layoutGroup.RectTransform), label, font: font, textAlignment: Alignment.CenterLeft) + text = new GUITextBlock(new RectTransform(textBlockScale, layoutGroup.RectTransform, Anchor.CenterLeft), label, font: font, textAlignment: Alignment.CenterLeft) { CanBeFocused = false }; - GUI.Style.Apply(text, "GUIButtonHorizontal", this); + GUI.Style.Apply(text, "GUITextBlock", this); Enabled = true; ResizeBox(); @@ -171,21 +177,26 @@ namespace Barotrauma { Vector2 textBlockScale = new Vector2(Math.Max(Rect.Width - box.Rect.Width, 0.0f) / Math.Max(Rect.Width, 1.0f), 1.0f); text.RectTransform.RelativeSize = textBlockScale; + box.RectTransform.MinSize = new Point(Rect.Height); + box.RectTransform.Resize(box.RectTransform.MinSize); text.SetTextPos(); } protected override void Update(float deltaTime) { - if (!Visible) return; + if (!Visible) { return; } + base.Update(deltaTime); if (GUI.MouseOn == this && Enabled) { - box.State = ComponentState.Hover; + State = Selected ? + ComponentState.HoverSelected : + ComponentState.Hover; if (PlayerInput.PrimaryMouseButtonHeld()) { - box.State = ComponentState.Selected; + State = ComponentState.Selected; } if (PlayerInput.PrimaryMouseButtonClicked()) @@ -200,14 +211,13 @@ namespace Barotrauma } } } + else if (selected) + { + State = ComponentState.Selected; + } else { - box.State = ComponentState.None; - } - - if (selected) - { - box.State = ComponentState.Selected; + State = ComponentState.None; } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs index d1609b69c..f8791c790 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs @@ -45,11 +45,6 @@ namespace Barotrauma get; private set; } - public static Alignment ChatBoxAlignment - { - get; private set; - } - public static Rectangle ObjectiveAnchor { get; private set; @@ -60,6 +55,10 @@ namespace Barotrauma get; private set; } + /*public static Rectangle HealthBarAreaRight + { + get; private set; + }*/ public static Rectangle HealthBarAreaLeft { get; private set; @@ -69,26 +68,17 @@ namespace Barotrauma get; private set; } - public static Rectangle HealthBarAreaRight - { - get; private set; - } - public static Rectangle AfflictionAreaRight - { - get; private set; - } - public static Rectangle HealthWindowAreaLeft { get; private set; } - public static Rectangle HealthWindowAreaRight + public static Rectangle PortraitArea { get; private set; } - public static Rectangle PortraitArea + public static Rectangle PortraitTooltipArea { get; private set; } @@ -125,74 +115,66 @@ namespace Barotrauma //slice from the top of the screen for misc buttons (info, end round, server controls) ButtonAreaTop = new Rectangle(Padding, Padding, GameMain.GraphicsWidth - Padding * 2, (int)(50 * GUI.Scale)); - int crewAreaHeight = (int)Math.Max(GameMain.GraphicsHeight * 0.22f, 150); - CrewArea = new Rectangle(Padding, ButtonAreaTop.Bottom + Padding, GameMain.GraphicsWidth - InventoryAreaUpper.Width - Padding * 3, crewAreaHeight); + int portraitSize = (int)(125 * GUI.Scale); + PortraitArea = new Rectangle(Padding * 2, Padding * 2, portraitSize, portraitSize); + PortraitTooltipArea = new Rectangle(PortraitArea.X + portraitSize / 2 + Padding, PortraitArea.Top - portraitSize, portraitSize, portraitSize); - int portraitSize = (int)(100 * GUI.Scale); - PortraitArea = new Rectangle(GameMain.GraphicsWidth - portraitSize - Padding, GameMain.GraphicsHeight - portraitSize - Padding, portraitSize, portraitSize); - //horizontal slices at the corners of the screen for health bar and affliction icons int healthBarWidth = (int)Math.Max(250 * GUI.Scale, 150); - int healthBarHeight = (int)Math.Max(20 * GUI.Scale, 15); - int afflictionAreaHeight = (int)(60 * GUI.Scale); - HealthBarAreaLeft = new Rectangle(Padding, GameMain.GraphicsHeight - healthBarHeight - Padding, healthBarWidth, healthBarHeight); + int healthBarHeight = (int)Math.Max(15f * GUI.Scale, 12.5f); + int afflictionAreaHeight = (int)(50 * GUI.Scale); + HealthBarAreaLeft = new Rectangle(PortraitArea.X, PortraitArea.Y + Padding / 2 + portraitSize, healthBarWidth, healthBarHeight); AfflictionAreaLeft = new Rectangle(Padding, HealthBarAreaLeft.Y - afflictionAreaHeight - Padding, healthBarWidth, afflictionAreaHeight); - HealthBarAreaRight = new Rectangle(PortraitArea.X - Padding - healthBarWidth, Math.Min(PortraitArea.Y + Padding * 3, inventoryTopY - healthBarHeight), healthBarWidth, HealthBarAreaLeft.Height); - if (HealthBarAreaRight.Y + healthBarHeight * 0.75f < PortraitArea.Y) + //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 - Padding - afflictionAreaHeight, healthBarWidth, afflictionAreaHeight); + }*/ + //AfflictionAreaRight = new Rectangle(HealthBarAreaRight.X, HealthBarAreaRight.Y + healthBarHeight + Padding, healthBarWidth, afflictionAreaHeight); int messageAreaWidth = GameMain.GraphicsWidth / 3; MessageAreaTop = new Rectangle((GameMain.GraphicsWidth - messageAreaWidth) / 2, ButtonAreaTop.Bottom, messageAreaWidth, ButtonAreaTop.Height); + CrewArea = new Rectangle(HealthBarAreaLeft.Right + Padding, MessageAreaTop.Bottom + Padding, + GameMain.GraphicsWidth - HealthBarAreaLeft.Right - 2 * Padding, (int)(0.6f * portraitSize)); + //slice for the upper slots of the inventory (clothes, id card, headset) int inventoryAreaUpperWidth = (int)(GameMain.GraphicsWidth * 0.2f); int inventoryAreaUpperHeight = (int)(GameMain.GraphicsHeight * 0.2f); InventoryAreaUpper = new Rectangle(GameMain.GraphicsWidth - inventoryAreaUpperWidth - Padding, CrewArea.Y, inventoryAreaUpperWidth, inventoryAreaUpperHeight); - //chatbox between upper and lower inventory areas, can be on either side depending on the alignment - ChatBoxAlignment = Alignment.Right; - int chatBoxWidth = (int)(500 * GUI.Scale); - int chatBoxHeight = crewAreaHeight; - ChatBoxArea = ChatBoxAlignment == Alignment.Left ? - new Rectangle(Padding, CrewArea.Y, chatBoxWidth, chatBoxHeight) : - new Rectangle(GameMain.GraphicsWidth - Padding - chatBoxWidth, CrewArea.Y, chatBoxWidth, chatBoxHeight); + int toggleButtonWidth = (int)(ChatBox.ToggleButtonWidthRaw * GUI.Scale); + int chatBoxWidth = (int)(475 * GUI.Scale); + int chatBoxHeight = (int)Math.Max(GameMain.GraphicsHeight * 0.22f, 150); + ChatBoxArea = new Rectangle(Padding + toggleButtonWidth, GameMain.GraphicsHeight - Padding - chatBoxHeight, chatBoxWidth, chatBoxHeight); int objectiveAnchorWidth = (int)(250 * GUI.Scale); - int objectiveAnchorOffsetY = (int)(100 * GUI.Scale); - ObjectiveAnchor = new Rectangle(GameMain.GraphicsWidth - Padding - objectiveAnchorWidth, CrewArea.Y + crewAreaHeight + objectiveAnchorOffsetY, objectiveAnchorWidth, 0); + int objectiveAnchorOffsetY = (int)(150 * GUI.Scale); + ObjectiveAnchor = new Rectangle(Padding, ChatBoxArea.Y - objectiveAnchorOffsetY, objectiveAnchorWidth, 0); int lowerAreaHeight = (int)Math.Min(GameMain.GraphicsHeight * 0.25f, 280); InventoryAreaLower = new Rectangle(Padding, GameMain.GraphicsHeight - lowerAreaHeight, GameMain.GraphicsWidth - Padding * 2, lowerAreaHeight); - int healthWindowY = CrewArea.Bottom + Padding; - Rectangle healthWindowArea = ChatBoxAlignment == Alignment.Left ? - new Rectangle(ChatBoxArea.Right + Padding, healthWindowY, GameMain.GraphicsWidth - ChatBoxArea.Width - inventoryAreaUpperWidth, GameMain.GraphicsHeight - healthWindowY - lowerAreaHeight / 2) : - new Rectangle(Padding - ChatBoxArea.Width, healthWindowY, GameMain.GraphicsWidth - ChatBoxArea.Width - inventoryAreaUpperWidth, GameMain.GraphicsHeight - healthWindowY - lowerAreaHeight / 2); + int healthWindowWidth = (int)(GameMain.GraphicsWidth * 0.5f); + int healthWindowHeight = (int)(GameMain.GraphicsWidth * 0.5f * 0.65f); + int healthWindowX = GameMain.GraphicsWidth / 2 - healthWindowWidth / 2; + int healthWindowY = GameMain.GraphicsHeight / 2 - healthWindowHeight / 2; - int healthWindowPadding = Padding * 3; - HealthWindowAreaLeft = new Rectangle(healthWindowPadding, healthWindowY, GameMain.GraphicsWidth / 2 - healthWindowPadding, GameMain.GraphicsHeight - healthWindowY - lowerAreaHeight); - HealthWindowAreaRight = new Rectangle(GameMain.GraphicsWidth / 2, healthWindowY, GameMain.GraphicsWidth / 2 - healthWindowPadding, GameMain.GraphicsHeight - healthWindowY - lowerAreaHeight); - + HealthWindowAreaLeft = new Rectangle(healthWindowX, healthWindowY, healthWindowWidth, healthWindowHeight); } public static void Draw(SpriteBatch spriteBatch) { GUI.DrawRectangle(spriteBatch, ButtonAreaTop, Color.White * 0.5f); - GUI.DrawRectangle(spriteBatch, MessageAreaTop, Color.Orange * 0.5f); + GUI.DrawRectangle(spriteBatch, MessageAreaTop, GUI.Style.Orange * 0.5f); GUI.DrawRectangle(spriteBatch, InventoryAreaUpper, Color.Yellow * 0.5f); GUI.DrawRectangle(spriteBatch, CrewArea, Color.Blue * 0.5f); GUI.DrawRectangle(spriteBatch, ChatBoxArea, Color.Cyan * 0.5f); GUI.DrawRectangle(spriteBatch, HealthBarAreaLeft, Color.Red * 0.5f); GUI.DrawRectangle(spriteBatch, AfflictionAreaLeft, Color.Red * 0.5f); - GUI.DrawRectangle(spriteBatch, HealthBarAreaRight, Color.Red * 0.5f); - GUI.DrawRectangle(spriteBatch, AfflictionAreaRight, Color.Red * 0.5f); GUI.DrawRectangle(spriteBatch, InventoryAreaLower, Color.Yellow * 0.5f); GUI.DrawRectangle(spriteBatch, HealthWindowAreaLeft, Color.Red * 0.5f); - GUI.DrawRectangle(spriteBatch, HealthWindowAreaRight, Color.Red * 0.5f); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/LoadingScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/LoadingScreen.cs index 7ec3aaedc..e513b7ba4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/LoadingScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/LoadingScreen.cs @@ -194,7 +194,18 @@ namespace Barotrauma string loadText; if (LoadState == 100.0f) { - loadText = TextManager.Get("PressAnyKey"); +#if DEBUG + if (GameMain.Config.AutomaticQuickStartEnabled && GameMain.FirstLoad) + { + loadText = "QUICKSTARTING ..."; + } + else + { +#endif + loadText = TextManager.Get("PressAnyKey"); +#if DEBUG + } +#endif } else { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs index 065427624..2745a3ee1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs @@ -23,7 +23,9 @@ namespace Barotrauma public enum ScaleBasis { - Normal, BothWidth, BothHeight + Normal, + BothWidth, BothHeight, + Smallest, Largest } public class RectTransform @@ -56,7 +58,7 @@ namespace Barotrauma } } - private List children = new List(); + private readonly List children = new List(); public IEnumerable Children => children; public int CountChildren => children.Count; @@ -291,7 +293,11 @@ namespace Barotrauma } } - private ScaleBasis scaleBasis; + public ScaleBasis ScaleBasis + { + get; + private set; + } public bool IsLastChild { @@ -330,7 +336,7 @@ namespace Barotrauma public RectTransform(Vector2 relativeSize, RectTransform parent, Anchor anchor = Anchor.TopLeft, Pivot? pivot = null, Point? minSize = null, Point? maxSize = null, ScaleBasis scaleBasis = ScaleBasis.Normal) { Init(parent, anchor, pivot); - this.scaleBasis = scaleBasis; + this.ScaleBasis = scaleBasis; this.relativeSize = relativeSize; this.minSize = minSize; this.maxSize = maxSize; @@ -348,7 +354,7 @@ namespace Barotrauma public RectTransform(Point absoluteSize, RectTransform parent = null, Anchor anchor = Anchor.TopLeft, Pivot? pivot = null) { Init(parent, anchor, pivot); - this.scaleBasis = ScaleBasis.Normal; + this.ScaleBasis = ScaleBasis.Normal; this.nonScaledSize = absoluteSize; RecalculateScale(); RecalculateRelativeSize(); @@ -364,8 +370,14 @@ namespace Barotrauma Enum.TryParse(element.GetAttributeString("pivot", anchor.ToString()), out Pivot pivot); Point? minSize = null, maxSize = null; - if (element.Attribute("minsize") != null) minSize = element.GetAttributePoint("minsize", Point.Zero); - //if (element.Attribute("maxsize") != null) maxSize = element.GetAttributePoint("maxsize", new Point(1000, 1000)); + if (element.Attribute("minsize") != null) + { + minSize = element.GetAttributePoint("minsize", Point.Zero); + } + if (element.Attribute("maxsize") != null) + { + maxSize = element.GetAttributePoint("maxsize", new Point(1000, 1000)); + } RectTransform rectTransform; if (element.Attribute("absolutesize") != null) @@ -426,14 +438,36 @@ namespace Barotrauma protected void RecalculateAbsoluteSize() { Point size = NonScaledParentRect.Size; - if (scaleBasis == ScaleBasis.BothWidth) + if (ScaleBasis == ScaleBasis.BothWidth) { size.Y = size.X; } - else if (scaleBasis == ScaleBasis.BothHeight) + else if (ScaleBasis == ScaleBasis.BothHeight) { size.X = size.Y; } + else if (ScaleBasis == ScaleBasis.Smallest) + { + if (size.X < size.Y) + { + size.Y = size.X; + } + else + { + size.X = size.Y; + } + } + else if (ScaleBasis == ScaleBasis.Largest) + { + if (size.X > size.Y) + { + size.Y = size.X; + } + else + { + size.X = size.Y; + } + } nonScaledSize = size.Multiply(RelativeSize).Clamp(MinSize, MaxSize); recalculateRect = true; SizeChanged?.Invoke(); @@ -573,7 +607,7 @@ namespace Barotrauma /// public IEnumerable GetAllChildren() { - return children.SelectManyRecursive(c => c.children); + return children.Concat(children.SelectManyRecursive(c => c.children)); } public int GetChildIndex(RectTransform rectT) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs index a94751438..8fdc01a25 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs @@ -37,11 +37,23 @@ namespace Barotrauma private set; } + public bool CrossFadeIn { get; private set; } = true; + public bool CrossFadeOut { get; private set; } = true; + + public TransitionMode TransitionMode { get; private set; } + public UISprite(XElement element) { Sprite = new Sprite(element); MaintainAspectRatio = element.GetAttributeBool("maintainaspectratio", false); Tile = element.GetAttributeBool("tile", true); + CrossFadeIn = element.GetAttributeBool("crossfadein", CrossFadeIn); + CrossFadeOut = element.GetAttributeBool("crossfadeout", CrossFadeOut); + string transitionMode = element.GetAttributeString("transition", string.Empty); + if (Enum.TryParse(transitionMode, ignoreCase: true, out TransitionMode transition)) + { + TransitionMode = transition; + } Vector4 sliceVec = element.GetAttributeVector4("slice", Vector4.Zero); if (sliceVec != Vector4.Zero) @@ -86,43 +98,30 @@ namespace Barotrauma { Vector2 pos = new Vector2(rect.X, rect.Y); - int centerWidth = Math.Max(rect.Width - Slices[0].Width - Slices[2].Width, 0); - int centerHeight = Math.Max(rect.Height - Slices[0].Height - Slices[8].Height, 0); - Vector2 scale = Vector2.One; - if (centerHeight == 0) - { - scale.Y = MathHelper.Clamp((float)rect.Height / (Slices[0].Height + Slices[3].Height + Slices[6].Height), 0, 1); - centerHeight = rect.Height - (int)((Slices[0].Height + Slices[6].Height) * scale.Y); - } - else - { - scale.Y = MathHelper.Clamp((float)rect.Height / (Slices[0].Height + Slices[6].Height), 0, 1); - centerHeight = (int)(centerHeight * scale.Y); - } - if (centerWidth == 0) - { - scale.X = MathHelper.Clamp((float)rect.Height / (Slices[0].Width + Slices[1].Width + Slices[2].Width), 0, 1); - centerWidth = rect.Width - (int)((Slices[0].Width + Slices[2].Width) * scale.X); - } - else - { - scale.X = MathHelper.Clamp((float)rect.Width / (Slices[0].Width + Slices[2].Width), 0, 1); - centerWidth = (int)(centerWidth * scale.X); - } + + scale.Y = MathHelper.Clamp((float)rect.Height / (Slices[0].Height + Slices[6].Height), 0, 1); + + scale.X = MathHelper.Clamp((float)rect.Width / (Slices[0].Width + Slices[2].Width), 0, 1); + + scale.X = scale.Y = Math.Min(scale.X, scale.Y); + int centerHeight = rect.Height - (int)((Slices[0].Height + Slices[6].Height) * scale.Y); + int centerWidth = rect.Width - (int)((Slices[0].Width + Slices[2].Width) * scale.X); for (int x = 0; x < 3; x++) { - float width = (x == 1 ? centerWidth : Slices[x].Width * scale.X); + int width = (int)(x == 1 ? centerWidth : Slices[x].Width * scale.X); + if (width <= 0) { continue; } for (int y = 0; y < 3; y++) { - float height = (y == 1 ? centerHeight : Slices[x + y * 3].Height * scale.Y); + int height = (int)(y == 1 ? centerHeight : Slices[x + y * 3].Height * scale.Y); + if (height <= 0) { continue; } spriteBatch.Draw(Sprite.Texture, - new Rectangle((int)pos.X, (int)pos.Y, (int)width, (int)height), + new Rectangle((int)pos.X, (int)pos.Y, width, height), Slices[x + y * 3], color); - + pos.Y += height; } pos.X += width; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs index b30eeb7fc..fdb531895 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs @@ -75,13 +75,13 @@ namespace Barotrauma } videoView = new GUICustomComponent(new RectTransform(Point.Zero, videoFrame.RectTransform, Anchor.Center), (spriteBatch, guiCustomComponent) => { DrawVideo(spriteBatch, guiCustomComponent.Rect); }); - title = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUI.VideoTitleFont, textColor: new Color(253, 174, 0), textAlignment: Alignment.Left); + title = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUI.LargeFont, textColor: new Color(253, 174, 0), textAlignment: Alignment.Left); textContent = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUI.Font, textAlignment: Alignment.TopLeft); - objectiveTitle = new GUITextBlock(new RectTransform(new Vector2(1f, 0f), textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.ObjectiveTitleFont, textAlignment: Alignment.CenterRight, textColor: Color.White); + objectiveTitle = new GUITextBlock(new RectTransform(new Vector2(1f, 0f), textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight, textColor: Color.White); objectiveTitle.Text = TextManager.Get("Tutorial.NewObjective"); - objectiveText = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.ObjectiveNameFont, textColor: new Color(4, 180, 108), textAlignment: Alignment.CenterRight); + objectiveText = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.SubHeadingFont, textColor: new Color(4, 180, 108), textAlignment: Alignment.CenterRight); objectiveTitle.Visible = objectiveText.Visible = false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/Widget.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/Widget.cs index 4b9002696..f10f5cda3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/Widget.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/Widget.cs @@ -41,7 +41,7 @@ namespace Barotrauma /// public bool isFilled; public int inputAreaMargin; - public Color color = Color.Red; + public Color color = GUI.Style.Red; public Color? secondaryColor; public Color textColor = Color.White; public Color textBackgroundColor = Color.Black * 0.5f; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index 5fd3c40eb..eb4e8b326 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -171,6 +171,10 @@ namespace Barotrauma private const GraphicsProfile GfxProfile = GraphicsProfile.Reach; +#if DEBUG + public static bool FirstLoad = true; +#endif + public GameMain(string[] args) { Content.RootDirectory = "Content"; @@ -391,7 +395,7 @@ namespace Barotrauma float baseVolume = MathHelper.Clamp(Config.SoundVolume * 2.0f, 0.0f, 1.0f); pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_UTG.webm", baseVolume * 0.5f)); pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_FF.webm", baseVolume)); - pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_Daedalic.webm", baseVolume * 0.15f)); + pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_Daedalic.webm", baseVolume * 0.1f)); } //if not loading in a separate thread, wait for the splash screens to finish before continuing the loading @@ -702,6 +706,15 @@ namespace Barotrauma loadingScreenOpen = false; } +#if DEBUG + if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && Config.AutomaticQuickStartEnabled && FirstLoad) + { + loadingScreenOpen = false; + FirstLoad = false; + MainMenuScreen.QuickStart(); + } +#endif + if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine)) { string errMsg = "Loading was interrupted due to an error"; @@ -778,7 +791,8 @@ namespace Barotrauma //open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC else if ((Character.Controlled == null || !itemHudActive()) //TODO: do we need to check Inventory.SelectedSlot? - && Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null) + && Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null + && !CrewManager.IsCommandInterfaceOpen) { // Otherwise toggle pausing, unless another window/interface is open. GUI.TogglePauseMenu(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs index 246084459..c01beeae5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs @@ -13,8 +13,6 @@ namespace Barotrauma { partial class CrewManager { - const float ChatMessageFadeTime = 10.0f; - /// /// How long the previously selected character waits doing nothing when switching to another character. Only affects idling. /// @@ -27,18 +25,15 @@ namespace Barotrauma #region UI + public GUIComponent ReportButtonFrame { get; set; } + private GUIFrame guiFrame; private GUIFrame crewArea; - private GUIListBox characterListBox; - - private GUIComponent reportButtonFrame; - - private GUIButton scrollButtonUp, scrollButtonDown; - + private GUILayoutGroup activeCrew; + private GUIFrame crewList; private GUIButton toggleCrewButton; - private float crewAreaOpenState; - private bool toggleCrewAreaOpen = true; - private int characterInfoWidth; + private float crewListOpenState; + private bool toggleCrewListOpen = true; /// /// Present only in single player games. In multiplayer. The chatbox is found from GameSession.Client. @@ -47,26 +42,22 @@ namespace Barotrauma private float prevUIScale; - private GUIComponent orderTargetFrame, orderTargetFrameShadow; - public bool AllowCharacterSwitch = true; - public bool ToggleCrewAreaOpen + public bool ToggleCrewListOpen { - get { return toggleCrewAreaOpen; } + get { return toggleCrewListOpen; } set { - if (toggleCrewAreaOpen == value) { return; } - toggleCrewAreaOpen = GameMain.Config.CrewMenuOpen = value; - foreach (GUIComponent child in toggleCrewButton.Children) - { - child.SpriteEffects = toggleCrewAreaOpen ? SpriteEffects.None : SpriteEffects.FlipHorizontally; - } + if (toggleCrewListOpen == value) { return; } + toggleCrewListOpen = GameMain.Config.CrewMenuOpen = value; } } public List OrderOptionButtons = new List(); + private Sprite jobIndicatorBackground; + #endregion #region Constructors @@ -96,45 +87,104 @@ namespace Barotrauma CanBeFocused = false }; - Point scrollButtonSize = new Point((int)(200 * GUI.Scale), (int)(30 * GUI.Scale)); - crewArea = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform), "", Color.Transparent) { CanBeFocused = false }; - toggleCrewButton = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), HUDLayoutSettings.CrewArea.Height), guiFrame.RectTransform) - { AbsoluteOffset = HUDLayoutSettings.CrewArea.Location }, - "", style: "UIToggleButton"); - toggleCrewButton.OnClicked += (GUIButton btn, object userdata) => + + // Based on the sprite dimensions + var buttonSize = new Point((int)(79.0f / 126.0f * crewArea.Rect.Height), crewArea.Rect.Height); + + var commandButton = new GUIButton( + new RectTransform(buttonSize, parent: crewArea.RectTransform, anchor: Anchor.CenterRight), + style: null) { - ToggleCrewAreaOpen = !ToggleCrewAreaOpen; + OnClicked = (button, userData) => + { + ToggleCommandUI(); + return true; + } + }; + + new GUIImage( + new RectTransform(Vector2.One, parent: commandButton.RectTransform), + new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(551, 1, 79, 126)), + scaleToFit: true) + { + Color = GUIColorSettings.InventorySlotColor * 0.8f, + HoverColor = GUIColorSettings.InventorySlotColor, + PressedColor = GUIColorSettings.InventorySlotColor, + SelectedColor = GUIColorSettings.InventorySlotColor * 0.8f, + ToolTip = TextManager.Get("inputtype.command") + }; + + activeCrew = new GUILayoutGroup( + new RectTransform( + new Point(crewArea.Rect.Width - commandButton.Rect.Width - HUDLayoutSettings.Padding, crewArea.Rect.Height), + parent: crewArea.RectTransform, + anchor: Anchor.CenterLeft), + isHorizontal: true, + childAnchor: Anchor.CenterRight) + { + AbsoluteSpacing = (int)(GUI.Scale * 5) + }; + + // AbsoluteOffset is set in UpdateProjectSpecific based on crewListOpenState + crewList = new GUIFrame( + new RectTransform( + new Point( + Math.Min(crewArea.Rect.Height * 10, 500), + Math.Min(crewArea.Rect.Height * 8, 400)), + parent: crewArea.RectTransform, + anchor: Anchor.BottomRight, + pivot: Pivot.TopCenter)); + + var listBox = new GUIListBox( + new RectTransform( + new Point((int)(crewList.Rect.Width / 2.0f - HUDLayoutSettings.Padding * 2), crewList.Rect.Height - HUDLayoutSettings.Padding * 4), + parent: crewList.RectTransform, + anchor: Anchor.CenterLeft) + { + AbsoluteOffset = new Point(HUDLayoutSettings.Padding * 2, 0), + }, + style: null) + { + AutoHideScrollBar = false, + Spacing = (int)(GUI.Scale * 10) + }; + + // Based on the sprite dimensions + buttonSize = new Point((int)(78.0f / 126.0f * crewArea.Rect.Height), crewArea.Rect.Height); + + toggleCrewButton = new GUIButton( + new RectTransform(buttonSize, parent: crewList.RectTransform, pivot: Pivot.TopRight) + { + AbsoluteOffset = new Point(-HUDLayoutSettings.Padding, 0) + }, + style: null); + toggleCrewButton.OnClicked = (GUIButton btn, object userdata) => + { + ToggleCrewListOpen = !ToggleCrewListOpen; return true; }; - characterListBox = new GUIListBox(new RectTransform(new Point(100, (int)(crewArea.Rect.Height - scrollButtonSize.Y * 1.6f)), crewArea.RectTransform, Anchor.CenterLeft), false, Color.Transparent, null) + new GUIImage( + new RectTransform(Vector2.One, parent: toggleCrewButton.RectTransform), + new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(891, 135, 78, 126)), + scaleToFit: true) { - //Spacing = (int)(3 * GUI.Scale), - ScrollBarEnabled = false, - ScrollBarVisible = false, - CanBeFocused = true, - OnSelected = (component, userdata) => false + Color = GUIColorSettings.InventorySlotColor * 0.8f, + HoverColor = GUIColorSettings.InventorySlotColor, + PressedColor = GUIColorSettings.InventorySlotColor, + SelectedColor = GUIColorSettings.InventorySlotColor * 0.8f, + ToolTip = TextManager.Get("crew") }; - scrollButtonUp = new GUIButton(new RectTransform(scrollButtonSize, crewArea.RectTransform, Anchor.TopLeft, Pivot.TopLeft), "", Alignment.Center, "GUIButtonVerticalArrow") - { - Visible = false, - UserData = -1, - OnClicked = ScrollCharacterList - }; - scrollButtonDown = new GUIButton(new RectTransform(scrollButtonSize, crewArea.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft), "", Alignment.Center, "GUIButtonVerticalArrow") - { - Visible = false, - UserData = 1, - OnClicked = ScrollCharacterList - }; - scrollButtonDown.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipVertically); + jobIndicatorBackground = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(0, 512, 128, 128)); - if (isSinglePlayer) + #region Chatbox + + if (IsSinglePlayer) { ChatBox = new ChatBox(guiFrame, isSinglePlayer: true) { @@ -174,14 +224,18 @@ namespace Barotrauma ChatBox.InputBox.OnTextChanged += ChatBox.TypingChatMessage; } + #endregion + + #region Reports + var reports = Order.PrefabList.FindAll(o => o.TargetAllCharacters && o.SymbolSprite != null); if (reports.None()) { DebugConsole.ThrowError("No valid orders for report buttons found! Cannot create report buttons. The orders for the report buttons must have 'targetallcharacters' attribute enabled and a valid 'symbolsprite' defined."); return; } - reportButtonFrame = new GUILayoutGroup(new RectTransform( - new Point((HUDLayoutSettings.CrewArea.Height - (int)((reports.Count - 1) * 5 * GUI.Scale)) / reports.Count, HUDLayoutSettings.CrewArea.Height), guiFrame.RectTransform)) + ReportButtonFrame = new GUILayoutGroup(new RectTransform( + new Point((HUDLayoutSettings.ChatBoxArea.Height - (int)((reports.Count - 1) * 5 * GUI.Scale)) / reports.Count, HUDLayoutSettings.ChatBoxArea.Height), guiFrame.RectTransform)) { AbsoluteSpacing = (int)(5 * GUI.Scale), UserData = "reportbuttons", @@ -191,8 +245,8 @@ namespace Barotrauma //report buttons foreach (Order order in reports) { - if (!order.TargetAllCharacters || order.SymbolSprite == null) continue; - var btn = new GUIButton(new RectTransform(new Point(reportButtonFrame.Rect.Width), reportButtonFrame.RectTransform), style: null) + if (!order.TargetAllCharacters || order.SymbolSprite == null) { continue; } + var btn = new GUIButton(new RectTransform(new Point(ReportButtonFrame.Rect.Width), ReportButtonFrame.RectTransform), style: null) { OnClicked = (GUIButton button, object userData) => { @@ -212,9 +266,9 @@ namespace Barotrauma new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlow") { - Color = Color.Red * 0.8f, - HoverColor = Color.Red * 1.0f, - PressedColor = Color.Red * 0.6f, + Color = GUI.Style.Red * 0.8f, + HoverColor = GUI.Style.Red * 1.0f, + PressedColor = GUI.Style.Red * 0.6f, UserData = "highlighted", CanBeFocused = false, Visible = false @@ -224,25 +278,25 @@ namespace Barotrauma { Color = order.Color, HoverColor = Color.Lerp(order.Color, Color.White, 0.5f), - ToolTip = order.Name + ToolTip = order.Name, + SpriteEffects = SpriteEffects.FlipHorizontally }; } + #endregion + screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); - prevUIScale = GUI.Scale; - - ToggleCrewAreaOpen = GameMain.Config.CrewMenuOpen; + ToggleCrewListOpen = GameMain.Config.CrewMenuOpen; } - #endregion #region Character list management - public Rectangle GetCharacterListArea() + public Rectangle GetActiveCrewArea() { - return characterListBox.Rect; + return crewArea.Rect; } public IEnumerable GetCharacters() @@ -268,14 +322,16 @@ namespace Barotrauma return; } - if (!characters.Contains(character)) characters.Add(character); + if (!characters.Contains(character)) + { + characters.Add(character); + } if (!characterInfos.Contains(character.Info)) { characterInfos.Add(character.Info); } - CreateCharacterFrame(character, characterListBox.Content); - characterListBox.Content.RectTransform.SortChildren((c1, c2) => { return c2.NonScaledSize.X - c1.NonScaledSize.X; }); + AddCharacterToCrewList(character); if (character is AICharacter) { @@ -313,7 +369,7 @@ namespace Barotrauma return; } characters.Remove(character); - if (removeInfo) characterInfos.Remove(character.Info); + if (removeInfo) { characterInfos.Remove(character.Info); } } /// @@ -325,100 +381,45 @@ namespace Barotrauma characterInfos.Remove(characterInfo); } - /// - /// Create the UI component that holds the character's portrait and order/report buttons for the character - /// - private GUIComponent CreateCharacterFrame(Character character, GUIComponent parent) + private GUIComponent AddCharacterToActiveCrew(Character character) { - int genericOrderCount = 0, correctOrderCount = 0, wrongOrderCount = 0; - //sort the orders - // 1. generic orders (follow, wait, etc) - // 2. orders appropriate for the character's job (captain -> steer, etc) - // 3. orders inappropriate for the job (captain -> operate reactor, etc) - List orders = new List(); - foreach (Order order in Order.PrefabList) - { - if (order.TargetAllCharacters || order.SymbolSprite == null) continue; - if (!JobPrefab.Prefabs.Any(jp => jp.AppropriateOrders.Contains(order.Identifier)) && - (order.AppropriateJobs == null || !order.AppropriateJobs.Any())) - { - orders.Insert(0, order); - genericOrderCount++; - } - else if (order.HasAppropriateJob(character)) - { - orders.Add(order); - correctOrderCount++; - } - } - foreach (Order order in Order.PrefabList) - { - if (order.SymbolSprite == null) continue; - if (!order.TargetAllCharacters && !orders.Contains(order)) - { - orders.Add(order); - wrongOrderCount++; - } - } + int size = HUDLayoutSettings.CrewArea.Height; + int iconSize = (int)(size * 0.9f); - int spacing = (int)(10 * GUI.Scale); - int height = (int)(45 * GUI.Scale); - characterInfoWidth = (int)(200 * GUI.Scale); - - float charactersPerView = characterListBox.Rect.Height / (float)(height + characterListBox.Spacing); - - //if we can fit less than 25% of the last character or more than 75%, - //change the size of the character frame slightly to fit them more nicely in the list box - if (charactersPerView % 1.0f < 0.25f || charactersPerView % 1.0f > 0.75f) - { - height = (int)(characterListBox.Rect.Height / (float)Math.Round(charactersPerView)) - characterListBox.Spacing; - } - - int iconSize = (int)(height * 0.8f); - - - var frame = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, height), parent.RectTransform), style: "InnerFrame") + var characterFrame = new GUIFrame(new RectTransform(new Point(size), activeCrew.RectTransform, Anchor.Center), style: null) { UserData = character, CanBeFocused = false }; - frame.Color = character.Info.Job.Prefab.UIColor; - frame.SelectedColor = Color.Lerp(frame.Color, Color.White, 0.5f); - frame.HoverColor = Color.Lerp(frame.Color, Color.White, 0.9f); - new GUIFrame(new RectTransform(new Point(characterInfoWidth, (int)(frame.Rect.Height * 1.3f)), frame.RectTransform, Anchor.CenterLeft), style: "OuterGlow") + var characterToolTip = character.Info?.Name; + if (character.Info?.Job != null) { - UserData = "highlight", - Color = frame.SelectedColor, - HoverColor = frame.SelectedColor, - PressedColor = frame.SelectedColor, - SelectedColor = frame.SelectedColor, - CanBeFocused = false - }; - //---------------- character area ---------------- - - string characterToolTip = character.Info.Name; - if (character.Info.Job != null) - { - characterToolTip += " (" + character.Info.Job.Name + ")"; + characterToolTip += " (" + character.Info.Job?.Name + ")"; } - var characterArea = new GUIButton(new RectTransform(new Point(characterInfoWidth, frame.Rect.Height), frame.RectTransform, Anchor.CenterLeft), style: "GUITextBox") + var tooltipColor = character.Info?.Job.Prefab?.UIColor; + var tooltipColorData = tooltipColor != null ? new List() { new ColorData() { Color = (Color)tooltipColor, EndIndex = characterToolTip.Length } } : null; + + var characterButton = new GUIButton(new RectTransform(Vector2.One, characterFrame.RectTransform, Anchor.Center), style: null) { UserData = character, - Color = frame.Color, - SelectedColor = frame.SelectedColor, - HoverColor = frame.HoverColor, - ToolTip = characterToolTip + ToolTip = characterToolTip, + TooltipColorData = tooltipColorData }; - var soundIcon = new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, - sprite: GUI.Style.GetComponentStyle("GUISoundIcon").Sprites[GUIComponent.ComponentState.None].FirstOrDefault().Sprite, scaleToFit: true) + #region Sound Icon + + new GUIImage( + new RectTransform(new Vector2(0.4f), characterFrame.RectTransform, anchor: Anchor.TopRight), + sprite: GUI.Style.GetComponentStyle("GUISoundIcon").Sprites[GUIComponent.ComponentState.None].FirstOrDefault().Sprite, + scaleToFit: true) { UserData = new Pair("soundicon", 0.0f), CanBeFocused = false, Visible = true }; - new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, + new GUIImage( + new RectTransform(new Vector2(0.5f), characterFrame.RectTransform, anchor: Anchor.TopRight), "GUISoundIconDisabled") { UserData = "soundicondisabled", @@ -426,172 +427,118 @@ namespace Barotrauma Visible = false }; - if (isSinglePlayer) + #endregion + + if (IsSinglePlayer) { - characterArea.OnClicked = CharacterClicked; + characterButton.OnClicked = CharacterClicked; } else { - characterArea.CanBeFocused = false; - characterArea.CanBeSelected = false; + characterButton.CanBeSelected = false; } - var characterImage = new GUICustomComponent(new RectTransform(new Point(characterArea.Rect.Height), characterArea.RectTransform, Anchor.CenterLeft), + new GUICustomComponent( + new RectTransform(new Point(iconSize), parent: characterFrame.RectTransform, anchor: Anchor.Center), onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2())) { CanBeFocused = false, HoverColor = Color.White, SelectedColor = Color.White, - ToolTip = characterToolTip + ToolTip = characterToolTip, + TooltipColorData = tooltipColorData }; + if (character?.Info?.Job.Prefab?.Icon != null) + { + new GUIImage( + new RectTransform(new Vector2(0.5f), characterFrame.RectTransform, anchor: Anchor.BottomLeft), + jobIndicatorBackground, + scaleToFit: true) + { + CanBeFocused = false + }; + new GUIImage( + new RectTransform(new Vector2(0.5f), characterFrame.RectTransform, anchor: Anchor.BottomLeft), + character.Info.Job.Prefab.Icon, + scaleToFit: true) + { + CanBeFocused = false, + Color = character.Info.Job.Prefab.UIColor, + ToolTip = characterToolTip, + TooltipColorData = tooltipColorData + }; + } - if (GameMain.GameSession?.GameMode?.Mission is CombatMission combatMission) + #region Combat Mission + /*if (GameMain.GameSession?.GameMode?.Mission is CombatMission combatMission) { new GUIFrame(new RectTransform(Vector2.One, characterArea.RectTransform), style: "InnerGlow", color: character.TeamID == Character.TeamType.Team1 ? Color.SteelBlue : Color.OrangeRed); + }*/ + #endregion + + return characterFrame; + } + + private void AddCharacterToCrewList(Character character) + { + GUIListBox listBox = (GUIListBox)crewList.FindChild(c => c is GUIListBox); + int height = Math.Min(crewArea.Rect.Height, (int)(listBox.Content.Rect.Width * 0.3f)); + var characterButton = new GUIButton(new RectTransform(new Point(listBox.Content.Rect.Width, height), parent: listBox.Content.RectTransform), style: null) + { + UserData = character + }; + + if (IsSinglePlayer) + { + characterButton.OnClicked = CharacterClicked; + } + else + { + characterButton.CanBeSelected = false; } - var characterName = new GUITextBlock(new RectTransform(new Point(characterArea.Rect.Width - characterImage.Rect.Width - soundIcon.Rect.Width - 10, characterArea.Rect.Height), - characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(soundIcon.Rect.Width + 10, 0) }, - character.Name, textColor: frame.Color, font: GUI.SmallFont, wrap: true) + var characterIcon = new GUICustomComponent( + new RectTransform( + new Point(height), + parent: characterButton.RectTransform, + anchor: Anchor.CenterLeft), + onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2())) { - Color = frame.Color, - HoverColor = Color.Transparent, - SelectedColor = Color.Transparent, CanBeFocused = false, - ToolTip = characterToolTip, - AutoScale = true + HoverColor = Color.White, + SelectedColor = Color.White }; - //---------------- order buttons ---------------- - - var orderButtonFrame = new GUILayoutGroup(new RectTransform(new Point(100, frame.Rect.Height), frame.RectTransform) - { AbsoluteOffset = new Point(characterInfoWidth + spacing, 0) }, - isHorizontal: true, childAnchor: Anchor.CenterLeft) + if (character?.Info?.Job.Prefab?.Icon != null) { - AbsoluteSpacing = (int)(10 * GUI.Scale), - UserData = "orderbuttons" - }; - - var spacer = new GUIFrame(new RectTransform(new Point(spacing, orderButtonFrame.Rect.Height), frame.RectTransform) - { - AbsoluteOffset = new Point(characterInfoWidth, 0) - }); - - //listbox for holding the orders inappropriate for this character - //(so we can easily toggle their visibility) - var wrongOrderList = new GUIListBox(new RectTransform(new Point(50, orderButtonFrame.Rect.Height), orderButtonFrame.RectTransform), isHorizontal: true, style: null) - { - ScrollBarEnabled = false, - ScrollBarVisible = false, - Enabled = false, - Spacing = spacing, - ClampMouseRectToParent = false - }; - wrongOrderList.Content.ClampMouseRectToParent = false; - - for (int i = 0; i < orders.Count; i++) - { - var order = orders[i]; - if (order.TargetAllCharacters) continue; - - RectTransform btnParent = (i >= genericOrderCount + correctOrderCount) ? - wrongOrderList.Content.RectTransform : - orderButtonFrame.RectTransform; - - var btn = new GUIButton(new RectTransform(new Point(iconSize, iconSize), btnParent, Anchor.CenterLeft), - style: null) + new GUIImage( + new RectTransform(new Vector2(0.5f), characterIcon.RectTransform, anchor: Anchor.BottomLeft, pivot: Pivot.BottomLeft), + jobIndicatorBackground, + scaleToFit: true) { - UserData = order + CanBeFocused = false }; - - new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlow") + new GUIImage( + new RectTransform(new Vector2(0.5f), characterIcon.RectTransform, anchor: Anchor.BottomLeft, pivot: Pivot.BottomLeft), + character.Info.Job.Prefab.Icon, + scaleToFit: true) { - Color = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.8f, - HoverColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 1.0f, - PressedColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.6f, - UserData = "selected", CanBeFocused = false, - Visible = false + Color = character.Info.Job.Prefab.UIColor }; - - var img = new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), order.Prefab.SymbolSprite); - img.Scale = iconSize / (float)img.SourceRect.Width; - img.Color = Color.Lerp(order.Color, frame.Color, 0.5f); - img.ToolTip = order.Name; - img.HoverColor = Color.Lerp(img.Color, Color.White, 0.5f); - - btn.OnClicked += (GUIButton button, object userData) => - { -#if CLIENT - if (GameMain.Client != null && Character.Controlled == null) { return false; } -#endif - if (Character.Controlled != null && Character.Controlled.SpeechImpediment >= 100.0f) { return false; } - - if (btn.GetChildByUserData("selected").Visible) - { - SetCharacterOrder(character, Order.GetPrefab("dismissed"), null, Character.Controlled); - } - else - { - if (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0 || order.Options.Length > 1) - { - CreateOrderTargetFrame(button, character, order); - } - else - { - SetCharacterOrder(character, order, null, Character.Controlled); - } - } - return true; - }; - btn.UserData = order; - btn.ToolTip = order.Name; - - //divider between different groups of orders - if (i == genericOrderCount - 1 || i == genericOrderCount + correctOrderCount - 1) - { - //TODO: divider sprite - new GUIFrame(new RectTransform(new Point(8, iconSize), orderButtonFrame.RectTransform), style: "GUIButton"); - } } - var toggleWrongOrderBtn = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), - "", style: "UIToggleButton") - { - UserData = "togglewrongorder", - CanBeFocused = false - }; + new GUITextBlock( + new RectTransform(new Point(characterButton.Rect.Width - characterIcon.Rect.Width, height), characterButton.RectTransform, anchor: Anchor.CenterRight) + { + AbsoluteOffset = new Point(HUDLayoutSettings.Padding, 0) + }, + character.Name + "\n" + character.Info?.Job?.Name, + textColor: character.Info?.Job?.Prefab?.UIColor); - wrongOrderList.RectTransform.NonScaledSize = new Point( - wrongOrderList.Content.Children.Sum(c => c.Rect.Width + wrongOrderList.Spacing), - wrongOrderList.RectTransform.NonScaledSize.Y); - wrongOrderList.RectTransform.SetAsLastChild(); - - new GUIFrame(new RectTransform(new Point( - wrongOrderList.Rect.Width - toggleWrongOrderBtn.Rect.Width - wrongOrderList.Spacing * 2, - wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), - style: null) - { - CanBeFocused = false - }; - - //scale to fit the content - orderButtonFrame.RectTransform.NonScaledSize = new Point( - orderButtonFrame.Children.Sum(c => c.Rect.Width + orderButtonFrame.AbsoluteSpacing), - orderButtonFrame.RectTransform.NonScaledSize.Y); - - frame.RectTransform.NonScaledSize = new Point( - characterInfoWidth + spacing + (orderButtonFrame.Rect.Width - wrongOrderList.Rect.Width), - frame.RectTransform.NonScaledSize.Y); - - characterListBox.RectTransform.NonScaledSize = new Point( - characterListBox.Content.Children.Max(c => c.Rect.Width) + wrongOrderList.Rect.Width, - characterListBox.RectTransform.NonScaledSize.Y); - characterListBox.Content.RectTransform.NonScaledSize = characterListBox.RectTransform.NonScaledSize; - characterListBox.UpdateScrollBarSize(); - return frame; + GUITextBlock.AutoScaleAndNormalize(listBox.Content.GetAllChildren(), defaultScale: 1.0f); } /// @@ -608,7 +555,7 @@ namespace Barotrauma public void ReviveCharacter(Character revivedCharacter) { - if (characterListBox.Content.GetChildByUserData(revivedCharacter) is GUIComponent characterBlock) + if (activeCrew.GetChildByUserData(revivedCharacter) is GUIComponent characterBlock) { characterBlock.Parent.RemoveChild(characterBlock); } @@ -617,31 +564,18 @@ namespace Barotrauma public void KillCharacter(Character killedCharacter) { - if (characterListBox.Content.GetChildByUserData(killedCharacter) is GUIComponent characterBlock) + if (activeCrew.GetChildByUserData(killedCharacter) is GUIComponent characterBlock) { CoroutineManager.StartCoroutine(KillCharacterAnim(characterBlock)); } - RemoveCharacter(killedCharacter); - } - - private bool ScrollCharacterList(GUIButton button, object obj) - { - if (characterListBox.Content.CountChildren == 0) return false; - int dir = (int)obj; - - float step = - (characterListBox.Content.Children.First().Rect.Height + characterListBox.Spacing) / - (characterListBox.TotalSize - characterListBox.Rect.Height); - characterListBox.BarScroll += dir * step; - - //round the scroll so that we're not displaying partial character frames - float roundedPos = MathUtils.RoundTowardsClosest(characterListBox.BarScroll, step); - if (Math.Abs(roundedPos - characterListBox.BarScroll) < step / 2) + else if (crewList.FindChild(c => c is GUIListBox) is GUIListBox listBox && + listBox.Content.GetChildByUserData(killedCharacter) is GUIComponent characterComponent) { - characterListBox.BarScroll = roundedPos; + listBox.Content.RemoveChild(characterComponent); + GUITextBlock.AutoScaleAndNormalize(listBox.Content.GetAllChildren(), defaultScale: 1.0f); + listBox.UpdateScrollBarSize(); } - - return false; + RemoveCharacter(killedCharacter); } private IEnumerable KillCharacterAnim(GUIComponent component) @@ -650,12 +584,10 @@ namespace Barotrauma components.Add(component); components.RemoveAll(c => c.UserData is Pair pair && pair.First == "soundicon" || - c.UserData as string == "soundicondisabled"); + c.UserData as string == "soundicondisabled" || + c is GUIButton || c is GUIFrame); - foreach (GUIComponent comp in components) - { - comp.Color = Color.DarkRed; - } + components.ForEach(c => c.Color = Color.DarkRed); yield return new WaitForSeconds(1.0f); @@ -666,25 +598,33 @@ namespace Barotrauma foreach (GUIComponent comp in components) { comp.Color = Color.Lerp(Color.DarkRed, Color.Transparent, timer / hideDuration); - comp.RectTransform.LocalScale = new Vector2(comp.RectTransform.LocalScale.X, 1.0f - (timer / hideDuration)); + comp.RectTransform.LocalScale = new Vector2(1.0f - (timer / hideDuration), comp.RectTransform.LocalScale.Y); } timer += CoroutineManager.DeltaTime; yield return CoroutineStatus.Running; } - component.Parent?.RemoveChild(component); - characterListBox.UpdateScrollBarSize(); + activeCrew.RemoveChild(component); + activeCrew.Recalculate(); + + var list = (GUIListBox)crewList.FindChild(c => c is GUIListBox); + var crewListComponent = list.Content.GetChildByUserData(component.UserData); + list.Content.RemoveChild(crewListComponent); + GUITextBlock.AutoScaleAndNormalize(list.Content.GetAllChildren(), defaultScale: 1.0f); + list.UpdateScrollBarSize(); + yield return CoroutineStatus.Success; } #endregion #region Dialog + /// /// Adds the message to the single player chatbox. /// public void AddSinglePlayerChatMessage(string senderName, string text, ChatMessageType messageType, Character sender) { - if (!isSinglePlayer) + if (!IsSinglePlayer) { DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace); return; @@ -725,15 +665,16 @@ namespace Barotrauma #endregion - #region Voice chat public void SetPlayerVoiceIconState(Client client, bool muted, bool mutedLocally) { if (client?.Character == null) { return; } - var playerFrame = characterListBox.Content.FindChild(client.Character)?.FindChild(client.Character); + var playerFrame = activeCrew.GetChildByUserData(client.Character) ?? AddCharacterToActiveCrew(client.Character); + if (playerFrame == null) { return; } + var soundIcon = playerFrame.FindChild(c => c.UserData is Pair pair && pair.First == "soundicon"); var soundIconDisabled = playerFrame.FindChild("soundicondisabled"); soundIcon.Visible = !muted && !mutedLocally; @@ -748,13 +689,18 @@ namespace Barotrauma public void SetCharacterSpeaking(Character character) { - var playerFrame = characterListBox.Content.FindChild(character)?.FindChild(character); + var playerFrame = activeCrew.GetChildByUserData(character); + if (playerFrame == null && character != Character.Controlled) + { + playerFrame = AddCharacterToActiveCrew(character); + } + if (playerFrame == null) { return; } + var soundIcon = playerFrame.FindChild(c => c.UserData is Pair pair && pair.First == "soundicon"); + soundIcon.Color = Color.White; Pair userdata = soundIcon.UserData as Pair; userdata.Second = 1.0f; - - soundIcon.Color = Color.White; } #endregion @@ -809,231 +755,46 @@ namespace Barotrauma /// public void DisplayCharacterOrder(Character character, Order order) { - foreach (GUIComponent characterListElement in characterListBox.Content.Children) + if (character == null) { return; } + + var characterFrame = activeCrew.GetChildByUserData(character); + if (characterFrame != null && characterFrame.GetChildByUserData("order") is GUIComponent existingOrderFrame) { - var characterFrame = characterListElement.FindChild(character); - if (characterFrame == null) continue; - - var orderButtonFrame = characterListElement.GetChildByUserData("orderbuttons"); - - //get all order buttons from the frame - List orderButtons = new List(); - foreach (GUIComponent child in orderButtonFrame.Children) - { - if (child is GUIButton orderBtn) - { - orderButtons.Add(orderBtn); - } - //the non-character-appropriate orders are in a hideable listbox, we need to go deeper! - else if (child is GUIListBox listBox) - { - foreach (GUIComponent listBoxElement in listBox.Content.Children) - { - if (listBoxElement is GUIButton orderBtn2 && listBoxElement.UserData is Order) orderButtons.Add(orderBtn2); - } - } - } - - foreach (GUIButton button in orderButtons) - { - var selectedIndicator = button.GetChildByUserData("selected"); - if (selectedIndicator != null) - { - selectedIndicator.Visible = (order != null && ((Order)button.UserData).Prefab == order.Prefab); - } - } - } - } - - /// - /// Create the UI panel that's used to select the target and options for a given order - /// (which railgun to use, whether to power up the reactor or shut it down...) - /// - private void CreateOrderTargetFrame(GUIComponent orderButton, Character character, Order order) - { - Submarine submarine = Character.Controlled != null && Character.Controlled.TeamID == Character.TeamType.Team2 && Submarine.MainSubs.Length > 1 ? - Submarine.MainSubs[1] : - Submarine.MainSub; - - List matchingItems = new List(); - if (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0) - { - matchingItems = order.ItemIdentifiers.Length > 0 ? - Item.ItemList.FindAll(it => order.ItemIdentifiers.Contains(it.Prefab.Identifier) || it.HasTag(order.ItemIdentifiers)) : - Item.ItemList.FindAll(it => it.Components.Any(ic => ic.GetType() == order.ItemComponentType)); - - matchingItems.RemoveAll(it => it.Submarine != submarine && !submarine.DockedTo.Contains(it.Submarine)); - matchingItems.RemoveAll(it => it.Submarine != null && it.Submarine.IsOutpost); + characterFrame.RemoveChild(existingOrderFrame); } - //more than one target item -> create a minimap-like selection with a pic of the sub - if (matchingItems.Count > 1) + if (order == null || order == dismissedOrder) { - Rectangle subBorders = submarine.GetDockedBorders(); - - Point frameSize; - if (subBorders.Width > subBorders.Height) + if (characterFrame != null) { - //make sure the right side doesn't go over the right side of the screen - frameSize.X = Math.Min(GameMain.GraphicsWidth / 2, GameMain.GraphicsWidth - orderButton.Rect.Center.X - 50); - //height depends on the dimensions of the sub - frameSize.Y = (int)(frameSize.X * (subBorders.Height / (float)subBorders.Width)); + // Remove dismissed characters from active crew + activeCrew.RemoveChild(characterFrame); + activeCrew.Recalculate(); } - else - { - //make sure the bottom side doesn't go over the bottom of the screen - frameSize.Y = Math.Min((int)(GameMain.GraphicsHeight * 0.6f), GameMain.GraphicsHeight - orderButton.Rect.Center.Y - 50); - //width depends on the dimensions of the sub - frameSize.X = (int)(frameSize.Y * (subBorders.Width / (float)subBorders.Height)); - } - orderTargetFrame = new GUIFrame(new RectTransform(frameSize, GUI.Canvas) - { AbsoluteOffset = new Point(orderButton.Rect.Center.X, orderButton.Rect.Bottom) }, - style: "InnerFrame") - { - UserData = character - }; - submarine.CreateMiniMap(orderTargetFrame, matchingItems); - - new GUICustomComponent(new RectTransform(Vector2.One, orderTargetFrame.RectTransform), DrawMiniMapOverlay) - { - CanBeFocused = false, - UserData = submarine - }; - - List optionFrames = new List(); - foreach (Item item in matchingItems) - { - var itemTargetFrame = orderTargetFrame.Children.First().FindChild(item); - if (itemTargetFrame == null) continue; - - Anchor anchor = Anchor.TopLeft; - if (itemTargetFrame.RectTransform.RelativeOffset.X < 0.5f && itemTargetFrame.RectTransform.RelativeOffset.Y < 0.5f) - anchor = Anchor.BottomRight; - else if (itemTargetFrame.RectTransform.RelativeOffset.X > 0.5f && itemTargetFrame.RectTransform.RelativeOffset.Y < 0.5f) - anchor = Anchor.BottomLeft; - else if (itemTargetFrame.RectTransform.RelativeOffset.X < 0.5f && itemTargetFrame.RectTransform.RelativeOffset.Y > 0.5f) - anchor = Anchor.TopRight; - - var optionFrame = new GUIFrame(new RectTransform(new Point((int)(250 * GUI.Scale), (int)((40 + order.Options.Length * 40) * GUI.Scale)), itemTargetFrame.RectTransform, anchor), - style: "InnerFrame"); - optionFrames.Add(optionFrame); - - new GUIFrame(new RectTransform(Vector2.One, optionFrame.RectTransform, Anchor.Center), - style: "OuterGlow") - { - Color = Color.Black * 0.7f - }; - - var optionContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f), optionFrame.RectTransform, Anchor.Center)) - { - Stretch = true, - RelativeSpacing = 0.05f - }; - - new GUITextBlock(new RectTransform(new Vector2(1.0f,0.3f), optionContainer.RectTransform), item != null ? item.Name : order.Name); - for (int i = 0; i < order.Options.Length; i++) - { - string option = order.Options[i]; - var optionButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), optionContainer.RectTransform), - order.OptionNames[i], style: "GUITextBox") - { - UserData = item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)), - Font = GUI.SmallFont, - OnClicked = (btn, userData) => - { -#if CLIENT - if (GameMain.Client != null && Character.Controlled == null) { return false; } -#endif - SetCharacterOrder(character, userData as Order, option, Character.Controlled); - orderTargetFrame = null; - OrderOptionButtons.Clear(); - return true; - } - }; - - OrderOptionButtons.Add(optionButton); - } - } - - GUI.PreventElementOverlap(optionFrames, null, new Rectangle(10, 10, GameMain.GraphicsWidth - 20, GameMain.GraphicsHeight - 20)); - } - //only one target (or an order with no particular targets), just show options - else - { - orderTargetFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f + order.Options.Length * 0.1f, 0.18f), GUI.Canvas) - { AbsoluteOffset = new Point((int)(200 * GUI.Scale), orderButton.Rect.Bottom) }, - isHorizontal: true, childAnchor: Anchor.BottomLeft) - { - UserData = character, - Stretch = true - }; - //line connecting the order button to the option buttons - //TODO: sprite - new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), orderTargetFrame.RectTransform), style: null); - - for (int i = 0; i < order.Options.Length; i++) - { - Item item = matchingItems.Count > 0 ? matchingItems[0] : null; - string option = order.Options[i]; - var optionButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), orderTargetFrame.RectTransform), - order.OptionNames[i], style: "GUITextBox") - { - UserData = item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)), - OnClicked = (btn, userData) => - { -#if CLIENT - if (GameMain.Client != null && Character.Controlled == null) { return false; } -#endif - SetCharacterOrder(character, userData as Order, option, Character.Controlled); - orderTargetFrame = null; - OrderOptionButtons.Clear(); - return true; - } - }; - new GUIFrame(new RectTransform(Vector2.One * 1.5f, optionButton.RectTransform, Anchor.Center), style: "OuterGlow") - { - Color = Color.Black, - HoverColor = Color.CadetBlue, - PressedColor = Color.Black - }.RectTransform.SetAsFirstChild(); - - OrderOptionButtons.Add(optionButton); - - //lines between the order buttons - if (i < order.Options.Length - 1) - { - //TODO: sprite - new GUIFrame(new RectTransform(new Vector2(0.1f, 1.0f), orderTargetFrame.RectTransform), style: null); - } - } - } - int shadowSize = (int)(200 * GUI.Scale); - orderTargetFrameShadow = new GUIFrame(new RectTransform(orderTargetFrame.Rect.Size + new Point(shadowSize * 2), GUI.Canvas) - { AbsoluteOffset = orderTargetFrame.Rect.Location - new Point(shadowSize) }, - style: "OuterGlow", - color: matchingItems.Count > 1 ? Color.Black * 0.9f : Color.Black * 0.7f); - } - - public void HighlightOrderButton(Character character, string orderIdentifier, Color color, Vector2? flashRectInflate = null) - { - var order = Order.GetPrefab(orderIdentifier); - if (order == null) - { - DebugConsole.ThrowError("Could not find an order with the AI tag \"" + orderIdentifier + "\".\n" + Environment.StackTrace); return; } - ToggleCrewAreaOpen = true; - var characterElement = characterListBox.Content.FindChild(character); - GUIButton orderBtn = characterElement.FindChild(order, recursive: true) as GUIButton; - if (orderBtn.FlashTimer <= 0) - { - orderBtn.Flash(color, 1.5f, false, flashRectInflate); - } - //orderBtn.Pulsate(Vector2.One, Vector2.One * 2.0f, 1.5f); + characterFrame ??= AddCharacterToActiveCrew(character); + + var orderFrame = new GUIButton( + new RectTransform(new Vector2(0.5f), characterFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter) + { + AbsoluteOffset = new Point(0, -HUDLayoutSettings.Padding) + }, + style: null) + { + UserData = "order", + OnClicked = (button, userData) => + { + SetCharacterOrder(character, dismissedOrder, null, Character.Controlled); + character.SetOrder(null, null, Character.Controlled); + return true; + } + }; + CreateNodeIcon(orderFrame.RectTransform, order.SymbolSprite, order.Color, order.Color, tooltip: order.Name); } -#region Updating and drawing the UI + #region Updating and drawing the UI private void DrawMiniMapOverlay(SpriteBatch spriteBatch, GUICustomComponent container) { @@ -1064,28 +825,26 @@ namespace Barotrauma public void AddToGUIUpdateList() { - if (GUI.DisableHUD || GUI.DisableUpperHUD) return; - if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || - prevUIScale != GUI.Scale) + if (GUI.DisableHUD) { return; } + + commandFrame?.AddToGUIUpdateList(); + + if (GUI.DisableUpperHUD) { return; } + + if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || prevUIScale != GUI.Scale) { - var prevCharacterListBox = characterListBox; + var previousCrewList = (GUIListBox)crewList.FindChild(c => c is GUIListBox); InitProjectSpecific(); - foreach (GUIComponent c in prevCharacterListBox.Content.Children) + foreach (GUIComponent c in previousCrewList.Content.Children) { - Character character = c.UserData as Character; - if (character == null || character.IsDead || character.Removed) continue; + if (!(c.UserData is Character character) || character.IsDead || character.Removed) { continue; } AddCharacter(character); DisplayCharacterOrder(character, character.CurrentOrder); } } guiFrame.AddToGUIUpdateList(); - if (orderTargetFrame != null) - { - orderTargetFrameShadow?.AddToGUIUpdateList(); - orderTargetFrame?.AddToGUIUpdateList(); - } } public void SelectNextCharacter() @@ -1146,7 +905,150 @@ namespace Barotrauma } } - if (GUI.DisableHUD || GUI.DisableUpperHUD) return; + if (GUI.DisableHUD) { return; } + + #region Command UI + + if (PlayerInput.KeyDown(InputType.Command) && GUI.KeyboardDispatcher.Subscriber == null && + (!GameMain.IsMultiplayer || (GameMain.IsMultiplayer && DebugConsole.CheatsEnabled)) && + commandFrame == null && !clicklessSelectionActive) + { + bool canIssueOrders = false; + if (Character.Controlled != null && Character.Controlled.SpeechImpediment < 100.0f) + { + WifiComponent radio = GetHeadset(Character.Controlled, true); + canIssueOrders = radio != null && radio.CanTransmit(); + } + + if (canIssueOrders) + { + CreateCommandUI(); + clicklessSelectionActive = isOpeningClick = true; + } + } + + if (commandFrame != null) + { + if ((GameMain.IsMultiplayer && !DebugConsole.CheatsEnabled && Character.Controlled == null)) + { + DisableCommandUI(); + } + else if (PlayerInput.RightButtonClicked() && + (optionNodes.Any(n => GUI.IsMouseOn(n)) || shortcutNodes.Any(n => GUI.IsMouseOn(n)))) + { + var node = optionNodes.Find(n => GUI.IsMouseOn(n)); + if (node == null) + { + node = shortcutNodes.Find(n => GUI.IsMouseOn(n)); + } + // Make sure the node is for an option-less order... + if (node.UserData is Order order && + !(order.ItemComponentType != null || order.ItemIdentifiers.Length > 0 || order.Options.Length > 1)) + { + CreateAssignmentNodes(node); + } + // ...or an order option + else if (node.UserData is Tuple) + { + CreateAssignmentNodes(node); + } + } + // TODO: Consider using HUD.CloseHUD() instead of KeyHit(Escape), the former method is also used for health UI + else if ((PlayerInput.KeyHit(InputType.Command) && selectedNode == null && !clicklessSelectionActive) || + PlayerInput.KeyHit(InputType.Deselect) || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) + { + DisableCommandUI(); + } + else if (PlayerInput.KeyUp(InputType.Command)) + { + if (!isOpeningClick && clicklessSelectionActive && timeSelected < 0.15f) + { + DisableCommandUI(); + } + else + { + clicklessSelectionActive = isOpeningClick = false; + if (selectedNode != null) + { + selectedNode.Children.ForEach(c => c.Color = c.HoverColor * nodeColorMultiplier); + selectedNode = null; + timeSelected = 0; + } + } + } + else if (PlayerInput.KeyDown(InputType.Command) && (targetFrame == null || !targetFrame.Visible)) + { + if (!GUI.IsMouseOn(centerNode)) + { + clicklessSelectionActive = true; + + var mouseBearing = GetBearing(centerNode.Center, PlayerInput.MousePosition, flipY: true); + + GUIComponent closestNode = null; + float closestBearing = 0; + + optionNodes.ForEach(n => CheckIfClosest(n)); + CheckIfClosest(returnNode); + + void CheckIfClosest(GUIComponent comp) + { + if (comp == null) { return; } + var offset = comp.RectTransform.AbsoluteOffset; + var nodeBearing = GetBearing(centerNode.RectTransform.AbsoluteOffset.ToVector2(), offset.ToVector2(), flipY: true); + if (closestNode == null) + { + closestNode = comp; + closestBearing = Math.Abs(nodeBearing - mouseBearing); + } + else + { + var difference = Math.Abs(nodeBearing - mouseBearing); + if (difference < closestBearing) + { + closestNode = comp; + closestBearing = difference; + } + } + } + + if (closestNode == selectedNode) + { + timeSelected += deltaTime; + if (timeSelected >= selectionTime) + { + selectedNode.OnClicked.Invoke(selectedNode, selectedNode.UserData); + selectedNode = null; + timeSelected = 0; + } + } + else + { + if (selectedNode != null) + { + selectedNode.Children.ForEach(c => c.Color = c.HoverColor * nodeColorMultiplier); + } + selectedNode = closestNode as GUIButton; + selectedNode.Children.ForEach(c => c.Color = c.HoverColor); + timeSelected = 0; + } + } + else if (selectedNode != null) + { + selectedNode.Children.ForEach(c => c.Color = c.HoverColor * nodeColorMultiplier); + selectedNode = null; + timeSelected = 0; + } + } + } + else if (PlayerInput.KeyUp(InputType.Command)) + { + clicklessSelectionActive = false; + } + + #endregion + + if (GUI.DisableUpperHUD) { return; } + if (ChatBox != null) { ChatBox.Update(deltaTime); @@ -1170,69 +1072,41 @@ namespace Barotrauma } crewArea.Visible = characters.Count > 0 && CharacterHealth.OpenHealthWindow == null; - if (orderTargetFrame != null) orderTargetFrame.Visible = characterListBox.Visible; - scrollButtonUp.Visible = characterListBox.BarScroll > 0.01f && characterListBox.BarSize < 1.0f; - scrollButtonDown.Visible = characterListBox.BarScroll < 0.99 && characterListBox.BarSize < 1.0f; - - foreach (GUIComponent child in characterListBox.Content.Children) + var shouldBeRemoved = new List(); + foreach (GUIComponent child in activeCrew.Children) { Character character = (Character)child.UserData; + if (character == null) { continue; } child.Visible = Character.Controlled == null || (Character.Controlled.TeamID == character.TeamID); if (child.Visible) { - child.GetChildByUserData("highlight").Visible = character == Character.Controlled; - - var soundIcon = child.FindChild(character)?.FindChild(c => c.UserData is Pair pair && pair.First == "soundicon") as GUIImage; + //child.GetChildByUserData("highlight").Visible = character == Character.Controlled; + var soundIcon = child.FindChild(c => c.UserData is Pair pair && pair.First == "soundicon") as GUIImage; VoipClient.UpdateVoiceIndicator(soundIcon, 0.0f, deltaTime); - - GUIListBox wrongOrderList = child.GetChildByUserData("orderbuttons")?.GetChild(); - if (wrongOrderList != null) + if (soundIcon.UserData is Pair soundStatus && + soundStatus.Second < 0.1f && child.FindChild("order") == null) { - Rectangle hoverRect = wrongOrderList.Rect; - if (wrongOrderList.BarScroll < 0.5f) - { - //higher tolerance when the orderlist is open (mouse needs to be moved further before it closes) - hoverRect.Inflate((int)(50 * GUI.Scale), (int)(50 * GUI.Scale)); - } - else - { - hoverRect.Inflate((int)(30 * GUI.Scale), (int)(0 * GUI.Scale)); - } - - bool toggleOpen = - characterListBox.Content.Rect.Contains(PlayerInput.MousePosition) && - hoverRect.Contains(PlayerInput.MousePosition); - wrongOrderList.CanBeFocused = toggleOpen; - wrongOrderList.Content.CanBeFocused = toggleOpen; - var wrongOrderBtn = wrongOrderList.GetChildByUserData("togglewrongorderbtn"); - if (wrongOrderBtn != null) - { - wrongOrderBtn.CanBeFocused = toggleOpen; - } - - //order target frame open on this character, check if we're giving any of the orders in wrongOrderList - if (!toggleOpen && orderTargetFrame != null && orderTargetFrame.UserData == child.UserData) - { - toggleOpen = wrongOrderList.Content.Children.Any(c => - c.UserData is Order order && - orderTargetFrame.Children.Any(c2 => c2.UserData == c.UserData)); - } - - float scroll = MathHelper.Clamp(wrongOrderList.BarScroll + (toggleOpen ? -deltaTime * 5.0f : deltaTime * 5.0f), 0.0f, 1.0f); - if (Math.Abs(wrongOrderList.BarScroll - scroll) > 0.01f) { wrongOrderList.BarScroll = scroll; } + shouldBeRemoved.Add(child); } } } + if (shouldBeRemoved.Any()) + { + shouldBeRemoved.ForEach(c => activeCrew.RemoveChild(c)); + activeCrew.Recalculate(); + } - crewArea.RectTransform.AbsoluteOffset = - Vector2.SmoothStep(new Vector2(-crewArea.Rect.Width, 0), new Vector2(toggleCrewButton.Rect.Width, 0), crewAreaOpenState).ToPoint(); - crewAreaOpenState = ToggleCrewAreaOpen ? - Math.Min(crewAreaOpenState + deltaTime * 2.0f, 1.0f) : - Math.Max(crewAreaOpenState - deltaTime * 2.0f, 0.0f); + crewList.RectTransform.AbsoluteOffset = Vector2.SmoothStep( + new Vector2(-HUDLayoutSettings.Padding - crewList.Rect.Width / 2.0f, -HUDLayoutSettings.Padding * 6), + new Vector2(0.0f, -HUDLayoutSettings.Padding * 6), + crewListOpenState).ToPoint(); + crewListOpenState = ToggleCrewListOpen ? + Math.Min(crewListOpenState + deltaTime * 2.0f, 1.0f) : + Math.Max(crewListOpenState - deltaTime * 2.0f, 0.0f); if (GUI.KeyboardDispatcher.Subscriber == null && PlayerInput.KeyHit(InputType.CrewOrders) && @@ -1243,33 +1117,887 @@ namespace Barotrauma { Character.Controlled.SelectedConstruction = null; } - ToggleCrewAreaOpen = !ToggleCrewAreaOpen; + ToggleCrewListOpen = !ToggleCrewListOpen; } - UpdateReports(deltaTime); + UpdateReports(); + } - if (orderTargetFrame != null) + #endregion + + #region Command UI + + public static bool IsCommandInterfaceOpen + { + get { - Rectangle hoverArea = orderTargetFrame.Rect; - foreach (GUIComponent child in orderTargetFrame.Children.First().Children) - { - if (!(child.UserData is Item)) continue; - foreach (GUIComponent grandChild in child.Children) - { - hoverArea = Rectangle.Union(hoverArea, grandChild.Rect); - } - } - hoverArea.Inflate(100, 100); + return commandFrame != null; + } + } + private static GUIFrame commandFrame, targetFrame; + private static GUIButton centerNode, returnNode, expandNode, shortcutCenterNode; + private static List optionNodes = new List(); + private static List shortcutNodes = new List(); + private static List extraOptionNodes = new List(); + private static GUICustomComponent nodeConnectors; + private static GUIImage background; - if (!hoverArea.Contains(PlayerInput.MousePosition) || PlayerInput.SecondaryMouseButtonClicked()) + private static GUIButton selectedNode; + private static float selectionTime = 0.75f, timeSelected = 0.0f; + private static bool clicklessSelectionActive, isOpeningClick; + + private Point centerNodeSize, nodeSize, shortcutCenterNodeSize, shortcutNodeSize, returnNodeSize; + private float centerNodeMargin, optionNodeMargin, shortcutCenterNodeMargin, shortcutNodeMargin, returnNodeMargin; + + private List availableCategories; + private static Stack historyNodes = new Stack(); + private static List extraOptionCharacters = new List(); + + /// + /// node.Color = node.HighlightColor * nodeColorMultiplier + /// + private const float nodeColorMultiplier = 0.75f; + private const int assignmentNodeMaxCount = 5; + private int nodeDistance = 150; + private float returnNodeDistanceModifier = 0.75f; + private Order dismissedOrder; + + private void CreateCommandUI() + { + ScaleCommandUI(); + commandFrame = new GUIFrame( + new RectTransform(Vector2.Zero, GUICanvas.Instance, anchor: Anchor.Center), + style: null, + color: Color.Transparent); + background = new GUIImage( + new RectTransform(Vector2.One, commandFrame.RectTransform, anchor: Anchor.Center), + Order.CommandBackground); + background.Color = background.Color * 0.8f; + var startNode = new GUIButton( + new RectTransform(centerNodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center), + style: null); + CreateNodeIcon(startNode.RectTransform, Order.StartNode, Color.White, Color.White); + SetCenterNode(startNode); + + if (availableCategories == null) + { + GetAvailableCategories(); + } + if (dismissedOrder == null) + { + dismissedOrder = Order.GetPrefab("dismissed"); + } + + CreateShortcutNodes(); + CreateOrderCategoryNodes(); + CreateNodeConnectors(); + } + + private void ToggleCommandUI() + { + if (commandFrame == null) + { + CreateCommandUI(); + } + else + { + DisableCommandUI(); + } + } + + private void ScaleCommandUI() + { + centerNodeSize = new Point((int)(80 * GUI.Scale)); + nodeSize = new Point((int)(80 * GUI.Scale)); + shortcutCenterNodeSize = new Point((int)(48 * GUI.Scale)); + shortcutNodeSize = new Point((int)(64 * GUI.Scale)); + returnNodeSize = new Point((int)(48 * GUI.Scale)); + centerNodeMargin = centerNodeSize.X * 0.6f; + optionNodeMargin = nodeSize.X * 0.6f; + shortcutCenterNodeMargin = shortcutCenterNodeSize.X * 0.45f; + shortcutNodeMargin = shortcutNodeSize.X * 0.6f; + returnNodeMargin = returnNodeSize.X * 0.6f; + nodeDistance = (int)(150 * GUI.Scale); + } + + private void GetAvailableCategories() + { + availableCategories = new List(); + foreach (OrderCategory category in Enum.GetValues(typeof(OrderCategory))) + { + if (category == OrderCategory.Undefined) { continue; } + if (Order.PrefabList.Any(o => o.Category == category && !o.TargetAllCharacters)) { - orderTargetFrame = null; - OrderOptionButtons.Clear(); + availableCategories.Add(category); } } } -#endregion + private void CreateNodeConnectors() + { + nodeConnectors = new GUICustomComponent( + new RectTransform(Vector2.One, commandFrame.RectTransform), + onDraw: DrawNodeConnectors); + nodeConnectors.SetAsFirstChild(); + background.SetAsFirstChild(); + } + + private void DrawNodeConnectors(SpriteBatch spriteBatch, GUIComponent container) + { + if (centerNode == null || optionNodes == null) { return; } + var startNodePos = centerNode.Rect.Center.ToVector2(); + if (targetFrame == null || !targetFrame.Visible) + { + optionNodes.ForEach(n => DrawNodeConnector(startNodePos, centerNodeMargin, n, optionNodeMargin, spriteBatch)); + } + DrawNodeConnector(startNodePos, centerNodeMargin, returnNode, returnNodeMargin, spriteBatch); + DrawNodeConnector(startNodePos, centerNodeMargin, expandNode, optionNodeMargin, spriteBatch); + if (shortcutCenterNode == null || !shortcutCenterNode.Visible) { return; } + DrawNodeConnector(startNodePos, centerNodeMargin, shortcutCenterNode, shortcutCenterNodeMargin, spriteBatch); + startNodePos = shortcutCenterNode.Rect.Center.ToVector2(); + shortcutNodes.ForEach(n => DrawNodeConnector(startNodePos, shortcutCenterNodeMargin, n, shortcutNodeMargin, spriteBatch)); + } + + private void DrawNodeConnector(Vector2 startNodePos, float startNodeMargin, GUIComponent endNode, float endNodeMargin, SpriteBatch spriteBatch) + { + if (endNode == null || !endNode.Visible) { return; } + var endNodePos = endNode.Rect.Center.ToVector2(); + var direction = (endNodePos - startNodePos) / Vector2.Distance(startNodePos, endNodePos); + var start = startNodePos + direction * startNodeMargin; + var end = endNodePos - direction * endNodeMargin; + var colorSource = endNode.GetChildByUserData("container"); + if (colorSource == null) { colorSource = endNode.GetChildByUserData("icon"); } + if ((selectedNode == null && endNode != shortcutCenterNode && GUI.IsMouseOn(endNode)) || + endNode == selectedNode || endNode == shortcutCenterNode && shortcutNodes.Any(n => GUI.IsMouseOn(n))) + { + GUI.DrawLine(spriteBatch, start, end, colorSource != null ? colorSource.HoverColor : Color.White, width: 4); + } + else + { + GUI.DrawLine(spriteBatch, start, end, colorSource != null ? colorSource.Color : Color.White * nodeColorMultiplier, width: 2); + } + } + + public static void DisableCommandUI() + { + if (commandFrame == null) { return; } + RemoveOptionNodes(); + historyNodes.Clear(); + nodeConnectors = null; + centerNode = null; + returnNode = null; + expandNode = null; + shortcutCenterNode = null; + targetFrame = null; + selectedNode = null; + timeSelected = 0; + background = null; + commandFrame = null; + extraOptionCharacters.Clear(); + clicklessSelectionActive = isOpeningClick = false; + } + + private bool NavigateForward(GUIButton node, object userData) + { + if (!optionNodes.Remove(node)) { shortcutNodes.Remove(node); }; + RemoveOptionNodes(); + if (returnNode != null) + { + returnNode.Children.ForEach(child => child.Visible = false); + returnNode.Visible = false; + historyNodes.Push(returnNode); + } + SetReturnNode(centerNode, new Point( + (int)(node.RectTransform.AbsoluteOffset.X * -returnNodeDistanceModifier), + (int)(node.RectTransform.AbsoluteOffset.Y * -returnNodeDistanceModifier))); + SetCenterNode(node); + if (shortcutCenterNode != null) + { + commandFrame.RemoveChild(shortcutCenterNode); + shortcutCenterNode = null; + } + CreateNodes(userData); + return true; + } + + private bool NavigateBackward(GUIButton node, object userData) + { + RemoveOptionNodes(); + if (targetFrame != null) { targetFrame.Visible = false; } + // TODO: Center node could move to option node instead of being removed + commandFrame.RemoveChild(centerNode); + SetCenterNode(node); + if (historyNodes.Count > 0) + { + var historyNode = historyNodes.Pop(); + SetReturnNode(historyNode, historyNode.RectTransform.AbsoluteOffset); + historyNode.Visible = true; + historyNode.Children.ForEach(child => child.Visible = true); + } + else + { + returnNode = null; + } + CreateNodes(userData); + return true; + } + + private void SetCenterNode(GUIButton node) + { + node.RectTransform.Parent = commandFrame.RectTransform; + node.RectTransform.NonScaledSize = centerNodeSize; + node.RectTransform.AbsoluteOffset = Point.Zero; + foreach (GUIComponent c in node.Children) + { + c.Color = c.HoverColor * nodeColorMultiplier; + c.HoverColor = c.Color; + c.PressedColor = c.Color; + c.SelectedColor = c.Color; + c.ToolTip = null; + } + node.OnClicked = null; + centerNode = node; + } + + private void SetReturnNode(GUIButton node, Point offset) + { + node.RectTransform.NonScaledSize = returnNodeSize; + node.RectTransform.AbsoluteOffset = offset; + foreach (GUIComponent c in node.Children) + { + c.HoverColor = c.Color * (1 / nodeColorMultiplier); + c.PressedColor = c.HoverColor; + c.SelectedColor = c.HoverColor; + c.ToolTip = TextManager.Get("commandui.return"); + } + node.OnClicked = NavigateBackward; + returnNode = node; + } + + private bool CreateNodes(object userData) + { + if (userData == null) + { + CreateShortcutNodes(); + CreateOrderCategoryNodes(); + } + else if (userData is OrderCategory category) + { + CreateOrderNodes(category); + } + else if (userData is Order order) + { + CreateOrderOptions(order); + } + return true; + } + + private static void RemoveOptionNodes() + { + optionNodes.ForEach(node => commandFrame.RemoveChild(node)); + optionNodes.Clear(); + shortcutNodes.ForEach(node => commandFrame.RemoveChild(node)); + shortcutNodes.Clear(); + commandFrame.RemoveChild(expandNode); + RemoveExtraOptionNodes(); + } + + private static void RemoveExtraOptionNodes() + { + extraOptionNodes.ForEach(node => commandFrame.RemoveChild(node)); + extraOptionNodes.Clear(); + } + + private void CreateOrderCategoryNodes() + { + var points = shortcutCenterNode != null ? + GetCircumferencePointCount(availableCategories.Count) : + availableCategories.Count; + var firstAngle = shortcutCenterNode != null ? + GetFirstNodeAngle(availableCategories.Count) : + 0.0f; + var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, points, firstAngle); + var offsetIndex = 0; + availableCategories.ForEach(oc => CreateOrderCategoryNode(oc, offsets[offsetIndex++].ToPoint())); + } + + private void CreateOrderCategoryNode(OrderCategory category, Point offset) + { + var node = new GUIButton( + new RectTransform(nodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center) + { + AbsoluteOffset = offset + }, + style: null) + { + UserData = category, + OnClicked = NavigateForward + }; + if (Order.OrderCategoryIcons.TryGetValue(category, out Sprite sprite)) + { + var tooltip = TextManager.Get("ordercategorytitle." + category.ToString().ToLower()); + var categoryDescription = TextManager.Get("ordercategorydescription." + category.ToString(), true); + if (!string.IsNullOrWhiteSpace(categoryDescription)) { tooltip += "\n" + categoryDescription; } + CreateNodeIcon(node.RectTransform, sprite, Color.White, Color.White, tooltip: tooltip); + } + optionNodes.Add(node); + } + + private void CreateShortcutNodes() + { + shortcutNodes.Clear(); + + var sub = Character.Controlled != null && Character.Controlled.TeamID == Character.TeamType.Team2 && Submarine.MainSubs.Length > 1 ? + Submarine.MainSubs[1] : Submarine.MainSub; + var reactor = sub.GetItems(false).Find(i => i.HasTag("reactor")).GetComponent(); + var reactorOutput = -reactor.CurrPowerConsumption; + + // If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor + // ---> Create shortcut node for "Operate Reactor" order's "Power Up" option + if ((Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("engineer")) && + reactorOutput < float.Epsilon && characters.None(c => c.SelectedConstruction == reactor.Item)) + { + var order = new Order(Order.GetPrefab("operatereactor"), reactor.Item, reactor, Character.Controlled); + shortcutNodes.Add( + CreateOrderOptionNode(shortcutNodeSize, null, Point.Zero, order, order.Prefab.Options[0], order.Prefab.OptionNames[0])); + } + + // TODO: Reconsider the conditions as bot captain can have the nav term selected without operating it + // If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up + // --> Create shortcut node for Steer order + if ((Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("captain")) && + sub.GetItems(false).Find(i => i.HasTag("navterminal")) is Item nav && characters.None(c => c.SelectedConstruction == nav) && + nav.GetComponent() is Steering steering && steering.Voltage > steering.MinVoltage) + { + shortcutNodes.Add( + CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("steer"))); + } + + // If player is not a security officer AND invaders are reported + // --> Create shorcut node for Fight Intruders order + if ((Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("securityofficer")) && + (Order.GetPrefab("reportintruders") is Order reportIntruders && ActiveOrders.Any(o => o.First.Prefab == reportIntruders))) + { + shortcutNodes.Add( + CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("fightintruders"))); + } + + // If player is not a mechanic AND a breach has been reported + // --> Create shorcut node for Fix Leaks order + if ((Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("mechanic")) && + (Order.GetPrefab("reportbreach") is Order reportBreach && ActiveOrders.Any(o => o.First.Prefab == reportBreach))) + { + shortcutNodes.Add( + CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("fixleaks"))); + } + + // If player is not an engineer AND broken devices have been reported + // --> Create shortcut node for Repair Damaged Systems order + if ((Character.Controlled == null || Character.Controlled.Info.Job.Prefab != JobPrefab.Get("engineer")) && + (Order.GetPrefab("reportbrokendevices") is Order reportBrokenDevices && ActiveOrders.Any(o => o.First.Prefab == reportBrokenDevices))) + { + shortcutNodes.Add( + CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("repairsystems"))); + } + + // If fire is reported + // --> Create shortcut node for Extinguish Fires order + if (ActiveOrders.Any(o=> o.First.Prefab == Order.GetPrefab("reportfire"))) + { + shortcutNodes.Add( + CreateOrderNode(shortcutNodeSize, null, Point.Zero, Order.GetPrefab("extinguishfires"))); + } + + if (shortcutNodes.Count < 1) { return; } + + shortcutCenterNode = new GUIButton( + new RectTransform(shortcutCenterNodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center) + { + AbsoluteOffset = new Point(0, (int)(1.25f * nodeDistance)) + }, + style: null); + CreateNodeIcon(shortcutCenterNode.RectTransform, Order.ShortcutNode, Color.Red, Color.Red, createContainer: false); + foreach (GUIComponent c in shortcutCenterNode.Children) + { + c.HoverColor = c.Color; + c.PressedColor = c.Color; + c.SelectedColor = c.Color; + } + + var nodeCountForCalculations = shortcutNodes.Count * 2 + 2; + var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, 0.75f * nodeDistance, nodeCountForCalculations); + for (int i = 0; i < shortcutNodes.Count; i++) + { + shortcutNodes[i].RectTransform.Parent = commandFrame.RectTransform; + shortcutNodes[i].RectTransform.AbsoluteOffset = shortcutCenterNode.RectTransform.AbsoluteOffset + offsets[i + 1].ToPoint(); + } + } + + private void CreateOrderNodes(OrderCategory orderCategory) + { + var orders = Order.PrefabList.FindAll(o => o.Category == orderCategory && !o.TargetAllCharacters); + var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, + GetCircumferencePointCount(orders.Count), GetFirstNodeAngle(orders.Count)); + for(int i = 0; i < orders.Count; i++) + { + optionNodes.Add(CreateOrderNode(nodeSize, commandFrame.RectTransform, offsets[i].ToPoint(), orders[i])); + } + } + + private GUIButton CreateOrderNode(Point size, RectTransform parent, Point offset, Order order) + { + var node = new GUIButton( + new RectTransform(size, parent: parent, anchor: Anchor.Center) + { + AbsoluteOffset = offset + }, + style: null) + { + UserData = order + }; + var hasOptions = order.ItemComponentType != null || order.ItemIdentifiers.Length > 0 || order.Options.Length > 1; + node.OnClicked = (button, userData) => + { + if (Character.Controlled != null && Character.Controlled.SpeechImpediment >= 100.0f) { return false; } + var o = userData as Order; + // TODO: Consider defining orders' or order categories' quick-assignment possibility in the XML + if (o.Category == OrderCategory.Movement) + { + CreateAssignmentNodes(node); + } + else if (hasOptions) + { + NavigateForward(button, userData); + } + else + { + SetCharacterOrder(GetBestCharacterForOrder(o), o, null, Character.Controlled); + DisableCommandUI(); + } + return true; + }; + CreateNodeIcon(node.RectTransform, order.SymbolSprite, order.Color, order.Color, + tooltip: hasOptions ? order.Name : + order.Name + "\nLMB: " + TextManager.Get("commandui.quickassigntooltip") + "\nRMB: " + TextManager.Get("commandui.manualassigntooltip")); + return node; + } + + private void CreateOrderOptions(Order order) + { + // This is largely based on the CreateOrderTargetFrame() method + + Submarine submarine = Character.Controlled != null && Character.Controlled.TeamID == Character.TeamType.Team2 && Submarine.MainSubs.Length > 1 ? + Submarine.MainSubs[1] : + Submarine.MainSub; + + List matchingItems = new List(); + if (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0) + { + matchingItems = order.ItemIdentifiers.Length > 0 ? + Item.ItemList.FindAll(it => order.ItemIdentifiers.Contains(it.Prefab.Identifier) || it.HasTag(order.ItemIdentifiers)) : + Item.ItemList.FindAll(it => it.Components.Any(ic => ic.GetType() == order.ItemComponentType)); + + matchingItems.RemoveAll(it => it.Submarine != submarine && !submarine.DockedTo.Contains(it.Submarine)); + matchingItems.RemoveAll(it => it.Submarine != null && it.Submarine.IsOutpost); + } + + //more than one target item -> create a minimap-like selection with a pic of the sub + if (matchingItems.Count > 1) + { + // TODO: Further adjustments to frameSize calculations + // I just divided the existing sizes by 2 to get it working quickly without it overlapping too much + Point frameSize; + Rectangle subBorders = submarine.GetDockedBorders(); + if (subBorders.Width > subBorders.Height) + { + frameSize.X = Math.Min(GameMain.GraphicsWidth / 2, GameMain.GraphicsWidth - 50) / 2; + //height depends on the dimensions of the sub + frameSize.Y = (int)(frameSize.X * (subBorders.Height / (float)subBorders.Width)); + } + else + { + frameSize.Y = Math.Min((int)(GameMain.GraphicsHeight * 0.6f), GameMain.GraphicsHeight - 50) / 2; + //width depends on the dimensions of the sub + frameSize.X = (int)(frameSize.Y * (subBorders.Width / (float)subBorders.Height)); + } + + // TODO: Use the old targetFrame if possible + targetFrame = new GUIFrame( + new RectTransform(frameSize, parent: commandFrame.RectTransform, anchor: Anchor.Center) + { + AbsoluteOffset = new Point(0, -150), + Pivot = Pivot.BottomCenter + }, + style: "InnerFrame"); + + submarine.CreateMiniMap(targetFrame, pointsOfInterest: matchingItems); + + new GUICustomComponent(new RectTransform(Vector2.One, targetFrame.RectTransform), onDraw: DrawMiniMapOverlay) + { + CanBeFocused = false, + UserData = submarine + }; + + List optionFrames = new List(); + foreach (Item item in matchingItems) + { + var itemTargetFrame = targetFrame.Children.First().FindChild(item); + if (itemTargetFrame == null) { continue; } + + var anchor = Anchor.TopLeft; + if (itemTargetFrame.RectTransform.RelativeOffset.X < 0.5f && itemTargetFrame.RectTransform.RelativeOffset.Y < 0.5f) + { + anchor = Anchor.BottomRight; + } + else if (itemTargetFrame.RectTransform.RelativeOffset.X > 0.5f && itemTargetFrame.RectTransform.RelativeOffset.Y < 0.5f) + { + anchor = Anchor.BottomLeft; + } + + else if (itemTargetFrame.RectTransform.RelativeOffset.X < 0.5f && itemTargetFrame.RectTransform.RelativeOffset.Y > 0.5f) + { + anchor = Anchor.TopRight; + } + + var optionFrame = new GUIFrame( + new RectTransform( + new Point((int)(250 * GUI.Scale), (int)((40 + order.Options.Length * 40) * GUI.Scale)), + parent: itemTargetFrame.RectTransform, + anchor: anchor), + style: "InnerFrame"); + + new GUIFrame( + new RectTransform(Vector2.One, optionFrame.RectTransform, anchor: Anchor.Center), + style: "OuterGlow", + color: Color.Black * 0.7f); + + var optionContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f), optionFrame.RectTransform, anchor: Anchor.Center)) + { + RelativeSpacing = 0.05f, + Stretch = true + }; + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), optionContainer.RectTransform), item != null ? item.Name : order.Name); + + for (int i = 0; i < order.Options.Length; i++) + { + optionNodes.Add(new GUIButton( + new RectTransform(new Vector2(1.0f, 0.2f), optionContainer.RectTransform), + text: order.OptionNames[i], + style: "GUITextBox") + { + UserData = new Tuple( + item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)), + order.Options[i]), + Font = GUI.SmallFont, + OnClicked = (_, userData) => + { + if (GameMain.Client != null && Character.Controlled == null) { return false; } + var o = userData as Tuple; + SetCharacterOrder(GetBestCharacterForOrder(o.Item1), o.Item1, o.Item2, Character.Controlled); + DisableCommandUI(); + return true; + } + }); + } + optionFrames.Add(optionFrame); + } + GUI.PreventElementOverlap(optionFrames, clampArea: new Rectangle(10, 10, GameMain.GraphicsWidth - 20, GameMain.GraphicsHeight - 20)); + + var shadow = new GUIFrame( + new RectTransform(targetFrame.Rect.Size + new Point((int)(200 * GUI.Scale)), targetFrame.RectTransform, anchor: Anchor.Center), + style: "OuterGlow", + color: matchingItems.Count > 1 ? Color.Black * 0.9f : Color.Black * 0.7f); + shadow.SetAsFirstChild(); + } + //only one target (or an order with no particular targets), just show options + else + { + var item = matchingItems.Count > 0 ? matchingItems[0] : null; + var o = item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)); + var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, + GetCircumferencePointCount(order.Options.Length), + GetFirstNodeAngle(order.Options.Length)); + var offsetIndex = 0; + for (int i = 0; i < order.Options.Length; i++) + { + optionNodes.Add( + CreateOrderOptionNode(nodeSize, commandFrame.RectTransform, offsets[offsetIndex++].ToPoint(), o, order.Options[i], order.OptionNames[i])); + } + } + } + + private GUIButton CreateOrderOptionNode(Point size, RectTransform parent, Point offset, Order order, string option, string optionName) + { + var node = new GUIButton( + new RectTransform(size, parent: parent, anchor: Anchor.Center) + { + AbsoluteOffset = offset + }, + style: null) + { + UserData = new Tuple(order, option), + OnClicked = (_, userData) => + { + if (GameMain.Client != null && Character.Controlled == null) { return false; } + var o = userData as Tuple; + SetCharacterOrder(GetBestCharacterForOrder(o.Item1), o.Item1, o.Item2, Character.Controlled); + DisableCommandUI(); + return true; + } + }; + if (order.Prefab.OptionSprites.TryGetValue(option, out Sprite sprite)) + { + CreateNodeIcon(node.RectTransform, sprite, order.Color, order.Color, + tooltip: optionName + "\nLMB: " + TextManager.Get("commandui.quickassigntooltip") + "\nRMB: " + TextManager.Get("commandui.manualassigntooltip")); + } + return node; + } + + private void CreateAssignmentNodes(GUIComponent node) + { + var order = (node.UserData is Order) ? + new Tuple(node.UserData as Order, null) : + node.UserData as Tuple; + var characters = GetCharactersSortedForOrder(order.Item1); + if (characters.Count < 1) { return; } + + if (!optionNodes.Remove(node)) { shortcutNodes.Remove(node); }; + RemoveOptionNodes(); + if (returnNode != null) + { + returnNode.Children.ForEach(child => child.Visible = false); + returnNode.Visible = false; + historyNodes.Push(returnNode); + } + SetReturnNode(centerNode, new Point( + (int)(node.RectTransform.AbsoluteOffset.X * -returnNodeDistanceModifier), + (int)(node.RectTransform.AbsoluteOffset.Y * -returnNodeDistanceModifier))); + if (targetFrame == null || !targetFrame.Visible) + { + SetCenterNode(node as GUIButton); + } + else + { + var optionNode = new GUIButton( + new RectTransform(centerNodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center), + style: null) + { + UserData = node.UserData + }; + if (order.Item1.Prefab.OptionSprites.TryGetValue(order.Item2, out Sprite sprite)) + { + CreateNodeIcon(optionNode.RectTransform, sprite, order.Item1.Color, order.Item1.Color, tooltip: order.Item2); + } + SetCenterNode(optionNode); + node = null; + targetFrame.Visible = false; + } + if (shortcutCenterNode != null) + { + commandFrame.RemoveChild(shortcutCenterNode); + shortcutCenterNode = null; + } + + var needToExpand = characters.Count > assignmentNodeMaxCount + 1; + var nodeCount = needToExpand ? assignmentNodeMaxCount + 1 : characters.Count; + var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, + GetCircumferencePointCount(nodeCount), + GetFirstNodeAngle(nodeCount)); + + var i = 0; + var assignmentNodeCount = (needToExpand ? nodeCount - 1 : nodeCount); + for (; i < assignmentNodeCount; i++) + { + CreateAssignmentNode(order, characters[i], offsets[i].ToPoint()); + } + + if (!needToExpand) { return; } + + extraOptionCharacters.Clear(); + extraOptionCharacters.AddRange(characters.GetRange(i, characters.Count - i)); + + expandNode = new GUIButton( + new RectTransform(nodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center) + { + AbsoluteOffset = offsets[i].ToPoint() + }, + style: null) + { + UserData = order, + OnClicked = ExpandAssignmentNodes + }; + CreateNodeIcon(expandNode.RectTransform, Order.ExpandNode, order.Item1.Color, order.Item1.Color, tooltip: TextManager.Get("commandui.expand")); + } + + private bool ExpandAssignmentNodes(GUIButton node, object userData) + { + node.OnClicked = (button, _) => + { + RemoveExtraOptionNodes(); + button.OnClicked = ExpandAssignmentNodes; + return true; + }; + + var order = userData as Tuple; + var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance * 2, + GetCircumferencePointCount(extraOptionCharacters.Count), + GetFirstNodeAngle(extraOptionCharacters.Count)); + for (int i = 0; i < extraOptionCharacters.Count; i++) + { + CreateAssignmentNode(order, extraOptionCharacters[i], offsets[i].ToPoint(), extraOption: true); + } + return true; + } + + private void CreateAssignmentNode(Tuple order, Character character, Point offset, bool extraOption = false) + { + // Button + var node = new GUIButton( + new RectTransform(nodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center) + { + AbsoluteOffset = offset + }, + style: null) + { + OnClicked = (button, userData) => + { + SetCharacterOrder(character, order.Item1, order.Item2, Character.Controlled); + DisableCommandUI(); + return true; + } + }; + // Character icon + new GUICustomComponent( + new RectTransform(Vector2.One, node.RectTransform), + (spriteBatch, _) => + { + character.Info.DrawIcon(spriteBatch, node.Center, node.Rect.Size.ToVector2() * 0.75f); + }); + // Smaller container + new GUIImage( + new RectTransform(new Vector2(1.2f), node.RectTransform, anchor: Anchor.Center), + Order.NodeContainer, + scaleToFit: true) + { + Color = character.Info.Job.Prefab.UIColor * nodeColorMultiplier, + HoverColor = character.Info.Job.Prefab.UIColor, + PressedColor = character.Info.Job.Prefab.UIColor, + SelectedColor = character.Info.Job.Prefab.UIColor, + UserData = "container" + }; + // Bigger container + new GUIImage( + new RectTransform(new Vector2(1.4f), node.RectTransform, anchor: Anchor.Center), + Order.NodeContainer, + scaleToFit: true) + { + Color = character.Info.Job.Prefab.UIColor * nodeColorMultiplier, + HoverColor = character.Info.Job.Prefab.UIColor, + PressedColor = character.Info.Job.Prefab.UIColor, + SelectedColor = character.Info.Job.Prefab.UIColor, + UserData = "container", + ToolTip = character.Info.DisplayName + " (" + character.Info.Job.Name + ")" + }; + (extraOption ? extraOptionNodes : optionNodes).Add(node); + } + + private void CreateNodeIcon(RectTransform parent, Sprite sprite, Color iconColor, Color containerColor, string tooltip = null, bool createContainer = true) + { + if (createContainer) + { + // Container + new GUIImage( + new RectTransform(new Vector2(1.2f), parent, anchor: Anchor.Center), + Order.NodeContainer, + scaleToFit: true) + { + Color = containerColor * nodeColorMultiplier, + HoverColor = containerColor, + PressedColor = containerColor, + SelectedColor = containerColor, + UserData = "container" + }; + } + // Icon + new GUIImage( + new RectTransform(Vector2.One, parent), + sprite, + scaleToFit: true) + { + Color = iconColor * nodeColorMultiplier, + HoverColor = iconColor, + PressedColor = iconColor, + SelectedColor = iconColor, + ToolTip = tooltip, + UserData = "icon" + }; + } + + private int GetCircumferencePointCount(int nodes) + { + return nodes % 2 > 0 ? nodes : nodes + 1; + } + + private float GetFirstNodeAngle(int nodeCount) + { + var bearing = 90.0f; + if (returnNode != null) + { + bearing = GetBearing( + centerNode.RectTransform.AbsoluteOffset.ToVector2(), + returnNode.RectTransform.AbsoluteOffset.ToVector2()); + } + else if (shortcutCenterNode != null) + { + bearing = GetBearing( + centerNode.RectTransform.AbsoluteOffset.ToVector2(), + shortcutCenterNode.RectTransform.AbsoluteOffset.ToVector2()); + } + return nodeCount % 2 > 0 ? + MathHelper.ToRadians(bearing + 360.0f / nodeCount / 2) : + MathHelper.ToRadians(bearing + 360.0f / (nodeCount + 1)); + } + + private float GetBearing(Vector2 startPoint, Vector2 endPoint, bool flipY = false, bool flipX = false) + { + var radians = Math.Atan2( + !flipY ? endPoint.Y - startPoint.Y : startPoint.Y - endPoint.Y, + !flipX ? endPoint.X - startPoint.X : startPoint.X - endPoint.X); + var degrees = MathHelper.ToDegrees((float)radians); + return (degrees < 0) ? (degrees + 360) : degrees; + } + + #region Crew Member Assignment Logic + + private Character GetBestCharacterForOrder(Order order) + { + return characters.FindAll(c => c != Character.Controlled) + .OrderByDescending(c => c.CurrentOrder == null || c.CurrentOrder == dismissedOrder) + .ThenByDescending(c => order.HasAppropriateJob(c)) + .FirstOrDefault(); + } + + private List GetCharactersSortedForOrder(Order order) + { + if (order.Identifier == "follow") + { + return characters.FindAll(c => c != Character.Controlled) + .OrderBy(c => c.CurrentOrder == null || c.CurrentOrder == dismissedOrder) + .ThenBy(c => order.HasAppropriateJob(c)) + .ToList(); + } + else + { + return characters.OrderBy(c => c.CurrentOrder == null || c.CurrentOrder == dismissedOrder) + .ThenBy(c => order.HasAppropriateJob(c)) + .ToList(); + } + } + + #endregion + + #endregion /// /// Creates a listbox that includes all the characters in the crew, can be used externally (round info menus etc) @@ -1338,31 +2066,30 @@ namespace Barotrauma /// protected bool SelectCrewCharacter(Character character, GUIComponent crewList) { - if (character == null) return false; + if (character == null) { return false; } GUIComponent crewFrame = (GUIComponent)crewList.UserData; - GUIComponent existingPreview = crewFrame.FindChild("SelectedCharacter"); - if (existingPreview != null) crewFrame.RemoveChild(existingPreview); + if (existingPreview != null) { crewFrame.RemoveChild(existingPreview); } - var previewPlayer = new GUIFrame(new RectTransform(new Vector2(0.45f, 0.9f), crewFrame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.05f, 0.0f) }, style: "InnerFrame") + var previewPlayer = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.7f), crewFrame.RectTransform, Anchor.TopRight), style: null) { UserData = "SelectedCharacter" }; character.Info.CreateInfoFrame(previewPlayer); - if (GameMain.NetworkMember != null) GameMain.Client.SelectCrewCharacter(character, previewPlayer); + if (GameMain.NetworkMember != null) { GameMain.Client.SelectCrewCharacter(character, previewPlayer); } return true; } -#region Reports + #region Reports /// /// Enables/disables report buttons when needed /// - public void UpdateReports(float deltaTime) + public void UpdateReports() { bool canIssueOrders = false; if (Character.Controlled?.CurrentHull?.Submarine != null && Character.Controlled.SpeechImpediment < 100.0f) @@ -1373,14 +2100,16 @@ namespace Barotrauma if (canIssueOrders) { - reportButtonFrame.Visible = true; + ReportButtonFrame.Visible = true; var reportButtonParent = ChatBox ?? GameMain.Client?.ChatBox; if (reportButtonParent == null) { return; } - reportButtonFrame.RectTransform.AbsoluteOffset = new Point( + /*reportButtonFrame.RectTransform.AbsoluteOffset = new Point( Math.Min(reportButtonParent.GUIFrame.Rect.X, reportButtonParent.ToggleButton.Rect.X) - reportButtonFrame.Rect.Width - (int)(10 * GUI.Scale), - reportButtonParent.GUIFrame.Rect.Y); + reportButtonParent.GUIFrame.Rect.Y);*/ + + ReportButtonFrame.RectTransform.AbsoluteOffset = new Point(reportButtonParent.GUIFrame.Rect.Right + (int)(10 * GUI.Scale), reportButtonParent.GUIFrame.Rect.Y); bool hasFires = Character.Controlled.CurrentHull.FireSources.Count > 0; ToggleReportButton("reportfire", hasFires); @@ -1391,7 +2120,7 @@ namespace Barotrauma bool hasIntruders = Character.CharacterList.Any(c => c.CurrentHull == Character.Controlled.CurrentHull && AIObjectiveFightIntruders.IsValidTarget(c, Character.Controlled)); ToggleReportButton("reportintruders", hasIntruders); - foreach (GUIComponent reportButton in reportButtonFrame.Children) + foreach (GUIComponent reportButton in ReportButtonFrame.Children) { var highlight = reportButton.GetChildByUserData("highlighted"); if (highlight.Visible) @@ -1402,34 +2131,25 @@ namespace Barotrauma } else { - reportButtonFrame.Visible = false; + ReportButtonFrame.Visible = false; } } - - /// - /// Should report buttons be visible on the screen atm? - /// - private bool ReportButtonsVisible() - { - return CharacterHealth.OpenHealthWindow == null; - } private void ToggleReportButton(string orderIdentifier, bool enabled) { Order order = Order.GetPrefab(orderIdentifier); - - var reportButton = reportButtonFrame.GetChildByUserData(order); + var reportButton = ReportButtonFrame.GetChildByUserData(order); if (reportButton != null) { reportButton.GetChildByUserData("highlighted").Visible = enabled; } } -#endregion + #endregion public void InitSinglePlayerRound() { - characterListBox.ClearChildren(); + activeCrew.ClearChildren(); characters.Clear(); WayPoint[] waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub); @@ -1456,8 +2176,6 @@ namespace Barotrauma } } - if (characters.Any()) characterListBox.Select(0); - conversationTimer = Rand.Range(5.0f, 10.0f); } @@ -1467,14 +2185,14 @@ namespace Barotrauma characterInfos.RemoveAll(c => c.Character == null || c.Character.Removed || c.CauseOfDeath != null); characters.Clear(); - characterListBox.ClearChildren(); + activeCrew.ClearChildren(); } public void Reset() { characters.Clear(); characterInfos.Clear(); - characterListBox.ClearChildren(); + activeCrew.ClearChildren(); } public void Save(XElement parentElement) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs index af9151d05..a2347cb24 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -35,8 +35,8 @@ namespace Barotrauma CanBeFocused = false }; - var newCampaignContainer = new GUIFrame(new RectTransform(Vector2.One, campaignContainer.RectTransform, Anchor.BottomLeft), style: null); - var loadCampaignContainer = new GUIFrame(new RectTransform(Vector2.One, campaignContainer.RectTransform, Anchor.BottomLeft), style: null); + var newCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null); + var loadCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null); var campaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer, null, saveFiles); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs index 5017a5598..711b190ac 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs @@ -156,13 +156,14 @@ namespace Barotrauma.Tutorials do { yield return null; } while (!captain_medicObjectiveSensor.MotionDetected); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(captain_medic.Info.DisplayName, TextManager.Get("Captain.Radio.Medic"), ChatMessageType.Radio, null); yield return new WaitForSeconds(2f, false); - GameMain.GameSession.CrewManager.ToggleCrewAreaOpen = true; + GameMain.GameSession.CrewManager.ToggleCrewListOpen = true; GameMain.GameSession.CrewManager.AddCharacter(captain_medic); - TriggerTutorialSegment(0); + TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Command)); do { yield return null; - GameMain.GameSession.CrewManager.HighlightOrderButton(captain_medic, "follow", highlightColor, new Vector2(5, 5)); + // TODO: Rework order highlighting for new command UI + // GameMain.GameSession.CrewManager.HighlightOrderButton(captain_medic, "follow", highlightColor, new Vector2(5, 5)); } while (!HasOrder(captain_medic, "follow")); SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true); @@ -172,34 +173,37 @@ namespace Barotrauma.Tutorials do { yield return null; } while (!captain_enteredSubmarineSensor.MotionDetected); yield return new WaitForSeconds(3f, false); captain_mechanic.AIController.Enabled = captain_security.AIController.Enabled = captain_engineer.AIController.Enabled = true; - TriggerTutorialSegment(1); + TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Command)); GameMain.GameSession.CrewManager.AddCharacter(captain_mechanic); do { yield return null; - GameMain.GameSession.CrewManager.HighlightOrderButton(captain_mechanic, "repairsystems", highlightColor, new Vector2(5, 5)); + // TODO: Rework order highlighting for new command UI + // GameMain.GameSession.CrewManager.HighlightOrderButton(captain_mechanic, "repairsystems", highlightColor, new Vector2(5, 5)); //HighlightOrderOption("jobspecific"); } while (!HasOrder(captain_mechanic, "repairsystems")); RemoveCompletedObjective(segments[1]); yield return new WaitForSeconds(2f, false); - TriggerTutorialSegment(2); + TriggerTutorialSegment(2, GameMain.Config.KeyBindText(InputType.Command)); GameMain.GameSession.CrewManager.AddCharacter(captain_security); do { yield return null; - GameMain.GameSession.CrewManager.HighlightOrderButton(captain_security, "operateweapons", highlightColor, new Vector2(5, 5)); + // TODO: Rework order highlighting for new command UI + // GameMain.GameSession.CrewManager.HighlightOrderButton(captain_security, "operateweapons", highlightColor, new Vector2(5, 5)); HighlightOrderOption("fireatwill"); } while (!HasOrder(captain_security, "operateweapons", "fireatwill")); RemoveCompletedObjective(segments[2]); yield return new WaitForSeconds(4f, false); - TriggerTutorialSegment(3); + TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command)); GameMain.GameSession.CrewManager.AddCharacter(captain_engineer); do { yield return null; - GameMain.GameSession.CrewManager.HighlightOrderButton(captain_engineer, "operatereactor", highlightColor, new Vector2(5, 5)); + // TODO: Rework order highlighting for new command UI + // GameMain.GameSession.CrewManager.HighlightOrderButton(captain_engineer, "operatereactor", highlightColor, new Vector2(5, 5)); HighlightOrderOption("powerup"); } while (!HasOrder(captain_engineer, "operatereactor", "powerup")); @@ -225,10 +229,9 @@ namespace Barotrauma.Tutorials { if (IsSelectedItem(captain_navConsole.Item)) { - if (captain_sonar.ActiveTickBox.Box.FlashTimer <= 0) + if (captain_sonar.SonarModeSwitch.Frame.FlashTimer <= 0) { - captain_sonar.ActiveTickBox.Box.Flash(highlightColor, 1.5f, false, new Vector2(2.5f, 2.5f)); - //captain_sonar.ActiveTickBox.Box.Pulsate(Vector2.One, Vector2.One * 1.5f, 1.5f); + captain_sonar.SonarModeSwitch.Frame.Flash(highlightColor, 1.5f, false, false, new Vector2(2.5f, 2.5f)); } } yield return null; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs index aa217fea3..10083e314 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/DoctorTutorial.cs @@ -55,6 +55,22 @@ namespace Barotrauma.Tutorials radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker"); doctor = Character.Controlled; + var bandages = FindOrGiveItem(doctor, "antibleeding1"); + bandages.Unequip(doctor); + doctor.Inventory.RemoveItem(bandages); + + var syringegun = FindOrGiveItem(doctor, "syringegun"); + syringegun.Unequip(doctor); + doctor.Inventory.RemoveItem(syringegun); + + var antibiotics = FindOrGiveItem(doctor, "antibiotics"); + antibiotics.Unequip(doctor); + doctor.Inventory.RemoveItem(antibiotics); + + var morphine = FindOrGiveItem(doctor, "antidama1"); + morphine.Unequip(doctor); + doctor.Inventory.RemoveItem(morphine); + doctor_suppliesCabinet = Item.ItemList.Find(i => i.HasTag("doctor_suppliescabinet"))?.GetComponent(); doctor_medBayCabinet = Item.ItemList.Find(i => i.HasTag("doctor_medbaycabinet"))?.GetComponent(); @@ -175,7 +191,7 @@ namespace Barotrauma.Tutorials yield return new WaitForSeconds(2.0f); }*/ - TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect)); // Medical supplies objective + TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Medical supplies objective do { @@ -254,17 +270,18 @@ namespace Barotrauma.Tutorials GameMain.GameSession.CrewManager.AllowCharacterSwitch = false; GameMain.GameSession.CrewManager.AddCharacter(doctor); GameMain.GameSession.CrewManager.AddCharacter(patient1); - GameMain.GameSession.CrewManager.ToggleCrewAreaOpen = true; + GameMain.GameSession.CrewManager.ToggleCrewListOpen = true; patient1.CharacterHealth.UseHealthWindow = false; yield return new WaitForSeconds(3.0f, false); patient1.AIController.Enabled = true; doctor.RemoveActiveObjectiveEntity(patient1); - TriggerTutorialSegment(3); // Get the patient to medbay + TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command)); // Get the patient to medbay while (patient1.CurrentOrder == null || patient1.CurrentOrder.Identifier != "follow") { - GameMain.GameSession.CrewManager.HighlightOrderButton(patient1, "follow", highlightColor, new Vector2(5, 5)); + // TODO: Rework order highlighting for new command UI + // GameMain.GameSession.CrewManager.HighlightOrderButton(patient1, "follow", highlightColor, new Vector2(5, 5)); yield return null; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs index cc1f812f9..fe78d0166 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/EngineerTutorial.cs @@ -127,7 +127,7 @@ namespace Barotrauma.Tutorials engineer_reactor = Item.ItemList.Find(i => i.HasTag("engineer_reactor")).GetComponent(); engineer_reactor.FireDelay = engineer_reactor.MeltdownDelay = float.PositiveInfinity; engineer_reactor.FuelConsumptionRate = 0.0f; - engineer_reactor.OnOffSwitch.BarScroll = 1f; + engineer_reactor.PowerOn = true; reactorOperatedProperly = false; engineer_secondDoor = Item.ItemList.Find(i => i.HasTag("engineer_seconddoor")).GetComponent(); ; @@ -195,7 +195,7 @@ namespace Barotrauma.Tutorials engineer_submarineJunctionBox_2 = Item.ItemList.Find(i => i.HasTag("engineer_submarinejunctionbox_2")); engineer_submarineJunctionBox_3 = Item.ItemList.Find(i => i.HasTag("engineer_submarinejunctionbox_3")); engineer_submarineReactor = Item.ItemList.Find(i => i.HasTag("engineer_submarinereactor")).GetComponent(); - engineer_submarineReactor.OnOffSwitch.BarScrollValue = .25f; + engineer_submarineReactor.PowerOn = true; engineer_submarineReactor.IsActive = engineer_submarineReactor.AutoTemp = false; engineer_submarineJunctionBox_1.Indestructible = false; @@ -235,7 +235,7 @@ namespace Barotrauma.Tutorials do { yield return null; } while (!engineer_equipmentObjectiveSensor.MotionDetected); GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Equipment"), ChatMessageType.Radio, null); yield return new WaitForSeconds(0.5f, false); - TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect)); // Retrieve equipment + TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Retrieve equipment bool firstSlotRemoved = false; bool secondSlotRemoved = false; bool thirdSlotRemoved = false; @@ -289,19 +289,19 @@ namespace Barotrauma.Tutorials { if (IsSelectedItem(engineer_reactor.Item)) { - engineer_reactor.AutoTempSlider.BarScrollValue = 1.0f; - if (engineer_reactor.OnOffSwitch.FlashTimer <= 0) + engineer_reactor.AutoTemp = false; + if (engineer_reactor.PowerButton.FlashTimer <= 0) { - engineer_reactor.OnOffSwitch.Flash(highlightColor, 1.5f, false); + engineer_reactor.PowerButton.Flash(highlightColor, 1.5f, false); } } yield return null; - } while (engineer_reactor.OnOffSwitch.BarScroll > 0.45f); + } while (!engineer_reactor.PowerOn); do { if (IsSelectedItem(engineer_reactor.Item) && engineer_reactor.Item.OwnInventory.slots != null) { - engineer_reactor.AutoTempSlider.BarScrollValue = 1.0f; + engineer_reactor.AutoTemp = false; HighlightInventorySlot(engineer.Inventory, "fuelrod", highlightColor, 0.5f, 0.5f, 0f); for (int i = 0; i < engineer_reactor.Item.OwnInventory.slots.Length; i++) @@ -316,7 +316,7 @@ namespace Barotrauma.Tutorials { if (IsSelectedItem(engineer_reactor.Item)) { - engineer_reactor.AutoTempSlider.BarScrollValue = 1.0f; + engineer_reactor.AutoTemp = false; if (engineer_reactor.FissionRateScrollBar.FlashTimer <= 0) { engineer_reactor.FissionRateScrollBar.Flash(highlightColor, 1.5f); @@ -335,9 +335,9 @@ namespace Barotrauma.Tutorials { if (IsSelectedItem(engineer_reactor.Item)) { - if (engineer_reactor.AutoTempSlider.FlashTimer <= 0) + if (engineer_reactor.AutoTempSwitch.FlashTimer <= 0) { - engineer_reactor.AutoTempSlider.Flash(highlightColor, 1.5f, false, new Vector2(10, 10)); + engineer_reactor.AutoTempSwitch.Flash(highlightColor, 1.5f, false, false, new Vector2(10, 10)); } } yield return null; @@ -348,7 +348,7 @@ namespace Barotrauma.Tutorials { yield return new WaitForSeconds(0.1f, false); wait -= 0.1f; - engineer_reactor.AutoTempSlider.BarScrollValue = 0.0f; + engineer_reactor.AutoTemp = true; } while (wait > 0.0f); engineer.SelectedConstruction = null; engineer_reactor.CanBeSelected = false; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs index 0579bcafd..8947b90f7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs @@ -254,7 +254,7 @@ namespace Barotrauma.Tutorials yield return new WaitForSeconds(0.0f, false); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Equipment"), ChatMessageType.Radio, null); do { yield return null; } while (!mechanic_equipmentObjectiveSensor.MotionDetected); - TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect)); // Equipment & inventory objective + TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Equipment & inventory objective SetHighlight(mechanic_equipmentCabinet.Item, true); bool firstSlotRemoved = false; bool secondSlotRemoved = false; @@ -296,7 +296,7 @@ namespace Barotrauma.Tutorials // Room 3 do { yield return null; } while (!mechanic_weldingObjectiveSensor.MotionDetected); - TriggerTutorialSegment(2, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot)); // Welding objective + TriggerTutorialSegment(2, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Welding objective do { if (!mechanic.HasEquippedItem("divingmask")) @@ -323,9 +323,9 @@ namespace Barotrauma.Tutorials yield return null; if (IsSelectedItem(mechanic_workingPump.Item)) { - if (mechanic_workingPump.IsActiveSlider.FlashTimer <= 0) + if (mechanic_workingPump.PowerButton.FlashTimer <= 0) { - mechanic_workingPump.IsActiveSlider.Flash(uiHighlightColor, 1.5f, true); + mechanic_workingPump.PowerButton.Flash(uiHighlightColor, 1.5f, true); } } } while (mechanic_workingPump.FlowPercentage >= 0 || !mechanic_workingPump.IsActive); // Highlight until draining @@ -554,9 +554,9 @@ namespace Barotrauma.Tutorials { if (IsSelectedItem(mechanic_brokenPump.Item)) { - if (mechanic_brokenPump.IsActiveSlider.FlashTimer <= 0) + if (mechanic_brokenPump.PowerButton.FlashTimer <= 0) { - mechanic_brokenPump.IsActiveSlider.Flash(uiHighlightColor, 1.5f, true); + mechanic_brokenPump.PowerButton.Flash(uiHighlightColor, 1.5f, true); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs index 6eb6a291f..7d8d7d1ef 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/OfficerTutorial.cs @@ -252,12 +252,12 @@ namespace Barotrauma.Tutorials { HighlightInventorySlot(officer.Inventory, "bodyarmor", highlightColor, .5f, .5f, 0f); } - if (!officer.HasEquippedItem("ballistichelmet")) + if (!officer.HasEquippedItem("ballistichelmet1")) { - HighlightInventorySlot(officer.Inventory, "ballistichelmet", highlightColor, .5f, .5f, 0f); + HighlightInventorySlot(officer.Inventory, "ballistichelmet1", highlightColor, .5f, .5f, 0f); } yield return new WaitForSeconds(1f, false); - } while (!officer.HasEquippedItem("stunbaton") || !officer.HasEquippedItem("bodyarmor") || !officer.HasEquippedItem("ballistichelmet")); + } while (!officer.HasEquippedItem("stunbaton") || !officer.HasEquippedItem("bodyarmor") || !officer.HasEquippedItem("ballistichelmet1")); RemoveCompletedObjective(segments[1]); SetDoorAccess(officer_firstDoor, officer_firstDoorLight, true); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs index 9a8ac64fc..40b0294db 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/ScenarioTutorial.cs @@ -31,8 +31,8 @@ namespace Barotrauma.Tutorials protected Color highlightColor = Color.OrangeRed; protected Color uiHighlightColor = new Color(150, 50, 0); protected Color buttonHighlightColor = new Color(255, 100, 0); - protected Color inaccessibleColor = Color.Red; - protected Color accessibleColor = Color.Green; + protected Color inaccessibleColor = GUI.Style.Red; + protected Color accessibleColor = GUI.Style.Green; public ScenarioTutorial(XElement element) : base(element) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs index 829152225..bbd67e90e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/Tutorial.cs @@ -372,9 +372,10 @@ namespace Barotrauma.Tutorials private void CreateObjectiveGUI(TutorialSegment segment, int index, TutorialContentTypes type) { - Point replayButtonSize = new Point((int)(GUI.ObjectiveNameFont.MeasureString(segment.Objective).X), (int)(GUI.ObjectiveNameFont.MeasureString(segment.Objective).Y * 1.45f)); + string objectiveText = TextManager.ParseInputTypes(segment.Objective); + Point replayButtonSize = new Point((int)(GUI.LargeFont.MeasureString(objectiveText).X), (int)(GUI.LargeFont.MeasureString(objectiveText).Y * 1.45f)); - segment.ReplayButton = new GUIButton(new RectTransform(replayButtonSize, objectiveFrame.RectTransform, Anchor.TopRight, Pivot.TopRight) { AbsoluteOffset = new Point(0, (replayButtonSize.Y + (int)(20f * GUI.Scale)) * index) }, style: null); + segment.ReplayButton = new GUIButton(new RectTransform(replayButtonSize, objectiveFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(0, (replayButtonSize.Y + (int)(20f * GUI.Scale)) * index) }, style: null); segment.ReplayButton.OnClicked += (GUIButton btn, object userdata) => { if (type == TutorialContentTypes.Video) @@ -389,13 +390,15 @@ namespace Barotrauma.Tutorials }; string objectiveTitleText = TextManager.ParseInputTypes(objectiveTranslated); - int yOffset = (int)((GUI.ObjectiveNameFont.MeasureString(objectiveTitleText).Y / 2f + 5)); - segment.LinkedTitle = new GUITextBlock(new RectTransform(new Point((int)GUI.ObjectiveTitleFont.MeasureString(objectiveTitleText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterRight, Pivot.BottomRight) /*{ AbsoluteOffset = new Point((int)(-10 * GUI.Scale), 0) }*/, - objectiveTitleText, textColor: Color.White, font: GUI.ObjectiveTitleFont, textAlignment: Alignment.CenterRight); + int yOffset = (int)((GUI.SubHeadingFont.MeasureString(objectiveTitleText).Y + 5)); + segment.LinkedTitle = new GUITextBlock(new RectTransform(new Point((int)GUI.SubHeadingFont.MeasureString(objectiveTitleText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.BottomLeft) /*{ AbsoluteOffset = new Point((int)(-10 * GUI.Scale), 0) }*/, + objectiveTitleText, textColor: Color.White, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft) + { + ForceUpperCase = true + }; - string objectiveText = TextManager.ParseInputTypes(segment.Objective); - segment.LinkedText = new GUITextBlock(new RectTransform(new Point((int)GUI.ObjectiveNameFont.MeasureString(objectiveText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterRight, Pivot.TopRight) /*{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), 0) }*/, - objectiveText, textColor: new Color(4, 180, 108), font: GUI.ObjectiveNameFont, textAlignment: Alignment.CenterRight); + segment.LinkedText = new GUITextBlock(new RectTransform(new Point((int)GUI.LargeFont.MeasureString(objectiveText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.TopLeft) /*{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), 0) }*/, + objectiveText, textColor: new Color(4, 180, 108), font: GUI.LargeFont, textAlignment: Alignment.CenterLeft); segment.LinkedTitle.Color = segment.LinkedTitle.HoverColor = segment.LinkedTitle.PressedColor = segment.LinkedTitle.SelectedColor = Color.Transparent; segment.LinkedText.Color = segment.LinkedText.HoverColor = segment.LinkedText.PressedColor = segment.LinkedText.SelectedColor = Color.Transparent; @@ -449,19 +452,19 @@ namespace Barotrauma.Tutorials RectTransform rectTA; if (objectiveTextWidth > objectiveTitleWidth) { - rectTA = new RectTransform(new Point(checkMarkWidth, checkMarkHeight), segment.ReplayButton.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft); - rectTA.AbsoluteOffset = new Point(-rectTA.Rect.Width - (int)(10 * GUI.Scale), 0); + rectTA = new RectTransform(new Point(checkMarkWidth, checkMarkHeight), segment.ReplayButton.RectTransform, Anchor.BottomRight, Pivot.BottomRight); + rectTA.AbsoluteOffset = new Point(-rectTA.Rect.Width - (int)(25 * GUI.Scale), 0); } else { - rectTA = new RectTransform(new Point(checkMarkWidth, checkMarkHeight), segment.ReplayButton.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft); - rectTA.AbsoluteOffset = new Point(-rectTA.Rect.Width - (int)(10 * GUI.Scale) - (objectiveTitleWidth - objectiveTextWidth), 0); + rectTA = new RectTransform(new Point(checkMarkWidth, checkMarkHeight), segment.ReplayButton.RectTransform, Anchor.BottomRight, Pivot.BottomRight); + rectTA.AbsoluteOffset = new Point(-rectTA.Rect.Width - (int)(25 * GUI.Scale) - (objectiveTitleWidth - objectiveTextWidth), 0); } GUIImage checkmark = new GUIImage(rectTA, "CheckMark"); checkmark.Color = checkmark.SelectedColor = checkmark.HoverColor = checkmark.PressedColor = color; - RectTransform rectTB = new RectTransform(new Vector2(1.1f, .8f), segment.LinkedText.RectTransform, Anchor.Center, Pivot.Center); + RectTransform rectTB = new RectTransform(new Vector2(1.0f, .8f), segment.LinkedText.RectTransform, Anchor.Center, Pivot.Center); GUIImage stroke = new GUIImage(rectTB, "Stroke"); stroke.Color = stroke.SelectedColor = stroke.HoverColor = stroke.PressedColor = color; @@ -493,14 +496,6 @@ namespace Barotrauma.Tutorials protected GUIComponent CreateInfoFrame(string title, string text, int width = 300, int height = 80, string anchorStr = "", bool hasButton = false, Action callback = null, Action showVideo = null) { if (hasButton) height += 60; - - string wrappedText = ToolBox.WrapText(text, width, GUI.Font); - - height += (int)(GUI.Font.MeasureString(wrappedText).Y + 50); - if (title.Length > 0) - { - height += 35; - } Anchor anchor = Anchor.TopRight; @@ -509,12 +504,23 @@ namespace Barotrauma.Tutorials Enum.TryParse(anchorStr, out anchor); } - var background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), "InnerFrame", new Color(0, 0, 0, 1f)); + width = (int)(width * GUI.Scale); + height = (int)(height * GUI.Scale); - var infoBlock = new GUIFrame(new RectTransform(new Point((int)(width * GUI.Scale), (int)(height * GUI.Scale)), background.RectTransform, anchor) { AbsoluteOffset = new Point(20) }); - infoBlock.Flash(Color.Green); + string wrappedText = ToolBox.WrapText(text, width, GUI.Font); + height += (int)GUI.Font.MeasureString(wrappedText).Y; - var infoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), infoBlock.RectTransform, Anchor.Center)) + if (title.Length > 0) + { + height += (int)GUI.Font.MeasureString(title).Y + (int)(150 * GUI.Scale); + } + + var background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), style: null, Color.Black * 0.5f); + + var infoBlock = new GUIFrame(new RectTransform(new Point(width, height), background.RectTransform, anchor)); + infoBlock.Flash(GUI.Style.Green); + + var infoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), infoBlock.RectTransform, Anchor.Center)) { Stretch = true, AbsoluteSpacing = 5 @@ -523,7 +529,7 @@ namespace Barotrauma.Tutorials if (title.Length > 0) { var titleBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), - title, font: GUI.VideoTitleFont, textAlignment: Alignment.Center, textColor: new Color(253, 174, 0)); + title, font: GUI.LargeFont, textAlignment: Alignment.Center, textColor: new Color(253, 174, 0)); titleBlock.RectTransform.IsFixedSize = true; } @@ -543,15 +549,15 @@ namespace Barotrauma.Tutorials if (hasButton) { - var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), infoContent.RectTransform) { MinSize = new Point(0, 30), MaxSize = new Point((int) infoContent.Rect.X, 60) }, isHorizontal: true) + var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), infoContent.RectTransform), isHorizontal: true) { - Stretch = true, RelativeSpacing = 0.1f }; buttonContainer.RectTransform.IsFixedSize = true; if (showVideo != null) { + buttonContainer.Stretch = true; var videoButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonContainer.RectTransform), TextManager.Get("Video"), style: "GUIButtonLarge") { @@ -562,8 +568,13 @@ namespace Barotrauma.Tutorials } }; } + else + { + buttonContainer.Stretch = false; + buttonContainer.ChildAnchor = Anchor.Center; + } - var okButton = new GUIButton(new RectTransform(new Vector2(0.6f, 1.0f), buttonContainer.RectTransform), + var okButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonContainer.RectTransform), TextManager.Get("OK"), style: "GUIButtonLarge") { OnClicked = CloseInfoFrame diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs index e6da35c43..aab3afeef 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs @@ -1,21 +1,19 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using System.Collections.Generic; namespace Barotrauma { partial class GameSession { private InfoFrameTab selectedTab; - private GUIButton infoFrame; + private GUIFrame infoFrame; + + private readonly List tabButtons = new List(); private GUIFrame infoFrameContent; + public RoundSummary RoundSummary { get; private set; } - private RoundSummary roundSummary; - public RoundSummary RoundSummary - { - get { return roundSummary; } - } - private bool ToggleInfoFrame() { if (GameMain.NetworkMember != null && GameMain.NetLobbyScreen != null) @@ -40,7 +38,9 @@ namespace Barotrauma { int width = 600, height = 400; - infoFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker"); + tabButtons.Clear(); + + infoFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker"); var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.35f), infoFrame.RectTransform, Anchor.Center) { MinSize = new Point(width, height), RelativeOffset = new Vector2(0.0f, 0.033f) }); @@ -56,12 +56,14 @@ namespace Barotrauma UserData = InfoFrameTab.Crew, OnClicked = SelectInfoFrameTab }; + tabButtons.Add(crewButton); var missionButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform), TextManager.Get("Mission"), style: "GUITabButton") { UserData = InfoFrameTab.Mission, OnClicked = SelectInfoFrameTab }; + tabButtons.Add(missionButton); if (GameMain.NetworkMember != null) { @@ -70,6 +72,7 @@ namespace Barotrauma UserData = InfoFrameTab.MyCharacter, OnClicked = SelectInfoFrameTab }; + tabButtons.Add(myCharacterButton); } /*TODO: fix @@ -89,6 +92,7 @@ namespace Barotrauma selectedTab = (InfoFrameTab)userData; CreateInfoFrame(); + tabButtons.ForEach(tb => tb.Selected = (InfoFrameTab)tb.UserData == selectedTab); switch (selectedTab) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSettings.cs index 8e060da8e..fdc9bef8c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSettings.cs @@ -19,6 +19,9 @@ namespace Barotrauma Graphics, Audio, Controls, +#if DEBUG + Debug +#endif } private readonly Point MinSupportedResolution = new Point(1024, 540); @@ -57,6 +60,7 @@ namespace Barotrauma keyMapping[(int)InputType.CrewOrders] = new KeyOrMouse(Keys.C); keyMapping[(int)InputType.Voice] = new KeyOrMouse(Keys.V); + keyMapping[(int)InputType.Command] = new KeyOrMouse(MouseButton.MiddleMouse); if (Language == "French") { @@ -64,6 +68,7 @@ namespace Barotrauma keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S); keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.Q); keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D); + keyMapping[(int)InputType.ToggleInventory] = new KeyOrMouse(Keys.A); keyMapping[(int)InputType.SelectNextCharacter] = new KeyOrMouse(Keys.X); keyMapping[(int)InputType.SelectPreviousCharacter] = new KeyOrMouse(Keys.W); @@ -74,6 +79,7 @@ namespace Barotrauma keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S); keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A); keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D); + keyMapping[(int)InputType.ToggleInventory] = new KeyOrMouse(Keys.Q); keyMapping[(int)InputType.SelectNextCharacter] = new KeyOrMouse(Keys.Z); keyMapping[(int)InputType.SelectPreviousCharacter] = new KeyOrMouse(Keys.X); @@ -227,7 +233,7 @@ namespace Barotrauma } label = text.Text.Substring(0, index); } - text.Text = label + " " + barScroll * 100 + "%"; + text.Text = label + " " + (int)(barScroll * 100) + "%"; return true; } @@ -256,26 +262,35 @@ namespace Barotrauma settingsHolder = settingsFrameContent.RectTransform; } - Vector2 tickBoxScale = Vector2.One * 0.05f; + Vector2 textBlockScale = new Vector2(1.0f, 0.05f); + Vector2 tickBoxScale = new Vector2(1.0f, 0.05f); - var settingsFramePadding = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), settingsHolder, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) }) { RelativeSpacing = 0.01f, IsHorizontal = true }; + var settingsFramePadding = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.93f), settingsHolder, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) }, style: null); + var buttonArea = new GUIFrame(new RectTransform(new Vector2(0.6f, 0.06f), settingsFramePadding.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.07f, 0.0f) }, style: null) + { + IgnoreLayoutGroups = true + }; /// General tab -------------------------------------------------------------- - var leftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 1.0f), settingsFramePadding.RectTransform, Anchor.TopLeft)); + var leftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 0.93f), settingsFramePadding.RectTransform)) + { + Stretch = true, + RelativeSpacing = 0.01f + }; var settingsTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform), TextManager.Get("Settings"), textAlignment: Alignment.TopLeft, font: GUI.LargeFont) { ForceUpperCase = true }; - var generalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), leftPanel.RectTransform, Anchor.TopLeft)); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform), TextManager.Get("ContentPackages"), font: GUI.SubHeadingFont); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), generalLayoutGroup.RectTransform), TextManager.Get("ContentPackages")); + var corePackageDropdown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform)) + { + ButtonEnabled = ContentPackage.List.Count(cp => cp.CorePackage) > 1 + }; - var corePackageDropdown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), generalLayoutGroup.RectTransform)); - corePackageDropdown.ButtonEnabled = ContentPackage.List.Count(cp => cp.CorePackage) > 1; - - contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.70f), generalLayoutGroup.RectTransform)) + contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.70f), leftPanel.RectTransform)) { OnSelected = (gc, obj) => false, ScrollBarVisible = true @@ -292,7 +307,7 @@ namespace Barotrauma if (!contentPackage.IsCompatible()) { frame.UserData = null; - text.TextColor = Color.Red * 0.6f; + text.TextColor = GUI.Style.Red * 0.6f; frame.ToolTip = text.ToolTip = TextManager.GetWithVariables(contentPackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage", new string[3] { "[packagename]", "[packageversion]", "[gameversion]" }, new string[3] { contentPackage.Name, contentPackage.GameVersion.ToString(), GameMain.Version.ToString() }); @@ -300,7 +315,7 @@ namespace Barotrauma else if (contentPackage.CorePackage && !contentPackage.ContainsRequiredCorePackageFiles(out List missingContentTypes)) { frame.UserData = null; - text.TextColor = Color.Red * 0.6f; + text.TextColor = GUI.Style.Red * 0.6f; frame.ToolTip = text.ToolTip = TextManager.GetWithVariables("ContentPackageMissingCoreFiles", new string[2] { "[packagename]", "[missingfiletypes]" }, new string[2] { contentPackage.Name, string.Join(", ", missingContentTypes) }, new bool[2] { false, true }); @@ -330,7 +345,19 @@ namespace Barotrauma { UserData = contentPackage }; - var tickBox = new GUITickBox(new RectTransform(Vector2.One, frame.RectTransform, scaleBasis: ScaleBasis.BothHeight), contentPackage.Name, + + var frameContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + + var dragIndicator = new GUIButton(new RectTransform(new Vector2(0.1f, 0.5f), frameContent.RectTransform, scaleBasis: ScaleBasis.BothHeight), + style: "GUIDragIndicator") + { + CanBeFocused = false + }; + var tickBox = new GUITickBox(new RectTransform(Vector2.One, frameContent.RectTransform), contentPackage.Name, style: "GUITickBox") { UserData = contentPackage, @@ -338,10 +365,11 @@ namespace Barotrauma OnSelected = SelectContentPackage, Enabled = CanHotswapPackages(false) }; + frame.RectTransform.MinSize = new Point(0, (int)(tickBox.RectTransform.MinSize.Y / frameContent.RectTransform.RelativeSize.Y)); if (!contentPackage.IsCompatible()) { tickBox.Enabled = false; - tickBox.TextColor = Color.Red * 0.6f; + tickBox.TextColor = GUI.Style.Red * 0.6f; tickBox.ToolTip = tickBox.TextBlock.ToolTip = TextManager.GetWithVariables(contentPackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage", new string[3] { "[packagename]", "[packageversion]", "[gameversion]" }, new string[3] { contentPackage.Name, contentPackage.GameVersion.ToString(), GameMain.Version.ToString() }); @@ -353,15 +381,13 @@ namespace Barotrauma TextManager.GetWithVariable("ContentPackageHasErrors", "[packagename]", contentPackage.Name) + "\n" + string.Join("\n", contentPackage.ErrorMessages); } - - tickBox.TextBlock.CanBeFocused = true; } contentPackageList.CanDragElements = CanHotswapPackages(false); contentPackageList.CanBeFocused = CanHotswapPackages(false); contentPackageList.OnRearranged = OnContentPackagesRearranged; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.045f), generalLayoutGroup.RectTransform), TextManager.Get("Language")); - var languageDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.045f), generalLayoutGroup.RectTransform)); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.045f), leftPanel.RectTransform), TextManager.Get("Language"), font: GUI.SubHeadingFont); + var languageDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.045f), leftPanel.RectTransform)); foreach (string language in TextManager.AvailableLanguages) { languageDD.AddItem(TextManager.GetTranslatedLanguageName(language), language); @@ -396,28 +422,48 @@ namespace Barotrauma return true; }; - var rightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.99f - leftPanel.RectTransform.RelativeSize.X, 0.95f), - settingsFramePadding.RectTransform, Anchor.TopLeft)); + // right panel -------------------------------------- + + var rightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.99f - leftPanel.RectTransform.RelativeSize.X, leftPanel.RectTransform.RelativeSize.Y), + settingsFramePadding.RectTransform, Anchor.TopRight)) + { + Stretch = true + }; var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), rightPanel.RectTransform, Anchor.TopCenter), isHorizontal: true); var paddedFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), rightPanel.RectTransform, Anchor.Center), style: null); - tabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length]; tabButtons = new GUIButton[tabs.Length]; foreach (Tab tab in Enum.GetValues(typeof(Tab))) { - tabs[(int)tab] = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.91f), paddedFrame.RectTransform), style: "InnerFrame") + tabs[(int)tab] = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), paddedFrame.RectTransform), style: "InnerFrame") { UserData = tab }; - tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tabButtonHolder.RectTransform), - TextManager.Get("SettingsTab." + tab.ToString()), style: "GUITabButton") + +#if DEBUG + if (tab != Tab.Debug) { - UserData = tab, - OnClicked = (bt, userdata) => { SelectTab((Tab)userdata); return true; } - }; +#endif + tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tabButtonHolder.RectTransform), + TextManager.Get("SettingsTab." + tab.ToString()), style: "GUITabButton") + { + UserData = tab, + OnClicked = (bt, userdata) => { SelectTab((Tab)userdata); return true; } + }; +#if DEBUG + } + else + { + tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tabButtonHolder.RectTransform), "Debug", style: "GUITabButton") + { + UserData = tab, + OnClicked = (bt, userdata) => { SelectTab((Tab)userdata); return true; } + }; + } +#endif } new GUIButton(new RectTransform(new Vector2(0.05f, 0.75f), tabButtonHolder.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.0f, 0.2f) }, style: "GUIBugButton") @@ -426,7 +472,6 @@ namespace Barotrauma OnClicked = (btn, userdata) => { GameMain.Instance.ShowBugReporter(); return true; } }; - var buttonArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.08f), paddedFrame.RectTransform, Anchor.BottomCenter), style: null); /// Graphics tab -------------------------------------------------------------- @@ -437,7 +482,7 @@ namespace Barotrauma { RelativeOffset = new Vector2(0.025f, 0.02f) }) { RelativeSpacing = 0.01f }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("Resolution")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("Resolution"), font: GUI.SubHeadingFont); var resolutionDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform)) { ButtonEnabled = GameMain.Config.WindowMode != WindowMode.BorderlessWindowed @@ -446,7 +491,7 @@ namespace Barotrauma var supportedDisplayModes = UpdateResolutionDD(resolutionDD); resolutionDD.OnSelected = SelectResolution; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("DisplayMode")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("DisplayMode"), font: GUI.SubHeadingFont); var displayModeDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform)); displayModeDD.AddItem(TextManager.Get("Fullscreen"), WindowMode.Fullscreen); @@ -486,7 +531,7 @@ namespace Barotrauma return true; }; - GUITickBox vsyncTickBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("EnableVSync")) + GUITickBox vsyncTickBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform), TextManager.Get("EnableVSync")) { ToolTip = TextManager.Get("EnableVSyncToolTip"), OnSelected = (GUITickBox box) => @@ -502,19 +547,21 @@ namespace Barotrauma }; - GUITickBox pauseOnFocusLostBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform, scaleBasis: ScaleBasis.BothHeight), - TextManager.Get("PauseOnFocusLost")); - pauseOnFocusLostBox.Selected = PauseOnFocusLost; - pauseOnFocusLostBox.ToolTip = TextManager.Get("PauseOnFocusLostToolTip"); - pauseOnFocusLostBox.OnSelected = (tickBox) => + GUITickBox pauseOnFocusLostBox = new GUITickBox(new RectTransform(tickBoxScale, leftColumn.RectTransform), + TextManager.Get("PauseOnFocusLost")) { - PauseOnFocusLost = tickBox.Selected; - UnsavedSettings = true; - return true; + Selected = PauseOnFocusLost, + ToolTip = TextManager.Get("PauseOnFocusLostToolTip"), + OnSelected = (tickBox) => + { + PauseOnFocusLost = tickBox.Selected; + UnsavedSettings = true; + return true; + } }; - GUITextBlock particleLimitText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("ParticleLimit")); - GUIScrollBar particleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), + GUITextBlock particleLimitText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("ParticleLimit"), font: GUI.SubHeadingFont); + GUIScrollBar particleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), style: "GUISlider", barSize: 0.1f) { UserData = particleLimitText, @@ -529,7 +576,7 @@ namespace Barotrauma }; particleScrollBar.OnMoved(particleScrollBar, particleScrollBar.BarScroll); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LosEffect")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LosEffect"), font: GUI.SubHeadingFont); var losModeDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform)); losModeDD.AddItem(TextManager.Get("LosModeNone"), LosMode.None); losModeDD.AddItem(TextManager.Get("LosModeTransparent"), LosMode.Transparent); @@ -547,12 +594,12 @@ namespace Barotrauma return true; }; - GUITextBlock LightText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LightMapScale")) + GUITextBlock LightText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LightMapScale"), font: GUI.SubHeadingFont) { ToolTip = TextManager.Get("LightMapScaleToolTip") }; GUIScrollBar lightScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), - barSize: 0.1f) + style: "GUISlider", barSize: 0.1f) { UserData = LightText, ToolTip = TextManager.Get("LightMapScaleToolTip"), @@ -567,7 +614,7 @@ namespace Barotrauma }; lightScrollBar.OnMoved(lightScrollBar, lightScrollBar.BarScroll); - /*new GUITickBox(new RectTransform(tickBoxScale, rightColumn.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("SpecularLighting")) + /*new GUITickBox(new RectTransform(tickBoxScale, rightColumn.RectTransform), TextManager.Get("SpecularLighting")) { ToolTip = TextManager.Get("SpecularLightingToolTip"), Selected = SpecularityEnabled, @@ -579,7 +626,7 @@ namespace Barotrauma } };*/ - new GUITickBox(new RectTransform(tickBoxScale, rightColumn.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("ChromaticAberration")) + new GUITickBox(new RectTransform(tickBoxScale, rightColumn.RectTransform), TextManager.Get("ChromaticAberration")) { ToolTip = TextManager.Get("ChromaticAberrationToolTip"), Selected = ChromaticAberrationEnabled, @@ -591,9 +638,9 @@ namespace Barotrauma } }; - GUITextBlock HUDScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("HUDScale")); + GUITextBlock HUDScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("HUDScale"), font: GUI.SubHeadingFont); GUIScrollBar HUDScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), - barSize: 0.1f) + style: "GUISlider", barSize: 0.1f) { UserData = HUDScaleText, BarScroll = (HUDScale - MinHUDScale) / (MaxHUDScale - MinHUDScale), @@ -609,8 +656,9 @@ namespace Barotrauma }; HUDScaleScrollBar.OnMoved(HUDScaleScrollBar, HUDScaleScrollBar.BarScroll); - GUITextBlock inventoryScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("InventoryScale")); - GUIScrollBar inventoryScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), barSize: 0.1f) + GUITextBlock inventoryScaleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("InventoryScale"), font: GUI.SubHeadingFont); + GUIScrollBar inventoryScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), + style: "GUISlider", barSize: 0.1f) { UserData = inventoryScaleText, BarScroll = (InventoryScale - MinInventoryScale) / (MaxInventoryScale - MinInventoryScale), @@ -627,13 +675,15 @@ namespace Barotrauma /// Audio tab ---------------------------------------------------------------- - var audioSliders = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.3f), tabs[(int)Tab.Audio].RectTransform, Anchor.TopCenter) - { RelativeOffset = new Vector2(0.0f, 0.02f) }) - { RelativeSpacing = 0.01f }; - - GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), audioSliders.RectTransform), TextManager.Get("SoundVolume")); - GUIScrollBar soundScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.15f), audioSliders.RectTransform), - barSize: 0.05f) + var audioContent = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 0.97f), tabs[(int)Tab.Audio].RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + { + Stretch = true, + RelativeSpacing = 0.01f + }; + + GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(textBlockScale, audioContent.RectTransform), TextManager.Get("SoundVolume"), font: GUI.SubHeadingFont); + GUIScrollBar soundScrollBar = new GUIScrollBar(new RectTransform(textBlockScale, audioContent.RectTransform), + style: "GUISlider", barSize: 0.05f) { UserData = soundVolumeText, BarScroll = SoundVolume, @@ -647,9 +697,9 @@ namespace Barotrauma }; soundScrollBar.OnMoved(soundScrollBar, soundScrollBar.BarScroll); - GUITextBlock musicVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), audioSliders.RectTransform), TextManager.Get("MusicVolume")); - GUIScrollBar musicScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.15f), audioSliders.RectTransform), - barSize: 0.05f) + GUITextBlock musicVolumeText = new GUITextBlock(new RectTransform(textBlockScale, audioContent.RectTransform), TextManager.Get("MusicVolume"), font: GUI.SubHeadingFont); + GUIScrollBar musicScrollBar = new GUIScrollBar(new RectTransform(textBlockScale, audioContent.RectTransform), + style: "GUISlider", barSize: 0.05f) { UserData = musicVolumeText, BarScroll = MusicVolume, @@ -663,9 +713,9 @@ namespace Barotrauma }; musicScrollBar.OnMoved(musicScrollBar, musicScrollBar.BarScroll); - GUITextBlock voiceChatVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), audioSliders.RectTransform), TextManager.Get("VoiceChatVolume")); - GUIScrollBar voiceChatScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.15f), audioSliders.RectTransform), - barSize: 0.05f) + GUITextBlock voiceChatVolumeText = new GUITextBlock(new RectTransform(textBlockScale, audioContent.RectTransform), TextManager.Get("VoiceChatVolume"), font: GUI.SubHeadingFont); + GUIScrollBar voiceChatScrollBar = new GUIScrollBar(new RectTransform(textBlockScale, audioContent.RectTransform), + style: "GUISlider", barSize: 0.05f) { UserData = voiceChatVolumeText, BarScroll = VoiceChatVolume, @@ -679,45 +729,43 @@ namespace Barotrauma }; voiceChatScrollBar.OnMoved(voiceChatScrollBar, voiceChatScrollBar.BarScroll); - var tickBoxes = new GUILayoutGroup(new RectTransform(new Vector2(0.28f, 0.15f), tabs[(int)Tab.Audio].RectTransform, Anchor.TopLeft) - { RelativeOffset = new Vector2(0.02f, 0.32f) }) - { RelativeSpacing = 0.01f }; - - GUITickBox muteOnFocusLostBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, tickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("MuteOnFocusLost")); - muteOnFocusLostBox.Selected = MuteOnFocusLost; - muteOnFocusLostBox.ToolTip = TextManager.Get("MuteOnFocusLostToolTip"); - muteOnFocusLostBox.OnSelected = (tickBox) => + GUITickBox muteOnFocusLostBox = new GUITickBox(new RectTransform(tickBoxScale, audioContent.RectTransform), TextManager.Get("MuteOnFocusLost")) { - MuteOnFocusLost = tickBox.Selected; - UnsavedSettings = true; - return true; + Selected = MuteOnFocusLost, + ToolTip = TextManager.Get("MuteOnFocusLostToolTip"), + OnSelected = (tickBox) => + { + MuteOnFocusLost = tickBox.Selected; + UnsavedSettings = true; + return true; + } }; - GUITickBox dynamicRangeCompressionTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, tickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("DynamicRangeCompression")); - dynamicRangeCompressionTickBox.Selected = DynamicRangeCompressionEnabled; - dynamicRangeCompressionTickBox.ToolTip = TextManager.Get("DynamicRangeCompressionToolTip"); - dynamicRangeCompressionTickBox.OnSelected = (tickBox) => + GUITickBox dynamicRangeCompressionTickBox = new GUITickBox(new RectTransform(tickBoxScale, audioContent.RectTransform), TextManager.Get("DynamicRangeCompression")) { - DynamicRangeCompressionEnabled = tickBox.Selected; - UnsavedSettings = true; - return true; + Selected = DynamicRangeCompressionEnabled, + ToolTip = TextManager.Get("DynamicRangeCompressionToolTip"), + OnSelected = (tickBox) => + { + DynamicRangeCompressionEnabled = tickBox.Selected; + UnsavedSettings = true; + return true; + } }; - GUITickBox voipAttenuationTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, tickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("VoipAttenuation")); - voipAttenuationTickBox.Selected = VoipAttenuationEnabled; - voipAttenuationTickBox.ToolTip = TextManager.Get("VoipAttenuationToolTip"); - voipAttenuationTickBox.OnSelected = (tickBox) => + GUITickBox voipAttenuationTickBox = new GUITickBox(new RectTransform(tickBoxScale, audioContent.RectTransform), TextManager.Get("VoipAttenuation")) { - VoipAttenuationEnabled = tickBox.Selected; - UnsavedSettings = true; - return true; + Selected = VoipAttenuationEnabled, + ToolTip = TextManager.Get("VoipAttenuationToolTip"), + OnSelected = (tickBox) => + { + VoipAttenuationEnabled = tickBox.Selected; + UnsavedSettings = true; + return true; + } }; - var voipSettings = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.35f), tabs[(int)Tab.Audio].RectTransform, Anchor.TopCenter) - { RelativeOffset = new Vector2(0.0f, 0.47f) }) - { RelativeSpacing = 0.01f }; - - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), voipSettings.RectTransform), TextManager.Get("VoiceChat")); + new GUITextBlock(new RectTransform(textBlockScale, audioContent.RectTransform), TextManager.Get("VoiceChat"), font: GUI.SubHeadingFont); CaptureDeviceNames = Alc.GetStringList((IntPtr)null, Alc.CaptureDeviceSpecifier); foreach (string name in CaptureDeviceNames) @@ -725,14 +773,16 @@ namespace Barotrauma DebugConsole.NewMessage(name + " " + name.Length.ToString(), Color.Lime); } - GUITickBox directionalVoiceChat = new GUITickBox(new RectTransform(tickBoxScale / 0.4f, voipSettings.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("DirectionalVoiceChat")); - directionalVoiceChat.Selected = UseDirectionalVoiceChat; - directionalVoiceChat.ToolTip = TextManager.Get("DirectionalVoiceChatToolTip"); - directionalVoiceChat.OnSelected = (tickBox) => + GUITickBox directionalVoiceChat = new GUITickBox(new RectTransform(tickBoxScale, audioContent.RectTransform), TextManager.Get("DirectionalVoiceChat")) { - UseDirectionalVoiceChat = tickBox.Selected; - UnsavedSettings = true; - return true; + Selected = UseDirectionalVoiceChat, + ToolTip = TextManager.Get("DirectionalVoiceChatToolTip"), + OnSelected = (tickBox) => + { + UseDirectionalVoiceChat = tickBox.Selected; + UnsavedSettings = true; + return true; + } }; if (string.IsNullOrWhiteSpace(VoiceCaptureDevice) || !(CaptureDeviceNames?.Contains(VoiceCaptureDevice) ?? false)) @@ -744,7 +794,7 @@ namespace Barotrauma VoiceSetting = VoiceMode.Disabled; } #if (!OSX) - var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.15f), voipSettings.RectTransform), TrimAudioDeviceName(VoiceCaptureDevice), CaptureDeviceNames.Count); + var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.15f), audioContent.RectTransform), TrimAudioDeviceName(VoiceCaptureDevice), CaptureDeviceNames.Count); if (CaptureDeviceNames?.Count > 0) { foreach (string name in CaptureDeviceNames) @@ -763,15 +813,15 @@ namespace Barotrauma else { deviceList.AddItem(TextManager.Get("VoipNoDevices") ?? "N/A", null); - deviceList.ButtonTextColor = Color.Red; + deviceList.ButtonTextColor = GUI.Style.Red; deviceList.ButtonEnabled = false; deviceList.Select(0); } #else - var defaultDeviceGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.3f), voipSettings.RectTransform), true, Anchor.CenterLeft); + var defaultDeviceGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.3f), audioContent.RectTransform), true, Anchor.CenterLeft); var currentDeviceTextBlock = new GUITextBlock(new RectTransform(new Vector2(.7f, 0.75f), null), - TextManager.AddPunctuation(':', TextManager.Get("CurrentDevice"), TrimAudioDeviceName(VoiceCaptureDevice))) + TextManager.AddPunctuation(':', TextManager.Get("CurrentDevice"), TrimAudioDeviceName(VoiceCaptureDevice)), font: GUI.SubHeadingFont) { ToolTip = TextManager.Get("CurrentDeviceToolTip.OSX"), TextAlignment = Alignment.CenterLeft @@ -795,7 +845,7 @@ namespace Barotrauma else { currentDeviceTextBlock.Text = TextManager.Get("VoipNoDevices") ?? "N/A"; - currentDeviceTextBlock.Flash(Color.Red); + currentDeviceTextBlock.Flash(GUI.Style.Red); } return true; @@ -807,16 +857,16 @@ namespace Barotrauma #endif var voiceModeCount = Enum.GetNames(typeof(VoiceMode)).Length; - var voiceModeDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.15f), voipSettings.RectTransform), elementCount: voiceModeCount); + var voiceModeDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.15f), audioContent.RectTransform), elementCount: voiceModeCount); for (int i = 0; i < voiceModeCount; i++) { var voiceMode = "VoiceMode." + ((VoiceMode)i).ToString(); voiceModeDropDown.AddItem(TextManager.Get(voiceMode), userData: i, toolTip: TextManager.Get(voiceMode + "ToolTip")); } - var micVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), voipSettings.RectTransform), TextManager.Get("MicrophoneVolume")); - var micVolumeSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.15f), voipSettings.RectTransform), - barSize: 0.05f) + var micVolumeText = new GUITextBlock(new RectTransform(textBlockScale, audioContent.RectTransform), TextManager.Get("MicrophoneVolume"), font: GUI.SubHeadingFont); + var micVolumeSlider = new GUIScrollBar(new RectTransform(textBlockScale, audioContent.RectTransform), + style: "GUISlider", barSize: 0.05f) { UserData = micVolumeText, BarScroll = (float)Math.Sqrt(MathUtils.InverseLerp(0.2f, MaxMicrophoneVolume, MicrophoneVolume)), @@ -832,14 +882,13 @@ namespace Barotrauma }; micVolumeSlider.OnMoved(micVolumeSlider, micVolumeSlider.BarScroll); - - var extraVoiceSettingsContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), voipSettings.RectTransform, Anchor.BottomCenter), style: null); + var extraVoiceSettingsContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), audioContent.RectTransform, Anchor.BottomCenter), style: null); var voiceActivityGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), extraVoiceSettingsContainer.RectTransform)) { Visible = VoiceSetting != VoiceMode.Disabled }; - GUITextBlock noiseGateText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), voiceActivityGroup.RectTransform), TextManager.Get("NoiseGateThreshold")) + GUITextBlock noiseGateText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), voiceActivityGroup.RectTransform), TextManager.Get("NoiseGateThreshold"), font: GUI.SubHeadingFont) { Visible = VoiceSetting == VoiceMode.Activity, TextGetter = () => @@ -854,7 +903,7 @@ namespace Barotrauma if (VoiceSetting == VoiceMode.Activity) { - dbMeter.Color = VoipCapture.Instance.LastdB > NoiseGateThreshold ? Color.Lime : Color.Orange; //TODO: i'm a filthy hack + dbMeter.Color = VoipCapture.Instance.LastdB > NoiseGateThreshold ? GUI.Style.Green : GUI.Style.Orange; //TODO: i'm a filthy hack } else { @@ -864,7 +913,8 @@ namespace Barotrauma float scrollVal = double.IsNegativeInfinity(VoipCapture.Instance.LastdB) ? 0.0f : ((float)VoipCapture.Instance.LastdB + 100.0f) / 100.0f; return scrollVal * scrollVal; }; - var noiseGateSlider = new GUIScrollBar(new RectTransform(Vector2.One, dbMeter.RectTransform, Anchor.Center), color: Color.White, barSize: 0.03f); + var noiseGateSlider = new GUIScrollBar(new RectTransform(Vector2.One, dbMeter.RectTransform, Anchor.Center), color: Color.White, + style: "GUISlider", barSize: 0.03f); noiseGateSlider.Frame.Visible = false; noiseGateSlider.Step = 0.01f; noiseGateSlider.Range = new Vector2(-100.0f, 0.0f); @@ -887,7 +937,7 @@ namespace Barotrauma { Visible = VoiceSetting == VoiceMode.PushToTalk }; - new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), voiceInputContainer.RectTransform), TextManager.Get("InputType.Voice")); + new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), voiceInputContainer.RectTransform), TextManager.Get("InputType.Voice"), font: GUI.SubHeadingFont); var voiceKeyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 1.0f), voiceInputContainer.RectTransform, Anchor.TopRight), text: KeyBindText(InputType.Voice)) { SelectedColor = Color.Gold * 0.3f, @@ -953,12 +1003,12 @@ namespace Barotrauma { RelativeOffset = new Vector2(0.0f, 0.02f) }) { RelativeSpacing = 0.01f }; - GUITextBlock aimAssistText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), TextManager.Get("AimAssist")) + GUITextBlock aimAssistText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), TextManager.Get("AimAssist"), font: GUI.SubHeadingFont) { ToolTip = TextManager.Get("AimAssistToolTip") }; - GUIScrollBar aimAssistSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), - barSize: 0.05f) + GUIScrollBar aimAssistSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), + style: "GUISlider", barSize: 0.05f) { UserData = aimAssistText, BarScroll = MathUtils.InverseLerp(0.0f, 5.0f, AimAssistAmount), @@ -973,7 +1023,7 @@ namespace Barotrauma }; aimAssistSlider.OnMoved(aimAssistSlider, aimAssistSlider.BarScroll); - new GUITickBox(new RectTransform(tickBoxScale, controlsLayoutGroup.RectTransform, scaleBasis: ScaleBasis.BothHeight), TextManager.Get("EnableMouseLook")) + new GUITickBox(new RectTransform(tickBoxScale, controlsLayoutGroup.RectTransform), TextManager.Get("EnableMouseLook")) { ToolTip = TextManager.Get("EnableMouseLookToolTip"), Selected = EnableMouseLook, @@ -999,11 +1049,11 @@ namespace Barotrauma { var inputContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.06f),(i <= (inputNames.Length / 2.2f) ? inputColumnLeft : inputColumnRight).RectTransform)) { Stretch = true, IsHorizontal = true, RelativeSpacing = 0.01f, Color = new Color(12, 14, 15, 215) }; - var inputName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), inputContainer.RectTransform, Anchor.TopLeft) { MinSize = new Point(150, 0) }, + var inputName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), inputContainer.RectTransform, Anchor.TopLeft) { MinSize = new Point(100, 0) }, TextManager.Get("InputType." + ((InputType)i)), font: GUI.SmallFont) { ForceUpperCase = true }; inputNameBlocks.Add(inputName); var keyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 1.0f), inputContainer.RectTransform), - text: KeyBindText((InputType)i), font: GUI.SmallFont) + text: KeyBindText((InputType)i), font: GUI.SmallFont, style: "GUITextBoxNoIcon") { UserData = i }; @@ -1020,12 +1070,15 @@ namespace Barotrauma GUITextBlock.AutoScaleAndNormalize(inputNameBlocks); - var resetControlsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), controlsLayoutGroup.RectTransform), isHorizontal: true) + var resetControlsArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.07f), controlsLayoutGroup.RectTransform), style: null); + var resetControlsHolder = new GUILayoutGroup(new RectTransform(new Vector2(buttonArea.RectTransform.RelativeSize.X / controlsLayoutGroup.RectTransform.RelativeSize.X / rightPanel.RectTransform.RelativeSize.X, 1.0f), resetControlsArea.RectTransform, Anchor.Center), + isHorizontal: true, childAnchor: Anchor.CenterLeft) { - RelativeSpacing = 0.02f - }; + Stretch = true, + RelativeSpacing = 0.05f + }; resetControlsHolder.CanBeFocused = true; - var defaultBindingsButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetDefaultBindings")) + var defaultBindingsButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetDefaultBindings"), style: "GUIButtonSmall") { ToolTip = TextManager.Get("SetDefaultBindingsToolTip"), OnClicked = (button, data) => @@ -1035,7 +1088,7 @@ namespace Barotrauma } }; - var legacyBindingsButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetLegacyBindings")) + var legacyBindingsButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetLegacyBindings"), style: "GUIButtonSmall") { ToolTip = TextManager.Get("SetLegacyBindingsToolTip"), OnClicked = (button, data) => @@ -1050,17 +1103,13 @@ namespace Barotrauma GUITextBlock.AutoScaleAndNormalize(defaultBindingsButton.TextBlock, legacyBindingsButton.TextBlock); }; - //spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), generalLayoutGroup.RectTransform), style: null); - - new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomLeft), - TextManager.Get("Cancel"), style: "GUIButtonLarge") + TextManager.Get("Cancel")) { IgnoreLayoutGroups = true, OnClicked = (x, y) => { - void ExitSettings() + static void ExitSettings() { if (Screen.Selected == GameMain.MainMenuScreen) { GameMain.MainMenuScreen.ReturnToMainMenu(null, null); } GUI.SettingsMenuOpen = false; @@ -1091,7 +1140,7 @@ namespace Barotrauma }; new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomCenter), - TextManager.Get("Reset"), style: "GUIButtonLarge") + TextManager.Get("Reset")) { IgnoreLayoutGroups = true, OnClicked = (button, data) => @@ -1126,13 +1175,50 @@ namespace Barotrauma }; applyButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomRight), - TextManager.Get("ApplySettingsButton"), style: "GUIButtonLarge") + TextManager.Get("ApplySettingsButton")) { IgnoreLayoutGroups = true, Enabled = false }; applyButton.OnClicked = ApplyClicked; +#if DEBUG + /// Debug tab ---------------------------------------------------------------- + var debugTickBoxes = new GUILayoutGroup(new RectTransform(new Vector2(0.28f, 0.15f), tabs[(int)Tab.Debug].RectTransform, Anchor.TopLeft) + { RelativeOffset = new Vector2(0.02f, 0.02f) }) + { RelativeSpacing = 0.01f }; + + var automaticQuickStartTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Enable automatic quickstart", style: "GUITickBox"); + automaticQuickStartTickBox.Selected = AutomaticQuickStartEnabled; + automaticQuickStartTickBox.ToolTip = "Will the game automatically move on to Quickstart when the game is launched"; + automaticQuickStartTickBox.OnSelected = (tickBox) => + { + AutomaticQuickStartEnabled = tickBox.Selected; + UnsavedSettings = true; + return true; + }; + + var showSplashScreenTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Show splash screen", style: "GUITickBox"); + showSplashScreenTickBox.Selected = EnableSplashScreen; + showSplashScreenTickBox.ToolTip = "Are the splash screens shown when the game is launched"; + showSplashScreenTickBox.OnSelected = (tickBox) => + { + EnableSplashScreen = tickBox.Selected; + UnsavedSettings = true; + return true; + }; + + var verboseLoggingTickBox = new GUITickBox(new RectTransform(tickBoxScale / 0.18f, debugTickBoxes.RectTransform, scaleBasis: ScaleBasis.BothHeight), "Enable verbose logging", style: "GUITickBox"); + verboseLoggingTickBox.Selected = VerboseLogging; + verboseLoggingTickBox.ToolTip = "Should verbose logging be used"; + verboseLoggingTickBox.OnSelected = (tickBox) => + { + VerboseLogging = tickBox.Selected; + UnsavedSettings = true; + return true; + }; +#endif + UnsavedSettings = false; // Reset unsaved settings to false once the UI has been created SelectTab(selectedTab); } @@ -1418,7 +1504,7 @@ namespace Barotrauma { SaveNewPlayerConfig(); - SettingsFrame.Flash(Color.Green); + SettingsFrame.Flash(GUI.Style.Green); if (GameMain.WindowMode != GameMain.Config.WindowMode || GameMain.Config.GraphicsWidth != GameMain.GraphicsWidth || GameMain.Config.GraphicsHeight != GameMain.GraphicsHeight) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs index 771acd183..54027a35d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs @@ -98,9 +98,10 @@ namespace Barotrauma limbSlotIcons.Add(InvSlotType.Headset, new Sprite("Content/UI/IconAtlas.png", new Rectangle(384 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2))); limbSlotIcons.Add(InvSlotType.InnerClothes, new Sprite("Content/UI/IconAtlas.png", new Rectangle(512 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2))); limbSlotIcons.Add(InvSlotType.Card, new Sprite("Content/UI/IconAtlas.png", new Rectangle(640 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2))); - limbSlotIcons.Add(InvSlotType.Head, new Sprite("Content/UI/IconAtlas.png", new Rectangle(896 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2))); - limbSlotIcons.Add(InvSlotType.LeftHand, new Sprite("Content/UI/IconAtlas.png", new Rectangle(640 + margin, 383 + margin, 128 - margin * 2, 128 - margin * 2))); - limbSlotIcons.Add(InvSlotType.RightHand, new Sprite("Content/UI/IconAtlas.png", new Rectangle(768 + margin, 383 + margin, 128 - margin * 2, 128 - margin * 2))); + + limbSlotIcons.Add(InvSlotType.Head, new Sprite("Content/UI/IconAtlas.png", new Rectangle(896 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2))); + limbSlotIcons.Add(InvSlotType.LeftHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(640 + margin, 0 + margin, 128 - margin * 2, 128 - margin * 2))); + limbSlotIcons.Add(InvSlotType.RightHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(768 + margin, 0 + margin, 128 - margin * 2, 128 - margin * 2))); limbSlotIcons.Add(InvSlotType.OuterClothes, new Sprite("Content/UI/IconAtlas.png", new Rectangle(768 + margin, 896 + margin, 128 - margin * 2, 128 - margin * 2))); } SlotPositions = new Vector2[SlotTypes.Length]; @@ -146,7 +147,7 @@ namespace Barotrauma { InventorySlot prevSlot = slots[i]; - Sprite slotSprite = slotSpriteSmall; + Sprite slotSprite = SlotSpriteSmall; Rectangle slotRect = new Rectangle( (int)(SlotPositions[i].X), (int)(SlotPositions[i].Y), @@ -243,7 +244,7 @@ namespace Barotrauma private void SetSlotPositions(Layout layout) { int spacing = (int)(10 * UIScale); - Point slotSize = (slotSpriteSmall.size * UIScale).ToPoint(); + Point slotSize = (SlotSpriteSmall.size * UIScale).ToPoint(); int bottomOffset = slotSize.Y + spacing * 2 + ContainedIndicatorHeight; if (slots == null) CreateSlots(); @@ -258,7 +259,7 @@ namespace Barotrauma int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s)); int x = GameMain.GraphicsWidth / 2 - normalSlotCount * (slotSize.X + spacing) / 2; - int upperX = HUDLayoutSettings.PortraitArea.X - slotSize.X * 2; + int upperX = GameMain.GraphicsWidth - slotSize.X * 2; //make sure the rightmost normal slot doesn't overlap with the personal slots x -= Math.Max((x + normalSlotCount * (slotSize.X + spacing)) - (upperX - personalSlotCount * (slotSize.X + spacing)), 0); @@ -631,7 +632,7 @@ namespace Barotrauma TextManager.Get("QuickUseAction.HoldToUnequip", returnNull: true) ?? (GameMain.Config.Language == "English" ? "Hold to unequip" : TextManager.Get("QuickUseAction.Unequip")); - if (PlayerInput.PrimaryMouseButtonHeld()) + if (PlayerInput.LeftButtonHeld()) { slot.QuickUseTimer = Math.Max(0.1f, slot.QuickUseTimer + deltaTime); if (slot.QuickUseTimer >= 1.0f) @@ -894,7 +895,7 @@ namespace Barotrauma success = true; for (int j = 0; j < capacity; j++) { - if (Items[j] == character.SelectedItems[i]) slots[j].ShowBorderHighlight(Color.Green, 0.1f, 0.4f); + if (Items[j] == character.SelectedItems[i]) slots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.4f); } break; } @@ -906,7 +907,7 @@ namespace Barotrauma { for (int i = 0; i < capacity; i++) { - if (Items[i] == item) slots[i].ShowBorderHighlight(Color.Green, 0.1f, 0.4f); + if (Items[i] == item) slots[i].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.4f); } } @@ -937,8 +938,18 @@ namespace Barotrauma character.Name, Color.White * 0.9f); } - base.Draw(spriteBatch); - + for (int i = 0; i < capacity; i++) + { + if (HideSlot(i)) continue; + + Rectangle interactRect = slots[i].InteractRect; + interactRect.Location += slots[i].DrawOffset.ToPoint(); + + //don't draw the item if it's being dragged out of the slot + bool drawItem = draggingItem == null || draggingItem != Items[i] || interactRect.Contains(PlayerInput.MousePosition); + DrawSlot(spriteBatch, this, slots[i], Items[i], i, drawItem, SlotTypes[i]); + } + if (hideButton != null && hideButton.Visible && !Locked) { hideButton.DrawManually(spriteBatch, alsoChildren: true); @@ -957,7 +968,7 @@ namespace Barotrauma if (limbSlotIcons.ContainsKey(SlotTypes[i])) { var icon = limbSlotIcons[SlotTypes[i]]; - icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2() + slots[i].DrawOffset, Color.White * 0.3f, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X); + icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2() + slots[i].DrawOffset, GUIColorSettings.EquipmentSlotIconColor, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X); } continue; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs index 04edd3b3d..4d06b050d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs @@ -54,7 +54,7 @@ namespace Barotrauma.Items.Components item.SpriteColor * 0.5f, 0.0f, item.Scale, SpriteEffects.None, 0.0f); - GUI.DrawRectangle(spriteBatch, new Vector2(attachPos.X - 2, -attachPos.Y - 2), Vector2.One * 5, Color.Red, thickness: 3); + GUI.DrawRectangle(spriteBatch, new Vector2(attachPos.X - 2, -attachPos.Y - 2), Vector2.One * 5, GUI.Style.Red, thickness: 3); } public void ClientWrite(IWriteMessage msg, object[] extraData = null) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs index 87ade4ac1..e1703048e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs @@ -117,7 +117,24 @@ namespace Barotrauma.Items.Components else { //if a GUIFrame has been defined, draw the inventory inside it - guiCustomComponent = new GUICustomComponent(new RectTransform(new Vector2(0.9f), GuiFrame.RectTransform, Anchor.Center), + + var content = new GUIFrame(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, + style: null) + { + CanBeFocused = false + }; + + string labelText = GetUILabel(); + GUITextBlock label = null; + if (!string.IsNullOrEmpty(labelText)) + { + label = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform, Anchor.TopCenter), + labelText, font: GUI.SubHeadingFont, textAlignment: Alignment.Center, wrap: true); + } + + float minInventoryAreaSize = 0.5f; + guiCustomComponent = new GUICustomComponent( + new RectTransform(new Vector2(1.0f, label == null ? 1.0f : Math.Max(1.0f - label.RectTransform.RelativeSize.Y, minInventoryAreaSize)), content.RectTransform, Anchor.BottomCenter), onDraw: (SpriteBatch spriteBatch, GUICustomComponent component) => { Inventory.Draw(spriteBatch); }, onUpdate: null) { @@ -127,6 +144,19 @@ namespace Barotrauma.Items.Components } } + public string GetUILabel() + { + if (UILabel == string.Empty) { return string.Empty; } + if (UILabel != null) + { + return TextManager.Get("UILabel." + UILabel); + } + else + { + return item?.Name; + } + } + public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1) { if (hideItems || (item.body != null && !item.body.Enabled)) { return; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Controller.cs index 7e5080ef7..d19b33666 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Controller.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Controller.cs @@ -43,9 +43,9 @@ namespace Barotrauma.Items.Components if (storeOriginalState) { - crewAreaOriginalState = crewManager.ToggleCrewAreaOpen; + crewAreaOriginalState = crewManager.ToggleCrewListOpen; } - crewManager.ToggleCrewAreaOpen = value; + crewManager.ToggleCrewListOpen = value; } private void ToggleChatBox(bool value, bool storeOriginalState) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs index fb1c37246..92a0ff8d3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs @@ -22,34 +22,68 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific(XElement element) { - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) { Stretch = true, RelativeSpacing = 0.02f }; - inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.7f), paddedFrame.RectTransform), style: null); + var topFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedFrame.RectTransform), style: null); + var paddedLine = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.25f), topFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + var inputText = new GUITextBlock(new RectTransform(new Vector2(0f, 1.0f), paddedLine.RectTransform), TextManager.Get("uilabel.input"), font: GUI.SubHeadingFont) { Padding = Vector4.Zero }; + new GUIFrame(new RectTransform(new Vector2(1f, 1.0f), paddedLine.RectTransform), style: "HorizontalLine"); + + // Resize GUITextBlock width according to the text length + inputText.RectTransform.Resize(new Point((int)inputText.Font.MeasureString(inputText.Text).X, inputText.RectTransform.Rect.Height)); + + + var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1.2f), topFrame.RectTransform, Anchor.CenterLeft), childAnchor: Anchor.BottomLeft, isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.045f + }; + inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 1f), inputArea.RectTransform), style: null); inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawOverLay, null) { CanBeFocused = false }; - activateButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.1f), paddedFrame.RectTransform), - TextManager.Get("DeconstructorDeconstruct")) + var buttonContainer = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.75f), inputArea.RectTransform), style: null); + activateButton = new GUIButton(new RectTransform(new Vector2(0.95f, 0.65f), buttonContainer.RectTransform, Anchor.CenterLeft), + TextManager.Get("DeconstructorDeconstruct"), style: "DeviceButton") { + TextBlock = { AutoScale = true }, OnClicked = ToggleActive }; inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), TextManager.Get("DeconstructorNoPower"), - textColor: Color.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow") + textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow") { HoverColor = Color.Black, IgnoreLayoutGroups = true, Visible = false, CanBeFocused = false }; - outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.3f), paddedFrame.RectTransform), style: null); + + var bottomFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedFrame.RectTransform), style: null); + var paddedBottomLine = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.25f), bottomFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + var outputText = new GUITextBlock(new RectTransform(new Vector2(0f, 1.0f), paddedBottomLine.RectTransform), TextManager.Get("uilabel.output"), font: GUI.SubHeadingFont) { Padding = Vector4.Zero }; + new GUIFrame(new RectTransform(new Vector2(1f, 1.0f), paddedBottomLine.RectTransform), style: "HorizontalLine"); + + // Resize GUITextBlock width according to the text length + outputText.RectTransform.Resize(new Point((int)outputText.Font.MeasureString(outputText.Text).X, outputText.RectTransform.Rect.Height)); + + + outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.2f), bottomFrame.RectTransform, Anchor.CenterLeft), style: null); } partial void OnItemLoadedProjSpecific() @@ -69,7 +103,7 @@ namespace Barotrauma.Items.Components new Rectangle( lastSlot.Rect.X, lastSlot.Rect.Y + (int)(lastSlot.Rect.Height * (1.0f - progressState)), lastSlot.Rect.Width, (int)(lastSlot.Rect.Height * progressState)), - Color.Green * 0.5f, isFilled: true); + GUI.Style.Green * 0.5f, isFilled: true); } public override void UpdateHUD(Character character, float deltaTime, Camera cam) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Engine.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Engine.cs index 1196b704d..b7a639180 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Engine.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Engine.cs @@ -30,37 +30,45 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific(XElement element) { - var content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center)) + var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.85f, 0.65f), GuiFrame.RectTransform, Anchor.Center) { - Stretch = true, - RelativeSpacing = 0.05f - }; + RelativeOffset = new Vector2(0, 0.04f) + }, style: null); - float indicatorSize = 0.3f; - powerIndicator = new GUITickBox(new RectTransform(new Vector2(indicatorSize), content.RectTransform), - TextManager.Get("EnginePowered"), style: "IndicatorLightGreen") + var lightsArea = new GUIFrame(new RectTransform(new Vector2(1, 0.38f), paddedFrame.RectTransform, Anchor.TopLeft), style: null); + powerIndicator = new GUITickBox(new RectTransform(new Vector2(0.45f, 0.8f), lightsArea.RectTransform, Anchor.Center, Pivot.CenterRight) + { + RelativeOffset = new Vector2(-0.05f, 0) + }, TextManager.Get("EnginePowered"), font: GUI.SubHeadingFont, style: "IndicatorLightGreen") { CanBeFocused = false }; - - autoControlIndicator = new GUITickBox(new RectTransform(new Vector2(indicatorSize), content.RectTransform), TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), style: "IndicatorLightRed") + autoControlIndicator = new GUITickBox(new RectTransform(new Vector2(0.45f, 0.8f), lightsArea.RectTransform, Anchor.Center, Pivot.CenterLeft) + { + RelativeOffset = new Vector2(0.05f, 0) + }, TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), font: GUI.SubHeadingFont, style: "IndicatorLightYellow") { CanBeFocused = false }; + powerIndicator.TextBlock.Wrap = autoControlIndicator.TextBlock.Wrap = true; + powerIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); + autoControlIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); + GUITextBlock.AutoScaleAndNormalize(powerIndicator.TextBlock, autoControlIndicator.TextBlock); + var sliderArea = new GUIFrame(new RectTransform(new Vector2(1, 0.6f), paddedFrame.RectTransform, Anchor.BottomLeft), style: null); string powerLabel = TextManager.Get("EngineForce"); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), content.RectTransform), "", textAlignment: Alignment.Center) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), sliderArea.RectTransform, Anchor.TopCenter), "", textColor: GUI.Style.TextColor, font: GUI.SubHeadingFont, textAlignment: Alignment.Center) { + AutoScale = true, TextGetter = () => { return TextManager.AddPunctuation(':', powerLabel, (int)(targetForce) + " %"); } }; - - forceSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform), barSize: 0.15f, style: "GUISlider") + forceSlider = new GUIScrollBar(new RectTransform(new Vector2(0.95f, 0.45f), sliderArea.RectTransform, Anchor.Center), barSize: 0.1f, style: "DeviceSlider") { Step = 0.05f, OnMoved = (GUIScrollBar scrollBar, float barScroll) => { float newTargetForce = barScroll * 200.0f - 100.0f; - if (Math.Abs(newTargetForce - targetForce) < 0.01) return false; + if (Math.Abs(newTargetForce - targetForce) < 0.01) { return false; } targetForce = newTargetForce; @@ -73,16 +81,13 @@ namespace Barotrauma.Items.Components } }; - var textArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform), isHorizontal: true) - { - Stretch = true - }; + var textsArea = new GUIFrame(new RectTransform(new Vector2(1, 0.25f), sliderArea.RectTransform, Anchor.BottomCenter), style: null); + var backwardsLabel = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1.0f), textsArea.RectTransform, Anchor.CenterLeft), TextManager.Get("EngineBackwards"), + textColor: GUI.Style.TextColor, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft); + var forwardsLabel = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1.0f), textsArea.RectTransform, Anchor.CenterRight), TextManager.Get("EngineForwards"), + textColor: GUI.Style.TextColor, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight); + GUITextBlock.AutoScaleAndNormalize(backwardsLabel, forwardsLabel); - new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textArea.RectTransform), TextManager.Get("EngineBackwards"), - font: GUI.SmallFont, textAlignment: Alignment.CenterLeft); - new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textArea.RectTransform), TextManager.Get("EngineForwards"), - font: GUI.SmallFont, textAlignment: Alignment.CenterRight); - foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) @@ -113,11 +118,16 @@ namespace Barotrauma.Items.Components partial void UpdateAnimation(float deltaTime) { - if (propellerSprite == null) return; - + if (propellerSprite == null) { return; } spriteIndex += (force / 100.0f) * AnimSpeed * deltaTime; - if (spriteIndex < 0) spriteIndex = propellerSprite.FrameCount; - if (spriteIndex >= propellerSprite.FrameCount) spriteIndex = 0.0f; + if (spriteIndex < 0) + { + spriteIndex = propellerSprite.FrameCount; + } + if (spriteIndex >= propellerSprite.FrameCount) + { + spriteIndex = 0.0f; + } } public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1) @@ -136,7 +146,7 @@ namespace Barotrauma.Items.Components Vector2 drawPos = item.DrawPosition; drawPos += PropellerPos; drawPos.Y = -drawPos.Y; - GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 10, Vector2.One * 20, Color.Red); + GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 10, Vector2.One * 20, GUI.Style.Red); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs index 3e029d22f..bd9ef0053 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs @@ -13,6 +13,7 @@ namespace Barotrauma.Items.Components private GUIListBox itemList; private GUIFrame selectedItemFrame; + private GUIFrame selectedItemReqsFrame; public GUIButton ActivateButton { @@ -22,6 +23,7 @@ namespace Barotrauma.Items.Components private GUITextBox itemFilterBox; + private GUIComponent outputSlot; private GUIComponent inputInventoryHolder, outputInventoryHolder; private GUICustomComponent inputInventoryOverlay, outputInventoryOverlay; @@ -39,54 +41,81 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific() { - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) { - Stretch = true, RelativeSpacing = 0.02f }; - itemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), paddedFrame.RectTransform)) + var topFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.7f), paddedFrame.RectTransform), "InnerFrameDark"); + + var paddedItemFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), topFrame.RectTransform), style: null); + var itemListFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), paddedItemFrame.RectTransform, Anchor.Center)) { - OnSelected = (GUIComponent component, object userdata) => + Stretch = true + }; + + var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), itemListFrame.RectTransform), isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.02f, + UserData = "filterarea" + }; + + new GUITextBlock(new RectTransform(new Vector2(0.2f, 0.5f), filterArea.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.SubHeadingFont) + { + Padding = Vector4.Zero, + AutoScale = true + }; + itemFilterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), createClearButton: true); + itemFilterBox.OnTextChanged += (textBox, text) => { FilterEntities(text); return true; }; + + itemList = new GUIListBox(new RectTransform(new Vector2(1f, 0.85f), itemListFrame.RectTransform), style: null) + { + OnSelected = (component, userdata) => { selectedItem = userdata as FabricationRecipe; if (selectedItem != null) { SelectItem(Character.Controlled, selectedItem); } return true; } }; + + new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), topFrame.RectTransform, Anchor.Center), style: "VerticalLine"); - var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.06f), paddedFrame.RectTransform), isHorizontal: true) + var paddedOutputFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1f), topFrame.RectTransform, Anchor.TopRight), style: null); + var outputArea = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), paddedOutputFrame.RectTransform, Anchor.Center), style: null); + + // TODO, take off the duct tape and figure out a proper way to do this \/ + var scaledFrame = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.55f), outputArea.RectTransform), style: null); + outputSlot = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.5f), outputArea.RectTransform), style: null); + + outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1.1f, 1.5f), scaledFrame.RectTransform, Anchor.BottomCenter), style: null); + outputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, outputArea.RectTransform), DrawOutputOverLay) { CanBeFocused = false }; + + selectedItemFrame = new GUIFrame(new RectTransform(new Vector2(0.6f, 0.5f), outputArea.RectTransform, Anchor.TopRight), style: null); + selectedItemReqsFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), outputArea.RectTransform, Anchor.BottomLeft), style: null); + + var bottomFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.35f), paddedFrame.RectTransform), style: null); + + var paddedLine = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.25f), bottomFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true) { Stretch = true, - UserData = "filterarea" - }; - new GUITextBlock(new RectTransform(new Vector2(0.25f, 1.0f), filterArea.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.Font); - itemFilterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font); - itemFilterBox.OnTextChanged += (textBox, text) => { FilterEntities(text); return true; }; - var clearButton = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), filterArea.RectTransform), "x") - { - OnClicked = (btn, userdata) => { ClearFilter(); itemFilterBox.Flash(Color.White); return true; } - }; - - inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.15f), paddedFrame.RectTransform), style: null); - inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawInputOverLay, null) - { - CanBeFocused = false - }; - - var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.25f), paddedFrame.RectTransform), isHorizontal: true); - - selectedItemFrame = new GUIFrame(new RectTransform(new Vector2(0.75f, 1.0f), outputArea.RectTransform), style: "InnerFrame"); - outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), outputArea.RectTransform), style: null); - outputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, outputArea.RectTransform), DrawOutputOverLay, null) - { - CanBeFocused = false + RelativeSpacing = 0.02f }; + var inputText = new GUITextBlock(new RectTransform(new Vector2(0f, 1.0f), paddedLine.RectTransform), TextManager.Get("uilabel.input"), font: GUI.SubHeadingFont) { Padding = Vector4.Zero }; + new GUIFrame(new RectTransform(new Vector2(1f, 1.0f), paddedLine.RectTransform), style: "HorizontalLine"); + + // Resize GUITextBlock width according to the text length + inputText.RectTransform.Resize(new Point((int)inputText.Font.MeasureString(inputText.Text).X, inputText.RectTransform.Rect.Height)); + + var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1f), bottomFrame.RectTransform, Anchor.BottomCenter), isHorizontal: true, childAnchor: Anchor.BottomLeft); + inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.8f, 1f), inputArea.RectTransform), style: null); + inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawInputOverLay) { CanBeFocused = false }; CreateRecipes(); - activateButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.07f), paddedFrame.RectTransform), - TextManager.Get("FabricatorCreate"), style: "GUIButtonLarge") + var buttonFrame = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.8f), inputArea.RectTransform), style: null); + activateButton = new GUIButton(new RectTransform(new Vector2(1f, 0.6f), buttonFrame.RectTransform, Anchor.CenterRight), + TextManager.Get("FabricatorCreate"), style: "DeviceButton") { OnClicked = StartButtonClicked, UserData = selectedItem, @@ -94,7 +123,7 @@ namespace Barotrauma.Items.Components }; inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), TextManager.Get("FabricatorNoPower"), - textColor: Color.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow") + textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow") { HoverColor = Color.Black, IgnoreLayoutGroups = true, @@ -117,7 +146,7 @@ namespace Barotrauma.Items.Components ToolTip = fi.TargetItem.Description }; - GUITextBlock textBlock = new GUITextBlock(new RectTransform(Vector2.Zero, frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point((int)(50 * GUI.xScale), 0) }, + new GUITextBlock(new RectTransform(Vector2.Zero, frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point((int)(50 * GUI.xScale), 0) }, fi.DisplayName) { ToolTip = fi.TargetItem.Description @@ -126,7 +155,7 @@ namespace Barotrauma.Items.Components var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite; if (itemIcon != null) { - GUIImage img = new GUIImage(new RectTransform(new Point((int)(30 * GUI.Scale)), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point((int)(3 * GUI.xScale), 0) }, + new GUIImage(new RectTransform(new Point((int)(30 * GUI.Scale)), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point((int)(3 * GUI.xScale), 0) }, itemIcon, scaleToFit: true) { Color = fi.TargetItem.InventoryIconColor, @@ -166,15 +195,17 @@ namespace Barotrauma.Items.Components }); var sufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), - TextManager.Get("fabricatorsufficientskills", returnNull: true) ?? "Sufficient skills to fabricate", textColor: Color.LightGreen) + TextManager.Get("fabricatorsufficientskills", returnNull: true) ?? "Sufficient skills to fabricate", textColor: GUI.Style.Green, font: GUI.SubHeadingFont) { + AutoScale = true, CanBeFocused = false }; sufficientSkillsText.RectTransform.SetAsFirstChild(); var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), - TextManager.Get("fabricatorinsufficientskills", returnNull: true) ?? "Insufficient skills to fabricate", textColor: Color.Orange) + TextManager.Get("fabricatorinsufficientskills", returnNull: true) ?? "Insufficient skills to fabricate", textColor: Color.Orange, font: GUI.SubHeadingFont) { + AutoScale = true, CanBeFocused = false }; var firstinSufficient = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe fabricableItem && DegreeOfSuccess(character, fabricableItem.RequiredSkills) < 0.5f); @@ -223,7 +254,7 @@ namespace Barotrauma.Items.Components { if (item.ParentInventory.slots[availableSlotIndex].HighlightTimer <= 0.0f) { - item.ParentInventory.slots[availableSlotIndex].ShowBorderHighlight(Color.LightGreen * 0.5f, 0.5f, 0.5f); + item.ParentInventory.slots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green * 0.5f, 0.5f, 0.5f); } } } @@ -277,7 +308,7 @@ namespace Barotrauma.Items.Components new Rectangle( slotRect.X, slotRect.Y + (int)(slotRect.Height * (1.0f - progressState)), slotRect.Width, (int)(slotRect.Height * progressState)), - Color.Green * 0.5f, isFilled: true); + GUI.Style.Green * 0.5f, isFilled: true); } itemIcon.Draw( @@ -327,8 +358,10 @@ namespace Barotrauma.Items.Components private bool SelectItem(Character user, FabricationRecipe selectedItem) { selectedItemFrame.ClearChildren(); + selectedItemReqsFrame.ClearChildren(); - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), selectedItemFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.03f, Stretch = true }; + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.9f), selectedItemFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.03f }; + var paddedReqFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), selectedItemReqsFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.03f }; /*var itemIcon = selectedItem.TargetItem.InventoryIcon ?? selectedItem.TargetItem.sprite; if (itemIcon != null) @@ -340,19 +373,27 @@ namespace Barotrauma.Items.Components }; }*/ var nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), - selectedItem.TargetItem.Name, textAlignment: Alignment.CenterLeft); - + selectedItem.TargetItem.Name, textAlignment: Alignment.CenterLeft, textColor: Color.Aqua, font: GUI.SubHeadingFont) + { + AutoScale = true + }; + + nameBlock.Padding = new Vector4(0, nameBlock.Padding.Y, nameBlock.Padding.Z, nameBlock.Padding.W); + if (!string.IsNullOrWhiteSpace(selectedItem.TargetItem.Description)) { var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), selectedItem.TargetItem.Description, font: GUI.SmallFont, wrap: true); - if (description.Rect.Height > paddedFrame.Rect.Height * 0.4f) + description.Padding = new Vector4(0, description.Padding.Y, description.Padding.Z, description.Padding.W); + + while (description.Rect.Height + nameBlock.Rect.Height > paddedFrame.Rect.Height) { - description.Wrap = false; - description.Text = description.WrappedText.Split('\n').First()+"..."; - nameBlock.ToolTip = description.ToolTip = selectedItem.TargetItem.Description; - description.RectTransform.MaxSize = new Point(int.MaxValue, (int)description.Font.MeasureString(description.Text).Y); + var lines = description.WrappedText.Split('\n'); + var newString = string.Join('\n', lines.Take(lines.Length - 1)); + description.Text = newString.Substring(0, newString.Length - 4) + "..."; + description.CalculateHeightFromText(); + description.ToolTip = selectedItem.TargetItem.Description; } } @@ -364,24 +405,33 @@ namespace Barotrauma.Items.Components if (selectedItem.RequiredSkills.Any()) { - string text = TextManager.Get("FabricatorRequiredSkills") + ":\n"; + string text = ""; + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), + TextManager.Get("FabricatorRequiredSkills"), textColor: inadequateSkills.Any() ? GUI.Style.Red : GUI.Style.Green, font: GUI.SubHeadingFont) + { + AutoScale = true, + }; foreach (Skill skill in selectedItem.RequiredSkills) { - text += " - " + TextManager.Get("SkillName." + skill.Identifier) + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level; + text += TextManager.Get("SkillName." + skill.Identifier) + " " + TextManager.Get("Lvl").ToLower() + " " + skill.Level; if (skill != selectedItem.RequiredSkills.Last()) { text += "\n"; } } - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), text, - textColor: inadequateSkills.Any() ? Color.Red : Color.LightGreen, font: GUI.SmallFont); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), text, font: GUI.SmallFont); } float degreeOfSuccess = user == null ? 0.0f : DegreeOfSuccess(user, selectedItem.RequiredSkills); if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; } float requiredTime = user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user); - string requiredTimeText = TextManager.AddPunctuation(':', TextManager.Get("FabricatorRequiredTime"), ToolBox.SecondsToReadableTime(requiredTime)); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), - requiredTimeText, textColor: ToolBox.GradientLerp(degreeOfSuccess, Color.Red, Color.Yellow, Color.LightGreen), font: GUI.SmallFont); - + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), + TextManager.Get("FabricatorRequiredTime") , textColor: ToolBox.GradientLerp(degreeOfSuccess, GUI.Style.Red, Color.Yellow, GUI.Style.Green), font: GUI.SubHeadingFont) + { + AutoScale = true, + }; + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), ToolBox.SecondsToReadableTime(requiredTime), + font: GUI.SmallFont); return true; } @@ -413,7 +463,7 @@ namespace Barotrauma.Items.Components if (selectedItem == null) { return false; } if (!outputContainer.Inventory.IsEmpty()) { - outputInventoryHolder.Flash(Color.Red); + outputSlot.Flash(GUI.Style.Red); return false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs index 1ccba72ca..75580ab4f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs @@ -19,25 +19,25 @@ namespace Barotrauma.Items.Components private string noPowerTip = ""; - private List displayedSubs = new List(); + private readonly List displayedSubs = new List(); partial void InitProjSpecific(XElement element) { noPowerTip = TextManager.Get("SteeringNoPowerTip"); GuiFrame.RectTransform.RelativeOffset = new Vector2(0.05f, 0.0f); - new GUICustomComponent(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), + new GUICustomComponent(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, DrawHUDBack, null); submarineContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), style: null); - new GUICustomComponent(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), + new GUICustomComponent(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, DrawHUDFront, null) { CanBeFocused = false }; hullInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.13f, 0.13f), GUI.Canvas, minSize: new Point(250, 150)), - style: "InnerFrame") + style: "GUIToolTip") { CanBeFocused = false }; @@ -120,7 +120,7 @@ namespace Barotrauma.Items.Components Vector2 textPos = GuiFrame.Rect.Center.ToVector2(); GUI.DrawString(spriteBatch, textPos - textSize / 2, noPowerTip, - Color.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f); + GUI.Style.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f, font: GUI.SubHeadingFont); return; } @@ -137,7 +137,7 @@ namespace Barotrauma.Items.Components if (textPos.X - textSize.X / 2 < submarineContainer.Rect.X) textPos.X += (submarineContainer.Rect.X - (textPos.X - textSize.X / 2)) + 10 * GUI.xScale; GUI.DrawString(spriteBatch, textPos - textSize / 2, text, - Color.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f); + GUI.Style.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f); break; } } @@ -213,7 +213,7 @@ namespace Barotrauma.Items.Components if (ShowHullIntegrity) { gapOpenSum = hull.ConnectedGaps.Where(g => !g.IsRoomToRoom).Sum(g => g.Open); - borderColor = Color.Lerp(neutralColor, Color.Red, Math.Min((float)gapOpenSum, 1.0f)); + borderColor = Color.Lerp(neutralColor, GUI.Style.Red, Math.Min((float)gapOpenSum, 1.0f)); } float? oxygenAmount = null; @@ -222,7 +222,7 @@ namespace Barotrauma.Items.Components oxygenAmount = RequireOxygenDetectors ? hullData.Oxygen : hull.OxygenPercentage; GUI.DrawRectangle( spriteBatch, hullFrame.Rect, - Color.Lerp(Color.Red * 0.5f, Color.Green * 0.3f, (float)oxygenAmount / 100.0f), + Color.Lerp(GUI.Style.Red * 0.5f, GUI.Style.Green * 0.3f, (float)oxygenAmount / 100.0f), true); } @@ -271,15 +271,15 @@ namespace Barotrauma.Items.Components waterAmount /= (hullData.LinkedHulls.Count + 1); hullBreachText.Text = gapOpenSum > 0.1f ? TextManager.Get("MiniMapHullBreach") : ""; - hullBreachText.TextColor = Color.Red; + hullBreachText.TextColor = GUI.Style.Red; hullAirQualityText.Text = oxygenAmount == null ? TextManager.Get("MiniMapAirQualityUnavailable") : TextManager.AddPunctuation(':', TextManager.Get("MiniMapAirQuality"), + (int)oxygenAmount + " %"); - hullAirQualityText.TextColor = oxygenAmount == null ? Color.Red : Color.Lerp(Color.Red, Color.LightGreen, (float)oxygenAmount / 100.0f); + hullAirQualityText.TextColor = oxygenAmount == null ? GUI.Style.Red : Color.Lerp(GUI.Style.Red, Color.LightGreen, (float)oxygenAmount / 100.0f); hullWaterText.Text = waterAmount == null ? TextManager.Get("MiniMapWaterLevelUnavailable") : TextManager.AddPunctuation(':', TextManager.Get("MiniMapWaterLevel"), (int)(waterAmount * 100.0f) + " %"); - hullWaterText.TextColor = waterAmount == null ? Color.Red : Color.Lerp(Color.LightGreen, Color.Red, (float)waterAmount); + hullWaterText.TextColor = waterAmount == null ? GUI.Style.Red : Color.Lerp(Color.LightGreen, GUI.Style.Red, (float)waterAmount); } hullFrame.Color = borderColor; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs index db9eba079..1244202f7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs @@ -10,10 +10,10 @@ namespace Barotrauma.Items.Components { partial class Pump : Powered, IServerSerializable, IClientSerializable { - public GUIScrollBar IsActiveSlider { get; private set; } + public GUIButton PowerButton { get; private set; } private GUIScrollBar pumpSpeedSlider; - private GUITickBox powerIndicator; + private GUITickBox powerLight; private GUITickBox autoControlIndicator; private List> pumpOutEmitters = new List>(); @@ -40,70 +40,67 @@ namespace Barotrauma.Items.Components if (GuiFrame == null) { return; } - GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), style: null); - - IsActiveSlider = new GUIScrollBar(new RectTransform(new Point((int)(50 * GUI.Scale), (int)(100 * GUI.Scale)), paddedFrame.RectTransform, Anchor.CenterLeft), - barSize: 0.2f, style: "OnOffLever") + GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.85f, 0.65f), GuiFrame.RectTransform, Anchor.Center) { - IsBooleanSwitch = true, - MinValue = 0.25f, - MaxValue = 0.75f + RelativeOffset = new Vector2(0, 0.04f) + }, style: null); + + // Power button + float powerButtonSize = 1f; + var powerArea = new GUIFrame(new RectTransform(new Vector2(0.3f, 1) * powerButtonSize, paddedFrame.RectTransform, Anchor.CenterLeft), style: null); + var paddedPowerArea = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.8f), powerArea.RectTransform, Anchor.Center), style: "PowerButtonFrame"); + var powerLightArea = new GUIFrame(new RectTransform(new Vector2(0.87f, 0.2f), powerArea.RectTransform, Anchor.TopRight), style: null); + powerLight = new GUITickBox(new RectTransform(Vector2.One, powerLightArea.RectTransform, Anchor.Center), + TextManager.Get("PowerLabel"), font: GUI.SubHeadingFont, style: "IndicatorLightPower") + { + CanBeFocused = false }; - var sliderHandle = IsActiveSlider.GetChild(); - sliderHandle.RectTransform.NonScaledSize = new Point((int)(84 * GUI.Scale), sliderHandle.Rect.Height); - IsActiveSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) => + powerLight.TextBlock.AutoScale = true; + powerLight.TextBlock.OverrideTextColor(GUI.Style.TextColor); + PowerButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.75f), paddedPowerArea.RectTransform, Anchor.TopCenter) { - bool active = scrollBar.BarScroll < 0.5f; - if (active == IsActive) return false; - - targetLevel = null; - IsActive = active; - if (!IsActive) currPowerConsumption = 0.0f; - - if (GameMain.Client != null) + RelativeOffset = new Vector2(0, 0.1f) + }, style: "PowerButton") + { + OnClicked = (button, data) => { - correctionTimer = CorrectionDelay; - item.CreateClientEvent(this); + targetLevel = null; + IsActive = !IsActive; + if (GameMain.Client != null) + { + correctionTimer = CorrectionDelay; + item.CreateClientEvent(this); + } + powerLight.Selected = IsActive; + return true; } - - return true; }; - var rightArea = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.95f), paddedFrame.RectTransform, Anchor.CenterRight)) - { - RelativeSpacing = 0.1f, - Stretch = true - }; - - powerIndicator = new GUITickBox(new RectTransform(new Point((int)(30 * GUI.Scale)), rightArea.RectTransform), TextManager.Get("PumpPowered"), style: "IndicatorLightGreen") - { - CanBeFocused = false - }; - autoControlIndicator = new GUITickBox(new RectTransform(new Point((int)(30 * GUI.Scale)), rightArea.RectTransform), TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), style: "IndicatorLightRed") + var rightArea = new GUIFrame(new RectTransform(new Vector2(0.65f, 1), paddedFrame.RectTransform, Anchor.CenterRight), style: null); + + autoControlIndicator = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), rightArea.RectTransform, Anchor.TopLeft), + TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), font: GUI.SubHeadingFont, style: "IndicatorLightYellow") { CanBeFocused = false }; + autoControlIndicator.TextBlock.AutoScale = true; + autoControlIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); - var pumpSpeedText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), rightArea.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.0f) }, - "", textAlignment: Alignment.BottomLeft, wrap: true); + var sliderArea = new GUIFrame(new RectTransform(new Vector2(1, 0.65f), rightArea.RectTransform, Anchor.BottomLeft), style: null); + var pumpSpeedText = new GUITextBlock(new RectTransform(new Vector2(1, 0.3f), sliderArea.RectTransform, Anchor.TopLeft), "", + textColor: GUI.Style.TextColor, textAlignment: Alignment.CenterLeft, wrap: false, font: GUI.SubHeadingFont) + { + AutoScale = true + }; string pumpSpeedStr = TextManager.Get("PumpSpeed"); pumpSpeedText.TextGetter = () => { return TextManager.AddPunctuation(':', pumpSpeedStr, (int)flowPercentage + " %"); }; - - var sliderArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), rightArea.RectTransform, Anchor.CenterLeft), isHorizontal: true) - { - Stretch = true, - RelativeSpacing = 0.01f - }; - - var outLabel = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1.0f), sliderArea.RectTransform), - TextManager.Get("PumpOut"), textAlignment: Alignment.Center, wrap: false, font: GUI.SmallFont); - pumpSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(0.5f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider") + pumpSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(1, 0.35f), sliderArea.RectTransform, Anchor.Center), barSize: 0.1f, style: "DeviceSlider") { Step = 0.05f, OnMoved = (GUIScrollBar scrollBar, float barScroll) => { float newValue = barScroll * 200.0f - 100.0f; - if (Math.Abs(newValue - FlowPercentage) < 0.1f) return false; + if (Math.Abs(newValue - FlowPercentage) < 0.1f) { return false; } FlowPercentage = newValue; @@ -115,11 +112,11 @@ namespace Barotrauma.Items.Components return true; } }; - var inLabel = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1.0f), sliderArea.RectTransform), - TextManager.Get("PumpIn"), textAlignment: Alignment.Center, wrap: false, font: GUI.SmallFont); - - rightArea.Recalculate(); - sliderArea.Recalculate(); + var textsArea = new GUIFrame(new RectTransform(new Vector2(1, 0.25f), sliderArea.RectTransform, Anchor.BottomCenter), style: null); + var outLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textsArea.RectTransform, Anchor.CenterLeft), TextManager.Get("PumpOut"), + textColor: GUI.Style.TextColor, textAlignment: Alignment.CenterLeft, wrap: false, font: GUI.SubHeadingFont); + var inLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textsArea.RectTransform, Anchor.CenterRight), TextManager.Get("PumpIn"), + textColor: GUI.Style.TextColor, textAlignment: Alignment.CenterRight, wrap: false, font: GUI.SubHeadingFont); GUITextBlock.AutoScaleAndNormalize(outLabel, inLabel); } @@ -156,19 +153,36 @@ namespace Barotrauma.Items.Components } } + private float flickerTimer; + private readonly float flickerFrequency = 1; public override void UpdateHUD(Character character, float deltaTime, Camera cam) { pumpSpeedLockTimer -= deltaTime; isActiveLockTimer -= deltaTime; - powerIndicator.Selected = hasPower && IsActive; autoControlIndicator.Selected = pumpSpeedLockTimer > 0.0f || isActiveLockTimer > 0.0f; - IsActiveSlider.Enabled = isActiveLockTimer <= 0.0f; + PowerButton.Enabled = isActiveLockTimer <= 0.0f; + if (HasPower) + { + flickerTimer = 0; + powerLight.Selected = IsActive; + } + else if (IsActive) + { + flickerTimer += deltaTime; + if (flickerTimer > flickerFrequency) + { + flickerTimer = 0; + powerLight.Selected = !powerLight.Selected; + } + } + else + { + flickerTimer = 0; + powerLight.Selected = false; + } pumpSpeedSlider.Enabled = pumpSpeedLockTimer <= 0.0f && IsActive; - if (!PlayerInput.PrimaryMouseButtonHeld()) { - IsActiveSlider.BarScroll += (IsActive ? -10.0f : 10.0f) * deltaTime; - float pumpSpeedScroll = (FlowPercentage + 100.0f) / 200.0f; if (Math.Abs(pumpSpeedScroll - pumpSpeedSlider.BarScroll) > 0.01f) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs index faae76485..71b31a810 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs @@ -1,4 +1,5 @@ -using Barotrauma.Networking; +using Barotrauma.Extensions; +using Barotrauma.Networking; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; @@ -10,21 +11,15 @@ namespace Barotrauma.Items.Components { partial class Reactor : Powered, IServerSerializable, IClientSerializable { - public GUIScrollBar AutoTempSlider - { - get { return autoTempSlider; } - } - private GUIScrollBar autoTempSlider; + public GUIButton AutoTempSwitch { get; private set; } - public GUIScrollBar OnOffSwitch - { - get { return onOffSwitch; } - } - private GUIScrollBar onOffSwitch; + public GUIButton PowerButton { get; private set; } + private GUITickBox powerLight; + private GUITickBox autoTempLight; private const int GraphSize = 25; private float graphTimer; - private int updateGraphInterval = 500; + private readonly int updateGraphInterval = 500; private Sprite fissionRateMeter, turbineOutputMeter; private Sprite meterPointer; @@ -34,21 +29,23 @@ namespace Barotrauma.Items.Components private Sprite tempRangeIndicator; private Sprite graphLine; + //private GUIFrame graph; - public GUIScrollBar FissionRateScrollBar - { - get { return fissionRateScrollBar; } - } - private GUIScrollBar fissionRateScrollBar; + private Color optimalRangeColor = new Color(74,238,104,255); + private Color offRangeColor = Color.Orange; + private Color warningColor = Color.Red; + private Color coldColor = Color.LightBlue; + private Color warmColor = Color.Orange; + private Color hotColor = Color.Red; + private Color outputColor = Color.Goldenrod; + private Color loadColor = Color.LightSteelBlue; - public GUIScrollBar TurbineOutputScrollBar - { - get { return turbineOutputScrollBar; } - } - private GUIScrollBar turbineOutputScrollBar; + public GUIScrollBar FissionRateScrollBar { get; private set; } - private float[] outputGraph = new float[GraphSize]; - private float[] loadGraph = new float[GraphSize]; + public GUIScrollBar TurbineOutputScrollBar { get; private set; } + + private readonly float[] outputGraph = new float[GraphSize]; + private readonly float[] loadGraph = new float[GraphSize]; private GUITickBox criticalHeatWarning; private GUITickBox lowTemperatureWarning; @@ -56,147 +53,149 @@ namespace Barotrauma.Items.Components private GUIFrame inventoryContainer; - private GUIComponent leftHUDColumn; - private GUIComponent midHUDColumn; - private GUIComponent rightHUDColumn; + private readonly Dictionary warningButtons = new Dictionary(); - private GUILayoutGroup sliderControlsContainer; - - private Dictionary warningButtons = new Dictionary(); - - private static string[] warningTexts = new string[] + private static readonly string[] warningTexts = new string[] { - "ReactorWarningLowTemp","ReactorWarningOverheating", - "ReactorWarningLowOutput", "ReactorWarningHighOutput", - "ReactorWarningLowFuel", "ReactorWarningFuelOut", - "ReactorWarningMeltdown","ReactorWarningSCRAM" + "ReactorWarningLowTemp", "ReactorWarningLowOutput", "ReactorWarningLowFuel", "ReactorWarningMeltdown", + "ReactorWarningOverheating", "ReactorWarningHighOutput", "ReactorWarningFuelOut", "ReactorWarningSCRAM" }; partial void InitProjSpecific(XElement element) { - foreach (XElement subElement in element.Elements()) - { - switch (subElement.Name.ToString().ToLowerInvariant()) - { - case "fissionratemeter": - fissionRateMeter = new Sprite(subElement); - break; - case "turbineoutputmeter": - turbineOutputMeter = new Sprite(subElement); - break; - case "meterpointer": - meterPointer = new Sprite(subElement); - break; - case "sectorsprite": - sectorSprite = new Sprite(subElement); - break; - case "tempmeterframe": - tempMeterFrame = new Sprite(subElement); - break; - case "tempmeterbar": - tempMeterBar = new Sprite(subElement); - break; - case "temprangeindicator": - tempRangeIndicator = new Sprite(subElement); - break; - case "graphline": - graphLine = new Sprite(subElement); - break; - } - } + // TODO: need to recreate the gui when the resolution changes - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.85f), GuiFrame.RectTransform, Anchor.Center), isHorizontal: true) + fissionRateMeter = new Sprite(element.GetChildElement("fissionratemeter")?.GetChildElement("sprite")); + turbineOutputMeter = new Sprite(element.GetChildElement("turbineoutputmeter")?.GetChildElement("sprite")); + meterPointer = new Sprite(element.GetChildElement("meterpointer")?.GetChildElement("sprite")); + sectorSprite = new Sprite(element.GetChildElement("sectorsprite")?.GetChildElement("sprite")); + tempMeterFrame = new Sprite(element.GetChildElement("tempmeterframe")?.GetChildElement("sprite")); + tempMeterBar = new Sprite(element.GetChildElement("tempmeterbar")?.GetChildElement("sprite")); + tempRangeIndicator = new Sprite(element.GetChildElement("temprangeindicator")?.GetChildElement("sprite")); + graphLine = new Sprite(element.GetChildElement("graphline")?.GetChildElement("sprite")); + + var paddedFrame = new GUILayoutGroup(new RectTransform( + GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin.Multiply(new Vector2(1.4f, 1.2f)), GuiFrame.RectTransform, Anchor.Center) + { AbsoluteOffset = GUIStyle.ItemFrameOffset }, + isHorizontal: true) { RelativeSpacing = 0.012f, Stretch = true }; - GUIFrame columnLeft = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), paddedFrame.RectTransform), style: null); - GUIFrame columnMid = new GUIFrame(new RectTransform(new Vector2(0.45f, 1.0f), paddedFrame.RectTransform), style: null); - GUIFrame columnRight = new GUIFrame(new RectTransform(new Vector2(0.3f, 1.0f), paddedFrame.RectTransform), style: null); - leftHUDColumn = columnLeft; - midHUDColumn = columnMid; - rightHUDColumn = columnRight; + GUILayoutGroup columnLeft = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform)) + { + RelativeSpacing = 0.012f, + Stretch = true + }; + GUILayoutGroup columnRight = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), paddedFrame.RectTransform)) + { + RelativeSpacing = 0.012f, + Stretch = true + }; //---------------------------------------------------------- //left column //---------------------------------------------------------- - int buttonsPerRow = 2; - int spacing = 5; - int buttonWidth = columnLeft.Rect.Width / buttonsPerRow - (spacing * (buttonsPerRow - 1)); - int buttonHeight = (int)(columnLeft.Rect.Height * 0.5f) / 4; - for (int i = 0; i < warningTexts.Length; i++) + GUIFrame inventoryWindow = new GUIFrame(new RectTransform(new Vector2(0.1f, 0.5f), GuiFrame.RectTransform, Anchor.TopLeft, Pivot.TopRight) { - var warningBtn = new GUIButton(new RectTransform(new Point(buttonWidth, buttonHeight), columnLeft.RectTransform) - { AbsoluteOffset = new Point((i % buttonsPerRow) * (buttonWidth + spacing), (int)Math.Floor(i / (float)buttonsPerRow) * (buttonHeight + spacing)) }, - TextManager.Get(warningTexts[i]), style: "IndicatorButton") - { - CanBeFocused = false - }; + MinSize = new Point(85, 220), + RelativeOffset = new Vector2(-0.02f, 0) + }, style: "ItemUI"); - var btnText = warningBtn.GetChild(); - btnText.Font = GUI.Font; - btnText.Wrap = false; - btnText.SetTextPos(); - warningButtons.Add(warningTexts[i], warningBtn); - } - GUITextBlock.AutoScaleAndNormalize(warningButtons.Values.Select(b => b.TextBlock)); + GUILayoutGroup inventoryContent = new GUILayoutGroup(new RectTransform(inventoryWindow.Rect.Size - GUIStyle.ItemFrameMargin.Multiply(0.75f), inventoryWindow.RectTransform, Anchor.Center) + { AbsoluteOffset = GUIStyle.ItemFrameOffset }, + childAnchor: Anchor.TopCenter) + { + Stretch = true + }; - inventoryContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.45f), columnLeft.RectTransform, Anchor.BottomLeft), style: null); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), inventoryContent.RectTransform), "", + textAlignment: Alignment.Center, font: GUI.SubHeadingFont, wrap: true); + inventoryContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.9f), inventoryContent.RectTransform), style: null); //---------------------------------------------------------- //mid column //---------------------------------------------------------- - - criticalHeatWarning = new GUITickBox(new RectTransform(new Point(columnMid.Rect.Width / 3, (int)(30 * GUI.Scale)), columnMid.RectTransform), - TextManager.Get("ReactorWarningCriticalTemp"), font: GUI.SmallFont, style: "IndicatorLightRed") + + var topLeftArea = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.2f), columnLeft.RectTransform), + isHorizontal: true, childAnchor: Anchor.CenterLeft) { - CanBeFocused = false - }; - lowTemperatureWarning = new GUITickBox(new RectTransform(new Point(columnMid.Rect.Width / 3, (int)(30 * GUI.Scale)), columnMid.RectTransform) { RelativeOffset = new Vector2(0.27f, 0.0f) }, - TextManager.Get("ReactorWarningCriticalLowTemp"), font: GUI.SmallFont, style: "IndicatorLightRed") - { - CanBeFocused = false - }; - criticalOutputWarning = new GUITickBox(new RectTransform(new Point(columnMid.Rect.Width / 3, (int)(30 * GUI.Scale)), columnMid.RectTransform) { RelativeOffset = new Vector2(0.66f, 0.0f) }, - TextManager.Get("ReactorWarningCriticalOutput"), font: GUI.SmallFont, style: "IndicatorLightRed") - { - CanBeFocused = false + Stretch = true, + RelativeSpacing = 0.02f }; - GUITextBlock.AutoScaleAndNormalize(criticalHeatWarning.TextBlock, lowTemperatureWarning.TextBlock, criticalOutputWarning.TextBlock); - - float gaugeOffset = criticalHeatWarning.Rect.Height / (float)columnMid.Rect.Height + 0.05f * GUI.Scale; + Point maxIndicatorSize = new Point(int.MaxValue, (int)(50 * GUI.Scale)); + criticalHeatWarning = new GUITickBox(new RectTransform(new Vector2(0.3f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize }, + TextManager.Get("ReactorWarningCriticalTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed") + { + CanBeFocused = false + }; + lowTemperatureWarning = new GUITickBox(new RectTransform(new Vector2(0.4f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize }, + TextManager.Get("ReactorWarningCriticalLowTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed") + { + CanBeFocused = false + }; + criticalOutputWarning = new GUITickBox(new RectTransform(new Vector2(0.3f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize }, + TextManager.Get("ReactorWarningCriticalOutput"), font: GUI.SubHeadingFont, style: "IndicatorLightRed") + { + CanBeFocused = false + }; + criticalHeatWarning.TextBlock.OverrideTextColor(GUI.Style.TextColor); + lowTemperatureWarning.TextBlock.OverrideTextColor(GUI.Style.TextColor); + criticalOutputWarning.TextBlock.OverrideTextColor(GUI.Style.TextColor); - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, gaugeOffset) }, - TextManager.Get("ReactorFissionRate")); - new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, gaugeOffset + 0.05f) }, + topLeftArea.Recalculate(); + + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), columnLeft.RectTransform), style: "HorizontalLine"); + + float relativeYMargin = 0.02f; + Vector2 relativeTextSize = new Vector2(0.8f, 0.1f); + Vector2 sliderSize = new Vector2(1.0f, 0.125f); + Vector2 meterSize = new Vector2(1, 1 - relativeTextSize.Y - relativeYMargin - sliderSize.Y - 0.1f); + + var meterArea = new GUIFrame(new RectTransform(new Vector2(1, 0.6f - relativeYMargin * 2), columnLeft.RectTransform), style: null); + var leftArea = new GUIFrame(new RectTransform(new Vector2(0.49f, 1), meterArea.RectTransform), style: null); + var rightArea = new GUIFrame(new RectTransform(new Vector2(0.49f, 1), meterArea.RectTransform, Anchor.TopCenter, Pivot.TopLeft), style: null); + + var fissionRateTextBox = new GUITextBlock(new RectTransform(relativeTextSize, leftArea.RectTransform, Anchor.TopCenter), + TextManager.Get("ReactorFissionRate"), textColor: GUI.Style.TextColor, textAlignment: Alignment.Center, font: GUI.SubHeadingFont) + { + AutoScale = true + }; + var fissionMeter = new GUICustomComponent(new RectTransform(meterSize, leftArea.RectTransform, Anchor.TopCenter) + { + RelativeOffset = new Vector2(0.0f, relativeTextSize.Y + relativeYMargin) + }, DrawFissionRateMeter, null) { ToolTip = TextManager.Get("ReactorTipFissionRate") }; - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, gaugeOffset) }, - TextManager.Get("ReactorTurbineOutput")); - new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, gaugeOffset + 0.05f) }, + var turbineOutputTextBox = new GUITextBlock(new RectTransform(relativeTextSize, rightArea.RectTransform, Anchor.TopCenter), + TextManager.Get("ReactorTurbineOutput"), textColor: GUI.Style.TextColor, textAlignment: Alignment.Center, font: GUI.SubHeadingFont) + { + AutoScale = true + }; + GUITextBlock.AutoScaleAndNormalize(turbineOutputTextBox, fissionRateTextBox); + + var turbineMeter = new GUICustomComponent(new RectTransform(meterSize, rightArea.RectTransform, Anchor.TopCenter) + { + RelativeOffset = new Vector2(0.0f, relativeTextSize.Y + relativeYMargin) + }, DrawTurbineOutputMeter, null) { ToolTip = TextManager.Get("ReactorTipTurbineOutput") }; - GUILayoutGroup sliderControls = new GUILayoutGroup(new RectTransform(new Point(columnMid.Rect.Width, (int)(114 * GUI.Scale)), columnMid.RectTransform, Anchor.BottomCenter)) + FissionRateScrollBar = new GUIScrollBar(new RectTransform(sliderSize, leftArea.RectTransform, Anchor.TopCenter) { - Stretch = true, - AbsoluteSpacing = (int)(5 * GUI.Scale) - }; - sliderControlsContainer = sliderControls; - - new GUITextBlock(new RectTransform(new Point(0, (int)(20 * GUI.Scale)), sliderControls.RectTransform, Anchor.TopLeft), - TextManager.Get("ReactorFissionRate")); - fissionRateScrollBar = new GUIScrollBar(new RectTransform(new Point(sliderControls.Rect.Width, (int)(30 * GUI.Scale)), sliderControls.RectTransform, Anchor.TopCenter), - style: "GUISlider", barSize: 0.1f) + RelativeOffset = new Vector2(0, fissionMeter.RectTransform.RelativeOffset.Y + meterSize.Y) + }, + style: "DeviceSlider", barSize: 0.1f) { + Enabled = false, OnMoved = (GUIScrollBar bar, float scrollAmount) => { LastUser = Character.Controlled; @@ -207,11 +206,13 @@ namespace Barotrauma.Items.Components } }; - new GUITextBlock(new RectTransform(new Point(0, (int)(20 * GUI.Scale)), sliderControls.RectTransform, Anchor.BottomLeft), - TextManager.Get("ReactorTurbineOutput")); - turbineOutputScrollBar = new GUIScrollBar(new RectTransform(new Point(sliderControls.Rect.Width, (int)(30 * GUI.Scale)), sliderControls.RectTransform, Anchor.BottomCenter), - style: "GUISlider", barSize: 0.1f, isHorizontal: true) + TurbineOutputScrollBar = new GUIScrollBar(new RectTransform(sliderSize, rightArea.RectTransform, Anchor.TopCenter) { + RelativeOffset = new Vector2(0, turbineMeter.RectTransform.RelativeOffset.Y + meterSize.Y) + }, + style: "DeviceSlider", barSize: 0.1f, isHorizontal: true) + { + Enabled = false, OnMoved = (GUIScrollBar bar, float scrollAmount) => { LastUser = Character.Controlled; @@ -222,134 +223,219 @@ namespace Barotrauma.Items.Components } }; + var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.2f), columnLeft.RectTransform)) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + var upperButtons = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.5f), buttonArea.RectTransform), isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.01f + }; + var lowerButtons = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.5f), buttonArea.RectTransform), isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.01f + }; + int buttonCount = warningTexts.Length; + for (int i = 0; i < buttonCount; i++) + { + string text = warningTexts[i]; + var b = new GUIButton(new RectTransform(Vector2.One, (i < 4) ? upperButtons.RectTransform : lowerButtons.RectTransform), + TextManager.Get(text), style: "IndicatorButton") + { + Font = GUI.SubHeadingFont, + CanBeFocused = false + }; + b.TextBlock.Wrap = false; + warningButtons.Add(text, b); + } + upperButtons.Recalculate(); + lowerButtons.Recalculate(); + GUITextBlock.AutoScaleAndNormalize(warningButtons.Values.Select(b => b.TextBlock)); + //---------------------------------------------------------- //right column //---------------------------------------------------------- - new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.1f), columnRight.RectTransform), TextManager.Get("ReactorAutoTemp")) + // Auto temp + var topRightArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), columnRight.RectTransform), + isHorizontal: true, childAnchor: Anchor.CenterLeft) { - ToolTip = TextManager.Get("ReactorTipAutoTemp"), - AutoScale = true + Stretch = true, + RelativeSpacing = 0.02f }; - autoTempSlider = new GUIScrollBar(new RectTransform(new Vector2(0.6f, 0.15f), columnRight.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.1f) }, - barSize: 0.55f, style: "OnOffSlider", isHorizontal: true) + topRightArea.RectTransform.MaxSize = new Point(int.MaxValue, topLeftArea.Rect.Height); + + new GUIFrame(new RectTransform(new Vector2(0.01f, 1.0f), topRightArea.RectTransform), style: "VerticalLine"); + + AutoTempSwitch = new GUIButton(new RectTransform(new Vector2(0.15f, 0.9f), topRightArea.RectTransform), + style: "SwitchVertical") { - ToolTip = TextManager.Get("ReactorTipAutoTemp"), - IsBooleanSwitch = true, - BarScroll = 1.0f, - OnMoved = (scrollBar, scrollAmount) => + Enabled = false, + Selected = AutoTemp, + OnClicked = (button, data) => { + AutoTemp = !AutoTemp; LastUser = Character.Controlled; unsentChanges = true; return true; } }; - var sliderSprite = autoTempSlider.Frame.Style.Sprites[GUIComponent.ComponentState.None].First(); - autoTempSlider.RectTransform.MaxSize = new Point((int)(sliderSprite.Sprite.SourceRect.Size.X * GUI.Scale), (int)(sliderSprite.Sprite.SourceRect.Size.Y * GUI.Scale)); + AutoTempSwitch.RectTransform.MaxSize = new Point((int)(AutoTempSwitch.Rect.Height * 0.4f), int.MaxValue); - onOffSwitch = new GUIScrollBar(new RectTransform(new Vector2(0.4f, 0.3f), columnRight.RectTransform, Anchor.TopRight), - barSize: 0.2f, style: "OnOffLever", isHorizontal: false) - { - IsBooleanSwitch = true, - MinValue = 0.25f, - MaxValue = 0.75f, - OnMoved = (scrollBar, scrollAmount) => + autoTempLight = new GUITickBox(new RectTransform(new Vector2(0.4f, 1.0f), topRightArea.RectTransform), + TextManager.Get("ReactorAutoTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightYellow") { + ToolTip = TextManager.Get("ReactorTipAutoTemp"), + CanBeFocused = true, + Selected = AutoTemp + }; + autoTempLight.RectTransform.MaxSize = new Point(int.MaxValue, criticalHeatWarning.Rect.Height); + autoTempLight.TextBlock.OverrideTextColor(GUI.Style.TextColor); + + new GUIFrame(new RectTransform(new Vector2(0.01f, 1.0f), topRightArea.RectTransform), style: "VerticalLine"); + + // Power button + var powerArea = new GUIFrame(new RectTransform(new Vector2(0.4f, 1.0f), topRightArea.RectTransform), style: null); + var paddedPowerArea = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), powerArea.RectTransform, Anchor.Center, scaleBasis: ScaleBasis.BothHeight), style: "PowerButtonFrame"); + powerLight = new GUITickBox(new RectTransform(new Vector2(0.87f, 0.2f), paddedPowerArea.RectTransform, Anchor.TopCenter, Pivot.Center), + TextManager.Get("PowerLabel"), font: GUI.SubHeadingFont, style: "IndicatorLightPower") + { + CanBeFocused = false, + Selected = _powerOn + }; + powerLight.TextBlock.AutoScale = true; + powerLight.TextBlock.OverrideTextColor(GUI.Style.TextColor); + PowerButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.75f), paddedPowerArea.RectTransform, Anchor.BottomCenter) + { + RelativeOffset = new Vector2(0, 0.1f) + }, style: "PowerButton") + { + OnClicked = (button, data) => + { + PowerOn = !PowerOn; LastUser = Character.Controlled; unsentChanges = true; return true; } }; - var switchSprite = onOffSwitch.Frame.Style.Sprites[GUIComponent.ComponentState.None].First(); - onOffSwitch.RectTransform.MaxSize = new Point((int)(switchSprite.Sprite.SourceRect.Size.X * GUI.Scale), (int)(switchSprite.Sprite.SourceRect.Size.Y * GUI.Scale)); - var lever = onOffSwitch.GetChild(); - lever.RectTransform.NonScaledSize = new Point(lever.Rect.Width + (int)(30 * GUI.Scale), lever.Rect.Height); + topRightArea.Recalculate(); + autoTempLight.TextBlock.Wrap = true; + GUITextBlock.AutoScaleAndNormalize( + criticalHeatWarning.TextBlock, lowTemperatureWarning.TextBlock, criticalOutputWarning.TextBlock, autoTempLight.TextBlock); - var graphArea = new GUICustomComponent(new RectTransform(new Vector2(1.0f, 0.5f), columnRight.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(0, 30) }, - DrawGraph, null); + // right bottom (graph area) ----------------------- - Point textSize = new Point((int)(100 * GUI.Scale), (int)(30 * GUI.Scale)); + new GUIFrame(new RectTransform(new Vector2(0.95f, 0.01f), columnRight.RectTransform), style: "HorizontalLine"); - var loadText = new GUITextBlock(new RectTransform(textSize, graphArea.RectTransform, Anchor.TopLeft, Pivot.BottomLeft), - "Load", textColor: Color.LightBlue, textAlignment: Alignment.CenterLeft) + var bottomRightArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), columnRight.RectTransform), isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + + new GUIFrame(new RectTransform(new Vector2(0.01f, 1.0f), bottomRightArea.RectTransform), style: "VerticalLine"); + + new GUICustomComponent(new RectTransform(new Vector2(0.1f, 1), bottomRightArea.RectTransform, Anchor.Center), DrawTempMeter, null); + + var graphArea = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 1.0f), bottomRightArea.RectTransform)) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + + relativeTextSize = new Vector2(1.0f, 0.0f); + var loadText = new GUITextBlock(new RectTransform(relativeTextSize, graphArea.RectTransform), + "Load", textColor: loadColor, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft) { ToolTip = TextManager.Get("ReactorTipLoad") }; string loadStr = TextManager.Get("ReactorLoad"); - loadText.TextGetter += () => { return loadStr.Replace("[kw]", ((int)load).ToString()); }; + string kW = TextManager.Get("kilowatt"); + loadText.TextGetter += () => $"{loadStr.Replace("[kw]", ((int)load).ToString())} {kW}"; + + var graph = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.9f), graphArea.RectTransform), style: "InnerFrameRed"); + new GUICustomComponent(new RectTransform(new Vector2(0.9f, 0.98f), graph.RectTransform, Anchor.Center), DrawGraph, null); - var outputText = new GUITextBlock(new RectTransform(textSize, graphArea.RectTransform, Anchor.BottomLeft, Pivot.TopLeft), - "Output", textColor: Color.LightGreen, textAlignment: Alignment.CenterLeft) + var outputText = new GUITextBlock(new RectTransform(relativeTextSize, graphArea.RectTransform), + "Output", textColor: outputColor, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft) { ToolTip = TextManager.Get("ReactorTipPower") }; string outputStr = TextManager.Get("ReactorOutput"); - outputText.TextGetter += () => { return outputStr.Replace("[kw]", ((int)-currPowerConsumption).ToString()); }; + outputText.TextGetter += () => $"{outputStr.Replace("[kw]", ((int)-currPowerConsumption).ToString())} {kW}"; } public override void OnItemLoaded() { base.OnItemLoaded(); - turbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f; - fissionRateScrollBar.BarScroll = targetFissionRate / 100.0f; + TurbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f; + FissionRateScrollBar.BarScroll = targetFissionRate / 100.0f; var itemContainer = item.GetComponent(); if (itemContainer != null) { itemContainer.AllowUIOverlap = true; itemContainer.Inventory.RectTransform = inventoryContainer.RectTransform; + var inventoryLabel = inventoryContainer.Parent?.GetChild(); + if (inventoryLabel != null) + { + inventoryLabel.RectTransform.MinSize = new Point(100, 0); + inventoryLabel.Text = itemContainer.GetUILabel(); + inventoryLabel.CalculateHeightFromText(); + (inventoryLabel.Parent as GUILayoutGroup).Recalculate(); + } } } - private void DrawGraph(SpriteBatch spriteBatch, GUICustomComponent container) + private void DrawTempMeter(SpriteBatch spriteBatch, GUICustomComponent container) { - if (item.Removed) { return; } + Vector2 meterPos = new Vector2(container.Rect.X, container.Rect.Y); + Vector2 meterScale = new Vector2(container.Rect.Width / (float)tempMeterFrame.SourceRect.Width, container.Rect.Height / (float)tempMeterFrame.SourceRect.Height); + tempMeterFrame.Draw(spriteBatch, meterPos, Color.White, tempMeterFrame.Origin, 0.0f, scale: meterScale); - Rectangle graphArea = new Rectangle(container.Rect.X + 30, container.Rect.Y, container.Rect.Width - 30, container.Rect.Height); - - float maxLoad = loadGraph.Max(); - - float xOffset = graphTimer / updateGraphInterval; - DrawGraph(outputGraph, spriteBatch, - graphArea, Math.Max(10000.0f, maxLoad), xOffset, Color.LightGreen); - - DrawGraph(loadGraph, spriteBatch, - graphArea, Math.Max(10000.0f, maxLoad), xOffset, Color.LightBlue); - - tempMeterFrame.Draw(spriteBatch, new Vector2(graphArea.X - 30, graphArea.Y), Color.White, Vector2.Zero, 0.0f, new Vector2(1.0f, graphArea.Height / tempMeterFrame.size.Y)); float tempFill = temperature / 100.0f; - - int barPadding = 5; - Vector2 meterBarPos = new Vector2(graphArea.X - 30 + tempMeterFrame.size.X / 2, graphArea.Bottom - tempMeterBar.size.Y); - while (meterBarPos.Y > graphArea.Bottom - graphArea.Height * tempFill) + float meterBarScale = container.Rect.Width / (float)tempMeterBar.SourceRect.Width; + Vector2 meterBarPos = new Vector2(container.Center.X, container.Rect.Bottom - tempMeterBar.size.Y * meterBarScale - (int)(5 * GUI.yScale)); + while (meterBarPos.Y > container.Rect.Bottom + (int)(5 * GUI.yScale) - container.Rect.Height * tempFill) { - float tempRatio = 1.0f - ((meterBarPos.Y - graphArea.Y) / graphArea.Height); - Color color = tempRatio < 0.5f ? - Color.Lerp(Color.Green, Color.Orange, tempRatio * 2.0f) : - Color.Lerp(Color.Orange, Color.Red, (tempRatio - 0.5f) * 2.0f); - - tempMeterBar.Draw(spriteBatch, meterBarPos, color); - meterBarPos.Y -= (tempMeterBar.size.Y + barPadding); + float tempRatio = 1.0f - ((meterBarPos.Y - container.Rect.Y) / container.Rect.Height); + Color color = ToolBox.GradientLerp(tempRatio, coldColor, optimalRangeColor, warmColor, hotColor); + tempMeterBar.Draw(spriteBatch, meterBarPos, color: color, scale: meterBarScale); + int spacing = 2; + meterBarPos.Y -= tempMeterBar.size.Y * meterBarScale + spacing; } if (temperature > optimalTemperature.Y) { GUI.DrawRectangle(spriteBatch, - new Vector2(graphArea.X - 30, graphArea.Y), - new Vector2(tempMeterFrame.SourceRect.Width, (graphArea.Bottom - graphArea.Height * optimalTemperature.Y / 100.0f) - graphArea.Y), - Color.Red * (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.7f, isFilled: true); + meterPos, + new Vector2(container.Rect.Width, (container.Rect.Bottom - container.Rect.Height * optimalTemperature.Y / 100.0f) - container.Rect.Y), + warningColor * (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.7f, isFilled: true); } if (temperature < optimalTemperature.X) { GUI.DrawRectangle(spriteBatch, - new Vector2(graphArea.X - 30, graphArea.Bottom - graphArea.Height * optimalTemperature.X / 100.0f), - new Vector2(tempMeterFrame.SourceRect.Width, graphArea.Bottom - (graphArea.Bottom - graphArea.Height * optimalTemperature.X / 100.0f)), - Color.Red * (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.7f, isFilled: true); + new Vector2(meterPos.X, container.Rect.Bottom - container.Rect.Height * optimalTemperature.X / 100.0f), + new Vector2(container.Rect.Width, container.Rect.Bottom - (container.Rect.Bottom - container.Rect.Height * optimalTemperature.X / 100.0f)), + warningColor * (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.7f, isFilled: true); } - tempRangeIndicator.Draw(spriteBatch, new Vector2(meterBarPos.X, graphArea.Bottom - graphArea.Height * optimalTemperature.X / 100.0f)); - tempRangeIndicator.Draw(spriteBatch, new Vector2(meterBarPos.X, graphArea.Bottom - graphArea.Height * optimalTemperature.Y / 100.0f)); + float tempRangeIndicatorScale = container.Rect.Width / (float)tempRangeIndicator.SourceRect.Width; + tempRangeIndicator.Draw(spriteBatch, new Vector2(container.Center.X, container.Rect.Bottom - container.Rect.Height * optimalTemperature.X / 100.0f), Color.White, tempRangeIndicator.Origin, 0, scale: tempRangeIndicatorScale); + tempRangeIndicator.Draw(spriteBatch, new Vector2(container.Center.X, container.Rect.Bottom - container.Rect.Height * optimalTemperature.Y / 100.0f), Color.White, tempRangeIndicator.Origin, 0, scale: tempRangeIndicatorScale); + } + private void DrawGraph(SpriteBatch spriteBatch, GUICustomComponent container) + { + if (item.Removed) { return; } + float maxLoad = loadGraph.Max(); + float xOffset = graphTimer / updateGraphInterval; + Rectangle graphRect = new Rectangle(container.Rect.X, container.Rect.Y, container.Rect.Width, container.Rect.Height - (int)(5 * GUI.yScale)); + DrawGraph(outputGraph, spriteBatch, graphRect, Math.Max(10000.0f, maxLoad), xOffset, outputColor); + DrawGraph(loadGraph, spriteBatch, graphRect, Math.Max(10000.0f, maxLoad), xOffset, loadColor); } @@ -367,8 +453,8 @@ namespace Barotrauma.Items.Components if (autoTemp) { - fissionRateScrollBar.BarScroll = FissionRate / 100.0f; - turbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f; + FissionRateScrollBar.BarScroll = FissionRate / 100.0f; + TurbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f; } } @@ -411,10 +497,7 @@ namespace Barotrauma.Items.Components { IsActive = true; - bool lightOn = Timing.TotalTime % 0.5f < 0.25f && onOffSwitch.BarScroll < 0.5f; - - fissionRateScrollBar.Enabled = !autoTemp; - turbineOutputScrollBar.Enabled = !autoTemp; + bool lightOn = Timing.TotalTime % 0.5f < 0.25f && PowerOn; criticalHeatWarning.Selected = temperature > allowedTemperature.Y && lightOn; lowTemperatureWarning.Selected = temperature < allowedTemperature.X && lightOn; @@ -427,21 +510,19 @@ namespace Barotrauma.Items.Components warningButtons["ReactorWarningFuelOut"].Selected = prevAvailableFuel < fissionRate * 0.01f && lightOn; warningButtons["ReactorWarningLowFuel"].Selected = prevAvailableFuel < fissionRate && lightOn; warningButtons["ReactorWarningMeltdown"].Selected = meltDownTimer > MeltdownDelay * 0.5f || item.Condition == 0.0f && lightOn; - warningButtons["ReactorWarningSCRAM"].Selected = temperature > 0.1f && onOffSwitch.BarScroll > 0.5f; + warningButtons["ReactorWarningSCRAM"].Selected = temperature > 0.1f && !PowerOn; - AutoTemp = autoTempSlider.BarScroll < 0.5f; - shutDown = onOffSwitch.BarScroll > 0.5f; - - if ((sliderControlsContainer.Rect.Contains(PlayerInput.MousePosition) || sliderControlsContainer.Children.Contains(GUIScrollBar.DraggingBar)) && + if ((FissionRateScrollBar.Rect.Contains(PlayerInput.MousePosition) || FissionRateScrollBar.Children.Contains(GUIScrollBar.DraggingBar) || + TurbineOutputScrollBar.Rect.Contains(PlayerInput.MousePosition) || TurbineOutputScrollBar.Children.Contains(GUIScrollBar.DraggingBar)) && !PlayerInput.KeyDown(InputType.Deselect) && !PlayerInput.KeyHit(InputType.Deselect)) { Character.DisableControls = true; } - if (shutDown) + if (!PowerOn) { - fissionRateScrollBar.BarScroll = FissionRate / 100.0f; - turbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f; + FissionRateScrollBar.BarScroll = FissionRate / 100.0f; + TurbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f; } else if (!autoTemp && Character.DisableControls && GUI.KeyboardDispatcher.Subscriber == null) { @@ -465,29 +546,20 @@ namespace Barotrauma.Items.Components { LastUser = Character.Controlled; unsentChanges = true; - if (input.X != 0.0f && GUIScrollBar.DraggingBar != fissionRateScrollBar) + if (input.X != 0.0f && GUIScrollBar.DraggingBar != FissionRateScrollBar) { targetFissionRate = MathHelper.Clamp(targetFissionRate + input.X, 0.0f, 100.0f); - fissionRateScrollBar.BarScroll += input.X / 100.0f; + FissionRateScrollBar.BarScroll += input.X / 100.0f; } - if (input.Y != 0.0f && GUIScrollBar.DraggingBar != turbineOutputScrollBar) + if (input.Y != 0.0f && GUIScrollBar.DraggingBar != TurbineOutputScrollBar) { targetTurbineOutput = MathHelper.Clamp(targetTurbineOutput + input.Y, 0.0f, 100.0f); - turbineOutputScrollBar.BarScroll += input.Y / 100.0f; + TurbineOutputScrollBar.BarScroll += input.Y / 100.0f; } } } } - private bool ToggleAutoTemp(GUITickBox tickBox) - { - unsentChanges = true; - autoTemp = tickBox.Selected; - LastUser = Character.Controlled; - - return true; - } - private void DrawMeter(SpriteBatch spriteBatch, Rectangle rect, Sprite meterSprite, float value, Vector2 range, Vector2 optimalRange, Vector2 allowedRange) { float scale = Math.Min(rect.Width / meterSprite.size.X, rect.Height / meterSprite.size.Y); @@ -513,7 +585,7 @@ namespace Barotrauma.Items.Components if (optimalRangeNormalized.X == optimalRangeNormalized.Y) { - sectorSprite.Draw(spriteBatch, pos, Color.Red, MathHelper.PiOver2, scale); + sectorSprite.Draw(spriteBatch, pos, GUI.Style.Red, MathHelper.PiOver2, scale); } else { @@ -522,13 +594,12 @@ namespace Barotrauma.Items.Components spriteBatch.GraphicsDevice.ScissorRectangle = new Rectangle(0, 0, GameMain.GraphicsWidth, (int)(pos.Y + (meterSprite.size.Y - meterSprite.Origin.Y) * scale) - 3); spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable); - sectorSprite.Draw(spriteBatch, pos, Color.LightGreen, MathHelper.PiOver2 + (allowedSectorRad.X + allowedSectorRad.Y) / 2.0f, scale); - - sectorSprite.Draw(spriteBatch, pos, Color.Orange, optimalSectorRad.X, scale); - sectorSprite.Draw(spriteBatch, pos, Color.Red, allowedSectorRad.X, scale); - - sectorSprite.Draw(spriteBatch, pos, Color.Orange, MathHelper.Pi + optimalSectorRad.Y, scale); - sectorSprite.Draw(spriteBatch, pos, Color.Red, MathHelper.Pi + allowedSectorRad.Y, scale); + float scaleMultiplier = 0.95f; + sectorSprite.Draw(spriteBatch, pos, optimalRangeColor, MathHelper.PiOver2 + (allowedSectorRad.X + allowedSectorRad.Y) / 2.0f, scale * scaleMultiplier); + sectorSprite.Draw(spriteBatch, pos, offRangeColor, optimalSectorRad.X, scale * scaleMultiplier); + sectorSprite.Draw(spriteBatch, pos, warningColor, allowedSectorRad.X, scale * scaleMultiplier); + sectorSprite.Draw(spriteBatch, pos, offRangeColor, MathHelper.Pi + optimalSectorRad.Y, scale * scaleMultiplier); + sectorSprite.Draw(spriteBatch, pos, warningColor, MathHelper.Pi + allowedSectorRad.Y, scale * scaleMultiplier); spriteBatch.End(); spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect; @@ -539,7 +610,8 @@ namespace Barotrauma.Items.Components float normalizedValue = (value - range.X) / (range.Y - range.X); float valueRad = MathHelper.Lerp(sectorRad.X, sectorRad.Y, normalizedValue); - meterPointer.Draw(spriteBatch, pos, valueRad, scale); + Vector2 offset = new Vector2(0, 40) * scale; + meterPointer.Draw(spriteBatch, pos - offset, valueRad, scale); } static void UpdateGraph(IList graph, T newValue) @@ -561,8 +633,6 @@ namespace Barotrauma.Items.Components float lineWidth = (float)rect.Width / (float)(graph.Count - 2); float yScale = (float)rect.Height / maxVal; - GUI.DrawRectangle(spriteBatch, rect, Color.White); - Vector2 prevPoint = new Vector2(rect.Right, rect.Bottom - (graph[1] + (graph[0] - graph[1]) * xOffset) * yScale); float currX = rect.Right - ((xOffset - 1.0f) * lineWidth); @@ -619,7 +689,7 @@ namespace Barotrauma.Items.Components public void ClientWrite(IWriteMessage msg, object[] extraData = null) { msg.Write(autoTemp); - msg.Write(shutDown); + msg.Write(PowerOn); msg.WriteRangedSingle(targetFissionRate, 0.0f, 100.0f, 8); msg.WriteRangedSingle(targetTurbineOutput, 0.0f, 100.0f, 8); @@ -635,17 +705,41 @@ namespace Barotrauma.Items.Components } AutoTemp = msg.ReadBoolean(); - shutDown = msg.ReadBoolean(); + PowerOn = msg.ReadBoolean(); Temperature = msg.ReadRangedSingle(0.0f, 100.0f, 8); targetFissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); targetTurbineOutput = msg.ReadRangedSingle(0.0f, 100.0f, 8); degreeOfSuccess = msg.ReadRangedSingle(0.0f, 1.0f, 8); - fissionRateScrollBar.BarScroll = targetFissionRate / 100.0f; - turbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f; - onOffSwitch.BarScroll = shutDown ? Math.Max(onOffSwitch.BarScroll, 0.55f) : Math.Min(onOffSwitch.BarScroll, 0.45f); + FissionRateScrollBar.BarScroll = targetFissionRate / 100.0f; + TurbineOutputScrollBar.BarScroll = targetTurbineOutput / 100.0f; IsActive = true; } + + private void UpdateUIElementStates() + { + if (powerLight != null) + { + powerLight.Selected = _powerOn; + } + if (AutoTempSwitch != null) + { + AutoTempSwitch.Selected = autoTemp; + AutoTempSwitch.Enabled = _powerOn; + } + if (autoTempLight != null) + { + autoTempLight.Selected = autoTemp && _powerOn; + } + if (FissionRateScrollBar != null) + { + FissionRateScrollBar.Enabled = _powerOn && !autoTemp; + } + if (TurbineOutputScrollBar != null) + { + TurbineOutputScrollBar.Enabled = _powerOn && !autoTemp; + } + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs index 6a15f2930..0e9266229 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs @@ -6,30 +6,32 @@ using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using Barotrauma.Extensions; namespace Barotrauma.Items.Components { partial class Sonar : Powered, IServerSerializable, IClientSerializable { + public enum BlipType + { + Default, + Disruption + } + private bool dynamicDockingIndicator = true; private bool unsentChanges; private float networkUpdateTimer; - public GUITickBox ActiveTickBox - { - get { return activeTickBox; } - } + public GUIButton SonarModeSwitch { get; private set; } private GUITickBox activeTickBox, passiveTickBox; private GUITextBlock signalWarningText; private GUIScrollBar zoomSlider; - private GUITickBox directionalTickBox; - private GUIScrollBar directionalSlider; + private GUIButton directionalModeSwitch; private Vector2? pingDragDirection = null; - private GUILayoutGroup activeControlsContainer; private GUIFrame controlContainer; private GUICustomComponent sonarView; @@ -54,21 +56,32 @@ namespace Barotrauma.Items.Components private Vector2 center; private float displayScale; + private const float DisruptionUpdateInterval = 0.2f; + private float disruptionUpdateTimer; + private float zoomSqrt; private float showDirectionalIndicatorTimer; - + //Vector2 = vector from the ping source to the position of the disruption //float = strength of the disruption, between 0-1 List> disruptedDirections = new List>(); - - private static readonly Color[] blipColorGradient = + + private readonly Color positiveColor = Color.Green; + private readonly Color warningColor = Color.Orange; + private readonly Color negativeColor = Color.Red; + private readonly Color markerColor = Color.Red; + + private static readonly Dictionary blipColorGradient = new Dictionary() { - Color.TransparentBlack, - new Color(0, 50, 160), - new Color(0, 133, 166), - new Color(2, 159, 30), - new Color(255, 255, 255) + { + BlipType.Default, + new Color[] { Color.TransparentBlack, new Color(0, 50, 160), new Color(0, 133, 166), new Color(2, 159, 30), new Color(255, 255, 255) } + }, + { + BlipType.Disruption, + new Color[] { Color.TransparentBlack, new Color(254, 68, 19), new Color(255, 220, 62), new Color(255, 255, 255) } + } }; private float prevDockingDist; @@ -79,102 +92,8 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific(XElement element) { + System.Diagnostics.Debug.Assert(Enum.GetValues(typeof(BlipType)).Cast().All(t => blipColorGradient.ContainsKey(t))); sonarBlips = new List(); - - sonarView = new GUICustomComponent(new RectTransform(Point.Zero, GuiFrame.RectTransform, Anchor.CenterLeft), - (spriteBatch, guiCustomComponent) => { DrawSonar(spriteBatch, guiCustomComponent.Rect); }, null); - - controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), GuiFrame.RectTransform, Anchor.TopLeft) - { MinSize = new Point(150, 0) }, "SonarFrame"); - - controlContainer.RectTransform.SetAsFirstChild(); - - var paddedControlContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), controlContainer.RectTransform, Anchor.Center)) - { - RelativeSpacing = 0.03f, - Stretch = true - }; - - passiveTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.2f), paddedControlContainer.RectTransform), TextManager.Get("SonarPassive"), style: "GUIRadioButton") - { - ToolTip = TextManager.Get("SonarTipPassive"), - Selected = true - }; - - activeTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.2f), paddedControlContainer.RectTransform), TextManager.Get("SonarActive"), style: "GUIRadioButton") - { - ToolTip = TextManager.Get("SonarTipActive"), - OnSelected = (GUITickBox box) => - { - CurrentMode = box.Selected ? Mode.Active : Mode.Passive; - if (GameMain.Client != null) - { - unsentChanges = true; - correctionTimer = CorrectionDelay; - } - return true; - } - }; - - var zoomContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), paddedControlContainer.RectTransform), isHorizontal: true); - new GUITextBlock(new RectTransform(new Vector2(0.35f, 1.0f), zoomContainer.RectTransform), TextManager.Get("SonarZoom"), font: GUI.SmallFont) - { - Padding = Vector4.Zero - }; - zoomSlider = new GUIScrollBar(new RectTransform(new Vector2(0.65f, 1.0f), zoomContainer.RectTransform), barSize: 0.1f, isHorizontal: true) - { - OnMoved = (scrollbar, scroll) => - { - zoom = MathHelper.Lerp(MinZoom, MaxZoom, scroll); - if (GameMain.Client != null) - { - unsentChanges = true; - correctionTimer = CorrectionDelay; - } - return true; - } - }; - - var activeControls = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.6f), paddedControlContainer.RectTransform) { RelativeOffset = new Vector2(0.1f, 0.0f) }, "InnerFrame"); - activeControlsContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), activeControls.RectTransform, Anchor.Center)) - { - RelativeSpacing = 0.03f, - Stretch = true - }; - - directionalTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), activeControlsContainer.RectTransform), TextManager.Get("SonarDirectionalPing")) - { - OnSelected = (tickBox) => - { - useDirectionalPing = tickBox.Selected; - if (GameMain.Client != null) - { - unsentChanges = true; - correctionTimer = CorrectionDelay; - } - return true; - } - }; - directionalSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.3f), activeControlsContainer.RectTransform), barSize: 0.1f, isHorizontal: true) - { - OnMoved = (scrollbar, scroll) => - { - showDirectionalIndicatorTimer = 1.0f; - float pingAngle = MathHelper.Lerp(0.0f, MathHelper.TwoPi, scroll); - SetPingDirection(new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle))); - return true; - }, - Range = new Vector2(0,MathHelper.TwoPi) - }; - - signalWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedControlContainer.RectTransform), "", Color.Orange, textAlignment: Alignment.Center); - - GUIRadioButtonGroup sonarMode = new GUIRadioButtonGroup(); - sonarMode.AddRadioButton((int)Mode.Active, activeTickBox); - sonarMode.AddRadioButton((int)Mode.Passive, passiveTickBox); - sonarMode.Selected = (int)Mode.Passive; - - GuiFrame.CanBeFocused = false; foreach (XElement subElement in element.Elements()) { @@ -212,20 +131,125 @@ namespace Barotrauma.Items.Components break; } } - - SetUILayout(); - - GameMain.Instance.OnResolutionChanged += SetUILayout; - GameMain.Config.OnHUDScaleChanged += SetUILayout; + CreateGUI(); + GameMain.Instance.OnResolutionChanged += ResetLayout; + // TODO: do we need to react on this? + GameMain.Config.OnHUDScaleChanged += ResetLayout; } - private void SetUILayout() + private void ResetLayout() { - int viewSize = (int)Math.Min(GuiFrame.Rect.Width - 150, GuiFrame.Rect.Height * 0.9f); - sonarView.RectTransform.NonScaledSize = new Point(viewSize); - controlContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0); + GuiFrame.RectTransform.Children.ForEachMod(c => c.Parent = null); + CreateGUI(); } + private void CreateGUI() + { + controlContainer = new GUIFrame(new RectTransform(new Vector2(controlContainerRelativeWidth, 0.32f), GuiFrame.RectTransform, Anchor.TopRight) + { + RelativeOffset = new Vector2(controlContainerRelativeOffset, 0) + }, "ItemUI"); + + var paddedControlContainer = new GUIFrame(new RectTransform(controlContainer.Rect.Size - GUIStyle.ItemFrameMargin, controlContainer.RectTransform, Anchor.Center) + { + AbsoluteOffset = GUIStyle.ItemFrameOffset + }, style: null); + var sonarModeArea = new GUIFrame(new RectTransform(new Vector2(1, 0.5f), paddedControlContainer.RectTransform, Anchor.TopCenter), style: null); + SonarModeSwitch = new GUIButton(new RectTransform(new Vector2(0.2f, 1), sonarModeArea.RectTransform), string.Empty, style: "SwitchVertical") + { + Selected = false, + Enabled = true, + OnClicked = (button, data) => + { + button.Selected = !button.Selected; + CurrentMode = button.Selected ? Mode.Active : Mode.Passive; + if (GameMain.Client != null) + { + unsentChanges = true; + correctionTimer = CorrectionDelay; + } + return true; + } + }; + var sonarModeRightSide = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.8f), sonarModeArea.RectTransform, Anchor.CenterLeft) + { + RelativeOffset = new Vector2(SonarModeSwitch.RectTransform.RelativeSize.X, 0) + }, style: null); + passiveTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), sonarModeRightSide.RectTransform, Anchor.TopLeft), + TextManager.Get("SonarPassive"), font: GUI.SubHeadingFont, style: "IndicatorLightRedSmall") + { + ToolTip = TextManager.Get("SonarTipPassive"), + Selected = true, + Enabled = false + }; + activeTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), sonarModeRightSide.RectTransform, Anchor.BottomLeft), + TextManager.Get("SonarActive"), font: GUI.SubHeadingFont, style: "IndicatorLightRedSmall") + { + ToolTip = TextManager.Get("SonarTipActive"), + Selected = false, + Enabled = false + }; + passiveTickBox.TextBlock.OverrideTextColor(GUI.Style.TextColor); + activeTickBox.TextBlock.OverrideTextColor(GUI.Style.TextColor); + + var zoomContainer = new GUIFrame(new RectTransform(new Vector2(1, 0.2f), paddedControlContainer.RectTransform, Anchor.TopCenter) + { + RelativeOffset = new Vector2(0, sonarModeArea.RectTransform.RelativeSize.Y + 0.025f) + }, style: null); + new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.6f), zoomContainer.RectTransform, Anchor.CenterLeft), + TextManager.Get("SonarZoom"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterRight); + zoomSlider = new GUIScrollBar(new RectTransform(new Vector2(0.6f, 0.8f), zoomContainer.RectTransform, Anchor.CenterLeft) + { + RelativeOffset = new Vector2(0.35f, 0) + }, barSize: 0.15f, isHorizontal: true, style: "DeviceSlider") + { + OnMoved = (scrollbar, scroll) => + { + zoom = MathHelper.Lerp(MinZoom, MaxZoom, scroll); + if (GameMain.Client != null) + { + unsentChanges = true; + correctionTimer = CorrectionDelay; + } + return true; + } + }; + + var directionalModeFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.2f), paddedControlContainer.RectTransform, Anchor.BottomCenter), style: null); + new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), directionalModeFrame.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) + { + RelativeOffset = new Vector2(0, -0.15f) + }, style: "HorizontalLine"); + directionalModeSwitch = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), directionalModeFrame.RectTransform, Anchor.CenterLeft), string.Empty, style: "SwitchHorizontal") + { + OnClicked = (button, data) => + { + useDirectionalPing = !useDirectionalPing; + button.Selected = useDirectionalPing; + if (GameMain.Client != null) + { + unsentChanges = true; + correctionTimer = CorrectionDelay; + } + return true; + } + }; + var directionalModeSwitchText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1), directionalModeFrame.RectTransform, Anchor.CenterRight), + TextManager.Get("SonarDirectionalPing"), GUI.Style.TextColor, GUI.SubHeadingFont, Alignment.CenterLeft); + + signalWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedControlContainer.RectTransform), "", warningColor, textAlignment: Alignment.Center); + + GuiFrame.CanBeFocused = false; + + sonarView = new GUICustomComponent(new RectTransform(SonarAreaSize, GuiFrame.RectTransform, Anchor.CenterLeft), + (spriteBatch, guiCustomComponent) => { DrawSonar(spriteBatch, guiCustomComponent.Rect); }, null); + sonarView.RectTransform.SetAsFirstChild(); + } + + public static readonly float controlContainerRelativeWidth = 0.35f; + public static readonly float controlContainerRelativeOffset = 0.1f; + public static Vector2 SonarAreaSize => Vector2.One - new Vector2(controlContainerRelativeWidth + controlContainerRelativeOffset); + private void SetPingDirection(Vector2 direction) { pingDirection = direction; @@ -278,15 +302,7 @@ namespace Barotrauma.Items.Components sonarBlips[i].FadeTimer -= deltaTime * MathHelper.Lerp(0.5f, 2.0f, distort); sonarBlips[i].Position += sonarBlips[i].Velocity * deltaTime; - if (sonarBlips[i].FadeTimer <= 0.0f) sonarBlips.RemoveAt(i); - } - - foreach (GUIComponent component in activeControlsContainer.Parent.GetAllChildren()) - { - if (component is GUITextBlock textBlock) - { - textBlock.TextColor = currentMode == Mode.Active ? textBlock.Style.textColor : textBlock.Style.textColor * 0.5f; - } + if (sonarBlips[i].FadeTimer <= 0.0f) { sonarBlips.RemoveAt(i); } } //sonar view can only get focus when the cursor is inside the circle @@ -415,44 +431,46 @@ namespace Barotrauma.Items.Components null; } - if (useDirectionalPing && PlayerInput.PrimaryMouseButtonHeld()) + if (useDirectionalPing) { - if ((MouseInDirectionalPingRing(sonarView.Rect, false) && PlayerInput.PrimaryMouseButtonDown()) || pingDragDirection != null) + Vector2 newDragDir = Vector2.Normalize(PlayerInput.MousePosition - sonarView.Rect.Center.ToVector2()); + if (MouseInDirectionalPingRing(sonarView.Rect, true) && PlayerInput.PrimaryMouseButtonDown()) { - Vector2 newDragDir = Vector2.Normalize(PlayerInput.MousePosition - sonarView.Rect.Center.ToVector2()); - if (pingDragDirection == null && !MouseInDirectionalPingRing(sonarView.Rect, true)) - { - directionalSlider.BarScrollValue = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(newDragDir)); - directionalSlider.OnMoved(directionalSlider, directionalSlider.BarScroll); - } - else if (pingDragDirection != null) - { - float newAngle = MathUtils.VectorToAngle(newDragDir); - float oldAngle = MathUtils.VectorToAngle(pingDragDirection.Value); - float pingAngle = MathUtils.VectorToAngle(pingDirection); - pingAngle = MathUtils.WrapAngleTwoPi(pingAngle + MathUtils.GetShortestAngle(oldAngle, newAngle)); - directionalSlider.BarScrollValue = pingAngle; - directionalSlider.OnMoved(directionalSlider, directionalSlider.BarScroll); - } - pingDragDirection = newDragDir; } + + if (pingDragDirection != null && PlayerInput.PrimaryMouseButtonHeld()) + { + float newAngle = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(newDragDir)); + SetPingDirection(new Vector2((float)Math.Cos(newAngle), (float)Math.Sin(newAngle))); + } + else + { + pingDragDirection = null; + } } else { pingDragDirection = null; } + + disruptionUpdateTimer -= deltaTime; for (var pingIndex = 0; pingIndex < activePingsCount; ++pingIndex) { var activePing = activePings[pingIndex]; float pingRadius = DisplayRadius * activePing.State / zoom; - UpdateDisruptions(transducerCenter, pingRadius / displayScale, activePing.PrevPingRadius / displayScale); + if (disruptionUpdateTimer <= 0.0f) { UpdateDisruptions(transducerCenter, pingRadius / displayScale); } Ping(transducerCenter, transducerCenter, pingRadius, activePing.PrevPingRadius, displayScale, range / zoom, passive: false, pingStrength: 2.0f); activePing.PrevPingRadius = pingRadius; - } + + if (disruptionUpdateTimer <= 0.0f) + { + disruptionUpdateTimer = DisruptionUpdateInterval; + } + if (currentMode == Mode.Active && currentPingIndex != -1) { return; @@ -464,7 +482,7 @@ namespace Barotrauma.Items.Components disruptedDirections.Clear(); foreach (AITarget t in AITarget.List) { - if (t.SoundRange <= 0.0f || !t.Enabled) { continue; } + if (t.SoundRange <= 0.0f || !t.Enabled || float.IsNaN(t.SoundRange) || float.IsInfinity(t.SoundRange)) { continue; } float distSqr = Vector2.DistanceSquared(t.WorldPosition, transducerCenter); if (distSqr > t.SoundRange * t.SoundRange * 2) { continue; } @@ -610,7 +628,7 @@ namespace Barotrauma.Items.Components if (signalStrength <= 0.5f) { signalWarningText.Text = TextManager.Get(signalStrength <= 0.0f ? "SonarNoSignal" : "SonarSignalWeak"); - signalWarningText.Color = signalStrength <= 0.0f ? Color.Red : Color.Orange; + signalWarningText.Color = signalStrength <= 0.0f ? negativeColor : warningColor; signalWarningText.Visible = true; } else @@ -796,7 +814,7 @@ namespace Barotrauma.Items.Components size.Y = 0.0f; } GUI.DrawLine(spriteBatch, center + offset - size - Vector2.Normalize(size) * zoom, center + offset + size + Vector2.Normalize(size) * zoom, Color.Black * signalStrength * 0.5f, width: (int)(zoom * 5.0f)); - GUI.DrawLine(spriteBatch, center + offset - size, center + offset + size, Color.LightGreen * signalStrength, width: (int)(zoom * 2.5f)); + GUI.DrawLine(spriteBatch, center + offset - size, center + offset + size, positiveColor * signalStrength, width: (int)(zoom * 2.5f)); } } @@ -845,7 +863,7 @@ namespace Barotrauma.Items.Components Vector2 midNormal = new Vector2(-normalizedDockingDir.Y, normalizedDockingDir.X); - DrawLine(spriteBatch, targetPortPos, targetPortPos + normalizedDockingDir * midLength, readyToDock ? Color.LightGreen : staticLineColor, width: 2); + DrawLine(spriteBatch, targetPortPos, targetPortPos + normalizedDockingDir * midLength, readyToDock ? positiveColor : staticLineColor, width: 2); DrawLine(spriteBatch, targetPortPos, targetPortPos + MathUtils.RotatePoint(normalizedDockingDir, sector) * sectorLength, staticLineColor, width: 2); DrawLine(spriteBatch, targetPortPos, @@ -859,7 +877,7 @@ namespace Barotrauma.Items.Components if (readyToDock) { - Color indicatorColor = Color.LightGreen * 0.8f; + Color indicatorColor = positiveColor * 0.8f; float indicatorSize = (float)Math.Sin((float)Timing.TotalTime * 5.0f) * DisplayRadius * 0.75f; Vector2 midPoint = (sourcePortPos + targetPortPos) / 2.0f; @@ -882,7 +900,8 @@ namespace Barotrauma.Items.Components Vector2.Dot(normalizedDockingDir, MathUtils.RotatePoint(normalizedDockingDir, indicatorSector)) < Vector2.Dot(normalizedDockingDir, Vector2.Normalize(dockingDir)); - Color indicatorColor = withinSector ? Color.LightGreen * 0.8f : Color.Red * 0.8f; + Color indicatorColor = withinSector ? positiveColor : negativeColor; + indicatorColor *= 0.8f; DrawLine(spriteBatch, targetPortPos, targetPortPos + MathUtils.RotatePoint(normalizedDockingDir,indicatorSector) * indicatorSectorLength, indicatorColor, width: 3); @@ -892,7 +911,7 @@ namespace Barotrauma.Items.Components } - private void UpdateDisruptions(Vector2 pingSource, float worldPingRadius, float worldPrevPingRadius) + private void UpdateDisruptions(Vector2 pingSource, float worldPingRadius) { float worldPingRadiusSqr = worldPingRadius * worldPingRadius; @@ -912,10 +931,8 @@ namespace Barotrauma.Items.Components float disruptionDist = Vector2.Distance(pingSource, disruptionPos); disruptedDirections.Add(new Pair((disruptionPos - pingSource) / disruptionDist, disruptionStrength)); - if (disruptionDist > worldPrevPingRadius && disruptionDist <= worldPingRadius) - { - CreateBlipsForDisruption(disruptionPos, disruptionStrength); - } + CreateBlipsForDisruption(disruptionPos, disruptionStrength); + } foreach (AITarget aiTarget in AITarget.List) { @@ -926,18 +943,23 @@ namespace Barotrauma.Items.Components float disruptionDist = (float)Math.Sqrt(distSqr); disruptedDirections.Add(new Pair((aiTarget.WorldPosition - pingSource) / disruptionDist, aiTarget.SonarDisruption)); - if (disruptionDist > worldPrevPingRadius && disruptionDist <= worldPingRadius) - { - CreateBlipsForDisruption(aiTarget.WorldPosition, aiTarget.SonarDisruption); - } + CreateBlipsForDisruption(aiTarget.WorldPosition, aiTarget.SonarDisruption); } } void CreateBlipsForDisruption(Vector2 disruptionPos, float disruptionStrength) { - for (int i = 0; i < disruptionStrength * Level.GridCellSize * 0.02f; i++) + disruptionStrength = Math.Min(disruptionStrength, 10.0f); + Vector2 dir = disruptionPos - pingSource; + for (int i = 0; i < disruptionStrength * 10.0f; i++) { - var blip = new SonarBlip(disruptionPos + Rand.Vector(Rand.Range(0.0f, Level.GridCellSize * 4 * disruptionStrength)), MathHelper.Lerp(1.0f, 1.5f, disruptionStrength), Rand.Range(1.0f, 2.0f + disruptionStrength)); + Vector2 pos = disruptionPos + Rand.Vector(Rand.Range(0.0f, Level.GridCellSize * 4 * disruptionStrength)); + if (Vector2.Dot(pos - pingSource, -dir) > 1.0f - disruptionStrength) { continue; } + var blip = new SonarBlip( + pos, + MathHelper.Lerp(0.1f, 1.5f, Math.Min(disruptionStrength, 1.0f)), + Rand.Range(0.2f, 1.0f + disruptionStrength), + BlipType.Disruption); sonarBlips.Add(blip); } } @@ -1143,6 +1165,8 @@ namespace Barotrauma.Items.Components Vector2 lineDir = (point2 - point1) / length; for (float x = 0; x < length; x += lineStep * Rand.Range(0.8f, 1.2f)) { + if (Rand.Int(sonarBlips.Count) > 500) { continue; } + Vector2 point = point1 + lineDir * x; //ignore if outside the display @@ -1253,7 +1277,7 @@ namespace Barotrauma.Items.Components Vector2 dir = pos / (float)Math.Sqrt(posDistSqr); Vector2 normal = new Vector2(dir.Y, -dir.X); float scale = (strength + 3.0f) * blip.Scale * zoomSqrt; - Color color = ToolBox.GradientLerp(strength, blipColorGradient); + Color color = ToolBox.GradientLerp(strength, blipColorGradient[blip.BlipType]); sonarBlip.Draw(spriteBatch, center + pos, color, sonarBlip.Origin, blip.Rotation ?? MathUtils.VectorToAngle(pos), blip.Size * scale * 0.04f, SpriteEffects.None, 0); @@ -1304,7 +1328,7 @@ namespace Barotrauma.Items.Components if (string.IsNullOrEmpty(iconIdentifier) || !targetIcons.ContainsKey(iconIdentifier)) { - GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X - 3, (int)markerPos.Y - 3, 6, 6), Color.Red, thickness: 2); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X - 3, (int)markerPos.Y - 3, 6, 6), markerColor, thickness: 2); } else { @@ -1355,7 +1379,8 @@ namespace Barotrauma.Items.Components msg.Write(useDirectionalPing); if (useDirectionalPing) { - msg.WriteRangedSingle(directionalSlider.BarScroll, 0.0f, 1.0f, 8); + float pingAngle = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(pingDirection)); + msg.WriteRangedSingle(MathUtils.InverseLerp(0.0f, MathHelper.TwoPi, pingAngle), 0.0f, 1.0f, 8); } } } @@ -1380,7 +1405,7 @@ namespace Barotrauma.Items.Components if (correctionTimer > 0.0f) { - int msgLength = (int)(msg.BitPosition - msgStartPos); + int msgLength = msg.BitPosition - msgStartPos; msg.BitPosition = msgStartPos; StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime); return; @@ -1389,22 +1414,25 @@ namespace Barotrauma.Items.Components CurrentMode = isActive ? Mode.Active : Mode.Passive; if (isActive) { - activeTickBox.Selected = true; zoomSlider.BarScroll = zoomT; zoom = MathHelper.Lerp(MinZoom, MaxZoom, zoomT); if (directionalPing) { - directionalSlider.BarScroll = directionT; - float pingAngle = MathHelper.Lerp(0.0f, MathHelper.TwoPi, directionalSlider.BarScroll); + float pingAngle = MathHelper.Lerp(0.0f, MathHelper.TwoPi, directionT); pingDirection = new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle)); } - useDirectionalPing = directionalTickBox.Selected = directionalPing; - } - else - { - passiveTickBox.Selected = true; + useDirectionalPing = directionalModeSwitch.Selected = directionalPing; } } + + private void UpdateGUIElements() + { + bool isActive = CurrentMode == Mode.Active; + SonarModeSwitch.Selected = isActive; + passiveTickBox.Selected = !isActive; + activeTickBox.Selected = isActive; + directionalModeSwitch.Selected = useDirectionalPing; + } } class SonarBlip @@ -1415,13 +1443,15 @@ namespace Barotrauma.Items.Components public Vector2 Velocity; public float? Rotation; public Vector2 Size; + public Sonar.BlipType BlipType; - public SonarBlip(Vector2 pos, float fadeTimer, float scale) + public SonarBlip(Vector2 pos, float fadeTimer, float scale, Sonar.BlipType blipType = Sonar.BlipType.Default) { Position = pos; FadeTimer = Math.Max(fadeTimer, 0.0f); Scale = scale; Size = new Vector2(0.5f, 1.0f); + BlipType = blipType; } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs index c5f0d16f4..d3a5447a7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs @@ -7,17 +7,14 @@ using System; using System.Linq; using System.Collections.Generic; using System.Xml.Linq; +using Barotrauma.Extensions; namespace Barotrauma.Items.Components { partial class Steering : Powered, IServerSerializable, IClientSerializable { - enum Mode - { - AutoPilot, - Manual - }; - private GUITickBox autopilotTickBox, manualTickBox; + private GUIButton steeringModeSwitch; + private GUITickBox autopilotIndicator, manualPilotIndicator; enum Destination { @@ -34,8 +31,6 @@ namespace Barotrauma.Items.Components private GUIButton dockingButton; private string dockText, undockText; - private GUIFrame autoPilotControlsDisabler; - private GUIComponent steerArea; private GUITextBlock pressureWarningText; @@ -92,67 +87,84 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific(XElement element) { - controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), GuiFrame.RectTransform, Anchor.CenterLeft) - { MinSize = new Point(150, 0) }, "SonarFrame"); - var paddedControlContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), controlContainer.RectTransform, Anchor.Center)) + foreach (XElement subElement in element.Elements()) { - RelativeSpacing = 0.03f, - Stretch = true - }; + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "steeringindicator": + steeringIndicator = new Sprite(subElement); + break; + case "maintainposindicator": + maintainPosIndicator = new Sprite(subElement); + break; + case "maintainposoriginindicator": + maintainPosOriginIndicator = new Sprite(subElement); + break; + } + } + CreateGUI(); + GameMain.Instance.OnResolutionChanged += ResetGUI; + // TODO: do we need to react on this? + GameMain.Config.OnHUDScaleChanged += ResetGUI; + } - statusContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft) - { MinSize = new Point(150, 0) }, "SonarFrame"); - var paddedStatusContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), statusContainer.RectTransform, Anchor.Center)) + private void CreateGUI() + { + controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.36f), GuiFrame.RectTransform, Anchor.CenterRight) { - RelativeSpacing = 0.03f, - Stretch = true - }; + RelativeOffset = new Vector2(Sonar.controlContainerRelativeOffset / 2, 0.01f) // Based on the relative size differende of the steering and the status windows + }, "ItemUI"); + var paddedControlContainer = new GUIFrame(new RectTransform(controlContainer.Rect.Size - GUIStyle.ItemFrameMargin, controlContainer.RectTransform, Anchor.Center) + { + AbsoluteOffset = GUIStyle.ItemFrameOffset + }, style: null); - manualTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform), - TextManager.Get("SteeringManual"), style: "GUIRadioButton") + var steeringModeArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f), paddedControlContainer.RectTransform, Anchor.TopLeft), style: null); + steeringModeSwitch = new GUIButton(new RectTransform(new Vector2(0.2f, 1), steeringModeArea.RectTransform), string.Empty, style: "SwitchVertical") + { + Selected = false, + Enabled = true, + OnClicked = (button, data) => + { + button.Selected = !button.Selected; + AutoPilot = button.Selected; + if (GameMain.Client != null) + { + unsentChanges = true; + user = Character.Controlled; + } + return true; + } + }; + var steeringModeRightSide = new GUIFrame(new RectTransform(new Vector2(1.0f - steeringModeSwitch.RectTransform.RelativeSize.X, 0.8f), steeringModeArea.RectTransform, Anchor.CenterLeft) + { + RelativeOffset = new Vector2(steeringModeSwitch.RectTransform.RelativeSize.X, 0) + }, style: null); + manualPilotIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), steeringModeRightSide.RectTransform, Anchor.TopLeft), + TextManager.Get("SteeringManual"), font: GUI.SubHeadingFont, style: "IndicatorLightRedSmall") { Selected = true, - OnSelected = (GUITickBox box) => - { - AutoPilot = !box.Selected; - unsentChanges = true; - user = Character.Controlled; - - return true; - } + Enabled = false }; - autopilotTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform), - TextManager.Get("SteeringAutoPilot"), style: "GUIRadioButton") + autopilotIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.45f), steeringModeRightSide.RectTransform, Anchor.BottomLeft), + TextManager.Get("SteeringAutoPilot"), font: GUI.SubHeadingFont, style: "IndicatorLightRedSmall") { - OnSelected = (GUITickBox box) => - { - AutoPilot = box.Selected; - if (AutoPilot && MaintainPos) - { - posToMaintain = controlledSub != null ? - controlledSub.WorldPosition : - item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; - } - unsentChanges = true; - user = Character.Controlled; - - return true; - } + Selected = false, + Enabled = false }; + manualPilotIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); + autopilotIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); + GUITextBlock.AutoScaleAndNormalize(manualPilotIndicator.TextBlock, autopilotIndicator.TextBlock); - GUIRadioButtonGroup modes = new GUIRadioButtonGroup(); - modes.AddRadioButton((int)Mode.AutoPilot, autopilotTickBox); - modes.AddRadioButton((int)Mode.Manual, manualTickBox); - modes.Selected = (int)Mode.Manual; - - var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), paddedControlContainer.RectTransform), "InnerFrame"); - var paddedAutoPilotControls = new GUILayoutGroup(new RectTransform(new Vector2(0.8f), autoPilotControls.RectTransform, Anchor.Center)) + var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(0.8f, 0.6f), paddedControlContainer.RectTransform, Anchor.BottomRight), "OutlineFrame"); + var paddedAutoPilotControls = new GUILayoutGroup(new RectTransform(new Vector2(0.9f), autoPilotControls.RectTransform, Anchor.Center)) { Stretch = true, - RelativeSpacing = 0.03f + RelativeSpacing = 0.03f, + ChildAnchor = Anchor.TopCenter }; - maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform), + maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.2f), paddedAutoPilotControls.RectTransform), TextManager.Get("SteeringMaintainPos"), font: GUI.SmallFont, style: "GUIRadioButton") { Enabled = false, @@ -188,7 +200,7 @@ namespace Barotrauma.Items.Components } }; - levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform), + levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.2f), paddedAutoPilotControls.RectTransform), GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, 20), font: GUI.SmallFont, style: "GUIRadioButton") { @@ -215,7 +227,7 @@ namespace Barotrauma.Items.Components } }; - levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), paddedAutoPilotControls.RectTransform), + levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.2f), paddedAutoPilotControls.RectTransform), GameMain.GameSession?.EndLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, 20), font: GUI.SmallFont, style: "GUIRadioButton") { @@ -242,53 +254,103 @@ namespace Barotrauma.Items.Components } }; - autoPilotControlsDisabler = new GUIFrame(new RectTransform(Vector2.One, autoPilotControls.RectTransform), "InnerFrame"); + GUITextBlock.AutoScaleAndNormalize(maintainPosTickBox.TextBlock, levelStartTickBox.TextBlock, levelEndTickBox.TextBlock); + maintainPosTickBox.RectTransform.IsFixedSize = levelStartTickBox.RectTransform.IsFixedSize = levelEndTickBox.RectTransform.IsFixedSize = false; + maintainPosTickBox.RectTransform.MaxSize = levelStartTickBox.RectTransform.MaxSize = levelEndTickBox.RectTransform.MaxSize = + new Point(int.MaxValue, paddedAutoPilotControls.Rect.Height / 3); + maintainPosTickBox.RectTransform.MinSize = levelStartTickBox.RectTransform.MinSize = levelEndTickBox.RectTransform.MinSize = + Point.Zero; GUIRadioButtonGroup destinations = new GUIRadioButtonGroup(); destinations.AddRadioButton((int)Destination.MaintainPos, maintainPosTickBox); destinations.AddRadioButton((int)Destination.LevelStart, levelStartTickBox); destinations.AddRadioButton((int)Destination.LevelEnd, levelEndTickBox); - destinations.Selected = (int)(maintainPos ? Destination.MaintainPos : - levelStartSelected ? Destination.LevelStart : Destination.LevelEnd); - - string steeringVelX = TextManager.Get("SteeringVelocityX"); - string steeringVelY = TextManager.Get("SteeringVelocityY"); - string steeringDepth = TextManager.Get("SteeringDepth"); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), "") - { - TextGetter = () => - { - Vector2 vel = controlledSub == null ? Vector2.Zero : controlledSub.Velocity; - var realWorldVel = ConvertUnits.ToDisplayUnits(vel.Y * Physics.DisplayToRealWorldRatio) * 3.6f; - return steeringVelY.Replace("[kph]", ((int)-realWorldVel).ToString()); - } - }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), "") - { - TextGetter = () => - { - Vector2 vel = controlledSub == null ? Vector2.Zero : controlledSub.Velocity; - var realWorldVel = ConvertUnits.ToDisplayUnits(vel.X * Physics.DisplayToRealWorldRatio) * 3.6f; - return steeringVelX.Replace("[kph]", ((int)realWorldVel).ToString()); - } - }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), "") - { - TextGetter = () => - { - Vector2 pos = controlledSub == null ? Vector2.Zero : controlledSub.Position; - float realWorldDepth = Level.Loaded == null ? 0.0f : Math.Abs(pos.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio; - return steeringDepth.Replace("[m]", ((int)realWorldDepth).ToString()); - } - }; + destinations.Selected = (int)(maintainPos ? Destination.MaintainPos : + levelStartSelected ? Destination.LevelStart : Destination.LevelEnd); - pressureWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), TextManager.Get("SteeringDepthWarning"), Color.Red) + // Status -> + statusContainer = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.3f), GuiFrame.RectTransform, Anchor.BottomRight) + { + RelativeOffset = new Vector2(Sonar.controlContainerRelativeOffset, 0) + }, "ItemUI"); + var paddedStatusContainer = new GUIFrame(new RectTransform(statusContainer.Rect.Size - GUIStyle.ItemFrameMargin, statusContainer.RectTransform, Anchor.Center) + { + AbsoluteOffset = GUIStyle.ItemFrameOffset + }, style: null); + + var elements = GUI.CreateElements(3, new Vector2(1f, 0.323f), paddedStatusContainer.RectTransform, rt => new GUIFrame(rt, style: null), Anchor.TopCenter, relativeSpacing: 0.01f); + List leftElements = new List(), centerElements = new List(), rightElements = new List(); + for (int i = 0; i < elements.Count; i++) + { + var e = elements[i]; + var group = new GUILayoutGroup(new RectTransform(Vector2.One, e.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + RelativeSpacing = 0.01f, + Stretch = true + }; + var left = new GUIFrame(new RectTransform(new Vector2(0.5f, 1), group.RectTransform), style: null); + var center = new GUIFrame(new RectTransform(new Vector2(0.175f, 1), group.RectTransform), style: null); + var right = new GUIFrame(new RectTransform(new Vector2(0.325f, 0.8f), group.RectTransform), style: null); + leftElements.Add(left); + centerElements.Add(center); + rightElements.Add(right); + string leftText = string.Empty, centerText = string.Empty; + GUITextBlock.TextGetterHandler rightTextGetter = null; + switch (i) + { + case 0: + leftText = TextManager.Get("DescentVelocity"); + centerText = $"({TextManager.Get("KilometersPerHour")})"; + rightTextGetter = () => + { + Vector2 vel = controlledSub == null ? Vector2.Zero : controlledSub.Velocity; + var realWorldVel = ConvertUnits.ToDisplayUnits(vel.Y * Physics.DisplayToRealWorldRatio) * 3.6f; + return ((int)(-realWorldVel)).ToString(); + }; + break; + case 1: + leftText = TextManager.Get("Velocity"); + centerText = $"({TextManager.Get("KilometersPerHour")})"; + rightTextGetter = () => + { + Vector2 vel = controlledSub == null ? Vector2.Zero : controlledSub.Velocity; + var realWorldVel = ConvertUnits.ToDisplayUnits(vel.X * Physics.DisplayToRealWorldRatio) * 3.6f; + return ((int)realWorldVel).ToString(); + }; + break; + case 2: + leftText = TextManager.Get("Depth"); + centerText = $"({TextManager.Get("Meter")})"; + rightTextGetter = () => + { + Vector2 pos = controlledSub == null ? Vector2.Zero : controlledSub.Position; + float realWorldDepth = Level.Loaded == null ? 0.0f : Math.Abs(pos.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio; + return ((int)realWorldDepth).ToString(); + }; + break; + } + new GUITextBlock(new RectTransform(Vector2.One, left.RectTransform), leftText, font: GUI.SubHeadingFont, wrap: true, textAlignment: Alignment.CenterRight); + new GUITextBlock(new RectTransform(Vector2.One, center.RectTransform), centerText, font: GUI.Font, textAlignment: Alignment.Center) { Padding = Vector4.Zero }; + var digitalFrame = new GUIFrame(new RectTransform(Vector2.One, right.RectTransform), style: "DigitalFrameDark"); + new GUITextBlock(new RectTransform(Vector2.One * 0.85f, digitalFrame.RectTransform, Anchor.Center), "12345", GUI.Style.TextColorDark, GUI.DigitalFont, Alignment.CenterRight) + { + TextGetter = rightTextGetter + }; + } + GUITextBlock.AutoScaleAndNormalize(leftElements.SelectMany(e => e.GetAllChildren())); + // TODO: center texts are too small on low resolutions + GUITextBlock.AutoScaleAndNormalize(centerElements.SelectMany(e => e.GetAllChildren())); + GUITextBlock.AutoScaleAndNormalize(rightElements.SelectMany(e => e.GetAllChildren())); + + pressureWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), paddedStatusContainer.RectTransform), TextManager.Get("SteeringDepthWarning"), GUI.Style.Red) { Visible = false }; - tipContainer = new GUITextBlock(new RectTransform(new Vector2(0.25f, 0.12f), GuiFrame.RectTransform, Anchor.BottomLeft) - { MinSize = new Point(150, 0), RelativeOffset = new Vector2(0.0f, -0.05f) }, "", wrap: true, style: "GUIToolTip") + tipContainer = new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.1f), GuiFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter) + { + RelativeOffset = new Vector2(-0.2f, 0.0f) + }, "", font: GUI.Font, wrap: true, style: "GUIToolTip", textAlignment: Alignment.Center) { AutoScale = true }; @@ -300,17 +362,17 @@ namespace Barotrauma.Items.Components autoPilotLevelEndTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]", GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.Name); - steerArea = new GUICustomComponent(new RectTransform(Point.Zero, GuiFrame.RectTransform, Anchor.CenterLeft), - (spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null); - //docking interface ---------------------------------------------------- - dockingContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft) - { MinSize = new Point(150, 0) }, style: null); - var paddedDockingContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), dockingContainer.RectTransform, Anchor.Center), style: null); - + float dockingButtonSize = 1.1f; + float elementScale = 0.6f; + dockingContainer = new GUIFrame(new RectTransform(new Point(160).Multiply(GUI.Scale * dockingButtonSize), GuiFrame.RectTransform, Anchor.BottomRight) + { + RelativeOffset = new Vector2(Sonar.controlContainerRelativeOffset + 0.05f, -0.05f) + }, style: null); + dockText = TextManager.Get("label.navterminaldock", fallBackTag: "captain.dock"); undockText = TextManager.Get("label.navterminalundock", fallBackTag: "captain.undock"); - dockingButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), paddedDockingContainer.RectTransform, Anchor.Center), dockText, style: "GUIButtonLarge") + dockingButton = new GUIButton(new RectTransform(new Vector2(elementScale), dockingContainer.RectTransform, Anchor.Center), dockText, style: "PowerButton") { OnClicked = (btn, userdata) => { @@ -326,65 +388,45 @@ namespace Barotrauma.Items.Components return true; } }; - dockingButton.Font = GUI.SmallFont; + dockingButton.Font = GUI.SubHeadingFont; - var leftButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.5f), paddedDockingContainer.RectTransform, Anchor.CenterLeft), "") + var style = GUI.Style.GetComponentStyle("DockingButtonUp"); + Sprite buttonSprite = style.Sprites.FirstOrDefault().Value.FirstOrDefault()?.Sprite; + Point buttonSize = buttonSprite != null ? buttonSprite.size.ToPoint() : new Point(149, 52); + Point horizontalButtonSize = buttonSize.Multiply(elementScale * GUI.Scale * dockingButtonSize); + Point verticalButtonSize = horizontalButtonSize.Flip(); + var leftButton = new GUIButton(new RectTransform(verticalButtonSize, dockingContainer.RectTransform, Anchor.CenterLeft), "", style: "DockingButtonLeft") { OnClicked = NudgeButtonClicked, UserData = -Vector2.UnitX }; - new GUIImage(new RectTransform(new Vector2(0.7f), leftButton.RectTransform, Anchor.Center), "GUIButtonHorizontalArrow").SpriteEffects = SpriteEffects.FlipHorizontally; - var rightButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.5f), paddedDockingContainer.RectTransform, Anchor.CenterRight), "") + var rightButton = new GUIButton(new RectTransform(verticalButtonSize, dockingContainer.RectTransform, Anchor.CenterRight), "", style: "DockingButtonRight") { OnClicked = NudgeButtonClicked, UserData = Vector2.UnitX }; - new GUIImage(new RectTransform(new Vector2(0.7f), rightButton.RectTransform, Anchor.Center), "GUIButtonHorizontalArrow"); - var upButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), paddedDockingContainer.RectTransform, Anchor.TopCenter), "") + var upButton = new GUIButton(new RectTransform(horizontalButtonSize, dockingContainer.RectTransform, Anchor.TopCenter), "", style: "DockingButtonUp") { OnClicked = NudgeButtonClicked, UserData = Vector2.UnitY }; - new GUIImage(new RectTransform(new Vector2(0.7f), upButton.RectTransform, Anchor.Center), "GUIButtonVerticalArrow"); - var downButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), paddedDockingContainer.RectTransform, Anchor.BottomCenter), "") + var downButton = new GUIButton(new RectTransform(horizontalButtonSize, dockingContainer.RectTransform, Anchor.BottomCenter), "", style: "DockingButtonDown") { OnClicked = NudgeButtonClicked, UserData = -Vector2.UnitY }; - new GUIImage(new RectTransform(new Vector2(0.7f), downButton.RectTransform, Anchor.Center), "GUIButtonVerticalArrow").SpriteEffects = SpriteEffects.FlipVertically; - foreach (XElement subElement in element.Elements()) - { - switch (subElement.Name.ToString().ToLowerInvariant()) - { - case "steeringindicator": - steeringIndicator = new Sprite(subElement); - break; - case "maintainposindicator": - maintainPosIndicator = new Sprite(subElement); - break; - case "maintainposoriginindicator": - maintainPosOriginIndicator = new Sprite(subElement); - break; - } - } - - SetUILayout(); - - GameMain.Instance.OnResolutionChanged += SetUILayout; - GameMain.Config.OnHUDScaleChanged += SetUILayout; + steerArea = new GUICustomComponent(new RectTransform(Sonar.SonarAreaSize, GuiFrame.RectTransform, Anchor.CenterLeft), + (spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null); + steerArea.RectTransform.SetAsFirstChild(); + steerRadius = steerArea.Rect.Width / 2; } - private void SetUILayout() + + private void ResetGUI() { - int viewSize = (int)Math.Min(GuiFrame.Rect.Width - 150, GuiFrame.Rect.Height * 0.9f); - - controlContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.99f), (int)(viewSize * 0.05f)); - statusContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0); - steerArea.RectTransform.NonScaledSize = new Point(viewSize); - dockingContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0); - - steerRadius = steerArea.Rect.Width / 2; + GuiFrame.RectTransform.Children.ForEachMod(c => c.Parent = null); + CreateGUI(); } /// @@ -434,7 +476,7 @@ namespace Barotrauma.Items.Components if (velRect.Contains(PlayerInput.MousePosition)) { - GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 4, (int)steeringInputPos.Y - 4, 8, 8), Color.Red, thickness: 2); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 4, (int)steeringInputPos.Y - 4, 8, 8), GUI.Style.Red, thickness: 2); } } else if (posToMaintain.HasValue && !LevelStartSelected && !LevelEndSelected) @@ -447,7 +489,7 @@ namespace Barotrauma.Items.Components displayPosToMaintain = displayPosToMaintain.ClampLength(velRect.Width / 2); displayPosToMaintain = steerArea.Rect.Center.ToVector2() + displayPosToMaintain; - Color crosshairColor = Color.Orange * (0.5f + ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) / 4.0f); + Color crosshairColor = GUI.Style.Orange * (0.5f + ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) / 4.0f); if (maintainPosIndicator != null) { maintainPosIndicator.Draw(spriteBatch, displayPosToMaintain, crosshairColor, scale: 0.5f * sonar.Zoom); @@ -461,11 +503,11 @@ namespace Barotrauma.Items.Components if (maintainPosOriginIndicator != null) { - maintainPosOriginIndicator.Draw(spriteBatch, displaySubPos, Color.Orange, scale: 0.5f * sonar.Zoom); + maintainPosOriginIndicator.Draw(spriteBatch, displaySubPos, GUI.Style.Orange, scale: 0.5f * sonar.Zoom); } else { - GUI.DrawRectangle(spriteBatch, new Rectangle((int)displaySubPos.X - 5, (int)displaySubPos.Y - 5, 10, 10), Color.Orange); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)displaySubPos.X - 5, (int)displaySubPos.Y - 5, 10, 10), GUI.Style.Orange); } } } @@ -507,11 +549,11 @@ namespace Barotrauma.Items.Components pos.Y = -pos.Y; pos += center; - GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 3 / 2, (int)pos.Y - 3, 6, 6), (SteeringPath.CurrentNode == wp) ? Color.LightGreen : Color.Green, false); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 3 / 2, (int)pos.Y - 3, 6, 6), (SteeringPath.CurrentNode == wp) ? Color.LightGreen : GUI.Style.Green, false); if (prevPos != Vector2.Zero) { - GUI.DrawLine(spriteBatch, pos, prevPos, Color.Green); + GUI.DrawLine(spriteBatch, pos, prevPos, GUI.Style.Green); } prevPos = pos; @@ -529,14 +571,14 @@ namespace Barotrauma.Items.Components GUI.DrawLine(spriteBatch, pos1, pos2, - Color.Red * 0.6f, width: 3); + GUI.Style.Red * 0.6f, width: 3); if (obstacle.Intersection.HasValue) { Vector2 intersectionPos = (obstacle.Intersection.Value - transducerCenter) *displayScale; intersectionPos.Y = -intersectionPos.Y; intersectionPos += center; - GUI.DrawRectangle(spriteBatch, intersectionPos - Vector2.One * 2, Vector2.One * 4, Color.Red); + GUI.DrawRectangle(spriteBatch, intersectionPos - Vector2.One * 2, Vector2.One * 4, GUI.Style.Red); } Vector2 obstacleCenter = (pos1 + pos2) / 2; @@ -545,7 +587,7 @@ namespace Barotrauma.Items.Components GUI.DrawLine(spriteBatch, obstacleCenter, obstacleCenter + new Vector2(obstacle.AvoidStrength.X, -obstacle.AvoidStrength.Y) * 100, - Color.Lerp(Color.Green, Color.Orange, obstacle.Dot), width: 2); + Color.Lerp(GUI.Style.Green, GUI.Style.Orange, obstacle.Dot), width: 2); } } } @@ -580,7 +622,7 @@ namespace Barotrauma.Items.Components dockingButton.Text = dockText; if (dockingButton.FlashTimer <= 0.0f) { - dockingButton.Flash(Color.LightGreen, 0.5f); + dockingButton.Flash(GUI.Style.Blue, 0.5f, useCircularFlash: true); dockingButton.Pulsate(Vector2.One, Vector2.One * 1.2f, dockingButton.FlashTimer); } } @@ -592,7 +634,7 @@ namespace Barotrauma.Items.Components statusContainer.Visible = false; if (dockingButton.FlashTimer <= 0.0f) { - dockingButton.Flash(Color.OrangeRed); + dockingButton.Flash(GUI.Style.Orange, useCircularFlash: true); dockingButton.Pulsate(Vector2.One, Vector2.One * 1.2f, dockingButton.FlashTimer); } } @@ -601,8 +643,6 @@ namespace Barotrauma.Items.Components dockingButton.Text = dockText; } - autoPilotControlsDisabler.Visible = !AutoPilot; - if (Voltage < MinVoltage) { tipContainer.Visible = true; @@ -781,11 +821,11 @@ namespace Barotrauma.Items.Components public void ClientWrite(IWriteMessage msg, object[] extraData = null) { - msg.Write(autoPilot); + msg.Write(AutoPilot); msg.Write(dockingNetworkMessagePending); dockingNetworkMessagePending = false; - if (!autoPilot) + if (!AutoPilot) { //no need to write steering info if autopilot is controlling msg.Write(steeringInput.X); @@ -879,5 +919,15 @@ namespace Barotrauma.Items.Components } } } + + private void UpdateGUIElements() + { + steeringModeSwitch.Selected = AutoPilot; + autopilotIndicator.Selected = AutoPilot; + manualPilotIndicator.Selected = !AutoPilot; + maintainPosTickBox.Enabled = AutoPilot; + levelEndTickBox.Enabled = AutoPilot; + levelStartTickBox.Enabled = AutoPilot; + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerContainer.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerContainer.cs index cb6f22c5b..c59e2571f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerContainer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerContainer.cs @@ -18,13 +18,20 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific() { - if (GuiFrame == null) return; + if (GuiFrame == null) { return; } + + var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.75f), GuiFrame.RectTransform, Anchor.Center) + { + //RelativeOffset = new Vector2(0, 0.05f) + }, style: null); + + var upperArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f), paddedFrame.RectTransform, Anchor.TopCenter), style: null); + var lowerArea = new GUIFrame(new RectTransform(new Vector2(1, 0.6f), paddedFrame.RectTransform, Anchor.BottomCenter), style: null); - GUILayoutGroup paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.7f), GuiFrame.RectTransform, Anchor.Center)) - { RelativeSpacing = 0.1f, Stretch = true }; string rechargeStr = TextManager.Get("PowerContainerRechargeRate"); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), "RechargeRate", textAlignment: Alignment.Center) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), upperArea.RectTransform, Anchor.TopCenter), + "RechargeRate", textColor: GUI.Style.TextColor, font: GUI.SubHeadingFont, textAlignment: Alignment.Center) { TextGetter = () => { @@ -32,21 +39,14 @@ namespace Barotrauma.Items.Components } }; - var sliderArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform, Anchor.BottomCenter), isHorizontal: true) - { - Stretch = true, - RelativeSpacing = 0.05f - }; - - new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform), - "0 %", textAlignment: Alignment.Center); - rechargeSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(0.8f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider") + rechargeSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(0.9f, 0.4f), upperArea.RectTransform, Anchor.BottomCenter), + barSize: 0.15f, style: "DeviceSlider") { Step = 0.1f, OnMoved = (GUIScrollBar scrollBar, float barScroll) => { float newRechargeSpeed = maxRechargeSpeed * barScroll; - if (Math.Abs(newRechargeSpeed - rechargeSpeed) < 0.1f) return false; + if (Math.Abs(newRechargeSpeed - rechargeSpeed) < 0.1f) { return false; } RechargeSpeed = newRechargeSpeed; if (GameMain.Client != null) @@ -57,21 +57,30 @@ namespace Barotrauma.Items.Components return true; } }; - new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform), - "100 %", textAlignment: Alignment.Center); + rechargeSpeedSlider.Bar.RectTransform.MaxSize = new Point(rechargeSpeedSlider.Bar.Rect.Height); + + // lower area -------------------------- - string chargeStr = TextManager.Get("PowerContainerCharge"); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), "Charge", textAlignment: Alignment.Center) + var textArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f), lowerArea.RectTransform), style: null); + var chargeLabel = new GUITextBlock(new RectTransform(new Vector2(0.4f, 0.0f), textArea.RectTransform, Anchor.CenterLeft), + TextManager.Get("charge"), textColor: GUI.Style.TextColor, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft) { - TextGetter = () => - { - return chargeStr.Replace("[charge]", (int)charge + "/" + (int)capacity).Replace("[percentage]", ((int)((charge / capacity) * 100.0f)).ToString()); - } + ToolTip = TextManager.Get("PowerTransferTipPower") }; - - chargeIndicator = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), barSize: 0.0f) + string kWmin = TextManager.Get("kilowattminute"); + var chargeText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), textArea.RectTransform, Anchor.CenterRight), + "", textColor: GUI.Style.TextColor, font: GUI.Font, textAlignment: Alignment.CenterRight) { - ProgressGetter = () => + TextGetter = () => $"{(int)charge}/{(int)capacity} {kWmin} ({((int)MathUtils.Percentage(charge, capacity)).ToString()} %)" + }; + if (chargeText.TextSize.X > chargeText.Rect.Width) { chargeText.Font = GUI.SmallFont; } + + chargeIndicator = new GUIProgressBar(new RectTransform(new Vector2(1.1f, 0.5f), lowerArea.RectTransform, Anchor.BottomCenter) + { + RelativeOffset = new Vector2(0, 0.1f) + }, barSize: 0.0f, style: "DeviceProgressBar") + { + ProgressGetter = () => { return capacity <= 0.0f ? 1.0f : charge / capacity; } @@ -95,7 +104,7 @@ namespace Barotrauma.Items.Components public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1) { - if (indicatorSize.X <= 1.0f || indicatorSize.Y <= 1.0f) return; + if (indicatorSize.X <= 1.0f || indicatorSize.Y <= 1.0f) { return; } GUI.DrawRectangle(spriteBatch, new Vector2( diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerTransfer.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerTransfer.cs index 599748a21..32c411ff8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerTransfer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerTransfer.cs @@ -1,5 +1,4 @@ using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; using System; using System.Xml.Linq; @@ -13,66 +12,95 @@ namespace Barotrauma.Items.Components partial void InitProjectSpecific(XElement element) { - if (GuiFrame == null) return; + if (GuiFrame == null) { return; } - Point indicatorSize = new Point((int)(30 * GUI.Scale)); - - var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.7f), GuiFrame.RectTransform, Anchor.Center), style: null); - powerIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform), - TextManager.Get("PowerTransferPowered"), style: "IndicatorLightGreen") + var paddedFrame = new GUIFrame(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, + style: null) { - Enabled = false + CanBeFocused = false }; - powerIndicator.TextColor = powerIndicator.DefaultTextColor.Value; - highVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(40 * GUI.yScale)) }, - TextManager.Get("PowerTransferHighVoltage"), style: "IndicatorLightRed") + var lightsArea = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1), paddedFrame.RectTransform, Anchor.CenterLeft)) + { + Stretch = true, + RelativeSpacing = 0.05f + }; + powerIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), lightsArea.RectTransform), + TextManager.Get("PowerTransferPowered"), font: GUI.SubHeadingFont, style: "IndicatorLightGreen") + { + CanBeFocused = false + }; + highVoltageIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), lightsArea.RectTransform), + TextManager.Get("PowerTransferHighVoltage"), font: GUI.SubHeadingFont, style: "IndicatorLightRed") { ToolTip = TextManager.Get("PowerTransferTipOvervoltage"), Enabled = false }; - highVoltageIndicator.TextColor = highVoltageIndicator.DefaultTextColor.Value; - - lowVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(80 * GUI.yScale)) }, - TextManager.Get("PowerTransferLowVoltage"), style: "IndicatorLightRed") + lowVoltageIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), lightsArea.RectTransform), + TextManager.Get("PowerTransferLowVoltage"), font: GUI.SubHeadingFont, style: "IndicatorLightRed") { ToolTip = TextManager.Get("PowerTransferTipLowvoltage"), Enabled = false }; - lowVoltageIndicator.TextColor = lowVoltageIndicator.DefaultTextColor.Value; + powerIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); + highVoltageIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); + lowVoltageIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); + GUITextBlock.AutoScaleAndNormalize(powerIndicator.TextBlock, highVoltageIndicator.TextBlock, lowVoltageIndicator.TextBlock); - var textContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform, Anchor.TopRight)); + var textContainer = new GUIFrame(new RectTransform(new Vector2(0.58f, 1.0f), paddedFrame.RectTransform, Anchor.CenterRight), style: null); + var upperTextArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), textContainer.RectTransform, Anchor.TopLeft), isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + Stretch = true + }; + var lowerTextArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), textContainer.RectTransform, Anchor.BottomLeft), isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + Stretch = true + }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContainer.RectTransform), - TextManager.Get("PowerTransferPowerLabel"), font: GUI.LargeFont) + var powerLabel = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), upperTextArea.RectTransform), + TextManager.Get("PowerTransferPowerLabel"), textColor: GUI.Style.TextColorBright, font: GUI.LargeFont, textAlignment: Alignment.CenterRight) { ToolTip = TextManager.Get("PowerTransferTipPower") }; - string powerStr = TextManager.Get("PowerTransferPower"); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), textContainer.RectTransform), "", textColor: Color.LightGreen) - { - ToolTip = TextManager.Get("PowerTransferTipPower"), - TextGetter = () => { return powerStr.Replace("[power]", ((int)Math.Round(-currPowerConsumption)).ToString()); } - }; - - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), textContainer.RectTransform), - TextManager.Get("PowerTransferLoadLabel"), font: GUI.LargeFont) + var loadLabel = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), lowerTextArea.RectTransform), + TextManager.Get("PowerTransferLoadLabel"), textColor: GUI.Style.TextColorBright, font: GUI.LargeFont, textAlignment: Alignment.CenterRight) { ToolTip = TextManager.Get("PowerTransferTipLoad") - }; - string loadStr = TextManager.Get("PowerTransferLoad"); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), textContainer.RectTransform), "", textColor: Color.LightBlue) + + var digitalBackground = new GUIFrame(new RectTransform(new Vector2(0.55f, 0.8f), upperTextArea.RectTransform), style: "DigitalFrameDark"); + var powerText = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.95f), digitalBackground.RectTransform, Anchor.Center), + "", font: GUI.DigitalFont, textColor: GUI.Style.TextColorDark) { - ToolTip = TextManager.Get("PowerTransferTipLoad"), - TextGetter = () => - { - return loadStr.Replace("[load]", - this is RelayComponent relay ? - ((int)Math.Round(relay.DisplayLoad)).ToString() : - ((int)Math.Round(powerLoad)).ToString()); - } + TextAlignment = Alignment.CenterRight, + ToolTip = TextManager.Get("PowerTransferTipPower"), + TextGetter = () => ((int)Math.Round(-currPowerConsumption)).ToString() }; + var kw1 = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.5f), upperTextArea.RectTransform), + TextManager.Get("kilowatt"), textColor: GUI.Style.TextColor, font: GUI.Font) + { + Padding = Vector4.Zero, + TextAlignment = Alignment.BottomCenter + }; + + digitalBackground = new GUIFrame(new RectTransform(new Vector2(0.55f, 0.8f), lowerTextArea.RectTransform), style: "DigitalFrameDark"); + var loadText = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.95f), digitalBackground.RectTransform, Anchor.Center), + "", font: GUI.DigitalFont, textColor: GUI.Style.TextColorDark) + { + TextAlignment = Alignment.CenterRight, + ToolTip = TextManager.Get("PowerTransferTipLoad"), + TextGetter = () => ((int)Math.Round(this is RelayComponent relay ? relay.DisplayLoad : powerLoad)).ToString() + }; + var kw2 = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.5f), lowerTextArea.RectTransform), + TextManager.Get("kilowatt"), textColor: GUI.Style.TextColor, font: GUI.Font) + { + Padding = Vector4.Zero, + TextAlignment = Alignment.BottomCenter + }; + + GUITextBlock.AutoScaleAndNormalize(powerLabel, loadLabel); + GUITextBlock.AutoScaleAndNormalize(powerText, loadText); + GUITextBlock.AutoScaleAndNormalize(kw1, kw2); } public override void UpdateHUD(Character character, float deltaTime, Camera cam) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/RepairTool.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/RepairTool.cs index 19d2d4caf..d83a4a17a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/RepairTool.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/RepairTool.cs @@ -84,7 +84,7 @@ namespace Barotrauma.Items.Components targetStructure.ID * 1000 + sectionIndex, //unique "identifier" for each wall section progressBarPos, 1.0f - targetStructure.SectionDamage(sectionIndex) / targetStructure.Health, - Color.Red, Color.Green); + GUI.Style.Red, GUI.Style.Green); if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f); @@ -121,7 +121,7 @@ namespace Barotrauma.Items.Components targetItem, progressBarPos, progressBarState, - Color.Red, Color.Green); + GUI.Style.Red, GUI.Style.Green); if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); } } prevProgressBarState = progressBarState; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs index 8ad40749e..e1defdaaf 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Repairable.cs @@ -48,10 +48,11 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific(XElement element) { - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.75f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) { Stretch = true, - RelativeSpacing = 0.05f + RelativeSpacing = 0.05f, + CanBeFocused = true }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), @@ -60,11 +61,11 @@ namespace Barotrauma.Items.Components new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), Description, font: GUI.SmallFont, wrap: true); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), - TextManager.Get("RequiredRepairSkills")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), + TextManager.Get("RequiredRepairSkills"), font: GUI.SubHeadingFont); for (int i = 0; i < requiredSkills.Count; i++) { - var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), + var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), " - " + TextManager.AddPunctuation(':', TextManager.Get("SkillName." + requiredSkills[i].Identifier), ((int) requiredSkills[i].Level).ToString()), font: GUI.SmallFont) { @@ -72,12 +73,17 @@ namespace Barotrauma.Items.Components }; } - progressBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), - color: Color.Green, barSize: 0.0f); + var progressBarHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + progressBar = new GUIProgressBar(new RectTransform(new Vector2(0.7f, 1.0f), progressBarHolder.RectTransform), + color: GUI.Style.Green, barSize: 0.0f, style: "DeviceProgressBar"); repairButtonText = TextManager.Get("RepairButton"); repairingText = TextManager.Get("Repairing"); - RepairButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.TopCenter), repairButtonText) + RepairButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), progressBarHolder.RectTransform, Anchor.TopCenter), repairButtonText) { OnClicked = (btn, obj) => { @@ -86,10 +92,15 @@ namespace Barotrauma.Items.Components return true; } }; + progressBarHolder.RectTransform.MinSize = RepairButton.RectTransform.MinSize; + RepairButton.RectTransform.MinSize = new Point((int)(RepairButton.TextBlock.TextSize.X * 1.2f), RepairButton.RectTransform.MinSize.Y); + sabotageButtonText = TextManager.Get("SabotageButton"); sabotagingText = TextManager.Get("Sabotaging"); - SabotageButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.BottomCenter), sabotageButtonText) + SabotageButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.BottomCenter), sabotageButtonText, style: "GUIButtonSmall") { + IgnoreLayoutGroups = true, + Visible = false, OnClicked = (btn, obj) => { requestStartFixAction = FixActions.Sabotage; @@ -157,7 +168,7 @@ namespace Barotrauma.Items.Components IsActive = true; progressBar.BarSize = item.Condition / item.MaxCondition; - progressBar.Color = ToolBox.GradientLerp(progressBar.BarSize, Color.Red, Color.Orange, Color.Green); + progressBar.Color = ToolBox.GradientLerp(progressBar.BarSize, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green); RepairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && !item.IsFullCondition; RepairButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Repair) ? @@ -165,6 +176,7 @@ namespace Barotrauma.Items.Components repairingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1); SabotageButton.Visible = character.IsTraitor; + SabotageButton.IgnoreLayoutGroups = !SabotageButton.Visible; SabotageButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Sabotage)) && character.IsTraitor && item.ConditionPercentage > MinSabotageCondition; SabotageButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Sabotage || !character.IsTraitor) ? sabotageButtonText : @@ -178,7 +190,7 @@ namespace Barotrauma.Items.Components GUITextBlock textBlock = (GUITextBlock)c; if (character.GetSkillLevel(skill.Identifier) < skill.Level) { - textBlock.TextColor = Color.Red; + textBlock.TextColor = GUI.Style.Red; } else { @@ -202,11 +214,11 @@ namespace Barotrauma.Items.Components { GUI.DrawString(spriteBatch, new Vector2(item.WorldPosition.X, -item.WorldPosition.Y), "Deteriorating at " + (int)(DeteriorationSpeed * 60.0f) + " units/min" + (paused ? " [PAUSED]" : ""), - paused ? Color.Cyan : Color.Red, Color.Black * 0.5f); + paused ? Color.Cyan : GUI.Style.Red, Color.Black * 0.5f); } GUI.DrawString(spriteBatch, new Vector2(item.WorldPosition.X, -item.WorldPosition.Y + 20), "Condition: " + (int)item.Condition + "/" + (int)item.MaxCondition, - Color.Orange); + GUI.Style.Orange); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs index 946db2f4a..5f33deade 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs @@ -16,21 +16,11 @@ namespace Barotrauma.Items.Components private static Sprite connectionSpriteHighlight; private static List screwSprites; - private static Wire draggingConnected; - private Color flashColor; private float flashDuration = 1.5f; - public float FlashTimer - { - get { return flashTimer; } - } - - public static Wire DraggingConnected - { - get => draggingConnected; - } - - private float flashTimer; + + public float FlashTimer { get; private set; } + public static Wire DraggingConnected { get; private set; } public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character) { @@ -38,6 +28,16 @@ namespace Barotrauma.Items.Components int x = panelRect.X, y = panelRect.Y; int width = panelRect.Width, height = panelRect.Height; + Vector2 scale = new Vector2(GUI.Scale); + if (panel.GuiFrame.RectTransform.MaxSize.X < int.MaxValue) + { + scale.X = panel.GuiFrame.RectTransform.MaxSize.X / panel.GuiFrame.Rect.Width; + } + if (panel.GuiFrame.RectTransform.MaxSize.Y < int.MaxValue) + { + scale.Y = panel.GuiFrame.RectTransform.MaxSize.Y / panel.GuiFrame.Rect.Height; + } + bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition); int totalWireCount = 0; @@ -57,73 +57,90 @@ namespace Barotrauma.Items.Components { Item selectedItem = character.SelectedItems[i]; - if (selectedItem == null) continue; + if (selectedItem == null) { continue; } Wire wireComponent = selectedItem.GetComponent(); - if (wireComponent != null) equippedWire = wireComponent; - } - } - - Vector2 rightPos = new Vector2(x + width - 110 * GUI.xScale, y + 80 * GUI.yScale); - Vector2 leftPos = new Vector2(x + 110 * GUI.xScale, y + 80 * GUI.yScale); - - Vector2 rightWirePos = new Vector2(x + width - 5 * GUI.xScale, y + 30 * GUI.yScale); - Vector2 leftWirePos = new Vector2(x + 5 * GUI.xScale, y + 30 * GUI.yScale); - - int wireInterval = (height - (int)(20 * GUI.yScale)) / Math.Max(totalWireCount, 1); - int connectorIntervalLeft = (height - (int)(100 * GUI.yScale)) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1); - int connectorIntervalRight = (height - (int)(100 * GUI.yScale)) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1); - - foreach (Connection c in panel.Connections) - { - //if dragging a wire, let the Inventory know so that the wire can be - //dropped or dragged from the panel to the players inventory - if (draggingConnected != null) - { - //the wire can only be dragged out if it's not connected to anything at the other end - if (Screen.Selected == GameMain.SubEditorScreen || - (draggingConnected.Connections[0] == null && draggingConnected.Connections[1] == null) || - (draggingConnected.Connections.Contains(c) && draggingConnected.Connections.Contains(null))) + if (wireComponent != null) { - int linkIndex = c.FindWireIndex(draggingConnected.Item); - if (linkIndex > -1 || panel.DisconnectedWires.Contains(draggingConnected)) - { - Inventory.draggingItem = draggingConnected.Item; - } + equippedWire = wireComponent; } } + } - //outputs are drawn at the right side of the panel, inputs at the left - if (c.IsOutput) + //two passes: first the connector, then the wires to get the wires to render in front + for (int i = 0; i < 2; i++) + { + Vector2 rightPos = new Vector2(x + width - 80 * scale.X, y + 60 * scale.Y); + Vector2 leftPos = new Vector2(x + 80 * scale.X, y + 60 * scale.Y); + + Vector2 rightWirePos = new Vector2(x + width - 5 * scale.X, y + 30 * scale.Y); + Vector2 leftWirePos = new Vector2(x + 5 * scale.X, y + 30 * scale.Y); + + int wireInterval = (height - (int)(20 * scale.Y)) / Math.Max(totalWireCount, 1); + int connectorIntervalLeft = (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1); + int connectorIntervalRight = (height - (int)(100 * scale.Y)) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1); + + foreach (Connection c in panel.Connections) { - c.Draw(spriteBatch, panel, rightPos, - new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.DisplayName).X - 20 * GUI.xScale, rightPos.Y + 3 * GUI.yScale), - rightWirePos, - mouseInRect, equippedWire, - wireInterval); + //if dragging a wire, let the Inventory know so that the wire can be + //dropped or dragged from the panel to the players inventory + if (DraggingConnected != null && i == 1) + { + //the wire can only be dragged out if it's not connected to anything at the other end + if (Screen.Selected == GameMain.SubEditorScreen || + (DraggingConnected.Connections[0] == null && DraggingConnected.Connections[1] == null) || + (DraggingConnected.Connections.Contains(c) && DraggingConnected.Connections.Contains(null))) + { + int linkIndex = c.FindWireIndex(DraggingConnected.Item); + if (linkIndex > -1 || panel.DisconnectedWires.Contains(DraggingConnected)) + { + Inventory.draggingItem = DraggingConnected.Item; + } + } + } - rightPos.Y += connectorIntervalLeft; - rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval; - } - else - { - c.Draw(spriteBatch, panel, leftPos, - new Vector2(leftPos.X + 20 * GUI.xScale, leftPos.Y - 12 * GUI.yScale), - leftWirePos, - mouseInRect, equippedWire, - wireInterval); + //outputs are drawn at the right side of the panel, inputs at the left + if (c.IsOutput) + { + if (i == 0) + { + c.DrawConnection(spriteBatch, panel, rightPos, + new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.DisplayName.ToUpper()).X - 25 * panel.Scale, rightPos.Y + 5 * panel.Scale), + scale); + } + else + { + c.DrawWires(spriteBatch, panel, rightPos, rightWirePos, mouseInRect, equippedWire, wireInterval); + } - leftPos.Y += connectorIntervalRight; - leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval; - //leftWireX -= wireInterval; + rightPos.Y += connectorIntervalLeft; + rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval; + } + else + { + if (i == 0) + { + c.DrawConnection(spriteBatch, panel, leftPos, + new Vector2(leftPos.X + 25 * panel.Scale, leftPos.Y - 5 * panel.Scale - GUI.SmallFont.MeasureString(c.DisplayName.ToUpper()).Y), + scale); + } + else + { + c.DrawWires(spriteBatch, panel, leftPos, leftWirePos, mouseInRect, equippedWire, wireInterval); + } + + leftPos.Y += connectorIntervalRight; + leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval; + } } } - if (draggingConnected != null) + + if (DraggingConnected != null) { if (mouseInRect) { - DrawWire(spriteBatch, draggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, ""); + DrawWire(spriteBatch, DraggingConnected, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height - 10), null, panel, ""); } panel.TriggerRewiringSound(); @@ -131,11 +148,11 @@ namespace Barotrauma.Items.Components { if (GameMain.NetworkMember != null || panel.CheckCharacterSuccess(character)) { - if (draggingConnected.Connections[0]?.ConnectionPanel == panel || - draggingConnected.Connections[1]?.ConnectionPanel == panel) + if (DraggingConnected.Connections[0]?.ConnectionPanel == panel || + DraggingConnected.Connections[1]?.ConnectionPanel == panel) { - draggingConnected.RemoveConnection(panel.Item); - panel.DisconnectedWires.Add(draggingConnected); + DraggingConnected.RemoveConnection(panel.Item); + panel.DisconnectedWires.Add(DraggingConnected); } } @@ -144,13 +161,13 @@ namespace Barotrauma.Items.Components panel.Item.CreateClientEvent(panel); } - draggingConnected = null; + DraggingConnected = null; } } //if the Character using the panel has a wire item equipped //and the wire hasn't been connected yet, draw it on the panel - if (equippedWire != null && (draggingConnected != equippedWire || !mouseInRect)) + if (equippedWire != null && (DraggingConnected != equippedWire || !mouseInRect)) { if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null) { @@ -158,7 +175,7 @@ namespace Barotrauma.Items.Components new Vector2(x + width / 2, y + height), null, panel, ""); - if (draggingConnected == equippedWire) { Inventory.draggingItem = equippedWire.Item; } + if (DraggingConnected == equippedWire) { Inventory.draggingItem = equippedWire.Item; } } } @@ -167,7 +184,7 @@ namespace Barotrauma.Items.Components x = (int)(x + width / 2 - step * (panel.DisconnectedWires.Count() - 1) / 2); foreach (Wire wire in panel.DisconnectedWires) { - if (wire == draggingConnected && mouseInRect) { continue; } + if (wire == DraggingConnected && mouseInRect) { continue; } Connection recipient = wire.OtherConnection(null); string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})"; @@ -183,15 +200,34 @@ namespace Barotrauma.Items.Components if (mouseInRect || GUI.MouseOn?.UserData is ConnectionPanel) { Inventory.draggingItem = null; } } - private void Draw(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval) + private void DrawConnection(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 scale) { - GUI.DrawString(spriteBatch, labelPos, DisplayName, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont); + string text = DisplayName.ToUpper(); + Vector2 textSize = GUI.SmallFont.MeasureString(text); - connectionSprite.Draw(spriteBatch, position); + //nasty + var labelSprite = GUI.Style.GetComponentStyle("ConnectionPanelLabel")?.Sprites.Values.First().First(); + if (labelSprite != null) + { + Rectangle labelArea = new Rectangle(labelPos.ToPoint(), textSize.ToPoint()); + labelArea.Inflate(10 * scale.X, 3 * scale.Y); + labelSprite.Draw(spriteBatch, labelArea, IsPower ? GUI.Style.Red : Color.SteelBlue); + } + + GUI.DrawString(spriteBatch, labelPos + Vector2.UnitY, text, Color.Black * 0.8f, font: GUI.SmallFont); + GUI.DrawString(spriteBatch, labelPos, text, GUI.Style.TextColorBright, font: GUI.SmallFont); + + float connectorSpriteScale = (35.0f / connectionSprite.SourceRect.Width) * panel.Scale; + connectionSprite.Draw(spriteBatch, position, scale: connectorSpriteScale); + } + + private void DrawWires(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval) + { + float connectorSpriteScale = (35.0f / connectionSprite.SourceRect.Width) * panel.Scale; for (int i = 0; i < MaxLinked; i++) { - if (wires[i] == null || wires[i].Hidden || (draggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen))) { continue; } + if (wires[i] == null || wires[i].Hidden || (DraggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen))) { continue; } Connection recipient = wires[i].OtherConnection(this); string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})"; @@ -201,9 +237,9 @@ namespace Barotrauma.Items.Components wirePosition.Y += wireInterval; } - if (draggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < (20.0f * GUI.Scale)) + if (DraggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < (20.0f * GUI.Scale)) { - connectionSpriteHighlight.Draw(spriteBatch, position); + connectionSpriteHighlight.Draw(spriteBatch, position, scale: connectorSpriteScale); if (!PlayerInput.PrimaryMouseButtonHeld()) { @@ -211,14 +247,14 @@ namespace Barotrauma.Items.Components { //find an empty cell for the new connection int index = FindEmptyIndex(); - if (index > -1 && !Wires.Contains(draggingConnected)) + if (index > -1 && !Wires.Contains(DraggingConnected)) { - bool alreadyConnected = draggingConnected.IsConnectedTo(panel.Item); - draggingConnected.RemoveConnection(panel.Item); - if (draggingConnected.Connect(this, !alreadyConnected, true)) + bool alreadyConnected = DraggingConnected.IsConnectedTo(panel.Item); + DraggingConnected.RemoveConnection(panel.Item); + if (DraggingConnected.Connect(this, !alreadyConnected, true)) { - var otherConnection = draggingConnected.OtherConnection(this); - SetWire(index, draggingConnected); + var otherConnection = DraggingConnected.OtherConnection(this); + SetWire(index, DraggingConnected); } } } @@ -227,11 +263,11 @@ namespace Barotrauma.Items.Components { panel.Item.CreateClientEvent(panel); } - draggingConnected = null; + DraggingConnected = null; } } - if (flashTimer > 0.0f) + if (FlashTimer > 0.0f) { //the number of flashes depends on the duration, 1 flash per 1 full second int flashCycleCount = (int)Math.Max(flashDuration, 1); @@ -239,27 +275,28 @@ namespace Barotrauma.Items.Components //MathHelper.Pi * 0.8f -> the curve goes from 144 deg to 0, //i.e. quickly bumps up from almost full brightness to full and then fades out - connectionSpriteHighlight.Draw(spriteBatch, position, flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f)); + connectionSpriteHighlight.Draw(spriteBatch, position, + flashColor * (float)Math.Sin(FlashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), scale: connectorSpriteScale); } - if (Wires.Any(w => w != null && w != draggingConnected)) + if (Wires.Any(w => w != null && w != DraggingConnected)) { int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count; - screwSprites[screwIndex].Draw(spriteBatch, position); + screwSprites[screwIndex].Draw(spriteBatch, position, scale: connectorSpriteScale); } } public void Flash(Color? color = null, float flashDuration = 1.5f) { - flashTimer = flashDuration; + FlashTimer = flashDuration; this.flashDuration = flashDuration; - flashColor = (color == null) ? Color.Red : (Color)color; + flashColor = (color == null) ? GUI.Style.Red : (Color)color; } public void UpdateFlashTimer(float deltaTime) { - if (flashTimer <= 0) return; - flashTimer -= deltaTime; + if (FlashTimer <= 0) return; + FlashTimer -= deltaTime; } private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Vector2 end, Vector2 start, Wire equippedWire, ConnectionPanel panel, string label) @@ -287,41 +324,45 @@ namespace Barotrauma.Items.Components if (start.Y > panel.GuiFrame.Rect.Bottom - 1.0f) { //wire at the bottom of the panel -> draw the text below the panel, tilted 45 degrees - GUI.SmallFont.DrawString(spriteBatch, label, start + Vector2.UnitY * 20 * GUI.Scale, Color.White, 45.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f); + GUI.Font.DrawString(spriteBatch, label, start + Vector2.UnitY * 20 * GUI.Scale, Color.White, 45.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f); } else { GUI.DrawString(spriteBatch, new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f), label, - (mouseOn ? Color.Gold : Color.White) * (wire.Locked ? 0.6f : 1.0f), Color.Black * 0.8f, + wire.Locked ? GUI.Style.TextColorDim : (mouseOn ? Wire.higlightColor : GUI.Style.TextColor), Color.Black * 0.9f, 3, GUI.SmallFont); } } - var wireEnd = end + Vector2.Normalize(start - end) * 30.0f; + var wireEnd = end + Vector2.Normalize(start - end) * 30.0f * panel.Scale; float dist = Vector2.Distance(start, wireEnd); + float wireWidth = 12 * panel.Scale; + float highlight = 5 * panel.Scale; if (mouseOn) { - spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point(18, (int)dist)), wireVertical.SourceRect, - Color.Gold, + spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point((int)(wireWidth + highlight), (int)dist)), wireVertical.SourceRect, + Wire.higlightColor, MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, - new Vector2(6, 0), // point in line about which to rotate + new Vector2(wireVertical.size.X / 2, 0), // point in line about which to rotate SpriteEffects.None, 0.0f); } - spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point(12, (int)dist)), wireVertical.SourceRect, + spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point((int)wireWidth, (int)dist)), wireVertical.SourceRect, wire.Item.Color * alpha, MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, - new Vector2(6, 0), // point in line about which to rotate + new Vector2(wireVertical.size.X / 2, 0), // point in line about which to rotate SpriteEffects.None, 0.0f); - connector.Draw(spriteBatch, end, Color.White, new Vector2(10.0f, 10.0f), MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2); + float connectorScale = wireWidth / (float)wireVertical.SourceRect.Width; - if (draggingConnected == null && canDrag) + connector.Draw(spriteBatch, end, Color.White, connector.Origin, MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, scale: connectorScale); + + if (DraggingConnected == null && canDrag) { if (mouseOn) { @@ -331,7 +372,7 @@ namespace Barotrauma.Items.Components if (allowRewiring && !wire.Locked && (!panel.Locked || Screen.Selected == GameMain.SubEditorScreen)) { //start dragging the wire - if (PlayerInput.PrimaryMouseButtonHeld()) { draggingConnected = wire; } + if (PlayerInput.PrimaryMouseButtonHeld()) { DraggingConnected = wire; } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs index ec0f459e5..eb03f1032 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/ConnectionPanel.cs @@ -19,6 +19,11 @@ namespace Barotrauma.Items.Components private SoundChannel rewireSoundChannel; private float rewireSoundTimer; + public float Scale + { + get { return GuiFrame.Rect.Width / 400.0f; } + } + partial void InitProjSpecific(XElement element) { if (GuiFrame == null) { return; } @@ -107,7 +112,6 @@ namespace Barotrauma.Items.Components } } - public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime) { if (GameMain.Client.MidRoundSyncing) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs index fa44904eb..6b9c2f67f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs @@ -19,7 +19,7 @@ namespace Barotrauma.Items.Components var visibleElements = customInterfaceElementList.Where(ciElement => !string.IsNullOrEmpty(ciElement.Label)); - uiElementContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), + uiElementContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.65f), GuiFrame.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.025f) }, childAnchor: customInterfaceElementList.Count > 1 ? Anchor.TopCenter : Anchor.Center) { RelativeSpacing = 0.05f, @@ -49,12 +49,15 @@ namespace Barotrauma.Items.Components } return true; }; + //reset size restrictions set by the Style to make sure the elements can fit the interface + tickBox.RectTransform.MinSize = new Point(0, 0); + tickBox.RectTransform.MaxSize = new Point(int.MaxValue, int.MaxValue); uiElements.Add(tickBox); } else { var btn = new GUIButton(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform), - TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label, style: "GUIButtonLarge") + TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label, style: "DeviceButton") { UserData = ciElement }; @@ -71,6 +74,12 @@ namespace Barotrauma.Items.Components } return true; }; + + //reset size restrictions set by the Style to make sure the elements can fit the interface + btn.RectTransform.MinSize = btn.Frame.RectTransform.MinSize = new Point(0, 0); + btn.RectTransform.MaxSize = btn.Frame.RectTransform.MaxSize = new Point(int.MaxValue, int.MaxValue); + btn.TextBlock.Wrap = true; + uiElements.Add(btn); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs index 87ae3fa5f..16e806bb2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs @@ -15,9 +15,14 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific(XElement element) { - GUILayoutGroup layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(.9f, .8f), GuiFrame.RectTransform, anchor: Anchor.Center)); + var layoutGroup = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }) + { + ChildAnchor = Anchor.TopCenter, + RelativeSpacing = 0.02f, + Stretch = true + }; - historyBox = new GUIListBox(new RectTransform(new Vector2(1, .9f), layoutGroup.RectTransform)) + historyBox = new GUIListBox(new RectTransform(new Vector2(1, .9f), layoutGroup.RectTransform), style: null) { AutoHideScrollBar = false }; @@ -29,6 +34,8 @@ namespace Barotrauma.Items.Components CanBeFocused = false }; + new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine"); + inputBox = new GUITextBox(new RectTransform(new Vector2(1, .1f), layoutGroup.RectTransform), textColor: Color.LimeGreen) { MaxTextLength = MaxMessageLength, diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs index 7de5cda92..0f8101213 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs @@ -11,6 +11,10 @@ namespace Barotrauma.Items.Components { partial class Wire : ItemComponent, IDrawableComponent, IServerSerializable, IClientSerializable { + public static Color higlightColor = Color.LightGreen; + public static Color editorHighlightColor = Color.Yellow; + public static Color editorSelectedColor = Color.Red; + partial class WireSection { public void Draw(SpriteBatch spriteBatch, Wire wire, Color color, Vector2 offset, float depth, float width = 0.3f) @@ -105,14 +109,14 @@ namespace Barotrauma.Items.Components { foreach (WireSection section in sections) { - section.Draw(spriteBatch, this, Color.Gold, drawOffset, depth + 0.00001f, 0.7f); + section.Draw(spriteBatch, this, Screen.Selected == GameMain.GameScreen ? higlightColor : editorHighlightColor, drawOffset, depth + 0.00001f, 0.7f); } } else if (item.IsSelected) { foreach (WireSection section in sections) { - section.Draw(spriteBatch, this, Color.Red, drawOffset, depth + 0.00001f, 0.7f); + section.Draw(spriteBatch, this, editorSelectedColor, drawOffset, depth + 0.00001f, 0.7f); } } @@ -183,7 +187,7 @@ namespace Barotrauma.Items.Components if ((highlightedNodeIndex == i && item.IsHighlighted) || (selectedNodeIndex == i && item.IsSelected)) { - GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-10, -10), new Vector2(20, 20), Color.Red, false, 0.0f); + GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-10, -10), new Vector2(20, 20), editorHighlightColor, false, 0.0f); } if (item.IsSelected) @@ -206,7 +210,7 @@ namespace Barotrauma.Items.Components WireSection.Draw( spriteBatch, this, start, endPos, - Color.Orange, depth + 0.00001f, 0.2f); + GUI.Style.Orange, depth + 0.00001f, 0.2f); WireSection.Draw( spriteBatch, this, diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/StatusHUD.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/StatusHUD.cs index 2008e67a4..c2371bcb7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/StatusHUD.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/StatusHUD.cs @@ -3,6 +3,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; +using System.Linq; namespace Barotrauma.Items.Components { @@ -47,13 +48,22 @@ namespace Barotrauma.Items.Components private set; } - private List visibleCharacters = new List(); + private readonly List visibleCharacters = new List(); private const float UpdateInterval = 0.5f; private float updateTimer; private Character equipper; + public IEnumerable VisibleCharacters + { + get + { + if (equipper == null || equipper.Removed) { return Enumerable.Empty(); } + return visibleCharacters; + } + } + public override void Update(float deltaTime, Camera cam) { base.Update(deltaTime, cam); @@ -104,10 +114,10 @@ namespace Barotrauma.Items.Components public override void DrawHUD(SpriteBatch spriteBatch, Character character) { - if (character == null) return; - - GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), - Color.Green * 0.1f, true); + if (character == null) { return; } + + GUI.UIGlow.Draw(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), + Color.LightGreen * 0.5f); Character closestCharacter = null; float closestDist = float.PositiveInfinity; @@ -141,40 +151,40 @@ namespace Barotrauma.Items.Components if (target.Info != null) { texts.Add(target.Name); - textColors.Add(Color.White); + textColors.Add(GUI.Style.TextColor); } if (target.IsDead) { texts.Add(TextManager.Get("Deceased")); - textColors.Add(Color.Red); + textColors.Add(GUI.Style.Red); texts.Add( target.CauseOfDeath.Affliction?.CauseOfDeathDescription ?? TextManager.AddPunctuation(':', TextManager.Get("CauseOfDeath"), TextManager.Get("CauseOfDeath." + target.CauseOfDeath.Type.ToString()))); - textColors.Add(Color.Red); + textColors.Add(GUI.Style.Red); } else { if (target.IsUnconscious) { texts.Add(TextManager.Get("Unconscious")); - textColors.Add(Color.Orange); + textColors.Add(GUI.Style.Orange); } if (target.Stun > 0.01f) { texts.Add(TextManager.Get("Stunned")); - textColors.Add(Color.Orange); + textColors.Add(GUI.Style.Orange); } int oxygenTextIndex = MathHelper.Clamp((int)Math.Floor((1.0f - (target.Oxygen / 100.0f)) * OxygenTexts.Length), 0, OxygenTexts.Length - 1); texts.Add(OxygenTexts[oxygenTextIndex]); - textColors.Add(Color.Lerp(Color.Red, Color.Green, target.Oxygen / 100.0f)); + textColors.Add(Color.Lerp(GUI.Style.Red, GUI.Style.Green, target.Oxygen / 100.0f)); if (target.Bleeding > 0.0f) { int bleedingTextIndex = MathHelper.Clamp((int)Math.Floor(target.Bleeding / 100.0f) * BleedingTexts.Length, 0, BleedingTexts.Length - 1); texts.Add(BleedingTexts[bleedingTextIndex]); - textColors.Add(Color.Lerp(Color.Orange, Color.Red, target.Bleeding / 100.0f)); + textColors.Add(Color.Lerp(GUI.Style.Orange, GUI.Style.Red, target.Bleeding / 100.0f)); } var allAfflictions = target.CharacterHealth.GetAllAfflictions(); @@ -195,11 +205,11 @@ namespace Barotrauma.Items.Components foreach (AfflictionPrefab affliction in combinedAfflictionStrengths.Keys) { texts.Add(TextManager.AddPunctuation(':', affliction.Name, ((int)combinedAfflictionStrengths[affliction]).ToString() + " %")); - textColors.Add(Color.Lerp(Color.Orange, Color.Red, combinedAfflictionStrengths[affliction] / affliction.MaxStrength)); + textColors.Add(Color.Lerp(GUI.Style.Orange, GUI.Style.Red, combinedAfflictionStrengths[affliction] / affliction.MaxStrength)); } } - GUI.DrawString(spriteBatch, hudPos, texts[0], textColors[0] * alpha, Color.Black * 0.7f * alpha, 2); + GUI.DrawString(spriteBatch, hudPos, texts[0], textColors[0] * alpha, Color.Black * 0.7f * alpha, 2, GUI.SubHeadingFont); hudPos.X += 5.0f; hudPos.Y += 24.0f; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Turret.cs index a821fc1e8..ac65c1819 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Turret.cs @@ -116,7 +116,7 @@ namespace Barotrauma.Items.Components MinSize = new Point(100,20), RelativeOffset = new Vector2(0.0f, 0.01f) }, - barSize: 0.0f); + barSize: 0.0f, style: "DeviceProgressBar"); } public override void Move(Vector2 amount) @@ -131,7 +131,7 @@ namespace Barotrauma.Items.Components Vector2 particlePos = new Vector2(item.WorldRect.X + transformedBarrelPos.X, item.WorldRect.Y - transformedBarrelPos.Y); foreach (ParticleEmitter emitter in particleEmitters) { - emitter.Emit(1.0f, particlePos, hullGuess: null, angle: rotation, particleRotation: rotation); + emitter.Emit(1.0f, particlePos, hullGuess: null, angle: -rotation, particleRotation: rotation); } } @@ -260,12 +260,12 @@ namespace Barotrauma.Items.Components GUI.DrawLine(spriteBatch, drawPos, drawPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius, - Color.Green); + GUI.Style.Green); GUI.DrawLine(spriteBatch, drawPos, drawPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * widgetRadius, - Color.Green); + GUI.Style.Green); GUI.DrawLine(spriteBatch, drawPos, @@ -278,7 +278,7 @@ namespace Barotrauma.Items.Components { widget.MouseDown += () => { - widget.color = Color.Green; + widget.color = GUI.Style.Green; prevAngle = minRotation; }; widget.Deselected += () => @@ -319,7 +319,7 @@ namespace Barotrauma.Items.Components { widget.MouseDown += () => { - widget.color = Color.Green; + widget.color = GUI.Style.Green; prevAngle = minRotation; }; widget.Deselected += () => @@ -431,7 +431,7 @@ namespace Barotrauma.Items.Components bool readyToFire = reload <= 0.0f && charged && availableAmmo.Any(p => p != null); if (ShowChargeIndicator && PowerConsumption > 0.0f) { - powerIndicator.Color = charged ? Color.Green : Color.Red; + powerIndicator.Color = charged ? GUI.Style.Green : GUI.Style.Red; if (flashLowPower) { powerIndicator.BarSize = 1; @@ -452,7 +452,7 @@ namespace Barotrauma.Items.Components if (ShowProjectileIndicator) { - Point slotSize = new Point((int)(60 * GUI.Scale), (int)(30 * GUI.Scale)); + Point slotSize = (Inventory.SlotSpriteSmall.size * Inventory.UIScale).ToPoint(); int spacing = 5; int slotsPerRow = Math.Min(availableAmmo.Count, 6); int totalWidth = slotSize.X * slotsPerRow + spacing * (slotsPerRow - 1); @@ -469,7 +469,7 @@ namespace Barotrauma.Items.Components Rectangle rect = new Rectangle(invSlotPos.X, invSlotPos.Y, totalWidth, slotSize.Y); float inflate = MathHelper.Lerp(3, 8, (float)Math.Abs(1 * Math.Sin(flashTimer * 5))); rect.Inflate(inflate, inflate); - Color color = Color.Red * MathHelper.Max(0.5f, (float)Math.Sin(flashTimer * 12)); + Color color = GUI.Style.Red * MathHelper.Max(0.5f, (float)Math.Sin(flashTimer * 12)); GUI.DrawRectangle(spriteBatch, rect, color, thickness: 3); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs index c8ea831a4..f20ae801a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs @@ -131,7 +131,8 @@ namespace Barotrauma protected float prevHUDScale = GUI.Scale; protected Point prevScreenResolution; - protected static Sprite slotSpriteSmall, slotSpriteHorizontal, slotSpriteVertical, slotSpriteRound; + protected static Sprite slotSpriteHorizontal, slotSpriteVertical, slotSpriteRound, slotHotkeySprite; + public static Sprite SlotSpriteSmall; public static Sprite EquipIndicator, EquipIndicatorHighlight; public static Sprite DropIndicator, DropIndicatorHighlight; public static Inventory DraggingInventory; @@ -293,8 +294,7 @@ namespace Barotrauma Vector2 spacing = new Vector2(10 * UIScale, (10 + EquipIndicator.size.Y) * UIScale); Vector2 rectSize = new Vector2(60.0f * UIScale); - //y is larger to give more space for the header - padding = new Vector4(spacing.X, 40 * UIScale, spacing.X, spacing.X); + padding = new Vector4(spacing.X, spacing.Y, spacing.X, spacing.X); Vector2 slotAreaSize = new Vector2( columns * rectSize.X + (columns - 1) * spacing.X, @@ -546,9 +546,6 @@ namespace Barotrauma else { Rectangle subRect = slot.Rect; - subRect.Width = slots[slotIndex].SlotSprite == null ? (int)(60 * UIScale) : (int)(slots[slotIndex].SlotSprite.size.X * UIScale); - subRect.Height = (int)(60 * UIScale); - Vector2 spacing = new Vector2(10 * UIScale, (10 + EquipIndicator.size.Y) * UIScale); int columns = (int)Math.Max(Math.Floor(Math.Sqrt(itemCapacity)), 1); @@ -615,7 +612,7 @@ namespace Barotrauma if (canMove) { subInventory.movableFrameRect.X = subRect.X - (int)spacing.X; - subInventory.movableFrameRect.Y = subRect.Y + (int)(spacing.Y / 2f); + subInventory.movableFrameRect.Y = subRect.Y + (int)(spacing.Y); } slots[slotIndex].State = GUIComponent.ComponentState.Hover; } @@ -933,7 +930,7 @@ namespace Barotrauma selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f); } } - selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); + selectedInventory.slots[slotIndex].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f); } GUI.PlayUISound(GUISoundType.PickItem); } @@ -944,7 +941,7 @@ namespace Barotrauma } else { - if (selectedInventory.slots != null){ selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); } + if (selectedInventory.slots != null){ selectedInventory.slots[slotIndex].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f); } GUI.PlayUISound(GUISoundType.PickItemFail); } selectedInventory.HideTimer = 2.0f; @@ -1056,7 +1053,7 @@ namespace Barotrauma new Rectangle(itemPos.ToPoint() - new Point(iconSize / 2) - shadowBorders, new Point(iconSize + textWidth + textSpacing, iconSize) + shadowBorders.Multiply(2)), Color.Black * 0.8f); GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y - iconSize / 2), draggingItem.Name, Color.White); GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y), toolTip, - color: Character.Controlled.FocusedItem == null && !mouseOnHealthInterface ? Color.Red : Color.LightGreen, + color: Character.Controlled.FocusedItem == null && !mouseOnHealthInterface ? GUI.Style.Red : Color.LightGreen, font: GUI.SmallFont); } sprite.Draw(spriteBatch, itemPos + Vector2.One * 2, Color.Black, scale: scale); @@ -1075,7 +1072,7 @@ namespace Barotrauma } } - public static void DrawSlot(SpriteBatch spriteBatch, Inventory inventory, InventorySlot slot, Item item, int slotIndex, bool drawItem = true) + public static void DrawSlot(SpriteBatch spriteBatch, Inventory inventory, InventorySlot slot, Item item, int slotIndex, bool drawItem = true, InvSlotType type = InvSlotType.Any) { Rectangle rect = slot.Rect; rect.Location += slot.DrawOffset.ToPoint(); @@ -1086,6 +1083,7 @@ namespace Barotrauma rect.Inflate(rect.Width * inflateAmount, rect.Height * inflateAmount); } + Color slotColor = Color.White; var itemContainer = item?.GetComponent(); if (itemContainer != null && (itemContainer.InventoryTopSprite != null || itemContainer.InventoryBottomSprite != null)) { @@ -1099,8 +1097,18 @@ namespace Barotrauma } else { - Sprite slotSprite = slot.SlotSprite ?? slotSpriteSmall; - Color slotColor = slot.IsHighlighted ? Color.White : Color.White * 0.8f; + Sprite slotSprite = slot.SlotSprite ?? SlotSpriteSmall; + + if (inventory != null && (CharacterInventory.PersonalSlots.HasFlag(type) || (inventory.isSubInventory && (inventory.Owner as Item) != null + && (inventory.Owner as Item).AllowedSlots.Any(a => CharacterInventory.PersonalSlots.HasFlag(a))))) + { + slotColor = slot.IsHighlighted ? GUIColorSettings.EquipmentSlotColor : GUIColorSettings.EquipmentSlotColor * 0.8f; + } + else + { + slotColor = slot.IsHighlighted ? GUIColorSettings.InventorySlotColor : GUIColorSettings.InventorySlotColor * 0.8f; + } + if (inventory != null && inventory.Locked) { slotColor = Color.Gray * 0.5f; } spriteBatch.Draw(slotSprite.Texture, rect, slotSprite.SourceRect, slotColor); @@ -1125,7 +1133,7 @@ namespace Barotrauma } if (slot.MouseOn() && canBePut) { - GUI.UIGlow.Draw(spriteBatch, rect, Color.LightGreen); + GUI.UIGlow.Draw(spriteBatch, rect, GUI.Style.Green); } if (item != null && drawItem) @@ -1135,7 +1143,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Bottom - 8, rect.Width, 8), Color.Black * 0.8f, true); GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Bottom - 8, (int)(rect.Width * (item.Condition / item.MaxCondition)), 8), - Color.Lerp(Color.Red, Color.Green, item.Condition / item.MaxCondition) * 0.8f, true); + Color.Lerp(GUI.Style.Red, GUI.Style.Green, item.Condition / item.MaxCondition) * 0.8f, true); } if (itemContainer != null && itemContainer.ShowContainedStateIndicator) @@ -1163,7 +1171,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, containedIndicatorArea, Color.DarkGray * 0.9f, true); GUI.DrawRectangle(spriteBatch, new Rectangle(containedIndicatorArea.X, containedIndicatorArea.Y, (int)(containedIndicatorArea.Width * containedState), containedIndicatorArea.Height), - Color.Lerp(Color.Red, Color.Green, containedState) * 0.8f, true); + Color.Lerp(GUI.Style.Red, GUI.Style.Green, containedState) * 0.8f, true); } else { @@ -1172,7 +1180,7 @@ namespace Barotrauma containedIndicatorArea.Width / (float)indicatorSprite.SourceRect.Width, containedIndicatorArea.Height / (float)indicatorSprite.SourceRect.Height); - if (containedState >= 0.0f && containedState < 0.25f) + if (containedState >= 0.0f && containedState < 0.25f && inventory == Character.Controlled?.Inventory && Character.Controlled.HasEquippedItem(item)) { indicatorScale += ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) * 0.25f; } @@ -1183,7 +1191,7 @@ namespace Barotrauma rotate: 0.0f, scale: indicatorScale); - Color indicatorColor = ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.Green); + Color indicatorColor = ToolBox.GradientLerp(containedState, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green); if (inventory != null && inventory.Locked) { indicatorColor *= 0.5f; } spriteBatch.Draw(indicatorSprite.Texture, containedIndicatorArea.Center.ToVector2(), @@ -1212,7 +1220,7 @@ namespace Barotrauma if (item != null && drawItem) { Sprite sprite = item.Prefab.InventoryIcon ?? item.Sprite; - float scale = Math.Min(Math.Min((rect.Width - 10) / sprite.size.X, (rect.Height - 10) / sprite.size.Y), 3.0f); + float scale = Math.Min(Math.Min((rect.Width - 10) / sprite.size.X, (rect.Height - 10) / sprite.size.Y), 2.0f); Vector2 itemPos = rect.Center.ToVector2(); if (itemPos.Y > GameMain.GraphicsHeight) { @@ -1245,15 +1253,14 @@ namespace Barotrauma Character.Controlled?.Inventory == inventory && slot.QuickUseKey != Keys.None) { - GUI.DrawString(spriteBatch, rect.Location.ToVector2(), - slot.QuickUseKey.ToString().Substring(1, 1), - item == null || !drawItem ? Color.Gray : Color.White, - Color.Black * 0.8f); + spriteBatch.Draw(slotHotkeySprite.Texture, rect.ScaleSize(1.25f), slotHotkeySprite.SourceRect, slotColor); + GUI.DrawString(spriteBatch, rect.Location.ToVector2() + new Vector2(1, -2), slot.QuickUseKey.ToString().Substring(1, 1), Color.Black, font: GUI.SmallFont); } } public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime) { + UInt16 lastEventID = msg.ReadUInt16(); byte itemCount = msg.ReadByte(); receivedItemIDs = new ushort[itemCount]; for (int i = 0; i < itemCount; i++) @@ -1268,7 +1275,7 @@ namespace Barotrauma if (syncItemsDelay > 0.0f || GameMain.Client.MidRoundSyncing) { if (syncItemsCoroutine != null) CoroutineManager.StopCoroutines(syncItemsCoroutine); - syncItemsCoroutine = CoroutineManager.StartCoroutine(SyncItemsAfterDelay()); + syncItemsCoroutine = CoroutineManager.StartCoroutine(SyncItemsAfterDelay(lastEventID)); } else { @@ -1281,9 +1288,13 @@ namespace Barotrauma } } - private IEnumerable SyncItemsAfterDelay() + private IEnumerable SyncItemsAfterDelay(UInt16 lastEventID) { - while (syncItemsDelay > 0.0f || (GameMain.Client != null && GameMain.Client.MidRoundSyncing)) + while (syncItemsDelay > 0.0f || + //don't apply inventory updates until + // 1. MidRound syncing is done AND + // 2. We've received all the events created before the update was written (otherwise we may not yet know about some items the server has spawned in the inventory) + (GameMain.Client != null && (GameMain.Client.MidRoundSyncing || NetIdUtils.IdMoreRecent(lastEventID, GameMain.Client.EntityEventManager.LastReceivedID)))) { syncItemsDelay = Math.Max((float)(syncItemsDelay - Timing.Step), 0.0f); yield return CoroutineStatus.Running; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs index baba28d31..a29077494 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs @@ -52,7 +52,7 @@ namespace Barotrauma if (itemInUseWarning == null) { itemInUseWarning = new GUITextBlock(new RectTransform(new Point(10), GUI.Canvas), "", - textColor: Color.Orange, color: Color.Black, + textColor: GUI.Style.Orange, color: Color.Black, textAlignment: Alignment.Center, style: "OuterGlow"); } return itemInUseWarning; @@ -195,7 +195,7 @@ namespace Barotrauma if (!Visible || (!editing && HiddenInGame)) return; if (editing && !ShowItems) return; - Color color = IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? Color.Orange : GetSpriteColor(); + Color color = IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? GUI.Style.Orange : GetSpriteColor(); //if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f); BrokenItemSprite fadeInBrokenSprite = null; @@ -364,7 +364,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, rectWorldPos, new Vector2(transformedTrigger.Width, transformedTrigger.Height), - Color.Green, + GUI.Style.Green, false, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); @@ -376,7 +376,7 @@ namespace Barotrauma foreach (MapEntity e in linkedTo) { bool isLinkAllowed = prefab.IsLinkAllowed(e.prefab); - Color lineColor = Color.Red * 0.5f; + Color lineColor = GUI.Style.Red * 0.5f; if (isLinkAllowed) { lineColor = e is Item i && (DisplaySideBySideWhenLinked || i.DisplaySideBySideWhenLinked) ? Color.Purple * 0.5f : Color.LightGreen * 0.5f; @@ -525,32 +525,19 @@ namespace Barotrauma { var linkText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, heightScaled)), TextManager.Get("HoldToLink"), font: GUI.SmallFont); var itemsText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, heightScaled)), TextManager.Get("AllowedLinks"), font: GUI.SmallFont); - if (AllowedLinks.None()) - { - itemsText.Text += TextManager.Get("None"); - } - else - { - for (int i = 0; i < AllowedLinks.Count; i++) - { - itemsText.Text += AllowedLinks[i]; - if (i < AllowedLinks.Count - 1) - { - itemsText.Text += ", "; - } - } - } + string allowedItems = AllowedLinks.None() ? TextManager.Get("None") :string.Join(", ", AllowedLinks); + itemsText.Text = TextManager.AddPunctuation(':', itemsText.Text, allowedItems); itemEditor.AddCustomContent(linkText, 1); itemEditor.AddCustomContent(itemsText, 2); - linkText.TextColor = Color.Yellow; - itemsText.TextColor = Color.Yellow; + linkText.TextColor = GUI.Style.Orange; + itemsText.TextColor = GUI.Style.Orange; } var buttonContainer = new GUILayoutGroup(new RectTransform(new Point(listBox.Content.Rect.Width, heightScaled)), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.02f }; - new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX")) + new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall") { ToolTip = TextManager.Get("MirrorEntityXToolTip"), OnClicked = (button, data) => @@ -559,7 +546,7 @@ namespace Barotrauma return true; } }; - new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY")) + new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall") { ToolTip = TextManager.Get("MirrorEntityYToolTip"), OnClicked = (button, data) => @@ -570,7 +557,7 @@ namespace Barotrauma }; if (Sprite != null) { - var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite")); + var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"), style: "GUIButtonSmall"); reloadTextureButton.OnClicked += (button, data) => { Sprite.ReloadXML(); @@ -578,7 +565,7 @@ namespace Barotrauma return true; }; } - new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ResetToPrefab")) + new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ResetToPrefab"), style: "GUIButtonSmall") { OnClicked = (button, data) => { @@ -587,6 +574,7 @@ namespace Barotrauma return true; } }; + buttonContainer.RectTransform.MinSize = new Point(0, buttonContainer.RectTransform.Children.Max(c => c.MinSize.Y)); itemEditor.AddCustomContent(buttonContainer, itemEditor.ContentCount); GUITextBlock.AutoScaleAndNormalize(buttonContainer.Children.Select(b => ((GUIButton)b).TextBlock)); } @@ -595,15 +583,17 @@ namespace Barotrauma { if (inGame) { - if (!ic.AllowInGameEditing) continue; - if (SerializableProperty.GetProperties(ic).Count == 0) continue; + if (!ic.AllowInGameEditing) { continue; } + if (SerializableProperty.GetProperties(ic).Count == 0) { continue; } } else { - if (ic.requiredItems.Count == 0 && ic.DisabledRequiredItems.Count == 0 && SerializableProperty.GetProperties(ic).Count == 0) continue; + if (ic.requiredItems.Count == 0 && ic.DisabledRequiredItems.Count == 0 && SerializableProperty.GetProperties(ic).Count == 0) { continue; } } - var componentEditor = new SerializableEntityEditor(listBox.Content.RectTransform, ic, inGame, showName: !inGame); + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), listBox.Content.RectTransform), style: "HorizontalLine"); + + var componentEditor = new SerializableEntityEditor(listBox.Content.RectTransform, ic, inGame, showName: !inGame, titleFont: GUI.SubHeadingFont); componentEditor.Children.First().Color = Color.Black * 0.7f; if (inGame) @@ -625,7 +615,7 @@ namespace Barotrauma foreach (RelatedItem relatedItem in requiredItems) { - var textBlock = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, heightScaled)), + var textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width, heightScaled)), relatedItem.Type.ToString() + " required", font: GUI.SmallFont) { Padding = new Vector4(10.0f, 0.0f, 10.0f, 0.0f) @@ -637,6 +627,7 @@ namespace Barotrauma Font = GUI.SmallFont, Text = relatedItem.JoinedIdentifiers }; + textBlock.RectTransform.Resize(new Point(textBlock.Rect.Width, namesBox.RectTransform.MinSize.Y)); namesBox.OnDeselected += (textBox, key) => { @@ -713,17 +704,17 @@ namespace Barotrauma if (GameMain.GameSession?.CrewManager != null && Screen.Selected == GameMain.GameScreen) { int disallowedPadding = (int)(50 * GUI.Scale); - disallowedAreas.Add(GameMain.GameSession.CrewManager.GetCharacterListArea()); + disallowedAreas.Add(GameMain.GameSession.CrewManager.GetActiveCrewArea()); disallowedAreas.Add(new Rectangle( HUDLayoutSettings.ChatBoxArea.X - disallowedPadding, HUDLayoutSettings.ChatBoxArea.Y, HUDLayoutSettings.ChatBoxArea.Width + disallowedPadding, HUDLayoutSettings.ChatBoxArea.Height)); } - GUI.PreventElementOverlap(elementsToMove, disallowedAreas, - new Rectangle( - 20, 20, - GameMain.GraphicsWidth - 40, - HUDLayoutSettings.InventoryTopY > 0 ? HUDLayoutSettings.InventoryTopY - 40 : GameMain.GraphicsHeight - 80)); + //GUI.PreventElementOverlap(elementsToMove, disallowedAreas, + // new Rectangle( + // 0, 20, + // GameMain.GraphicsWidth, + // HUDLayoutSettings.InventoryTopY > 0 ? HUDLayoutSettings.InventoryTopY - 40 : GameMain.GraphicsHeight - 80)); foreach (ItemComponent ic in activeHUDs) { @@ -1125,10 +1116,10 @@ namespace Barotrauma catch (Exception e) { DebugConsole.ThrowError("Exception in PhysicsBody.Enabled = false (" + body.PhysEnabled + ")", e); - if (body.UserData != null) DebugConsole.NewMessage("PhysicsBody UserData: " + body.UserData.GetType().ToString(), Color.Red); - if (GameMain.World.ContactManager == null) DebugConsole.NewMessage("ContactManager is null!", Color.Red); - else if (GameMain.World.ContactManager.BroadPhase == null) DebugConsole.NewMessage("Broadphase is null!", Color.Red); - if (body.FarseerBody.FixtureList == null) DebugConsole.NewMessage("FixtureList is null!", Color.Red); + if (body.UserData != null) DebugConsole.NewMessage("PhysicsBody UserData: " + body.UserData.GetType().ToString(), GUI.Style.Red); + if (GameMain.World.ContactManager == null) DebugConsole.NewMessage("ContactManager is null!", GUI.Style.Red); + else if (GameMain.World.ContactManager.BroadPhase == null) DebugConsole.NewMessage("Broadphase is null!", GUI.Style.Red); + if (body.FarseerBody.FixtureList == null) DebugConsole.NewMessage("FixtureList is null!", GUI.Style.Red); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemInventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemInventory.cs index 7483ce030..d637d1aa6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/ItemInventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/ItemInventory.cs @@ -1,4 +1,5 @@ -using Microsoft.Xna.Framework; +using System; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System.Linq; @@ -6,8 +7,6 @@ namespace Barotrauma { partial class ItemInventory : Inventory { - private string uiLabel; - protected override void ControlInput(Camera cam) { base.ControlInput(cam); @@ -75,30 +74,7 @@ namespace Barotrauma 0.0f, UIScale); } - if (container.InventoryTopSprite == null) - { - if (uiLabel == null || uiLabel == string.Empty) - { - if (container.UILabel != null && container.UILabel.Length > 0) - { - uiLabel = TextManager.Get("UILabel." + container.UILabel); - } - else - { - Item item = Owner as Item; - uiLabel = item?.Name; - } - } - - if (!string.IsNullOrEmpty(uiLabel) && !subInventory) - { - uiLabel = ToolBox.WrapText(uiLabel, BackgroundFrame.Width, GUI.Font, 1); - GUI.DrawString(spriteBatch, - new Vector2((int)(BackgroundFrame.Center.X - GUI.Font.MeasureString(uiLabel).X / 2), (int)BackgroundFrame.Y + 5), - uiLabel, Color.White * 0.9f); - } - } - else if (!subInventory) + if (container.InventoryTopSprite != null && !subInventory) { container.InventoryTopSprite.Draw(spriteBatch, new Vector2(BackgroundFrame.Center.X, BackgroundFrame.Y), 0.0f, UIScale); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs index cb07ca96b..b2fc35ae7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Gap.cs @@ -27,8 +27,8 @@ namespace Barotrauma if (GameMain.DebugDraw) { Vector2 center = new Vector2(WorldRect.X + rect.Width / 2.0f, -(WorldRect.Y - rect.Height / 2.0f)); - GUI.DrawLine(sb, center, center + new Vector2(flowForce.X, -flowForce.Y) / 10.0f, Color.Red); - GUI.DrawLine(sb, center + Vector2.One * 5.0f, center + new Vector2(lerpedFlowForce.X, -lerpedFlowForce.Y) / 10.0f + Vector2.One * 5.0f, Color.Orange); + GUI.DrawLine(sb, center, center + new Vector2(flowForce.X, -flowForce.Y) / 10.0f, GUI.Style.Red); + GUI.DrawLine(sb, center + Vector2.One * 5.0f, center + new Vector2(lerpedFlowForce.X, -lerpedFlowForce.Y) / 10.0f + Vector2.One * 5.0f, GUI.Style.Orange); if (outsideCollisionBlocker.Enabled && Submarine != null) { @@ -43,7 +43,7 @@ namespace Barotrauma if (!editing || !ShowGaps) return; - Color clr = (open == 0.0f) ? Color.Red : Color.Cyan; + Color clr = (open == 0.0f) ? GUI.Style.Red : Color.Cyan; if (IsHighlighted) clr = Color.Gold; float depth = (ID % 255) * 0.000001f; @@ -109,7 +109,7 @@ namespace Barotrauma GUI.DrawRectangle(sb, new Vector2(WorldRect.X - 5, -WorldRect.Y - 5), new Vector2(rect.Width + 10, rect.Height + 10), - Color.Red, + GUI.Style.Red, false, depth, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs index f31869a90..baf8124c6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs @@ -86,7 +86,7 @@ namespace Barotrauma { editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this }; GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null); - new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true); + new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont); PositionEditingHUD(); @@ -260,7 +260,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height), - Color.Red * ((100.0f - OxygenPercentage) / 400.0f), true, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); + GUI.Style.Red * ((100.0f - OxygenPercentage) / 400.0f), true, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); if (GameMain.DebugDraw) { @@ -271,14 +271,14 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, (int)(100 * Math.Min(waterVolume / Volume, 1.0f))), Color.Cyan, true); if (WaterVolume > Volume) { - GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, (int)(100 * (waterVolume - Volume) / MaxCompress)), Color.Red, true); + GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, (int)(100 * (waterVolume - Volume) / MaxCompress)), GUI.Style.Red, true); } GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, 100), Color.Black); foreach (FireSource fs in FireSources) { Rectangle fireSourceRect = new Rectangle((int)fs.WorldPosition.X, -(int)fs.WorldPosition.Y, (int)fs.Size.X, (int)fs.Size.Y); - GUI.DrawRectangle(spriteBatch, fireSourceRect, Color.Orange, false, 0, 5); + GUI.DrawRectangle(spriteBatch, fireSourceRect, GUI.Style.Orange, false, 0, 5); //GUI.DrawRectangle(spriteBatch, new Rectangle((int)fs.LastExtinguishPos.X, (int)-fs.LastExtinguishPos.Y, 5,5), Color.Yellow, true); } @@ -296,7 +296,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, new Vector2(drawRect.X + 5, -drawRect.Y + 5), new Vector2(rect.Width - 10, rect.Height - 10), - IsHighlighted ? Color.LightBlue * 0.5f : Color.Red * 0.5f, true, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); + IsHighlighted ? Color.LightBlue * 0.5f : GUI.Style.Red * 0.5f, true, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); } foreach (MapEntity e in linkedTo) @@ -322,7 +322,7 @@ namespace Barotrauma GUI.DrawLine(spriteBatch, new Vector2(currentHullRect.X, -currentHullRect.Y), new Vector2(connectedHullRect.X, -connectedHullRect.Y), - Color.Green, width: 2); + GUI.Style.Green, width: 2); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelObjects/LevelObjectManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelObjects/LevelObjectManager.cs index bf2231d4f..a792836fb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelObjects/LevelObjectManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelObjects/LevelObjectManager.cs @@ -142,7 +142,7 @@ namespace Barotrauma if (GameMain.DebugDraw) { - GUI.DrawRectangle(spriteBatch, new Vector2(obj.Position.X, -obj.Position.Y), new Vector2(10.0f, 10.0f), Color.Red, true); + GUI.DrawRectangle(spriteBatch, new Vector2(obj.Position.X, -obj.Position.Y), new Vector2(10.0f, 10.0f), GUI.Style.Red, true); foreach (LevelTrigger trigger in obj.Triggers) { @@ -153,7 +153,7 @@ namespace Barotrauma if (flowForce.LengthSquared() > 1) { flowForce.Y = -flowForce.Y; - GUI.DrawLine(spriteBatch, new Vector2(trigger.WorldPosition.X, -trigger.WorldPosition.Y), new Vector2(trigger.WorldPosition.X, -trigger.WorldPosition.Y) + flowForce * 10, Color.Orange, 0, 5); + GUI.DrawLine(spriteBatch, new Vector2(trigger.WorldPosition.X, -trigger.WorldPosition.Y), new Vector2(trigger.WorldPosition.X, -trigger.WorldPosition.Y) + flowForce * 10, GUI.Style.Orange, 0, 5); } trigger.PhysicsBody.UpdateDrawPosition(); trigger.PhysicsBody.DebugDraw(spriteBatch, trigger.IsTriggered ? Color.Cyan : Color.DarkCyan); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelRenderer.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelRenderer.cs index 2697e3d77..07ac14679 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelRenderer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelRenderer.cs @@ -259,7 +259,7 @@ namespace Barotrauma GUI.DrawLine(spriteBatch, new Vector2(nodeList[i - 1].X, -nodeList[i - 1].Y), new Vector2(nodeList[i].X, -nodeList[i].Y), - Color.Lerp(Color.Yellow, Color.Red, i / (float)nodeList.Count), 0, 10); + Color.Lerp(Color.Yellow, GUI.Style.Red, i / (float)nodeList.Count), 0, 10); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/Ruins/RuinGenerator.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/Ruins/RuinGenerator.cs index 664d68d99..6238f2d5d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/Ruins/RuinGenerator.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/Ruins/RuinGenerator.cs @@ -13,7 +13,7 @@ namespace Barotrauma.RuinGeneration } foreach (Line line in walls) { - GUI.DrawLine(spriteBatch, new Vector2(line.A.X, -line.A.Y), new Vector2(line.B.X, -line.B.Y), Color.Red, 0.0f, 10); + GUI.DrawLine(spriteBatch, new Vector2(line.A.X, -line.A.Y), new Vector2(line.B.X, -line.B.Y), GUI.Style.Red, 0.0f, 10); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Lights/LightSource.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Lights/LightSource.cs index 734c85027..fe2abefaf 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Lights/LightSource.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Lights/LightSource.cs @@ -985,16 +985,16 @@ namespace Barotrauma.Lights if (CastShadows && Screen.Selected == GameMain.SubEditorScreen) { - GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 20, Vector2.One * 40, Color.Orange, isFilled: false); - GUI.DrawLine(spriteBatch, drawPos - Vector2.One * 20, drawPos + Vector2.One * 20, Color.Orange); - GUI.DrawLine(spriteBatch, drawPos - new Vector2(1.0f, -1.0f) * 20, drawPos + new Vector2(1.0f, -1.0f) * 20, Color.Orange); + GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 20, Vector2.One * 40, GUI.Style.Orange, isFilled: false); + GUI.DrawLine(spriteBatch, drawPos - Vector2.One * 20, drawPos + Vector2.One * 20, GUI.Style.Orange); + GUI.DrawLine(spriteBatch, drawPos - new Vector2(1.0f, -1.0f) * 20, drawPos + new Vector2(1.0f, -1.0f) * 20, GUI.Style.Orange); } //visualize light recalculations float timeSinceRecalculation = (float)Timing.TotalTime - lastRecalculationTime; if (timeSinceRecalculation < 0.1f) { - GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 10, Vector2.One * 20, Color.Red * (1.0f - timeSinceRecalculation * 10.0f), isFilled: true); + GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 10, Vector2.One * 20, GUI.Style.Red * (1.0f - timeSinceRecalculation * 10.0f), isFilled: true); GUI.DrawLine(spriteBatch, drawPos - Vector2.One * Range, drawPos + Vector2.One * Range, Color); GUI.DrawLine(spriteBatch, drawPos - new Vector2(1.0f, -1.0f) * Range, drawPos + new Vector2(1.0f, -1.0f) * Range, Color); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/LinkedSubmarine.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/LinkedSubmarine.cs index 2e6f1db13..215fd0d52 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/LinkedSubmarine.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/LinkedSubmarine.cs @@ -3,6 +3,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System.IO; +using System.Linq; using System.Xml.Linq; namespace Barotrauma @@ -13,8 +14,8 @@ namespace Barotrauma { if (!editing || wallVertices == null) return; - Color color = (IsHighlighted) ? Color.Orange : Color.Green; - if (IsSelected) color = Color.Red; + Color color = (IsHighlighted) ? GUI.Style.Orange : GUI.Style.Green; + if (IsSelected) color = GUI.Style.Red; Vector2 pos = Position; @@ -38,7 +39,7 @@ namespace Barotrauma Rectangle drawRect = rect; drawRect.Y = -rect.Y; - GUI.DrawRectangle(spriteBatch, drawRect, Color.Red, true); + GUI.DrawRectangle(spriteBatch, drawRect, GUI.Style.Red, true); if (!Item.ShowLinks) return; @@ -49,7 +50,7 @@ namespace Barotrauma GUI.DrawLine(spriteBatch, new Vector2(WorldPosition.X, -WorldPosition.Y), new Vector2(e.WorldPosition.X, -e.WorldPosition.Y), - isLinkAllowed ? Color.LightGreen * 0.5f : Color.Red * 0.5f, width: 3); + isLinkAllowed ? GUI.Style.Green * 0.5f : GUI.Style.Red * 0.5f, width: 3); } } @@ -83,18 +84,14 @@ namespace Barotrauma private GUIComponent CreateEditingHUD(bool inGame = false) { - int width = 450, height = 120; - int x = GameMain.GraphicsWidth / 2 - width / 2, y = 30; - - editingHUD = new GUIFrame(new RectTransform(new Point(width, height), GUI.Canvas) { ScreenSpaceOffset = new Point(x, y) }) + editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { - UserData = this + UserData = this }; - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), editingHUD.RectTransform, Anchor.Center)) { Stretch = true, - RelativeSpacing = 0.05f + AbsoluteSpacing = (int)(GUI.Scale * 5) }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), @@ -103,19 +100,24 @@ namespace Barotrauma if (!inGame) { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), - TextManager.Get("LinkLinkedSub"), textColor: Color.Yellow, font: GUI.SmallFont); + TextManager.Get("LinkLinkedSub"), textColor: GUI.Style.Orange, font: GUI.SmallFont); } var pathContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), isHorizontal: true); - var pathBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), pathContainer.RectTransform), filePath, font: GUI.SmallFont); - var reloadButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), pathContainer.RectTransform), TextManager.Get("ReloadLinkedSub")) + var pathBox = new GUITextBox(new RectTransform(new Vector2(0.75f, 1.0f), pathContainer.RectTransform), filePath, font: GUI.SmallFont); + var reloadButton = new GUIButton(new RectTransform(new Vector2(0.25f / pathBox.RectTransform.RelativeSize.X, 1.0f), pathBox.RectTransform, Anchor.CenterRight, Pivot.CenterLeft), + TextManager.Get("ReloadLinkedSub"), style: "GUIButtonSmall") { OnClicked = Reload, UserData = pathBox, ToolTip = TextManager.Get("ReloadLinkedSubTooltip") }; + editingHUD.RectTransform.Resize(new Point( + editingHUD.Rect.Width, + (int)(paddedFrame.Children.Sum(c => c.Rect.Height + paddedFrame.AbsoluteSpacing) / paddedFrame.RectTransform.RelativeSize.Y))); + PositionEditingHUD(); return editingHUD; @@ -128,7 +130,7 @@ namespace Barotrauma if (!File.Exists(pathBox.Text)) { new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariable("ReloadLinkedSubError", "[file]", pathBox.Text)); - pathBox.Flash(Color.Red); + pathBox.Flash(GUI.Style.Red); pathBox.Text = filePath; return false; } @@ -136,7 +138,7 @@ namespace Barotrauma XDocument doc = Submarine.OpenFile(pathBox.Text); if (doc == null || doc.Root == null) return false; - pathBox.Flash(Color.Green); + pathBox.Flash(GUI.Style.Green); GenerateWallVertices(doc.Root); saveElement = doc.Root; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs index 1188ea50b..afbfdcf3b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs @@ -510,7 +510,7 @@ namespace Barotrauma MapGenerationParams.Instance.LargeLevelConnectionLength, connection.Length); - connectionColor = ToolBox.GradientLerp(sizeFactor, Color.LightGreen, Color.Orange, Color.Red); + connectionColor = ToolBox.GradientLerp(sizeFactor, Color.LightGreen, GUI.Style.Orange, GUI.Style.Red); } else { @@ -667,10 +667,10 @@ namespace Barotrauma pos.Y -= 5 * zoom; Vector2 size = GUI.LargeFont.MeasureString(location.Name); GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw( - spriteBatch, new Rectangle((int)pos.X - 30, (int)pos.Y, (int)size.X + 60, (int)(size.Y + 25 * GUI.Scale)), Color.Black * hudOpenState * 0.7f); + spriteBatch, new Rectangle((int)pos.X - 30, (int)(pos.Y - 10), (int)size.X + 60, (int)(size.Y + 50 * GUI.Scale)), Color.Black * hudOpenState * 0.7f); GUI.DrawString(spriteBatch, pos, location.Name, Color.White * hudOpenState * 1.5f, font: GUI.LargeFont); - GUI.DrawString(spriteBatch, pos + Vector2.UnitY * 25 * GUI.Scale, + GUI.DrawString(spriteBatch, pos + Vector2.UnitY * size.Y * 0.8f, location.Type.Name, Color.White * hudOpenState * 1.5f); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs index 8af490237..dd34c8037 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs @@ -8,6 +8,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; +using System.Linq; namespace Barotrauma { @@ -78,12 +79,12 @@ namespace Barotrauma int heightScaled = (int)(20 * GUI.Scale); editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this }; GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null); - var editor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true); + var editor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUI.LargeFont); var buttonContainer = new GUILayoutGroup(new RectTransform(new Point(listBox.Content.Rect.Width, heightScaled)), isHorizontal: true) { Stretch = true, - RelativeSpacing = 0.02f + RelativeSpacing = 0.01f }; new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX")) { @@ -103,7 +104,7 @@ namespace Barotrauma return true; } }; - var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite")) + new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite")) { OnClicked = (button, data) => { @@ -121,6 +122,8 @@ namespace Barotrauma return true; } }; + GUITextBlock.AutoScaleAndNormalize(buttonContainer.Children.Where(c => c is GUIButton).Select(b => ((GUIButton)b).TextBlock)); + buttonContainer.RectTransform.Resize(new Point(buttonContainer.Rect.Width, buttonContainer.RectTransform.Children.Max(c => c.MinSize.Y))); editor.AddCustomContent(buttonContainer, editor.ContentCount); PositionEditingHUD(); @@ -191,7 +194,7 @@ namespace Barotrauma if (HasBody && !ShowWalls) return; } - Color color = IsHighlighted ? Color.Orange : spriteColor; + Color color = IsHighlighted ? GUI.Style.Orange : spriteColor; if (IsSelected && editing) { //color = Color.Lerp(color, Color.Gold, 0.5f); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Submarine.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Submarine.cs index a8c75e533..b290632f0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Submarine.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Submarine.cs @@ -342,22 +342,24 @@ namespace Barotrauma public void CreatePreviewWindow(GUIComponent parent) { - var upperPart = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.5f), parent.RectTransform, Anchor.Center, Pivot.BottomCenter)); - var descriptionBox = new GUIListBox(new RectTransform(new Vector2(1, 0.5f), parent.RectTransform, Anchor.Center, Pivot.TopCenter)) - { - ScrollBarVisible = true, - Spacing = 5 - }; + var content = new GUIFrame(new RectTransform(Vector2.One, parent.RectTransform), style: null); if (PreviewImage == null) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 1), upperPart.RectTransform), TextManager.Get(SavedSubmarines.Contains(this) ? "SubPreviewImageNotFound" : "SubNotDownloaded")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), TextManager.Get(SavedSubmarines.Contains(this) ? "SubPreviewImageNotFound" : "SubNotDownloaded")); } else { - var submarinePreviewBackground = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), upperPart.RectTransform)) { Color = Color.Black }; - new GUIImage(new RectTransform(new Vector2(1.0f, 1.0f), submarinePreviewBackground.RectTransform), PreviewImage, scaleToFit: true); + var submarinePreviewBackground = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), style: null) { Color = Color.Black }; + new GUIImage(new RectTransform(new Vector2(0.98f), submarinePreviewBackground.RectTransform, Anchor.Center), PreviewImage, scaleToFit: true); + new GUIFrame(new RectTransform(Vector2.One, submarinePreviewBackground.RectTransform), "InnerGlow", color: Color.Black); } + var descriptionBox = new GUIListBox(new RectTransform(new Vector2(1, 0.5f), content.RectTransform, Anchor.BottomCenter)) + { + UserData = "descriptionbox", + ScrollBarVisible = true, + Spacing = 5 + }; //space new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), descriptionBox.Content.RectTransform), style: null); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/WayPoint.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/WayPoint.cs index cb39d7be5..195cb57a4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/WayPoint.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/WayPoint.cs @@ -41,7 +41,7 @@ namespace Barotrauma { clr = Color.Black; } - if (IsSelected) clr = Color.Red; + if (IsSelected) clr = GUI.Style.Red; if (IsHighlighted) clr = Color.DarkRed; int iconX = iconIndices[(int)spawnType] * IconSize % iconTexture.Width; @@ -74,7 +74,7 @@ namespace Barotrauma GUI.DrawLine(spriteBatch, drawPos, new Vector2(e.DrawPosition.X, -e.DrawPosition.Y), - isObstructed ? Color.Gray : Color.Green, width: 5); + isObstructed ? Color.Gray : GUI.Style.Green, width: 5); } GUI.SmallFont.DrawString(spriteBatch, @@ -193,7 +193,7 @@ namespace Barotrauma { IdCardDesc = text; textBox.Text = text; - textBox.Color = Color.Green; + textBox.Color = GUI.Style.Green; textBox.Deselect(); @@ -203,14 +203,14 @@ namespace Barotrauma { IdCardTags = text.Split(','); textBox.Text = string.Join(",", IdCardTags); - textBox.Flash(Color.Green); + textBox.Flash(GUI.Style.Green); textBox.Deselect(); return true; } private bool TextBoxChanged(GUITextBox textBox, string text) { - textBox.Color = Color.Red; + textBox.Color = GUI.Style.Red; return true; } @@ -234,12 +234,12 @@ namespace Barotrauma if (spawnType == SpawnType.Path) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), TextManager.Get("Editing") + " " + TextManager.Get("Waypoint")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), TextManager.Get("Waypoint"), font: GUI.LargeFont); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), TextManager.Get("LinkWaypoint")); } else { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), TextManager.Get("Editing") + " " + TextManager.Get("Spawnpoint")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), TextManager.Get("Spawnpoint"), font: GUI.LargeFont); var spawnTypeContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), isHorizontal: true) { @@ -248,7 +248,7 @@ namespace Barotrauma }; new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), spawnTypeContainer.RectTransform), TextManager.Get("SpawnType")); - var button = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), spawnTypeContainer.RectTransform), "-") + var button = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), spawnTypeContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton") { UserData = -1, OnClicked = ChangeSpawnType @@ -257,13 +257,12 @@ namespace Barotrauma { UserData = "spawntypetext" }; - button = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), spawnTypeContainer.RectTransform), "+") + button = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), spawnTypeContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton") { UserData = 1, OnClicked = ChangeSpawnType }; - var descText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), TextManager.Get("IDCardDescription"), font: GUI.SmallFont); GUITextBox propertyBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), descText.RectTransform, Anchor.CenterRight), idCardDesc) @@ -274,7 +273,6 @@ namespace Barotrauma }; propertyBox.OnTextChanged += TextBoxChanged; - var tagsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform), TextManager.Get("IDCardTags"), font: GUI.SmallFont); propertyBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), tagsText.RectTransform, Anchor.CenterRight), string.Join(", ", idCardTags)) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs index 54e2d9418..1dffec685 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/BanList.cs @@ -1,6 +1,7 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; +using System.Linq; namespace Barotrauma.Networking { @@ -44,9 +45,9 @@ namespace Barotrauma.Networking foreach (BannedPlayer bannedPlayer in bannedPlayers) { - if (localRemovedBans.Contains(bannedPlayer.UniqueIdentifier)) continue; + if (localRemovedBans.Contains(bannedPlayer.UniqueIdentifier)) { continue; } - var playerFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), ((GUIListBox)banFrame).Content.RectTransform) { MinSize = new Point(0, 70) }, style: null) + var playerFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), ((GUIListBox)banFrame).Content.RectTransform) { MinSize = new Point(0, 70) }) { UserData = banFrame }; @@ -54,42 +55,56 @@ namespace Barotrauma.Networking var paddedPlayerFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.85f), playerFrame.RectTransform, Anchor.Center)) { Stretch = true, - RelativeSpacing = 0.05f + RelativeSpacing = 0.05f, + CanBeFocused = true + }; + + var topArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.0f), paddedPlayerFrame.RectTransform), + isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + Stretch = true, + RelativeSpacing = 0.02f }; string ip = bannedPlayer.IP; if (localRangeBans.Contains(bannedPlayer.UniqueIdentifier)) ip = ToRange(ip); - GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), paddedPlayerFrame.RectTransform), + GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), topArea.RectTransform), bannedPlayer.Name + " (" + ip + ")"); + textBlock.RectTransform.MinSize = new Point(textBlock.Rect.Width, 0); - var removeButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.4f), paddedPlayerFrame.RectTransform, Anchor.TopRight), TextManager.Get("BanListRemove")) - { - UserData = bannedPlayer, - IgnoreLayoutGroups = true, - OnClicked = RemoveBan - }; if (bannedPlayer.IP.IndexOf(".x") <= -1) { - var rangeBanButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.4f), paddedPlayerFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.22f, 0.0f) }, TextManager.Get("BanRange")) + var rangeBanButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.4f), topArea.RectTransform), + TextManager.Get("BanRange"), style: "GUIButtonSmall") { UserData = bannedPlayer, - IgnoreLayoutGroups = true, OnClicked = RangeBan }; } + var removeButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.4f), topArea.RectTransform), + TextManager.Get("BanListRemove"), style: "GUIButtonSmall") + { + UserData = bannedPlayer, + OnClicked = RemoveBan + }; + topArea.RectTransform.MinSize = new Point(0, (int)topArea.RectTransform.Children.Max(c => c.Rect.Height * 1.25f)); - new GUITextBlock(new RectTransform(new Vector2(0.6f, 0.0f), paddedPlayerFrame.RectTransform), + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedPlayerFrame.RectTransform), bannedPlayer.ExpirationTime == null ? TextManager.Get("BanPermanent") : TextManager.GetWithVariable("BanExpires", "[time]", bannedPlayer.ExpirationTime.Value.ToString()), font: GUI.SmallFont); - var reasonText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 0.0f), paddedPlayerFrame.RectTransform), + var reasonText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedPlayerFrame.RectTransform), TextManager.Get("BanReason") + " " + - (string.IsNullOrEmpty(bannedPlayer.Reason) ? TextManager.Get("None") : ToolBox.LimitString(bannedPlayer.Reason, GUI.SmallFont, 170)), + (string.IsNullOrEmpty(bannedPlayer.Reason) ? TextManager.Get("None") : bannedPlayer.Reason), font: GUI.SmallFont, wrap: true) { ToolTip = bannedPlayer.Reason }; + + paddedPlayerFrame.Recalculate(); + + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), ((GUIListBox)banFrame).Content.RectTransform), style: "HorizontalLine"); } return banFrame; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ChildServerRelay.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ChildServerRelay.cs index 05f77097c..e0915a5af 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ChildServerRelay.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ChildServerRelay.cs @@ -26,7 +26,6 @@ namespace Barotrauma.Networking PrivateStart(); processInfo.Arguments += " -pipes " + writePipe.GetClientHandleAsString() + " " + readPipe.GetClientHandleAsString(); - DebugConsole.NewMessage(processInfo.Arguments, Microsoft.Xna.Framework.Color.Orange); Process = Process.Start(processInfo); localHandlesDisposed = false; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index eaf08af43..7fd043161 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -128,6 +128,11 @@ namespace Barotrauma.Networking get { return entityEventManager.MidRoundSyncing; } } + public ClientEntityEventManager EntityEventManager + { + get { return entityEventManager; } + } + private object serverEndpoint; private int ownerKey; private bool steamP2POwner; @@ -1028,33 +1033,39 @@ namespace Barotrauma.Networking if (!IsServerOwner) { GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData as string == "permissions"); + GUIMessageBox msgBox = new GUIMessageBox("", "") { UserData = "permissions" }; + msgBox.Content.ClearChildren(); + msgBox.Content.RectTransform.RelativeSize = new Vector2(0.95f, 0.9f); - string msg = ""; - if (newPermissions == ClientPermissions.None) + var header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgBox.Content.RectTransform), TextManager.Get("PermissionsChanged"), textAlignment: Alignment.Center, font: GUI.LargeFont); + header.RectTransform.IsFixedSize = true; + + var permissionArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), msgBox.Content.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; + var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), permissionArea.RectTransform)) { Stretch = true, RelativeSpacing = 0.05f }; + var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), permissionArea.RectTransform)) { Stretch = true, RelativeSpacing = 0.05f }; + + var permissionsLabel = new GUITextBlock(new RectTransform(new Vector2(newPermissions == ClientPermissions.None ? 2.0f : 1.0f, 0.0f), leftColumn.RectTransform), + TextManager.Get(newPermissions == ClientPermissions.None ? "PermissionsRemoved" : "CurrentPermissions"), + wrap: true, font: (newPermissions == ClientPermissions.None ? GUI.Font : GUI.SubHeadingFont)); + permissionsLabel.RectTransform.NonScaledSize = new Point(permissionsLabel.Rect.Width, permissionsLabel.Rect.Height); + permissionsLabel.RectTransform.IsFixedSize = true; + if (newPermissions != ClientPermissions.None) { - msg = TextManager.Get("PermissionsRemoved"); - } - else - { - msg = TextManager.Get("CurrentPermissions") + '\n'; + string permissionList = ""; foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions))) { - if (!newPermissions.HasFlag(permission) || permission == ClientPermissions.None) continue; - msg += " - " + TextManager.Get("ClientPermission." + permission) + "\n"; + if (!newPermissions.HasFlag(permission) || permission == ClientPermissions.None) { continue; } + permissionList += " - " + TextManager.Get("ClientPermission." + permission) + "\n"; } + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), leftColumn.RectTransform), + permissionList); } - GUIMessageBox msgBox = new GUIMessageBox(TextManager.Get("PermissionsChanged"), msg) - { - UserData = "permissions" - }; - if (newPermissions.HasFlag(ClientPermissions.ConsoleCommands)) { - int listBoxWidth = (int)(msgBox.InnerFrame.Rect.Width) / 2 - 30; - new GUITextBlock(new RectTransform(new Vector2(0.4f, 0.1f), msgBox.InnerFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.05f, 0.15f) }, - TextManager.Get("PermittedConsoleCommands"), wrap: true, font: GUI.SmallFont); - var commandList = new GUIListBox(new RectTransform(new Vector2(0.4f, 0.55f), msgBox.InnerFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.05f, 0.25f) }); + var commandsLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), rightColumn.RectTransform), + TextManager.Get("PermittedConsoleCommands"), wrap: true, font: GUI.SubHeadingFont); + var commandList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform)); foreach (string permittedCommand in permittedConsoleCommands) { new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), commandList.Content.RectTransform, minSize: new Point(0, 15)), @@ -1063,7 +1074,23 @@ namespace Barotrauma.Networking CanBeFocused = false }; } + permissionsLabel.RectTransform.NonScaledSize = commandsLabel.RectTransform.NonScaledSize = + new Point(permissionsLabel.Rect.Width, Math.Max(permissionsLabel.Rect.Height, commandsLabel.Rect.Height)); + commandsLabel.RectTransform.IsFixedSize = true; } + + new GUIButton(new RectTransform(new Vector2(0.5f, 0.05f), msgBox.Content.RectTransform), TextManager.Get("ok")) + { + OnClicked = msgBox.Close + }; + + permissionArea.RectTransform.MinSize = new Point(0, Math.Max( leftColumn.RectTransform.Children.Sum(c => c.Rect.Height), rightColumn.RectTransform.Children.Sum(c => c.Rect.Height))); + permissionArea.RectTransform.IsFixedSize = true; + int contentHeight = (int)(msgBox.Content.RectTransform.Children.Sum(c => c.Rect.Height + msgBox.Content.AbsoluteSpacing) * 1.05f); + msgBox.Content.ChildAnchor = Anchor.TopCenter; + msgBox.Content.Stretch = true; + msgBox.Content.RectTransform.MinSize = new Point(0, contentHeight); + msgBox.InnerFrame.RectTransform.MinSize = new Point(0, (int)(contentHeight / permissionArea.RectTransform.RelativeSize.Y / msgBox.Content.RectTransform.RelativeSize.Y)); } GameMain.NetLobbyScreen.UpdatePermissions(); @@ -2488,7 +2515,7 @@ namespace Barotrauma.Networking //oscillate between 0-1 float phase = (float)(Math.Sin(timeLeft * MathHelper.Pi) + 1.0f) * 0.5f; textScale = 1.0f + phase * 0.5f; - textColor = Color.Lerp(Color.Red, Color.White, 1.0f - phase); + textColor = Color.Lerp(GUI.Style.Red, Color.White, 1.0f - phase); } } @@ -2536,14 +2563,17 @@ namespace Barotrauma.Networking var client = GameMain.NetworkMember.ConnectedClients.Find(c => c.Character == character); if (client == null) { return false; } - var mute = new GUITickBox(new RectTransform(new Vector2(0.95f, 0.1f), characterFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) }, + var content = new GUIFrame(new RectTransform(new Vector2(0.9f, 1.0f - characterFrame.RectTransform.RelativeSize.Y), characterFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter), + style: null); + + var mute = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform, Anchor.TopCenter), TextManager.Get("Mute")) { Selected = client.MutedLocally, OnSelected = (tickBox) => { client.MutedLocally = tickBox.Selected; return true; } }; - var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.1f), characterFrame.RectTransform, Anchor.BottomCenter), isHorizontal: true) + var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform, Anchor.BottomCenter), isHorizontal: true) { RelativeSpacing = 0.05f, ChildAnchor = Anchor.CenterLeft, @@ -2553,7 +2583,7 @@ namespace Barotrauma.Networking if (HasPermission(ClientPermissions.Ban)) { var banButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("Ban")) + TextManager.Get("Ban"), style: "GUIButtonSmall") { UserData = client, OnClicked = (btn, userdata) => { GameMain.NetLobbyScreen.BanPlayer(client); return false; } @@ -2562,7 +2592,7 @@ namespace Barotrauma.Networking if (HasPermission(ClientPermissions.Kick)) { var kickButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("Kick")) + TextManager.Get("Kick"), style: "GUIButtonSmall") { UserData = client, OnClicked = (btn, userdata) => { GameMain.NetLobbyScreen.KickPlayer(client); return false; } @@ -2571,7 +2601,7 @@ namespace Barotrauma.Networking else if (serverSettings.Voting.AllowVoteKick) { var kickVoteButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("VoteToKick")) + TextManager.Get("VoteToKick"), style: "GUIButtonSmall") { UserData = client, OnClicked = (btn, userdata) => { VoteForKick(client); btn.Enabled = false; return true; } @@ -2708,6 +2738,19 @@ namespace Barotrauma.Networking errorLines.Add("Event ID: " + eventID + ", entity ID " + entityID); } + if (GameMain.GameSession?.GameMode != null) + { + errorLines.Add("Game mode: " + GameMain.GameSession.GameMode.Name); + } + if (GameMain.GameSession?.Submarine != null) + { + errorLines.Add("Submarine: " + GameMain.GameSession.Submarine.Name); + } + if (Level.Loaded != null) + { + errorLines.Add("Level: " + Level.Loaded.Seed + ", " + Level.Loaded.EqualityCheckVal); + } + errorLines.Add("Entity IDs:"); List sortedEntities = Entity.GetEntityList(); sortedEntities.Sort((e1, e2) => e1.ID.CompareTo(e2.ID)); @@ -2716,9 +2759,20 @@ namespace Barotrauma.Networking errorLines.Add(e.ID + ": " + e.ToString()); } + errorLines.Add(""); + errorLines.Add("Last debug messages:"); + for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i--) + { + errorLines.Add(" " + DebugConsole.Messages[i].Time + " - " + DebugConsole.Messages[i].Text); + } + string filePath = "event_error_log_client_" + Name + "_" + ToolBox.RemoveInvalidFileNameChars(DateTime.UtcNow.ToShortTimeString() + ".log"); filePath = Path.Combine(ServerLog.SavePath, filePath); + if (!Directory.Exists(ServerLog.SavePath)) + { + Directory.CreateDirectory(ServerLog.SavePath); + } File.WriteAllLines(filePath, errorLines); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/KarmaManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/KarmaManager.cs index e47611943..4f1bc98e0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/KarmaManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/KarmaManager.cs @@ -1,6 +1,7 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; +using System.Linq; using System.Text; namespace Barotrauma @@ -14,41 +15,43 @@ namespace Barotrauma CreateLabeledTickBox(parent, "ResetKarmaBetweenRounds"); } - CreateLabeledSlider(parent, 0.0f, 40.0f, 1.0f, "KickBanThreshold"); + CreateLabeledSlider(parent, 0.0f, 40.0f, 1.0f, nameof(KickBanThreshold)); if (TextManager.ContainsTag("Karma.KicksBeforeBan")) { - CreateLabeledNumberInput(parent, 0, 10, "KicksBeforeBan"); + CreateLabeledNumberInput(parent, 0, 10, nameof(KicksBeforeBan)); } - CreateLabeledSlider(parent, 0.0f, 50.0f, 1.0f, "HerpesThreshold"); + CreateLabeledSlider(parent, 0.0f, 50.0f, 1.0f, nameof(HerpesThreshold)); - CreateLabeledSlider(parent, 0.0f, 0.5f, 0.01f, "KarmaDecay"); - CreateLabeledSlider(parent, 50.0f, 100.0f, 1.0f, "KarmaDecayThreshold"); - CreateLabeledSlider(parent, 0.0f, 0.5f, 0.01f, "KarmaIncrease"); - CreateLabeledSlider(parent, 0.0f, 50.0f, 1.0f, "KarmaIncreaseThreshold"); + CreateLabeledSlider(parent, 0.0f, 0.5f, 0.01f, nameof(KarmaDecay)); + CreateLabeledSlider(parent, 50.0f, 100.0f, 1.0f, nameof(KarmaDecayThreshold)); + CreateLabeledSlider(parent, 0.0f, 0.5f, 0.01f, nameof(KarmaIncrease)); + CreateLabeledSlider(parent, 0.0f, 50.0f, 1.0f, nameof(KarmaIncreaseThreshold)); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.12f), parent.RectTransform), TextManager.Get("Karma.PositiveActions"), textAlignment: Alignment.Center) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.12f), parent.RectTransform), TextManager.Get("Karma.PositiveActions"), + textAlignment: Alignment.Center, font: GUI.SubHeadingFont) { CanBeFocused = false }; - CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "StructureRepairKarmaIncrease"); - CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "HealFriendlyKarmaIncrease"); - CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "DamageEnemyKarmaIncrease"); - CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "ItemRepairKarmaIncrease"); - CreateLabeledSlider(parent, 0.0f, 10.0f, 0.05f, "ExtinguishFireKarmaIncrease"); + CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, nameof(StructureRepairKarmaIncrease)); + CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, nameof(HealFriendlyKarmaIncrease)); + CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, nameof(DamageEnemyKarmaIncrease)); + CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, nameof(ItemRepairKarmaIncrease)); + CreateLabeledSlider(parent, 0.0f, 10.0f, 0.05f, nameof(ExtinguishFireKarmaIncrease)); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.12f), parent.RectTransform), TextManager.Get("Karma.NegativeActions"), textAlignment: Alignment.Center) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.12f), parent.RectTransform), TextManager.Get("Karma.NegativeActions"), + textAlignment: Alignment.Center, font: GUI.SubHeadingFont) { CanBeFocused = false }; - CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "StructureDamageKarmaDecrease"); - CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, "DamageFriendlyKarmaDecrease"); - CreateLabeledSlider(parent, 0.0f, 100.0f, 1.0f, "ReactorMeltdownKarmaDecrease"); - CreateLabeledSlider(parent, 0.0f, 10.0f, 0.05f, "ReactorOverheatKarmaDecrease"); - CreateLabeledNumberInput(parent, 0, 20, "AllowedWireDisconnectionsPerMinute"); - CreateLabeledSlider(parent, 0.0f, 20.0f, 0.5f, "WireDisconnectionKarmaDecrease"); - CreateLabeledSlider(parent, 0.0f, 30.0f, 1.0f, "SpamFilterKarmaDecrease"); + CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, nameof(StructureDamageKarmaDecrease)); + CreateLabeledSlider(parent, 0.0f, 1.0f, 0.01f, nameof(DamageFriendlyKarmaDecrease)); + CreateLabeledSlider(parent, 0.0f, 100.0f, 1.0f, nameof(ReactorMeltdownKarmaDecrease)); + CreateLabeledSlider(parent, 0.0f, 10.0f, 0.05f, nameof(ReactorOverheatKarmaDecrease)); + CreateLabeledNumberInput(parent, 0, 20, nameof(AllowedWireDisconnectionsPerMinute)); + CreateLabeledSlider(parent, 0.0f, 20.0f, 0.5f, nameof(WireDisconnectionKarmaDecrease)); + CreateLabeledSlider(parent, 0.0f, 30.0f, 1.0f, nameof(SpamFilterKarmaDecrease)); } private void CreateLabeledSlider(GUIComponent parent, float min, float max, float step, string propertyName) @@ -61,13 +64,13 @@ namespace Barotrauma }; string labelText = TextManager.Get("Karma." + propertyName); - var label = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.8f), container.RectTransform), - labelText, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), container.RectTransform), + labelText, textAlignment: Alignment.CenterLeft, font: GUI.SmallFont) { ToolTip = TextManager.Get("Karma." + propertyName + "ToolTip") }; - var slider = new GUIScrollBar(new RectTransform(new Vector2(0.3f, 0.8f), container.RectTransform), barSize: 0.1f) + var slider = new GUIScrollBar(new RectTransform(new Vector2(0.3f, 1.0f), container.RectTransform), barSize: 0.1f, style: "GUISlider") { Step = step <= 0.0f ? 0.0f : step / (max - min), Range = new Vector2(min, max), @@ -80,6 +83,7 @@ namespace Barotrauma return true; } }; + container.RectTransform.MinSize = new Point(0, container.RectTransform.Children.Max(c => c.MinSize.Y)); GameMain.NetworkMember.ServerSettings.AssignGUIComponent(propertyName, slider); slider.OnMoved(slider, slider.BarScroll); } @@ -94,16 +98,18 @@ namespace Barotrauma }; string labelText = TextManager.Get("Karma." + propertyName); - new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.8f), container.RectTransform), labelText, font: GUI.SmallFont) + new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), container.RectTransform), labelText, textAlignment: Alignment.CenterLeft, font: GUI.SmallFont) { ToolTip = TextManager.Get("Karma." + propertyName + "ToolTip") }; - var numInput = new GUINumberInput(new RectTransform(new Vector2(0.3f, 0.8f), container.RectTransform), GUINumberInput.NumberType.Int) + var numInput = new GUINumberInput(new RectTransform(new Vector2(0.3f, 1.0f), container.RectTransform), GUINumberInput.NumberType.Int) { MinValueInt = min, MaxValueInt = max }; + + container.RectTransform.MinSize = new Point(0, container.RectTransform.Children.Max(c => c.MinSize.Y)); GameMain.NetworkMember.ServerSettings.AssignGUIComponent(propertyName, numInput); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs index 4ae4a887b..0e06cf296 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetEntityEvent/ClientEntityEventManager.cs @@ -195,7 +195,7 @@ namespace Barotrauma.Networking DebugConsole.NewMessage( "Received msg " + thisEventID + " (waiting for " + (lastReceivedID + 1) + ")", NetIdUtils.IdMoreRecent(thisEventID, (UInt16)(lastReceivedID + 1)) - ? Microsoft.Xna.Framework.Color.Red + ? GUI.Style.Red : Microsoft.Xna.Framework.Color.Yellow); } } @@ -203,7 +203,7 @@ namespace Barotrauma.Networking { DebugConsole.NewMessage( "Received msg " + thisEventID + ", entity " + entityID + " not found", - Microsoft.Xna.Framework.Color.Red); + GUI.Style.Red); GameMain.Client.ReportError(ClientNetError.MISSING_ENTITY, eventID: thisEventID, entityID: entityID); return false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetStats.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetStats.cs index 4cf86271e..90cd0a00e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/NetStats.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/NetStats.cs @@ -65,9 +65,9 @@ namespace Barotrauma.Networking graphs[(int)NetStatType.ReceivedBytes].Draw(spriteBatch, rect, null, 0.0f, Color.Cyan); - graphs[(int)NetStatType.SentBytes].Draw(spriteBatch, rect, null, 0.0f, Color.Orange); + graphs[(int)NetStatType.SentBytes].Draw(spriteBatch, rect, null, 0.0f, GUI.Style.Orange); - graphs[(int)NetStatType.ResentMessages].Draw(spriteBatch, rect, null, 0.0f, Color.Red); + graphs[(int)NetStatType.ResentMessages].Draw(spriteBatch, rect, null, 0.0f, GUI.Style.Red); GUI.SmallFont.DrawString(spriteBatch, "Peak received: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.ReceivedBytes].LargestValue()) + "/s " + @@ -77,17 +77,17 @@ namespace Barotrauma.Networking GUI.SmallFont.DrawString(spriteBatch, "Peak sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].LargestValue()) + "/s " + "Avg sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].Average()) + "/s", - new Vector2(rect.Right + 10, rect.Y + 30), Color.Orange); + new Vector2(rect.Right + 10, rect.Y + 30), GUI.Style.Orange); GUI.SmallFont.DrawString(spriteBatch, "Peak resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s", - new Vector2(rect.Right + 10, rect.Y + 50), Color.Red); + new Vector2(rect.Right + 10, rect.Y + 50), GUI.Style.Red); #if DEBUG /*int y = 10; foreach (KeyValuePair msgBytesSent in server.messageCount.OrderBy(key => -key.Value)) { GUI.SmallFont.DrawString(spriteBatch, msgBytesSent.Key + ": " + MathUtils.GetBytesReadable(msgBytesSent.Value), - new Vector2(rect.Right - 200, rect.Y + y), Color.Red); + new Vector2(rect.Right - 200, rect.Y + y), GUI.Style.Red); y += 15; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs index b00a4ccb9..d315062c3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/LidgrenClientPeer.cs @@ -83,6 +83,14 @@ namespace Barotrauma.Networking { if (!isActive) { return; } + if (ownerKey != 0 && (ChildServerRelay.Process?.HasExited ?? true)) + { + Close(); + var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), TextManager.Get("ServerProcessClosed")); + msgBox.Buttons[0].OnClicked += (btn, obj) => { GameMain.MainMenuScreen.Select(); return false; }; + return; + } + netClient.ReadMessages(incomingLidgrenMessages); foreach (NetIncomingMessage inc in incomingLidgrenMessages) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs index f8ddaf7ac..04c664c92 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/SteamP2POwnerPeer.cs @@ -188,6 +188,14 @@ namespace Barotrauma.Networking { if (!isActive) { return; } + if (ChildServerRelay.HasShutDown || (ChildServerRelay.Process?.HasExited ?? true)) + { + Close(); + var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), TextManager.Get("ServerProcessClosed")); + msgBox.Buttons[0].OnClicked += (btn, obj) => { GameMain.MainMenuScreen.Select(); return false; }; + return; + } + for (int i = remotePeers.Count - 1; i >= 0; i--) { if (remotePeers[i].DisconnectTime != null && remotePeers[i].DisconnectTime < Timing.TotalTime) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs index 3a73813b3..37c70df02 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs @@ -109,27 +109,21 @@ namespace Barotrauma.Networking { frame.ClearChildren(); - if (frame == null) return; + if (frame == null) { return; } - var previewContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), frame.RectTransform, Anchor.Center)) + var previewContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.98f), frame.RectTransform, Anchor.Center)) { Stretch = true }; - var titleContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.035f), previewContainer.RectTransform), true) - { - Color = Color.White * 0.2f - }; - - var title = new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.0f), titleContainer.RectTransform, Anchor.CenterLeft), ServerName, font: GUI.LargeFont) + var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), previewContainer.RectTransform, Anchor.CenterLeft), ServerName, font: GUI.LargeFont) { ToolTip = ServerName }; - title.Text = ToolBox.LimitString(title.Text, title.Font, title.Rect.Width); + title.Text = ToolBox.LimitString(title.Text, title.Font, (int)(title.Rect.Width * 0.85f)); - title.Padding = new Vector4(10, 0, 0, 10); - - GUITickBox favoriteTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.85f), titleContainer.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(0.0f, 0.1f) }, "", null, "GUIServerListFavoriteTickBox") + GUITickBox favoriteTickBox = new GUITickBox(new RectTransform(new Vector2(0.15f, 0.8f), title.RectTransform, Anchor.CenterRight), + "", null, "GUIServerListFavoriteTickBox") { Selected = Favorite, ToolTip = TextManager.Get(Favorite ? "removefromfavorites" : "addtofavorites"), @@ -153,44 +147,59 @@ namespace Barotrauma.Networking PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious; - Sprite playStyleBannerSprite = GameMain.ServerListScreen.PlayStyleBanners[(int)playStyle]; - float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / (playStyleBannerSprite.SourceRect.Height * 0.65f); - var playStyleBanner = new GUIImage(new RectTransform(new Vector2(1.0f, 1.0f / playStyleBannerAspectRatio), previewContainer.RectTransform, Anchor.TopCenter, scaleBasis: ScaleBasis.BothWidth), + Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle]; + float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height; + var playStyleBanner = new GUIImage(new RectTransform(new Point(previewContainer.Rect.Width, (int)(previewContainer.Rect.Width / playStyleBannerAspectRatio)), previewContainer.RectTransform), playStyleBannerSprite, null, true); var playStyleName = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) { RelativeOffset = new Vector2(0.01f, 0.06f) }, TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag."+ playStyle)), textColor: Color.White, font: GUI.SmallFont, textAlignment: Alignment.Center, - color: GameMain.ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader"); + color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader"); playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint(); playStyleName.RectTransform.IsFixedSize = true; - - var columnContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.45f), previewContainer.RectTransform), isHorizontal: true) + var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform)) { Stretch = true }; + // playstyle tags ----------------------------------------------------------------------------- - // Left column ------------------------------------------------------------------------------- - var leftColumnHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 1.0f), columnContainer.RectTransform), childAnchor: Anchor.Center) + var playStyleContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), content.RectTransform), isHorizontal: true) { - Stretch = true + Stretch = true, + RelativeSpacing = 0.01f, + CanBeFocused = true }; - var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1.0f), leftColumnHolder.RectTransform)) + var playStyleTags = GetPlayStyleTags(); + foreach (string tag in playStyleTags) { - Stretch = true - }; + if (!ServerListScreen.PlayStyleIcons.ContainsKey(tag)) { continue; } + + new GUIImage(new RectTransform(Vector2.One, playStyleContainer.RectTransform), + ServerListScreen.PlayStyleIcons[tag], scaleToFit: true) + { + ToolTip = TextManager.Get("servertagdescription." + tag), + Color = ServerListScreen.PlayStyleIconColors[tag] + }; + } + + playStyleContainer.Recalculate(); + + // ----------------------------------------------------------------------------- float elementHeight = 0.075f; // Spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.025f), leftColumn.RectTransform), style: null); + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.025f), content.RectTransform), style: null); - var serverMsg = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), leftColumn.RectTransform)) { ScrollBarVisible = true }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverMsg.Content.RectTransform), ServerMessage, font: GUI.SmallFont, wrap: true) { CanBeFocused = false }; + var serverMsg = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform)) { ScrollBarVisible = true }; + var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverMsg.Content.RectTransform), ServerMessage, font: GUI.SmallFont, wrap: true) { CanBeFocused = true }; + serverMsg.Content.RectTransform.SizeChanged += () => { msgText.CalculateHeightFromText(); }; + msgText.RectTransform.SizeChanged += () => { serverMsg.UpdateScrollBarSize(); }; - var gameMode = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), leftColumn.RectTransform), TextManager.Get("GameMode")); + var gameMode = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("GameMode")); new GUITextBlock(new RectTransform(Vector2.One, gameMode.RectTransform), TextManager.Get(string.IsNullOrEmpty(GameMode) ? "Unknown" : "GameMode." + GameMode, returnNull: true) ?? GameMode, textAlignment: Alignment.Right); @@ -198,13 +207,21 @@ namespace Barotrauma.Networking /*var traitors = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), bodyContainer.RectTransform), TextManager.Get("Traitors")); new GUITextBlock(new RectTransform(Vector2.One, traitors.RectTransform), TextManager.Get(!TraitorsEnabled.HasValue ? "Unknown" : TraitorsEnabled.Value.ToString()), textAlignment: Alignment.Right);*/ - var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), leftColumn.RectTransform), TextManager.Get("ServerListSubSelection")); + var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("ServerListSubSelection")); new GUITextBlock(new RectTransform(Vector2.One, subSelection.RectTransform), TextManager.Get(!SubSelectionMode.HasValue ? "Unknown" : SubSelectionMode.Value.ToString()), textAlignment: Alignment.Right); - var modeSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), leftColumn.RectTransform), TextManager.Get("ServerListModeSelection")); + var modeSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("ServerListModeSelection")); new GUITextBlock(new RectTransform(Vector2.One, modeSelection.RectTransform), TextManager.Get(!ModeSelectionMode.HasValue ? "Unknown" : ModeSelectionMode.Value.ToString()), textAlignment: Alignment.Right); - var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), leftColumn.RectTransform), TextManager.Get("ServerListAllowSpectating")) + if (gameMode.TextSize.X + gameMode.GetChild().TextSize.X > gameMode.Rect.Width || + subSelection.TextSize.X + subSelection.GetChild().TextSize.X > subSelection.Rect.Width || + modeSelection.TextSize.X + modeSelection.GetChild().TextSize.X > modeSelection.Rect.Width) + { + gameMode.Font = subSelection.Font = modeSelection.Font = GUI.SmallFont; + gameMode.GetChild().Font = subSelection.GetChild().Font = modeSelection.GetChild().Font = GUI.SmallFont; + } + + var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerListAllowSpectating")) { CanBeFocused = false }; @@ -213,7 +230,7 @@ namespace Barotrauma.Networking else allowSpectating.Selected = AllowSpectating.Value; - var allowRespawn = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), leftColumn.RectTransform), TextManager.Get("ServerSettingsAllowRespawning")) + var allowRespawn = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerSettingsAllowRespawning")) { CanBeFocused = false }; @@ -231,7 +248,7 @@ namespace Barotrauma.Networking else voipEnabledTickBox.Selected = VoipEnabled.Value;*/ - var usingWhiteList = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), leftColumn.RectTransform), TextManager.Get("ServerListUsingWhitelist")) + var usingWhiteList = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerListUsingWhitelist")) { CanBeFocused = false }; @@ -241,15 +258,15 @@ namespace Barotrauma.Networking usingWhiteList.Selected = UsingWhiteList.Value; - leftColumn.RectTransform.SizeChanged += () => + content.RectTransform.SizeChanged += () => { GUITextBlock.AutoScaleAndNormalize(allowSpectating.TextBlock, allowRespawn.TextBlock, usingWhiteList.TextBlock); }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), leftColumn.RectTransform), - TextManager.Get("ServerListContentPackages")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), + TextManager.Get("ServerListContentPackages"), textAlignment: Alignment.Center, font: GUI.SubHeadingFont); - var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), leftColumn.RectTransform)) { ScrollBarVisible = true }; + var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform)) { ScrollBarVisible = true }; if (ContentPackageNames.Count == 0) { new GUITextBlock(new RectTransform(Vector2.One, contentPackageList.Content.RectTransform), TextManager.Get("Unknown"), textAlignment: Alignment.Center) @@ -278,7 +295,7 @@ namespace Barotrauma.Networking //matching content package found, but it hasn't been enabled if (ContentPackage.List.Any(cp => cp.MD5hash.Hash == ContentPackageHashes[i])) { - packageText.TextColor = Color.Orange; + packageText.TextColor = GUI.Style.Orange; packageText.ToolTip = TextManager.GetWithVariable("ServerListContentPackageNotEnabled", "[contentpackage]", ContentPackageNames[i]); } //workshop download link found @@ -290,7 +307,7 @@ namespace Barotrauma.Networking } else //no package or workshop download link found, tough luck { - packageText.TextColor = Color.Red; + packageText.TextColor = GUI.Style.Red; packageText.ToolTip = TextManager.GetWithVariables("ServerListIncompatibleContentPackage", new string[2] { "[contentpackage]", "[hash]" }, new string[2] { ContentPackageNames[i], ContentPackageHashes[i] }); } @@ -298,7 +315,7 @@ namespace Barotrauma.Networking } if (availableWorkshopUrls.Count > 0) { - var workshopBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), leftColumn.RectTransform), TextManager.Get("ServerListSubscribeMissingPackages")) + var workshopBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), content.RectTransform), TextManager.Get("ServerListSubscribeMissingPackages")) { ToolTip = TextManager.Get(SteamManager.IsInitialized ? "ServerListSubscribeMissingPackagesTooltip" : "ServerListSubscribeMissingPackagesTooltipNoSteam"), Enabled = SteamManager.IsInitialized, @@ -313,50 +330,11 @@ namespace Barotrauma.Networking } } - // Spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform), style: null); - - // Right column ------------------------------------------------------------------------------ - - var rightColumnBackground = new GUIFrame(new RectTransform(new Vector2(0.2f, 1.0f), columnContainer.RectTransform), style: null) - { - Color = Color.Black * 0.25f - }; - - var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1.0f), rightColumnBackground.RectTransform, Anchor.Center)); - - // playstyle tags ----------------------------------------------------------------------------- - - var playStyleTags = GetPlayStyleTags(); - foreach (string tag in playStyleTags) - { - if (!GameMain.ServerListScreen.PlayStyleIcons.ContainsKey(tag)) { continue; } - - new GUIImage(new RectTransform(Vector2.One, rightColumn.RectTransform, scaleBasis: ScaleBasis.BothWidth), - GameMain.ServerListScreen.PlayStyleIcons[tag], scaleToFit: true) - { - ToolTip = TextManager.Get("servertagdescription." + tag), - Color = GameMain.ServerListScreen.PlayStyleIconColors[tag] - }; - } - - - /*var playerCount = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListPlayers")); - new GUITextBlock(new RectTransform(Vector2.One, playerCount.RectTransform), PlayerCount + "/" + MaxPlayers, textAlignment: Alignment.Right); - - - new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), "Round running") - { - Selected = GameStarted, - CanBeFocused = false - };*/ - - // ----------------------------------------------------------------------------- - foreach (GUIComponent c in leftColumn.Children) + foreach (GUIComponent c in content.Children) { - if (c is GUITextBlock textBlock) textBlock.Padding = Vector4.Zero; + if (c is GUITextBlock textBlock) { textBlock.Padding = Vector4.Zero; } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs index 0f2b51e58..229e0c7b1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs @@ -25,27 +25,11 @@ namespace Barotrauma.Networking }; GUIFrame innerFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.5f), LogFrame.RectTransform, Anchor.Center) { MinSize = new Point(700, 500) }); - GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.85f), innerFrame.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, -0.03f) }, style: null); + GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), innerFrame.RectTransform, Anchor.Center), style: null); - new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.05f), paddedFrame.RectTransform, Anchor.TopRight), TextManager.Get("ServerLog.Filter"), font: GUI.SmallFont); - GUITextBox searchBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 0.05f), paddedFrame.RectTransform, Anchor.TopRight), font: GUI.SmallFont); - searchBox.OnTextChanged += (textBox, text) => - { - msgFilter = text; - FilterMessages(); - return true; - }; - GUI.KeyboardDispatcher.Subscriber = searchBox; + // left column ---------------- - var clearButton = new GUIButton(new RectTransform(new Vector2(0.05f, 0.05f), paddedFrame.RectTransform, Anchor.TopRight), "x") - { - OnClicked = ClearFilter, - UserData = searchBox - }; - - listBox = new GUIListBox(new RectTransform(new Vector2(0.75f, 0.95f), paddedFrame.RectTransform, Anchor.BottomRight)); - - var tickBoxContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 0.95f), paddedFrame.RectTransform, Anchor.BottomLeft)); + var tickBoxContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 1.0f), paddedFrame.RectTransform, Anchor.BottomLeft)); int y = 30; List tickBoxes = new List(); foreach (MessageType msgType in Enum.GetValues(typeof(MessageType))) @@ -61,6 +45,7 @@ namespace Barotrauma.Networking return true; } }; + tickBox.TextBlock.SelectedTextColor = tickBox.TextBlock.TextColor; tickBox.Selected = !msgTypeHidden[(int)msgType]; tickBoxes.Add(tickBox); @@ -72,19 +57,32 @@ namespace Barotrauma.Networking GUITextBlock.AutoScaleAndNormalize(tickBoxes.Select(t => t.TextBlock), defaultScale: 1.0f); }; - var currLines = lines.ToList(); + // right column ---------------- - foreach (LogMessage line in currLines) + var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 1.0f), paddedFrame.RectTransform, Anchor.CenterRight), childAnchor: Anchor.TopRight) { - AddLine(line); - } - FilterMessages(); + Stretch = true, + RelativeSpacing = 0.02f + }; - listBox.UpdateScrollBarSize(); + GUILayoutGroup filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform, Anchor.TopRight), + isHorizontal: true, childAnchor: Anchor.CenterLeft); - if (listBox.BarScroll == 0.0f || listBox.BarScroll == 1.0f) listBox.BarScroll = 1.0f; + new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), filterArea.RectTransform), TextManager.Get("ServerLog.Filter"), + font: GUI.SubHeadingFont); + GUITextBox searchBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.SmallFont, createClearButton: true); + searchBox.OnTextChanged += (textBox, text) => + { + msgFilter = text; + FilterMessages(); + return true; + }; + GUI.KeyboardDispatcher.Subscriber = searchBox; + filterArea.RectTransform.MinSize = new Point(0, filterArea.RectTransform.Children.Max(c => c.MinSize.Y)); - GUIButton closeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.05f), innerFrame.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.02f, 0.03f) }, TextManager.Get("Close")) + listBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.95f), rightColumn.RectTransform)); + + GUIButton closeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.05f), rightColumn.RectTransform), TextManager.Get("Close")) { OnClicked = (button, userData) => { @@ -93,6 +91,19 @@ namespace Barotrauma.Networking } }; + rightColumn.Recalculate(); + + var currLines = lines.ToList(); + foreach (LogMessage line in currLines) + { + AddLine(line); + } + FilterMessages(); + + listBox.UpdateScrollBarSize(); + + if (listBox.BarScroll == 0.0f || listBox.BarScroll == 1.0f) { listBox.BarScroll = 1.0f; } + msgFilter = ""; } @@ -110,7 +121,7 @@ namespace Barotrauma.Networking List tickBoxes = new List(); foreach (MessageType msgType in Enum.GetValues(typeof(MessageType))) { - var tickBox = new GUITickBox(new RectTransform(new Point(tickBoxContainer.Rect.Width, 16), tickBoxContainer.RectTransform), TextManager.Get("ServerLog." + messageTypeName[msgType]), font: GUI.SmallFont) + var tickBox = new GUITickBox(new RectTransform(new Point(tickBoxContainer.Rect.Width, (int)(25 * GUI.Scale)), tickBoxContainer.RectTransform), TextManager.Get("ServerLog." + messageTypeName[msgType]), font: GUI.SmallFont) { Selected = true, TextColor = messageColor[msgType], @@ -121,6 +132,7 @@ namespace Barotrauma.Networking return true; } }; + tickBox.TextBlock.SelectedTextColor = tickBox.TextBlock.TextColor; tickBox.Selected = !msgTypeHidden[(int)msgType]; tickBoxes.Add(tickBox); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs index 64868ad14..7a37eec55 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs @@ -130,7 +130,7 @@ namespace Barotrauma.Networking ServerMessageText = incMsg.ReadString(); MaxPlayers = incMsg.ReadByte(); HasPassword = incMsg.ReadBoolean(); - isPublic = incMsg.ReadBoolean(); + IsPublic = incMsg.ReadBoolean(); incMsg.ReadPadBits(); TickRate = incMsg.ReadRangedInteger(1, 60); GameMain.NetworkMember.TickRate = TickRate; @@ -269,7 +269,7 @@ namespace Barotrauma.Networking settingsFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: null, color: Color.Black * 0.5f); new GUIButton(new RectTransform(Vector2.One, settingsFrame.RectTransform), "", style: null).OnClicked += (btn, userData) => { - if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) ToggleSettingsFrame(btn, userData); + if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) { ToggleSettingsFrame(btn, userData); } return true; }; @@ -279,17 +279,23 @@ namespace Barotrauma.Networking }; //center frames - GUIFrame innerFrame = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.75f), settingsFrame.RectTransform, Anchor.Center) { MinSize = new Point(400, 430) }); - GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), innerFrame.RectTransform, Anchor.Center), style: null); + GUIFrame innerFrame = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.8f), settingsFrame.RectTransform, Anchor.Center) { MinSize = new Point(400, 430) }); + GUILayoutGroup paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), innerFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + { + Stretch = true, + RelativeSpacing = 0.02f + }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), paddedFrame.RectTransform), TextManager.Get("Settings"), font: GUI.LargeFont); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), TextManager.Get("Settings"), font: GUI.LargeFont); - var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), paddedFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.1f) }, isHorizontal: true) + var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), paddedFrame.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.01f }; + var tabContent = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.85f), paddedFrame.RectTransform), style: "InnerFrame"); + //tabs var tabValues = Enum.GetValues(typeof(SettingsTab)).Cast().ToArray(); string[] tabNames = new string[tabValues.Count()]; @@ -301,10 +307,8 @@ namespace Barotrauma.Networking tabButtons = new GUIButton[tabNames.Length]; for (int i = 0; i < tabNames.Length; i++) { - settingsTabs[i] = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.79f), paddedFrame.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.05f) }, - style: "InnerFrame"); - - tabButtons[i] = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform), tabNames[i], style: "GUITabButton") + settingsTabs[i] = new GUIFrame(new RectTransform(Vector2.One, tabContent.RectTransform, Anchor.Center), style: null); + tabButtons[i] = new GUIButton(new RectTransform(new Vector2(0.2f, 1.2f), buttonArea.RectTransform), tabNames[i], style: "GUITabButton") { UserData = i, OnClicked = SelectSettingsTab @@ -314,7 +318,8 @@ namespace Barotrauma.Networking SelectSettingsTab(tabButtons[0], 0); //"Close" - var closeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.05f), paddedFrame.RectTransform, Anchor.BottomRight), TextManager.Get("Close")) + var buttonContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.05f), paddedFrame.RectTransform), style: null); + var closeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonContainer.RectTransform, Anchor.BottomRight), TextManager.Get("Close")) { OnClicked = ToggleSettingsFrame }; @@ -327,36 +332,14 @@ namespace Barotrauma.Networking var serverTab = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), settingsTabs[(int)SettingsTab.General].RectTransform, Anchor.Center)) { Stretch = true, - RelativeSpacing = 0.02f + RelativeSpacing = 0.01f }; //*********************************************** - // Play Style Selection - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsPlayStyle")); - var playStyleSelection = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.16f), serverTab.RectTransform)) - { - AutoHideScrollBar = true, - UseGridLayout = true - }; - - List playStyleTickBoxes = new List(); - GUIRadioButtonGroup selectionPlayStyle = new GUIRadioButtonGroup(); - foreach (PlayStyle playStyle in Enum.GetValues(typeof(PlayStyle))) - { - var selectionTick = new GUITickBox(new RectTransform(new Vector2(0.32f, 0.49f), playStyleSelection.Content.RectTransform), TextManager.Get("servertag." + playStyle), font: GUI.SmallFont, style: "GUIRadioButton") - { - ToolTip = TextManager.Get("servertagdescription." + playStyle) - }; - selectionPlayStyle.AddRadioButton((int)playStyle, selectionTick); - playStyleTickBoxes.Add(selectionTick); - } - GetPropertyData("PlayStyle").AssignGUIComponent(selectionPlayStyle); - GUITextBlock.AutoScaleAndNormalize(playStyleTickBoxes.Select(t => t.TextBlock)); - // Sub Selection - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsSubSelection")); - var selectionFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), isHorizontal: true) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverTab.RectTransform), TextManager.Get("ServerSettingsSubSelection"), font: GUI.SubHeadingFont); + var selectionFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.02f), serverTab.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f @@ -368,12 +351,14 @@ namespace Barotrauma.Networking var selectionTick = new GUITickBox(new RectTransform(new Vector2(0.3f, 1.0f), selectionFrame.RectTransform), TextManager.Get(((SelectionMode)i).ToString()), font: GUI.SmallFont, style: "GUIRadioButton"); selectionMode.AddRadioButton(i, selectionTick); } - DebugConsole.NewMessage(SubSelectionMode.ToString(), Color.White); + selectionFrame.RectTransform.NonScaledSize = new Point(selectionFrame.Rect.Width, selectionFrame.Children.First().Rect.Height); + selectionFrame.RectTransform.IsFixedSize = true; + GetPropertyData("SubSelectionMode").AssignGUIComponent(selectionMode); // Mode Selection - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsModeSelection")); - selectionFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), isHorizontal: true) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverTab.RectTransform), TextManager.Get("ServerSettingsModeSelection"), font: GUI.SubHeadingFont); + selectionFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.02f), serverTab.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f @@ -385,8 +370,11 @@ namespace Barotrauma.Networking var selectionTick = new GUITickBox(new RectTransform(new Vector2(0.3f, 1.0f), selectionFrame.RectTransform), TextManager.Get(((SelectionMode)i).ToString()), font: GUI.SmallFont, style: "GUIRadioButton"); selectionMode.AddRadioButton(i, selectionTick); } + selectionFrame.RectTransform.NonScaledSize = new Point(selectionFrame.Rect.Width, selectionFrame.Children.First().Rect.Height); + selectionFrame.RectTransform.IsFixedSize = true; GetPropertyData("ModeSelectionMode").AssignGUIComponent(selectionMode); + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), serverTab.RectTransform), style: "HorizontalLine"); //*********************************************** @@ -397,8 +385,8 @@ namespace Barotrauma.Networking //*********************************************** string autoRestartDelayLabel = TextManager.Get("ServerSettingsAutoRestartDelay") + " "; - var startIntervalText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), autoRestartDelayLabel); - var startIntervalSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), barSize: 0.1f) + var startIntervalText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverTab.RectTransform), autoRestartDelayLabel); + var startIntervalSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), barSize: 0.1f, style: "GUISlider") { UserData = startIntervalText, Step = 0.05f, @@ -436,7 +424,6 @@ namespace Barotrauma.Networking var allowSpecBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsAllowSpectating")); GetPropertyData("AllowSpectating").AssignGUIComponent(allowSpecBox); - var shareSubsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), serverTab.RectTransform), TextManager.Get("ServerSettingsShareSubFiles")); GetPropertyData("AllowFileTransfers").AssignGUIComponent(shareSubsBox); @@ -464,6 +451,29 @@ namespace Barotrauma.Networking RelativeSpacing = 0.02f }; + // Play Style Selection + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsPlayStyle"), font: GUI.SubHeadingFont); + var playstyleList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.16f), roundsTab.RectTransform)) + { + AutoHideScrollBar = true, + UseGridLayout = true + }; + playstyleList.Padding *= 2.0f; + + List playStyleTickBoxes = new List(); + GUIRadioButtonGroup selectionPlayStyle = new GUIRadioButtonGroup(); + foreach (PlayStyle playStyle in Enum.GetValues(typeof(PlayStyle))) + { + var selectionTick = new GUITickBox(new RectTransform(new Vector2(0.32f, 0.49f), playstyleList.Content.RectTransform), TextManager.Get("servertag." + playStyle), font: GUI.SmallFont, style: "GUIRadioButton") + { + ToolTip = TextManager.Get("servertagdescription." + playStyle) + }; + selectionPlayStyle.AddRadioButton((int)playStyle, selectionTick); + playStyleTickBoxes.Add(selectionTick); + } + GetPropertyData("PlayStyle").AssignGUIComponent(selectionPlayStyle); + GUITextBlock.AutoScaleAndNormalize(playStyleTickBoxes.Select(t => t.TextBlock)); + playstyleList.RectTransform.MinSize = new Point(0, (int)(playstyleList.Content.Children.First().Rect.Height * 2.0f + playstyleList.Padding.Y + playstyleList.Padding.W)); var endBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsEndRoundWhenDestReached")); @@ -615,7 +625,7 @@ namespace Barotrauma.Networking }; var monsterButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonHolder.RectTransform), - TextManager.Get("ServerSettingsMonsterSpawns")) + TextManager.Get("ServerSettingsMonsterSpawns"), style: "GUIButtonSmall") { Enabled = !GameMain.NetworkMember.GameStarted }; @@ -655,7 +665,7 @@ namespace Barotrauma.Networking } var cargoButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonHolder.RectTransform), - TextManager.Get("ServerSettingsAdditionalCargo")) + TextManager.Get("ServerSettingsAdditionalCargo"), style: "GUIButtonSmall") { Enabled = !GameMain.NetworkMember.GameStarted }; @@ -740,21 +750,31 @@ namespace Barotrauma.Networking RelativeSpacing = 0.02f }; - var allowFriendlyFire = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), antigriefingTab.RectTransform), + var tickBoxContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.16f), antigriefingTab.RectTransform)) + { + AutoHideScrollBar = true, + UseGridLayout = true + }; + tickBoxContainer.Padding *= 2.0f; + + var allowFriendlyFire = new GUITickBox(new RectTransform(new Vector2(0.4f, 0.05f), tickBoxContainer.Content.RectTransform), TextManager.Get("ServerSettingsAllowFriendlyFire")); GetPropertyData("AllowFriendlyFire").AssignGUIComponent(allowFriendlyFire); - var allowRewiring = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), antigriefingTab.RectTransform), + var allowRewiring = new GUITickBox(new RectTransform(new Vector2(0.4f, 0.05f), tickBoxContainer.Content.RectTransform), TextManager.Get("ServerSettingsAllowRewiring")); GetPropertyData("AllowRewiring").AssignGUIComponent(allowRewiring); - var allowDisguises = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), antigriefingTab.RectTransform), + var allowDisguises = new GUITickBox(new RectTransform(new Vector2(0.4f, 0.05f), tickBoxContainer.Content.RectTransform), TextManager.Get("ServerSettingsAllowDisguises")); GetPropertyData("AllowDisguises").AssignGUIComponent(allowDisguises); - var voteKickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), antigriefingTab.RectTransform), TextManager.Get("ServerSettingsAllowVoteKick")); + var voteKickBox = new GUITickBox(new RectTransform(new Vector2(0.4f, 0.05f), tickBoxContainer.Content.RectTransform), + TextManager.Get("ServerSettingsAllowVoteKick")); GetPropertyData("AllowVoteKick").AssignGUIComponent(voteKickBox); + tickBoxContainer.RectTransform.MinSize = new Point(0, (int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W)); + CreateLabeledSlider(antigriefingTab, "ServerSettingsKickVotesRequired", out slider, out sliderLabel); string votesRequiredLabel = sliderLabel.Text + " "; slider.Step = 0.2f; @@ -801,10 +821,19 @@ namespace Barotrauma.Networking } var karmaSettingsContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), antigriefingTab.RectTransform), style: null); - var karmaSettingsList = new GUIListBox(new RectTransform(Vector2.One, karmaSettingsContainer.RectTransform)); + var karmaSettingsList = new GUIListBox(new RectTransform(Vector2.One, karmaSettingsContainer.RectTransform)) + { + Spacing = (int)(8 * GUI.Scale) + }; + karmaSettingsList.Padding *= 2.0f; - karmaSettingsBlocker = new GUIFrame(new RectTransform(Vector2.One, karmaSettingsContainer.RectTransform, Anchor.CenterLeft) { MaxSize = new Point(karmaSettingsList.Content.Rect.Width, int.MaxValue) }, - style: "InnerFrame"); + karmaSettingsBlocker = new GUIFrame(new RectTransform(Vector2.One, karmaSettingsContainer.RectTransform, Anchor.CenterLeft) + { MaxSize = new Point(karmaSettingsList.ContentBackground.Rect.Width, int.MaxValue) }, style: null) + { + UserData = "karmasettingsblocker", + Color = Color.Black * 0.95f + }; + karmaSettingsBlocker.Color *= 0.5f; karmaPresetDD.SelectItem(KarmaPreset); karmaSettingsBlocker.Visible = !karmaBox.Selected || KarmaPreset != "custom"; GameMain.NetworkMember.KarmaManager.CreateSettingsFrame(karmaSettingsList.Content); @@ -864,9 +893,12 @@ namespace Barotrauma.Networking RelativeSpacing = 0.05f }; - slider = new GUIScrollBar(new RectTransform(new Vector2(0.5f, 0.8f), container.RectTransform), barSize: 0.1f); - label = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.8f), container.RectTransform), - string.IsNullOrEmpty(labelTag) ? "" : TextManager.Get(labelTag), font: GUI.SmallFont); + slider = new GUIScrollBar(new RectTransform(new Vector2(0.5f, 1.0f), container.RectTransform), barSize: 0.1f, style: "GUISlider"); + label = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), container.RectTransform), + string.IsNullOrEmpty(labelTag) ? "" : TextManager.Get(labelTag), textAlignment: Alignment.CenterLeft, font: GUI.SmallFont); + + container.RectTransform.MinSize = new Point(0, slider.RectTransform.MinSize.Y); + container.RectTransform.MaxSize = new Point(int.MaxValue, slider.RectTransform.MaxSize.Y); //slider has a reference to the label to change the text when it's used slider.UserData = label; @@ -881,13 +913,18 @@ namespace Barotrauma.Networking ToolTip = TextManager.Get(labelTag) }; - new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.8f), container.RectTransform), - TextManager.Get(labelTag), font: GUI.SmallFont); - return new GUINumberInput(new RectTransform(new Vector2(0.3f, 0.8f), container.RectTransform), GUINumberInput.NumberType.Int) + new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), container.RectTransform), + TextManager.Get(labelTag), textAlignment: Alignment.CenterLeft, font: GUI.SmallFont); + var input = new GUINumberInput(new RectTransform(new Vector2(0.5f, 1.0f), container.RectTransform), GUINumberInput.NumberType.Int) { MinValueInt = min, MaxValueInt = max }; + + container.RectTransform.MinSize = new Point(0, input.RectTransform.MinSize.Y); + container.RectTransform.MaxSize = new Point(int.MaxValue, input.RectTransform.MaxSize.Y); + + return input; } private bool SelectSettingsTab(GUIButton button, object obj) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/SteamManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/SteamManager.cs index 94866241f..e7550496a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/SteamManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/SteamManager.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using RestSharp.Contrib; using System.Xml.Linq; using System.Xml; +using Color = Microsoft.Xna.Framework.Color; namespace Barotrauma.Steam { @@ -132,7 +133,7 @@ namespace Barotrauma.Steam lobbyState = LobbyState.Owner; lobbyID = (currentLobby?.Id).Value; - if (serverSettings.isPublic) + if (serverSettings.IsPublic) { currentLobby?.SetPublic(); } @@ -203,6 +204,8 @@ namespace Barotrauma.Steam currentLobby?.Leave(); currentLobby = null; lobbyState = LobbyState.NotConnected; + lobbyID = 0; + Steamworks.SteamMatchmaking.ResetActions(); } } @@ -257,6 +260,7 @@ namespace Barotrauma.Steam serverInfo.ServerName = lobby.GetData("name"); serverInfo.OwnerID = SteamIDStringToUInt64(lobby.GetData("lobbyowner")); serverInfo.LobbyID = lobby.Id; + bool.TryParse(lobby.GetData("haspassword"), out serverInfo.HasPassword); serverInfo.PlayerCount = int.TryParse(lobby.GetData("playercount"), out int playerCount) ? playerCount : 0; serverInfo.MaxPlayers = int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers) ? maxPlayers : 1; serverInfo.RespondedToSteamQuery = true; @@ -327,6 +331,7 @@ namespace Barotrauma.Steam TaskPool.Add(serverQuery.RunQueryAsync(), (t) => { + serverQuery.Dispose(); taskDone(); if (t.Status == TaskStatus.Faulted) { @@ -610,7 +615,7 @@ namespace Barotrauma.Steam nonSubscribedItems = nonSubscribedItems.Take(amount - processedResults); } - onItemsFound?.Invoke(resultPage.Value.Entries.ToList()); + onItemsFound?.Invoke(nonSubscribedItems.ToList()); processedResults += resultPage.Value.ResultCount; pageIndex++; @@ -785,7 +790,7 @@ namespace Barotrauma.Steam { if (!EnableWorkShopItem(existingItem, false, out string errorMsg)) { - DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); + DebugConsole.NewMessage(errorMsg, Color.Red); new GUIMessageBox( TextManager.Get("Error"), TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { existingItem?.Title, errorMsg })); @@ -895,13 +900,13 @@ namespace Barotrauma.Steam workshopPublishStatus.Success = false; workshopPublishStatus.TaskStatus = task.Status; - DebugConsole.NewMessage("Publishing workshop item " + item?.Title + " failed: task failed with status " + task.Status.ToString(), Microsoft.Xna.Framework.Color.Red); + DebugConsole.NewMessage("Publishing workshop item " + item?.Title + " failed: task failed with status " + task.Status.ToString(), Color.Red); } else if (!task.Result.Success) { workshopPublishStatus.Success = false; workshopPublishStatus.Result = task.Result; - DebugConsole.NewMessage("Publishing workshop item " + item?.Title + " failed: Workshop result "+task.Result.Result.ToString(), Microsoft.Xna.Framework.Color.Red); + DebugConsole.NewMessage("Publishing workshop item " + item?.Title + " failed: Workshop result "+task.Result.Result.ToString(), Color.Red); } else { @@ -926,7 +931,7 @@ namespace Barotrauma.Steam if (!(item?.IsInstalled ?? false)) { errorMsg = TextManager.GetWithVariable("WorkshopErrorInstallRequiredToEnable", "[itemname]", item?.Title ?? "[NULL]"); - DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); + DebugConsole.NewMessage(errorMsg, Color.Red); return false; } @@ -1036,7 +1041,7 @@ namespace Barotrauma.Steam if (File.Exists(newContentPackagePath) && !CheckFileEquality(newContentPackagePath, metaDataFilePath)) { errorMsg = TextManager.GetWithVariables("WorkshopErrorOverwriteOnEnable", new string[2] { "[itemname]", "[filename]" }, new string[2] { item?.Title, newContentPackagePath }); - DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); + DebugConsole.NewMessage(errorMsg, Color.Red); return false; } @@ -1047,7 +1052,7 @@ namespace Barotrauma.Steam if (File.Exists(sourceFile) && File.Exists(contentFile.Path) && !CheckFileEquality(sourceFile, contentFile.Path)) { errorMsg = TextManager.GetWithVariables("WorkshopErrorOverwriteOnEnable", new string[2] { "[itemname]", "[filename]" }, new string[2] { item?.Title, contentFile.Path }); - DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); + DebugConsole.NewMessage(errorMsg, Color.Red); return false; } } @@ -1121,7 +1126,7 @@ namespace Barotrauma.Steam catch (Exception e) { errorMsg = TextManager.GetWithVariable("WorkshopErrorEnableFailed", "[itemname]", item?.Title) + " {" + e.Message + "}"; - DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); + DebugConsole.NewMessage(errorMsg, Color.Red); return false; } @@ -1155,7 +1160,7 @@ namespace Barotrauma.Steam errorMsg = "Cannot disable workshop item \"" + item?.Title + "\" because it has not been installed."; if (!noLog) { - DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); + DebugConsole.NewMessage(errorMsg, Color.Red); } return false; } @@ -1304,7 +1309,9 @@ namespace Barotrauma.Steam { return false; } - return item?.Updated <= myPackage.InstallTime.Value; + DateTime latestTime = item.Value.Updated > item.Value.Created ? item.Value.Updated : item.Value.Created; + bool upToDate = latestTime <= myPackage.InstallTime.Value; + return upToDate; } public static bool AutoUpdateWorkshopItems() @@ -1385,11 +1392,8 @@ namespace Barotrauma.Steam { errorMsg = ""; if (!(item?.IsInstalled ?? false)) { return false; } - if (item.Value.NeedsUpdate) - { - if (!DisableWorkShopItem(item, false, out errorMsg)) { return false; } - if (!EnableWorkShopItem(item, allowFileOverwrite: false, errorMsg: out errorMsg)) { return false; } - } + if (!DisableWorkShopItem(item, false, out errorMsg)) { return false; } + if (!EnableWorkShopItem(item, allowFileOverwrite: false, errorMsg: out errorMsg)) { return false; } return true; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs index 4af7a9aab..59db1c580 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs @@ -80,7 +80,7 @@ namespace Barotrauma.Networking if (queue == null) { #if DEBUG - DebugConsole.NewMessage("Couldn't find VoipQueue with id " + queueId.ToString() + "!", Color.Red); + DebugConsole.NewMessage("Couldn't find VoipQueue with id " + queueId.ToString() + "!", GUI.Style.Red); #endif return; } @@ -144,13 +144,13 @@ namespace Barotrauma.Networking if (voiceIconSheetRects == null) { var soundIconStyle = GUI.Style.GetComponentStyle("GUISoundIcon"); - Point sourceRectSize = soundIconStyle.Sprites.First().Value.First().Sprite.SourceRect.Size; + Rectangle sourceRect = soundIconStyle.Sprites.First().Value.First().Sprite.SourceRect; var indexPieces = soundIconStyle.Element.Attribute("sheetindices").Value.Split(';'); voiceIconSheetRects = new Rectangle[indexPieces.Length]; for (int i = 0; i < indexPieces.Length; i++) { - Point location = XMLExtensions.ParsePoint(indexPieces[i].Trim()) * sourceRectSize; - voiceIconSheetRects[i] = new Rectangle(location, sourceRectSize); + Point location = sourceRect.Location + XMLExtensions.ParsePoint(indexPieces[i].Trim()) * sourceRect.Size; + voiceIconSheetRects[i] = new Rectangle(location, sourceRect.Size); } } @@ -164,8 +164,7 @@ namespace Barotrauma.Networking else { soundIcon.Visible = true; - int sheetIndex = 0; - sheetIndex = (int)Math.Floor(userdata.Second * voiceIconSheetRects.Length); + int sheetIndex = (int)Math.Floor(userdata.Second * voiceIconSheetRects.Length); sheetIndex = MathHelper.Clamp(sheetIndex, 0, voiceIconSheetRects.Length - 1); soundIcon.SourceRect = voiceIconSheetRects[sheetIndex]; soundIcon.OverrideState = GUIComponent.ComponentState.None; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/WhiteList.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/WhiteList.cs index 9e65cdaad..0406f6703 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/WhiteList.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/WhiteList.cs @@ -73,13 +73,14 @@ namespace Barotrauma.Networking if (localRemoved.Contains(wlp.UniqueIdentifier)) continue; string blockText = wlp.Name; if (!string.IsNullOrWhiteSpace(wlp.IP)) blockText += " (" + wlp.IP + ")"; - GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), listBox.Content.RectTransform), + GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform), blockText) { UserData = wlp }; - var removeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), textBlock.RectTransform, Anchor.CenterRight), TextManager.Get("WhiteListRemove")) + var removeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), textBlock.RectTransform, Anchor.CenterRight), + TextManager.Get("WhiteListRemove"), style: "GUIButtonSmall") { UserData = wlp, OnClicked = RemoveFromWhiteList @@ -90,20 +91,26 @@ namespace Barotrauma.Networking { string blockText = lad.Name; if (!string.IsNullOrWhiteSpace(lad.IP)) blockText += " (" + lad.IP + ")"; - GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), listBox.Content.RectTransform), + GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform), blockText) { UserData = lad }; - var removeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), textBlock.RectTransform, Anchor.CenterRight), TextManager.Get("WhiteListRemove")) + var removeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), textBlock.RectTransform, Anchor.CenterRight), + TextManager.Get("WhiteListRemove"), style: "GUIButtonSmall") { UserData = lad, OnClicked = RemoveFromWhiteList }; } - var nameArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), whitelistFrame.RectTransform), isHorizontal: true) + foreach (GUIComponent c in listBox.Content.Children) + { + c.RectTransform.MinSize = new Point(0, Math.Max((int)(20 * GUI.Scale), c.RectTransform.Children.Max(c2 => c2.MinSize.Y))); + } + + var nameArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), whitelistFrame.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f @@ -115,8 +122,9 @@ namespace Barotrauma.Networking addNewButton.Enabled = !string.IsNullOrEmpty(ipBox.Text) && !string.IsNullOrEmpty(nameBox.Text); return true; }; + nameArea.RectTransform.MinSize = new Point(0, nameBox.RectTransform.MinSize.Y); - var ipArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), whitelistFrame.RectTransform), isHorizontal: true) + var ipArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), whitelistFrame.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f @@ -128,11 +136,13 @@ namespace Barotrauma.Networking addNewButton.Enabled = !string.IsNullOrEmpty(ipBox.Text) && !string.IsNullOrEmpty(nameBox.Text); return true; }; + ipBox.RectTransform.MinSize = new Point(0, ipBox.RectTransform.MinSize.Y); - addNewButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.1f), whitelistFrame.RectTransform), TextManager.Get("WhiteListAdd")) + addNewButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), whitelistFrame.RectTransform), TextManager.Get("WhiteListAdd"), style: "GUIButtonSmall") { OnClicked = AddToWhiteList }; + GUITextBlock.AutoScaleAndNormalize(addNewButton.TextBlock); nameBox.Enabled = localEnabled; ipBox.Enabled = localEnabled; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaClient/ClientSource/Physics/PhysicsBody.cs index 212ba27b8..ee5078feb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Physics/PhysicsBody.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Physics/PhysicsBody.cs @@ -66,7 +66,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, new Vector2(pos.X - 5, -(pos.Y + 5)), - Vector2.One * 10.0f, Color.Red, false, 0, 3); + Vector2.One * 10.0f, GUI.Style.Red, false, 0, 3); } if (drawOffset != Vector2.Zero) diff --git a/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs b/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs index c1f996ec3..5e2f6e3bb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/PlayerInput.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; +using System; #if WINDOWS using System.Runtime.InteropServices; #endif @@ -144,7 +145,10 @@ namespace Barotrauma static Point lastClickPosition; const float DoubleClickDelay = 0.4f; - const float MaxDoubleClickDistance = 10.0f; + public static float MaxDoubleClickDistance + { + get { return Math.Max(15.0f * Math.Max(GameMain.GraphicsHeight / 1920.0f, GameMain.GraphicsHeight / 1080.0f), 10.0f); } + } static bool doubleClicked; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI.cs index 0cebb23c6..63a40aa07 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI.cs @@ -24,6 +24,12 @@ namespace Barotrauma public Action StartNewGame; public Action LoadGame; + public GUIButton StartButton + { + get; + private set; + } + private readonly bool isMultiplayer; public CampaignSetupUI(bool isMultiplayer, GUIComponent newGameContainer, GUIComponent loadGameContainer, IEnumerable submarines, IEnumerable saveFiles = null) @@ -35,7 +41,7 @@ namespace Barotrauma var columnContainer = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: true) { Stretch = true, - RelativeSpacing = isMultiplayer ? 0.0f : 0.05f + RelativeSpacing = isMultiplayer ? 0.0f : 0.02f }; var leftColumn = new GUILayoutGroup(new RectTransform(Vector2.One, columnContainer.RectTransform)) @@ -53,18 +59,18 @@ namespace Barotrauma columnContainer.Recalculate(); // New game left side - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SaveName")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SaveName"), font: GUI.SubHeadingFont); saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, string.Empty) { textFilterFunction = (string str) => { return ToolBox.RemoveInvalidFileNameChars(str); } }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed"), font: GUI.SubHeadingFont); seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8)); if (!isMultiplayer) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SelectedSub")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SelectedSub"), font: GUI.SubHeadingFont); var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), isHorizontal: true) { @@ -74,15 +80,10 @@ namespace Barotrauma subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform)) { ScrollBarVisible = true }; var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font); - var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font); + var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true); searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; - searchBox.OnTextChanged += (textBox, text) => { FilterSubs(subList, text); return true; }; - var clearButton = new GUIButton(new RectTransform(new Vector2(0.075f, 1.0f), filterContainer.RectTransform), "x") - { - OnClicked = (btn, userdata) => { searchBox.Text = ""; FilterSubs(subList, ""); searchBox.Flash(Color.White); return true; } - }; subList.OnSelected = OnSubSelected; } @@ -93,15 +94,16 @@ namespace Barotrauma } // New game right side - subPreviewContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform)) + subPreviewContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform)) { Stretch = true }; var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.13f), (isMultiplayer ? leftColumn : rightColumn).RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.TopRight); + if (!isMultiplayer) { buttonContainer.IgnoreLayoutGroups = true; } - var startButton = new GUIButton(new RectTransform(isMultiplayer ? new Vector2(0.5f, 1.0f) : Vector2.One, + StartButton = new GUIButton(new RectTransform(isMultiplayer ? new Vector2(0.5f, 1.0f) : Vector2.One, buttonContainer.RectTransform, Anchor.BottomRight) { MaxSize = new Point(350, 60) }, TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge") { @@ -109,7 +111,7 @@ namespace Barotrauma { if (string.IsNullOrWhiteSpace(saveNameBox.Text)) { - saveNameBox.Flash(Color.Red); + saveNameBox.Flash(GUI.Style.Red); return false; } @@ -207,6 +209,7 @@ namespace Barotrauma disclaimerBtn.RectTransform.MaxSize = new Point((int)(30 * GUI.Scale)); } + columnContainer.Recalculate(); leftColumn.Recalculate(); rightColumn.Recalculate(); @@ -232,7 +235,7 @@ namespace Barotrauma private bool OnSubSelected(GUIComponent component, object obj) { if (subPreviewContainer == null) { return false; } - + (subPreviewContainer.Parent as GUILayoutGroup)?.Recalculate(); subPreviewContainer.ClearChildren(); Submarine sub = obj as Submarine; @@ -389,10 +392,16 @@ namespace Barotrauma { nameText.Text = Path.GetFileNameWithoutExtension(saveFile); XDocument doc = SaveUtil.LoadGameSessionDoc(saveFile); + if (doc.Root.GetChildElement("multiplayercampaign") != null) + { + //multiplayer campaign save in the wrong folder -> don't show the save + saveList.Content.RemoveChild(saveFrame); + continue; + } if (doc?.Root == null) { DebugConsole.ThrowError("Error loading save file \"" + saveFile + "\". The file may be corrupted."); - nameText.TextColor = Color.Red; + nameText.TextColor = GUI.Style.Red; continue; } subName = doc.Root.GetAttributeString("submarine", ""); @@ -421,7 +430,7 @@ namespace Barotrauma List contentPackagePaths = contentPackageStr.Split('|').ToList(); if (!GameSession.IsCompatibleWithSelectedContentPackages(contentPackagePaths, out string errorMsg)) { - nameText.TextColor = Color.Red; + nameText.TextColor = GUI.Style.Red; saveFrame.ToolTip = string.Join("\n", errorMsg, TextManager.Get("campaignmode.contentpackagemismatchwarning")); } } @@ -466,7 +475,7 @@ namespace Barotrauma return file2WriteTime.CompareTo(file1WriteTime); }); - loadGameButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomRight), TextManager.Get("LoadButton"), style: "GUIButtonLarge") + loadGameButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomRight), TextManager.Get("LoadButton")) { OnClicked = (btn, obj) => { @@ -480,7 +489,8 @@ namespace Barotrauma }, Enabled = false }; - deleteMpSaveButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomLeft), TextManager.Get("Delete"), style: "GUIButtonLarge") + deleteMpSaveButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomLeft), + TextManager.Get("Delete"), style: "GUIButtonSmall") { OnClicked = DeleteSave, Visible = false @@ -550,7 +560,7 @@ namespace Barotrauma new GUIButton(new RectTransform(new Vector2(0.4f, 0.15f), saveFileFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0, 0.1f) - }, TextManager.Get("Delete")) + }, TextManager.Get("Delete"), style: "GUIButtonSmall") { UserData = fileName, OnClicked = DeleteSave diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs index efdd896ad..17b39fb47 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs @@ -207,16 +207,10 @@ namespace Barotrauma Stretch = true }; var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font); - searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform), font: GUI.Font); + searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform), createClearButton: true); searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; - searchBox.OnTextChanged += (textBox, text) => { FilterStoreItems(null, text); return true; }; - var clearButton = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), filterContainer.RectTransform), "x") - { - OnClicked = (btn, userdata) => { searchBox.Text = ""; FilterStoreItems(selectedItemCategory, ""); searchBox.Flash(Color.White); return true; } - }; - var storeItemLists = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), storeContent.RectTransform), isHorizontal: true) { RelativeSpacing = 0.03f, @@ -307,12 +301,12 @@ namespace Barotrauma IgnoreLayoutGroups = true, CanBeFocused = false }; - var repairHullsLabel = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.3f), repairHullsHolder.RectTransform), TextManager.Get("RepairAllWalls"), textAlignment: Alignment.Right, font: GUI.LargeFont) + var repairHullsLabel = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.3f), repairHullsHolder.RectTransform), TextManager.Get("RepairAllWalls"), textAlignment: Alignment.Right, font: GUI.SubHeadingFont) { ForceUpperCase = true }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairHullsHolder.RectTransform), CampaignMode.HullRepairCost.ToString(), textAlignment: Alignment.Right, font: GUI.LargeFont); - repairHullsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairHullsHolder.RectTransform), TextManager.Get("Repair"), style: "GUIButtonLarge") + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairHullsHolder.RectTransform), CampaignMode.HullRepairCost.ToString(), textAlignment: Alignment.Right, font: GUI.SubHeadingFont); + repairHullsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairHullsHolder.RectTransform), TextManager.Get("Repair")) { OnClicked = (btn, userdata) => { @@ -352,12 +346,12 @@ namespace Barotrauma IgnoreLayoutGroups = true, CanBeFocused = false }; - var repairItemsLabel = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.3f), repairItemsHolder.RectTransform), TextManager.Get("RepairAllItems"), textAlignment: Alignment.Right, font: GUI.LargeFont) + var repairItemsLabel = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.3f), repairItemsHolder.RectTransform), TextManager.Get("RepairAllItems"), textAlignment: Alignment.Right, font: GUI.SubHeadingFont) { ForceUpperCase = true }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairItemsHolder.RectTransform), CampaignMode.ItemRepairCost.ToString(), textAlignment: Alignment.Right, font: GUI.LargeFont); - repairItemsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairItemsHolder.RectTransform), TextManager.Get("Repair"), style: "GUIButtonLarge") + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairItemsHolder.RectTransform), CampaignMode.ItemRepairCost.ToString(), textAlignment: Alignment.Right, font: GUI.SubHeadingFont); + repairItemsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairItemsHolder.RectTransform), TextManager.Get("Repair")) { OnClicked = (btn, userdata) => { @@ -401,8 +395,8 @@ namespace Barotrauma { ForceUpperCase = true }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), replaceShuttlesHolder.RectTransform), CampaignMode.ShuttleReplaceCost.ToString(), textAlignment: Alignment.Right, font: GUI.LargeFont); - replaceShuttlesButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), replaceShuttlesHolder.RectTransform), TextManager.Get("ReplaceShuttles"), style: "GUIButtonLarge") + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), replaceShuttlesHolder.RectTransform), CampaignMode.ShuttleReplaceCost.ToString(), textAlignment: Alignment.Right, font: GUI.SubHeadingFont); + replaceShuttlesButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), replaceShuttlesHolder.RectTransform), TextManager.Get("ReplaceShuttles")) { OnClicked = (btn, userdata) => { @@ -462,7 +456,7 @@ namespace Barotrauma UserData = "missionlabel", AutoScale = true }; - var missionPanelContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), missionPanel.RectTransform, Anchor.Center)) + var missionPanelContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), missionPanel.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.05f @@ -473,7 +467,8 @@ namespace Barotrauma RelativeSpacing = 0.02f, Stretch = true }; - selectedMissionInfo = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.25f), missionPanel.RectTransform, Anchor.BottomRight, Pivot.TopRight)) + selectedMissionInfo = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.25f), missionPanel.RectTransform, Anchor.BottomRight, Pivot.TopRight) + { MinSize = new Point(0, (int)(250 * GUI.Scale)) }) { Visible = false }; @@ -683,13 +678,13 @@ namespace Barotrauma { AutoScale = true }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), location.Type.Name); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), location.Type.Name, font: GUI.SubHeadingFont); Sprite portrait = location.Type.GetPortrait(location.PortraitId); new GUIImage(new RectTransform(new Vector2(1.0f, 0.6f), container.RectTransform), portrait, scaleToFit: true); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), TextManager.Get("SelectMission"), font: GUI.LargeFont) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), TextManager.Get("SelectMission"), font: GUI.SubHeadingFont) { AutoScale = true }; @@ -704,7 +699,6 @@ namespace Barotrauma SelectedLevel = connection?.Level; if (connection != null) { - Point maxTickBoxSize = new Point(int.MaxValue, missionContent.Rect.Height / 4) ; List availableMissions = Campaign.Map.CurrentLocation.GetMissionsInConnection(connection).ToList(); if (!availableMissions.Contains(null)) { availableMissions.Add(null); } @@ -719,7 +713,7 @@ namespace Barotrauma for (int i = 0; i < availableMissions.Count; i++) { var mission = availableMissions[i]; - var tickBox = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.1f), missionContent.RectTransform) { MaxSize = maxTickBoxSize }, + var tickBox = new GUITickBox(new RectTransform(new Vector2(0.1f, 0.1f), missionContent.RectTransform), mission?.Name ?? TextManager.Get("NoMission"), style: "GUIRadioButton") { Enabled = GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign) @@ -728,6 +722,9 @@ namespace Barotrauma missionRadioButtonGroup.AddRadioButton(i, tickBox); } + missionFrame.RectTransform.MinSize = + new Point(0, (int)(missionContent.RectTransform.Children.Sum(c => c.MinSize.Y * 1.02f) / missionContent.RectTransform.RelativeSize.Y)); + if (GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign)) { missionRadioButtonGroup.OnSelect = (rbg, missionInd) => @@ -818,24 +815,26 @@ namespace Barotrauma private GUIComponent CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIListBox listBox) { - GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, (int)(GUI.Scale * 50)), listBox.Content.RectTransform), style: "ListBoxElement") + GUIFrame frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), style: "ListBoxElement") { UserData = pi, ToolTip = pi.ItemPrefab.Description }; + frame.RectTransform.MinSize = new Point(0, (int)(GUI.Scale * 50)); - var content = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform), isHorizontal: true) + var content = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1.0f), frame.RectTransform, Anchor.Center), + isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.02f, Stretch = true }; - ScalableFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; + ScalableFont font = listBox.Content.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; Sprite itemIcon = pi.ItemPrefab.InventoryIcon ?? pi.ItemPrefab.sprite; if (itemIcon != null) { - GUIImage img = new GUIImage(new RectTransform(new Point((int)(content.Rect.Height * 0.8f)), content.RectTransform, Anchor.CenterLeft), itemIcon, scaleToFit: true) + GUIImage img = new GUIImage(new RectTransform(new Point((int)(content.Rect.Height * 0.8f)), content.RectTransform), itemIcon, scaleToFit: true) { Color = itemIcon == pi.ItemPrefab.InventoryIcon ? pi.ItemPrefab.InventoryIconColor : pi.ItemPrefab.SpriteColor }; @@ -900,8 +899,8 @@ namespace Barotrauma content.RectTransform.RecalculateChildren(true, true); amountInput?.LayoutGroup.Recalculate(); textBlock.Text = ToolBox.LimitString(textBlock.Text, textBlock.Font, textBlock.Rect.Width); - content.RectTransform.IsFixedSize = true; - content.RectTransform.Children.ForEach(c => c.IsFixedSize = true); + /*content.RectTransform.IsFixedSize = true; + content.RectTransform.Children.ForEach(c => c.IsFixedSize = true);*/ return frame; } @@ -950,6 +949,7 @@ namespace Barotrauma var priceInfo = pi.ItemPrefab.GetPrice(Campaign.Map.CurrentLocation); if (priceInfo == null) { continue; } itemFrame = CreateItemFrame(pi, priceInfo, myItemList); + itemFrame.Flash(GUI.Style.Green); } itemFrame.GetChild(0).GetChild().IntValue = pi.Quantity; existingItemFrames.Add(itemFrame); @@ -1094,8 +1094,9 @@ namespace Barotrauma { UserData = characterInfo }; + var characterPreviewContent = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.8f), characterPreviewFrame.RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.02f) }, style: null); - characterInfo.CreateInfoFrame(characterPreviewFrame); + characterInfo.CreateInfoFrame(characterPreviewContent); } var currentCrew = GameMain.GameSession.CrewManager.GetCharacterInfos(); @@ -1104,7 +1105,7 @@ namespace Barotrauma new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), characterPreviewFrame.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) }, TextManager.Get("FireButton")) { - Color = Color.Red, + Color = GUI.Style.Red, UserData = characterInfo, Enabled = currentCrew.Count() > 1, //can't fire if there's only one character in the crew OnClicked = (btn, obj) => diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs index 316ba7657..ca7d456dc 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs @@ -278,12 +278,8 @@ namespace Barotrauma.CharacterEditor #region Main methods public override void AddToGUIUpdateList() { - fileEditPanel.AddToGUIUpdateList(); - modesPanel.AddToGUIUpdateList(); - minorModesPanel.AddToGUIUpdateList(); - buttonsPanel.AddToGUIUpdateList(); - optionsPanel.AddToGUIUpdateList(); - characterSelectionPanel.AddToGUIUpdateList(); + rightArea.AddToGUIUpdateList(); + leftArea.AddToGUIUpdateList(); Wizard.instance?.AddToGUIUpdateList(); if (displayBackgroundColor) @@ -738,7 +734,7 @@ namespace Barotrauma.CharacterEditor } } } - optionsToggle?.UpdateOpenState((float)deltaTime, new Vector2(optionsPanel.Rect.Width + rightArea.RectTransform.AbsoluteOffset.X, 0), optionsPanel.RectTransform); + optionsToggle?.UpdateOpenState((float)deltaTime, new Vector2(-optionsPanel.Rect.Width - rightArea.RectTransform.AbsoluteOffset.X, 0), optionsPanel.RectTransform); fileEditToggle?.UpdateOpenState((float)deltaTime, new Vector2(-fileEditPanel.Rect.Width - rightArea.RectTransform.AbsoluteOffset.X, 0), fileEditPanel.RectTransform); characterPanelToggle?.UpdateOpenState((float)deltaTime, new Vector2(-characterSelectionPanel.Rect.Width - rightArea.RectTransform.AbsoluteOffset.X, 0), characterSelectionPanel.RectTransform); minorModesToggle?.UpdateOpenState((float)deltaTime, new Vector2(-minorModesPanel.Rect.Width - leftArea.RectTransform.AbsoluteOffset.X, 0), minorModesPanel.RectTransform); @@ -802,7 +798,7 @@ namespace Barotrauma.CharacterEditor else if (showColliders) { character.AnimController.Collider.DebugDraw(spriteBatch, Color.White, forceColor: true); - character.AnimController.Limbs.ForEach(l => l.body.DebugDraw(spriteBatch, Color.LightGreen, forceColor: true)); + character.AnimController.Limbs.ForEach(l => l.body.DebugDraw(spriteBatch, GUI.Style.Green, forceColor: true)); } spriteBatch.End(); @@ -867,8 +863,8 @@ namespace Barotrauma.CharacterEditor } if (jointEndLimb != null && jointEndLimb.ActiveSprite != null) { - GUI.DrawRectangle(spriteBatch, GetLimbSpritesheetRect(jointEndLimb), Color.LightGreen, thickness: 3); - GUI.DrawRectangle(spriteBatch, GetLimbPhysicRect(jointEndLimb), Color.LightGreen, thickness: 3); + GUI.DrawRectangle(spriteBatch, GetLimbSpritesheetRect(jointEndLimb), GUI.Style.Green, thickness: 3); + GUI.DrawRectangle(spriteBatch, GetLimbPhysicRect(jointEndLimb), GUI.Style.Green, thickness: 3); } if (spriteSheetRect.Contains(PlayerInput.MousePosition)) { @@ -878,7 +874,7 @@ namespace Barotrauma.CharacterEditor var offset = anchor1Pos ?? Vector2.Zero; offset = -offset; startPos += offset; - GUI.DrawLine(spriteBatch, startPos, PlayerInput.MousePosition, Color.LightGreen, width: 3); + GUI.DrawLine(spriteBatch, startPos, PlayerInput.MousePosition, GUI.Style.Green, width: 3); } } else @@ -888,7 +884,7 @@ namespace Barotrauma.CharacterEditor // TODO: there's something wrong here var offset = anchor1Pos.HasValue ? Vector2.Transform(ConvertUnits.ToSimUnits(anchor1Pos.Value), Matrix.CreateRotationZ(jointStartLimb.Rotation)) : Vector2.Zero; var startPos = SimToScreen(jointStartLimb.SimPosition + offset); - GUI.DrawLine(spriteBatch, startPos, PlayerInput.MousePosition, Color.LightGreen, width: 3); + GUI.DrawLine(spriteBatch, startPos, PlayerInput.MousePosition, GUI.Style.Green, width: 3); } } } @@ -976,11 +972,11 @@ namespace Barotrauma.CharacterEditor var colliderDrawPos = SimToScreen(collider.SimPosition); Vector2 forward = Vector2.Transform(Vector2.UnitY, Matrix.CreateRotationZ(collider.Rotation)); var endPos = SimToScreen(collider.SimPosition + forward * collider.radius); - GUI.DrawLine(spriteBatch, colliderDrawPos, endPos, Color.LightGreen); + GUI.DrawLine(spriteBatch, colliderDrawPos, endPos, GUI.Style.Green); GUI.DrawLine(spriteBatch, colliderDrawPos, SimToScreen(collider.SimPosition + forward * 0.25f), Color.Blue); Vector2 left = forward.Left(); - GUI.DrawLine(spriteBatch, colliderDrawPos, SimToScreen(collider.SimPosition + left * 0.25f), Color.Red); - ShapeExtensions.DrawCircle(spriteBatch, colliderDrawPos, (endPos - colliderDrawPos).Length(), 40, Color.LightGreen); + GUI.DrawLine(spriteBatch, colliderDrawPos, SimToScreen(collider.SimPosition + left * 0.25f), GUI.Style.Red); + ShapeExtensions.DrawCircle(spriteBatch, colliderDrawPos, (endPos - colliderDrawPos).Length(), 40, GUI.Style.Green); GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 300, 0), $"Collider rotation: {MathHelper.ToDegrees(MathUtils.WrapAngleTwoPi(collider.Rotation))}", Color.White, font: GUI.SmallFont); } spriteBatch.End(); @@ -1662,7 +1658,7 @@ namespace Barotrauma.CharacterEditor #if !DEBUG if (vanilla != null && contentPackage == vanilla) { - GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), Color.Red, font: GUI.LargeFont); + GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), GUI.Style.Red, font: GUI.LargeFont); return false; } #endif @@ -1828,12 +1824,9 @@ namespace Barotrauma.CharacterEditor #region GUI private static Point outerMargin = new Point(0, 0); - private static Point innerMargin = new Point(40, 40); - private static Color panelColor = new Color(20, 20, 20, 255); - private static Color toggleButtonColor = new Color(0.4f, 0.4f, 0.4f, 1); + private static Vector2 innerScale = new Vector2(0.95f, 0.95f); - private GUIFrame rightArea; - private GUIFrame leftArea; + private GUILayoutGroup rightArea, leftArea; private GUIFrame centerArea; private GUIFrame characterSelectionPanel; @@ -1904,49 +1897,43 @@ namespace Barotrauma.CharacterEditor } // Create the areas - rightArea = new GUIFrame(new RectTransform(new Vector2(0.15f, 0.95f), parent: Frame.RectTransform, anchor: Anchor.CenterRight) + rightArea = new GUILayoutGroup(new RectTransform(new Vector2(0.15f, 0.95f), parent: Frame.RectTransform, anchor: Anchor.CenterRight), childAnchor: Anchor.BottomRight) { - AbsoluteOffset = new Point(outerMargin.X, 0) - }, style: null) { CanBeFocused = false }; + RelativeSpacing = 0.02f + }; centerArea = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.95f), parent: Frame.RectTransform, anchor: Anchor.TopRight) { AbsoluteOffset = new Point((int)(rightArea.RectTransform.ScaledSize.X + rightArea.RectTransform.RelativeOffset.X * rightArea.RectTransform.Parent.ScaledSize.X + 20), outerMargin.Y + 20) }, style: null) { CanBeFocused = false }; - leftArea = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.95f), parent: Frame.RectTransform, anchor: Anchor.CenterLeft) + leftArea = new GUILayoutGroup(new RectTransform(new Vector2(0.15f, 0.95f), parent: Frame.RectTransform, anchor: Anchor.CenterLeft), childAnchor: Anchor.BottomLeft) { - AbsoluteOffset = new Point(outerMargin.X, 0) - }, style: null) - { - CanBeFocused = false + RelativeSpacing = 0.02f }; - Vector2 buttonSize = new Vector2(1, 0.04f); Vector2 toggleSize = new Vector2(1.0f, 0.03f); - CreateCharacterSelectionPanel(); - CreateMinorModesPanel(toggleSize); - CreateModesPanel(toggleSize); - CreateButtonsPanel(); CreateFileEditPanel(); CreateOptionsPanel(toggleSize); + CreateCharacterSelectionPanel(); + + CreateButtonsPanel(); + CreateModesPanel(toggleSize); + CreateMinorModesPanel(toggleSize); + CreateContextualControls(); } private void CreateMinorModesPanel(Vector2 toggleSize) { - minorModesPanel = new GUIFrame(new RectTransform(new Vector2(0.6f, 0.25f), leftArea.RectTransform, Anchor.BottomLeft) - { - RelativeOffset = new Vector2(0, 0.21f) - }, style: null, color: panelColor); - var layoutGroup = new GUILayoutGroup(new RectTransform(new Point(minorModesPanel.Rect.Width - innerMargin.X, minorModesPanel.Rect.Height - innerMargin.Y), - minorModesPanel.RectTransform, Anchor.Center)) + minorModesPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), leftArea.RectTransform)); + var layoutGroup = new GUILayoutGroup(new RectTransform(innerScale, minorModesPanel.RectTransform, Anchor.Center)) { AbsoluteSpacing = 2, Stretch = true }; - new GUITextBlock(new RectTransform(new Vector2(0.03f, 0.06f), layoutGroup.RectTransform), GetCharacterEditorTranslation("MinorModesTitle"), font: GUI.LargeFont); + new GUITextBlock(new RectTransform(new Vector2(0.03f, 0.0f), layoutGroup.RectTransform), GetCharacterEditorTranslation("MinorModesTitle"), font: GUI.LargeFont); paramsToggle = new GUITickBox(new RectTransform(toggleSize, layoutGroup.RectTransform), GetCharacterEditorTranslation("ShowParameters")) { Selected = showParamsEditor }; paramsToggle.OnSelected = box => { @@ -1992,19 +1979,19 @@ namespace Barotrauma.CharacterEditor drawDamageModifiers = box.Selected; return true; }; - minorModesToggle = new ToggleButton(new RectTransform(new Vector2(0.125f, 1), minorModesPanel.RectTransform, Anchor.CenterRight, Pivot.CenterLeft), Direction.Left); + minorModesToggle = new ToggleButton(new RectTransform(new Vector2(0.08f, 1), minorModesPanel.RectTransform, Anchor.CenterRight, Pivot.CenterLeft), Direction.Left); + minorModesPanel.RectTransform.MinSize = new Point(0, (int)(layoutGroup.RectTransform.Children.Sum(c => c.MinSize.Y + layoutGroup.AbsoluteSpacing) * 1.2f)); } private void CreateModesPanel(Vector2 toggleSize) { - modesPanel = new GUIFrame(new RectTransform(new Vector2(0.6f, 0.2f), leftArea.RectTransform, Anchor.BottomLeft), style: null, color: panelColor); - var layoutGroup = new GUILayoutGroup(new RectTransform(new Point(modesPanel.Rect.Width - innerMargin.X, modesPanel.Rect.Height - innerMargin.Y), - modesPanel.RectTransform, Anchor.Center)) + modesPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), leftArea.RectTransform)); + var layoutGroup = new GUILayoutGroup(new RectTransform(innerScale, modesPanel.RectTransform, Anchor.Center)) { AbsoluteSpacing = 2, Stretch = true }; - new GUITextBlock(new RectTransform(new Vector2(0.03f, 0.06f), layoutGroup.RectTransform), GetCharacterEditorTranslation("ModesPanel"), font: GUI.LargeFont); + new GUITextBlock(new RectTransform(new Vector2(0.03f, 0.0f), layoutGroup.RectTransform), GetCharacterEditorTranslation("ModesPanel"), font: GUI.LargeFont); characterInfoToggle = new GUITickBox(new RectTransform(toggleSize, layoutGroup.RectTransform), GetCharacterEditorTranslation("EditCharacter")) { Selected = editCharacterInfo }; ragdollToggle = new GUITickBox(new RectTransform(toggleSize, layoutGroup.RectTransform), GetCharacterEditorTranslation("EditRagdoll")) { Selected = editRagdoll }; limbsToggle = new GUITickBox(new RectTransform(toggleSize, layoutGroup.RectTransform), GetCharacterEditorTranslation("EditLimbs")) { Selected = editLimbs }; @@ -2086,7 +2073,8 @@ namespace Barotrauma.CharacterEditor ResetParamsEditor(); return true; }; - modesToggle = new ToggleButton(new RectTransform(new Vector2(0.125f, 1), modesPanel.RectTransform, Anchor.CenterRight, Pivot.CenterLeft), Direction.Left); + modesToggle = new ToggleButton(new RectTransform(new Vector2(0.08f, 1), modesPanel.RectTransform, Anchor.CenterRight, Pivot.CenterLeft), Direction.Left); + modesPanel.RectTransform.MinSize = new Point(0, (int)(layoutGroup.RectTransform.Children.Sum(c => c.MinSize.Y + layoutGroup.AbsoluteSpacing) * 1.2f)); } private void SetToggle(GUITickBox toggle, bool value) @@ -2095,11 +2083,11 @@ namespace Barotrauma.CharacterEditor { if (value) { - toggle.Box.Flash(Color.LightGreen, useRectangleFlash: true); + toggle.Box.Flash(GUI.Style.Green, useRectangleFlash: true); } else { - toggle.Box.Flash(Color.Red, useRectangleFlash: true); + toggle.Box.Flash(GUI.Style.Red, useRectangleFlash: true); } } toggle.Selected = value; @@ -2107,11 +2095,7 @@ namespace Barotrauma.CharacterEditor private void CreateButtonsPanel() { - buttonsPanel = new GUIFrame(new RectTransform(new Vector2(0.6f, 0.1f), leftArea.RectTransform, Anchor.BottomLeft) - { - MinSize = new Point(120, 60), - RelativeOffset = new Vector2(0, 0.47f) - }, style: null, color: panelColor); + buttonsPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), leftArea.RectTransform)); Vector2 buttonSize = new Vector2(1, 0.45f); var parent = new GUIFrame(new RectTransform(new Vector2(0.85f, 0.70f), buttonsPanel.RectTransform, Anchor.Center), style: null); var reloadTexturesButton = new GUIButton(new RectTransform(buttonSize, parent.RectTransform, Anchor.TopCenter), GetCharacterEditorTranslation("ReloadTextures")); @@ -2136,23 +2120,20 @@ namespace Barotrauma.CharacterEditor return true; } }; - buttonsPanelToggle = new ToggleButton(new RectTransform(new Vector2(0.125f, 1), buttonsPanel.RectTransform, Anchor.CenterRight, Pivot.CenterLeft), Direction.Left); + buttonsPanelToggle = new ToggleButton(new RectTransform(new Vector2(0.08f, 1), buttonsPanel.RectTransform, Anchor.CenterRight, Pivot.CenterLeft), Direction.Left); + buttonsPanel.RectTransform.MinSize = new Point(0, (int)(parent.RectTransform.Children.Sum(c => c.MinSize.Y) * 1.5f)); } private void CreateOptionsPanel(Vector2 toggleSize) { - optionsPanel = new GUIFrame(new RectTransform(new Vector2(1, 0.3f), rightArea.RectTransform, Anchor.Center) - { - RelativeOffset = new Vector2(0, -0.075f) - }, style: null, color: panelColor); - var layoutGroup = new GUILayoutGroup(new RectTransform(new Point(optionsPanel.Rect.Width - innerMargin.X, optionsPanel.Rect.Height - innerMargin.Y), - optionsPanel.RectTransform, Anchor.Center)) + optionsPanel = new GUIFrame(new RectTransform(new Vector2(1, 0.3f), rightArea.RectTransform)); + var layoutGroup = new GUILayoutGroup(new RectTransform(innerScale, optionsPanel.RectTransform, Anchor.Center)) { AbsoluteSpacing = 2, Stretch = true }; - new GUITextBlock(new RectTransform(new Vector2(0.03f, 0.06f), layoutGroup.RectTransform), GetCharacterEditorTranslation("OptionsPanel"), font: GUI.LargeFont); + new GUITextBlock(new RectTransform(new Vector2(0.03f, 0.0f), layoutGroup.RectTransform), GetCharacterEditorTranslation("OptionsPanel"), font: GUI.LargeFont); freezeToggle = new GUITickBox(new RectTransform(toggleSize, layoutGroup.RectTransform), GetCharacterEditorTranslation("Freeze")) { Selected = isFrozen, @@ -2218,7 +2199,8 @@ namespace Barotrauma.CharacterEditor return true; } }; - optionsToggle = new ToggleButton(new RectTransform(new Vector2(0.1f, 1), optionsPanel.RectTransform, Anchor.CenterLeft, Pivot.CenterRight), Direction.Right); + optionsToggle = new ToggleButton(new RectTransform(new Vector2(0.08f, 1), optionsPanel.RectTransform, Anchor.CenterLeft, Pivot.CenterRight), Direction.Right); + optionsPanel.RectTransform.MinSize = new Point(0, (int)(layoutGroup.RectTransform.Children.Sum(c => c.MinSize.Y + layoutGroup.AbsoluteSpacing) * 1.2f)); } private void CreateContextualControls() @@ -2266,12 +2248,12 @@ namespace Barotrauma.CharacterEditor switch (i) { case 0: - colorLabel.TextColor = Color.Red; + colorLabel.TextColor = GUI.Style.Red; numberInput.IntValue = backgroundColor.R; numberInput.OnValueChanged += (numInput) => backgroundColor.R = (byte)numInput.IntValue; break; case 1: - colorLabel.TextColor = Color.LightGreen; + colorLabel.TextColor = GUI.Style.Green; numberInput.IntValue = backgroundColor.G; numberInput.OnValueChanged += (numInput) => backgroundColor.G = (byte)numInput.IntValue; break; @@ -2294,7 +2276,7 @@ namespace Barotrauma.CharacterEditor new GUITextBlock(new RectTransform(new Point(elementSize.X, textAreaHeight), layoutGroupSpriteSheet.RectTransform), GetCharacterEditorTranslation("SpriteSheetZoom") + ":", Color.White); var spriteSheetControlElement = new GUIFrame(new RectTransform(new Point(elementSize.X * 2, textAreaHeight), layoutGroupSpriteSheet.RectTransform), style: null); CalculateSpritesheetZoom(); - spriteSheetZoomBar = new GUIScrollBar(new RectTransform(new Vector2(0.75f, 1), spriteSheetControlElement.RectTransform), barSize: 0.2f) + spriteSheetZoomBar = new GUIScrollBar(new RectTransform(new Vector2(0.75f, 1), spriteSheetControlElement.RectTransform, Anchor.CenterLeft), barSize: 0.2f) { BarScroll = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(spriteSheetMinZoom, spriteSheetMaxZoom, spriteSheetZoom)), Step = 0.01f, @@ -2304,8 +2286,9 @@ namespace Barotrauma.CharacterEditor return true; } }; - new GUIButton(new RectTransform(new Vector2(0.3f, 1), spriteSheetControlElement.RectTransform, Anchor.TopRight), GetCharacterEditorTranslation("Reset")) - { + new GUIButton(new RectTransform(new Vector2(0.3f, 1), spriteSheetControlElement.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.75f, 0.0f) }, + GetCharacterEditorTranslation("Reset")) + { OnClicked = (box, data) => { spriteSheetZoom = Math.Min(1, spriteSheetMaxZoom); @@ -2437,11 +2420,11 @@ namespace Barotrauma.CharacterEditor { ToolTip = GetCharacterEditorTranslation("CopyJointSettingsTooltip"), Selected = copyJointSettings, - TextColor = copyJointSettings ? Color.Red : Color.White, + TextColor = copyJointSettings ? GUI.Style.Red : Color.White, OnSelected = (GUITickBox box) => { copyJointSettings = box.Selected; - box.TextColor = copyJointSettings ? Color.Red : Color.White; + box.TextColor = copyJointSettings ? GUI.Style.Red : Color.White; return true; } }; @@ -2523,7 +2506,7 @@ namespace Barotrauma.CharacterEditor return true; }; - Point buttonSize = new Point(140, 30); + Point buttonSize = new Point(180, 30); int innerMargin = 5; int outerMargin = 10; extraRagdollControls = new GUIFrame(new RectTransform(new Point(buttonSize.X + outerMargin * 2, buttonSize.Y * 4 + innerMargin * 3 + outerMargin * 2), centerArea.RectTransform, Anchor.BottomRight) @@ -2570,6 +2553,11 @@ namespace Barotrauma.CharacterEditor } }; + extraRagdollLayout.RectTransform.Resize( + new Point(extraRagdollLayout.Rect.Width, extraRagdollLayout.RectTransform.Children.Sum(c => c.MinSize.Y + extraRagdollLayout.AbsoluteSpacing))); + extraRagdollControls.RectTransform.Resize(new Point(extraRagdollControls.Rect.Width, extraRagdollLayout.Rect.Height + outerMargin * 2)); + GUITextBlock.AutoScaleAndNormalize(extraRagdollLayout.Children.Where(c => c is GUIButton).Select(b => ((GUIButton)b).TextBlock)); + // Animation animationControls = new GUIFrame(new RectTransform(Vector2.One, centerArea.RectTransform), style: null) { CanBeFocused = false }; var layoutGroupAnimation = new GUILayoutGroup(new RectTransform(Vector2.One, animationControls.RectTransform), childAnchor: Anchor.TopLeft) { CanBeFocused = false }; @@ -2647,25 +2635,20 @@ namespace Barotrauma.CharacterEditor private void CreateCharacterSelectionPanel() { - characterSelectionPanel = new GUIFrame(new RectTransform(new Vector2(1, 0.25f), rightArea.RectTransform, Anchor.TopRight), style: null, color: panelColor); - var padding = new GUIFrame(new RectTransform(new Point(characterSelectionPanel.Rect.Width - innerMargin.X, characterSelectionPanel.Rect.Height - innerMargin.Y), - characterSelectionPanel.RectTransform, Anchor.Center), style: null) + characterSelectionPanel = new GUIFrame(new RectTransform(new Vector2(1, 0.2f), rightArea.RectTransform)); + var content = new GUILayoutGroup(new RectTransform(innerScale, characterSelectionPanel.RectTransform, Anchor.Center)) { - CanBeFocused = false + Stretch = true }; - // Disclaimer - var disclaimerBtnHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), padding.RectTransform), style: null); - var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), disclaimerBtnHolder.RectTransform, Anchor.TopRight), style: "GUINotificationButton") + // Character selection + var characterLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), GetCharacterEditorTranslation("CharacterPanel"), font: GUI.LargeFont); + var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(0.2f, 0.7f), characterLabel.RectTransform, Anchor.CenterRight), style: "GUINotificationButton") { OnClicked = (btn, userdata) => { GameMain.Instance.ShowEditorDisclaimer(); return true; } }; - disclaimerBtn.RectTransform.MaxSize = new Point(disclaimerBtn.Rect.Height); - // Character selection - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.2f), padding.RectTransform), GetCharacterEditorTranslation("CharacterPanel"), font: GUI.LargeFont); - - var characterDropDown = new GUIDropDown(new RectTransform(new Vector2(1, 0.2f), padding.RectTransform) + var characterDropDown = new GUIDropDown(new RectTransform(new Vector2(1, 0.2f), content.RectTransform) { RelativeOffset = new Vector2(0, 0.2f) }, elementCount: 8, style: null); @@ -2682,7 +2665,7 @@ namespace Barotrauma.CharacterEditor }; if (currentCharacterConfig == CharacterPrefab.HumanConfigFile) { - var jobDropDown = new GUIDropDown(new RectTransform(new Vector2(1, 0.15f), padding.RectTransform) + var jobDropDown = new GUIDropDown(new RectTransform(new Vector2(1, 0.15f), content.RectTransform) { RelativeOffset = new Vector2(0, 0.45f) }, elementCount: 8, style: null); @@ -2701,7 +2684,7 @@ namespace Barotrauma.CharacterEditor return true; }; } - var charButtons = new GUIFrame(new RectTransform(new Vector2(1, 0.25f), parent: padding.RectTransform, anchor: Anchor.BottomLeft), style: null); + var charButtons = new GUIFrame(new RectTransform(new Vector2(1, 0.25f), parent: content.RectTransform, anchor: Anchor.BottomLeft), style: null); var prevCharacterButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), charButtons.RectTransform, Anchor.TopLeft), GetCharacterEditorTranslation("PreviousCharacter")); prevCharacterButton.TextBlock.AutoScale = true; prevCharacterButton.OnClicked += (b, obj) => @@ -2716,33 +2699,34 @@ namespace Barotrauma.CharacterEditor SpawnCharacter(GetNextConfigFile()); return true; }; - characterPanelToggle = new ToggleButton(new RectTransform(new Vector2(0.1f, 1), characterSelectionPanel.RectTransform, Anchor.CenterLeft, Pivot.CenterRight), Direction.Right); + charButtons.RectTransform.MinSize = new Point(0, prevCharacterButton.RectTransform.MinSize.Y); + characterPanelToggle = new ToggleButton(new RectTransform(new Vector2(0.08f, 1), characterSelectionPanel.RectTransform, Anchor.CenterLeft, Pivot.CenterRight), Direction.Right); + characterSelectionPanel.RectTransform.MinSize = new Point(0, (int)(content.RectTransform.Children.Sum(c => c.MinSize.Y) * 1.2f)); } private void CreateFileEditPanel() { Vector2 buttonSize = new Vector2(1, 0.04f); - fileEditPanel = new GUIFrame(new RectTransform(new Vector2(1, 0.4f), rightArea.RectTransform, Anchor.BottomRight), style: null, color: panelColor); - var layoutGroup = new GUILayoutGroup(new RectTransform(new Point(fileEditPanel.Rect.Width - innerMargin.X, fileEditPanel.Rect.Height - innerMargin.Y), - fileEditPanel.RectTransform, Anchor.Center)) + fileEditPanel = new GUIFrame(new RectTransform(new Vector2(1, 0.4f), rightArea.RectTransform)); + var layoutGroup = new GUILayoutGroup(new RectTransform(innerScale, fileEditPanel.RectTransform, Anchor.Center)) { AbsoluteSpacing = 1, Stretch = true }; - new GUITextBlock(new RectTransform(new Vector2(0.03f, 0.06f), layoutGroup.RectTransform), GetCharacterEditorTranslation("FileEditPanel"), font: GUI.LargeFont); + new GUITextBlock(new RectTransform(new Vector2(0.03f, 0.0f), layoutGroup.RectTransform), GetCharacterEditorTranslation("FileEditPanel"), font: GUI.LargeFont); // Spacing new GUIFrame(new RectTransform(buttonSize / 2, layoutGroup.RectTransform), style: null) { CanBeFocused = false }; var saveAllButton = new GUIButton(new RectTransform(buttonSize, layoutGroup.RectTransform), TextManager.Get("editor.saveall")); - saveAllButton.Color = Color.LightGreen; + saveAllButton.Color = GUI.Style.Green; saveAllButton.OnClicked += (button, userData) => { #if !DEBUG if (VanillaCharacters != null && VanillaCharacters.Contains(currentCharacterConfig)) { - GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), Color.Red, font: GUI.LargeFont); + GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), GUI.Style.Red, font: GUI.LargeFont); return false; } #endif @@ -2754,9 +2738,9 @@ namespace Barotrauma.CharacterEditor else { character.Params.Save(); - GUI.AddMessage(GetCharacterEditorTranslation("CharacterSavedTo").Replace("[path]", CharacterParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5); + GUI.AddMessage(GetCharacterEditorTranslation("CharacterSavedTo").Replace("[path]", CharacterParams.FullPath), GUI.Style.Green, font: GUI.Font, lifeTime: 5); character.AnimController.SaveRagdoll(); - GUI.AddMessage(GetCharacterEditorTranslation("RagdollSavedTo").Replace("[path]", RagdollParams.FullPath), Color.Green, font: GUI.Font, lifeTime: 5); + GUI.AddMessage(GetCharacterEditorTranslation("RagdollSavedTo").Replace("[path]", RagdollParams.FullPath), GUI.Style.Green, font: GUI.Font, lifeTime: 5); AnimParams.ForEach(p => p.Save()); } return true; @@ -2781,7 +2765,7 @@ namespace Barotrauma.CharacterEditor #if !DEBUG if (VanillaCharacters != null && VanillaCharacters.Contains(currentCharacterConfig)) { - GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), Color.Red, font: GUI.LargeFont); + GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), GUI.Style.Red, font: GUI.LargeFont); box.Close(); return false; } @@ -2848,7 +2832,7 @@ namespace Barotrauma.CharacterEditor try { File.Delete(selectedFile); - GUI.AddMessage(GetCharacterEditorTranslation("RagdollDeletedFrom").Replace("[file]", selectedFile), Color.Red, font: GUI.Font); + GUI.AddMessage(GetCharacterEditorTranslation("RagdollDeletedFrom").Replace("[file]", selectedFile), GUI.Style.Red, font: GUI.Font); } catch (Exception e) { @@ -2916,7 +2900,7 @@ namespace Barotrauma.CharacterEditor #if !DEBUG if (VanillaCharacters != null && VanillaCharacters.Contains(currentCharacterConfig)) { - GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), Color.Red, font: GUI.LargeFont); + GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), GUI.Style.Red, font: GUI.LargeFont); box.Close(); return false; } @@ -3005,7 +2989,7 @@ namespace Barotrauma.CharacterEditor try { File.Delete(selectedFile); - GUI.AddMessage(GetCharacterEditorTranslation("AnimationOfTypeDeleted").Replace("[type]", selectedType.ToString()).Replace("[file]", selectedFile), Color.Red, font: GUI.Font); + GUI.AddMessage(GetCharacterEditorTranslation("AnimationOfTypeDeleted").Replace("[type]", selectedType.ToString()).Replace("[file]", selectedFile), GUI.Style.Red, font: GUI.Font); } catch (Exception e) { @@ -3080,7 +3064,7 @@ namespace Barotrauma.CharacterEditor // Spacing new GUIFrame(new RectTransform(buttonSize / 2, layoutGroup.RectTransform), style: null) { CanBeFocused = false }; var resetButton = new GUIButton(new RectTransform(buttonSize, layoutGroup.RectTransform), GetCharacterEditorTranslation("ResetButton")); - resetButton.Color = Color.Red; + resetButton.Color = GUI.Style.Red; resetButton.OnClicked += (button, userData) => { CharacterParams.Reset(true); @@ -3121,7 +3105,7 @@ namespace Barotrauma.CharacterEditor } }; - fileEditToggle = new ToggleButton(new RectTransform(new Vector2(0.1f, 1), fileEditPanel.RectTransform, Anchor.CenterLeft, Pivot.CenterRight), Direction.Right); + fileEditToggle = new ToggleButton(new RectTransform(new Vector2(0.08f, 1), fileEditPanel.RectTransform, Anchor.CenterLeft, Pivot.CenterRight), Direction.Right); void ResetView() { @@ -3135,6 +3119,8 @@ namespace Barotrauma.CharacterEditor skeletonToggle.Selected = false; damageModifiersToggle.Selected = false; } + + fileEditPanel.RectTransform.MinSize = new Point(0, (int)(layoutGroup.RectTransform.Children.Sum(c => c.MinSize.Y + layoutGroup.AbsoluteSpacing) * 1.2f)); } #endregion @@ -3165,9 +3151,9 @@ namespace Barotrauma.CharacterEditor public ToggleButton(RectTransform rectT, Direction dir) { + rectT.MaxSize = new Point(int.MaxValue, (int)(100 * GUI.Scale)); toggleButton = new GUIButton(rectT, style: "UIToggleButton") { - Color = toggleButtonColor, OnClicked = (button, data) => { IsHidden = !IsHidden; @@ -3196,8 +3182,8 @@ namespace Barotrauma.CharacterEditor public void UpdateOpenState(float deltaTime, Vector2 hiddenPos, RectTransform panel) { - panel.AbsoluteOffset = Vector2.SmoothStep(hiddenPos, Vector2.Zero, OpenState).ToPoint(); - OpenState = isHidden ? Math.Max(OpenState - deltaTime * 2, 0) : Math.Min(OpenState + deltaTime * 2, 1); + panel.AbsoluteOffset = new Vector2(MathHelper.SmoothStep(hiddenPos.X, 0.0f, OpenState), panel.AbsoluteOffset.Y).ToPoint(); + OpenState = isHidden ? Math.Max(OpenState - deltaTime * 5, 0) : Math.Min(OpenState + deltaTime * 5, 1); } } @@ -3354,7 +3340,7 @@ namespace Barotrauma.CharacterEditor { CanBeFocused = false }; - new GUIButton(new RectTransform(new Vector2(0.08f, 0.8f), parent.RectTransform, Anchor.BottomRight), "X", color: Color.Red) + new GUIButton(new RectTransform(new Vector2(0.08f, 0.8f), parent.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight), style: "GUICancelButton", color: GUI.Style.Red) { OnClicked = (button, data) => { @@ -3832,7 +3818,7 @@ namespace Barotrauma.CharacterEditor DrawRadialWidget(spriteBatch, SimToScreen(head.SimPosition), animParams.HeadAngle, GetCharacterEditorTranslation("HeadAngle"), Color.White, angle => TryUpdateAnimParam("headangle", angle), circleRadius: 25, rotationOffset: collider.Rotation + MathHelper.Pi, clockWise: dir < 0, wrapAnglePi: true, holdPosition: true); // Head position and leaning - Color color = Color.Red; + Color color = GUI.Style.Red; if (animParams.IsGroundedAnimation) { if (humanGroundedParams != null && character.AnimController is HumanoidAnimController humanAnimController) @@ -4110,7 +4096,7 @@ namespace Barotrauma.CharacterEditor { if (hand != null || arm != null) { - GetAnimationWidget("HandMoveAmount", Color.LightGreen, Color.Black, initMethod: w => + GetAnimationWidget("HandMoveAmount", GUI.Style.Green, Color.Black, initMethod: w => { w.tooltip = GetCharacterEditorTranslation("HandMoveAmount"); float offset = 0.1f; @@ -4131,7 +4117,7 @@ namespace Barotrauma.CharacterEditor { if (w.IsSelected) { - GUI.DrawLine(sp, w.DrawPos, SimToScreen(collider.SimPosition + GetSimSpaceForward() * offset), Color.LightGreen); + GUI.DrawLine(sp, w.DrawPos, SimToScreen(collider.SimPosition + GetSimSpaceForward() * offset), GUI.Style.Green); } }; }).Draw(spriteBatch, deltaTime); @@ -4250,7 +4236,7 @@ namespace Barotrauma.CharacterEditor lengthWidget.Draw(spriteBatch, deltaTime); amplitudeWidget.Draw(spriteBatch, deltaTime); // Arms - GetAnimationWidget("HandMoveAmount", Color.LightGreen, Color.Black, initMethod: w => + GetAnimationWidget("HandMoveAmount", GUI.Style.Green, Color.Black, initMethod: w => { w.tooltip = GetCharacterEditorTranslation("HandMoveAmount"); float offset = 0.4f; @@ -4273,7 +4259,7 @@ namespace Barotrauma.CharacterEditor { if (w.IsSelected) { - GUI.DrawLine(sp, w.DrawPos, SimToScreen(collider.SimPosition + GetSimSpaceForward() * offset), Color.LightGreen); + GUI.DrawLine(sp, w.DrawPos, SimToScreen(collider.SimPosition + GetSimSpaceForward() * offset), GUI.Style.Green); } }; }).Draw(spriteBatch, deltaTime); @@ -4284,7 +4270,7 @@ namespace Barotrauma.CharacterEditor if (limb.type == LimbType.LeftFoot || limb.type == LimbType.RightFoot) { GUI.DrawRectangle(spriteBatch, SimToScreen(limb.DebugRefPos) - Vector2.One * 3, Vector2.One * 6, Color.White, isFilled: true); - GUI.DrawRectangle(spriteBatch, SimToScreen(limb.DebugTargetPos) - Vector2.One * 3, Vector2.One * 6, Color.LightGreen, isFilled: true); + GUI.DrawRectangle(spriteBatch, SimToScreen(limb.DebugTargetPos) - Vector2.One * 3, Vector2.One * 6, GUI.Style.Green, isFilled: true); } } } @@ -4379,7 +4365,7 @@ namespace Barotrauma.CharacterEditor { var pullJointWidgetSize = new Vector2(5, 5); Vector2 tformedPullPos = SimToScreen(limb.PullJointWorldAnchorA); - GUI.DrawRectangle(spriteBatch, tformedPullPos - pullJointWidgetSize / 2, pullJointWidgetSize, Color.Red, true); + GUI.DrawRectangle(spriteBatch, tformedPullPos - pullJointWidgetSize / 2, pullJointWidgetSize, GUI.Style.Red, true); DrawWidget(spriteBatch, tformedPullPos, WidgetType.Rectangle, 8, Color.Cyan, $"IK ({limb.Name})", () => { if (!selectedLimbs.Contains(limb)) @@ -4451,7 +4437,7 @@ namespace Barotrauma.CharacterEditor //GUI.DrawRectangle(spriteBatch, tformedJointPos - dotSize / 2, dotSize, color, true); //GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + up * 20, Color.White, width: 3); GUI.DrawLine(spriteBatch, limbScreenPos, tformedJointPos, Color.Yellow, width: 3); - //GUI.DrawRectangle(spriteBatch, inputRect, Color.Red); + //GUI.DrawRectangle(spriteBatch, inputRect, GUI.Style.Red); GUI.DrawString(spriteBatch, tformedJointPos + new Vector2(dotSize.X, -dotSize.Y) * 2, $"{joint.Params.Name} {jointPos.FormatZeroDecimal()}", Color.White, Color.Black * 0.5f); if (PlayerInput.PrimaryMouseButtonHeld()) { @@ -4717,7 +4703,7 @@ namespace Barotrauma.CharacterEditor { if (isSelected || !onlyShowSourceRectForSelectedLimbs) { - GUI.DrawRectangle(spriteBatch, rect, isSelected ? Color.Yellow : (isMouseOn ? Color.White : Color.Red)); + GUI.DrawRectangle(spriteBatch, rect, isSelected ? Color.Yellow : (isMouseOn ? Color.White : GUI.Style.Red)); } } if (isSelected) @@ -5048,7 +5034,7 @@ namespace Barotrauma.CharacterEditor private void DrawJointLimitWidgets(SpriteBatch spriteBatch, Limb limb, LimbJoint joint, Vector2 drawPos, bool autoFreeze, bool allowPairEditing, bool holdPosition, float rotationOffset = 0) { rotationOffset -= limb.Params.GetSpriteOrientation(); - Color angleColor = joint.UpperLimit - joint.LowerLimit > 0 ? Color.LightGreen * 0.5f : Color.Red; + Color angleColor = joint.UpperLimit - joint.LowerLimit > 0 ? GUI.Style.Green * 0.5f : GUI.Style.Red; DrawRadialWidget(spriteBatch, drawPos, MathHelper.ToDegrees(joint.UpperLimit), $"{joint.Params.Name}: {GetCharacterEditorTranslation("UpperLimit")}", Color.Cyan, angle => { joint.UpperLimit = MathHelper.ToRadians(angle); @@ -5240,7 +5226,7 @@ namespace Barotrauma.CharacterEditor } onClick(angle); var zeroPos = drawPos + VectorExtensions.ForwardFlipped(rotationOffset, circleRadius); - GUI.DrawLine(spriteBatch, drawPos, zeroPos, Color.Red, width: 3); + GUI.DrawLine(spriteBatch, drawPos, zeroPos, GUI.Style.Red, width: 3); }, autoFreeze, holdPosition, onHovered: () => { if (!PlayerInput.PrimaryMouseButtonHeld()) @@ -5399,7 +5385,7 @@ namespace Barotrauma.CharacterEditor widget.refresh = () => { widget.showTooltip = !selectedJoints.Contains(joint); - widget.color = selectedJoints.Contains(joint) ? Color.Yellow : Color.Red; + widget.color = selectedJoints.Contains(joint) ? Color.Yellow : GUI.Style.Red; }; widget.refresh(); widget.PreUpdate += dTime => widget.Enabled = editJoints; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/Wizard.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/Wizard.cs index cc8088f3a..ba788163d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/Wizard.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/Wizard.cs @@ -110,7 +110,7 @@ namespace Barotrauma.CharacterEditor msgBox.Close(); if (CharacterEditorScreen.Instance.CreateCharacter(name, Path.GetDirectoryName(xmlPath), isHumanoid, contentPackage, ragdollElement, characterElement, animations)) { - GUI.AddMessage(GetCharacterEditorTranslation("CharacterCreated").Replace("[name]", name), Color.Green, font: GUI.Font); + GUI.AddMessage(GetCharacterEditorTranslation("CharacterCreated").Replace("[name]", name), GUI.Style.Green, font: GUI.Font); } Wizard.Instance.SelectTab(Tab.None); return true; @@ -126,7 +126,7 @@ namespace Barotrauma.CharacterEditor { if (CharacterEditorScreen.Instance.CreateCharacter(name, Path.GetDirectoryName(xmlPath), isHumanoid, contentPackage, ragdollElement, characterElement, animations)) { - GUI.AddMessage(GetCharacterEditorTranslation("CharacterCreated").Replace("[name]", name), Color.Green, font: GUI.Font); + GUI.AddMessage(GetCharacterEditorTranslation("CharacterCreated").Replace("[name]", name), GUI.Style.Green, font: GUI.Font); } Wizard.Instance.SelectTab(Tab.None); } @@ -141,12 +141,12 @@ namespace Barotrauma.CharacterEditor protected override GUIMessageBox Create() { - var box = new GUIMessageBox(GetCharacterEditorTranslation("CreateNewCharacter"), string.Empty, new string[] { TextManager.Get("Cancel"), IsCopy ? TextManager.Get("Create") : TextManager.Get("Next") }, new Vector2(0.65f, 1f)); + var box = new GUIMessageBox(GetCharacterEditorTranslation("CreateNewCharacter"), string.Empty, new string[] { TextManager.Get("Cancel"), IsCopy ? TextManager.Get("Create") : TextManager.Get("Next") }, new Vector2(0.65f, 0.9f)); box.Header.Font = GUI.LargeFont; box.Content.ChildAnchor = Anchor.TopCenter; box.Content.AbsoluteSpacing = 20; int elementSize = 30; - var frame = new GUIFrame(new RectTransform(new Point(box.Content.Rect.Width - (int)(80 * GUI.xScale), box.Content.Rect.Height - (int)(100 * GUI.yScale)), + var frame = new GUIFrame(new RectTransform(new Point(box.Content.Rect.Width - (int)(40 * GUI.xScale), box.Content.Rect.Height - (int)(50 * GUI.yScale)), box.Content.RectTransform, Anchor.Center), style: null, color: ParamsEditor.Color) { CanBeFocused = false @@ -174,13 +174,11 @@ namespace Barotrauma.CharacterEditor { var mainElement = new GUIFrame(new RectTransform(new Point(topGroup.RectTransform.Rect.Width, elementSize), topGroup.RectTransform), style: null, color: Color.Gray * 0.25f); fields.Add(mainElement); - RectTransform leftElement = new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.TopLeft); - RectTransform rightElement = new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.TopRight); switch (i) { case 0: - new GUITextBlock(leftElement, TextManager.Get("Name")); - var nameField = new GUITextBox(rightElement, Name ?? GetCharacterEditorTranslation("DefaultName")) { CaretColor = Color.White }; + new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), TextManager.Get("Name")); + var nameField = new GUITextBox(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), Name ?? GetCharacterEditorTranslation("DefaultName")) { CaretColor = Color.White }; string ProcessText(string text) => text.RemoveWhitespace().CapitaliseFirstInvariant(); Name = ProcessText(nameField.Text); nameField.OnTextChanged += (tb, text) => @@ -191,8 +189,8 @@ namespace Barotrauma.CharacterEditor }; break; case 1: - var label = new GUITextBlock(leftElement, GetCharacterEditorTranslation("IsHumanoid")); - var tickBox = new GUITickBox(rightElement, string.Empty) + var label = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), GetCharacterEditorTranslation("IsHumanoid")); + var tickBox = new GUITickBox(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), string.Empty) { Selected = IsHumanoid, Enabled = !IsCopy, @@ -204,8 +202,8 @@ namespace Barotrauma.CharacterEditor } break; case 2: - var l = new GUITextBlock(leftElement, GetCharacterEditorTranslation("CanEnterSubmarines")); - var t = new GUITickBox(rightElement, string.Empty) + var l = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), GetCharacterEditorTranslation("CanEnterSubmarines")); + var t = new GUITickBox(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), string.Empty) { Selected = CanEnterSubmarine, Enabled = !IsCopy, @@ -217,8 +215,8 @@ namespace Barotrauma.CharacterEditor } break; case 3: - var lbl = new GUITextBlock(leftElement, GetCharacterEditorTranslation("CanWalk")); - var txt = new GUITickBox(rightElement, string.Empty) + var lbl = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), GetCharacterEditorTranslation("CanWalk")); + var txt = new GUITickBox(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), string.Empty) { Selected = CanWalk, Enabled = !IsCopy, @@ -230,8 +228,8 @@ namespace Barotrauma.CharacterEditor } break; case 4: - new GUITextBlock(leftElement, GetCharacterEditorTranslation("ConfigFileOutput")); - xmlPathElement = new GUITextBox(rightElement, string.Empty) + new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), GetCharacterEditorTranslation("ConfigFileOutput")); + xmlPathElement = new GUITextBox(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), string.Empty) { Text = XMLPath, CaretColor = Color.White @@ -243,127 +241,138 @@ namespace Barotrauma.CharacterEditor }; break; case 5: - //new GUITextBlock(leftElement, GetCharacterEditorTranslation("TexturePath")); - texturePathElement = new GUITextBox(rightElement, string.Empty) { - Text = TexturePath, - CaretColor = Color.White, - }; - texturePathElement.OnTextChanged += (tb, text) => - { - updateTexturePath = false; - TexturePath = text; - return true; - }; - string title = GetCharacterEditorTranslation("SelectTexture"); - new GUIButton(leftElement, title) - { - OnClicked = (button, data) => + new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), GetCharacterEditorTranslation("TexturePath")); + var rightContainer = new GUIFrame(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), style: null); + texturePathElement = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), rightContainer.RectTransform, Anchor.CenterLeft), string.Empty) { - FileSelection.OnFileSelected = (file) => + Text = TexturePath, + CaretColor = Color.White, + }; + texturePathElement.OnTextChanged += (tb, text) => + { + updateTexturePath = false; + TexturePath = text; + return true; + }; + string title = GetCharacterEditorTranslation("SelectTexture"); + new GUIButton(new RectTransform(new Vector2(0.3f / texturePathElement.RectTransform.RelativeSize.X, 1.0f), texturePathElement.RectTransform, Anchor.CenterRight, Pivot.CenterLeft), title, style: "GUIButtonSmall") + { + OnClicked = (button, data) => { - string relativePath = UpdaterUtil.GetRelativePath(Path.GetFullPath(file), Environment.CurrentDirectory); - string destinationPath = relativePath; + FileSelection.OnFileSelected = (file) => + { + string relativePath = UpdaterUtil.GetRelativePath(Path.GetFullPath(file), Environment.CurrentDirectory); + string destinationPath = relativePath; //copy file to XML path if it's not located relative to the game's files if (relativePath.StartsWith("..") || - Path.GetPathRoot(Environment.CurrentDirectory) != Path.GetPathRoot(file)) - { - destinationPath = Path.Combine(Path.GetDirectoryName(XMLPath), Path.GetFileName(file)); - - string destinationDir = Path.GetDirectoryName(destinationPath); - if (!Directory.Exists(destinationDir)) + Path.GetPathRoot(Environment.CurrentDirectory) != Path.GetPathRoot(file)) { - Directory.CreateDirectory(destinationDir); + destinationPath = Path.Combine(Path.GetDirectoryName(XMLPath), Path.GetFileName(file)); + + string destinationDir = Path.GetDirectoryName(destinationPath); + if (!Directory.Exists(destinationDir)) + { + Directory.CreateDirectory(destinationDir); + } + + if (!File.Exists(destinationPath)) + { + File.Copy(file, Path.GetFullPath(destinationPath), overwrite: true); + } } - if (!File.Exists(destinationPath)) - { - File.Copy(file, Path.GetFullPath(destinationPath), overwrite: true); - } - } - - isTextureSelected = true; - texturePathElement.Text = destinationPath; - }; - FileSelection.ClearFileTypeFilters(); - FileSelection.AddFileTypeFilter("PNG", "*.png"); - FileSelection.AddFileTypeFilter("JPEG", "*.jpg, *.jpeg"); - FileSelection.AddFileTypeFilter("All files", "*.*"); - FileSelection.SelectFileTypeFilter("*.png"); - FileSelection.Open = true; - return true; - } - }; + isTextureSelected = true; + texturePathElement.Text = destinationPath; + }; + FileSelection.ClearFileTypeFilters(); + FileSelection.AddFileTypeFilter("PNG", "*.png"); + FileSelection.AddFileTypeFilter("JPEG", "*.jpg, *.jpeg"); + FileSelection.AddFileTypeFilter("All files", "*.*"); + FileSelection.SelectFileTypeFilter("*.png"); + FileSelection.Open = true; + return true; + } + }; + } break; case 6: - mainElement.RectTransform.NonScaledSize = new Point( - mainElement.RectTransform.NonScaledSize.X, - mainElement.RectTransform.NonScaledSize.Y * 2); - new GUITextBlock(leftElement, TextManager.Get("ContentPackage")); - var rightContainer = new GUIFrame(rightElement, style: null); - contentPackageDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.5f), rightContainer.RectTransform, Anchor.TopRight)); - foreach (ContentPackage cp in ContentPackage.List) { + mainElement.RectTransform.NonScaledSize = new Point( + mainElement.RectTransform.NonScaledSize.X, + mainElement.RectTransform.NonScaledSize.Y * 2); + new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), mainElement.RectTransform, Anchor.CenterLeft), TextManager.Get("ContentPackage")); + var rightContainer = new GUIFrame(new RectTransform(new Vector2(0.7f, 1), mainElement.RectTransform, Anchor.CenterRight), style: null); + contentPackageDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.5f), rightContainer.RectTransform, Anchor.TopRight)); + foreach (ContentPackage cp in ContentPackage.List) + { #if !DEBUG if (cp == GameMain.VanillaContent) { continue; } #endif - contentPackageDropDown.AddItem(cp.Name, userData: cp, toolTip: cp.Path); - } - contentPackageDropDown.OnSelected = (obj, userdata) => - { - ContentPackage = userdata as ContentPackage; - updateTexturePath = !isTextureSelected && !IsCopy; - UpdatePaths(); - return true; - }; - contentPackageDropDown.Select(0); - var contentPackageNameElement = new GUITextBox(new RectTransform(new Vector2(0.7f, 0.5f), rightContainer.RectTransform, Anchor.BottomLeft), - GetCharacterEditorTranslation("NewContentPackage")) - { - CaretColor = Color.White, - }; - var createNewPackageButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.5f), rightContainer.RectTransform, Anchor.BottomRight), TextManager.Get("CreateNew")) - { - OnClicked = (btn, userdata) => + contentPackageDropDown.AddItem(cp.Name, userData: cp, toolTip: cp.Path); + } + contentPackageDropDown.OnSelected = (obj, userdata) => { - if (string.IsNullOrEmpty(contentPackageNameElement.Text)) - { - contentPackageNameElement.Flash(); - return false; - } - if (ContentPackage.List.Any(cp => cp.Name.ToLower() == contentPackageNameElement.Text.ToLower())) - { - new GUIMessageBox("", TextManager.Get("charactereditor.contentpackagenameinuse", fallBackTag: "leveleditorlevelobjnametaken")); - return false; - } - string modName = ToolBox.RemoveInvalidFileNameChars(contentPackageNameElement.Text); - ContentPackage = ContentPackage.CreatePackage(contentPackageNameElement.Text, Path.Combine("Mods", modName, Steam.SteamManager.MetadataFileName), false); - ContentPackage.List.Add(ContentPackage); - GameMain.Config.SelectContentPackage(ContentPackage); - contentPackageDropDown.AddItem(ContentPackage.Name, ContentPackage, ContentPackage.Path); - contentPackageDropDown.SelectItem(ContentPackage); - contentPackageNameElement.Text = ""; + ContentPackage = userdata as ContentPackage; + updateTexturePath = !isTextureSelected && !IsCopy; + UpdatePaths(); return true; - }, - Enabled = false - }; - Color textColor = contentPackageNameElement.TextColor; - contentPackageNameElement.TextColor *= 0.6f; - contentPackageNameElement.OnSelected += (sender, key) => - { - contentPackageNameElement.Text = ""; - }; - contentPackageNameElement.OnTextChanged += (textBox, text) => - { - textBox.TextColor = textColor; - createNewPackageButton.Enabled = !string.IsNullOrWhiteSpace(text); - return true; - }; + }; + contentPackageDropDown.Select(0); + var contentPackageNameElement = new GUITextBox(new RectTransform(new Vector2(0.7f, 0.5f), rightContainer.RectTransform, Anchor.BottomLeft), + GetCharacterEditorTranslation("NewContentPackage")) + { + CaretColor = Color.White, + }; + var createNewPackageButton = new GUIButton(new RectTransform(new Vector2(0.3f / contentPackageNameElement.RectTransform.RelativeSize.X, 1.0f), contentPackageNameElement.RectTransform, Anchor.CenterRight, Pivot.CenterLeft), TextManager.Get("CreateNew"), style: "GUIButtonSmall") + { + OnClicked = (btn, userdata) => + { + if (string.IsNullOrEmpty(contentPackageNameElement.Text)) + { + contentPackageNameElement.Flash(); + return false; + } + if (ContentPackage.List.Any(cp => cp.Name.ToLower() == contentPackageNameElement.Text.ToLower())) + { + new GUIMessageBox("", TextManager.Get("charactereditor.contentpackagenameinuse", fallBackTag: "leveleditorlevelobjnametaken")); + return false; + } + string modName = ToolBox.RemoveInvalidFileNameChars(contentPackageNameElement.Text); + ContentPackage = ContentPackage.CreatePackage(contentPackageNameElement.Text, Path.Combine("Mods", modName, Steam.SteamManager.MetadataFileName), false); + ContentPackage.List.Add(ContentPackage); + GameMain.Config.SelectContentPackage(ContentPackage); + contentPackageDropDown.AddItem(ContentPackage.Name, ContentPackage, ContentPackage.Path); + contentPackageDropDown.SelectItem(ContentPackage); + contentPackageNameElement.Text = ""; + return true; + }, + Enabled = false + }; + Color textColor = contentPackageNameElement.TextColor; + contentPackageNameElement.TextColor *= 0.6f; + contentPackageNameElement.OnSelected += (sender, key) => + { + contentPackageNameElement.Text = ""; + }; + contentPackageNameElement.OnTextChanged += (textBox, text) => + { + textBox.TextColor = textColor; + createNewPackageButton.Enabled = !string.IsNullOrWhiteSpace(text); + return true; + }; + rightContainer.RectTransform.MinSize = new Point(0, + contentPackageDropDown.RectTransform.MinSize.Y + Math.Max(contentPackageNameElement.RectTransform.MinSize.Y, createNewPackageButton.RectTransform.MinSize.Y)); + } break; } + int contentSize = mainElement.RectTransform.Children.Max(c => c.MinSize.Y) ; + mainElement.RectTransform.Resize(new Point(mainElement.Rect.Width, Math.Max(mainElement.Rect.Height, contentSize))); } UpdatePaths(); + box.Buttons[0].Parent.RectTransform.SetAsLastChild(); + box.Buttons[1].RectTransform.SetAsLastChild(); // Cancel box.Buttons[0].OnClicked += (b, d) => { @@ -380,15 +389,15 @@ namespace Barotrauma.CharacterEditor } if (!File.Exists(TexturePath)) { - GUI.AddMessage(GetCharacterEditorTranslation("TextureDoesNotExist"), Color.Red); - texturePathElement.Flash(Color.Red); + GUI.AddMessage(GetCharacterEditorTranslation("TextureDoesNotExist"), GUI.Style.Red); + texturePathElement.Flash(GUI.Style.Red); return false; } var path = Path.GetFileName(TexturePath); if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase)) { - GUI.AddMessage(TextManager.Get("WrongFileType"), Color.Red); - texturePathElement.Flash(Color.Red); + GUI.AddMessage(TextManager.Get("WrongFileType"), GUI.Style.Red); + texturePathElement.Flash(GUI.Style.Red); return false; } if (IsCopy) @@ -421,27 +430,32 @@ namespace Barotrauma.CharacterEditor var box = new GUIMessageBox(GetCharacterEditorTranslation("DefineRagdoll"), string.Empty, new string[] { TextManager.Get("Previous"), TextManager.Get("Create") }, new Vector2(0.65f, 1f)); box.Header.Font = GUI.LargeFont; box.Content.ChildAnchor = Anchor.TopCenter; - box.Content.AbsoluteSpacing = 20; - int elementSize = 30; + box.Content.AbsoluteSpacing = (int)(20 * GUI.Scale); + int elementSize = (int)(30 * GUI.Scale); var frame = new GUIFrame(new RectTransform(new Point(box.Content.Rect.Width - (int)(80 * GUI.xScale), box.Content.Rect.Height - (int)(200 * GUI.yScale)), box.Content.RectTransform, Anchor.Center), style: null, color: ParamsEditor.Color) { CanBeFocused = false }; - var topGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.05f), frame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.TopCenter) { AbsoluteSpacing = 2 }; - var bottomGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.9f), frame.RectTransform, Anchor.BottomCenter), childAnchor: Anchor.TopCenter) { AbsoluteSpacing = 10 }; + var content = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.9f), frame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.TopCenter) + { + Stretch = true, + RelativeSpacing = 0.02f + }; // HTML GUIMessageBox htmlBox = null; - var loadHtmlButton = new GUIButton(new RectTransform(new Point(topGroup.Rect.Width / 3, elementSize), topGroup.RectTransform), GetCharacterEditorTranslation("LoadFromHTML")); + var loadHtmlButton = new GUIButton(new RectTransform(new Point(content.Rect.Width / 3, elementSize), content.RectTransform), GetCharacterEditorTranslation("LoadFromHTML")); // Limbs - var limbsElement = new GUIFrame(new RectTransform(new Vector2(1, 0.05f), bottomGroup.RectTransform), style: null) { CanBeFocused = false }; - new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), limbsElement.RectTransform), $"{GetCharacterEditorTranslation("Limbs")}: "); - var limbButtonElement = new GUIFrame(new RectTransform(new Vector2(0.8f, 1f), limbsElement.RectTransform) - { RelativeOffset = new Vector2(0.1f, 0) }, style: null) - { CanBeFocused = false }; - var limbEditLayout = new GUILayoutGroup(new RectTransform(Vector2.One, limbButtonElement.RectTransform), isHorizontal: true) { AbsoluteSpacing = 10 }; - var limbsList = new GUIListBox(new RectTransform(new Vector2(1, 0.45f), bottomGroup.RectTransform)); - var removeLimbButton = new GUIButton(new RectTransform(new Point(limbButtonElement.Rect.Height, limbButtonElement.Rect.Height), limbEditLayout.RectTransform), "-") + var limbsElement = new GUIFrame(new RectTransform(new Vector2(1, 0.05f), content.RectTransform), style: null) { CanBeFocused = false }; + + var limbEditLayout = new GUILayoutGroup(new RectTransform(Vector2.One, limbsElement.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), limbEditLayout.RectTransform), GetCharacterEditorTranslation("Limbs"), font: GUI.SubHeadingFont); + var limbsList = new GUIListBox(new RectTransform(new Vector2(1, 0.45f), content.RectTransform)); + var removeLimbButton = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), limbEditLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton") { OnClicked = (b, d) => { @@ -452,7 +466,7 @@ namespace Barotrauma.CharacterEditor return true; } }; - var addLimbButton = new GUIButton(new RectTransform(new Point(limbButtonElement.Rect.Height, limbButtonElement.Rect.Height), limbEditLayout.RectTransform), "+") + var addLimbButton = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), limbEditLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton") { OnClicked = (b, d) => { @@ -472,9 +486,7 @@ namespace Barotrauma.CharacterEditor }; int _x = 1, _y = 1, w = 100, h = 100; - int otherElements = limbButtonElement.Rect.Width / 4 + 10 + limbButtonElement.Rect.Height * 2 + 10 + limbButtonElement.RectTransform.AbsoluteOffset.X; - frame = new GUIFrame(new RectTransform(new Point(limbEditLayout.Rect.Width - otherElements, limbButtonElement.Rect.Height), limbEditLayout.RectTransform), color: Color.Transparent); - var inputArea = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) + var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), limbEditLayout.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.01f @@ -523,8 +535,9 @@ namespace Barotrauma.CharacterEditor } }; } - new GUIButton(new RectTransform(new Point(limbButtonElement.Rect.Width / 4, limbButtonElement.Rect.Height), limbEditLayout.RectTransform) - , GetCharacterEditorTranslation("AddMultipleLimbsButton")) + inputArea.Recalculate(); + new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), limbEditLayout.RectTransform), + GetCharacterEditorTranslation("AddMultipleLimbsButton")) { OnClicked = (b, d) => { @@ -532,6 +545,8 @@ namespace Barotrauma.CharacterEditor return true; } }; + limbsElement.RectTransform.MinSize = new Point(0, limbEditLayout.RectTransform.Children.Max(c => c.MinSize.Y)); + // If no elements are defined, create some as default if (LimbGUIElements.None()) { @@ -606,14 +621,14 @@ namespace Barotrauma.CharacterEditor } } // Joints - new GUIFrame(new RectTransform(new Vector2(1, 0.05f), bottomGroup.RectTransform), style: null) { CanBeFocused = false }; - var jointsElement = new GUIFrame(new RectTransform(new Vector2(1, 0.05f), bottomGroup.RectTransform), style: null) { CanBeFocused = false }; - new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), jointsElement.RectTransform), $"{GetCharacterEditorTranslation("Joints")}: "); + new GUIFrame(new RectTransform(new Vector2(1, 0.05f), content.RectTransform), style: null) { CanBeFocused = false }; + var jointsElement = new GUIFrame(new RectTransform(new Vector2(1, 0.05f), content.RectTransform), style: null) { CanBeFocused = false }; + new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), jointsElement.RectTransform), GetCharacterEditorTranslation("Joints"), font: GUI.SubHeadingFont); var jointButtonElement = new GUIFrame(new RectTransform(new Vector2(0.5f, 1f), jointsElement.RectTransform) - { RelativeOffset = new Vector2(0.1f, 0) }, style: null) + { RelativeOffset = new Vector2(0.15f, 0) }, style: null) { CanBeFocused = false }; - var jointsList = new GUIListBox(new RectTransform(new Vector2(1, 0.45f), bottomGroup.RectTransform)); - var removeJointButton = new GUIButton(new RectTransform(new Point(jointButtonElement.Rect.Height, jointButtonElement.Rect.Height), jointButtonElement.RectTransform), "-") + var jointsList = new GUIListBox(new RectTransform(new Vector2(1, 0.45f), content.RectTransform)); + var removeJointButton = new GUIButton(new RectTransform(new Point(jointButtonElement.Rect.Height, jointButtonElement.Rect.Height), jointButtonElement.RectTransform), style: "GUIMinusButton") { OnClicked = (b, d) => { @@ -624,10 +639,10 @@ namespace Barotrauma.CharacterEditor return true; } }; - var addJointButton = new GUIButton(new RectTransform(new Point(jointButtonElement.Rect.Height, jointButtonElement.Rect.Height), jointButtonElement.RectTransform) + var addJointButton = new GUIButton(new RectTransform(new Point(jointButtonElement.Rect.Height), jointButtonElement.RectTransform) { AbsoluteOffset = new Point(removeJointButton.Rect.Width + 10, 0) - }, "+") + }, style: "GUIPlusButton") { OnClicked = (b, d) => { @@ -713,14 +728,14 @@ namespace Barotrauma.CharacterEditor LimbXElements.Values.Select(xe => xe.Attribute("type")).Where(a => a.Value.ToLowerInvariant() == "head").FirstOrDefault(); if (main == null) { - GUI.AddMessage(GetCharacterEditorTranslation("MissingTorsoOrHead"), Color.Red); + GUI.AddMessage(GetCharacterEditorTranslation("MissingTorsoOrHead"), GUI.Style.Red); return false; } if (IsHumanoid) { if (!IsValid(LimbXElements.Values, true, out string missingType)) { - GUI.AddMessage(GetCharacterEditorTranslation("MissingLimbType").Replace("[limbtype]", missingType.FormatCamelCaseWithSpaces()), Color.Red); + GUI.AddMessage(GetCharacterEditorTranslation("MissingLimbType").Replace("[limbtype]", missingType.FormatCamelCaseWithSpaces()), GUI.Style.Red); return false; } } @@ -810,7 +825,7 @@ namespace Barotrauma.CharacterEditor CanBeFocused = false }; var group = new GUILayoutGroup(new RectTransform(Vector2.One, limbElement.RectTransform)) { AbsoluteSpacing = 2 }; - var label = new GUITextBlock(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), name); + var label = new GUITextBlock(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), name, font: GUI.SubHeadingFont); var idField = new GUIFrame(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), style: null); var nameField = new GUIFrame(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), style: null); var limbTypeField = GUI.CreateEnumField(limbType, elementSize, GetCharacterEditorTranslation("LimbType"), group.RectTransform, font: GUI.Font); @@ -850,7 +865,7 @@ namespace Barotrauma.CharacterEditor CanBeFocused = false }; var group = new GUILayoutGroup(new RectTransform(Vector2.One, jointElement.RectTransform)) { AbsoluteSpacing = 2 }; - var label = new GUITextBlock(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), jointName); + var label = new GUITextBlock(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), jointName, font: GUI.SubHeadingFont); var nameField = new GUIFrame(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), style: null); new GUITextBlock(new RectTransform(new Vector2(0.5f, 1), nameField.RectTransform, Anchor.TopLeft), TextManager.Get("Name")); var nameInput = new GUITextBox(new RectTransform(new Vector2(0.5f, 1), nameField.RectTransform, Anchor.TopRight), jointName) @@ -991,7 +1006,7 @@ namespace Barotrauma.CharacterEditor string limbName = GetField(TextManager.Get("Name")).Parent.GetChild().Text; LimbType limbType = (LimbType)GetField(GetCharacterEditorTranslation("LimbType")).Parent.GetChild().SelectedData; // Reverse, because the elements are created from right to left - var rectInputs = GetField(GetCharacterEditorTranslation("SourceRectangle")).Parent.GetAllChildren().Where(c => c is GUINumberInput).Select(c => c as GUINumberInput).Reverse().ToArray(); + var rectInputs = GetField(GetCharacterEditorTranslation("SourceRectangle")).Parent.GetAllChildren().Reverse().ToArray(); int width = rectInputs[2].IntValue; int height = rectInputs[3].IntValue; var colliderAttributes = new List(); @@ -1042,8 +1057,8 @@ namespace Barotrauma.CharacterEditor int limb1ID = GetField(GetCharacterEditorTranslation("LimbWithIndex").Replace("[index]", "1")).Parent.GetChild().IntValue; int limb2ID = GetField(GetCharacterEditorTranslation("LimbWithIndex").Replace("[index]", "2")).Parent.GetChild().IntValue; // Reverse, because the elements are created from right to left - var anchor1Inputs = GetField(GetCharacterEditorTranslation("LimbWithIndexAnchor").Replace("[index]", "1")).Parent.GetAllChildren().Where(c => c is GUINumberInput).Select(c => c as GUINumberInput).Reverse().ToArray(); - var anchor2Inputs = GetField(GetCharacterEditorTranslation("LimbWithIndexAnchor").Replace("[index]", "2")).Parent.GetAllChildren().Where(c => c is GUINumberInput).Select(c => c as GUINumberInput).Reverse().ToArray(); + var anchor1Inputs = GetField(GetCharacterEditorTranslation("LimbWithIndexAnchor").Replace("[index]", "1")).Parent.GetAllChildren().Reverse().ToArray(); + var anchor2Inputs = GetField(GetCharacterEditorTranslation("LimbWithIndexAnchor").Replace("[index]", "2")).Parent.GetAllChildren().Reverse().ToArray(); JointXElements.Add(new XElement("joint", new XAttribute("name", jointName), new XAttribute("limb1", limb1ID), diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs index 04a379356..8b7d7ac27 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs @@ -17,15 +17,11 @@ namespace Barotrauma private RenderTarget2D renderTargetFinal; private Effect damageEffect; - private Effect postProcessEffect; - private Texture2D damageStencil; private Texture2D distortTexture; - public Effect PostProcessEffect - { - get { return postProcessEffect; } - } + public Effect PostProcessEffect { get; private set; } + public Effect GradientEffect { get; private set; } public GameScreen(GraphicsDevice graphics, ContentManager content) { @@ -41,11 +37,13 @@ namespace Barotrauma #if LINUX || OSX //var blurEffect = content.Load("Effects/blurshader_opengl"); damageEffect = content.Load("Effects/damageshader_opengl"); - postProcessEffect = content.Load("Effects/postprocess_opengl"); + PostProcessEffect = content.Load("Effects/postprocess_opengl"); + GradientEffect = content.Load("Effects/gradientshader_opengl"); #else //var blurEffect = content.Load("Effects/blurshader"); damageEffect = content.Load("Effects/damageshader"); - postProcessEffect = content.Load("Effects/postprocess"); + PostProcessEffect = content.Load("Effects/postprocess"); + GradientEffect = content.Load("Effects/gradientshader"); #endif damageStencil = TextureLoader.FromFile("Content/Map/walldamage.png"); @@ -54,7 +52,7 @@ namespace Barotrauma damageEffect.Parameters["cMultiplier"].SetValue(200.0f); distortTexture = TextureLoader.FromFile("Content/Effects/distortnormals.png"); - postProcessEffect.Parameters["xDistortTexture"].SetValue(distortTexture); + PostProcessEffect.Parameters["xDistortTexture"].SetValue(distortTexture); } private void CreateRenderTargets(GraphicsDevice graphics) @@ -119,7 +117,7 @@ namespace Barotrauma if (Submarine.MainSubs[i] == null) continue; if (Level.Loaded != null && Submarine.MainSubs[i].WorldPosition.Y < Level.MaxEntityDepth) continue; - Color indicatorColor = i == 0 ? Color.LightBlue * 0.5f : Color.Red * 0.5f; + Color indicatorColor = i == 0 ? Color.LightBlue * 0.5f : GUI.Style.Red * 0.5f; GUI.DrawIndicator( spriteBatch, Submarine.MainSubs[i].WorldPosition, cam, Math.Max(Submarine.MainSub.Borders.Width, Submarine.MainSub.Borders.Height), @@ -346,22 +344,22 @@ namespace Barotrauma if (BlurStrength > 0.0f) { postProcessTechnique += "Blur"; - postProcessEffect.Parameters["blurDistance"].SetValue(BlurStrength); + PostProcessEffect.Parameters["blurDistance"].SetValue(BlurStrength); } if (chromaticAberrationStrength != Vector3.Zero) { postProcessTechnique += "ChromaticAberration"; - postProcessEffect.Parameters["chromaticAberrationStrength"].SetValue(chromaticAberrationStrength); + PostProcessEffect.Parameters["chromaticAberrationStrength"].SetValue(chromaticAberrationStrength); } if (DistortStrength > 0.0f) { postProcessTechnique += "Distort"; - postProcessEffect.Parameters["distortScale"].SetValue(Vector2.One * DistortStrength); - postProcessEffect.Parameters["distortUvOffset"].SetValue(WaterRenderer.Instance.WavePos * 0.001f); + PostProcessEffect.Parameters["distortScale"].SetValue(Vector2.One * DistortStrength); + PostProcessEffect.Parameters["distortUvOffset"].SetValue(WaterRenderer.Instance.WavePos * 0.001f); #if LINUX || OSX - postProcessEffect.Parameters["xTexture"].SetValue(distortTexture); + PostProcessEffect.Parameters["xTexture"].SetValue(distortTexture); #else - postProcessEffect.Parameters["xTexture"].SetValue(renderTargetFinal); + PostProcessEffect.Parameters["xTexture"].SetValue(renderTargetFinal); #endif } @@ -371,9 +369,9 @@ namespace Barotrauma } else { - postProcessEffect.CurrentTechnique = postProcessEffect.Techniques[postProcessTechnique]; - postProcessEffect.CurrentTechnique.Passes[0].Apply(); - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.None, effect: postProcessEffect); + PostProcessEffect.CurrentTechnique = PostProcessEffect.Techniques[postProcessTechnique]; + PostProcessEffect.CurrentTechnique.Passes[0].Apply(); + spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.None, effect: PostProcessEffect); } #if LINUX || OSX spriteBatch.Draw(renderTargetFinal, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/LevelEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/LevelEditorScreen.cs index 9a87a4eaf..8f1d91a21 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/LevelEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/LevelEditorScreen.cs @@ -44,8 +44,7 @@ namespace Barotrauma MaxZoom = 1.0f }; - leftPanel = new GUIFrame(new RectTransform(new Vector2(0.125f, 0.8f), Frame.RectTransform) { MinSize = new Point(150, 0) }, - style: "GUIFrameLeft"); + leftPanel = new GUIFrame(new RectTransform(new Vector2(0.125f, 0.8f), Frame.RectTransform) { MinSize = new Point(150, 0) }); var paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), leftPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.02f, 0.0f) }) { Stretch = true, @@ -107,8 +106,7 @@ namespace Barotrauma } }; - rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), Frame.RectTransform, Anchor.TopRight) { MinSize = new Point(450, 0) }, - style: "GUIFrameRight"); + rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), Frame.RectTransform, Anchor.TopRight) { MinSize = new Point(450, 0) }); var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.02f, 0.0f) }) { Stretch = true, @@ -133,14 +131,14 @@ namespace Barotrauma cam.Position = new Vector2(Level.Loaded.Size.X / 2, Level.Loaded.Size.Y / 2); foreach (GUITextBlock param in paramsList.Content.Children) { - param.TextColor = param.UserData == selectedParams ? Color.LightGreen : param.Style.textColor; + param.TextColor = param.UserData == selectedParams ? GUI.Style.Green : param.Style.TextColor; } seedBox.Deselect(); return true; } }; - bottomPanel = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.2f), Frame.RectTransform, Anchor.BottomLeft) + bottomPanel = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.22f), Frame.RectTransform, Anchor.BottomLeft) { MaxSize = new Point(GameMain.GraphicsWidth - rightPanel.Rect.Width, 1000) }, style: "GUIFrameBottom"); levelObjectList = new GUIListBox(new RectTransform(new Vector2(0.99f, 0.85f), bottomPanel.RectTransform, Anchor.Center)) @@ -235,14 +233,14 @@ namespace Barotrauma editorContainer.ClearChildren(); levelObjectList.Content.ClearChildren(); - int objectsPerRow = (int)Math.Ceiling(levelObjectList.Content.Rect.Width / Math.Max(150 * GUI.Scale, 100)); + int objectsPerRow = (int)Math.Ceiling(levelObjectList.Content.Rect.Width / Math.Max(100 * GUI.Scale, 100)); float relWidth = 1.0f / objectsPerRow; foreach (LevelObjectPrefab levelObjPrefab in LevelObjectPrefab.List) { var frame = new GUIFrame(new RectTransform( new Vector2(relWidth, relWidth * ((float)levelObjectList.Content.Rect.Width / levelObjectList.Content.Rect.Height)), - levelObjectList.Content.RectTransform) { MinSize = new Point(0, 60) }, style: "GUITextBox") + levelObjectList.Content.RectTransform) { MinSize = new Point(0, 60) }, style: "ListBoxElementSquare") { UserData = levelObjPrefab }; @@ -267,7 +265,7 @@ namespace Barotrauma { editorContainer.ClearChildren(); - var editor = new SerializableEntityEditor(editorContainer.Content.RectTransform, levelObjectPrefab, false, true, elementHeight: 20); + var editor = new SerializableEntityEditor(editorContainer.Content.RectTransform, levelObjectPrefab, false, true, elementHeight: 20, titleFont: GUI.LargeFont); if (selectedParams != null) { @@ -319,7 +317,7 @@ namespace Barotrauma } //child object editing new GUITextBlock(new RectTransform(new Point(editor.Rect.Width, 40), editorContainer.Content.RectTransform), - TextManager.Get("leveleditor.childobjects"), textAlignment: Alignment.BottomCenter); + TextManager.Get("leveleditor.childobjects"), font: GUI.SubHeadingFont, textAlignment: Alignment.BottomCenter); foreach (LevelObjectPrefab.ChildObject childObj in levelObjectPrefab.ChildObjects) { var childObjFrame = new GUIFrame(new RectTransform(new Point(editor.Rect.Width, 30))); @@ -361,7 +359,7 @@ namespace Barotrauma } }.IntValue = childObj.MaxCount; - new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), paddedFrame.RectTransform), "X") + new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), paddedFrame.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUICancelButton") { OnClicked = (btn, userdata) => { @@ -374,7 +372,8 @@ namespace Barotrauma childObjFrame.RectTransform.Parent = editorContainer.Content.RectTransform; } - new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20), editorContainer.Content.RectTransform), + var buttonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), editorContainer.Content.RectTransform), style: null); + new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20), buttonContainer.RectTransform, Anchor.Center), TextManager.Get("leveleditor.addchildobject")) { OnClicked = (btn, userdata) => @@ -384,15 +383,17 @@ namespace Barotrauma return true; } }; + buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.Children.First().MinSize; //light editing new GUITextBlock(new RectTransform(new Point(editor.Rect.Width, 40), editorContainer.Content.RectTransform), - TextManager.Get("leveleditor.lightsources"), textAlignment: Alignment.BottomCenter); + TextManager.Get("leveleditor.lightsources"), textAlignment: Alignment.BottomCenter, font: GUI.SubHeadingFont); foreach (LightSourceParams lightSourceParams in selectedLevelObject.LightSourceParams) { new SerializableEntityEditor(editorContainer.Content.RectTransform, lightSourceParams, inGame: false, showName: true); } - new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20), editorContainer.Content.RectTransform), + buttonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), editorContainer.Content.RectTransform), style: null); + new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20), buttonContainer.RectTransform, Anchor.Center), TextManager.Get("leveleditor.addlightsource")) { OnClicked = (btn, userdata) => @@ -403,6 +404,7 @@ namespace Barotrauma return true; } }; + buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.Children.First().MinSize; } private void SortLevelObjectsList(LevelGenerationParams selectedParams) @@ -411,9 +413,16 @@ namespace Barotrauma foreach (GUIComponent levelObjFrame in levelObjectList.Content.Children) { var levelObj = levelObjFrame.UserData as LevelObjectPrefab; - Color color = levelObj.GetCommonness(selectedParams.Name) > 0.0f ? Color.White : Color.White * 0.3f; - levelObjFrame.Color = color; - levelObjFrame.GetAnyChild().Color = color; + float commonness = levelObj.GetCommonness(selectedParams.Name); + levelObjFrame.Color = commonness > 0.0f ? GUI.Style.Green * 0.4f : Color.Transparent; + levelObjFrame.SelectedColor = commonness > 0.0f ? GUI.Style.Green * 0.6f : Color.White * 0.5f; + levelObjFrame.HoverColor = commonness > 0.0f ? GUI.Style.Green * 0.7f : Color.White * 0.6f; + + levelObjFrame.GetAnyChild().Color = commonness > 0.0f ? Color.White : Color.DarkGray; + if (commonness <= 0.0f) + { + levelObjFrame.GetAnyChild().TextColor = Color.DarkGray; + } } //sort the levelobjects according to commonness in this level @@ -639,22 +648,22 @@ namespace Barotrauma { if (string.IsNullOrEmpty(nameBox.Text)) { - nameBox.Flash(Color.Red); - GUI.AddMessage(TextManager.Get("leveleditor.levelobjnameempty"), Color.Red); + nameBox.Flash(GUI.Style.Red); + GUI.AddMessage(TextManager.Get("leveleditor.levelobjnameempty"), GUI.Style.Red); return false; } if (LevelObjectPrefab.List.Any(obj => obj.Name.ToLower() == nameBox.Text.ToLower())) { - nameBox.Flash(Color.Red); - GUI.AddMessage(TextManager.Get("leveleditor.levelobjnametaken"), Color.Red); + nameBox.Flash(GUI.Style.Red); + GUI.AddMessage(TextManager.Get("leveleditor.levelobjnametaken"), GUI.Style.Red); return false; } if (!File.Exists(texturePathBox.Text)) { - texturePathBox.Flash(Color.Red); - GUI.AddMessage(TextManager.Get("leveleditor.levelobjtexturenotfound"), Color.Red); + texturePathBox.Flash(GUI.Style.Red); + GUI.AddMessage(TextManager.Get("leveleditor.levelobjtexturenotfound"), GUI.Style.Red); return false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs index c8b822797..267908311 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs @@ -26,7 +26,7 @@ namespace Barotrauma private readonly GUIFrame[] menuTabs; - private readonly CampaignSetupUI campaignSetupUI; + private CampaignSetupUI campaignSetupUI; private GUITextBox serverNameBox, /*portBox, queryPortBox,*/ passwordBox, maxPlayersBox; private GUITickBox isPublicBox, wrongPasswordBanBox, karmaEnabledBox; @@ -46,13 +46,24 @@ namespace Barotrauma private readonly CreditsPlayer creditsPlayer; - #if OSX +#if OSX private bool firstLoadOnMac = true; - #endif +#endif - #region Creation +#region Creation public MainMenuScreen(GameMain game) { + GameMain.Instance.OnResolutionChanged += () => + { + if (Selected == this && selectedTab == Tab.Settings) + { + GameMain.Config.ResetSettingsFrame(); + SelectTab(Tab.Settings); + } + CreateHostServerFields(); + CreateCampaignSetupUI(); + }; + backgroundVignette = new Sprite("Content/UI/MainMenuVignette.png", Vector2.Zero); new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight) @@ -89,6 +100,8 @@ namespace Barotrauma FetchRemoteContent(); #endif + float labelHeight = 0.18f; + // === CAMPAIGN var campaignHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 1.0f), parent: buttonsParent.RectTransform) { RelativeOffset = new Vector2(0.1f, 0.0f) }, isHorizontal: true); @@ -103,7 +116,7 @@ namespace Barotrauma var campaignNavigation = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.75f), parent: campaignHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.25f) }); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), campaignNavigation.RectTransform), + new GUITextBlock(new RectTransform(new Vector2(1.0f, labelHeight), campaignNavigation.RectTransform), TextManager.Get("CampaignLabel"), textAlignment: Alignment.Left, font: GUI.LargeFont, textColor: Color.Black, style: "MainMenuGUITextBlock") { ForceUpperCase = true }; var campaignButtons = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), parent: campaignNavigation.RectTransform), style: "MainMenuGUIFrame"); @@ -160,7 +173,7 @@ namespace Barotrauma var multiplayerNavigation = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.75f), parent: multiplayerHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.25f) }); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), multiplayerNavigation.RectTransform), + new GUITextBlock(new RectTransform(new Vector2(1.0f, labelHeight), multiplayerNavigation.RectTransform), TextManager.Get("MultiplayerLabel"), textAlignment: Alignment.Left, font: GUI.LargeFont, textColor: Color.Black, style: "MainMenuGUITextBlock") { ForceUpperCase = true }; var multiplayerButtons = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), parent: multiplayerNavigation.RectTransform), style: "MainMenuGUIFrame"); @@ -205,7 +218,7 @@ namespace Barotrauma var customizeNavigation = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.75f), parent: customizeHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.25f) }); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), customizeNavigation.RectTransform), + new GUITextBlock(new RectTransform(new Vector2(1.0f, labelHeight), customizeNavigation.RectTransform), TextManager.Get("CustomizeLabel"), textAlignment: Alignment.Left, font: GUI.LargeFont, textColor: Color.Black, style: "MainMenuGUITextBlock") { ForceUpperCase = true }; var customizeButtons = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), parent: customizeNavigation.RectTransform), style: "MainMenuGUIFrame"); @@ -289,7 +302,7 @@ namespace Barotrauma //debug button for quickly starting a new round #if DEBUG new GUIButton(new RectTransform(new Point(300, 30), Frame.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(40, 80) }, - "Quickstart (dev)", style: "GUIButtonLarge", color: Color.Red) + "Quickstart (dev)", style: "GUIButtonLarge", color: GUI.Style.Red) { IgnoreLayoutGroups = true, UserData = Tab.QuickStartDev, @@ -300,7 +313,7 @@ namespace Barotrauma } }; new GUIButton(new RectTransform(new Point(300, 30), Frame.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(40, 130) }, - "Profiling", style: "GUIButtonLarge", color: Color.Red) + "Profiling", style: "GUIButtonLarge", color: GUI.Style.Red) { IgnoreLayoutGroups = true, UserData = Tab.ProfilingTestBench, @@ -328,19 +341,14 @@ namespace Barotrauma style: null); menuTabs[(int)Tab.NewGame] = new GUIFrame(new RectTransform(relativeSize, GUI.Canvas, anchor, pivot, minSize, maxSize) { RelativeOffset = relativeSpacing }); - var paddedNewGame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.NewGame].RectTransform, Anchor.Center), style: null); menuTabs[(int)Tab.LoadGame] = new GUIFrame(new RectTransform(relativeSize, GUI.Canvas, anchor, pivot, minSize, maxSize) { RelativeOffset = relativeSpacing }); - var paddedLoadGame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.LoadGame].RectTransform, Anchor.Center), style: null); - - campaignSetupUI = new CampaignSetupUI(false, paddedNewGame, paddedLoadGame, Submarine.SavedSubmarines) - { - LoadGame = LoadGame, - StartNewGame = StartGame - }; + + CreateCampaignSetupUI(); var hostServerScale = new Vector2(0.7f, 1.2f); menuTabs[(int)Tab.HostServer] = new GUIFrame(new RectTransform( - Vector2.Multiply(relativeSize, hostServerScale), GUI.Canvas, anchor, pivot, minSize.Multiply(hostServerScale), maxSize.Multiply(hostServerScale)) { RelativeOffset = relativeSpacing }); + Vector2.Multiply(relativeSize, hostServerScale), GUI.Canvas, anchor, pivot, minSize.Multiply(hostServerScale), maxSize.Multiply(hostServerScale)) + { RelativeOffset = relativeSpacing }); CreateHostServerFields(); @@ -350,8 +358,7 @@ namespace Barotrauma //PLACEHOLDER var tutorialList = new GUIListBox( - new RectTransform(new Vector2(0.95f, 0.85f), menuTabs[(int)Tab.Tutorials].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) }, - false, null, ""); + new RectTransform(new Vector2(0.95f, 0.85f), menuTabs[(int)Tab.Tutorials].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) }); foreach (Tutorial tutorial in Tutorial.Tutorials) { var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), tutorialList.Content.RectTransform), tutorial.DisplayName, textAlignment: Alignment.Center, font: GUI.LargeFont) @@ -383,7 +390,7 @@ namespace Barotrauma } #endregion -#region Selection + #region Selection public override void Select() { base.Select(); @@ -520,7 +527,6 @@ namespace Barotrauma selectedTab = 0; return false; } - SetServerPlayStyle(PlayStyle.Serious); if (GameMain.Config.ShowTutorialSkipWarning) { selectedTab = 0; @@ -617,7 +623,7 @@ namespace Barotrauma } #endregion - private void QuickStart(bool fixedSeed = false) + public void QuickStart(bool fixedSeed = false) { if (fixedSeed) { @@ -717,7 +723,7 @@ namespace Barotrauma { if (i < completedTutorials + 1) { - (tutorialList.Content.GetChild(i) as GUITextBlock).TextColor = Color.LightGreen; + (tutorialList.Content.GetChild(i) as GUITextBlock).TextColor = GUI.Style.Green; #if !DEBUG (tutorialList.Content.GetChild(i) as GUITextBlock).CanBeFocused = true; #endif @@ -1048,12 +1054,46 @@ namespace Barotrauma GameMain.LobbyScreen.Select(); } -#region UI Methods + #region UI Methods + private void CreateCampaignSetupUI() + { + menuTabs[(int)Tab.NewGame].ClearChildren(); + menuTabs[(int)Tab.LoadGame].ClearChildren(); + + var innerNewGame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.NewGame].RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.025f) }) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + var newGameContent = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.95f), innerNewGame.RectTransform, Anchor.Center), + style: "InnerFrame"); + + var paddedNewGame = new GUIFrame(new RectTransform(new Vector2(0.95f), newGameContent.RectTransform, Anchor.Center), style: null); + var paddedLoadGame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.LoadGame].RectTransform, Anchor.Center) { AbsoluteOffset = new Point(0, 10) }, + style: null); + + campaignSetupUI = new CampaignSetupUI(false, paddedNewGame, paddedLoadGame, Submarine.SavedSubmarines) + { + LoadGame = LoadGame, + StartNewGame = StartGame + }; + + var startButtonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), innerNewGame.RectTransform, Anchor.Center), style: null); + campaignSetupUI.StartButton.RectTransform.Parent = startButtonContainer.RectTransform; + campaignSetupUI.StartButton.RectTransform.MinSize = new Point( + (int)(campaignSetupUI.StartButton.TextBlock.TextSize.X * 1.5f), + campaignSetupUI.StartButton.RectTransform.MinSize.Y); + startButtonContainer.RectTransform.MinSize = new Point(0, campaignSetupUI.StartButton.RectTransform.MinSize.Y); + } + private void CreateHostServerFields() { + menuTabs[(int)Tab.HostServer].ClearChildren(); + int port = NetConfig.DefaultPort; int queryPort = NetConfig.DefaultQueryPort; int maxPlayers = 8; + PlayStyle selectedPlayStyle = PlayStyle.Casual; if (File.Exists(ServerSettings.SettingsFile)) { XDocument settingsDoc = XMLExtensions.TryLoadXml(ServerSettings.SettingsFile); @@ -1062,6 +1102,8 @@ namespace Barotrauma port = settingsDoc.Root.GetAttributeInt("port", port); queryPort = settingsDoc.Root.GetAttributeInt("queryport", queryPort); maxPlayers = settingsDoc.Root.GetAttributeInt("maxplayers", maxPlayers); + string playStyleStr = settingsDoc.Root.GetAttributeString("playstyle", "Casual"); + Enum.TryParse(playStyleStr, out selectedPlayStyle); } } @@ -1069,25 +1111,35 @@ namespace Barotrauma Alignment textAlignment = Alignment.CenterLeft; Vector2 textFieldSize = new Vector2(0.5f, 1.0f); Vector2 tickBoxSize = new Vector2(0.4f, 0.07f); - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.85f, 0.8f), menuTabs[(int)Tab.HostServer].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) }) + var content = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 0.9f), menuTabs[(int)Tab.HostServer].RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) { RelativeSpacing = 0.02f, Stretch = true - }; - GUIComponent parent = paddedFrame; + }; + GUIComponent parent = content; new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("HostServerButton"), textAlignment: Alignment.Center, font: GUI.LargeFont) { ForceUpperCase = true }; //play style ----------------------------------------------------- - var playstyleContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), parent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) + var playstyleContainer = new GUIFrame(new RectTransform(new Vector2(1.5f, 0.1f), parent.RectTransform), style: null, color: Color.Black); + + playstyleBanner = new GUIImage(new RectTransform(new Vector2(1.0f, 0.1f), playstyleContainer.RectTransform), + ServerListScreen.PlayStyleBanners[0], scaleToFit: true) { - Stretch = true, - Color = Color.Black - //RelativeSpacing = 0.02f + UserData = PlayStyle.Serious }; + float bannerAspectRatio = (float) playstyleBanner.Sprite.SourceRect.Width / playstyleBanner.Sprite.SourceRect.Height; + playstyleBanner.RectTransform.NonScaledSize = new Point(playstyleBanner.Rect.Width, (int)(playstyleBanner.Rect.Width / bannerAspectRatio)); + playstyleBanner.RectTransform.IsFixedSize = true; + new GUIFrame(new RectTransform(Vector2.One, playstyleBanner.RectTransform), "InnerGlow", color: Color.Black); + + new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.05f), playstyleBanner.RectTransform) { RelativeOffset = new Vector2(0.01f, 0.03f) }, + "playstyle name goes here", font: GUI.SmallFont, textAlignment: Alignment.Center, textColor: Color.White, style: "GUISlopedHeader"); - new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), playstyleContainer.RectTransform), style: "UIToggleButton") + new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), playstyleContainer.RectTransform, Anchor.CenterLeft) + { RelativeOffset = new Vector2(0.02f, 0.0f), MaxSize = new Point(int.MaxValue, (int)(150 * GUI.Scale)) }, + style: "UIToggleButton") { OnClicked = (btn, userdata) => { @@ -1098,14 +1150,9 @@ namespace Barotrauma } }.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipHorizontally); - playstyleBanner = new GUIImage(new RectTransform(new Vector2(0.8f, 1.0f), playstyleContainer.RectTransform), style: null, scaleToFit: true) - { - UserData = PlayStyle.Serious - }; - new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.05f), playstyleBanner.RectTransform) { RelativeOffset = new Vector2(0.01f, 0.06f) }, - "playstyle name goes here", font: GUI.SmallFont, textAlignment: Alignment.Center, textColor: Color.White, style: "GUISlopedHeader"); - - new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), playstyleContainer.RectTransform), style: "UIToggleButton") + new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), playstyleContainer.RectTransform, Anchor.CenterRight) + { RelativeOffset = new Vector2(0.02f, 0.0f), MaxSize = new Point(int.MaxValue, (int)(150 * GUI.Scale)) }, + style: "UIToggleButton") { OnClicked = (btn, userdata) => { @@ -1123,24 +1170,33 @@ namespace Barotrauma if (playStyleStr.Length > longestPlayStyleStr.Length) { longestPlayStyleStr = playStyleStr; } } - playstyleDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), playstyleBanner.RectTransform, Anchor.BottomCenter), - "playstyle description goes here", style: null, wrap: true) + playstyleDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), playstyleContainer.RectTransform, Anchor.BottomCenter), + longestPlayStyleStr, style: null, wrap: true) { Color = Color.Black * 0.8f, - TextColor = Color.White + TextColor = GUI.Style.GetComponentStyle("GUITextBlock").TextColor }; playstyleDescription.Padding = Vector4.One * 10.0f * GUI.Scale; playstyleDescription.CalculateHeightFromText(padding: (int)(15 * GUI.Scale)); - playstyleDescription.RectTransform.MinSize = new Point(0, playstyleDescription.Rect.Height); + playstyleDescription.RectTransform.NonScaledSize = new Point(playstyleDescription.Rect.Width, playstyleDescription.Rect.Height); + playstyleDescription.RectTransform.IsFixedSize = true; + playstyleContainer.RectTransform.NonScaledSize = new Point(playstyleContainer.Rect.Width, playstyleBanner.Rect.Height + playstyleDescription.Rect.Height); + playstyleContainer.RectTransform.IsFixedSize = true; + + SetServerPlayStyle(selectedPlayStyle); //other settings ----------------------------------------------------- + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null); + var label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerName"), textAlignment: textAlignment); serverNameBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment) { MaxTextLength = NetConfig.ServerNameMaxLength, OverflowClip = true }; + label.RectTransform.MaxSize = serverNameBox.RectTransform.MaxSize; /* TODO: allow lidgren servers from client? label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerPort"), textAlignment: textAlignment); @@ -1166,29 +1222,29 @@ namespace Barotrauma Stretch = true, RelativeSpacing = 0.1f }; - new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform), "-", textAlignment: Alignment.Center) + new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton", textAlignment: Alignment.Center) { UserData = -1, OnClicked = ChangeMaxPlayers }; - maxPlayersBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 1.0f), buttonContainer.RectTransform), textAlignment: Alignment.Center) { Text = maxPlayers.ToString(), - // ? - // Enabled = false + CanBeFocused = false }; - new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform), "+", textAlignment: Alignment.Center) + new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center) { UserData = 1, OnClicked = ChangeMaxPlayers }; - + maxPlayersLabel.RectTransform.MaxSize = maxPlayersBox.RectTransform.MaxSize; + label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("Password"), textAlignment: textAlignment); passwordBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment) { Censor = true }; + label.RectTransform.MaxSize = passwordBox.RectTransform.MaxSize; // tickbox upper --------------- @@ -1201,6 +1257,8 @@ namespace Barotrauma wrongPasswordBanBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaUpper.RectTransform), TextManager.Get("ServerSettingsBanAfterWrongPassword")); + tickboxAreaUpper.RectTransform.MaxSize = isPublicBox.RectTransform.MaxSize; + // tickbox lower --------------- var tickboxAreaLower = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, tickBoxSize.Y), parent.RectTransform), isHorizontal: true); @@ -1227,30 +1285,32 @@ namespace Barotrauma } if (karmaPresetDD.SelectedIndex == -1) { karmaPresetDD.Select(0); } - new GUIButton(new RectTransform(new Vector2(0.4f, 0.1f), menuTabs[(int)Tab.HostServer].RectTransform, Anchor.BottomRight) + tickboxAreaLower.RectTransform.MaxSize = karmaEnabledBox.RectTransform.MaxSize; + + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null); + + new GUIButton(new RectTransform(new Vector2(0.4f, 0.07f), content.RectTransform), TextManager.Get("StartServerButton"), style: "GUIButtonLarge") { - RelativeOffset = new Vector2(0.05f, 0.05f) - }, TextManager.Get("StartServerButton"), style: "GUIButtonLarge") - { - IgnoreLayoutGroups = true, OnClicked = HostServerClicked }; } private void SetServerPlayStyle(PlayStyle playStyle) { - playstyleBanner.Sprite = GameMain.ServerListScreen.PlayStyleBanners[(int)playStyle]; + playstyleBanner.Sprite = ServerListScreen.PlayStyleBanners[(int)playStyle]; playstyleBanner.UserData = playStyle; var nameText = playstyleBanner.GetChild(); nameText.Text = TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag." + playStyle)); - nameText.Color = GameMain.ServerListScreen.PlayStyleColors[(int)playStyle]; + nameText.Color = ServerListScreen.PlayStyleColors[(int)playStyle]; nameText.RectTransform.NonScaledSize = (nameText.Font.MeasureString(nameText.Text) + new Vector2(25, 10) * GUI.Scale).ToPoint(); playstyleDescription.Text = TextManager.Get("servertagdescription." + playStyle); - playstyleDescription.CalculateHeightFromText(padding: (int)(15 * GUI.Scale)); + playstyleDescription.TextAlignment = playstyleDescription.WrappedText.Contains('\n') ? + Alignment.CenterLeft : Alignment.Center; } -#endregion + #endregion private void FetchRemoteContent() { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs index 01ea45052..890df0f63 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs @@ -13,9 +13,10 @@ namespace Barotrauma partial class NetLobbyScreen : Screen { private readonly List characterSprites = new List(); - private readonly List jobPreferenceSprites = new List(); + //private readonly List jobPreferenceSprites = new List(); private GUIFrame infoFrame, modeFrame; + private GUILayoutGroup infoFrameContent; private GUIFrame myCharacterFrame; private GUIListBox subList, modeList; @@ -120,7 +121,7 @@ namespace Barotrauma (GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.SelectSub)); } } - + public GUITextBox ServerName { get; @@ -334,25 +335,25 @@ namespace Barotrauma RelativeSpacing = panelSpacing }; - GUILayoutGroup bottomBar = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), innerFrame.RectTransform)) + GUILayoutGroup bottomBar = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), innerFrame.RectTransform), childAnchor: Anchor.CenterLeft) { Stretch = true, IsHorizontal = true, RelativeSpacing = panelSpacing }; - GUILayoutGroup bottomBarLeft = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1.0f), bottomBar.RectTransform)) + GUILayoutGroup bottomBarLeft = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1.0f), bottomBar.RectTransform), childAnchor: Anchor.CenterLeft) { Stretch = true, IsHorizontal = true, RelativeSpacing = panelSpacing }; - GUILayoutGroup bottomBarMid = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), bottomBar.RectTransform)) + GUILayoutGroup bottomBarMid = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), bottomBar.RectTransform), childAnchor: Anchor.CenterLeft) { Stretch = true, IsHorizontal = true, RelativeSpacing = panelSpacing }; - GUILayoutGroup bottomBarRight = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1.0f), bottomBar.RectTransform)) + GUILayoutGroup bottomBarRight = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1.0f), bottomBar.RectTransform), childAnchor: Anchor.CenterLeft) { Stretch = true, IsHorizontal = true, @@ -362,7 +363,7 @@ namespace Barotrauma //server info panel ------------------------------------------------------------ infoFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), panelHolder.RectTransform)); - var infoFrameContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), infoFrame.RectTransform, Anchor.Center)) + infoFrameContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), infoFrame.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.025f @@ -383,7 +384,7 @@ namespace Barotrauma campaignViewButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.4f), gameModeTabButtonContainer.RectTransform), TextManager.Get("CampaignLabel"), style: "GUITabButton") { - Visible = false, + Enabled = false, OnClicked = (bt, userData) => { ToggleCampaignView(true); return true; } }; @@ -396,7 +397,7 @@ namespace Barotrauma gameModeContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), modeFrame.RectTransform, Anchor.Center)) { - RelativeSpacing = panelSpacing * 2.0f, + RelativeSpacing = panelSpacing * 4.0f, Stretch = true }; @@ -405,7 +406,7 @@ namespace Barotrauma Visible = false }; - new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), bottomBarLeft.RectTransform), TextManager.Get("disconnect"), style: "GUIButtonLarge") + new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), bottomBarLeft.RectTransform), TextManager.Get("disconnect")) { OnClicked = (bt, userdata) => { GameMain.QuitToMainMenu(save: false, showVerificationPrompt: true); return true; } }; @@ -440,6 +441,7 @@ namespace Barotrauma GUILayoutGroup sideBar = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1.0f), panelContainer.RectTransform, maxSize: new Point(650, panelContainer.RectTransform.Rect.Height))) { + RelativeSpacing = panelSpacing, Stretch = true }; @@ -456,7 +458,7 @@ namespace Barotrauma myCharacterFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), sideBar.RectTransform)); playerInfoContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), myCharacterFrame.RectTransform, Anchor.Center), style: null); - spectateBox = new GUITickBox(new RectTransform(new Vector2(0.06f, 0.06f), myCharacterFrame.RectTransform) { RelativeOffset = new Vector2(0.05f,0.05f) }, + spectateBox = new GUITickBox(new RectTransform(new Vector2(0.06f, 0.06f), myCharacterFrame.RectTransform) { RelativeOffset = new Vector2(0.05f, 0.05f) }, TextManager.Get("spectatebutton")) { Selected = false, @@ -464,6 +466,9 @@ namespace Barotrauma UserData = "spectate" }; + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, gameModeTabButtonContainer.RectTransform.RelativeSize.Y), sideBar.RectTransform), style: null); + // Social area GUIFrame logBackground = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), sideBar.RectTransform)); @@ -645,6 +650,9 @@ namespace Barotrauma }; clientHiddenElements.Add(StartButton); + bottomBar.RectTransform.MinSize = + new Point(0, (int)Math.Max(ReadyToStartBox.RectTransform.MinSize.Y / 0.75f, StartButton.RectTransform.MinSize.Y)); + //autorestart ------------------------------------------------------------------ autoRestartText = new GUITextBlock(new RectTransform(Vector2.One, bottomBarMid.RectTransform), "", font: GUI.SmallFont, style: "TextFrame", textAlignment: Alignment.Center); @@ -666,8 +674,10 @@ namespace Barotrauma //server info ------------------------------------------------------------------ // Server Info Header - GUILayoutGroup lobbyHeader = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), infoFrameContent.RectTransform), isHorizontal: true) + GUILayoutGroup lobbyHeader = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), infoFrameContent.RectTransform), + isHorizontal: true, childAnchor: Anchor.CenterLeft) { + RelativeSpacing = 0.05f, Stretch = true }; @@ -683,10 +693,12 @@ namespace Barotrauma clientDisabledElements.Add(ServerName); SettingsButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), lobbyHeader.RectTransform, Anchor.TopRight), - TextManager.Get("ServerSettingsButton"), style: "GUIButtonLarge"); + TextManager.Get("ServerSettingsButton")); clientHiddenElements.Add(SettingsButton); - GUILayoutGroup lobbyContent = new GUILayoutGroup(new RectTransform(Vector2.One, infoFrameContent.RectTransform), isHorizontal: true) + lobbyHeader.RectTransform.MinSize = new Point(0, Math.Max(ServerName.Rect.Height, SettingsButton.Rect.Height)); + + GUILayoutGroup lobbyContent = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), infoFrameContent.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.025f @@ -709,14 +721,14 @@ namespace Barotrauma }; var serverMessageContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), serverInfoHolder.RectTransform)); - ServerMessage = new GUITextBox(new RectTransform(Vector2.One, serverMessageContainer.Content.RectTransform)) + ServerMessage = new GUITextBox(new RectTransform(Vector2.One, serverMessageContainer.Content.RectTransform), style: "GUITextBoxNoBorder") { Wrap = true }; ServerMessage.OnTextChanged += (textBox, text) => { Vector2 textSize = textBox.Font.MeasureString(textBox.WrappedText); - textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(serverMessageContainer.Rect.Height, (int)textSize.Y + 10)); + textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(serverMessageContainer.Content.Rect.Height, (int)textSize.Y + 10)); serverMessageContainer.UpdateScrollBarSize(); serverMessageContainer.BarScroll = 1.0f; return true; @@ -735,7 +747,7 @@ namespace Barotrauma Stretch = true }; - var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("Submarine")); + var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("Submarine"), font: GUI.SubHeadingFont); subList = new GUIListBox(new RectTransform(Vector2.One, subHolder.RectTransform)) { OnSelected = VotableClicked @@ -756,7 +768,7 @@ namespace Barotrauma Stretch = true }; - GUILayoutGroup shuttleHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform) { MinSize = new Point(0, 25) }, isHorizontal: true) + GUILayoutGroup shuttleHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), isHorizontal: true) { Stretch = true }; @@ -790,26 +802,26 @@ namespace Barotrauma } }; shuttleList.ListBox.RectTransform.MinSize = new Point(250, 0); + shuttleHolder.RectTransform.MinSize = new Point(0, shuttleList.RectTransform.Children.Max(c => c.MinSize.Y)); subPreviewContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.9f), rightColumn.RectTransform), style: null); subPreviewContainer.RectTransform.SizeChanged += () => { - if (SelectedSub != null) - { - subPreviewContainer.ClearChildren(); - SelectedSub.CreatePreviewWindow(subPreviewContainer); - } + if (SelectedSub != null) { CreateSubPreview(SelectedSub); } }; //------------------------------------------------------------------------------------------------------------------ // Gamemode panel //------------------------------------------------------------------------------------------------------------------ - GUILayoutGroup miscSettingsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.075f), gameModeContainer.RectTransform), isHorizontal: true) + GUILayoutGroup miscSettingsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), gameModeContainer.RectTransform), + isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true, RelativeSpacing = 0.01f }; + + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), gameModeContainer.RectTransform), style: "HorizontalLine"); miscSettingsHolder.RectTransform.SizeChanged += () => { @@ -833,7 +845,7 @@ namespace Barotrauma //seed ------------------------------------------------------------------ - var seedLabel = new GUITextBlock(new RectTransform(Vector2.One, miscSettingsHolder.RectTransform), TextManager.Get("LevelSeed")); + var seedLabel = new GUITextBlock(new RectTransform(Vector2.One, miscSettingsHolder.RectTransform), TextManager.Get("LevelSeed"), font: GUI.SubHeadingFont); seedLabel.RectTransform.MaxSize = new Point((int)(seedLabel.TextSize.X + 30 * GUI.Scale), int.MaxValue); SeedBox = new GUITextBox(new RectTransform(new Vector2(0.25f, 1.0f), miscSettingsHolder.RectTransform)); SeedBox.OnDeselected += (textBox, key) => @@ -845,11 +857,11 @@ namespace Barotrauma //level difficulty ------------------------------------------------------------------ - var difficultyLabel = new GUITextBlock(new RectTransform(Vector2.One, miscSettingsHolder.RectTransform), TextManager.Get("LevelDifficulty")) + var difficultyLabel = new GUITextBlock(new RectTransform(Vector2.One, miscSettingsHolder.RectTransform), TextManager.Get("LevelDifficulty"), font: GUI.SubHeadingFont) { ToolTip = TextManager.Get("leveldifficultyexplanation") }; - levelDifficultyScrollBar = new GUIScrollBar(new RectTransform(new Vector2(0.25f, 1.0f), miscSettingsHolder.RectTransform), barSize: 0.2f) + levelDifficultyScrollBar = new GUIScrollBar(new RectTransform(new Vector2(0.25f, 1.0f), miscSettingsHolder.RectTransform), style: "GUISlider", barSize: 0.2f) { Step = 0.05f, Range = new Vector2(0.0f, 100.0f), @@ -869,7 +881,7 @@ namespace Barotrauma { if (EventManagerSettings.List.Count == 0) { return true; } difficultyName.Text = EventManagerSettings.List[Math.Min((int)Math.Floor(value * EventManagerSettings.List.Count), EventManagerSettings.List.Count - 1)].Name; - difficultyName.TextColor = Color.Lerp(ToolBox.GradientLerp(scrollbar.BarScroll, Color.LightGreen, Color.Orange, Color.Red), difficultyLabel.TextColor, 0.5f); + difficultyName.TextColor = ToolBox.GradientLerp(scrollbar.BarScroll, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red); return true; }; @@ -888,7 +900,7 @@ namespace Barotrauma Stretch = true }; - var modeLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), gameModeHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("GameMode")); + var modeLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), gameModeHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("GameMode"), font: GUI.SubHeadingFont); voteText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), modeLabel.RectTransform, Anchor.TopRight), TextManager.Get("Votes"), textAlignment: Alignment.CenterRight) { @@ -904,12 +916,31 @@ namespace Barotrauma { if (mode.IsSinglePlayer) { continue; } - GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), modeList.Content.RectTransform) { MinSize = new Point(0, (int)(30 * GUI.Scale)) }, - mode.Name, style: "ListBoxElement", textAlignment: Alignment.CenterLeft) + var modeFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.15f), modeList.Content.RectTransform), style: null) { - UserData = mode, + UserData = mode + }; + + var modeContent = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.9f), modeFrame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.02f, 0.0f) }) + { + AbsoluteSpacing = (int)(5 * GUI.Scale), + Stretch = true }; - textBlock.ToolTip = mode.Description; + + var modeTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), modeContent.RectTransform), mode.Name, font: GUI.SubHeadingFont); + var modeDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), modeContent.RectTransform), mode.Description, font: GUI.SmallFont, wrap: true); + modeTitle.HoverColor = modeDescription.HoverColor = modeTitle.SelectedColor = modeDescription.SelectedColor = Color.Transparent; + modeTitle.HoverTextColor = modeDescription.HoverTextColor = modeTitle.TextColor; + modeTitle.TextColor = modeDescription.TextColor = modeTitle.TextColor * 0.5f; + modeFrame.OnAddedToGUIUpdateList = (c) => + { + modeTitle.State = modeDescription.State = c.State; + }; + + new GUIImage(new RectTransform(new Vector2(0.2f, 0.8f), modeFrame.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.02f, 0.0f) }, + style: "GameModeIcon." + mode.Identifier, scaleToFit: true); + + modeFrame.RectTransform.MinSize = new Point(0, (int)(modeContent.Children.Sum(c => c.Rect.Height + modeContent.AbsoluteSpacing) / modeContent.RectTransform.RelativeSize.Y)); } var gameModeSpecificFrame = new GUIFrame(new RectTransform(new Vector2(0.333f, 1.0f), gameModeBackground.RectTransform), style: null); @@ -926,7 +957,8 @@ namespace Barotrauma Stretch = true }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), missionHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("MissionType")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), missionHolder.RectTransform) { MinSize = new Point(0, 25) }, + TextManager.Get("MissionType"), font: GUI.SubHeadingFont); missionTypeList = new GUIListBox(new RectTransform(Vector2.One, missionHolder.RectTransform)) { OnSelected = (component, obj) => @@ -958,6 +990,7 @@ namespace Barotrauma return true; } }; + frame.RectTransform.MinSize = missionTypeTickBoxes[index].RectTransform.MinSize; index++; } @@ -972,22 +1005,19 @@ namespace Barotrauma }; new GUIFrame(new RectTransform(new Vector2(1.0f, 0.055f), settingsHolder.RectTransform) { MinSize = new Point(0, 25) }, style: null); - var settingsContent = new GUILayoutGroup(new RectTransform(Vector2.One, settingsHolder.RectTransform)) + var settingsFrame = new GUIFrame(new RectTransform(Vector2.One, settingsHolder.RectTransform), style: "InnerFrame"); + var settingsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), settingsFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.025f }; - new GUIFrame(new RectTransform(Vector2.One, settingsContent.RectTransform), style: "InnerFrame") - { - IgnoreLayoutGroups = true - }; var traitorsSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), isHorizontal: true) { Stretch = true }; new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), traitorsSettingHolder.RectTransform), TextManager.Get("Traitors")); - var traitorProbContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), traitorsSettingHolder.RectTransform), isHorizontal: true) { Stretch = true }; + var traitorProbContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), traitorsSettingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.05f, Stretch = true }; traitorProbabilityButtons = new GUIButton[2]; - traitorProbabilityButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), traitorProbContainer.RectTransform), "<") + traitorProbabilityButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), traitorProbContainer.RectTransform), style: "GUIButtonToggleLeft") { OnClicked = (button, obj) => { @@ -997,8 +1027,9 @@ namespace Barotrauma } }; - traitorProbabilityText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), traitorProbContainer.RectTransform), TextManager.Get("No"), textAlignment: Alignment.Center); - traitorProbabilityButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), traitorProbContainer.RectTransform), ">") + traitorProbabilityText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), traitorProbContainer.RectTransform), TextManager.Get("No"), + textAlignment: Alignment.Center, style: "GUITextBox"); + traitorProbabilityButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), traitorProbContainer.RectTransform), style: "GUIButtonToggleRight") { OnClicked = (button, obj) => { @@ -1015,9 +1046,9 @@ namespace Barotrauma var botCountSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), isHorizontal: true) { Stretch = true }; new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), botCountSettingHolder.RectTransform), TextManager.Get("BotCount")); - var botCountContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), botCountSettingHolder.RectTransform), isHorizontal: true) { Stretch = true }; + var botCountContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), botCountSettingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.05f, Stretch = true }; botCountButtons = new GUIButton[2]; - botCountButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), botCountContainer.RectTransform), "<") + botCountButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), botCountContainer.RectTransform), style: "GUIButtonToggleLeft") { OnClicked = (button, obj) => { @@ -1026,8 +1057,8 @@ namespace Barotrauma } }; - botCountText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), botCountContainer.RectTransform), "0", textAlignment: Alignment.Center); - botCountButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), botCountContainer.RectTransform), ">") + botCountText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), botCountContainer.RectTransform), "0", textAlignment: Alignment.Center, style: "GUITextBox"); + botCountButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), botCountContainer.RectTransform), style: "GUIButtonToggleRight") { OnClicked = (button, obj) => { @@ -1040,10 +1071,10 @@ namespace Barotrauma var botSpawnModeSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), isHorizontal: true) { Stretch = true }; - new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), botSpawnModeSettingHolder.RectTransform), TextManager.Get("BotSpawnMode")); - var botSpawnModeContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), botSpawnModeSettingHolder.RectTransform), isHorizontal: true) { Stretch = true }; + new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), botSpawnModeSettingHolder.RectTransform), TextManager.Get("BotSpawnMode"), wrap: true); + var botSpawnModeContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), botSpawnModeSettingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.05f, Stretch = true }; botSpawnModeButtons = new GUIButton[2]; - botSpawnModeButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), botSpawnModeContainer.RectTransform), "<") + botSpawnModeButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), botSpawnModeContainer.RectTransform), style: "GUIButtonToggleLeft") { OnClicked = (button, obj) => { @@ -1052,8 +1083,8 @@ namespace Barotrauma } }; - botSpawnModeText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), botSpawnModeContainer.RectTransform), "", textAlignment: Alignment.Center); - botSpawnModeButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), botSpawnModeContainer.RectTransform), ">") + botSpawnModeText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), botSpawnModeContainer.RectTransform), "", textAlignment: Alignment.Center, style: "GUITextBox"); + botSpawnModeButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), botSpawnModeContainer.RectTransform), style: "GUIButtonToggleRight") { OnClicked = (button, obj) => { @@ -1129,8 +1160,8 @@ namespace Barotrauma foreach (Sprite sprite in characterSprites) { sprite.Remove(); } characterSprites.Clear(); - foreach (Sprite sprite in jobPreferenceSprites) { sprite.Remove(); } - jobPreferenceSprites.Clear(); + /*foreach (Sprite sprite in jobPreferenceSprites) { sprite.Remove(); } + jobPreferenceSprites.Clear();*/ } public override void Select() @@ -1140,6 +1171,8 @@ namespace Barotrauma if (HeadSelectionList != null) { HeadSelectionList.Visible = false; } if (JobSelectionFrame != null) { JobSelectionFrame.Visible = false; } + infoFrameContent.Recalculate(); + Character.Controlled = null; GameMain.LightManager.LosEnabled = false; @@ -1387,7 +1420,7 @@ namespace Barotrauma break; } - var slot = new GUIFrame(new RectTransform(new Vector2(0.333f, 1.0f), JobList.Content.RectTransform), style: "ListBoxElement") + var slot = new GUIFrame(new RectTransform(new Vector2(0.333f, 1.0f), JobList.Content.RectTransform), style: "ListBoxElementSquare") { CanBeFocused = true, UserData = jobPrefab @@ -1404,7 +1437,11 @@ namespace Barotrauma } else { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), infoContainer.RectTransform), characterInfo.Job.Name, textAlignment: Alignment.Center, wrap: true); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), infoContainer.RectTransform), characterInfo.Job.Name, textAlignment: Alignment.Center, wrap: true) + { + HoverColor = Color.Transparent, + SelectedColor = Color.Transparent + }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), infoContainer.RectTransform), TextManager.Get("Skills")); foreach (Skill skill in characterInfo.Job.Skills) @@ -1546,16 +1583,6 @@ namespace Barotrauma { subTextBlock.TextColor = new Color(subTextBlock.TextColor, sub.HasTag(SubmarineTag.Shuttle) ? 1.0f : 0.6f); } - - /*GUIButton infoButton = new GUIButton(new RectTransform(new Point(buttonSize, buttonSize), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point((int)(buttonSize * 0.2f), 0) }, "?") - { - UserData = sub - }; - infoButton.OnClicked += (component, userdata) => - { - ((Submarine)userdata).CreatePreviewWindow(new GUIMessageBox("", "", new Vector2(0.25f, 0.25f), new Point(500, 400))); - return true; - };*/ } if (!sub.RequiredContentPackagesInstalled) @@ -1622,8 +1649,7 @@ namespace Barotrauma } if (component.UserData is Submarine sub) { - subPreviewContainer.ClearChildren(); - sub.CreatePreviewWindow(subPreviewContainer); + CreateSubPreview(sub); } voteType = VoteType.Sub; } @@ -1814,7 +1840,7 @@ namespace Barotrauma playerFrame.UserData = selectedClient; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), paddedPlayerFrame.RectTransform), - TextManager.Get("Rank")); + TextManager.Get("Rank"), font: GUI.SubHeadingFont); var rankDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.1f), paddedPlayerFrame.RectTransform), TextManager.Get("Rank")) { @@ -1847,13 +1873,14 @@ namespace Barotrauma return true; }; - var permissionLabels = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), paddedPlayerFrame.RectTransform), isHorizontal: true) + var permissionLabels = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedPlayerFrame.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; - var permissionLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), permissionLabels.RectTransform), TextManager.Get("Permissions")); - var consoleCommandLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), permissionLabels.RectTransform), TextManager.Get("PermittedConsoleCommands")); + var permissionLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), permissionLabels.RectTransform), TextManager.Get("Permissions"), font: GUI.SubHeadingFont); + var consoleCommandLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), permissionLabels.RectTransform), + TextManager.Get("PermittedConsoleCommands"), wrap: true, font: GUI.SubHeadingFont); GUITextBlock.AutoScaleAndNormalize(permissionLabel, consoleCommandLabel); var permissionContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.4f), paddedPlayerFrame.RectTransform), isHorizontal: true) @@ -1909,8 +1936,7 @@ namespace Barotrauma //reset rank to custom rankDropDown.SelectItem(null); - var client = playerFrame.UserData as Client; - if (client == null) { return false; } + if (!(playerFrame.UserData is Client client)) { return false; } var thisPermission = (ClientPermissions)tickBox.UserData; if (tickBox.Selected) @@ -1944,8 +1970,7 @@ namespace Barotrauma //reset rank to custom rankDropDown.SelectItem(null); - var client = playerFrame.UserData as Client; - if (client == null) { return false; } + if (!(playerFrame.UserData is Client client)) { return false; } foreach (GUIComponent child in tickbox.Parent.GetChild().Content.Children) { @@ -1977,9 +2002,8 @@ namespace Barotrauma //reset rank to custom rankDropDown.SelectItem(null); - Client client = playerFrame.UserData as Client; DebugConsole.Command selectedCommand = tickBox.UserData as DebugConsole.Command; - if (client == null) return false; + if (!(playerFrame.UserData is Client client)) { return false; } if (!tickBox.Selected) { @@ -2057,12 +2081,20 @@ namespace Barotrauma } var closeButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonAreaLower.RectTransform, Anchor.BottomRight), - TextManager.Get("Close"), style: "GUIButtonLarge") + TextManager.Get("Close")) { IgnoreLayoutGroups = true, OnClicked = ClosePlayerFrame }; + buttonAreaLower.RectTransform.MinSize = new Point(0, buttonAreaLower.RectTransform.Children.Max(c => c.MinSize.Y)); + + if (buttonAreaTop != null) + { + buttonAreaTop.RectTransform.MinSize = buttonAreaLower.RectTransform.MinSize = + new Point(0, Math.Max(buttonAreaLower.RectTransform.MinSize.Y, buttonAreaTop.RectTransform.Children.Max(c => c.MinSize.Y))); + } + return false; } @@ -2198,12 +2230,12 @@ namespace Barotrauma PlayStyle playStyle = GameMain.NetworkMember.ServerSettings.PlayStyle; if ((int)playStyle < 0 || - (int)playStyle >= GameMain.ServerListScreen.PlayStyleBanners.Length) + (int)playStyle >= ServerListScreen.PlayStyleBanners.Length) { return; } - Sprite sprite = GameMain.ServerListScreen.PlayStyleBanners[(int)playStyle]; + Sprite sprite = ServerListScreen.PlayStyleBanners[(int)playStyle]; float scale = component.Rect.Width / sprite.size.X; sprite.Draw(spriteBatch, component.Center, scale: scale); @@ -2211,7 +2243,7 @@ namespace Barotrauma { var nameText = component.GetChild(); nameText.Text = TextManager.Get("servertag." + playStyle); - nameText.Color = GameMain.ServerListScreen.PlayStyleColors[(int)playStyle]; + nameText.Color = ServerListScreen.PlayStyleColors[(int)playStyle]; nameText.RectTransform.NonScaledSize = (nameText.Font.MeasureString(nameText.Text) + new Vector2(25, 10) * GUI.Scale).ToPoint(); prevPlayStyle = playStyle; @@ -2278,24 +2310,19 @@ namespace Barotrauma var info = GameMain.Client.CharacterInfo; - GUILayoutGroup columnLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), appearanceFrame.RectTransform, Anchor.Center), isHorizontal: true) - { - Stretch = true, - RelativeSpacing = 0.05f - }; - - //left column - GUILayoutGroup leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), columnLayout.RectTransform)) + GUILayoutGroup content = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), appearanceFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.05f }; - GUILayoutGroup genderContainer = new GUILayoutGroup(new RectTransform(new Vector2(2.0f, 0.2f), leftColumn.RectTransform), isHorizontal: true) + Vector2 elementSize = new Vector2(1.0f, 0.18f); + + GUILayoutGroup genderContainer = new GUILayoutGroup(new RectTransform(elementSize, content.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), genderContainer.RectTransform), TextManager.Get("Gender")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), genderContainer.RectTransform), TextManager.Get("Gender"), font: GUI.SubHeadingFont); maleButton = new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), genderContainer.RectTransform), TextManager.Get("Male"), style: "ListBoxElement") { @@ -2314,8 +2341,8 @@ namespace Barotrauma int hairCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables), WearableType.Hair).Count(); if (hairCount > 0) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), leftColumn.RectTransform), TextManager.Get("FaceAttachment.Hair")); - var hairSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.15f), leftColumn.RectTransform)) + var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Hair"), font: GUI.SubHeadingFont); + var hairSlider = new GUIScrollBar(new RectTransform(new Vector2(0.4f, 1.0f), label.RectTransform, Anchor.CenterRight), style: "GUISlider") { Range = new Vector2(0, hairCount), StepValue = 1, @@ -2328,8 +2355,8 @@ namespace Barotrauma int beardCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables), WearableType.Beard).Count(); if (beardCount > 0) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), leftColumn.RectTransform), TextManager.Get("FaceAttachment.Beard")); - var beardSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.15f), leftColumn.RectTransform)) + var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Beard"), font: GUI.SubHeadingFont); + var beardSlider = new GUIScrollBar(new RectTransform(new Vector2(0.4f, 1.0f), label.RectTransform, Anchor.CenterRight), style: "GUISlider") { Range = new Vector2(0, beardCount), StepValue = 1, @@ -2339,23 +2366,11 @@ namespace Barotrauma }; } - //right column - GUILayoutGroup rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), columnLayout.RectTransform)) - { - RelativeSpacing = 0.05f - }; - - //spacing to account for the gender selection in the left column - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), rightColumn.RectTransform), style: null) - { - CanBeFocused = false - }; - int moustacheCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables), WearableType.Moustache).Count(); if (moustacheCount > 0) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), rightColumn.RectTransform), TextManager.Get("FaceAttachment.Moustache")); - var moustacheSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.15f), rightColumn.RectTransform)) + var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Moustache"), font: GUI.SubHeadingFont); + var moustacheSlider = new GUIScrollBar(new RectTransform(new Vector2(0.4f, 1.0f), label.RectTransform, Anchor.CenterRight), style: "GUISlider") { Range = new Vector2(0, moustacheCount), StepValue = 1, @@ -2368,8 +2383,8 @@ namespace Barotrauma int faceAttachmentCount = info.FilterByTypeAndHeadID(info.FilterElementsByGenderAndRace(info.Wearables), WearableType.FaceAttachment).Count(); if (faceAttachmentCount > 0) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), rightColumn.RectTransform), TextManager.Get("FaceAttachment.Accessories")); - var faceAttachmentSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.15f), rightColumn.RectTransform)) + var label = new GUITextBlock(new RectTransform(elementSize, content.RectTransform), TextManager.Get("FaceAttachment.Accessories"), font: GUI.SubHeadingFont); + var faceAttachmentSlider = new GUIScrollBar(new RectTransform(new Vector2(0.4f, 1.0f), label.RectTransform, Anchor.CenterRight), style: "GUISlider") { Range = new Vector2(0, faceAttachmentCount), StepValue = 1, @@ -2409,6 +2424,7 @@ namespace Barotrauma if (characterInfoFrame == null || HeadSelectionList?.RectTransform == null || button == null) { return; } HeadSelectionList.RectTransform.Resize(new Point(characterInfoFrame.Rect.Width, (characterInfoFrame.Rect.Bottom - button.Rect.Bottom) + characterInfoFrame.Rect.Height * 2)); HeadSelectionList.RectTransform.AbsoluteOffset = new Point(characterInfoFrame.Rect.Right - characterInfoFrame.Rect.Width, button.Rect.Bottom); + if (SelectedSub != null) { CreateSubPreview(SelectedSub); } }; new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), HeadSelectionList.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black) @@ -2458,7 +2474,7 @@ namespace Barotrauma itemsInRow = 0; } - var btn = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), row.RectTransform), style: "ListBoxElement") + var btn = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), row.RectTransform), style: "ListBoxElementSquare") { OutlineColor = Color.White * 0.5f, PressedColor = Color.White * 0.5f, @@ -2578,10 +2594,8 @@ namespace Barotrauma itemsInRow = 0; } - jobButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), row.RectTransform), style: "ListBoxElement") + jobButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), row.RectTransform), style: "ListBoxElementSquare") { - PressedColor = Color.White, - OutlineColor = Color.White * 0.5f, UserData = jobPrefab, OnClicked = (btn, usdt) => { @@ -2591,15 +2605,7 @@ namespace Barotrauma }; itemsInRow++; - var images = AddJobSpritesToGUIComponent(jobButton, jobPrefab.First); - for (int variantIndex = 0; variantIndex < images.Length; variantIndex++) - { - foreach (GUIImage image in images[variantIndex]) - { - characterSprites.Add(image.Sprite); - } - } - + var images = AddJobSpritesToGUIComponent(jobButton, jobPrefab.First, selectedByPlayer: false); if (images != null && images.Length > 1) { jobPrefab.Second = Math.Min(jobPrefab.Second, images.Length); @@ -2646,39 +2652,19 @@ namespace Barotrauma return true; } - private GUIImage[][] AddJobSpritesToGUIComponent(GUIComponent parent, JobPrefab jobPrefab) + private GUIImage[][] AddJobSpritesToGUIComponent(GUIComponent parent, JobPrefab jobPrefab, bool selectedByPlayer) { GUIFrame innerFrame = null; - List outfitPreviews = jobPrefab.GetJobOutfitSprites(Gender.Male, out var maxDimensions); + List outfitPreviews = jobPrefab.GetJobOutfitSprites(Gender.Male, useInventoryIcon: true, out var maxDimensions); - innerFrame = new GUIFrame(new RectTransform(Vector2.One * 0.8f, parent.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(-0.07f, -0.06f) }, style: null) + innerFrame = new GUIFrame(new RectTransform(Vector2.One * 0.8f, parent.RectTransform, Anchor.Center), style: null) { CanBeFocused = false }; - void recalculateInnerFrame() - { - float buttonWidth = parent.Rect.Width; - float buttonHeight = parent.Rect.Height; - - Vector2 innerFrameSize; - if (buttonWidth / maxDimensions.X > buttonHeight / maxDimensions.Y) - { - innerFrameSize = new Vector2((maxDimensions.X / maxDimensions.Y) * (buttonHeight / buttonWidth), 1.0f); - } - else - { - innerFrameSize = new Vector2(1.0f, (maxDimensions.Y / maxDimensions.X) * (buttonWidth / buttonHeight)); - } - - innerFrame.RectTransform.RelativeSize = innerFrameSize * 0.8f; - } - GUIImage[][] retVal = new GUIImage[0][]; if (outfitPreviews != null && outfitPreviews.Any()) { - parent.RectTransform.SizeChanged += recalculateInnerFrame; - retVal = new GUIImage[outfitPreviews.Count][]; for (int i = 0; i < outfitPreviews.Count; i++) { @@ -2687,23 +2673,25 @@ namespace Barotrauma for (int j = 0; j < outfitPreview.Sprites.Count; j++) { Pair sprite = outfitPreview.Sprites[j]; - retVal[i][j] = new GUIImage(new RectTransform(sprite.First.SourceRect.Size.ToVector2() / outfitPreview.Dimensions, innerFrame.RectTransform, Anchor.Center) { RelativeOffset = sprite.Second / outfitPreview.Dimensions }, sprite.First, scaleToFit: true) + float aspectRatio = outfitPreview.Dimensions.Y / outfitPreview.Dimensions.X; + retVal[i][j] = new GUIImage(new RectTransform(new Vector2(0.7f / aspectRatio, 0.7f), innerFrame.RectTransform, Anchor.Center) + { RelativeOffset = sprite.Second / outfitPreview.Dimensions }, sprite.First, scaleToFit: true) { PressedColor = Color.White, CanBeFocused = false }; } } - - recalculateInnerFrame(); } var textBlock = new GUITextBlock( innerFrame.CountChildren == 0 ? new RectTransform(Vector2.One, parent.RectTransform, Anchor.Center) : - new RectTransform(new Vector2(1.0f, 0.2f), parent.RectTransform, Anchor.BottomCenter), - jobPrefab.Name, textAlignment: Alignment.Center) + new RectTransform(new Vector2(selectedByPlayer ? 0.75f : 0.95f, 0.25f), parent.RectTransform, Anchor.TopCenter), + jobPrefab.Name, wrap: true, textAlignment: Alignment.Center) { + HoverColor = Color.Transparent, + SelectedColor = Color.Transparent, TextColor = jobPrefab.UIColor, CanBeFocused = false, AutoScale = true @@ -2829,7 +2817,7 @@ namespace Barotrauma shuttleList.Enabled = !enabled && GameMain.Client.HasPermission(ClientPermissions.SelectSub); StartButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound) && !GameMain.Client.GameStarted && !enabled; - if (campaignViewButton != null) { campaignViewButton.Visible = enabled; } + if (campaignViewButton != null) { campaignViewButton.Enabled = enabled; } if (enabled) { @@ -2876,8 +2864,7 @@ namespace Barotrauma subPreviewContainer.ClearChildren(); foreach (GUIComponent child in subList.Content.Children) { - Submarine sub = child.UserData as Submarine; - if (sub == null) { continue; } + if (!(child.UserData is Submarine sub)) { continue; } //just check the name, even though the campaign sub may not be the exact same version //we're selecting the sub just for show, the selection is not actually used for anything if (sub.Name == name) @@ -2885,7 +2872,7 @@ namespace Barotrauma subList.Select(sub); if (Submarine.SavedSubmarines.Contains(sub)) { - sub.CreatePreviewWindow(subPreviewContainer); + CreateSubPreview(sub); displayed = true; } break; @@ -2894,7 +2881,7 @@ namespace Barotrauma subList.OnSelected += VotableClicked; if (!displayed) { - submarine.CreatePreviewWindow(subPreviewContainer); + CreateSubPreview(submarine); } } @@ -2921,8 +2908,8 @@ namespace Barotrauma private void UpdateJobPreferences(GUIListBox listBox) { - foreach (Sprite sprite in jobPreferenceSprites) { sprite.Remove(); } - jobPreferenceSprites.Clear(); + /*foreach (Sprite sprite in jobPreferenceSprites) { sprite.Remove(); } + jobPreferenceSprites.Clear();*/ List> jobNamePreferences = new List>(); @@ -2931,22 +2918,17 @@ namespace Barotrauma { GUIComponent slot = listBox.Content.GetChild(i); - slot.OutlineColor = Color.White * 0.4f; - slot.Color = Color.Gray; - slot.HoverColor = Color.White; - slot.SelectedColor = Color.White; - slot.ClearChildren(); slot.CanBeFocused = !disableNext; if (slot.UserData is Pair jobPrefab) { - var images = AddJobSpritesToGUIComponent(slot, jobPrefab.First); + var images = AddJobSpritesToGUIComponent(slot, jobPrefab.First, selectedByPlayer: true); for (int variantIndex = 0; variantIndex < images.Length; variantIndex++) { foreach (GUIImage image in images[variantIndex]) { - jobPreferenceSprites.Add(image.Sprite); + //jobPreferenceSprites.Add(image.Sprite); int selectedVariantIndex = Math.Min(jobPrefab.Second, images.Length); image.Visible = images.Length == 1 || selectedVariantIndex == variantIndex; } @@ -3023,16 +3005,12 @@ namespace Barotrauma private GUIButton CreateJobVariantButton(Pair jobPrefab, int variantIndex, int variantCount, GUIComponent slot) { - float relativeHeight = Math.Min(0.7f / variantCount, 0.2f); + float relativeSize = 0.2f; - var btn = new GUIButton(new RectTransform(new Vector2(relativeHeight), slot.RectTransform, scaleBasis: ScaleBasis.BothHeight) - { RelativeOffset = new Vector2(0.05f, 0.25f + relativeHeight * 1.05f * variantIndex) }, - (variantIndex + 1).ToString(), style: null) + var btn = new GUIButton(new RectTransform(new Vector2(relativeSize), slot.RectTransform, Anchor.BottomCenter, scaleBasis: ScaleBasis.BothHeight) + { RelativeOffset = new Vector2(relativeSize * 1.05f * (variantIndex - (variantCount - 1) / 2.0f), 0.02f) }, + (variantIndex + 1).ToString(), style: "JobVariantButton") { - Color = new Color(50, 50, 50, 200), - HoverColor = Color.Gray * 0.75f, - PressedColor = Color.Black * 0.75f, - SelectedColor = new Color(45, 70, 100, 200), Selected = jobPrefab.Second == variantIndex, UserData = new Pair(jobPrefab.First, variantIndex), }; @@ -3061,8 +3039,7 @@ namespace Barotrauma { if (subList == this.subList) { - subPreviewContainer.ClearChildren(); - sub.CreatePreviewWindow(subPreviewContainer); + CreateSubPreview(sub); } if (subList.SelectedData is Submarine selectedSub && selectedSub.MD5Hash?.Hash == md5Hash && System.IO.File.Exists(sub.FilePath)) { @@ -3121,7 +3098,7 @@ namespace Barotrauma { errorMsg = TextManager.GetWithVariable("SubLoadError", "[subname]", subName) + " "; GUITextBlock textBlock = subList.Content.GetChildByUserData(sub)?.GetChild(); - if (textBlock != null) { textBlock.TextColor = Color.Red; } + if (textBlock != null) { textBlock.TextColor = GUI.Style.Red; } } else { @@ -3154,5 +3131,17 @@ namespace Barotrauma return false; } + + private void CreateSubPreview(Submarine sub) + { + subPreviewContainer.ClearChildren(); + sub.CreatePreviewWindow(subPreviewContainer); + var descriptionBox = subPreviewContainer.FindChild("descriptionbox", recursive: true); + //if description box and character info box are roughly the same size, scale them to the same size + if (characterInfoFrame != null && Math.Abs(descriptionBox.Rect.Height - characterInfoFrame.Rect.Height) < 80 * GUI.Scale) + { + descriptionBox.RectTransform.MaxSize = new Point(descriptionBox.Rect.Width, characterInfoFrame.Rect.Height); + } + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ParticleEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ParticleEditorScreen.cs index 16aa154db..922e24e57 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ParticleEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ParticleEditorScreen.cs @@ -61,16 +61,14 @@ namespace Barotrauma } } - private readonly GUIComponent rightPanel, leftPanel; - private readonly GUIListBox prefabList; - private readonly GUITextBox filterBox; - private readonly GUITextBlock filterLabel; + private GUIComponent rightPanel, leftPanel; + private GUIListBox prefabList; + private GUITextBox filterBox; + private GUITextBlock filterLabel; private ParticlePrefab selectedPrefab; - private SerializableEntityEditor particlePrefabEditor; - - private readonly Emitter emitter; + private Emitter emitter; private readonly Camera cam; @@ -85,6 +83,14 @@ namespace Barotrauma public ParticleEditorScreen() { cam = new Camera(); + GameMain.Instance.OnResolutionChanged += CreateUI; + CreateUI(); + + } + + private void CreateUI() + { + Frame.ClearChildren(); leftPanel = new GUIFrame(new RectTransform(new Vector2(0.125f, 1.0f), Frame.RectTransform) { MinSize = new Point(150, 0) }, style: "GUIFrameLeft"); @@ -94,9 +100,9 @@ namespace Barotrauma Stretch = true }; - rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), Frame.RectTransform, Anchor.TopRight) { MinSize = new Point(450, 0) }, + rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), Frame.RectTransform, Anchor.TopRight) { MinSize = new Point(350, 0) }, style: "GUIFrameRight"); - var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center) {RelativeOffset = new Vector2(0.02f, 0.0f) }) + var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.02f, 0.0f) }) { RelativeSpacing = 0.01f, Stretch = true @@ -124,7 +130,7 @@ namespace Barotrauma emitter = new Emitter(); var emitterEditorContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), paddedRightPanel.RectTransform), style: null); - var emitterEditor = new SerializableEntityEditor(emitterEditorContainer.RectTransform, emitter, false, true, elementHeight: 20); + var emitterEditor = new SerializableEntityEditor(emitterEditorContainer.RectTransform, emitter, false, true, elementHeight: 20, titleFont: GUI.SubHeadingFont); emitterEditor.RectTransform.RelativeSize = Vector2.One; emitterEditorContainer.RectTransform.Resize(new Point(emitterEditorContainer.RectTransform.NonScaledSize.X, emitterEditor.ContentHeight), false); @@ -139,7 +145,7 @@ namespace Barotrauma filterLabel = new GUITextBlock(new RectTransform(Vector2.One, filterArea.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.Font) { IgnoreLayoutGroups = true }; filterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font); filterBox.OnTextChanged += (textBox, text) => { FilterEmitters(text); return true; }; - new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), filterArea.RectTransform) { MinSize = new Point(20, 0) }, "x") + new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), filterArea.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUICancelButton") { OnClicked = (btn, userdata) => { FilterEmitters(""); filterBox.Text = ""; filterBox.Flash(Color.White); return true; } }; @@ -149,11 +155,13 @@ namespace Barotrauma { selectedPrefab = obj as ParticlePrefab; listBox.ClearChildren(); - particlePrefabEditor = new SerializableEntityEditor(listBox.Content.RectTransform, selectedPrefab, false, true, elementHeight: 20); + new SerializableEntityEditor(listBox.Content.RectTransform, selectedPrefab, false, true, elementHeight: 20, titleFont: GUI.SubHeadingFont); //listBox.Content.RectTransform.NonScaledSize = particlePrefabEditor.RectTransform.NonScaledSize; //listBox.UpdateScrollBarSize(); return true; }; + + if (GameMain.ParticleManager != null) { RefreshPrefabList(); } } public override void Select() diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs index 72296fff0..8ebe3ca95 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs @@ -23,16 +23,16 @@ namespace Barotrauma //how often the client is allowed to refresh servers private TimeSpan AllowedRefreshInterval = new TimeSpan(0, 0, 3); - private readonly GUIFrame menu; + private GUIFrame menu; - private readonly GUIListBox serverList; - private readonly GUIFrame serverPreview; + private GUIListBox serverList; + private GUIFrame serverPreview; - private readonly GUIButton joinButton; + private GUIButton joinButton; private ServerInfo selectedServer; //friends list - private readonly GUILayoutGroup friendsButtonHolder; + private GUILayoutGroup friendsButtonHolder; private GUIButton friendsDropdownButton; private GUIListBox friendsDropdown; @@ -42,8 +42,9 @@ namespace Barotrauma public UInt64 SteamID; public string Name; public Sprite Sprite; - public string Status; + public string StatusText; public bool PlayingThisGame; + public bool PlayingAnotherGame; public string ConnectName; public string ConnectEndpoint; public UInt64 ConnectLobby; @@ -52,7 +53,7 @@ namespace Barotrauma { get { - return PlayingThisGame && !string.IsNullOrWhiteSpace(Status) && (!string.IsNullOrWhiteSpace(ConnectEndpoint) || ConnectLobby != 0); + return PlayingThisGame && !string.IsNullOrWhiteSpace(StatusText) && (!string.IsNullOrWhiteSpace(ConnectEndpoint) || ConnectLobby != 0); } } } @@ -93,23 +94,31 @@ namespace Barotrauma } private GUIButton[] tabButtons; + private static Sprite[] playStyleBanners; //server playstyle and tags - public Sprite[] PlayStyleBanners + public static Sprite[] PlayStyleBanners { - get; private set; + get + { + if (playStyleBanners == null) + { + LoadPlayStyleBanners(); + } + return playStyleBanners; + } } - public Color[] PlayStyleColors + public static Color[] PlayStyleColors { get; private set; } public GUITextBox ClientNameBox { get; private set; } - public Dictionary PlayStyleIcons + public static Dictionary PlayStyleIcons { get; private set; } - public Dictionary PlayStyleIconColors + public static Dictionary PlayStyleIconColors { get; private set; } @@ -120,28 +129,28 @@ namespace Barotrauma private readonly float[] columnRelativeWidth = new float[] { 0.1f, 0.1f, 0.7f, 0.12f, 0.08f, 0.08f }; private readonly string[] columnLabel = new string[] { "ServerListCompatible", "ServerListHasPassword", "ServerListName", "ServerListRoundStarted", "ServerListPlayers", "ServerListPing" }; - private readonly GUILayoutGroup labelHolder; + private GUILayoutGroup labelHolder; private readonly List labelTexts = new List(); //filters - private readonly GUITextBox searchBox; - private readonly GUITickBox filterSameVersion; - private readonly GUITickBox filterPassword; - private readonly GUITickBox filterIncompatible; - private readonly GUITickBox filterFull; - private readonly GUITickBox filterEmpty; - private readonly GUITickBox filterWhitelisted; - private readonly GUITickBox filterFriendlyFire; - private readonly GUITickBox filterKarma; - private readonly GUITickBox filterTraitor; - private readonly GUITickBox filterModded; - private readonly GUITickBox filterVoip; - private readonly List playStyleTickBoxes; - private readonly List gameModeTickBoxes; + private GUITextBox searchBox; + private GUITickBox filterSameVersion; + private GUITickBox filterPassword; + private GUITickBox filterIncompatible; + private GUITickBox filterFull; + private GUITickBox filterEmpty; + private GUITickBox filterWhitelisted; + private GUITickBox filterFriendlyFire; + private GUITickBox filterKarma; + private GUITickBox filterTraitor; + private GUITickBox filterModded; + private GUITickBox filterVoip; + private List playStyleTickBoxes; + private List gameModeTickBoxes; private string sortedBy; - private readonly GUIButton serverPreviewToggleButton; + private GUIButton serverPreviewToggleButton; //a timer for preventing the client from spamming the refresh button faster than AllowedRefreshInterval private DateTime refreshDisableTimer; @@ -152,11 +161,15 @@ namespace Barotrauma private const float sidebarWidth = 0.2f; public ServerListScreen() { - GameMain.Instance.OnResolutionChanged += OnResolutionChanged; + GameMain.Instance.OnResolutionChanged += CreateUI; + CreateUI(); + } + private void CreateUI() + { menu = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.85f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) }); - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 0.95f), menu.RectTransform, Anchor.Center)) + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.98f), menu.RectTransform, Anchor.Center)) { RelativeSpacing = 0.02f, Stretch = true @@ -175,11 +188,11 @@ namespace Barotrauma AutoScale = true }; - var infoHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), isHorizontal: true) { RelativeSpacing = 0.05f, Stretch = false }; + var infoHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), isHorizontal: true, Anchor.BottomLeft) { RelativeSpacing = 0.01f, Stretch = false }; var clientNameHolder = new GUILayoutGroup(new RectTransform(new Vector2(sidebarWidth, 1.0f), infoHolder.RectTransform)) { RelativeSpacing = 0.05f }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), clientNameHolder.RectTransform), TextManager.Get("YourName")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), clientNameHolder.RectTransform), TextManager.Get("YourName"), font: GUI.SubHeadingFont); ClientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), clientNameHolder.RectTransform), "") { Text = GameMain.Config.PlayerName, @@ -197,18 +210,14 @@ namespace Barotrauma return true; }; - var tabButtonHolder = new GUIFrame(new RectTransform(new Vector2(1.0f - (sidebarWidth*2.0f), 1.25f), infoHolder.RectTransform), style: null); + var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - sidebarWidth - infoHolder.RelativeSpacing, 0.5f), infoHolder.RectTransform), isHorizontal: true); var tabVals = Enum.GetValues(typeof(ServerListTab)); tabButtons = new GUIButton[tabVals.Length]; - int ind = 0; foreach (ServerListTab tab in tabVals) { - tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(0.25f, 0.5f), tabButtonHolder.RectTransform) - { - RelativeOffset = new Vector2(-0.06f + 0.22f * ind, 0.5f) - }, - TextManager.Get("ServerListTab."+tab.ToString()), style: "GUIButtonServerListTab"+(ind==0 ? "Left" : "Middle")) + tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), tabButtonHolder.RectTransform), + TextManager.Get("ServerListTab." + tab.ToString()), style: "GUITabButton") { OnClicked = (btn, usrdat) => { @@ -216,11 +225,14 @@ namespace Barotrauma return false; } }; - ind++; } - var friendsButtonFrame = new GUIFrame(new RectTransform(new Vector2(0.31f, 0.5f), tabButtonHolder.RectTransform) { RelativeOffset = new Vector2(0.60f, 0.5f) }, style: "GUIFrameServerListTabRight"); - friendsButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.81f, 1.0f), friendsButtonFrame.RectTransform, Anchor.TopLeft) { RelativeOffset = new Vector2(0.19f, 0.0f) }, childAnchor: Anchor.TopLeft) { RelativeSpacing = 0.01f, IsHorizontal = true }; + var friendsButtonFrame = new GUIFrame(new RectTransform(new Vector2(0.31f, 2.0f), tabButtonHolder.RectTransform, Anchor.BottomRight), style: "InnerFrame") + { + IgnoreLayoutGroups = true + }; + + friendsButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.9f), friendsButtonFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopLeft) { RelativeSpacing = 0.01f, IsHorizontal = true }; friendsList = new List(); //------------------------------------------------------------------------------------- @@ -233,7 +245,7 @@ namespace Barotrauma Stretch = true }; - var serverListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), bottomRow.RectTransform), isHorizontal: true) + var serverListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), bottomRow.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { OutlineColor = Color.Black }; @@ -263,12 +275,31 @@ namespace Barotrauma OutlineColor = Color.Black }; - var filters = new GUIListBox(new RectTransform(new Vector2(0.98f, 1.0f), filtersHolder.RectTransform, Anchor.CenterRight), style: null) + float elementHeight = 0.05f; + var filterTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), filtersHolder.RectTransform), TextManager.Get("FilterServers"), font: GUI.SubHeadingFont) { - ScrollBarVisible = true + Padding = Vector4.Zero, + AutoScale = true, + CanBeFocused = false }; - filterToggle = new GUIButton(new RectTransform(new Vector2(0.01f, 1.0f), serverListHolder.RectTransform, Anchor.CenterRight) { MinSize = new Point(20, 0) }, style: "UIToggleButton") + var searchHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementHeight), filtersHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, elementHeight) }, isHorizontal: true) { Stretch = true }; + + var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), searchHolder.RectTransform), TextManager.Get("Search") + "..."); + searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), searchHolder.RectTransform), ""); + searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; + searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; + searchBox.OnTextChanged += (txtBox, txt) => { FilterServers(); return true; }; + + var filters = new GUIListBox(new RectTransform(new Vector2(0.98f, 1.0f - elementHeight * 2), filtersHolder.RectTransform, Anchor.BottomLeft)) + { + ScrollBarVisible = true, + Spacing = (int)(5 * GUI.Scale) + }; + + filterToggle = new GUIButton(new RectTransform(new Vector2(0.01f, 1.0f), serverListHolder.RectTransform) + { MinSize = new Point(20, 0), MaxSize = new Point(int.MaxValue, (int)(150 * GUI.Scale)) }, + style: "UIToggleButton") { OnClicked = (btn, userdata) => { @@ -284,31 +315,6 @@ namespace Barotrauma }; filterToggle.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipHorizontally); - /*var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.99f), filters.Content.RectTransform, Anchor.Center)) - { - Stretch = true, - RelativeSpacing = 0.015f - };*/ - - var filterTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), filters.Content.RectTransform), TextManager.Get("FilterServers"), font: GUI.LargeFont) - { - Padding = Vector4.Zero, - AutoScale = true, - CanBeFocused = false - }; - - float elementHeight = 0.05f; - - var searchHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), isHorizontal: true) { Stretch = true }; - - var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), searchHolder.RectTransform), TextManager.Get("Search") + "..."); - searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), searchHolder.RectTransform), ""); - searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; - searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; - searchBox.OnTextChanged += (txtBox, txt) => { FilterServers(); return true; }; - - //var filterHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), filters.Content.RectTransform)) { RelativeSpacing = 0.005f }; - List filterTextList = new List(); filterSameVersion = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("FilterSameVersion")) @@ -355,7 +361,7 @@ namespace Barotrauma filterTextList.Add(filterWhitelisted.TextBlock); // Filter Tags - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("servertags")) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("servertags"), font: GUI.SubHeadingFont) { CanBeFocused = false }; @@ -387,7 +393,6 @@ namespace Barotrauma OnSelected = (tickBox) => { FilterServers(); return true; } }; filterTextList.Add(filterVoip.TextBlock); - filterModded = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), TextManager.Get("servertag.modded.true")) { @@ -397,7 +402,7 @@ namespace Barotrauma filterTextList.Add(filterModded.TextBlock); // Play Style Selection - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("ServerSettingsPlayStyle")) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("ServerSettingsPlayStyle"), font: GUI.SubHeadingFont) { CanBeFocused = false }; @@ -452,7 +457,7 @@ namespace Barotrauma serverListContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), serverListHolder.RectTransform)) { Stretch = true }; labelHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.99f, 0.05f), serverListContainer.RectTransform) { MinSize = new Point(0, 15) }, - isHorizontal: true) + isHorizontal: true, childAnchor: Anchor.BottomLeft) { Stretch = true }; @@ -460,18 +465,14 @@ namespace Barotrauma for (int i = 0; i < columnRelativeWidth.Length; i++) { var btn = new GUIButton(new RectTransform(new Vector2(columnRelativeWidth[i], 1.0f), labelHolder.RectTransform), - text: TextManager.Get(columnLabel[i]), textAlignment: Alignment.Center, style: null) + text: TextManager.Get(columnLabel[i]), textAlignment: Alignment.Center, style: "GUIButtonSmall") { - Color = new Color(12, 14, 15, 255) * 0.5f, - HoverColor = new Color(12, 14, 15, 255) * 2.5f, - SelectedColor = Color.Gray * 0.7f, - PressedColor = Color.Gray * 0.7f, - OutlineColor = Color.Black, ToolTip = TextManager.Get(columnLabel[i]), ForceUpperCase = true, UserData = columnLabel[i], OnClicked = SortList }; + btn.Color *= 0.5f; labelTexts.Add(btn.TextBlock); new GUIImage(new RectTransform(new Vector2(0.5f, 0.3f), btn.RectTransform, Anchor.BottomCenter, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonVerticalArrow", scaleToFit: true) @@ -516,7 +517,9 @@ namespace Barotrauma //server preview panel -------------------------------------------------- - serverPreviewToggleButton = new GUIButton(new RectTransform(new Vector2(0.01f, 1.0f), serverListHolder.RectTransform, Anchor.CenterRight) { MinSize = new Point(20, 0) }, style: "UIToggleButton") + serverPreviewToggleButton = new GUIButton(new RectTransform(new Vector2(0.01f, 1.0f), serverListHolder.RectTransform) + { MinSize = new Point(20, 0), MaxSize = new Point(int.MaxValue, (int)(150 * GUI.Scale)) }, + style: "UIToggleButton") { Visible = false, OnClicked = (btn, userdata) => @@ -550,25 +553,25 @@ namespace Barotrauma }; GUIButton button = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("Back"), style: "GUIButtonLarge") + TextManager.Get("Back")) { OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu }; new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("ServerListRefresh"), style: "GUIButtonLarge") + TextManager.Get("ServerListRefresh")) { OnClicked = (btn, userdata) => { RefreshServers(); return true; } }; var directJoinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("serverlistdirectjoin"), style: "GUIButtonLarge") + TextManager.Get("serverlistdirectjoin")) { OnClicked = (btn, userdata) => { ShowDirectJoinPrompt(); return true; } }; joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform), - TextManager.Get("ServerListJoin"), style: "GUIButtonLarge") + TextManager.Get("ServerListJoin")) { OnClicked = (btn, userdata) => { @@ -593,6 +596,8 @@ namespace Barotrauma Enabled = false }; + buttonContainer.RectTransform.MinSize = new Point(0, (int)(buttonContainer.RectTransform.Children.Max(c => c.MinSize.Y) * 1.2f)); + //-------------------------------------------------------- bottomRow.Recalculate(); @@ -614,9 +619,24 @@ namespace Barotrauma button.SelectedColor = button.Color; refreshDisableTimer = DateTime.Now; + + //recent and favorite servers + ReadServerMemFromFile(recentServersFile, ref recentServers); + ReadServerMemFromFile(favoriteServersFile, ref favoriteServers); + recentServers.ForEach(s => s.Recent = true); + favoriteServers.ForEach(s => s.Favorite = true); + SelectedTab = ServerListTab.All; + tabButtons[(int)selectedTab].Selected = true; + + RecalculateHolder(); + } + + + private static void LoadPlayStyleBanners() + { //playstyle banners - PlayStyleBanners = new Sprite[Enum.GetValues(typeof(PlayStyle)).Length]; + playStyleBanners = new Sprite[Enum.GetValues(typeof(PlayStyle)).Length]; PlayStyleColors = new Color[Enum.GetValues(typeof(PlayStyle)).Length]; PlayStyleIcons = new Dictionary(); PlayStyleIconColors = new Dictionary(); @@ -643,17 +663,6 @@ namespace Barotrauma break; } } - - //recent and favorite servers - ReadServerMemFromFile(recentServersFile, ref recentServers); - ReadServerMemFromFile(favoriteServersFile, ref favoriteServers); - recentServers.ForEach(s => s.Recent = true); - favoriteServers.ForEach(s => s.Favorite = true); - - SelectedTab = ServerListTab.All; - tabButtons[(int)selectedTab].Selected = true; - - RecalculateHolder(); } private void ReadServerMemFromFile(string file, ref List servers) @@ -800,16 +809,6 @@ namespace Barotrauma } } - private void OnResolutionChanged() - { - menu.RectTransform.MinSize = new Point(GameMain.GraphicsHeight, 0); - labelHolder.RectTransform.MaxSize = new Point(serverList.Content.Rect.Width, int.MaxValue); - foreach (GUITextBlock labelText in labelTexts) - { - labelText.Text = ToolBox.LimitString(labelText.ToolTip, labelText.Font, labelText.Rect.Width); - } - } - private bool SortList(GUIButton button, object obj) { if (!(obj is string sortBy)) { return false; } @@ -1019,18 +1018,24 @@ namespace Barotrauma private void ShowDirectJoinPrompt() { - var msgBox = new GUIMessageBox(TextManager.Get("ServerListDirectJoin"), "", new string[] { TextManager.Get("ServerListJoin"), TextManager.Get("Cancel") }, + var msgBox = new GUIMessageBox(TextManager.Get("ServerListDirectJoin"), "", + new string[] { TextManager.Get("ServerListJoin"), TextManager.Get("AddToFavorites"), TextManager.Get("Cancel") }, relativeSize: new Vector2(0.25f, 0.2f), minSize: new Point(400, 150)); + msgBox.Content.ChildAnchor = Anchor.TopCenter; - var content = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.5f), msgBox.InnerFrame.RectTransform, Anchor.Center) { MinSize = new Point(0, 50) }) + var content = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.5f), msgBox.Content.RectTransform), childAnchor: Anchor.TopCenter) { - IgnoreLayoutGroups = true, + IgnoreLayoutGroups = false, Stretch = true, RelativeSpacing = 0.05f }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.33f), content.RectTransform), TextManager.Get("ServerEndpoint")); - var endpointBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.33f), content.RectTransform)); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), TextManager.Get("ServerEndpoint"), textAlignment: Alignment.Center); + var endpointBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform)); + + content.RectTransform.NonScaledSize = new Point(content.Rect.Width, (int)(content.RectTransform.Children.Sum(c => c.Rect.Height))); + content.RectTransform.IsFixedSize = true; + msgBox.InnerFrame.RectTransform.MinSize = new Point(0, (int)((content.RectTransform.NonScaledSize.Y + msgBox.Content.RectTransform.Children.Sum(c => c.NonScaledSize.Y + msgBox.Content.AbsoluteSpacing)) * 1.1f)); var okButton = msgBox.Buttons[0]; okButton.Enabled = false; @@ -1041,21 +1046,9 @@ namespace Barotrauma return true; }; - var cancelButton = msgBox.Buttons[1]; - cancelButton.OnClicked = msgBox.Close; - - endpointBox.OnTextChanged += (textBox, text) => - { - okButton.Enabled = !string.IsNullOrEmpty(text); - return true; - }; - - var spacingLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.33f), content.RectTransform), true); - - new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), spacingLayoutGroup.RectTransform), null); - - var addToFavoritesButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), spacingLayoutGroup.RectTransform), TextManager.Get("AddToFavorites")); - addToFavoritesButton.OnClicked = (button, userdata) => + var favoriteButton = msgBox.Buttons[1]; + favoriteButton.Enabled = false; + favoriteButton.OnClicked = (button, userdata) => { UInt64 steamId = SteamManager.SteamIDStringToUInt64(endpointBox.Text); string ip = ""; int port = 0; @@ -1115,6 +1108,15 @@ namespace Barotrauma msgBox.Close(); return false; }; + + var cancelButton = msgBox.Buttons[2]; + cancelButton.OnClicked = msgBox.Close; + + endpointBox.OnTextChanged += (textBox, text) => + { + okButton.Enabled = favoriteButton.Enabled = !string.IsNullOrEmpty(text); + return true; + }; } private bool JoinFriend(GUIButton button, object userdata) @@ -1182,7 +1184,8 @@ namespace Barotrauma float prevDropdownScroll = friendsDropdown?.ScrollBar.BarScrollValue ?? 0.0f; - if (friendsDropdown == null) { + if (friendsDropdown == null) + { friendsDropdown = new GUIListBox(new RectTransform(Vector2.One, GUI.Canvas)) { OutlineColor = Color.Black, @@ -1286,17 +1289,17 @@ namespace Barotrauma info.ConnectLobby = 0; info.PlayingThisGame = friend.IsPlayingThisGame; + info.PlayingAnotherGame = friend.GameInfo.HasValue; if (friend.IsPlayingThisGame) { - info.Status = friend.GetRichPresence("status") ?? ""; + info.StatusText = friend.GetRichPresence("status") ?? ""; string connectCommand = friend.GetRichPresence("connect") ?? ""; - ToolBox.ParseConnectCommand(connectCommand.Split(' '), out info.ConnectName, out info.ConnectEndpoint, out info.ConnectLobby); } else { - info.Status = TextManager.Get(friend.GameInfo.HasValue ? "FriendPlayingAnotherGame" : "FriendNotPlaying"); + info.StatusText = TextManager.Get(info.PlayingAnotherGame ? "FriendPlayingAnotherGame" : "FriendNotPlaying"); } } @@ -1319,10 +1322,8 @@ namespace Barotrauma OnClicked = (button, udt) => { friendsDropdown.RectTransform.NonScaledSize = new Point(friendsButtonHolder.Rect.Height * 5 * 166 / 100, friendsButtonHolder.Rect.Height * 4 * 166 / 100); - friendsDropdown.RectTransform.RelativeOffset = new Vector2(0.295f, 0.235f); + friendsDropdown.RectTransform.AbsoluteOffset = new Point(friendsButtonHolder.Rect.X, friendsButtonHolder.Rect.Bottom); friendsDropdown.RectTransform.RecalculateChildren(true); - friendsDropdown.RectTransform.SetPosition(Anchor.TopRight); - friendsDropdown.Visible = !friendsDropdown.Visible; return false; } @@ -1358,11 +1359,11 @@ namespace Barotrauma UserData = friend, OnClicked = OpenFriendPopup }; - guiButton.ToolTip = friend.Name + "\n" + friend.Status; + guiButton.ToolTip = friend.Name + "\n" + friend.StatusText; if (friend.Sprite != null) { - Color BrightenColor(Color color) + static Color BrightenColor(Color color) { Vector3 hls = ToolBox.RgbToHLS(color); hls.Y = hls.Y * 0.3f + 0.7f; @@ -1398,10 +1399,12 @@ namespace Barotrauma var friendFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.167f), friendsDropdown.Content.RectTransform), style: "GUIFrameFriendsDropdown"); var guiImage2TheSequel = new GUIImage(new RectTransform(Vector2.One * 0.9f, friendFrame.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(0.02f, 0.02f) } , friend.Sprite, null, true); - var textBlock = new GUITextBlock(new RectTransform(Vector2.One * 0.8f, friendFrame.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(1.0f / 7.7f, 0.0f) }, friend.Name + "\n" + friend.Status) + var textBlock = new GUITextBlock(new RectTransform(Vector2.One * 0.8f, friendFrame.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.BothHeight) { RelativeOffset = new Vector2(1.0f / 7.7f, 0.0f) }, friend.Name + "\n" + friend.StatusText) { Font = GUI.SmallFont }; + if (friend.PlayingThisGame) { textBlock.TextColor = GUI.Style.Green; } + if (friend.PlayingAnotherGame) { textBlock.TextColor = GUI.Style.Blue; } if (friend.InServer) { @@ -1414,9 +1417,8 @@ namespace Barotrauma } friendsDropdown.RectTransform.NonScaledSize = new Point(friendsButtonHolder.Rect.Height * 5 * 166 / 100, friendsButtonHolder.Rect.Height * 4 * 166 / 100); - friendsDropdown.RectTransform.RelativeOffset = new Vector2(0.295f, 0.235f); + friendsDropdown.RectTransform.AbsoluteOffset = new Point(friendsButtonHolder.Rect.X, friendsButtonHolder.Rect.Bottom); friendsDropdown.RectTransform.RecalculateChildren(true); - friendsDropdown.RectTransform.SetPosition(Anchor.TopRight); friendsDropdown.ScrollBar.BarScrollValue = prevDropdownScroll; } @@ -1577,7 +1579,7 @@ namespace Barotrauma if (serverFrame == null) { serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 35) }, - style: "InnerFrame", color: Color.White * 0.5f) + style: "ListBoxElement") { UserData = serverInfo }; @@ -1716,7 +1718,7 @@ namespace Barotrauma else if (string.IsNullOrEmpty(serverInfo.GameVersion) || !serverInfo.ContentPackageHashes.Any()) { compatibleBox.Selected = false; - new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), compatibleBox.Box.RectTransform, Anchor.Center), " ? ", Color.Yellow * 0.85f, textAlignment: Alignment.Center) + new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), compatibleBox.Box.RectTransform, Anchor.Center), " ? ", GUI.Style.Orange * 0.85f, textAlignment: Alignment.Center) { ToolTip = TextManager.Get(string.IsNullOrEmpty(serverInfo.GameVersion) ? "ServerListUnknownVersion" : @@ -1941,7 +1943,7 @@ namespace Barotrauma private Color GetPingTextColor(int ping) { if (ping < 0) { return Color.DarkRed; } - return ToolBox.GradientLerp(ping / 200.0f, Color.LightGreen, Color.Yellow * 0.8f, Color.Red * 0.75f); + return ToolBox.GradientLerp(ping / 200.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red); } public async Task PingServerAsync(string ip, int timeOut) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SpriteEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SpriteEditorScreen.cs index f3e385b33..8a267922e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SpriteEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SpriteEditorScreen.cs @@ -60,20 +60,21 @@ namespace Barotrauma public SpriteEditorScreen() { cam = new Camera(); - CreateGUIElements(); + GameMain.Instance.OnResolutionChanged += CreateUI; + CreateUI(); } #region Initialization - private void CreateGUIElements() + private void CreateUI() { - originLabel = TextManager.Get("charactereditor.origin") + ": "; + originLabel = TextManager.Get("charactereditor.origin"); positionLabel = TextManager.GetWithVariable("charactereditor.position", "[coordinates]", string.Empty); - sizeLabel = TextManager.Get("charactereditor.origin") + ": "; + sizeLabel = TextManager.Get("charactereditor.size"); - topPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), Frame.RectTransform) { MinSize = new Point(0, 60) }, "GUIFrameTop"); + topPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.15f), Frame.RectTransform) { MinSize = new Point(0, 60) }, "GUIFrameTop"); topPanelContents = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.8f), topPanel.RectTransform, Anchor.Center), style: null); - new GUIButton(new RectTransform(new Vector2(0.12f, 0.4f), topPanelContents.RectTransform, Anchor.TopLeft) + new GUIButton(new RectTransform(new Vector2(0.14f, 0.4f), topPanelContents.RectTransform, Anchor.TopLeft) { RelativeOffset = new Vector2(0, 0.1f) }, TextManager.Get("spriteeditor.reloadtexture")) @@ -88,11 +89,11 @@ namespace Barotrauma textureList.Select(firstSelected.Texture, autoScroll: false); selected.ForEachMod(s => spriteList.Select(s, autoScroll: false)); texturePathText.Text = TextManager.GetWithVariable("spriteeditor.texturesreloaded", "[filepath]", firstSelected.FilePath); - texturePathText.TextColor = Color.LightGreen; + texturePathText.TextColor = GUI.Style.Green; return true; } }; - new GUIButton(new RectTransform(new Vector2(0.12f, 0.4f), topPanelContents.RectTransform, Anchor.BottomLeft) + new GUIButton(new RectTransform(new Vector2(0.14f, 0.4f), topPanelContents.RectTransform, Anchor.BottomLeft) { RelativeOffset = new Vector2(0, 0.1f) }, TextManager.Get("spriteeditor.resetchanges")) @@ -111,11 +112,11 @@ namespace Barotrauma } ResetWidgets(); xmlPathText.Text = TextManager.Get("spriteeditor.resetsuccessful"); - xmlPathText.TextColor = Color.LightGreen; + xmlPathText.TextColor = GUI.Style.Green; return true; } }; - new GUIButton(new RectTransform(new Vector2(0.12f, 0.4f), topPanelContents.RectTransform, Anchor.TopLeft) + new GUIButton(new RectTransform(new Vector2(0.14f, 0.4f), topPanelContents.RectTransform, Anchor.TopLeft) { RelativeOffset = new Vector2(0.15f, 0.1f) }, TextManager.Get("spriteeditor.saveselectedsprites")) @@ -125,7 +126,7 @@ namespace Barotrauma return SaveSprites(selectedSprites); } }; - new GUIButton(new RectTransform(new Vector2(0.12f, 0.4f), topPanelContents.RectTransform, Anchor.BottomLeft) + new GUIButton(new RectTransform(new Vector2(0.14f, 0.4f), topPanelContents.RectTransform, Anchor.BottomLeft) { RelativeOffset = new Vector2(0.15f, 0.1f) }, TextManager.Get("spriteeditor.saveallsprites")) @@ -135,11 +136,14 @@ namespace Barotrauma return SaveSprites(loadedSprites); } }; + + GUITextBlock.AutoScaleAndNormalize(topPanelContents.Children.Where(c => c is GUIButton).Select(c => ((GUIButton)c).TextBlock)); + new GUITextBlock(new RectTransform(new Vector2(0.2f, 0.2f), topPanelContents.RectTransform, Anchor.TopCenter, Pivot.CenterRight) { RelativeOffset = new Vector2(0, 0.3f) }, TextManager.Get("spriteeditor.zoom")); zoomBar = new GUIScrollBar(new RectTransform(new Vector2(0.2f, 0.35f), topPanelContents.RectTransform, Anchor.TopCenter, Pivot.CenterRight) { RelativeOffset = new Vector2(0.05f, 0.3f) - }, barSize: 0.1f) + }, style: "GUISlider", barSize: 0.1f) { BarScroll = GetBarScrollValue(), Step = 0.01f, @@ -184,8 +188,7 @@ namespace Barotrauma leftPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f - topPanel.RectTransform.RelativeSize.Y), Frame.RectTransform, Anchor.BottomLeft) { MinSize = new Point(150, 0) }, style: "GUIFrameLeft"); - var paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), leftPanel.RectTransform, Anchor.CenterLeft) - { RelativeOffset = new Vector2(0.02f, 0.0f) }) + var paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), leftPanel.RectTransform, Anchor.Center)) { RelativeSpacing = 0.01f, Stretch = true }; var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true) @@ -194,12 +197,8 @@ namespace Barotrauma UserData = "filterarea" }; filterTexturesLabel = new GUITextBlock(new RectTransform(Vector2.One, filterArea.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.Font) { IgnoreLayoutGroups = true }; ; - filterTexturesBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font); + filterTexturesBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font, createClearButton: true); filterTexturesBox.OnTextChanged += (textBox, text) => { FilterTextures(text); return true; }; - new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), filterArea.RectTransform) { MinSize = new Point(20, 0) }, "x") - { - OnClicked = (btn, userdata) => { FilterTextures(""); filterTexturesBox.Text = ""; filterTexturesBox.Flash(Color.White); return true; } - }; textureList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedLeftPanel.RectTransform)) { @@ -230,7 +229,7 @@ namespace Barotrauma }; rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f - topPanel.RectTransform.RelativeSize.Y), Frame.RectTransform, Anchor.BottomRight) { MinSize = new Point(150, 0) }, style: "GUIFrameRight"); - var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.02f, 0.0f) }) + var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.01f @@ -242,12 +241,8 @@ namespace Barotrauma UserData = "filterarea" }; filterSpritesLabel = new GUITextBlock(new RectTransform(Vector2.One, filterArea.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.Font) { IgnoreLayoutGroups = true }; - filterSpritesBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font); + filterSpritesBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font, createClearButton: true); filterSpritesBox.OnTextChanged += (textBox, text) => { FilterSprites(text); return true; }; - new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), filterArea.RectTransform) { MinSize = new Point(20, 0) }, "x") - { - OnClicked = (btn, userdata) => { FilterSprites(""); filterSpritesBox.Text = ""; filterSpritesBox.Flash(Color.White); return true; } - }; spriteList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedRightPanel.RectTransform)) { @@ -301,12 +296,12 @@ namespace Barotrauma switch (i) { case 0: - colorLabel.TextColor = Color.Red; + colorLabel.TextColor = GUI.Style.Red; numberInput.IntValue = backgroundColor.R; numberInput.OnValueChanged += (numInput) => backgroundColor.R = (byte)(numInput.IntValue); break; case 1: - colorLabel.TextColor = Color.LightGreen; + colorLabel.TextColor = GUI.Style.Green; numberInput.IntValue = backgroundColor.G; numberInput.OnValueChanged += (numInput) => backgroundColor.G = (byte)(numInput.IntValue); break; @@ -401,6 +396,16 @@ namespace Barotrauma if (element == null) { continue; } element.SetAttributeValue("sourcerect", XMLExtensions.RectToString(sprite.SourceRect)); element.SetAttributeValue("origin", XMLExtensions.Vector2ToString(sprite.RelativeOrigin)); + + /*if (element.Attribute("slice") != null) + { + Rectangle slice = new Rectangle( + sprite.SourceRect.X + 5, + sprite.SourceRect.Y + 5, + sprite.SourceRect.Right - 5, + sprite.SourceRect.Bottom - 5); + element.SetAttributeValue("slice", XMLExtensions.RectToString(slice)); + }*/ docsToSave.Add(element.Document); } xmlPathText.Text = TextManager.Get("spriteeditor.allchangessavedto"); @@ -410,7 +415,7 @@ namespace Barotrauma xmlPathText.Text += "\n" + xmlPath; doc.Save(xmlPath); } - xmlPathText.TextColor = Color.LightGreen; + xmlPathText.TextColor = GUI.Style.Green; return true; } #endregion @@ -436,7 +441,7 @@ namespace Barotrauma // Select rects with the mouse if (Widget.selectedWidgets.None() || Widget.EnableMultiSelect) { - if (selectedTexture != null) + if (selectedTexture != null && GUI.MouseOn == null) { foreach (Sprite sprite in loadedSprites) { @@ -449,6 +454,8 @@ namespace Barotrauma spriteList.Select(sprite, autoScroll: false); UpdateScrollBar(spriteList); UpdateScrollBar(textureList); + // Release the keyboard so that we can nudge the source rects + GUI.KeyboardDispatcher.Subscriber = null; } } } @@ -471,21 +478,128 @@ namespace Barotrauma } if (GUI.KeyboardDispatcher.Subscriber == null) { - Point moveAmount = Point.Zero; - if (PlayerInput.KeyHit(Keys.Left)) { moveAmount.X--; } - if (PlayerInput.KeyHit(Keys.Right)) { moveAmount.X++; } - if (PlayerInput.KeyHit(Keys.Up)) { moveAmount.Y--; } - if (PlayerInput.KeyHit(Keys.Down)) { moveAmount.Y++; } - if (moveAmount != Point.Zero) + if (PlayerInput.KeyHit(Keys.Left)) { + Nudge(Keys.Left); + } + if (PlayerInput.KeyHit(Keys.Right)) + { + Nudge(Keys.Right); + } + if (PlayerInput.KeyHit(Keys.Down)) + { + Nudge(Keys.Down); + } + if (PlayerInput.KeyHit(Keys.Up)) + { + Nudge(Keys.Up); + } + if (PlayerInput.KeyDown(Keys.Left)) + { + holdTimer += deltaTime; + if (holdTimer > holdTime) + { + Nudge(Keys.Left); + } + } + else if (PlayerInput.KeyDown(Keys.Right)) + { + holdTimer += deltaTime; + if (holdTimer > holdTime) + { + Nudge(Keys.Right); + } + } + else if (PlayerInput.KeyDown(Keys.Down)) + { + holdTimer += deltaTime; + if (holdTimer > holdTime) + { + Nudge(Keys.Down); + } + } + else if (PlayerInput.KeyDown(Keys.Up)) + { + holdTimer += deltaTime; + if (holdTimer > holdTime) + { + Nudge(Keys.Up); + } + } + else + { + holdTimer = 0; + } + } + } + + private double holdTimer; + private readonly float holdTime = 0.2f; + private void Nudge(Keys key) + { + switch (key) + { + case Keys.Left: foreach (var sprite in selectedSprites) { var newRect = sprite.SourceRect; - newRect.Location += moveAmount; + if (PlayerInput.KeyDown(Keys.LeftControl)) + { + newRect.Width--; + } + else + { + newRect.X--; + } UpdateSourceRect(sprite, newRect); } - } - } + break; + case Keys.Right: + foreach (var sprite in selectedSprites) + { + var newRect = sprite.SourceRect; + if (PlayerInput.KeyDown(Keys.LeftControl)) + { + newRect.Width++; + } + else + { + newRect.X++; + } + UpdateSourceRect(sprite, newRect); + } + break; + case Keys.Down: + foreach (var sprite in selectedSprites) + { + var newRect = sprite.SourceRect; + if (PlayerInput.KeyDown(Keys.LeftControl)) + { + newRect.Height++; + } + else + { + newRect.Y++; + } + UpdateSourceRect(sprite, newRect); + } + break; + case Keys.Up: + foreach (var sprite in selectedSprites) + { + var newRect = sprite.SourceRect; + if (PlayerInput.KeyDown(Keys.LeftControl)) + { + newRect.Height--; + } + else + { + newRect.Y--; + } + UpdateSourceRect(sprite, newRect); + } + break; + } } public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch) @@ -535,7 +649,7 @@ namespace Barotrauma (int)(sprite.SourceRect.Height * zoom)); bool isSelected = selectedSprites.Contains(sprite); - GUI.DrawRectangle(spriteBatch, sourceRect, isSelected ? Color.Yellow : Color.Red * 0.5f, thickness: isSelected ? 2 : 1); + GUI.DrawRectangle(spriteBatch, sourceRect, isSelected ? GUI.Style.Orange : GUI.Style.Red * 0.5f, thickness: isSelected ? 2 : 1); string id = sprite.ID; if (!string.IsNullOrEmpty(id)) @@ -546,12 +660,12 @@ namespace Barotrauma Vector2 GetBottomRight() => new Vector2(GetTopRight().X, GetTopRight().Y + sprite.SourceRect.Height); var originWidget = GetWidget($"{id}_origin", sprite, widgetSize, Widget.Shape.Cross, initMethod: w => { - w.tooltip = originLabel + sprite.RelativeOrigin.FormatDoubleDecimal(); + w.tooltip = TextManager.AddPunctuation(':', originLabel, sprite.RelativeOrigin.FormatDoubleDecimal()); w.MouseHeld += dTime => { w.DrawPos = PlayerInput.MousePosition.Clamp(textureRect.Location.ToVector2() + GetTopLeft() * zoom, textureRect.Location.ToVector2() + GetBottomRight() * zoom); sprite.Origin = (w.DrawPos - textureRect.Location.ToVector2() - sprite.SourceRect.Location.ToVector2() * zoom) / zoom; - w.tooltip = originLabel + sprite.RelativeOrigin.FormatDoubleDecimal(); + w.tooltip = TextManager.AddPunctuation(':', originLabel, sprite.RelativeOrigin.FormatDoubleDecimal()); }; w.refresh = () => w.DrawPos = (textureRect.Location.ToVector2() + (sprite.Origin + sprite.SourceRect.Location.ToVector2()) * zoom) @@ -578,7 +692,7 @@ namespace Barotrauma }); var sizeWidget = GetWidget($"{id}_size", sprite, widgetSize, Widget.Shape.Rectangle, initMethod: w => { - w.tooltip = sizeLabel + sprite.SourceRect.Size; + w.tooltip = TextManager.AddPunctuation(':', sizeLabel, sprite.SourceRect.Size.ToString()); w.MouseHeld += dTime => { w.DrawPos = (drawGrid && snapToGrid) ? @@ -593,10 +707,13 @@ namespace Barotrauma // TODO: cache the sprite name? textBox.Text = GetSpriteName(sprite) + " " + sprite.SourceRect; } - w.tooltip = sizeLabel + sprite.SourceRect.Size; + w.tooltip = TextManager.AddPunctuation(':', sizeLabel, sprite.SourceRect.Size.ToString()); }; w.refresh = () => w.DrawPos = textureRect.Location.ToVector2() + new Vector2(sprite.SourceRect.Right, sprite.SourceRect.Bottom) * zoom; }); + originWidget.MouseDown += () => GUI.KeyboardDispatcher.Subscriber = null; + positionWidget.MouseDown += () => GUI.KeyboardDispatcher.Subscriber = null; + sizeWidget.MouseDown += () => GUI.KeyboardDispatcher.Subscriber = null; if (isSelected) { positionWidget.Draw(spriteBatch, (float)deltaTime); @@ -822,7 +939,6 @@ namespace Barotrauma new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), textureList.Content.RectTransform) { MinSize = new Point(0, 20) }, Path.GetFileName(sprite.FilePath)) { - Padding = Vector4.Zero, ToolTip = sprite.FilePath, UserData = sprite.Texture }; @@ -834,9 +950,9 @@ namespace Barotrauma //foreach (Sprite sprite in loadedSprites.OrderBy(s => GetSpriteName(s))) foreach (Sprite sprite in loadedSprites.OrderBy(s => s.SourceElement.GetAttributeString("texture", string.Empty))) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), spriteList.Content.RectTransform) { MinSize = new Point(0, 20) }, GetSpriteName(sprite) + " " + sprite.SourceRect) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), spriteList.Content.RectTransform) { MinSize = new Point(0, 20) }, + GetSpriteName(sprite) + " (" + sprite.SourceRect.X + ", " + sprite.SourceRect.Y + ", " + sprite.SourceRect.Width + ", " + sprite.SourceRect.Height + ")") { - Padding = Vector4.Zero, UserData = sprite }; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SteamWorkshopScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SteamWorkshopScreen.cs index bc56d6ebf..f49c37cd9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SteamWorkshopScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SteamWorkshopScreen.cs @@ -26,12 +26,10 @@ namespace Barotrauma //listbox that shows the files included in the item being created private GUIListBox createItemFileList; - private GUIComponent buttonContainer; - - private List tabButtons = new List(); + private readonly List tabButtons = new List(); private readonly HashSet pendingPreviewImageDownloads = new HashSet(); - private Dictionary itemPreviewSprites = new Dictionary(); + private readonly Dictionary itemPreviewSprites = new Dictionary(); private enum Tab { @@ -40,7 +38,7 @@ namespace Barotrauma Publish } - private GUIFrame[] tabs; + private GUIComponent[] tabs; private ContentPackage itemContentPackage; private Steamworks.Ugc.Editor? itemEditor; @@ -54,50 +52,63 @@ namespace Barotrauma public SteamWorkshopScreen() { - GameMain.Instance.OnResolutionChanged += OnResolutionChanged; - - tabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length]; - - menu = new GUIFrame(new RectTransform(new Vector2(0.85f, 0.85f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) }); - - var container = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.85f), menu.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.05f) }) { Stretch = true }; - - var tabContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.7f), container.RectTransform), style: "InnerFrame"); - - var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), tabContainer.RectTransform, Anchor.TopRight, Pivot.BottomRight), - isHorizontal: true) - { - RelativeSpacing = 0.01f, - Stretch = true - }; + GameMain.Instance.OnResolutionChanged += CreateUI; + CreateUI(); + } + + private void CreateUI() + { + tabs = new GUIComponent[Enum.GetValues(typeof(Tab)).Length]; + menu = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), GUI.Canvas, Anchor.Center) { MinSize = new Point(GameMain.GraphicsHeight, 0) }); + var container = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), menu.RectTransform, Anchor.Center)) { Stretch = true }; + var topButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.03f), container.RectTransform), isHorizontal: true); + foreach (Tab tab in Enum.GetValues(typeof(Tab))) { - GUIButton tabButton = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), tabButtonHolder.RectTransform), + GUIButton tabButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), topButtonContainer.RectTransform), TextManager.Get(tab.ToString() + "Tab"), style: "GUITabButton") { UserData = tab, - OnClicked = (btn, userData) => + OnClicked = (btn, userData) => { SelectTab((Tab)userData); return true; } }; tabButtons.Add(tabButton); } + topButtonContainer.RectTransform.MinSize = new Point(0, topButtonContainer.RectTransform.Children.Max(c => c.MinSize.Y)); + topButtonContainer.RectTransform.MaxSize = new Point(int.MaxValue, topButtonContainer.RectTransform.MinSize.Y); + + var tabContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.7f), container.RectTransform), style: "InnerFrame"); + + var bottomButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), container.RectTransform), isHorizontal: true); + GUIButton backButton = new GUIButton(new RectTransform(new Vector2(0.1f, 0.9f), bottomButtonContainer.RectTransform) { MinSize = new Point(150, 0) }, + TextManager.Get("Back")) + { + OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu + }; + backButton.SelectedColor = backButton.Color; + topButtonContainer.RectTransform.MinSize = new Point(0, backButton.RectTransform.MinSize.Y); + topButtonContainer.RectTransform.MaxSize = new Point(int.MaxValue, backButton.RectTransform.MinSize.Y); //------------------------------------------------------------------------------- //Subscribed Mods tab //------------------------------------------------------------------------------- - tabs[(int)Tab.Mods] = new GUIFrame(new RectTransform(Vector2.One, tabContainer.RectTransform, Anchor.Center), style: null); - - var modsContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), tabs[(int)Tab.Mods].RectTransform)) + tabs[(int)Tab.Mods] = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), tabContainer.RectTransform, Anchor.Center), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.02f }; - subscribedItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.7f), modsContainer.RectTransform)) + var modsContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), tabs[(int)Tab.Mods].RectTransform)) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + + subscribedItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), modsContainer.RectTransform)) { ScrollBarVisible = true, OnSelected = (GUIComponent component, object userdata) => @@ -108,21 +119,25 @@ namespace Barotrauma } }; - modsPreviewFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), tabs[(int)Tab.Mods].RectTransform, Anchor.TopRight), style: "InnerFrame"); + modsPreviewFrame = new GUIFrame(new RectTransform(new Vector2(0.6f, 1.0f), tabs[(int)Tab.Mods].RectTransform, Anchor.TopRight), style: null); //------------------------------------------------------------------------------- //Popular Mods tab //------------------------------------------------------------------------------- - tabs[(int)Tab.Browse] = new GUIFrame(new RectTransform(Vector2.One, tabContainer.RectTransform, Anchor.Center), style: null); - - var listContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), tabs[(int)Tab.Browse].RectTransform)) + tabs[(int)Tab.Browse] = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), tabContainer.RectTransform, Anchor.Center), isHorizontal: true) { - RelativeSpacing = 0.01f, - Stretch = true + Stretch = true, + RelativeSpacing = 0.02f }; - topItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), listContainer.RectTransform)) + var listContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), tabs[(int)Tab.Browse].RectTransform), childAnchor: Anchor.TopCenter) + { + Stretch = true, + RelativeSpacing = 0.02f + }; + + topItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.9f), listContainer.RectTransform)) { ScrollBarVisible = true, OnSelected = (GUIComponent component, object userdata) => @@ -132,13 +147,8 @@ namespace Barotrauma } }; - var findModsButtonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), listContainer.RectTransform), style: null); - new GUIButton(new RectTransform(new Vector2(1.0f, 0.9f), findModsButtonContainer.RectTransform, Anchor.Center), TextManager.Get("FindModsButton"), style: null) + new GUIButton(new RectTransform(new Vector2(1.0f, 0.02f), listContainer.RectTransform), TextManager.Get("FindModsButton"), style: "GUIButtonSmall") { - Color = new Color(38, 86, 38, 75), - HoverColor = new Color(85, 203, 99, 50), - TextColor = Color.White, - OutlineColor = new Color(72, 124, 77, 255), OnClicked = (btn, userdata) => { SteamManager.OverlayCustomURL("steam://url/SteamWorkshopPage/" + SteamManager.AppID); @@ -146,13 +156,17 @@ namespace Barotrauma } }; - browsePreviewFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), tabs[(int)Tab.Browse].RectTransform, Anchor.TopRight), style: "InnerFrame"); + browsePreviewFrame = new GUIFrame(new RectTransform(new Vector2(0.6f, 1.0f), tabs[(int)Tab.Browse].RectTransform, Anchor.TopRight), style: null); //------------------------------------------------------------------------------- //Publish tab //------------------------------------------------------------------------------- - tabs[(int)Tab.Publish] = new GUIFrame(new RectTransform(Vector2.One, tabContainer.RectTransform, Anchor.Center), style: null); + tabs[(int)Tab.Publish] = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), tabContainer.RectTransform, Anchor.Center), isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.02f + }; var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), tabs[(int)Tab.Publish].RectTransform)) { @@ -160,7 +174,7 @@ namespace Barotrauma RelativeSpacing = 0.02f }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("PublishedWorkshopItems")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("PublishedWorkshopItems"), font: GUI.SubHeadingFont); publishedItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), leftColumn.RectTransform)) { OnSelected = (component, userdata) => @@ -178,7 +192,7 @@ namespace Barotrauma } }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("YourWorkshopItems")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("YourWorkshopItems"), font: GUI.SubHeadingFont); myItemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), leftColumn.RectTransform)) { OnSelected = (component, userdata) => @@ -198,25 +212,11 @@ namespace Barotrauma } }; - createItemFrame = new GUIFrame(new RectTransform(new Vector2(0.58f, 1.0f), tabs[(int)Tab.Publish].RectTransform, Anchor.TopRight), style: "InnerFrame"); - - buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.08f), container.RectTransform), childAnchor: Anchor.CenterLeft); - - GUIButton backButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.9f), buttonContainer.RectTransform) { MinSize = new Point(150, 0) }, - TextManager.Get("Back"), style: "GUIButtonLarge") - { - OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu - }; - backButton.SelectedColor = backButton.Color; + createItemFrame = new GUIFrame(new RectTransform(new Vector2(0.58f, 1.0f), tabs[(int)Tab.Publish].RectTransform, Anchor.TopRight), style: null); SelectTab(Tab.Mods); } - private void OnResolutionChanged() - { - menu.RectTransform.MinSize = new Point(GameMain.GraphicsHeight, 0); - } - public override void Select() { base.Select(); @@ -307,7 +307,8 @@ namespace Barotrauma private void RefreshMyItemList() { myItemList.ClearChildren(); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), myItemList.Content.RectTransform), TextManager.Get("WorkshopLabelSubmarines"), textAlignment: Alignment.Center, font: GUI.LargeFont) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), myItemList.Content.RectTransform), TextManager.Get("WorkshopLabelSubmarines"), + textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { CanBeFocused = false }; @@ -339,7 +340,8 @@ namespace Barotrauma CreateMyItemFrame(sub, myItemList); } - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), myItemList.Content.RectTransform), TextManager.Get("WorkshopLabelContentPackages"), textAlignment: Alignment.Center, font: GUI.LargeFont) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), myItemList.Content.RectTransform), TextManager.Get("WorkshopLabelContentPackages"), + textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { CanBeFocused = false }; @@ -495,7 +497,7 @@ namespace Barotrauma if (compatible.HasValue && !compatible.Value) { new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.3f), rightColumn.RectTransform), - TextManager.Get("WorkshopItemIncompatible"), textColor: Color.Red) + TextManager.Get("WorkshopItemIncompatible"), textColor: GUI.Style.Red) { ToolTip = TextManager.Get("WorkshopItemIncompatibleTooltip") }; @@ -515,10 +517,10 @@ namespace Barotrauma { if (enabledTickBox != null) { enabledTickBox.Enabled = false; } itemFrame.ToolTip = e.Message; - itemFrame.Color = Color.Red; - itemFrame.HoverColor = Color.Red; - itemFrame.SelectedColor = Color.Red; - titleText.TextColor = Color.Red; + itemFrame.Color = GUI.Style.Red; + itemFrame.HoverColor = GUI.Style.Red; + itemFrame.SelectedColor = GUI.Style.Red; + titleText.TextColor = GUI.Style.Red; if (item?.IsSubscribed ?? false) { @@ -568,13 +570,8 @@ namespace Barotrauma } else { - var downloadBtn = new GUIButton(new RectTransform(new Point((int)(32 * GUI.Scale)), rightColumn.RectTransform), "+", style: null) + var downloadBtn = new GUIButton(new RectTransform(new Point((int)(32 * GUI.Scale)), rightColumn.RectTransform), "", style: "GUIPlusButton") { - Font = GUI.LargeFont, - Color = new Color(38, 65, 86, 255), - HoverColor = new Color(85, 160, 203, 255), - TextColor = Color.White, - OutlineColor = new Color(72, 103, 124, 255), ToolTip = TextManager.Get("DownloadButton"), ForceUpperCase = true, UserData = item @@ -675,9 +672,7 @@ namespace Barotrauma itemPreviewSprites.Add(item?.PreviewImageUrl, newSprite); } - - var previewImage = listBox.Content.FindChild(item)?.GetChildByUserData("previewimage") as GUIImage; - if (previewImage != null) + if (listBox.Content.FindChild(item)?.GetChildByUserData("previewimage") is GUIImage previewImage) { previewImage.Sprite = newSprite; } @@ -714,11 +709,11 @@ namespace Barotrauma if (SteamManager.EnableWorkShopItem(item, false, out _)) { textBlock.Text = TextManager.Get("workshopiteminstalled"); - frame.Flash(Color.LightGreen); + frame.Flash(GUI.Style.Green); } else { - frame.Flash(Color.Red); + frame.Flash(GUI.Style.Red); } RefreshSubscribedItems(); }); @@ -738,14 +733,14 @@ namespace Barotrauma var updateButton = tickBox.Parent.FindChild("updatebutton"); - string errorMsg = ""; + string errorMsg; if (tickBox.Selected) { if (!SteamManager.EnableWorkShopItem(item, false, out errorMsg)) { tickBox.Visible = false; tickBox.Selected = false; - if (tickBox.Parent.GetChildByUserData("titletext") is GUITextBlock titleText) { titleText.TextColor = Color.Red; } + if (tickBox.Parent.GetChildByUserData("titletext") is GUITextBlock titleText) { titleText.TextColor = GUI.Style.Red; } } } else @@ -773,35 +768,26 @@ namespace Barotrauma { itemPreviewFrame.ClearChildren(); - if (item == null) return; + if (item == null) { return; } var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), itemPreviewFrame.RectTransform, Anchor.Center)) { Stretch = true, - UserData = item, - RelativeSpacing = 0.015f + UserData = item }; - //spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.005f), content.RectTransform), style: null); - - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), item?.Title, textAlignment: Alignment.TopLeft, font: GUI.LargeFont, wrap: true); - - var creatorHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform)) { IsHorizontal = true, Stretch = true }; - - new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.0f), creatorHolder.RectTransform), - TextManager.Get("WorkshopItemCreator"), textAlignment: Alignment.TopLeft, wrap: true); - - new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.0f), creatorHolder.RectTransform), - item?.Owner.Name, textAlignment: Alignment.TopRight, wrap: true); - - - new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), creatorHolder.RectTransform, Anchor.BottomRight), TextManager.Get("WorkshopShowItemInSteam"), style: null) + var headerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), content.RectTransform)) { - Color = new Color(38, 86, 38, 75), - HoverColor = new Color(85, 203, 99, 50), - TextColor = Color.White, - OutlineColor = new Color(72, 124, 77, 255), + Stretch = true + }; + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerArea.RectTransform), item?.Title, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont, wrap: true); + + new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.0f), headerArea.RectTransform), item?.Owner.Name, textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont); + + var btn = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), headerArea.RectTransform, Anchor.CenterRight), TextManager.Get("WorkshopShowItemInSteam"), style: "GUIButtonSmall") + { + IgnoreLayoutGroups = true, OnClicked = (btn, userdata) => { SteamManager.OverlayCustomURL("steam://url/CommunityFilePage/" + item?.Id); @@ -809,11 +795,20 @@ namespace Barotrauma } }; + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null); + + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.005f), content.RectTransform), style: "HorizontalLine"); + + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null); + + //--------------- + var centerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), isHorizontal: true) { Stretch = true, - RelativeSpacing = 0.01f, - Color = Color.Black * 0.9f + RelativeSpacing = 0.01f }; if (itemPreviewSprites.ContainsKey(item?.PreviewImageUrl)) @@ -824,43 +819,33 @@ namespace Barotrauma { new GUIImage(new RectTransform(new Vector2(0.5f, 0.0f), centerArea.RectTransform), SteamManager.DefaultPreviewImage, scaleToFit: true); } - - var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), centerArea.RectTransform)) { ScrollBarVisible = true }; - //spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform) { MinSize = new Point(0, 5) }, style: null); - - string description = item?.Description; - description = ToolBox.RemoveBBCodeTags(description); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform), description, wrap: true) + var statsFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), centerArea.RectTransform), style: "GUIFrameListBox"); + var statsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f), statsFrame.RectTransform, Anchor.Center)) { - CanBeFocused = false + Stretch = true, + RelativeSpacing = 0.01f }; - //spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform) { MinSize = new Point(0, 5) }, style: null); - //score ------------------------------------- - var scoreContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) + var scoreContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), statsContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { + Stretch = true, RelativeSpacing = 0.02f }; - new GUITextBlock(new RectTransform(new Vector2(0.2f, 0.0f), scoreContainer.RectTransform), TextManager.Get("WorkshopItemScore")); + new GUITextBlock(new RectTransform(new Vector2(0.2f, 0.0f), scoreContainer.RectTransform), TextManager.Get("WorkshopItemScore"), font: GUI.SubHeadingFont); int starCount = (int)Math.Round((item?.Score ?? 0.0f) * 5); for (int i = 0; i < 5; i++) { new GUIImage(new RectTransform(new Point(scoreContainer.Rect.Height), scoreContainer.RectTransform), i < starCount ? "GUIStarIconBright" : "GUIStarIconDark"); } - new GUITextBlock(new RectTransform(new Vector2(0.2f, 0.0f), scoreContainer.RectTransform), TextManager.GetWithVariable("WorkshopItemVotes", "[votecount]", (item.Value.VotesUp + item.Value.VotesDown).ToString())); + new GUITextBlock(new RectTransform(new Vector2(0.2f, 0.0f), scoreContainer.RectTransform), + TextManager.GetWithVariable("WorkshopItemVotes", "[votecount]", (item.Value.VotesUp + item.Value.VotesDown).ToString()), + textAlignment: Alignment.CenterRight); - //tags ------------------------------------ - var tagContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) - { - Stretch = true, - RelativeSpacing = 0.05f - }; - new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), tagContainer.RectTransform), TextManager.Get("WorkshopItemTags")); + //tags ------------------------------------ + List tags = new List(); for (int i = 0; i < item?.Tags.Length && i < 5; i++) { @@ -871,31 +856,37 @@ namespace Barotrauma } if (tags.Count > 0) { - if (tags.Count == 1) + var tagContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), statsContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { - tagContainer.RectTransform.RelativeSize = new Vector2(0.7f, tagContainer.RectTransform.RelativeSize.Y); - } - new GUITextBlock(new RectTransform(new Vector2(tags.Count == 1 ? 0.5f : 0.8f, 1.0f), tagContainer.RectTransform, Anchor.TopRight), string.Join(", ", tags)) + Stretch = true, + RelativeSpacing = 0.05f, + CanBeFocused = true + }; + new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), tagContainer.RectTransform), TextManager.Get("WorkshopItemTags"), font: GUI.SubHeadingFont); + + var t = new GUITextBlock(new RectTransform(new Vector2(0.8f, 1.0f), tagContainer.RectTransform, Anchor.TopRight), string.Join(", ", tags), textAlignment: Alignment.CenterRight); + t.RectTransform.SizeChanged += () => { - AutoScale = true + t.TextScale = 1.0f; + t.AutoScale = true; }; } - var fileSize = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), content.RectTransform), TextManager.Get("WorkshopItemFileSize")); - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), fileSize.RectTransform, Anchor.TopRight), MathUtils.GetBytesReadable(item?.IsInstalled ?? false ? (long)item.Value.SizeBytes : item.Value.DownloadBytesDownloaded), textAlignment: Alignment.TopRight); + var fileSize = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), statsContent.RectTransform), TextManager.Get("WorkshopItemFileSize"), font: GUI.SubHeadingFont); + new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), fileSize.RectTransform, Anchor.TopRight), MathUtils.GetBytesReadable(item?.IsInstalled ?? false ? (long)item.Value.SizeBytes : item.Value.DownloadBytesDownloaded), textAlignment: Alignment.CenterRight); //var dateContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), isHorizontal: true); - var creationDate = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), content.RectTransform), TextManager.Get("WorkshopItemCreationDate")); - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), creationDate.RectTransform, Anchor.CenterRight), item?.Created.ToString("dd.MM.yyyy"), textAlignment: Alignment.TopRight); + var creationDate = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), statsContent.RectTransform), TextManager.Get("WorkshopItemCreationDate"), font: GUI.SubHeadingFont); + new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), creationDate.RectTransform, Anchor.CenterRight), item?.Created.ToString("dd.MM.yyyy"), textAlignment: Alignment.CenterRight); - var modificationDate = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), content.RectTransform), TextManager.Get("WorkshopItemModificationDate")); - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), modificationDate.RectTransform, Anchor.CenterRight), item?.Updated.ToString("dd.MM.yyyy"), textAlignment: Alignment.TopRight); + var modificationDate = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), statsContent.RectTransform), TextManager.Get("WorkshopItemModificationDate"), font: GUI.SubHeadingFont); + new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), modificationDate.RectTransform, Anchor.CenterRight), item?.Updated.ToString("dd.MM.yyyy"), textAlignment: Alignment.CenterRight); if (item?.IsSubscribed ?? false) { - var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform) { MinSize = new Point(0, 25) }, isHorizontal: true); - new GUIButton(new RectTransform(new Vector2(0.5f, 0.95f), buttonContainer.RectTransform), TextManager.Get("WorkshopItemUnsubscribe")) + var buttonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), statsContent.RectTransform), style: null); + var unsubscribeButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.95f), buttonContainer.RectTransform, Anchor.Center), TextManager.Get("WorkshopItemUnsubscribe"), style: "GUIButtonSmall") { UserData = item, OnClicked = (btn, userdata) => @@ -907,7 +898,26 @@ namespace Barotrauma return true; } }; + buttonContainer.RectTransform.MinSize = unsubscribeButton.RectTransform.MinSize; + statsContent.Recalculate(); } + + //------------------ + + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null); + + var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform)) { ScrollBarVisible = true }; + + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform) { MinSize = new Point(0, 5) }, style: null); + + string description = item?.Description; + description = ToolBox.RemoveBBCodeTags(description); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform), description, wrap: true) + { + CanBeFocused = false + }; } private void CreateWorkshopItem(Submarine sub) @@ -1021,7 +1031,7 @@ namespace Barotrauma return; } - var createItemContent = new GUILayoutGroup(new RectTransform(new Vector2(0.92f, 0.92f), createItemFrame.RectTransform, Anchor.Center)) + var createItemContent = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.98f), createItemFrame.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.02f @@ -1030,15 +1040,15 @@ namespace Barotrauma var topPanel = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.4f), createItemContent.RectTransform), isHorizontal: true) { Stretch = true, - RelativeSpacing = 0.05f + RelativeSpacing = 0.01f }; - var topLeftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 1.0f), topPanel.RectTransform)) + var topLeftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1.0f), topPanel.RectTransform)) { Stretch = true, RelativeSpacing = 0.02f }; - var topRightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 1.0f), topPanel.RectTransform)) + var topRightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1.0f), topPanel.RectTransform)) { Stretch = true, RelativeSpacing = 0.02f @@ -1046,17 +1056,18 @@ namespace Barotrauma // top right column -------------------------------------------------------------------------------------- - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemTitle")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemTitle"), font: GUI.SubHeadingFont); var titleBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.15f), topRightColumn.RectTransform), itemEditor?.Title); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemDescription")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemDescription"), font: GUI.SubHeadingFont); var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), topRightColumn.RectTransform)); - var descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform), itemEditor?.Description, textAlignment: Alignment.TopLeft, font: GUI.SmallFont, wrap: true); + var descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform), itemEditor?.Description, + textAlignment: Alignment.TopLeft, style: "GUITextBoxNoBorder", font: GUI.SmallFont, wrap: true); descriptionBox.OnTextChanged += (textBox, text) => { Vector2 textSize = textBox.Font.MeasureString(descriptionBox.WrappedText); - textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(descriptionContainer.Rect.Height, (int)textSize.Y + 10)); + textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(descriptionContainer.Content.Rect.Height, (int)textSize.Y + 10)); descriptionContainer.UpdateScrollBarSize(); descriptionContainer.BarScroll = 1.0f; itemEditor = itemEditor?.WithDescription(text); @@ -1064,7 +1075,7 @@ namespace Barotrauma }; descriptionContainer.RectTransform.SizeChanged += () => { descriptionBox.Text = descriptionBox.Text; }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemTags")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topRightColumn.RectTransform), TextManager.Get("WorkshopItemTags"), font: GUI.SubHeadingFont); var tagHolder = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.17f), topRightColumn.RectTransform) { MinSize = new Point(0, 50) }, isHorizontal: true) { Spacing = 5 @@ -1083,15 +1094,13 @@ namespace Barotrauma foreach (string tag in availableTags) { - var tagBtn = new GUIButton(new RectTransform(new Vector2(0.25f, 0.8f), tagHolder.Content.RectTransform, anchor: Anchor.CenterLeft), tag.CapitaliseFirstInvariant()); + var tagBtn = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tagHolder.Content.RectTransform, anchor: Anchor.CenterLeft), + tag.CapitaliseFirstInvariant(), style: "GUIButtonRound"); tagBtn.TextBlock.AutoScale = true; - tagBtn.Color *= 0.5f; - tagBtn.SelectedColor = Color.LightGreen; - tagBtn.HoverColor = Color.Lerp(tagBtn.HoverColor, Color.LightGreen, 0.5f); tagBtn.Selected = itemEditor?.Tags?.Any(t => t.ToLowerInvariant() == tag) ?? false; Color defaultTextColor = tagBtn.TextColor; - tagBtn.TextColor = tagBtn.Selected ? Color.LightGreen : defaultTextColor; + tagBtn.TextColor = tagBtn.Selected ? GUI.Style.Green : defaultTextColor; tagBtn.OnClicked = (btn, userdata) => { @@ -1099,7 +1108,7 @@ namespace Barotrauma { if (!(itemEditor?.Tags?.Any(t => t.ToLowerInvariant() == tag) ?? false)) { itemEditor = itemEditor?.WithTag(tagBtn.Text); } tagBtn.Selected = true; - tagBtn.TextColor = Color.LightGreen; + tagBtn.TextColor = GUI.Style.Green; } else { @@ -1114,10 +1123,10 @@ namespace Barotrauma // top left column -------------------------------------------------------------------------------------- - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemPreviewImage")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemPreviewImage"), font: GUI.SubHeadingFont); var previewIcon = new GUIImage(new RectTransform(new Vector2(1.0f, 0.7f), topLeftColumn.RectTransform), SteamManager.DefaultPreviewImage, scaleToFit: true); - new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemBrowse")) + new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), topLeftColumn.RectTransform), TextManager.Get("WorkshopItemBrowse"), style: "GUIButtonSmall") { OnClicked = (btn, userdata) => { @@ -1190,8 +1199,8 @@ namespace Barotrauma //spacing new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), createItemContent.RectTransform), style: null); - var fileListTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), createItemContent.RectTransform), TextManager.Get("WorkshopItemFiles")); - new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), fileListTitle.RectTransform, Anchor.CenterRight), TextManager.Get("WorkshopItemShowFolder")) + var fileListTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), createItemContent.RectTransform), TextManager.Get("WorkshopItemFiles"), font: GUI.SubHeadingFont); + new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), fileListTitle.RectTransform, Anchor.CenterRight), TextManager.Get("WorkshopItemShowFolder"), style: "GUIButtonSmall") { IgnoreLayoutGroups = true, OnClicked = (btn, userdata) => { ToolBox.OpenFileWithShell(Path.GetFullPath(Path.GetDirectoryName(itemContentPackage.Path))); return true; } @@ -1201,10 +1210,10 @@ namespace Barotrauma var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), createItemContent.RectTransform), isHorizontal: true) { - RelativeSpacing = 0.05f + RelativeSpacing = 0.02f }; - new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonContainer.RectTransform, Anchor.TopRight), TextManager.Get("WorkshopItemRefreshFileList")) + new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform, Anchor.TopRight), TextManager.Get("WorkshopItemRefreshFileList"), style: "GUIButtonSmall") { ToolTip = TextManager.Get("WorkshopItemRefreshFileListTooltip"), OnClicked = (btn, userdata) => @@ -1214,7 +1223,7 @@ namespace Barotrauma return true; } }; - new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonContainer.RectTransform, Anchor.TopRight), TextManager.Get("WorkshopItemAddFiles")) + new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform, Anchor.TopRight), TextManager.Get("WorkshopItemAddFiles"), style: "GUIButtonSmall") { OnClicked = (btn, userdata) => { @@ -1236,58 +1245,56 @@ namespace Barotrauma } }; - var bottomRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), createItemContent.RectTransform), isHorizontal: true); //the item has been already published if it has a non-zero ID -> allow adding a changenote if ((itemEditor?.FileId ?? 0) > 0) { + var bottomRow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), createItemContent.RectTransform), isHorizontal: true); var changeNoteLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 1.0f), bottomRow.RectTransform)); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), changeNoteLayout.RectTransform), TextManager.Get("WorkshopItemChangenote")) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), changeNoteLayout.RectTransform), TextManager.Get("WorkshopItemChangenote"), font: GUI.SubHeadingFont) { ToolTip = TextManager.Get("WorkshopItemChangenoteTooltip") }; - var changenoteContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), changeNoteLayout.RectTransform)); - var changenoteBox = new GUITextBox(new RectTransform(Vector2.One, changenoteContainer.Content.RectTransform), "", textAlignment: Alignment.TopLeft, wrap: true) + var changenoteBox = new GUITextBox(new RectTransform(Vector2.One, changenoteContainer.Content.RectTransform), "", + textAlignment: Alignment.TopLeft, style: "GUITextBoxNoBorder", wrap: true) { ToolTip = TextManager.Get("WorkshopItemChangenoteTooltip") }; changenoteBox.OnTextChanged += (textBox, text) => { Vector2 textSize = textBox.Font.MeasureString(changenoteBox.WrappedText); - textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(changenoteContainer.Rect.Height, (int)textSize.Y + 10)); + textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(changenoteContainer.Content.Rect.Height, (int)textSize.Y + 10)); changenoteContainer.UpdateScrollBarSize(); changenoteContainer.BarScroll = 1.0f; itemEditor = itemEditor?.WithChangeLog(text); return true; }; } - else - { - //spacing - new GUIFrame(new RectTransform(new Vector2(0.7f, 1.0f), bottomRow.RectTransform), style: null); - } - - var visibilityLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1.0f), bottomRow.RectTransform)); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), visibilityLayout.RectTransform), TextManager.Get("WorkshopItemVisibility")) + var bottomButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.08f), createItemContent.RectTransform), + isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + RelativeSpacing = 0.03f + }; + + var visibilityLabel = new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), bottomButtonContainer.RectTransform), TextManager.Get("WorkshopItemVisibility"), + textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { ToolTip = TextManager.Get("WorkshopItemVisibilityTooltip") }; + visibilityLabel.RectTransform.MaxSize = new Point((int)(visibilityLabel.TextSize.X * 1.1f), 0); - var visibilityListBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), visibilityLayout.RectTransform)); + var visibilityDropDown = new GUIDropDown(new RectTransform(new Vector2(0.2f, 1.0f), bottomButtonContainer.RectTransform)); foreach (VisibilityType visibilityType in Enum.GetValues(typeof(VisibilityType))) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), visibilityListBox.Content.RectTransform), TextManager.Get("WorkshopItemVisibility."+visibilityType.ToString())) - { - UserData = visibilityType - }; + visibilityDropDown.AddItem(TextManager.Get("WorkshopItemVisibility." + visibilityType), visibilityType); } - visibilityListBox.Select(itemEditor.Value.IsPublic ? VisibilityType.Public : - itemEditor.Value.IsFriendsOnly ? VisibilityType.FriendsOnly : - VisibilityType.Private); - visibilityListBox.OnSelected = (lb, ud) => + visibilityDropDown.SelectItem(itemEditor.Value.IsPublic ? VisibilityType.Public : + itemEditor.Value.IsFriendsOnly ? VisibilityType.FriendsOnly : + VisibilityType.Private); + visibilityDropDown.OnSelected = (c, ud) => { if (!(ud is VisibilityType visibilityType)) { return false; } switch (visibilityType) @@ -1306,18 +1313,13 @@ namespace Barotrauma return true; }; - var bottomButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.08f), createItemContent.RectTransform), isHorizontal: true) - { - RelativeSpacing = 0.05f - }; - if ((itemEditor?.FileId ?? 0) > 0) { - new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), bottomButtonContainer.RectTransform), - TextManager.Get("WorkshopItemDelete"), style: "GUIButtonLarge") + new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), bottomButtonContainer.RectTransform), + TextManager.Get("WorkshopItemDelete"), style: "GUIButtonSmall") { ToolTip = TextManager.Get("WorkshopItemDeleteTooltip"), - TextColor = Color.Red, + TextColor = GUI.Style.Red, OnClicked = (btn, userData) => { if (itemEditor == null) { return false; } @@ -1350,7 +1352,7 @@ namespace Barotrauma }; } var publishBtn = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), bottomButtonContainer.RectTransform, Anchor.CenterRight), - TextManager.Get((itemEditor?.FileId ?? 0) > 0 ? "WorkshopItemUpdate" : "WorkshopItemPublish"), style: "GUIButtonLarge") + TextManager.Get((itemEditor?.FileId ?? 0) > 0 ? "WorkshopItemUpdate" : "WorkshopItemPublish")) { IgnoreLayoutGroups = true, ToolTip = TextManager.Get("WorkshopItemPublishTooltip"), @@ -1360,17 +1362,17 @@ namespace Barotrauma itemEditor = itemEditor?.WithDescription(descriptionBox.Text); if (string.IsNullOrWhiteSpace(itemEditor?.Title)) { - titleBox.Flash(Color.Red); + titleBox.Flash(GUI.Style.Red); return false; } if (string.IsNullOrWhiteSpace(itemEditor?.Description)) { - descriptionBox.Flash(Color.Red); + descriptionBox.Flash(GUI.Style.Red); return false; } if (createItemFileList.Content.CountChildren == 0) { - createItemFileList.Flash(Color.Red); + createItemFileList.Flash(GUI.Style.Red); } if (!itemContentPackage.CheckErrors(out List errorMessages)) @@ -1472,6 +1474,7 @@ namespace Barotrauma var fileFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.12f), createItemFileList.Content.RectTransform) { MinSize = new Point(0, 20) }, style: "ListBoxElement") { + CanBeFocused = false, UserData = contentFile }; @@ -1494,12 +1497,12 @@ namespace Barotrauma }; if (!fileExists) { - nameText.TextColor = Color.Red; + nameText.TextColor = GUI.Style.Red; tickBox.ToolTip = TextManager.Get("WorkshopItemFileNotFound"); } else if (illegalPath && !ContentPackage.List.Any(cp => cp.Files.Any(f => Path.GetFullPath(f.Path) == Path.GetFullPath(contentFile.Path)))) { - nameText.TextColor = Color.Red; + nameText.TextColor = GUI.Style.Red; tickBox.ToolTip = TextManager.Get("WorkshopItemIllegalPath"); } @@ -1521,7 +1524,7 @@ namespace Barotrauma return true; }; - new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), content.RectTransform), TextManager.Get("Delete")) + new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), content.RectTransform), TextManager.Get("Delete"), style: "GUIButtonSmall") { OnClicked = (btn, userdata) => { @@ -1534,7 +1537,8 @@ namespace Barotrauma }; content.Recalculate(); - tickBox.RectTransform.NonScaledSize = new Point(content.Rect.Height); + fileFrame.RectTransform.MinSize = + new Point(0, (int)(content.RectTransform.Children.Max(c => c.MinSize.Y) / content.RectTransform.RelativeSize.Y)); nameText.Text = ToolBox.LimitString(nameText.Text, nameText.Font, maxWidth: nameText.Rect.Width); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 0dc69bdea..255c2a553 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -1,36 +1,42 @@ using Barotrauma.Extensions; using Barotrauma.Items.Components; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; -using System.ComponentModel; using System.IO; using System.Linq; -using System.Reflection; using System.Xml.Linq; namespace Barotrauma { class SubEditorScreen : Screen { - private static string[] crewExperienceLevels = new string[] + private static readonly string[] crewExperienceLevels = new string[] { "CrewExperienceLow", "CrewExperienceMid", "CrewExperienceHigh" }; + public enum Mode + { + Default, + Character, + Wiring + } + private readonly Point defaultPreviewImageSize = new Point(640, 368); - private Camera cam; + private readonly Camera cam; private Point screenResolution; private bool lightingEnabled; - public GUIComponent TopPanel, LeftPanel; + public GUIComponent TopPanel; + private GUIComponent showEntitiesPanel, entityCountPanel; + private List showEntitiesTickBoxes = new List(); private bool entityMenuOpen = true; private float entityMenuOpenState = 1.0f; @@ -43,18 +49,19 @@ namespace Barotrauma private GUITextBox nameBox, descriptionBox; - private List entityCategoryButtons = new List(); + private readonly List entityCategoryButtons = new List(); private GUIFrame hullVolumeFrame; private GUIFrame saveAssemblyFrame; const int PreviouslyUsedCount = 10; + private GUIFrame previouslyUsedPanel; private GUIListBox previouslyUsedList; private GUIDropDown linkedSubBox; - private GUITickBox characterModeTickBox, wiringModeTickBox; + private GUIRadioButtonGroup modeButtonGroup; //a Character used for picking up and manipulating items private Character dummyCharacter; @@ -69,20 +76,19 @@ namespace Barotrauma private GUIListBox contextMenu; - private Color primaryColor = new Color(12, 14, 15, 190); - private Color secondaryColor = new Color(12, 14, 15, 215); - private const int submarineNameLimit = 30; private GUITextBlock submarineNameCharacterCount; private const int submarineDescriptionLimit = 500; private GUITextBlock submarineDescriptionCharacterCount; + private Mode mode; + public override Camera Cam { get { return cam; } } - + public string GetSubName() { return (Submarine.MainSub == null) ? "" : Submarine.MainSub.Name; @@ -95,16 +101,6 @@ namespace Barotrauma return (Submarine.MainSub == null) ? "" : Submarine.MainSub.Description; } - private string GetItemCount() - { - return TextManager.AddPunctuation(':', TextManager.Get("Items"), Item.ItemList.Count.ToString()); - } - - private string GetStructureCount() - { - return TextManager.AddPunctuation(':', TextManager.Get("Structures"), (MapEntity.mapEntityList.Count - Item.ItemList.Count - Hull.hullList.Count - WayPoint.WayPointList.Count - Gap.GapList.Count).ToString()); - } - private string GetTotalHullVolume() { return TextManager.Get("TotalHullVolume") + ":\n" + Hull.hullList.Sum(h => h.Volume); @@ -139,14 +135,9 @@ namespace Barotrauma return retVal; } - private string GetPhysicsBodyCount() - { - return TextManager.AddPunctuation(':', TextManager.Get("PhysicsBodies"), GameMain.World.BodyList.Count.ToString()); - } + public bool CharacterMode { get { return mode == Mode.Character; } } - public bool CharacterMode { get; private set; } - - public bool WiringMode { get; private set; } + public bool WiringMode { get { return mode == Mode.Wiring; } } public SubEditorScreen() { @@ -160,12 +151,17 @@ namespace Barotrauma private void CreateUI() { - TopPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), GUI.Canvas) { MinSize = new Point(0, 35) }, "GUIFrameTop"); + TopPanel = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), GUI.Canvas) { MinSize = new Point(0, 35) }, "GUIFrameTop"); - GUIFrame paddedTopPanel = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.55f), TopPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, -0.1f) }, style: null); - - var button = new GUIButton(new RectTransform(new Vector2(0.07f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft), TextManager.Get("Back")) + GUILayoutGroup paddedTopPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.8f), TopPanel.RectTransform, Anchor.Center), + isHorizontal: true, childAnchor: Anchor.CenterLeft) { + RelativeSpacing = 0.005f + }; + + new GUIButton(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonToggleLeft") + { + ToolTip = TextManager.Get("back"), OnClicked = (b, d) => { var msgBox = new GUIMessageBox("", TextManager.Get("PauseMenuQuitVerificationEditor"), new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") }) @@ -188,8 +184,11 @@ namespace Barotrauma } }; - button = new GUIButton(new RectTransform(new Vector2(0.07f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.07f, 0.0f) }, TextManager.Get("OpenSubButton")) + new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), paddedTopPanel.RectTransform), style: "VerticalLine"); + + new GUIButton(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "OpenButton") { + ToolTip = TextManager.Get("OpenSubButton"), OnClicked = (GUIButton btn, object data) => { saveFrame = null; @@ -199,8 +198,11 @@ namespace Barotrauma } }; - button = new GUIButton(new RectTransform(new Vector2(0.07f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.14f, 0.0f) }, TextManager.Get("SaveSubButton")) + new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), paddedTopPanel.RectTransform), style: "VerticalLine"); + + new GUIButton(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "SaveButton") { + ToolTip = TextManager.Get("SaveSubButton"), OnClicked = (GUIButton btn, object data) => { loadFrame = null; @@ -210,24 +212,19 @@ namespace Barotrauma } }; - var nameLabel = new GUITextBlock(new RectTransform(new Vector2(0.1f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.21f, 0.0f) }, + new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), paddedTopPanel.RectTransform), style: "VerticalLine"); + + var nameLabel = new GUITextBlock(new RectTransform(new Vector2(0.1f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft), "", font: GUI.LargeFont, textAlignment: Alignment.CenterLeft) { TextGetter = GetSubName }; - var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), paddedTopPanel.RectTransform, Anchor.CenterRight), style: "GUINotificationButton") - { - OnClicked = (btn, userdata) => { GameMain.Instance.ShowEditorDisclaimer(); return true; } - }; - disclaimerBtn.RectTransform.MaxSize = new Point(disclaimerBtn.Rect.Height); - - linkedSubBox = new GUIDropDown(new RectTransform(new Vector2(0.15f, 0.9f), paddedTopPanel.RectTransform) { RelativeOffset = new Vector2(0.385f, 0.0f) }, + linkedSubBox = new GUIDropDown(new RectTransform(new Vector2(0.15f, 0.9f), paddedTopPanel.RectTransform), TextManager.Get("AddSubButton"), elementCount: 20) { ToolTip = TextManager.Get("AddSubToolTip") }; - foreach (Submarine sub in Submarine.SavedSubmarines) { linkedSubBox.AddItem(sub.Name, sub); @@ -239,240 +236,131 @@ namespace Barotrauma return true; }; - LeftPanel = new GUIFrame(new RectTransform(new Vector2(0.08f, 1.0f), GUI.Canvas) { MinSize = new Point(170, 0) }, style: null) { Color = primaryColor }; + new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), paddedTopPanel.RectTransform), style: "VerticalLine"); - GUILayoutGroup paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Point((int)(LeftPanel.Rect.Width), (int)(GameMain.GraphicsHeight - TopPanel.Rect.Height * 0.95f)), - LeftPanel.RectTransform, Anchor.Center)) - { - Stretch = true - }; + modeButtonGroup = new GUIRadioButtonGroup(); - //empty guiframe as a separator - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), paddedLeftPanel.RectTransform) { AbsoluteOffset = new Point(0, TopPanel.Rect.Height) }, style: null); - - var itemCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("Items"), font: GUI.SmallFont); - var itemCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), itemCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.TopRight); - itemCount.TextGetter = () => + var defaultModeTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "EditSubButton") { - itemCount.TextColor = ToolBox.GradientLerp(Item.ItemList.Count / 5000.0f, Color.LightGreen, Color.Yellow, Color.Red); - return Item.ItemList.Count.ToString(); - }; - - var structureCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("Structures"), font: GUI.SmallFont); - var structureCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), structureCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.TopRight); - structureCount.TextGetter = () => - { - int count = (MapEntity.mapEntityList.Count - Item.ItemList.Count - Hull.hullList.Count - WayPoint.WayPointList.Count - Gap.GapList.Count); - structureCount.TextColor = ToolBox.GradientLerp(count / 1000.0f, Color.LightGreen, Color.Yellow, Color.Red); - return count.ToString(); - }; - - var wallCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("Walls"), font: GUI.SmallFont); - var wallCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), wallCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.TopRight); - wallCount.TextGetter = () => - { - wallCount.TextColor = ToolBox.GradientLerp(Structure.WallList.Count / 500.0f, Color.LightGreen, Color.Yellow, Color.Red); - return Structure.WallList.Count.ToString(); - }; - - var lightCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("SubEditorLights"), font: GUI.SmallFont); - var lightCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), lightCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.TopRight); - lightCount.TextGetter = () => - { - int disabledItemLightCount = 0; - foreach (Item item in Item.ItemList) + ToolTip = TextManager.Get("SubEditorEditingMode"), + OnSelected = (GUITickBox tBox) => { - if (item.ParentInventory == null) { continue; } - disabledItemLightCount += item.GetComponents().Count(); - } - int count = GameMain.LightManager.Lights.Count() - disabledItemLightCount; - lightCount.TextColor = ToolBox.GradientLerp(count / 250.0f, Color.LightGreen, Color.Yellow, Color.Red); - return count.ToString(); - }; - var shadowCastingLightCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("SubEditorShadowCastingLights"), font: GUI.SmallFont, wrap: true); - var shadowCastingLightCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), shadowCastingLightCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.TopRight); - shadowCastingLightCount.TextGetter = () => - { - int disabledItemLightCount = 0; - foreach (Item item in Item.ItemList) - { - if (item.ParentInventory == null) { continue; } - disabledItemLightCount += item.GetComponents().Count(); - } - int count = GameMain.LightManager.Lights.Count(l => l.CastShadows) - disabledItemLightCount; - shadowCastingLightCount.TextColor = ToolBox.GradientLerp(count / 60.0f, Color.LightGreen, Color.Yellow, Color.Red); - return count.ToString(); - }; - GUITextBlock.AutoScaleAndNormalize(paddedLeftPanel.Children.Where(c => c is GUITextBlock).Cast()); - - hullVolumeFrame = new GUIFrame(new RectTransform(new Vector2(0.15f, 2.0f), TopPanel.RectTransform, Anchor.BottomLeft, Pivot.TopLeft, minSize: new Point(300, 85)) { AbsoluteOffset = new Point(LeftPanel.Rect.Width, 0) }, "GUIToolTip") - { - Visible = false - }; - GUITextBlock totalHullVolume = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), hullVolumeFrame.RectTransform), "", font: GUI.SmallFont) - { - TextGetter = GetTotalHullVolume - }; - GUITextBlock selectedHullVolume = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), hullVolumeFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.5f) }, "", font: GUI.SmallFont) - { - TextGetter = GetSelectedHullVolume - }; - - saveAssemblyFrame = new GUIFrame(new RectTransform(new Vector2(0.08f, 0.5f), TopPanel.RectTransform, Anchor.BottomLeft, Pivot.TopLeft) - { MinSize = new Point(200, 40), AbsoluteOffset = new Point(LeftPanel.Rect.Width + hullVolumeFrame.Rect.Width, 0) }, "InnerFrame") - { - Visible = false - }; - var saveAssemblyButton = new GUIButton(new RectTransform(new Vector2(0.9f, 0.8f), saveAssemblyFrame.RectTransform, Anchor.Center), TextManager.Get("SaveItemAssembly")); - saveAssemblyButton.TextBlock.AutoScale = true; - saveAssemblyButton.OnClicked += (btn, userdata) => - { - CreateSaveAssemblyScreen(); - return true; - }; - - - //Entity menu - //------------------------------------------------ - - EntityMenu = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth - LeftPanel.Rect.Width, (int)(359 * GUI.Scale)), GUI.Canvas, Anchor.BottomRight), style: null) { Color = primaryColor }; - - toggleEntityMenuButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.1f), EntityMenu.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { RelativeOffset = new Vector2(0.0f, -0.05f) }, - style: "GUIButtonVerticalArrow") - { - OnClicked = (btn, userdata) => - { - entityMenuOpen = !entityMenuOpen; - if (CharacterMode) SetCharacterMode(false); - if (WiringMode) SetWiringMode(false); - foreach (GUIComponent child in btn.Children) + if (tBox.Selected) { - child.SpriteEffects = entityMenuOpen ? SpriteEffects.None : SpriteEffects.FlipVertically; + SetMode(Mode.Default); } return true; } }; - var paddedTab = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), EntityMenu.RectTransform, Anchor.Center), style: null); - - var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedTab.RectTransform) { AbsoluteOffset = new Point(0, 10) }, isHorizontal: true) + var characterModeTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "CharacterModeButton") { - Color = secondaryColor, - Stretch = true, - UserData = "filterarea" - }; - - new GUITextBlock(new RectTransform(new Vector2(0.05f, 1.0f), filterArea.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.Font); - entityFilterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font); - entityFilterBox.OnTextChanged += (textBox, text) => { FilterEntities(text); return true; }; - var clearButton = new GUIButton(new RectTransform(new Vector2(0.02f, 1.0f), filterArea.RectTransform), "x") - { - OnClicked = (btn, userdata) => { ClearFilter(); entityFilterBox.Flash(Color.White); return true; } - }; - - var entityListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.85f), paddedTab.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.06f) }); - - var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), entityListHolder.RectTransform, Anchor.TopRight, Pivot.BottomRight), - isHorizontal: true) - { - RelativeSpacing = 0.01f, - Stretch = true - }; - - entityCategoryButtons.Clear(); - entityCategoryButtons.Add( - new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), tabButtonHolder.RectTransform), TextManager.Get("MapEntityCategory.All"), style: "GUITabButton") + ToolTip = TextManager.Get("CharacterModeButton") + '\n' + TextManager.Get("CharacterModeToolTip"), + OnSelected = (GUITickBox tBox) => { - OnClicked = (btn, userdata) => { entityCategoryButtons.ForEach(b => b.Selected = b == btn); ClearFilter(); return true; } - }); - - foreach (MapEntityCategory category in Enum.GetValues(typeof(MapEntityCategory))) - { - entityCategoryButtons.Add(new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), tabButtonHolder.RectTransform), - TextManager.Get("MapEntityCategory." + category.ToString()), style: "GUITabButton") - { - UserData = category, - OnClicked = (btn, userdata) => + if (tBox.Selected) { - entityMenuOpen = true; - OpenEntityMenu((MapEntityCategory)userdata); - return true; + SetMode(Mode.Character); } - }); - } - - foreach (GUIButton tabButton in entityCategoryButtons) - { - tabButton.TextBlock.RectTransform.SetPosition(Anchor.Center); - tabButton.TextBlock.RectTransform.RelativeSize = new Vector2(0.9f, 1.0f); - } - GUITextBlock.AutoScaleAndNormalize(entityCategoryButtons.Select(b => b.TextBlock)); - entityCategoryButtons.Last().TextBlock.RectTransform.SizeChanged += () => - { - GUITextBlock.AutoScaleAndNormalize(entityCategoryButtons.Select(b => b.TextBlock), defaultScale: 1.0f); - }; - - entityList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.9f), entityListHolder.RectTransform, Anchor.BottomCenter)) - { - OnSelected = SelectPrefab, - UseGridLayout = true, - CheckSelected = MapEntityPrefab.GetSelected - }; - - //empty guiframe as a separator - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), paddedLeftPanel.RectTransform), style: null); - - var characterModeTickBoxHolder = new GUILayoutGroup(new RectTransform(new Vector2(paddedLeftPanel.RectTransform.RelativeSize.X, 0.01f), paddedLeftPanel.RectTransform) { MinSize = new Point(0, 32) }) - { Color = secondaryColor }; - - characterModeTickBox = new GUITickBox(new RectTransform(Vector2.One, characterModeTickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("CharacterModeButton")) - { - ToolTip = TextManager.Get("CharacterModeToolTip"), - OnSelected = (GUITickBox tBox) => - { - SetCharacterMode(tBox.Selected); return true; } }; - var wiringModeTickBoxHolder = new GUILayoutGroup(new RectTransform(new Vector2(paddedLeftPanel.RectTransform.RelativeSize.X, 0.01f), paddedLeftPanel.RectTransform) { MinSize = new Point(0, 32) }) - { Color = secondaryColor }; - - wiringModeTickBox = new GUITickBox(new RectTransform(Vector2.One, wiringModeTickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("WiringModeButton")) + var wiringModeTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "WiringModeButton") { - ToolTip = TextManager.Get("WiringModeToolTip"), + ToolTip = TextManager.Get("WiringModeButton") + '\n' + TextManager.Get("WiringModeToolTip"), OnSelected = (GUITickBox tBox) => { - SetWiringMode(tBox.Selected); + if (tBox.Selected) + { + SetMode(Mode.Wiring); + } return true; } }; - - GUITextBlock.AutoScaleAndNormalize(characterModeTickBox.TextBlock, wiringModeTickBox.TextBlock); - - button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("GenerateWaypointsButton"), style: null, color: new Color(70, 100, 122, 255)) + + modeButtonGroup.AddRadioButton((int)Mode.Default, defaultModeTickBox); + modeButtonGroup.AddRadioButton((int)Mode.Character, characterModeTickBox); + modeButtonGroup.AddRadioButton((int)Mode.Wiring, wiringModeTickBox); + modeButtonGroup.Selected = (int)Mode.Default; + + new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), paddedTopPanel.RectTransform), style: "VerticalLine"); + + new GUIButton(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "GenerateWaypointsButton") { - ForceUpperCase = true, - HoverColor = new Color(33, 33, 33, 255), - TextColor = Color.White, - ToolTip = TextManager.Get("GenerateWaypointsToolTip"), + ToolTip = TextManager.Get("GenerateWaypointsButton") + '\n' + TextManager.Get("GenerateWaypointsToolTip"), OnClicked = GenerateWaypoints }; - button.TextBlock.AutoScale = true; - //spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), paddedLeftPanel.RectTransform), style: null); + new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), paddedTopPanel.RectTransform), style: "VerticalLine"); - var tickBoxHolder = new GUILayoutGroup(new RectTransform(new Vector2(paddedLeftPanel.RectTransform.RelativeSize.X, 0.3f), paddedLeftPanel.RectTransform)) - { Color = secondaryColor, Stretch = true, RelativeSpacing = 0.05f }; - - //spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), tickBoxHolder.RectTransform) { MinSize = new Point(0, 3) }, style: null); - - var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), tickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowLighting")) + var visibilityButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "SetupVisibilityButton") { + ToolTip = TextManager.Get("SubEditorVisibilityButton") + '\n' + TextManager.Get("SubEditorVisibilityToolTip"), + OnClicked = (btn, userData) => + { + previouslyUsedPanel.Visible = false; + showEntitiesPanel.Visible = !showEntitiesPanel.Visible; + showEntitiesPanel.RectTransform.AbsoluteOffset = new Point(btn.Rect.X, TopPanel.Rect.Height); + return true; + } + }; + + var previouslyUsedButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "RecentlyUsedButton") + { + ToolTip = TextManager.Get("PreviouslyUsedLabel"), + OnClicked = (btn, userData) => + { + showEntitiesPanel.Visible = false; + previouslyUsedPanel.Visible = !previouslyUsedPanel.Visible; + previouslyUsedPanel.RectTransform.AbsoluteOffset = new Point(btn.Rect.X, TopPanel.Rect.Height); + return true; + } + }; + + var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), paddedTopPanel.RectTransform, Anchor.CenterRight), style: "GUINotificationButton") + { + IgnoreLayoutGroups = true, + OnClicked = (btn, userdata) => { GameMain.Instance.ShowEditorDisclaimer(); return true; } + }; + disclaimerBtn.RectTransform.MaxSize = new Point(disclaimerBtn.Rect.Height); + + TopPanel.RectTransform.MinSize = new Point(0, (int)(paddedTopPanel.RectTransform.Children.Max(c => c.MinSize.Y) / paddedTopPanel.RectTransform.RelativeSize.Y)); + paddedTopPanel.Recalculate(); + + //----------------------------------------------- + + previouslyUsedPanel = new GUIFrame(new RectTransform(new Vector2(0.1f, 0.2f), GUI.Canvas, Anchor.TopLeft) { MinSize = new Point(200, 200) }) + { + Visible = false + }; + previouslyUsedList = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.9f), previouslyUsedPanel.RectTransform, Anchor.Center)) + { + ScrollBarVisible = true, + OnSelected = SelectPrefab + }; + + //----------------------------------------------- + + showEntitiesPanel = new GUIFrame(new RectTransform(new Vector2(0.08f, 0.5f), GUI.Canvas) + { + MinSize = new Point(170, 0), + AbsoluteOffset = new Point(visibilityButton.Rect.X, TopPanel.Rect.Height) + }) + { + Visible = false + }; + + GUILayoutGroup paddedShowEntitiesPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), showEntitiesPanel.RectTransform, Anchor.Center)) + { + Stretch = true + }; + + var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedShowEntitiesPanel.RectTransform), TextManager.Get("ShowLighting")) + { + UserData = "lighting", Selected = lightingEnabled, - OnSelected = (GUITickBox obj) => + OnSelected = (GUITickBox obj) => { lightingEnabled = obj.Selected; if (lightingEnabled) @@ -491,70 +379,264 @@ namespace Barotrauma return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), tickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowWalls")) + new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedShowEntitiesPanel.RectTransform), TextManager.Get("ShowWalls")) { + UserData = "wall", Selected = Structure.ShowWalls, OnSelected = (GUITickBox obj) => { Structure.ShowWalls = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), tickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowStructures")) + new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedShowEntitiesPanel.RectTransform), TextManager.Get("ShowStructures")) { + UserData = "structure", Selected = Structure.ShowStructures, OnSelected = (GUITickBox obj) => { Structure.ShowStructures = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), tickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowItems")) + new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedShowEntitiesPanel.RectTransform), TextManager.Get("ShowItems")) { + UserData = "item", Selected = Item.ShowItems, OnSelected = (GUITickBox obj) => { Item.ShowItems = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), tickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowWaypoints")) + new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedShowEntitiesPanel.RectTransform), TextManager.Get("ShowWaypoints")) { + UserData = "waypoint", Selected = WayPoint.ShowWayPoints, OnSelected = (GUITickBox obj) => { WayPoint.ShowWayPoints = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), tickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowSpawnpoints")) + new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedShowEntitiesPanel.RectTransform), TextManager.Get("ShowSpawnpoints")) { + UserData = "spawnpoint", Selected = WayPoint.ShowSpawnPoints, OnSelected = (GUITickBox obj) => { WayPoint.ShowSpawnPoints = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), tickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowLinks")) + new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedShowEntitiesPanel.RectTransform), TextManager.Get("ShowLinks")) { + UserData = "link", Selected = Item.ShowLinks, OnSelected = (GUITickBox obj) => { Item.ShowLinks = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), tickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowHulls")) + new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedShowEntitiesPanel.RectTransform), TextManager.Get("ShowHulls")) { + UserData = "hull", Selected = Hull.ShowHulls, OnSelected = (GUITickBox obj) => { Hull.ShowHulls = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), tickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowGaps")) + new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedShowEntitiesPanel.RectTransform), TextManager.Get("ShowGaps")) { + UserData = "gap", Selected = Gap.ShowGaps, OnSelected = (GUITickBox obj) => { Gap.ShowGaps = obj.Selected; return true; }, }; - GUITextBlock.AutoScaleAndNormalize(tickBoxHolder.Children.Where(c => c is GUITickBox).Select(c => ((GUITickBox)c).TextBlock)); + showEntitiesTickBoxes.AddRange(paddedShowEntitiesPanel.Children.Select(c => c as GUITickBox)); - //spacing - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), tickBoxHolder.RectTransform) { MinSize = new Point(0, 3) }, style: null); + showEntitiesPanel.RectTransform.NonScaledSize = + new Point( + (int)(paddedShowEntitiesPanel.RectTransform.Children.Max(c => (int)((c.GUIComponent as GUITickBox)?.TextBlock.TextSize.X ?? 0)) / paddedShowEntitiesPanel.RectTransform.RelativeSize.X), + (int)(paddedShowEntitiesPanel.RectTransform.Children.Sum(c => c.MinSize.Y) / paddedShowEntitiesPanel.RectTransform.RelativeSize.Y)); + GUITextBlock.AutoScaleAndNormalize(paddedShowEntitiesPanel.Children.Where(c => c is GUITickBox).Select(c => ((GUITickBox)c).TextBlock)); - new GUITextBlock(new RectTransform(new Vector2(0.95f, 0.025f), paddedLeftPanel.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("PreviouslyUsedLabel")) + //----------------------------------------------- + + float longestTextWidth = GUI.SmallFont.MeasureString(TextManager.Get("SubEditorShadowCastingLights")).X; + entityCountPanel = new GUIFrame(new RectTransform(new Vector2(0.08f, 0.5f), GUI.Canvas) { - AutoScale = true - }; - previouslyUsedList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform, Anchor.BottomCenter)) + MinSize = new Point(Math.Max(170, (int)(longestTextWidth * 1.5f)), 0), + AbsoluteOffset = new Point(0, TopPanel.Rect.Height) + }); + + GUILayoutGroup paddedEntityCountPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), entityCountPanel.RectTransform, Anchor.Center)) { - ScrollBarVisible = true, - OnSelected = SelectPrefab + Stretch = true, + AbsoluteSpacing = (int)(GUI.Scale * 4) }; + var itemCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("Items"), + textAlignment: Alignment.CenterLeft, font: GUI.SmallFont); + var itemCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), itemCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight); + itemCount.TextGetter = () => + { + itemCount.TextColor = ToolBox.GradientLerp(Item.ItemList.Count / 5000.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red); + return Item.ItemList.Count.ToString(); + }; + + var structureCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("Structures"), + textAlignment: Alignment.CenterLeft, font: GUI.SmallFont); + var structureCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), structureCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight); + structureCount.TextGetter = () => + { + int count = (MapEntity.mapEntityList.Count - Item.ItemList.Count - Hull.hullList.Count - WayPoint.WayPointList.Count - Gap.GapList.Count); + structureCount.TextColor = ToolBox.GradientLerp(count / 1000.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red); + return count.ToString(); + }; + + var wallCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("Walls"), + textAlignment: Alignment.CenterLeft, font: GUI.SmallFont); + var wallCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), wallCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight); + wallCount.TextGetter = () => + { + wallCount.TextColor = ToolBox.GradientLerp(Structure.WallList.Count / 500.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red); + return Structure.WallList.Count.ToString(); + }; + + var lightCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorLights"), + textAlignment: Alignment.CenterLeft, font: GUI.SmallFont); + var lightCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), lightCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight); + lightCount.TextGetter = () => + { + int disabledItemLightCount = 0; + foreach (Item item in Item.ItemList) + { + if (item.ParentInventory == null) { continue; } + disabledItemLightCount += item.GetComponents().Count(); + } + int count = GameMain.LightManager.Lights.Count() - disabledItemLightCount; + lightCount.TextColor = ToolBox.GradientLerp(count / 250.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red); + return count.ToString(); + }; + var shadowCastingLightCountText = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorShadowCastingLights"), + textAlignment: Alignment.CenterLeft, font: GUI.SmallFont, wrap: true); + var shadowCastingLightCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), shadowCastingLightCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight); + shadowCastingLightCount.TextGetter = () => + { + int disabledItemLightCount = 0; + foreach (Item item in Item.ItemList) + { + if (item.ParentInventory == null) { continue; } + disabledItemLightCount += item.GetComponents().Count(); + } + int count = GameMain.LightManager.Lights.Count(l => l.CastShadows) - disabledItemLightCount; + shadowCastingLightCount.TextColor = ToolBox.GradientLerp(count / 60.0f, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red); + return count.ToString(); + }; + entityCountPanel.RectTransform.NonScaledSize = + new Point( + (int)(paddedEntityCountPanel.RectTransform.Children.Max(c => (int)(c.GUIComponent as GUITextBlock).TextSize.X / 0.75f) / paddedEntityCountPanel.RectTransform.RelativeSize.X), + (int)(paddedEntityCountPanel.RectTransform.Children.Sum(c => (int)(c.NonScaledSize.Y * 1.5f) + paddedEntityCountPanel.AbsoluteSpacing) / paddedEntityCountPanel.RectTransform.RelativeSize.Y)); + //GUITextBlock.AutoScaleAndNormalize(paddedEntityCountPanel.Children.Where(c => c is GUITextBlock).Cast()); + + //----------------------------------------------- + + hullVolumeFrame = new GUIFrame(new RectTransform(new Vector2(0.15f, 2.0f), TopPanel.RectTransform, Anchor.BottomLeft, Pivot.TopLeft, minSize: new Point(300, 85)) { AbsoluteOffset = new Point(entityCountPanel.Rect.Width, 0) }, "GUIToolTip") + { + Visible = false + }; + GUITextBlock totalHullVolume = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), hullVolumeFrame.RectTransform), "", font: GUI.SmallFont) + { + TextGetter = GetTotalHullVolume + }; + GUITextBlock selectedHullVolume = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), hullVolumeFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.5f) }, "", font: GUI.SmallFont) + { + TextGetter = GetSelectedHullVolume + }; + + saveAssemblyFrame = new GUIFrame(new RectTransform(new Vector2(0.08f, 0.5f), TopPanel.RectTransform, Anchor.BottomLeft, Pivot.TopLeft) + { MinSize = new Point((int)(250 * GUI.Scale), (int)(80 * GUI.Scale)), AbsoluteOffset = new Point((int)(10 * GUI.Scale), -entityCountPanel.Rect.Height - (int)(10 * GUI.Scale)) }, "InnerFrame") + { + Visible = false + }; + var saveAssemblyButton = new GUIButton(new RectTransform(new Vector2(0.9f, 0.8f), saveAssemblyFrame.RectTransform, Anchor.Center), TextManager.Get("SaveItemAssembly")); + saveAssemblyButton.TextBlock.AutoScale = true; + saveAssemblyButton.OnClicked += (btn, userdata) => + { + CreateSaveAssemblyScreen(); + return true; + }; + saveAssemblyFrame.RectTransform.MinSize = new Point(saveAssemblyFrame.Rect.Width, (int)(saveAssemblyButton.Rect.Height / saveAssemblyButton.RectTransform.RelativeSize.Y)); + + + //Entity menu + //------------------------------------------------ + + EntityMenu = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, (int)(359 * GUI.Scale)), GUI.Canvas, Anchor.BottomRight)); + + toggleEntityMenuButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.08f), EntityMenu.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { MinSize = new Point(0, 15) }, + style: "UIToggleButtonVertical") + { + OnClicked = (btn, userdata) => + { + entityMenuOpen = !entityMenuOpen; + SetMode(Mode.Default); + foreach (GUIComponent child in btn.Children) + { + child.SpriteEffects = entityMenuOpen ? SpriteEffects.None : SpriteEffects.FlipVertically; + } + return true; + } + }; + + var paddedTab = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.96f), EntityMenu.RectTransform, Anchor.BottomCenter), childAnchor: Anchor.TopCenter) + { + RelativeSpacing = 0.05f, + Stretch = true + }; + + var entityMenuTop = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.13f), paddedTab.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + Stretch = true + }; + + var selectedCategoryButton = new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), entityMenuTop.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "CategoryButton.All") + { + CanBeFocused = false + }; + var selectedCategoryText = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1.0f), entityMenuTop.RectTransform), TextManager.Get("MapEntityCategory.All"), font: GUI.LargeFont); + + entityCategoryButtons.Clear(); + entityCategoryButtons.Add( + new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), entityMenuTop.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "CategoryButton.All") + { + OnClicked = (btn, userdata) => + { + entityCategoryButtons.ForEach(b => b.Selected = b == btn); + selectedCategoryText.Text = TextManager.Get("MapEntityCategory.All"); + selectedCategoryButton.ApplyStyle(GUI.Style.GetComponentStyle("CategoryButton.All")); + ClearFilter(); + return true; + } + }); + + foreach (MapEntityCategory category in Enum.GetValues(typeof(MapEntityCategory))) + { + entityCategoryButtons.Add(new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), entityMenuTop.RectTransform, scaleBasis: ScaleBasis.BothHeight), + "", style: "CategoryButton." + category.ToString()) + { + UserData = category, + ToolTip = TextManager.Get("MapEntityCategory." + category.ToString()), + OnClicked = (btn, userdata) => + { + entityMenuOpen = true; + MapEntityCategory newCategory = (MapEntityCategory)userdata; + selectedCategoryText.Text = TextManager.Get("MapEntityCategory." + newCategory.ToString()); + selectedCategoryButton.ApplyStyle(GUI.Style.GetComponentStyle("CategoryButton." + category.ToString())); + OpenEntityMenu(newCategory); + return true; + } + }); + } + + var filterText = new GUITextBlock(new RectTransform(new Vector2(0.1f, 1.0f), entityMenuTop.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.SubHeadingFont); + filterText.RectTransform.MaxSize = new Point((int)(filterText.TextSize.X * 1.5f), int.MaxValue); + entityFilterBox = new GUITextBox(new RectTransform(new Vector2(0.2f, 1.0f), entityMenuTop.RectTransform), font: GUI.Font, createClearButton: true); + entityFilterBox.OnTextChanged += (textBox, text) => { FilterEntities(text); return true; }; + + new GUIFrame(new RectTransform(new Vector2(0.8f, 0.01f), paddedTab.RectTransform), style: "HorizontalLine"); + + entityList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.9f), paddedTab.RectTransform)) + { + OnSelected = SelectPrefab, + UseGridLayout = true, + CheckSelected = MapEntityPrefab.GetSelected + }; + screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); } - + private void UpdateEntityList() { entityList.Content.ClearChildren(); - int entitiesPerRow = (int)Math.Ceiling(entityList.Content.Rect.Width / Math.Max(150 * GUI.Scale, 100)); + int entitiesPerRow = (int)Math.Ceiling(entityList.Content.Rect.Width / Math.Max(125 * GUI.Scale, 100)); foreach (MapEntityPrefab ep in MapEntityPrefab.List) { @@ -572,6 +654,9 @@ namespace Barotrauma { UserData = ep, }; + frame.RectTransform.MinSize = new Point(0, frame.Rect.Width); + frame.RectTransform.MaxSize = new Point(int.MaxValue, frame.Rect.Width); + string name = legacy ? ep.Name + " (legacy)" : ep.Name; frame.ToolTip = string.IsNullOrEmpty(ep.Description) ? name : name + '\n' + ep.Description; @@ -629,7 +714,7 @@ namespace Barotrauma if (ep.Category == MapEntityCategory.ItemAssembly) { var deleteButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform, Anchor.BottomCenter) { MinSize = new Point(0, 20) }, - TextManager.Get("Delete")) + TextManager.Get("Delete"), style: "GUIButtonSmall") { UserData = ep, OnClicked = (btn, userData) => @@ -667,7 +752,6 @@ namespace Barotrauma } } - entityList.Content.RectTransform.SortChildren((i1, i2) => (i1.GUIComponent.UserData as MapEntityPrefab).Name.CompareTo((i2.GUIComponent.UserData as MapEntityPrefab).Name)); } @@ -690,7 +774,7 @@ namespace Barotrauma editorSelectedTime = DateTime.Now; GUI.ForceMouseOn(null); - SetCharacterMode(false); + SetMode(Mode.Default); if (Submarine.MainSub != null) { @@ -741,8 +825,7 @@ namespace Barotrauma MapEntity.DeselectAll(); MapEntity.SelectionGroups.Clear(); - if (CharacterMode) SetCharacterMode(false); - if (WiringMode) SetWiringMode(false); + SetMode(Mode.Default); SoundPlayer.OverrideMusicType = null; GameMain.SoundManager.SetCategoryGainMultiplier("default", GameMain.Config.SoundVolume, 0); @@ -916,7 +999,7 @@ namespace Barotrauma { if (string.IsNullOrWhiteSpace(nameBox.Text)) { - GUI.AddMessage(TextManager.Get("SubNameMissingWarning"), Color.Red); + GUI.AddMessage(TextManager.Get("SubNameMissingWarning"), GUI.Style.Red); nameBox.Flash(); return false; @@ -926,7 +1009,7 @@ namespace Barotrauma { if (nameBox.Text.Contains(illegalChar)) { - GUI.AddMessage(TextManager.GetWithVariable("SubNameIllegalCharsWarning", "[illegalchar]", illegalChar.ToString()), Color.Red); + GUI.AddMessage(TextManager.GetWithVariable("SubNameIllegalCharsWarning", "[illegalchar]", illegalChar.ToString()), GUI.Style.Red); nameBox.Flash(); return false; } @@ -952,7 +1035,7 @@ namespace Barotrauma string pathToCompare = savePath.Replace(@"\", @"/").ToLowerInvariant(); if (vanillaSubs.Any(sub => sub.Replace(@"\", @"/").ToLowerInvariant() == pathToCompare)) { - GUI.AddMessage(TextManager.Get("CannotEditVanillaSubs"), Color.Red, font: GUI.LargeFont); + GUI.AddMessage(TextManager.Get("CannotEditVanillaSubs"), GUI.Style.Red, font: GUI.LargeFont); return false; } } @@ -972,7 +1055,7 @@ namespace Barotrauma } Submarine.MainSub.CheckForErrors(); - GUI.AddMessage(TextManager.GetWithVariable("SubSavedNotification", "[filepath]", Submarine.MainSub.FilePath), Color.Green); + GUI.AddMessage(TextManager.GetWithVariable("SubSavedNotification", "[filepath]", Submarine.MainSub.FilePath), GUI.Style.Green); Submarine.RefreshSavedSub(savePath); if (prevSavePath != null && prevSavePath != savePath) @@ -993,8 +1076,7 @@ namespace Barotrauma private void CreateSaveScreen() { - if (CharacterMode) SetCharacterMode(false); - if (WiringMode) SetWiringMode(false); + SetMode(Mode.Default); saveFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker") { @@ -1006,7 +1088,7 @@ namespace Barotrauma //var header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedSaveFrame.RectTransform), TextManager.Get("SaveSubDialogHeader"), font: GUI.LargeFont); - var columnArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), paddedSaveFrame.RectTransform), isHorizontal: true) { Stretch = true }; + var columnArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), paddedSaveFrame.RectTransform), isHorizontal: true) { RelativeSpacing = 0.02f, Stretch = true }; var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.55f, 1.0f), columnArea.RectTransform)) { RelativeSpacing = 0.01f, Stretch = true }; var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.42f, 1.0f), columnArea.RectTransform)) { RelativeSpacing = 0.02f, Stretch = true }; @@ -1014,7 +1096,7 @@ namespace Barotrauma var nameHeaderGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.03f), leftColumn.RectTransform), true); var saveSubLabel = new GUITextBlock(new RectTransform(new Vector2(.5f, 1f), nameHeaderGroup.RectTransform), - TextManager.Get("SaveSubDialogName")); + TextManager.Get("SaveSubDialogName"), font: GUI.SubHeadingFont); submarineNameCharacterCount = new GUITextBlock(new RectTransform(new Vector2(.5f, 1f), nameHeaderGroup.RectTransform), string.Empty, textAlignment: Alignment.TopRight); @@ -1028,7 +1110,7 @@ namespace Barotrauma if (text.Length > submarineNameLimit) { nameBox.Text = text.Substring(0, submarineNameLimit); - nameBox.Flash(Color.Red); + nameBox.Flash(GUI.Style.Red); return true; } @@ -1040,11 +1122,12 @@ namespace Barotrauma var descriptionHeaderGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.03f), leftColumn.RectTransform), true); - new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), descriptionHeaderGroup.RectTransform), TextManager.Get("SaveSubDialogDescription")); + new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), descriptionHeaderGroup.RectTransform), TextManager.Get("SaveSubDialogDescription"), font: GUI.SubHeadingFont); submarineDescriptionCharacterCount = new GUITextBlock(new RectTransform(new Vector2(.5f, 1f), descriptionHeaderGroup.RectTransform), string.Empty, textAlignment: Alignment.TopRight); var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.25f), leftColumn.RectTransform)); - descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform, Anchor.Center), font: GUI.SmallFont, wrap: true, textAlignment: Alignment.TopLeft) + descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform, Anchor.Center), + font: GUI.SmallFont, style: "GUITextBoxNoBorder", wrap: true, textAlignment: Alignment.TopLeft) { Padding = new Vector4(10 * GUI.Scale) }; @@ -1054,12 +1137,12 @@ namespace Barotrauma if (text.Length > submarineDescriptionLimit) { descriptionBox.Text = text.Substring(0, submarineDescriptionLimit); - descriptionBox.Flash(Color.Red); + descriptionBox.Flash(GUI.Style.Red); return true; } Vector2 textSize = textBox.Font.MeasureString(descriptionBox.WrappedText); - textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(descriptionContainer.Rect.Height, (int)textSize.Y + 10)); + textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(descriptionContainer.Content.Rect.Height, (int)textSize.Y + 10)); descriptionContainer.UpdateScrollBarSize(); descriptionContainer.BarScroll = 1.0f; ChangeSubDescription(textBox, text); @@ -1068,10 +1151,14 @@ namespace Barotrauma descriptionBox.Text = GetSubDescription(); - var crewSizeArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.03f), leftColumn.RectTransform), isHorizontal: true) { AbsoluteSpacing = 5 }; + var crewSizeArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), leftColumn.RectTransform), isHorizontal: true) + { + Stretch = true, + AbsoluteSpacing = 5 + }; new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), crewSizeArea.RectTransform), - TextManager.Get("RecommendedCrewSize"), font: GUI.SmallFont); + TextManager.Get("RecommendedCrewSize"), textAlignment: Alignment.CenterLeft, wrap: true, font: GUI.SmallFont); var crewSizeMin = new GUINumberInput(new RectTransform(new Vector2(0.1f, 1.0f), crewSizeArea.RectTransform), GUINumberInput.NumberType.Int) { MinValueInt = 1, @@ -1097,16 +1184,19 @@ namespace Barotrauma Submarine.MainSub.RecommendedCrewSizeMin = crewSizeMin.IntValue; Submarine.MainSub.RecommendedCrewSizeMax = crewSizeMax.IntValue; }; - - var crewExpArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.03f), leftColumn.RectTransform), isHorizontal: true) { AbsoluteSpacing = 5 }; - new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), crewExpArea.RectTransform), - TextManager.Get("RecommendedCrewExperience"), font: GUI.SmallFont); + var crewExpArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), leftColumn.RectTransform), isHorizontal: true) + { + Stretch = true, + AbsoluteSpacing = 5 + }; - var toggleExpLeft = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), crewExpArea.RectTransform), "<"); - var experienceText = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), crewExpArea.RectTransform), crewExperienceLevels[0], textAlignment: Alignment.Center); - var toggleExpRight = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), crewExpArea.RectTransform), ">"); + new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), crewExpArea.RectTransform), + TextManager.Get("RecommendedCrewExperience"), textAlignment: Alignment.CenterLeft, wrap: true, font: GUI.SmallFont); + var toggleExpLeft = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), crewExpArea.RectTransform), style: "GUIButtonToggleLeft"); + var experienceText = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), crewExpArea.RectTransform), crewExperienceLevels[0], textAlignment: Alignment.Center); + var toggleExpRight = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), crewExpArea.RectTransform), style: "GUIButtonToggleRight"); toggleExpLeft.OnClicked += (btn, userData) => { @@ -1143,14 +1233,14 @@ namespace Barotrauma // right column --------------------------------------------------- - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), rightColumn.RectTransform), TextManager.Get("SubPreviewImage")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), rightColumn.RectTransform), TextManager.Get("SubPreviewImage"), font: GUI.SubHeadingFont); var previewImageHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), rightColumn.RectTransform), style: null) { Color = Color.Black, CanBeFocused = false }; previewImage = new GUIImage(new RectTransform(Vector2.One, previewImageHolder.RectTransform), Submarine.MainSub?.PreviewImage, scaleToFit: true); - var previewImageButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; + var previewImageButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; - new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), previewImageButtonHolder.RectTransform), TextManager.Get("SubPreviewImageCreate")) + new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), previewImageButtonHolder.RectTransform), TextManager.Get("SubPreviewImageCreate"), style: "GUIButtonSmall") { OnClicked = (btn, userdata) => { @@ -1167,7 +1257,7 @@ namespace Barotrauma } }; - new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), previewImageButtonHolder.RectTransform), TextManager.Get("SubPreviewImageBrowse")) + new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), previewImageButtonHolder.RectTransform), TextManager.Get("SubPreviewImageBrowse"), style: "GUIButtonSmall") { OnClicked = (btn, userdata) => { @@ -1195,11 +1285,12 @@ namespace Barotrauma } }; + previewImageButtonHolder.RectTransform.MinSize = new Point(0, previewImageButtonHolder.RectTransform.Children.Max(c => c.MinSize.Y)); var horizontalArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.35f), rightColumn.RectTransform), style: null); var settingsLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), horizontalArea.RectTransform), - TextManager.Get("SaveSubDialogSettings"), font: GUI.SmallFont); + TextManager.Get("SaveSubDialogSettings"), wrap: true, font: GUI.SmallFont); var tagContainer = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f - settingsLabel.RectTransform.RelativeSize.Y), horizontalArea.RectTransform, Anchor.BottomLeft), @@ -1231,7 +1322,7 @@ namespace Barotrauma } var contentPackagesLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), horizontalArea.RectTransform, Anchor.TopRight), - TextManager.Get("RequiredContentPackages"), font: GUI.SmallFont); + TextManager.Get("RequiredContentPackages"), wrap: true, font: GUI.SmallFont); var contentPackList = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f - contentPackagesLabel.RectTransform.RelativeSize.Y), horizontalArea.RectTransform, Anchor.BottomRight)); @@ -1270,7 +1361,7 @@ namespace Barotrauma var buttonArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), paddedSaveFrame.RectTransform, Anchor.BottomCenter, minSize: new Point(0, 30)), style: null); var cancelButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomLeft), - TextManager.Get("Cancel"), style: "GUIButtonLarge") + TextManager.Get("Cancel")) { OnClicked = (GUIButton btn, object userdata) => { @@ -1280,7 +1371,7 @@ namespace Barotrauma }; var saveButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomRight), - TextManager.Get("SaveSubButton"), style: "GUIButtonLarge") + TextManager.Get("SaveSubButton")) { OnClicked = SaveSub }; @@ -1293,8 +1384,7 @@ namespace Barotrauma private void CreateSaveAssemblyScreen() { - if (CharacterMode) SetCharacterMode(false); - if (WiringMode) SetWiringMode(false); + SetMode(Mode.Default); saveFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker") { @@ -1351,7 +1441,7 @@ namespace Barotrauma { if (string.IsNullOrWhiteSpace(nameBox.Text)) { - GUI.AddMessage(TextManager.Get("ItemAssemblyNameMissingWarning"), Color.Red); + GUI.AddMessage(TextManager.Get("ItemAssemblyNameMissingWarning"), GUI.Style.Red); nameBox.Flash(); return false; @@ -1361,7 +1451,7 @@ namespace Barotrauma { if (nameBox.Text.Contains(illegalChar)) { - GUI.AddMessage(TextManager.GetWithVariable("ItemAssemblyNameIllegalCharsWarning", "[illegalchar]", illegalChar.ToString()), Color.Red); + GUI.AddMessage(TextManager.GetWithVariable("ItemAssemblyNameIllegalCharsWarning", "[illegalchar]", illegalChar.ToString()), GUI.Style.Red); nameBox.Flash(); return false; } @@ -1405,10 +1495,8 @@ namespace Barotrauma private bool CreateLoadScreen() { - if (CharacterMode) SetCharacterMode(false); - if (WiringMode) SetWiringMode(false); - - + SetMode(Mode.Default); + loadFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker") { OnClicked = (btn, userdata) => { if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) loadFrame = null; return true; }, @@ -1419,11 +1507,15 @@ namespace Barotrauma var paddedLoadFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), innerFrame.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.02f }; var deleteButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedLoadFrame.RectTransform, Anchor.Center)); - - var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedLoadFrame.RectTransform), isHorizontal: true) + + var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedLoadFrame.RectTransform), font: GUI.Font, createClearButton: true); + var searchTitle = new GUITextBlock(new RectTransform(Vector2.One, searchBox.RectTransform), TextManager.Get("serverlog.filter"), + textAlignment: Alignment.CenterLeft, font: GUI.Font) { - Stretch = true + CanBeFocused = false, + IgnoreLayoutGroups = true }; + searchTitle.TextColor *= 0.5f; var subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedLoadFrame.RectTransform)) { @@ -1442,25 +1534,18 @@ namespace Barotrauma } }; - var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font); - var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform), font: GUI.Font); searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; }; searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; }; - searchBox.OnTextChanged += (textBox, text) => { FilterSubs(subList, text); return true; }; - var clearButton = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), filterContainer.RectTransform), "x") - { - OnClicked = (btn, userdata) => { searchBox.Text = ""; FilterSubs(subList, ""); searchBox.Flash(Color.White); return true; } - }; foreach (Submarine sub in Submarine.SavedSubmarines) { GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), subList.Content.RectTransform) { MinSize = new Point(0, 30) }, ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width - 80)) - { - UserData = sub, - ToolTip = sub.FilePath - }; + { + UserData = sub, + ToolTip = sub.FilePath + }; if (sub.HasTag(SubmarineTag.Shuttle)) { @@ -1474,7 +1559,7 @@ namespace Barotrauma } var deleteButton = new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), deleteButtonHolder.RectTransform, Anchor.TopCenter), - TextManager.Get("Delete"), style: "GUIButtonLarge") + TextManager.Get("Delete")) { Enabled = false, UserData = "delete" @@ -1492,7 +1577,7 @@ namespace Barotrauma var controlBtnHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedLoadFrame.RectTransform), isHorizontal: true) { RelativeSpacing = 0.2f, Stretch = true }; new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), controlBtnHolder.RectTransform, Anchor.BottomLeft), - TextManager.Get("Cancel"), style: "GUIButtonLarge") + TextManager.Get("Cancel")) { OnClicked = (GUIButton btn, object userdata) => { @@ -1502,12 +1587,11 @@ namespace Barotrauma }; new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), controlBtnHolder.RectTransform, Anchor.BottomRight), - TextManager.Get("Load"), style: "GUIButtonLarge") + TextManager.Get("Load")) { OnClicked = LoadSub }; - return true; } @@ -1515,8 +1599,7 @@ namespace Barotrauma { foreach (GUIComponent child in subList.Content.Children) { - var sub = child.UserData as Submarine; - if (sub == null) { return; } + if (!(child.UserData is Submarine sub)) { return; } child.Visible = string.IsNullOrEmpty(filter) ? true : sub.Name.ToLower().Contains(filter.ToLower()); } } @@ -1620,8 +1703,7 @@ namespace Barotrauma private bool OpenEntityMenu(MapEntityCategory selectedCategory) { entityFilterBox.Text = ""; - if (CharacterMode) SetCharacterMode(false); - if (WiringMode) SetWiringMode(false); + SetMode(Mode.Default); saveFrame = null; loadFrame = null; @@ -1683,23 +1765,30 @@ namespace Barotrauma return true; } - public bool SetCharacterMode(bool enabled) + public void SetMode(Mode mode) { - characterModeTickBox.Selected = enabled; - CharacterMode = enabled; - if (CharacterMode) - { - wiringModeTickBox.Selected = false; - WiringMode = false; - } + if (mode == this.mode) { return; } - if (CharacterMode) + this.mode = mode; + modeButtonGroup.Selected = (int)mode; + + switch (mode) { - CreateDummyCharacter(); - } - else if (dummyCharacter != null && !WiringMode) - { - RemoveDummyCharacter(); + case Mode.Character: + CreateDummyCharacter(); + break; + case Mode.Wiring: + CreateDummyCharacter(); + var item = new Item(MapEntityPrefab.Find(null, "screwdriver") as ItemPrefab, Vector2.Zero, null); + dummyCharacter.Inventory.TryPutItem(item, null, new List() { InvSlotType.RightHand }); + wiringToolPanel = CreateWiringPanel(); + break; + default: + if (dummyCharacter != null) + { + RemoveDummyCharacter(); + } + break; } foreach (MapEntity me in MapEntity.mapEntityList) @@ -1708,51 +1797,21 @@ namespace Barotrauma } MapEntity.DeselectAll(); - - return true; - } - - public bool SetWiringMode(bool enabled) - { - wiringModeTickBox.Selected = enabled; - WiringMode = enabled; - if (WiringMode) - { - characterModeTickBox.Selected = false; - CharacterMode = false; - } - - if (WiringMode) - { - CreateDummyCharacter(); - var item = new Item(MapEntityPrefab.Find(null, "screwdriver") as ItemPrefab, Vector2.Zero, null); - dummyCharacter.Inventory.TryPutItem(item, null, new List() { InvSlotType.RightHand }); - wiringToolPanel = CreateWiringPanel(); - } - else if (dummyCharacter != null && !CharacterMode) - { - RemoveDummyCharacter(); - } - - MapEntity.DeselectAll(); - - return true; } private void RemoveDummyCharacter() { - if (dummyCharacter == null) return; - + if (dummyCharacter == null) { return; } + foreach (Item item in dummyCharacter.Inventory.Items) { - if (item == null) continue; + if (item == null) { continue; } item.Remove(); } dummyCharacter.Remove(); - dummyCharacter = null; - + dummyCharacter = null; } private void CreateContextMenu() @@ -1826,11 +1885,10 @@ namespace Barotrauma private GUIFrame CreateWiringPanel() { - GUIFrame frame = new GUIFrame(new RectTransform(new Vector2(0.03f, 0.35f), GUI.Canvas, Anchor.TopLeft, Pivot.CenterLeft) - { MinSize = new Point(120, 300), AbsoluteOffset = new Point(LeftPanel.Rect.Right, LeftPanel.Rect.Center.Y) }, - style: "GUIFrameRight"); + GUIFrame frame = new GUIFrame(new RectTransform(new Vector2(0.03f, 0.35f), GUI.Canvas) + { MinSize = new Point(120, 300), AbsoluteOffset = new Point((int)(10 * GUI.Scale), TopPanel.Rect.Height + entityCountPanel.Rect.Height + (int)(10 * GUI.Scale)) }); - GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.8f, 0.85f), frame.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.1f, 0.0f) }) + GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.9f), frame.RectTransform, Anchor.Center)) { OnSelected = SelectWire }; @@ -1840,13 +1898,14 @@ namespace Barotrauma if (string.IsNullOrEmpty(itemPrefab.Name)) { continue; } if (!itemPrefab.Tags.Contains("wire")) { continue; } - GUIFrame imgFrame = new GUIFrame(new RectTransform(new Point(listBox.Rect.Width - 20, listBox.Rect.Width / 2), listBox.Content.RectTransform), style: "ListBoxElement") + GUIFrame imgFrame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, listBox.Rect.Width / 2), listBox.Content.RectTransform), style: "ListBoxElement") { UserData = itemPrefab }; - var img = new GUIImage(new RectTransform(Vector2.One, imgFrame.RectTransform), itemPrefab.sprite) + var img = new GUIImage(new RectTransform(new Vector2(0.9f), imgFrame.RectTransform, Anchor.Center), itemPrefab.sprite, scaleToFit: true) { + UserData = itemPrefab, Color = itemPrefab.SpriteColor }; } @@ -1897,7 +1956,7 @@ namespace Barotrauma { if (string.IsNullOrWhiteSpace(text)) { - textBox.Flash(Color.Red); + textBox.Flash(GUI.Style.Red); return false; } @@ -1906,7 +1965,7 @@ namespace Barotrauma textBox.Text = text; - textBox.Flash(Color.Green); + textBox.Flash(GUI.Style.Green); return true; } @@ -1929,10 +1988,23 @@ namespace Barotrauma private bool SelectPrefab(GUIComponent component, object obj) { - if (GUI.MouseOn is GUIButton || GUI.MouseOn?.Parent is GUIButton) return false; + if (GUI.MouseOn is GUIButton || GUI.MouseOn?.Parent is GUIButton) { return false; } AddPreviouslyUsed(obj as MapEntityPrefab); + //if selecting a gap/hull/waypoint/spawnpoint, make sure the visibility is toggled on + if (obj is CoreEntityPrefab prefab) + { + var matchingTickBox = showEntitiesTickBoxes.Find(tb => tb.UserData as string == prefab.Identifier); + if (matchingTickBox != null && !matchingTickBox.Selected) + { + previouslyUsedPanel.Visible = false; + showEntitiesPanel.Visible = true; + matchingTickBox.Selected = true; + matchingTickBox.Flash(GUI.Style.Green); + } + } + MapEntityPrefab.SelectPrefab(obj); GUI.ForceMouseOn(null); return false; @@ -1948,7 +2020,7 @@ namespace Barotrauma private void AddPreviouslyUsed(MapEntityPrefab mapEntityPrefab) { - if (previouslyUsedList == null || mapEntityPrefab == null) return; + if (previouslyUsedList == null || mapEntityPrefab == null) { return; } previouslyUsedList.Deselect(); @@ -1958,18 +2030,16 @@ namespace Barotrauma } var existing = previouslyUsedList.Content.FindChild(mapEntityPrefab); - if (existing != null) previouslyUsedList.Content.RemoveChild(existing); - - string name = ToolBox.LimitString(mapEntityPrefab.Name,15); + if (existing != null) { previouslyUsedList.Content.RemoveChild(existing); } var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), previouslyUsedList.Content.RectTransform) { MinSize = new Point(0, 15) }, - ToolBox.LimitString(name, GUI.SmallFont, previouslyUsedList.Rect.Width), font: GUI.SmallFont) + ToolBox.LimitString(mapEntityPrefab.Name, GUI.SmallFont, previouslyUsedList.Content.Rect.Width), font: GUI.SmallFont) { UserData = mapEntityPrefab }; textBlock.RectTransform.SetAsFirstChild(); } - + public void AutoHull() { for (int i = 0; i < MapEntity.mapEntityList.Count; i++) @@ -2280,7 +2350,9 @@ namespace Barotrauma { MapEntity.FilteredSelectedList.FirstOrDefault()?.AddToGUIUpdateList(); EntityMenu.AddToGUIUpdateList(); - LeftPanel.AddToGUIUpdateList(); + showEntitiesPanel.AddToGUIUpdateList(); + previouslyUsedPanel.AddToGUIUpdateList(); + entityCountPanel.AddToGUIUpdateList(); TopPanel.AddToGUIUpdateList(); if (WiringMode) @@ -2334,6 +2406,7 @@ namespace Barotrauma loadFrame = null; saveAssemblyFrame = null; CreateUI(); + UpdateEntityList(); } hullVolumeFrame.Visible = MapEntity.SelectedList.Any(s => s is Hull); @@ -2361,7 +2434,7 @@ namespace Barotrauma { if (dummyCharacter == null || Entity.FindEntityByID(dummyCharacter.ID) != dummyCharacter) { - SetCharacterMode(false); + SetMode(Mode.Default); } else { @@ -2447,7 +2520,7 @@ namespace Barotrauma EntityMenu.RectTransform.ScreenSpaceOffset = Vector2.Lerp(new Vector2(0.0f, EntityMenu.Rect.Height - 10), Vector2.Zero, entityMenuOpenState).ToPoint(); - if (WiringMode) + if (WiringMode && dummyCharacter != null) { if (!dummyCharacter.SelectedItems.Any(it => it != null && it.HasTag("wire"))) { @@ -2462,11 +2535,17 @@ namespace Barotrauma if (loadFrame != null) { - if (PlayerInput.SecondaryMouseButtonClicked()) loadFrame = null; + if (PlayerInput.SecondaryMouseButtonClicked()) + { + loadFrame = null; + } } else if (saveFrame != null) { - if (PlayerInput.SecondaryMouseButtonClicked()) saveFrame = null; + if (PlayerInput.SecondaryMouseButtonClicked()) + { + saveFrame = null; + } } if ((CharacterMode || WiringMode) && dummyCharacter != null) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs index bd94a7643..15f332f9e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs @@ -12,6 +12,8 @@ namespace Barotrauma { private int elementHeight; private GUILayoutGroup layoutGroup; + private float inputFieldWidth = 0.5f; + private float largeInputFieldWidth = 0.8f; #if DEBUG public static List MissingLocalizations = new List(); #endif @@ -55,7 +57,7 @@ namespace Barotrauma numInput.FloatValue = f; if (flash) { - numInput.Flash(Color.LightGreen); + numInput.Flash(GUI.Style.Green); } } } @@ -72,7 +74,7 @@ namespace Barotrauma numInput.IntValue = integer; if (flash) { - numInput.Flash(Color.LightGreen); + numInput.Flash(GUI.Style.Green); } } } @@ -85,7 +87,7 @@ namespace Barotrauma tickBox.Selected = b; if (flash) { - tickBox.Flash(Color.LightGreen); + tickBox.Flash(GUI.Style.Green); } } } @@ -96,7 +98,7 @@ namespace Barotrauma textBox.Text = s; if (flash) { - textBox.Flash(Color.LightGreen); + textBox.Flash(GUI.Style.Green); } } } @@ -107,7 +109,7 @@ namespace Barotrauma dropDown.Select((int)newValue); if (flash) { - dropDown.Flash(Color.LightGreen); + dropDown.Flash(GUI.Style.Green); } } } @@ -123,7 +125,7 @@ namespace Barotrauma numInput.FloatValue = i == 0 ? v2.X : v2.Y; if (flash) { - numInput.Flash(Color.LightGreen); + numInput.Flash(GUI.Style.Green); } } } @@ -152,7 +154,7 @@ namespace Barotrauma } if (flash) { - numInput.Flash(Color.LightGreen); + numInput.Flash(GUI.Style.Green); } } } @@ -184,7 +186,7 @@ namespace Barotrauma } if (flash) { - numInput.Flash(Color.LightGreen); + numInput.Flash(GUI.Style.Green); } } } @@ -216,7 +218,7 @@ namespace Barotrauma } if (flash) { - numInput.Flash(Color.LightGreen); + numInput.Flash(GUI.Style.Green); } } } @@ -248,7 +250,7 @@ namespace Barotrauma } if (flash) { - numInput.Flash(Color.LightGreen); + numInput.Flash(GUI.Style.Green); } } } @@ -264,8 +266,15 @@ namespace Barotrauma public SerializableEntityEditor(RectTransform parent, ISerializableEntity entity, IEnumerable properties, bool showName, string style = "", int elementHeight = 24, ScalableFont titleFont = null) : base(style, new RectTransform(Vector2.One, parent)) { - this.elementHeight = (int)(elementHeight * GUI.Scale); - layoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, RectTransform)) { AbsoluteSpacing = 2 }; + this.elementHeight = (int)(elementHeight * GUI.Scale); + var tickBoxStyle = GUI.Style.GetComponentStyle("GUITickBox"); + var textBoxStyle = GUI.Style.GetComponentStyle("GUITextBox"); + var numberInputStyle = GUI.Style.GetComponentStyle("GUINumberInput"); + if (tickBoxStyle.Height.HasValue) { this.elementHeight = Math.Max(tickBoxStyle.Height.Value, this.elementHeight); } + if (textBoxStyle.Height.HasValue) { this.elementHeight = Math.Max(textBoxStyle.Height.Value, this.elementHeight); } + if (numberInputStyle.Height.HasValue) { this.elementHeight = Math.Max(numberInputStyle.Height.Value, this.elementHeight); } + + layoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, RectTransform)) { AbsoluteSpacing = (int)(5 * GUI.Scale) }; if (showName) { new GUITextBlock(new RectTransform(new Point(layoutGroup.Rect.Width, this.elementHeight), layoutGroup.RectTransform), entity.Name, font: titleFont ?? GUI.Font) @@ -284,6 +293,7 @@ namespace Barotrauma { component.RectTransform.Parent = layoutGroup.RectTransform; component.RectTransform.RepositionChildInHierarchy(childIndex); + layoutGroup.Recalculate(); Recalculate(); } @@ -403,7 +413,7 @@ namespace Barotrauma public GUIComponent CreateIntField(ISerializableEntity entity, SerializableProperty property, int value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip }; @@ -411,7 +421,7 @@ namespace Barotrauma GUIComponent field; if (editableAttribute.ReadOnly) { - var numberInput = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform, Anchor.TopRight), value.ToString()) + var numberInput = new GUITextBlock(new RectTransform(new Vector2(inputFieldWidth, 1), frame.RectTransform, Anchor.TopRight), value.ToString()) { ToolTip = toolTip, Font = GUI.SmallFont @@ -420,7 +430,7 @@ namespace Barotrauma } else { - var numberInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform, Anchor.TopRight), GUINumberInput.NumberType.Int) + var numberInput = new GUINumberInput(new RectTransform(new Vector2(inputFieldWidth, 1), frame.RectTransform, Anchor.TopRight), GUINumberInput.NumberType.Int) { ToolTip = toolTip, Font = GUI.SmallFont @@ -444,12 +454,12 @@ namespace Barotrauma public GUIComponent CreateFloatField(ISerializableEntity entity, SerializableProperty property, float value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - 1, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip }; - GUINumberInput numberInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform, + GUINumberInput numberInput = new GUINumberInput(new RectTransform(new Vector2(inputFieldWidth, 1), frame.RectTransform, Anchor.TopRight), GUINumberInput.NumberType.Float) { ToolTip = toolTip, @@ -461,6 +471,7 @@ namespace Barotrauma numberInput.DecimalsToDisplay = editableAttribute.DecimalCount; numberInput.valueStep = editableAttribute.ValueStep; numberInput.FloatValue = value; + numberInput.OnValueChanged += (numInput) => { if (property.TrySetValue(entity, numInput.FloatValue)) @@ -475,11 +486,11 @@ namespace Barotrauma public GUIComponent CreateEnumField(ISerializableEntity entity, SerializableProperty property, object value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip }; - GUIDropDown enumDropDown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform, Anchor.TopRight), + GUIDropDown enumDropDown = new GUIDropDown(new RectTransform(new Vector2(inputFieldWidth, 1), frame.RectTransform, Anchor.TopRight), elementCount: Enum.GetValues(value.GetType()).Length) { ToolTip = toolTip @@ -504,11 +515,11 @@ namespace Barotrauma public GUIComponent CreateEnumFlagField(ISerializableEntity entity, SerializableProperty property, object value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip }; - GUIDropDown enumDropDown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform, Anchor.TopRight), + GUIDropDown enumDropDown = new GUIDropDown(new RectTransform(new Vector2(inputFieldWidth, 1), frame.RectTransform, Anchor.TopRight), elementCount: Enum.GetValues(value.GetType()).Length, selectMultiple: true) { ToolTip = toolTip @@ -536,16 +547,20 @@ namespace Barotrauma public GUIComponent CreateStringField(ISerializableEntity entity, SerializableProperty property, string value, string displayName, string toolTip) { - var frame = new GUILayoutGroup(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), isHorizontal: true) + var frame = new GUILayoutGroup(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true }; - var label = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform), displayName, font: GUI.SmallFont, textAlignment: Alignment.Left) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont, textAlignment: Alignment.Left) { ToolTip = toolTip }; + string translationTextTag = property.GetAttribute()?.translationTextTag; + float browseButtonWidth = 0.1f; var editableAttribute = property.GetAttribute(); - GUITextBox propertyBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform)) + float textBoxWidth = inputFieldWidth; + if (translationTextTag != null) { textBoxWidth -= browseButtonWidth; } + GUITextBox propertyBox = new GUITextBox(new RectTransform(new Vector2(textBoxWidth, 1), frame.RectTransform)) { Enabled = editableAttribute != null && !editableAttribute.ReadOnly, ToolTip = toolTip, @@ -563,10 +578,9 @@ namespace Barotrauma return true; } }; - string translationTextTag = property.GetAttribute()?.translationTextTag; if (translationTextTag != null) { - new GUIButton(new RectTransform(new Vector2(0.1f, 1), frame.RectTransform, Anchor.TopRight), "...") + new GUIButton(new RectTransform(new Vector2(browseButtonWidth, 1), frame.RectTransform, Anchor.TopRight), "...", style: "GUIButtonSmall") { OnClicked = (bt, userData) => { CreateTextPicker(translationTextTag, entity, property, propertyBox); return true; } }; @@ -580,14 +594,14 @@ namespace Barotrauma } else { - propertyBox.TextColor = Color.LightGreen; + propertyBox.TextColor = GUI.Style.Green; propertyBox.ToolTip = TextManager.GetWithVariable("StringPropertyTranslate", "[translation]", translatedText); } return true; }; propertyBox.Text = value; } - + frame.RectTransform.MinSize = new Point(0, frame.RectTransform.Children.Max(c => c.MinSize.Y)); if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, new GUIComponent[] { propertyBox }); } return frame; } @@ -595,11 +609,11 @@ namespace Barotrauma public GUIComponent CreatePointField(ISerializableEntity entity, SerializableProperty property, Point value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip }; - var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) + var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(inputFieldWidth, 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) { Stretch = true, RelativeSpacing = 0.05f @@ -640,6 +654,7 @@ namespace Barotrauma }; fields[i] = numberInput; } + frame.RectTransform.MinSize = new Point(0, frame.RectTransform.Children.Max(c => c.MinSize.Y)); if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); } return frame; } @@ -647,11 +662,11 @@ namespace Barotrauma public GUIComponent CreateVector2Field(ISerializableEntity entity, SerializableProperty property, Vector2 value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip }; - var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) + var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(inputFieldWidth, 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) { Stretch = true, RelativeSpacing = 0.05f @@ -694,6 +709,7 @@ namespace Barotrauma }; fields[i] = numberInput; } + frame.RectTransform.MinSize = new Point(0, frame.RectTransform.Children.Max(c => c.MinSize.Y)); if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); } return frame; } @@ -701,11 +717,11 @@ namespace Barotrauma public GUIComponent CreateVector3Field(ISerializableEntity entity, SerializableProperty property, Vector3 value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - largeInputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip }; - var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) + var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(largeInputFieldWidth, 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) { Stretch = true, RelativeSpacing = 0.03f @@ -752,6 +768,7 @@ namespace Barotrauma }; fields[i] = numberInput; } + frame.RectTransform.MinSize = new Point(0, frame.RectTransform.Children.Max(c => c.MinSize.Y)); if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); } return frame; } @@ -759,13 +776,13 @@ namespace Barotrauma public GUIComponent CreateVector4Field(ISerializableEntity entity, SerializableProperty property, Vector4 value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - largeInputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip }; var editableAttribute = property.GetAttribute(); var fields = new GUIComponent[4]; - var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) + var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(largeInputFieldWidth, 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) { Stretch = true, RelativeSpacing = 0.01f @@ -814,6 +831,7 @@ namespace Barotrauma }; fields[i] = numberInput; } + frame.RectTransform.MinSize = new Point(0, frame.RectTransform.Children.Max(c => c.MinSize.Y)); if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); } return frame; } @@ -821,15 +839,16 @@ namespace Barotrauma public GUIComponent CreateColorField(ISerializableEntity entity, SerializableProperty property, Color value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), frame.RectTransform) { MinSize = new Point(80, 26) }, displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - largeInputFieldWidth, 1), frame.RectTransform) { MinSize = new Point(80, 26) }, displayName, font: GUI.SmallFont) { - ToolTip = toolTip + ToolTip = displayName + '\n' + toolTip }; - var colorBoxBack = new GUIFrame(new RectTransform(new Vector2(0.075f, 1), frame.RectTransform) + label.Text = ToolBox.LimitString(label.Text, label.Font, label.Rect.Width); + var colorBoxBack = new GUIFrame(new RectTransform(new Vector2(0.04f, 1), frame.RectTransform) { AbsoluteOffset = new Point(label.Rect.Width, 0) }, color: Color.Black, style: null); - var colorBox = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), colorBoxBack.RectTransform, Anchor.Center), style: null); + var colorBox = new GUIFrame(new RectTransform(new Vector2(largeInputFieldWidth, 0.9f), colorBoxBack.RectTransform, Anchor.Center), style: null); var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(Math.Max((frame.Rect.Width - label.Rect.Width - colorBoxBack.Rect.Width) / (float)frame.Rect.Width, 0.5f), 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) { Stretch = true, @@ -838,7 +857,7 @@ namespace Barotrauma var fields = new GUIComponent[4]; for (int i = 3; i >= 0; i--) { - var element = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 1), inputArea.RectTransform), isHorizontal: true) + var element = new GUILayoutGroup(new RectTransform(new Vector2(0.18f, 1), inputArea.RectTransform), isHorizontal: true) { Stretch = true }; @@ -884,6 +903,7 @@ namespace Barotrauma colorBox.Color = (Color)property.GetValue(entity); fields[i] = numberInput; } + frame.RectTransform.MinSize = new Point(0, frame.RectTransform.Children.Max(c => c.MinSize.Y)); if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); } return frame; } @@ -891,10 +911,11 @@ namespace Barotrauma public GUIComponent CreateRectangleField(ISerializableEntity entity, SerializableProperty property, Rectangle value, string displayName, string toolTip) { var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent); - var label = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) + var label = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { - ToolTip = toolTip + ToolTip = displayName + '\n' + toolTip }; + label.Text = ToolBox.LimitString(label.Text, label.Font, label.Rect.Width); var fields = new GUIComponent[4]; var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1), frame.RectTransform, Anchor.TopRight), isHorizontal: true, childAnchor: Anchor.CenterRight) { @@ -904,7 +925,7 @@ namespace Barotrauma for (int i = 3; i >= 0; i--) { var element = new GUIFrame(new RectTransform(new Vector2(0.22f, 1), inputArea.RectTransform) { MinSize = new Point(50, 0), MaxSize = new Point(150, 50) }, style: null); - new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), element.RectTransform, Anchor.CenterLeft), GUI.rectComponentLabels[i], font: GUI.SmallFont, textAlignment: Alignment.CenterLeft); + new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), element.RectTransform, Anchor.CenterLeft), GUI.rectComponentLabels[i], font: GUI.SmallFont, textAlignment: Alignment.Center); GUINumberInput numberInput = new GUINumberInput(new RectTransform(new Vector2(0.7f, 1), element.RectTransform, Anchor.CenterRight), GUINumberInput.NumberType.Int) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundChannel.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundChannel.cs index 41574aa96..cb28e241c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundChannel.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundChannel.cs @@ -512,7 +512,11 @@ namespace Barotrauma.Sounds return debugName; } - public bool FadingOutAndDisposing; + public bool FadingOutAndDisposing + { + get; + private set; + } public void FadeOutAndDispose() { FadingOutAndDisposing = true; diff --git a/Barotrauma/BarotraumaClient/Content/Effects/gradientshader.xnb b/Barotrauma/BarotraumaClient/Content/Effects/gradientshader.xnb new file mode 100644 index 000000000..97847aa2d Binary files /dev/null and b/Barotrauma/BarotraumaClient/Content/Effects/gradientshader.xnb differ diff --git a/Barotrauma/BarotraumaClient/Content/Effects/gradientshader_opengl.xnb b/Barotrauma/BarotraumaClient/Content/Effects/gradientshader_opengl.xnb new file mode 100644 index 000000000..480658200 Binary files /dev/null and b/Barotrauma/BarotraumaClient/Content/Effects/gradientshader_opengl.xnb differ diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 1509d2d51..cdcfe3c8e 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.9.701.0 + 0.9.702.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index e7ff4f8da..d6414dc0d 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.9.701.0 + 0.9.702.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/Properties/launchSettings.json b/Barotrauma/BarotraumaClient/Properties/launchSettings.json new file mode 100644 index 000000000..cc9cae3a3 --- /dev/null +++ b/Barotrauma/BarotraumaClient/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "WindowsClient": { + "commandName": "Project", + "nativeDebugging": false + } + } +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/Shaders/Content.mgcb b/Barotrauma/BarotraumaClient/Shaders/Content.mgcb index cc09bad54..168994193 100644 --- a/Barotrauma/BarotraumaClient/Shaders/Content.mgcb +++ b/Barotrauma/BarotraumaClient/Shaders/Content.mgcb @@ -31,6 +31,12 @@ /processorParam:DebugMode=Auto /build:deformshader.fx +#begin gradientshader.fx +/importer:EffectImporter +/processor:EffectProcessor +/processorParam:DebugMode=Auto +/build:gradientshader.fx + #begin losshader.fx /importer:EffectImporter /processor:EffectProcessor @@ -43,15 +49,15 @@ /processorParam:DebugMode=Auto /build:postprocess.fx -#begin watershader.fx -/importer:EffectImporter -/processor:EffectProcessor -/processorParam:DebugMode=Auto -/build:watershader.fx - #begin solidcolor.fx /importer:EffectImporter /processor:EffectProcessor /processorParam:DebugMode=Auto /build:solidcolor.fx +#begin watershader.fx +/importer:EffectImporter +/processor:EffectProcessor +/processorParam:DebugMode=Auto +/build:watershader.fx + diff --git a/Barotrauma/BarotraumaClient/Shaders/Content_opengl.mgcb b/Barotrauma/BarotraumaClient/Shaders/Content_opengl.mgcb index 6606ae7ca..2d201daec 100644 --- a/Barotrauma/BarotraumaClient/Shaders/Content_opengl.mgcb +++ b/Barotrauma/BarotraumaClient/Shaders/Content_opengl.mgcb @@ -36,6 +36,12 @@ /processorParam:DebugMode=Auto /build:deformshader_opengl.fx +#begin gradientshader_opengl.fx +/importer:EffectImporter +/processor:EffectProcessor +/processorParam:DebugMode=Auto +/build:gradientshader_opengl.fx + #begin losshader_opengl.fx /importer:EffectImporter /processor:EffectProcessor diff --git a/Barotrauma/BarotraumaClient/Shaders/gradientshader.fx b/Barotrauma/BarotraumaClient/Shaders/gradientshader.fx new file mode 100644 index 000000000..26e364323 --- /dev/null +++ b/Barotrauma/BarotraumaClient/Shaders/gradientshader.fx @@ -0,0 +1,24 @@ +sampler TextureSampler : register(s0); + +float4 color1; +float4 color2; +float midPoint; +float fadeDist; + +float4 PixelShaderF(float4 position : SV_Position, float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0 +{ + float4 t = tex2D(TextureSampler, texCoord); + + float a = saturate(((texCoord.y - midPoint) / fadeDist) + 0.5); + + return t * (color1 * a + color2 * (1.0-a)); +} + + +technique Gradient +{ + pass Pass1 + { + PixelShader = compile ps_4_0_level_9_1 PixelShaderF(); + } +} diff --git a/Barotrauma/BarotraumaClient/Shaders/gradientshader_opengl.fx b/Barotrauma/BarotraumaClient/Shaders/gradientshader_opengl.fx new file mode 100644 index 000000000..ab209fa73 --- /dev/null +++ b/Barotrauma/BarotraumaClient/Shaders/gradientshader_opengl.fx @@ -0,0 +1,24 @@ +sampler TextureSampler : register(s0); + +float4 color1; +float4 color2; +float midPoint; +float fadeDist; + +float4 PixelShaderF(float4 position : SV_Position, float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0 +{ + float4 t = tex2D(TextureSampler, texCoord); + + float a = saturate(((texCoord.y - midPoint) / fadeDist) + 0.5); + + return t * (color1 * a + color2 * (1.0-a)); +} + + +technique Gradient +{ + pass Pass1 + { + PixelShader = compile ps_2_0 PixelShaderF(); + } +} diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index aed256881..4f701d93f 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.9.701.0 + 0.9.702.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index dc3176212..e14f65a74 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.9.701.0 + 0.9.702.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 27ccac0b4..e1f5e4e95 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.9.701.0 + 0.9.702.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs index 18037c405..21e81d07c 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs @@ -2,6 +2,7 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; +using System.Linq; namespace Barotrauma { @@ -264,7 +265,8 @@ namespace Barotrauma { case NetEntityEvent.Type.InventoryState: msg.WriteRangedInteger(0, 0, 3); - Inventory.SharedWrite(msg, extraData); + msg.Write(GameMain.Server.EntityEventManager.Events.Last()?.ID ?? (ushort)0); + Inventory.ServerWrite(msg, c); break; case NetEntityEvent.Type.Control: msg.WriteRangedInteger(1, 0, 3); diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs index 7002988f0..727947c01 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs @@ -347,6 +347,7 @@ namespace Barotrauma Timing.Accumulator -= Timing.Step; } +#if !DEBUG if (Server?.OwnerConnection == null && !Console.IsOutputRedirected) { DebugConsole.UpdateCommandLine((int)(Timing.Accumulator * 800)); @@ -355,6 +356,9 @@ namespace Barotrauma { DebugConsole.Clear(); } +#else + DebugConsole.UpdateCommandLine((int)(Timing.Accumulator * 800)); +#endif int frameTime = (int)(((double)(stopwatch.ElapsedTicks - prevTicks) / frequency) * 1000.0); frameTime = Math.Max(0, frameTime); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs index 1fdfb5d1f..9069c1946 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs @@ -24,10 +24,10 @@ namespace Barotrauma.Items.Components if (!autoTemp && AutoTemp) blameOnBroken = c; if (turbineOutput < targetTurbineOutput) blameOnBroken = c; if (fissionRate > targetFissionRate) blameOnBroken = c; - if (!this.shutDown && shutDown) blameOnBroken = c; + if (!this._powerOn && shutDown) blameOnBroken = c; AutoTemp = autoTemp; - this.shutDown = shutDown; + this._powerOn = shutDown; targetFissionRate = fissionRate; targetTurbineOutput = turbineOutput; @@ -44,7 +44,7 @@ namespace Barotrauma.Items.Components public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null) { msg.Write(autoTemp); - msg.Write(shutDown); + msg.Write(_powerOn); msg.WriteRangedSingle(temperature, 0.0f, 100.0f, 8); msg.WriteRangedSingle(targetFissionRate, 0.0f, 100.0f, 8); msg.WriteRangedSingle(targetTurbineOutput, 0.0f, 100.0f, 8); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Item.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Item.cs index ba44d677e..ec8bab21b 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Item.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Item.cs @@ -75,6 +75,7 @@ namespace Barotrauma break; } msg.WriteRangedInteger(containerIndex, 0, components.Count - 1); + msg.Write(GameMain.Server.EntityEventManager.Events.Last()?.ID ?? (ushort)0); (components[containerIndex] as ItemContainer).Inventory.ServerWrite(msg, c); break; case NetEntityEvent.Type.Status: diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index 80ce75d4f..db79485db 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -765,6 +765,11 @@ namespace Barotrauma.Networking private void WriteEventErrorData(Client client, string errorStr) { + if (!Directory.Exists(ServerLog.SavePath)) + { + Directory.CreateDirectory(ServerLog.SavePath); + } + string filePath = "event_error_log_server_" + client.Name + "_" + ToolBox.RemoveInvalidFileNameChars(DateTime.UtcNow.ToShortTimeString() + ".log"); filePath = Path.Combine(ServerLog.SavePath, filePath); if (File.Exists(filePath)) { return; } @@ -774,6 +779,19 @@ namespace Barotrauma.Networking errorStr, "" }; + if (GameMain.GameSession?.GameMode != null) + { + errorLines.Add("Game mode: " + GameMain.GameSession.GameMode.Name); + } + if (GameMain.GameSession?.Submarine != null) + { + errorLines.Add("Submarine: " + GameMain.GameSession.Submarine.Name); + } + if (Level.Loaded != null) + { + errorLines.Add("Level: " + Level.Loaded.Seed + ", " + Level.Loaded.EqualityCheckVal); + } + errorLines.Add("Entity IDs:"); List sortedEntities = Entity.GetEntityList(); sortedEntities.Sort((e1, e2) => e1.ID.CompareTo(e2.ID)); @@ -797,6 +815,13 @@ namespace Barotrauma.Networking } } + errorLines.Add(""); + errorLines.Add("Last debug messages:"); + for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i--) + { + errorLines.Add(" " + DebugConsole.Messages[i].Time + " - " + DebugConsole.Messages[i].Text); + } + File.WriteAllLines(filePath, errorLines); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs index ecf7b22a5..f64f8c05a 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs @@ -67,7 +67,7 @@ namespace Barotrauma.Networking { AcceptIncomingConnections = true, AutoExpandMTU = false, - MaximumConnections = serverSettings.MaxPlayers * 2, + MaximumConnections = NetConfig.MaxPlayers * 2, EnableUPnP = serverSettings.EnableUPnP, Port = serverSettings.Port }; @@ -80,7 +80,7 @@ namespace Barotrauma.Networking netPeerConfiguration.EnableMessageType(NetIncomingMessageType.ConnectionApproval); netServer = new NetServer(netPeerConfiguration); - + netServer.Start(); if (serverSettings.EnableUPnP) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs index c3431013d..01d687ea4 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs @@ -48,7 +48,7 @@ namespace Barotrauma.Networking outMsg.Write(ServerMessageText); outMsg.Write((byte)MaxPlayers); outMsg.Write(HasPassword); - outMsg.Write(isPublic); + outMsg.Write(IsPublic); outMsg.WritePadBits(); outMsg.WriteRangedInteger(TickRate, 1, 60); @@ -186,12 +186,11 @@ namespace Barotrauma.Networking SerializableProperty.SerializeProperties(this, doc.Root, true); doc.Root.SetAttributeValue("name", ServerName); - doc.Root.SetAttributeValue("public", isPublic); + doc.Root.SetAttributeValue("public", IsPublic); doc.Root.SetAttributeValue("port", Port); #if USE_STEAM doc.Root.SetAttributeValue("queryport", QueryPort); #endif - doc.Root.SetAttributeValue("maxplayers", maxPlayers); doc.Root.SetAttributeValue("enableupnp", EnableUPnP); doc.Root.SetAttributeValue("autorestart", autoRestart); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Program.cs b/Barotrauma/BarotraumaServer/ServerSource/Program.cs index 27efc58e8..ccdf0b14b 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Program.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Program.cs @@ -25,20 +25,19 @@ namespace Barotrauma { GameMain game = null; -#if !DEBUG || TRUE +#if !DEBUG try { #endif - Console.WriteLine("Barotrauma Dedicated Server " + GameMain.Version + " (" + AssemblyInfo.GetBuildString() + ", branch " + AssemblyInfo.GetGitBranch() + ", revision " + AssemblyInfo.GetGitRevision() + ")"); game = new GameMain(args); game.Run(); - if (GameSettings.SendUserStatistics) GameAnalytics.OnQuit(); + if (GameSettings.SendUserStatistics) { GameAnalytics.OnQuit(); } SteamManager.ShutDown(); -#if !DEBUG || TRUE +#if !DEBUG } catch (Exception e) { diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 8f179e660..fdf2b7c3b 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.9.701.0 + 0.9.702.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/.gitignore b/Barotrauma/BarotraumaShared/.gitignore new file mode 100644 index 000000000..a2c944923 --- /dev/null +++ b/Barotrauma/BarotraumaShared/.gitignore @@ -0,0 +1 @@ +Content/* diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/AITarget.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/AITarget.cs index 9eda2048f..167119088 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/AITarget.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/AITarget.cs @@ -9,10 +9,14 @@ namespace Barotrauma { public static List List = new List(); + private Entity entity; public Entity Entity { - get; - private set; + get + { + if (entity != null && entity.Removed) { return null; } + return entity; + } } private float soundRange; @@ -28,13 +32,29 @@ namespace Barotrauma public float SoundRange { get { return soundRange; } - set { soundRange = MathHelper.Clamp(value, MinSoundRange, MaxSoundRange); } + set + { + if (float.IsNaN(value)) + { + DebugConsole.ThrowError("Attempted to set the SoundRange of an AITarget to NaN.\n" + Environment.StackTrace); + return; + } + soundRange = MathHelper.Clamp(value, MinSoundRange, MaxSoundRange); + } } public float SightRange { get { return sightRange; } - set { sightRange = MathHelper.Clamp(value, MinSightRange, MaxSightRange); } + set + { + if (float.IsNaN(value)) + { + DebugConsole.ThrowError("Attempted to set the SightRange of an AITarget to NaN.\n" + Environment.StackTrace); + return; + } + sightRange = MathHelper.Clamp(value, MinSightRange, MaxSightRange); + } } private float sectorRad = MathHelper.TwoPi; @@ -54,7 +74,7 @@ namespace Barotrauma { string errorMsg = "Invalid AITarget sector direction (" + value + ")\n" + Environment.StackTrace; DebugConsole.ThrowError(errorMsg); - GameAnalyticsManager.AddErrorEventOnce("AITarget.SectorDir:" + Entity?.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); + GameAnalyticsManager.AddErrorEventOnce("AITarget.SectorDir:" + entity?.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); return; } sectorDir = value; @@ -88,7 +108,7 @@ namespace Barotrauma { get { - if (Entity == null || Entity.Removed) + if (entity == null || entity.Removed) { #if DEBUG DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace); @@ -99,7 +119,7 @@ namespace Barotrauma return Vector2.Zero; } - return Entity.WorldPosition; + return entity.WorldPosition; } } @@ -107,7 +127,7 @@ namespace Barotrauma { get { - if (Entity == null || Entity.Removed) + if (entity == null || entity.Removed) { #if DEBUG DebugConsole.ThrowError("Attempted to access a removed AITarget\n" + Environment.StackTrace); @@ -118,7 +138,7 @@ namespace Barotrauma return Vector2.Zero; } - return Entity.SimPosition; + return entity.SimPosition; } } @@ -156,7 +176,7 @@ namespace Barotrauma public AITarget(Entity e) { - Entity = e; + entity = e; List.Add(this); } @@ -181,7 +201,7 @@ namespace Barotrauma public void Remove() { List.Remove(this); - Entity = null; + entity = null; } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs index 75fd533bc..792fd6ae3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs @@ -89,6 +89,9 @@ namespace Barotrauma private readonly float memoryFadeTime = 0.5f; private readonly float avoidTime = 3; + //Has the character been attacked since the last Update. + private bool wasAttacked; + private float avoidTimer; public LatchOntoAI LatchOntoAI { get; private set; } @@ -231,7 +234,15 @@ namespace Barotrauma public override void Update(float deltaTime) { + if (wasAttacked) + { + LatchOntoAI?.DeattachFromBody(); + Character.AnimController.ReleaseStuckLimbs(); + wasAttacked = false; + } + if (DisableEnemyAI) { return; } + base.Update(deltaTime); bool ignorePlatforms = (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); @@ -630,7 +641,7 @@ namespace Barotrauma if (pickable != null) { var target = pickable.Picker?.AiTarget; - if (target != null) + if (target?.Entity != null && !target.Entity.Removed) { SelectedAiTarget = target; } @@ -1224,14 +1235,13 @@ namespace Barotrauma } return isDisabled; } - + public override void OnAttacked(Character attacker, AttackResult attackResult) { float reactionTime = Rand.Range(0.1f, 0.3f); updateTargetsTimer = Math.Min(updateTargetsTimer, reactionTime); - - LatchOntoAI?.DeattachFromBody(); - Character.AnimController.ReleaseStuckLimbs(); + + wasAttacked = true; if (attacker == null || attacker.AiTarget == null) { return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveManager.cs index 53861173b..cdf43f230 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveManager.cs @@ -131,6 +131,8 @@ namespace Barotrauma } coroutine = CoroutineManager.InvokeAfter(() => { + //round ended before the coroutine finished + if (GameMain.GameSession == null || Level.Loaded == null) { return; } DelayedObjectives.Remove(objective); AddObjective(objective); callback?.Invoke(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs index 41a860a35..3d279cb85 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs @@ -2,15 +2,30 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; -using System.IO; using System.Xml.Linq; using System.Linq; namespace Barotrauma { + public enum OrderCategory + { + Emergency, + Movement, + Power, + Maintenance, + Operate, + Undefined + } + class Order { public static Dictionary Prefabs { get; private set; } + public static Dictionary OrderCategoryIcons { get; private set; } + public static Sprite StartNode { get; private set; } + public static Sprite ShortcutNode { get; private set; } + public static Sprite ExpandNode { get; private set; } + public static Sprite NodeContainer { get; private set; } + public static Sprite CommandBackground { get; private set; } public static List PrefabList { get; private set; } public static Order GetPrefab(string identifier) { @@ -49,15 +64,20 @@ namespace Barotrauma public Controller ConnectedController; public Character OrderGiver; - + + public readonly OrderCategory Category; + //legacy support public readonly string[] AppropriateJobs; public readonly string[] Options; public readonly string[] OptionNames; + public readonly Dictionary OptionSprites; + static Order() { Prefabs = new Dictionary(); + OrderCategoryIcons = new Dictionary(); foreach (ContentFile file in GameMain.Instance.GetFilesOfType(ContentType.Orders)) { @@ -72,11 +92,11 @@ namespace Barotrauma } foreach (XElement sourceElement in mainElement.Elements()) { - var orderElement = sourceElement.IsOverride() ? sourceElement.FirstElement() : sourceElement; - string name = orderElement.Name.ToString(); + var element = sourceElement.IsOverride() ? sourceElement.FirstElement() : sourceElement; + string name = element.Name.ToString(); if (name.Equals("order", StringComparison.OrdinalIgnoreCase)) { - string identifier = orderElement.GetAttributeString("identifier", null); + string identifier = element.GetAttributeString("identifier", null); if (string.IsNullOrWhiteSpace(identifier)) { DebugConsole.ThrowError($"Error in file {file.Path}: The order element '{name}' does not have an identifier! All orders must have a unique identifier."); @@ -95,10 +115,58 @@ namespace Barotrauma continue; } } - var newOrder = new Order(orderElement); + var newOrder = new Order(element); newOrder.Prefab = newOrder; Prefabs.Add(identifier, newOrder); } + else if (name.Equals("ordercategory", StringComparison.OrdinalIgnoreCase)) + { + var category = (OrderCategory)Enum.Parse(typeof(OrderCategory), element.GetAttributeString("category", "undefined"), true); + if (OrderCategoryIcons.TryGetValue(category, out Sprite duplicate)) + { + if (allowOverriding || sourceElement.IsOverride()) + { + DebugConsole.NewMessage($"Overriding an existing icon for the '{category}' order category with another one defined in '{file}'", Color.Yellow); + OrderCategoryIcons.Remove(category); + } + else + { + DebugConsole.ThrowError($"Error in file {file}: Duplicate element for the '{category}' order category found in '{file}'! All order categories must be unique. Use tags to override an order category."); + continue; + } + } + var spriteElement = element.GetChildElement("sprite"); + if (spriteElement != null) + { + var sprite = new Sprite(spriteElement, lazyLoad: true); + OrderCategoryIcons.Add(category, sprite); + } + } + else + { + var spriteElement = element.GetChildElement("sprite"); + if (spriteElement != null) + { + switch (name.ToLowerInvariant()) + { + case "startnode": + StartNode = new Sprite(spriteElement, lazyLoad: true); + break; + case "shortcutnode": + ShortcutNode = new Sprite(spriteElement, lazyLoad: true); + break; + case "expandnode": + ExpandNode = new Sprite(spriteElement, lazyLoad: true); + break; + case "nodecontainer": + NodeContainer = new Sprite(spriteElement, lazyLoad: true); + break; + case "commandbackground": + CommandBackground = new Sprite(spriteElement, lazyLoad: true); + break; + } + } + } } } PrefabList = new List(Prefabs.Values); @@ -130,6 +198,7 @@ namespace Barotrauma TargetAllCharacters = orderElement.GetAttributeBool("targetallcharacters", false); AppropriateJobs = orderElement.GetAttributeStringArray("appropriatejobs", new string[0]); Options = orderElement.GetAttributeStringArray("options", new string[0]); + Category = (OrderCategory)Enum.Parse(typeof(OrderCategory), orderElement.GetAttributeString("category", "undefined"), true); string translatedOptionNames = TextManager.Get("OrderOptions." + Identifier, true); if (translatedOptionNames == null) @@ -152,13 +221,24 @@ namespace Barotrauma OptionNames = Options; } - foreach (XElement subElement in orderElement.Elements()) + var spriteElement = orderElement.GetChildElement("sprite"); + if (spriteElement != null) { - switch (subElement.Name.ToString().ToLowerInvariant()) + SymbolSprite = new Sprite(spriteElement, lazyLoad: true); + } + + OptionSprites = new Dictionary(); + if (Options != null && Options.Length > 0) + { + var optionSpriteElements = orderElement.GetChildElement("optionsprites")?.GetChildElements("sprite"); + if (optionSpriteElements != null && optionSpriteElements.Any()) { - case "sprite": - SymbolSprite = new Sprite(subElement, lazyLoad: true); - break; + for (int i = 0; i < Options.Length; i++) + { + if (i >= optionSpriteElements.Count()) { break; }; + var sprite = new Sprite(optionSpriteElements.ElementAt(i), lazyLoad: true); + OptionSprites.Add(Options[i], sprite); + } } } } @@ -226,5 +306,4 @@ namespace Barotrauma return msg; } } - } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs index eaaf6aef5..caf7425cf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs @@ -1789,7 +1789,7 @@ namespace Barotrauma } } - item.SetTransform(currItemPos, itemAngle + itemAngleRelativeToHoldAngle * Dir); + item.SetTransform(currItemPos, itemAngle + itemAngleRelativeToHoldAngle * Dir, setPrevTransform: false); if (!isClimbing) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs index d12338726..69a8abfe6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs @@ -958,8 +958,8 @@ namespace Barotrauma else { if (character.Position.X < gap.Rect.X || character.Position.X > gap.Rect.Right) continue; - if (Math.Sign((gap.Rect.Y - gap.Rect.Height / 2) - (currentHull.Rect.Center.X - currentHull.Rect.Height / 2)) != - Math.Sign(character.Position.X - (currentHull.Rect.Center.X - currentHull.Rect.Height / 2))) + if (Math.Sign((gap.Rect.Y - gap.Rect.Height / 2) - (currentHull.Rect.Center.Y - currentHull.Rect.Height / 2)) != + Math.Sign(character.Position.Y - (currentHull.Rect.Center.Y - currentHull.Rect.Height / 2))) { continue; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs index c47d98feb..40b7dab76 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs @@ -311,6 +311,21 @@ namespace Barotrauma selectedCharacter = value; if (selectedCharacter != null) selectedCharacter.selectedBy = this; + +#if CLIENT + if (GameMain.GameSession == null) return; + // Quick & dirty hiding of the chat whenever a character with an accessible inventory is selected to prevent overlaps + if (GameMain.GameSession.CrewManager.IsSinglePlayer) + { + if (GameMain.GameSession.CrewManager.ChatBox == null) return; + GameMain.GameSession.CrewManager.ChatBox.SetVisibility(!(IsHumanoid && value != null && value.Inventory != null && value.CanInventoryBeAccessed)); + } + else + { + if (GameMain.Client?.ChatBox == null) return; + GameMain.Client.ChatBox.SetVisibility(!(IsHumanoid && value != null && value.Inventory != null && value.CanInventoryBeAccessed)); + } +#endif } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs index faf6e6af7..a725356f2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs @@ -260,6 +260,11 @@ namespace Barotrauma } } +#if CLIENT + private Sprite jobIcon; + private Vector2 jobIconPos; +#endif + private Sprite portraitBackground; public Sprite PortraitBackground { @@ -442,6 +447,13 @@ namespace Barotrauma CalculateHeadSpriteRange(); Head.HeadSpriteId = GetRandomHeadID(); Job = (jobPrefab == null) ? Job.Random(Rand.RandSync.Server) : new Job(jobPrefab, variant); +#if CLIENT + jobIcon = Job.Prefab.Icon; + //TODO: fix jobIconPos + jobIconPos = new Vector2(HUDLayoutSettings.HealthBarAreaLeft.Right, HUDLayoutSettings.HealthBarAreaLeft.Y - HUDLayoutSettings.Padding); + GameMain.Instance.OnResolutionChanged += () => jobIconPos = new Vector2(HUDLayoutSettings.HealthBarAreaLeft.Right, HUDLayoutSettings.HealthBarAreaLeft.Y - HUDLayoutSettings.Padding); +#endif + if (!string.IsNullOrEmpty(name)) { Name = name; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs index 574f2c273..23dc3f22d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs @@ -145,7 +145,7 @@ namespace Barotrauma AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength); if (currentEffect == null) return 0.0f; if (currentEffect.MaxResistance - currentEffect.MinResistance <= 0.0f) return 0.0f; - if (afflictionId != currentEffect.ResistanceFor) return 0.0f; + if (afflictionId != null && afflictionId != currentEffect.ResistanceFor) return 0.0f; return MathHelper.Lerp( currentEffect.MinResistance, diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs index e46f4167b..82316ab38 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs @@ -256,7 +256,7 @@ namespace Barotrauma public readonly string AchievementOnRemoved; public readonly Sprite Icon; - public readonly Color IconColor; + public readonly Color[] IconColors; private List effects = new List(); @@ -510,7 +510,7 @@ namespace Barotrauma CauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeath." + Identifier, true) ?? element.GetAttributeString("causeofdeathdescription", ""); SelfCauseOfDeathDescription = TextManager.Get("AfflictionCauseOfDeathSelf." + Identifier, true) ?? element.GetAttributeString("selfcauseofdeathdescription", ""); - + IconColors = element.GetAttributeColorArray("iconcolors", null); AchievementOnRemoved = element.GetAttributeString("achievementonremoved", ""); foreach (XElement subElement in element.Elements()) @@ -519,7 +519,6 @@ namespace Barotrauma { case "icon": Icon = new Sprite(subElement); - IconColor = subElement.GetAttributeColor("color", Color.White); break; case "effect": effects.Add(new Effect(subElement, Name)); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs index ee872c138..f3c5d4b13 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs @@ -160,6 +160,7 @@ namespace Barotrauma private set; } + public Sprite Icon; public string FilePath { get; private set; } public XElement Element { get; private set; } @@ -200,6 +201,9 @@ namespace Barotrauma case "appropriateorders": subElement.Elements().ForEach(order => AppropriateOrders.Add(order.GetAttributeString("identifier", "").ToLowerInvariant())); break; + case "icon": + Icon = new Sprite(subElement.FirstElement()); + break; } } @@ -244,76 +248,6 @@ namespace Barotrauma ClothingElement = element.GetChildElement("PortraitClothing"); } - public class OutfitPreview - { - /// - /// Pair.First = sprite, Pair.Second = draw offset - /// - public readonly List> Sprites; - public Vector2 Dimensions; - - public OutfitPreview() - { - Sprites = new List>(); - Dimensions = Vector2.One; - } - - public void AddSprite(Sprite sprite, Vector2 drawOffset) - { - Sprites.Add(new Pair(sprite, drawOffset)); - } - } - - public List GetJobOutfitSprites(Gender gender, out Vector2 maxDimensions) - { - List outfitPreviews = new List(); - maxDimensions = Vector2.One; - - var equipIdentifiers = Element.GetChildElements("ItemSet").Elements().Where(e => e.GetAttributeBool("outfit", false)).Select(e => e.GetAttributeString("identifier", "")); - - var outfitPrefabs = ItemPrefab.Prefabs.Where(itemPrefab => equipIdentifiers.Contains(itemPrefab.Identifier)).ToList(); - if (!outfitPrefabs.Any()) { return null; } - - for (int i = 0; i < outfitPrefabs.Count; i++) - { - var outfitPreview = new OutfitPreview(); - - if (!ItemSets.TryGetValue(i, out var itemSetElement)) { continue; } - var previewElement = itemSetElement.GetChildElement("PreviewSprites"); - if (previewElement == null) - { -#if CLIENT - if (outfitPrefabs[i] is ItemPrefab prefab && prefab.InventoryIcon != null) - { - outfitPreview.AddSprite(prefab.InventoryIcon, Vector2.Zero); - outfitPreview.Dimensions = prefab.InventoryIcon.SourceRect.Size.ToVector2(); - maxDimensions.X = MathHelper.Max(maxDimensions.X, outfitPreview.Dimensions.X); - maxDimensions.Y = MathHelper.Max(maxDimensions.Y, outfitPreview.Dimensions.Y); - } -#endif - outfitPreviews.Add(outfitPreview); - continue; - } - - var children = previewElement.Elements().ToList(); - for (int n = 0; n < children.Count; n++) - { - XElement spriteElement = children[n]; - string spriteTexture = spriteElement.GetAttributeString("texture", "").Replace("[GENDER]", (gender == Gender.Female) ? "female" : "male"); - var sprite = new Sprite(spriteElement, file: spriteTexture); - sprite.size = new Vector2(sprite.SourceRect.Width, sprite.SourceRect.Height); - outfitPreview.AddSprite(sprite, children[n].GetAttributeVector2("offset", Vector2.Zero)); - } - - outfitPreview.Dimensions = previewElement.GetAttributeVector2("dims", Vector2.One); - maxDimensions.X = MathHelper.Max(maxDimensions.X, outfitPreview.Dimensions.X); - maxDimensions.Y = MathHelper.Max(maxDimensions.Y, outfitPreview.Dimensions.Y); - - outfitPreviews.Add(outfitPreview); - } - - return outfitPreviews; - } public static JobPrefab Random(Rand.RandSync sync = Rand.RandSync.Unsynced) => Prefabs.GetRandom(sync); diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index 3da49b115..bbb889b45 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -1210,7 +1210,7 @@ namespace Barotrauma return; } - if (string.IsNullOrWhiteSpace(command) || command == "\\" || command == "\n") return; + if (string.IsNullOrWhiteSpace(command) || command == "\\" || command == "\n") { return; } string[] splitCommand = SplitCommand(command); if (splitCommand.Length == 0) @@ -1231,12 +1231,17 @@ namespace Barotrauma #if CLIENT if (GameMain.Client != null) { - if (GameMain.Client.HasConsoleCommandPermission(splitCommand[0].ToLowerInvariant())) + Command matchingCommand = commands.Find(c => c.names.Contains(splitCommand[0].ToLowerInvariant())); + if (matchingCommand == null) { - Command matchingCommand = commands.Find(c => c.names.Contains(splitCommand[0].ToLowerInvariant())); - //if the command is not defined client-side, we'll relay it anyway because it may be a custom command at the server's side - if (matchingCommand == null || matchingCommand.RelayToServer) + GameMain.Client.SendConsoleCommand(command); + NewMessage("Server command: " + command, Color.White); + return; + } + else if (GameMain.Client.HasConsoleCommandPermission(splitCommand[0].ToLowerInvariant())) + { + if (matchingCommand.RelayToServer) { GameMain.Client.SendConsoleCommand(command); NewMessage("Server command: " + command, Color.White); @@ -1245,7 +1250,6 @@ namespace Barotrauma { matchingCommand.ClientExecute(splitCommand.Skip(1).ToArray()); } - return; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs index 3c65c084c..df5c497b1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs @@ -258,6 +258,9 @@ namespace Barotrauma { CoroutineManager.InvokeAfter(() => { + //round ended before the coroutine finished + if (GameMain.GameSession == null || Level.Loaded == null) { return; } + System.Diagnostics.Debug.Assert(GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer, "Clients should not create monster events."); monsters.Add(Character.Create(speciesName, spawnPos.Value + Rand.Vector(offsetAmount), Level.Loaded.Seed + i.ToString(), null, false, true, true)); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Extensions/PointExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Extensions/PointExtensions.cs index d76cc2aed..41392d1c8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Extensions/PointExtensions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Extensions/PointExtensions.cs @@ -37,11 +37,22 @@ namespace Barotrauma.Extensions return new Point((int)(p.X / v.X), (int)(p.Y / v.Y)); } + /// + /// Negates the X and Y components. + /// public static Point Inverse(this Point p) { return new Point(-p.X, -p.Y); } + /// + /// Flips the X and Y components. + /// + public static Point Flip(this Point p) + { + return new Point(p.Y, p.X); + } + public static Point Clamp(this Point p, Point min, Point max) { return new Point(MathHelper.Clamp(p.X, min.X, max.X), MathHelper.Clamp(p.Y, min.Y, max.Y)); diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs index c5ff0d854..ca5d46580 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/CrewManager.cs @@ -1,9 +1,6 @@ -using Barotrauma.Networking; -using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Barotrauma { @@ -14,22 +11,12 @@ namespace Barotrauma private float conversationTimer, conversationLineTimer; private List> pendingConversationLines = new List>(); - //orders that have not been issued to a specific character - private List> activeOrders = new List>(); - public List> ActiveOrders - { - get { return activeOrders; } - } - - private bool isSinglePlayer; - public bool IsSinglePlayer - { - get { return isSinglePlayer; } - } + public List> ActiveOrders { get; } = new List>(); + public bool IsSinglePlayer { get; private set; } public CrewManager(bool isSinglePlayer) { - this.isSinglePlayer = isSinglePlayer; + IsSinglePlayer = isSinglePlayer; conversationTimer = 5.0f; InitProjectSpecific(); @@ -45,7 +32,7 @@ namespace Barotrauma return false; } - Pair existingOrder = activeOrders.Find(o => o.First.Prefab == order.Prefab && o.First.TargetEntity == order.TargetEntity); + Pair existingOrder = ActiveOrders.Find(o => o.First.Prefab == order.Prefab && o.First.TargetEntity == order.TargetEntity); if (existingOrder != null) { existingOrder.Second = fadeOutTime; @@ -53,23 +40,23 @@ namespace Barotrauma } else { - activeOrders.Add(new Pair(order, fadeOutTime)); + ActiveOrders.Add(new Pair(order, fadeOutTime)); return true; } } public void RemoveOrder(Order order) { - activeOrders.RemoveAll(o => o.First == order); + ActiveOrders.RemoveAll(o => o.First == order); } public void Update(float deltaTime) { - foreach (Pair order in activeOrders) + foreach (Pair order in ActiveOrders) { order.Second -= deltaTime; } - activeOrders.RemoveAll(o => o.Second <= 0.0f); + ActiveOrders.RemoveAll(o => o.Second <= 0.0f); UpdateConversations(deltaTime); UpdateProjectSpecific(deltaTime); diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs index bee6e7ee2..1eb7ccc2e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs @@ -288,7 +288,7 @@ namespace Barotrauma #if CLIENT if (GameMode is SinglePlayerCampaign) { SteamAchievementManager.OnBiomeDiscovered(level.Biome); } - roundSummary = new RoundSummary(this); + RoundSummary = new RoundSummary(this); GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f); @@ -325,9 +325,9 @@ namespace Barotrauma (Mission == null ? "None" : Mission.GetType().ToString())); #if CLIENT - if (roundSummary != null) + if (RoundSummary != null) { - GUIFrame summaryFrame = roundSummary.CreateSummaryFrame(endMessage); + GUIFrame summaryFrame = RoundSummary.CreateSummaryFrame(endMessage); GUIMessageBox.MessageBoxes.Add(summaryFrame); var okButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), summaryFrame.Children.First().Children.First().FindChild("buttonarea").RectTransform), TextManager.Get("OK")) diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSettings.cs index a54a51da5..11424d818 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSettings.cs @@ -234,6 +234,9 @@ namespace Barotrauma public volatile bool SuppressModFolderWatcher; +#if DEBUG + public bool AutomaticQuickStartEnabled { get; set; } +#endif private FileSystemWatcher modsFolderWatcher; @@ -1196,7 +1199,11 @@ namespace Barotrauma new XAttribute("crewmenuopen", CrewMenuOpen), new XAttribute("campaigndisclaimershown", CampaignDisclaimerShown), new XAttribute("editordisclaimershown", EditorDisclaimerShown), - new XAttribute("tutorialskipwarning", ShowTutorialSkipWarning)); + new XAttribute("tutorialskipwarning", ShowTutorialSkipWarning) +#if DEBUG + , new XAttribute("automaticquickstartenabled", AutomaticQuickStartEnabled) +#endif + ); if (!string.IsNullOrEmpty(overrideSaveFolder)) { @@ -1378,6 +1385,9 @@ namespace Barotrauma CampaignDisclaimerShown = doc.Root.GetAttributeBool("campaigndisclaimershown", CampaignDisclaimerShown); EditorDisclaimerShown = doc.Root.GetAttributeBool("editordisclaimershown", EditorDisclaimerShown); ShowTutorialSkipWarning = doc.Root.GetAttributeBool("tutorialskipwarning", true); +#if DEBUG + AutomaticQuickStartEnabled = doc.Root.GetAttributeBool("automaticquickstartenabled", AutomaticQuickStartEnabled); +#endif XElement gameplayElement = doc.Root.Element("gameplay"); jobPreferences = new List>(); if (gameplayElement != null) diff --git a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs index 0779870b9..addbfee1c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/InputType.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/InputType.cs @@ -14,6 +14,8 @@ namespace Barotrauma SelectPreviousCharacter, Voice, Deselect, - Shoot + Shoot, + Command, + ToggleInventory } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/CharacterInventory.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/CharacterInventory.cs index bc3d7525a..869e90cb8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/CharacterInventory.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/CharacterInventory.cs @@ -199,7 +199,7 @@ namespace Barotrauma #if CLIENT for (int j = 0; j < capacity; j++) { - if (slots != null && Items[j] == Items[i]) slots[j].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); + if (slots != null && Items[j] == Items[i]) slots[j].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f); } #endif } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs index f2d35ec4f..7a9b760b7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs @@ -300,7 +300,7 @@ namespace Barotrauma.Items.Components #if CLIENT else if (hasRequiredItems && character != null && character == Character.Controlled) { - GUI.AddMessage(accessDeniedTxt, Color.Red); + GUI.AddMessage(accessDeniedTxt, GUI.Style.Red); } #endif diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs index 576d3797a..1c7ab61cf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Pickable.cs @@ -139,7 +139,7 @@ namespace Barotrauma.Items.Components this, item.WorldPosition, pickTimer / requiredTime, - Color.Red, Color.Green); + GUI.Style.Red, GUI.Style.Green); #endif picker.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f)); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs index f8420c9c5..31b47c057 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs @@ -462,7 +462,7 @@ namespace Barotrauma.Items.Components this, targetItem.WorldPosition, levelResource.DeattachTimer / levelResource.DeattachDuration, - Color.Red, Color.Green); + GUI.Style.Red, GUI.Style.Green); #endif } FixItemProjSpecific(user, deltaTime, targetItem); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs index 1b3963813..73e3baad9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs @@ -504,11 +504,12 @@ namespace Barotrauma.Items.Components loopingSoundChannel = null; } - foreach (SoundChannel channel in playingOneshotSoundChannels) + //no need to Dispose these - SoundManager will do it when it when it needs a free channel and the sound has stopped playing + //disposing immediately on Remove will for example prevent explosives from playing a sound if the explosion removes the item + /*foreach (SoundChannel channel in playingOneshotSoundChannels) { channel.Dispose(); - loopingSoundChannel = null; - } + }*/ if (GuiFrame != null) { GUI.RemoveFromUpdateList(GuiFrame, true); } #endif diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs index b959ef7b8..63d16e4b6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs @@ -85,7 +85,7 @@ namespace Barotrauma.Items.Components currPowerConsumption = Math.Abs(targetForce) / 100.0f * powerConsumption; //pumps consume more power when in a bad condition - currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition); + currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition); if (powerConsumption == 0.0f) { Voltage = 1.0f; } @@ -95,7 +95,8 @@ namespace Barotrauma.Items.Components Force = MathHelper.Lerp(force, (Voltage < MinVoltage) ? 0.0f : targetForce, 0.1f); if (Math.Abs(Force) > 1.0f) { - Vector2 currForce = new Vector2((force / 10.0f) * maxForce * Math.Min(Voltage / MinVoltage, 1.0f), 0.0f); + float voltageFactor = MinVoltage <= 0.0f ? 1.0f : Math.Min(Voltage / MinVoltage, 1.0f); + Vector2 currForce = new Vector2((force / 10.0f) * maxForce * voltageFactor, 0.0f); //less effective when in a bad condition currForce *= MathHelper.Lerp(0.5f, 2.0f, item.Condition / item.MaxCondition); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs index f62883a5e..3fe0406e9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs @@ -154,7 +154,7 @@ namespace Barotrauma.Items.Components outputContainer.Inventory.Locked = true; currPowerConsumption = powerConsumption; - currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition); + currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition); } private void CancelFabricating(Character user = null) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/MiniMap.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/MiniMap.cs index 42ad0ab99..bba73efce 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/MiniMap.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/MiniMap.cs @@ -73,7 +73,7 @@ namespace Barotrauma.Items.Components } currPowerConsumption = powerConsumption; - currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition); + currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition); hasPower = Voltage > MinVoltage; if (hasPower) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/OxygenGenerator.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/OxygenGenerator.cs index dd2558b8f..49c294f4a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/OxygenGenerator.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/OxygenGenerator.cs @@ -42,7 +42,7 @@ namespace Barotrauma.Items.Components CurrFlow = 0.0f; currPowerConsumption = powerConsumption; //consume more power when in a bad condition - currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition); + currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition); if (powerConsumption <= 0.0f) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs index 662a6d4a3..520b0b0a3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs @@ -14,8 +14,6 @@ namespace Barotrauma.Items.Components private float? targetLevel; private float pumpSpeedLockTimer, isActiveLockTimer; - - private bool hasPower; [Serialize(0.0f, true, description: "How fast the item is currently pumping water (-100 = full speed out, 100 = full speed in). Intended to be used by StatusEffect conditionals (setting this value in XML has no effect).")] public float FlowPercentage @@ -23,7 +21,7 @@ namespace Barotrauma.Items.Components get { return flowPercentage; } set { - if (!MathUtils.IsValid(flowPercentage)) return; + if (!MathUtils.IsValid(flowPercentage)) { return; } flowPercentage = MathHelper.Clamp(value, -100.0f, 100.0f); flowPercentage = MathUtils.Round(flowPercentage, 1.0f); } @@ -41,11 +39,26 @@ namespace Barotrauma.Items.Components { get { - if (!IsActive) return 0.0f; + if (!IsActive) { return 0.0f; } return Math.Abs(currFlow); } } - + + public override bool IsActive + { + get => base.IsActive; + set + { + base.IsActive = value; + if (!IsActive) + { + powerConsumption = 0; + } + } + } + + public bool HasPower => IsActive && Voltage >= MinVoltage; + public Pump(Item item, XElement element) : base(item, element) { @@ -57,7 +70,6 @@ namespace Barotrauma.Items.Components public override void Update(float deltaTime, Camera cam) { currFlow = 0.0f; - hasPower = false; if (targetLevel != null) { @@ -74,14 +86,12 @@ namespace Barotrauma.Items.Components currPowerConsumption = powerConsumption * Math.Abs(flowPercentage / 100.0f); //pumps consume more power when in a bad condition - currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition); + currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition); - if (Voltage < MinVoltage) { return; } + if (!HasPower) { return; } UpdateProjSpecific(deltaTime); - hasPower = true; - ApplyStatusEffects(ActionType.OnActive, deltaTime, null); if (item.CurrentHull == null) { return; } @@ -102,8 +112,8 @@ namespace Barotrauma.Items.Components { if (connection.Name == "toggle") { - isActiveLockTimer = 0.1f; IsActive = !IsActive; + isActiveLockTimer = 0.1f; } else if (connection.Name == "set_active") { @@ -126,21 +136,23 @@ namespace Barotrauma.Items.Components pumpSpeedLockTimer = 0.1f; } } - - if (!IsActive) currPowerConsumption = 0.0f; } public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective) { #if CLIENT - if (GameMain.Client != null) return false; + if (GameMain.Client != null) { return false; } #endif if (objective.Option.ToLowerInvariant() == "stoppumping") { #if SERVER - if (FlowPercentage > 0.0f) item.CreateServerEvent(this); + if (FlowPercentage > 0.0f) + { + item.CreateServerEvent(this); + } #endif + IsActive = false; FlowPercentage = 0.0f; } else diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs index 4cb6341ce..93c355bfa 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs @@ -48,7 +48,19 @@ namespace Barotrauma.Items.Components private Vector2 optimalFissionRate, allowedFissionRate; private Vector2 optimalTurbineOutput, allowedTurbineOutput; - private bool shutDown; + private bool _powerOn; + + public bool PowerOn + { + get { return _powerOn; } + set + { + _powerOn = value; +#if CLIENT + UpdateUIElementStates(); +#endif + } + } private Character lastAIUser; @@ -152,12 +164,7 @@ namespace Barotrauma.Items.Components { autoTemp = value; #if CLIENT - if (autoTempSlider != null) - { - autoTempSlider.BarScroll = value ? - Math.Min(0.45f, autoTempSlider.BarScroll) : - Math.Max(0.55f, autoTempSlider.BarScroll); - } + UpdateUIElementStates(); #endif } } @@ -257,7 +264,7 @@ namespace Barotrauma.Items.Components } currPowerConsumption += autoAdjustAmount; - if (shutDown) + if (!PowerOn) { targetFissionRate = 0.0f; targetTurbineOutput = 0.0f; @@ -472,8 +479,8 @@ namespace Barotrauma.Items.Components targetFissionRate = Math.Max(targetFissionRate - deltaTime * 10.0f, 0.0f); targetTurbineOutput = Math.Max(targetTurbineOutput - deltaTime * 10.0f, 0.0f); #if CLIENT - fissionRateScrollBar.BarScroll = 1.0f - FissionRate / 100.0f; - turbineOutputScrollBar.BarScroll = 1.0f - TurbineOutput / 100.0f; + FissionRateScrollBar.BarScroll = 1.0f - FissionRate / 100.0f; + TurbineOutputScrollBar.BarScroll = 1.0f - TurbineOutput / 100.0f; UpdateGraph(deltaTime); #endif } @@ -582,14 +589,14 @@ namespace Barotrauma.Items.Components LastUser = lastAIUser = character; bool prevAutoTemp = autoTemp; - bool prevShutDown = shutDown; + bool prevPowerOn = _powerOn; float prevFissionRate = targetFissionRate; float prevTurbineOutput = targetTurbineOutput; switch (objective.Option.ToLowerInvariant()) { case "powerup": - shutDown = false; + PowerOn = true; if (objective.Override || !autoTemp) { //characters with insufficient skill levels simply set the autotemp on instead of trying to adjust the temperature manually @@ -604,24 +611,20 @@ namespace Barotrauma.Items.Components } } #if CLIENT - onOffSwitch.BarScroll = 0.0f; - fissionRateScrollBar.BarScroll = FissionRate / 100.0f; - turbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f; + FissionRateScrollBar.BarScroll = FissionRate / 100.0f; + TurbineOutputScrollBar.BarScroll = TurbineOutput / 100.0f; #endif break; case "shutdown": -#if CLIENT - onOffSwitch.BarScroll = 1.0f; -#endif + PowerOn = false; AutoTemp = false; - shutDown = true; targetFissionRate = 0.0f; targetTurbineOutput = 0.0f; break; } if (autoTemp != prevAutoTemp || - prevShutDown != shutDown || + prevPowerOn != _powerOn || Math.Abs(prevFissionRate - targetFissionRate) > 1.0f || Math.Abs(prevTurbineOutput - targetTurbineOutput) > 1.0f) { @@ -640,14 +643,11 @@ namespace Barotrauma.Items.Components case "shutdown": if (targetFissionRate > 0.0f || targetTurbineOutput > 0.0f) { - shutDown = true; + PowerOn = false; AutoTemp = false; targetFissionRate = 0.0f; targetTurbineOutput = 0.0f; unsentChanges = true; -#if CLIENT - onOffSwitch.BarScroll = 1.0f; -#endif } break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs index 9293a1f0c..4d94f2ec8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs @@ -116,8 +116,7 @@ namespace Barotrauma.Items.Components } } #if CLIENT - if (activeTickBox != null) activeTickBox.Selected = value == Mode.Active; - if (passiveTickBox != null) passiveTickBox.Selected = value == Mode.Passive; + UpdateGUIElements(); #endif } } @@ -126,10 +125,9 @@ namespace Barotrauma.Items.Components : base(item, element) { connectedTransducers = new List(); - - CurrentMode = Mode.Passive; IsActive = true; InitProjSpecific(element); + CurrentMode = Mode.Passive; } partial void InitProjSpecific(XElement element); @@ -344,14 +342,10 @@ namespace Barotrauma.Items.Components } } - if (!item.CanClientAccess(c)) return; + if (!item.CanClientAccess(c)) { return; } CurrentMode = isActive ? Mode.Active : Mode.Passive; - //TODO: cleanup -#if CLIENT - activeTickBox.Selected = currentMode == Mode.Active; -#endif if (isActive) { zoom = MathHelper.Lerp(MinZoom, MaxZoom, zoomT); @@ -363,8 +357,7 @@ namespace Barotrauma.Items.Components } #if CLIENT zoomSlider.BarScroll = zoomT; - directionalTickBox.Selected = useDirectionalPing; - directionalSlider.BarScroll = pingDirectionT; + directionalModeSwitch.Selected = useDirectionalPing; #endif } #if SERVER diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs index b11b75830..80da2e0bf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs @@ -58,19 +58,24 @@ namespace Barotrauma.Items.Components get { return autoPilot; } set { - if (value == autoPilot) return; + if (value == autoPilot) { return; } autoPilot = value; #if CLIENT - autopilotTickBox.Selected = autoPilot; - manualTickBox.Selected = !autoPilot; - maintainPosTickBox.Enabled = autoPilot; - levelEndTickBox.Enabled = autoPilot; - levelStartTickBox.Enabled = autoPilot; + UpdateGUIElements(); #endif if (autoPilot) { - if (pathFinder == null) pathFinder = new PathFinder(WayPoint.WayPointList, false); + if (pathFinder == null) + { + pathFinder = new PathFinder(WayPoint.WayPointList, false); + } MaintainPos = true; + if (posToMaintain == null) + { + posToMaintain = controlledSub != null ? + controlledSub.WorldPosition : + item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; + } } else { @@ -272,7 +277,7 @@ namespace Barotrauma.Items.Components ApplyStatusEffects(ActionType.OnActive, deltaTime, null); - if (autoPilot) + if (AutoPilot) { UpdateAutoPilot(deltaTime); float userSkill = 0.0f; @@ -317,7 +322,7 @@ namespace Barotrauma.Items.Components private void UpdateAutoPilot(float deltaTime) { - if (controlledSub == null) return; + if (controlledSub == null) { return; } if (posToMaintain != null) { Vector2 steeringVel = GetSteeringVelocity((Vector2)posToMaintain, 10.0f); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs index 5d7d4b0a7..5879e6be8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs @@ -577,6 +577,8 @@ namespace Barotrauma.Items.Components railSprite?.Remove(); railSprite = null; #if CLIENT + crosshairSprite?.Remove(); crosshairSprite = null; + crosshairPointerSprite?.Remove(); crosshairPointerSprite = null; moveSoundChannel?.Dispose(); moveSoundChannel = null; #endif } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs index 825ad2514..998411cec 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs @@ -37,13 +37,17 @@ namespace Barotrauma #if CLIENT this.slotsPerRow = slotsPerRow; - if (slotSpriteSmall == null) + if (SlotSpriteSmall == null) { //TODO: define these in xml - slotSpriteSmall = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(532, 395, 75, 71), null, 0); + SlotSpriteSmall = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(0, 0, 128, 128), null, 0); + // Adjustment to match the old size of 75,71 + SlotSpriteSmall.size = new Vector2(SlotSpriteSmall.SourceRect.Width * 0.5859375f, SlotSpriteSmall.SourceRect.Height * 0.5546875f); + slotSpriteVertical = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(672, 218, 75, 144), null, 0); slotSpriteHorizontal = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(476, 186, 160, 75), null, 0); slotSpriteRound = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(681, 373, 58, 64), null, 0); + slotHotkeySprite = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(128, 0, 128, 128), null, 0); EquipIndicator = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(673, 182, 73, 27), new Vector2(0.5f, 0.5f), 0); EquipIndicatorHighlight = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(679, 108, 67, 21), new Vector2(0.5f, 0.5f), 0); @@ -154,7 +158,7 @@ namespace Barotrauma else { #if CLIENT - if (slots != null && createNetworkEvent) slots[i].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); + if (slots != null && createNetworkEvent) slots[i].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f); #endif return false; } @@ -280,11 +284,11 @@ namespace Barotrauma { for (int j = 0; j < capacity; j++) { - if (Items[j] == item) slots[j].ShowBorderHighlight(Color.Green, 0.1f, 0.9f); + if (Items[j] == item) slots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f); } for (int j = 0; j < otherInventory.capacity; j++) { - if (otherInventory.Items[j] == existingItem) otherInventory.slots[j].ShowBorderHighlight(Color.Green, 0.1f, 0.9f); + if (otherInventory.Items[j] == existingItem) otherInventory.slots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f); } } #endif @@ -322,7 +326,7 @@ namespace Barotrauma { if (Items[j] == existingItem) { - slots[j].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); + slots[j].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs index 14712fe12..557f0bdbb 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs @@ -916,7 +916,7 @@ namespace Barotrauma contained.Container = null; } - public void SetTransform(Vector2 simPosition, float rotation, bool findNewHull = true) + public void SetTransform(Vector2 simPosition, float rotation, bool findNewHull = true, bool setPrevTransform = true) { if (!MathUtils.IsValid(simPosition)) { @@ -938,13 +938,13 @@ namespace Barotrauma try { #endif - if (body.Enabled) + if (body.PhysEnabled) { - body.SetTransform(simPosition, rotation); + body.SetTransform(simPosition, rotation, setPrevTransform); } else { - body.SetTransformIgnoreContacts(simPosition, rotation); + body.SetTransformIgnoreContacts(simPosition, rotation, setPrevTransform); } #if DEBUG } @@ -1270,10 +1270,6 @@ namespace Barotrauma HandleCollision(impact); } - if (!isActive) { return; } - - aiTarget?.Update(deltaTime); - if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer) { sendConditionUpdateTimer -= deltaTime; @@ -1283,6 +1279,10 @@ namespace Barotrauma } } + if (!isActive) { return; } + + aiTarget?.Update(deltaTime); + ApplyStatusEffects(ActionType.Always, deltaTime, character: (parentInventory as CharacterInventory)?.Owner as Character); for (int i = 0; i < updateableComponents.Count; i++) @@ -1376,7 +1376,7 @@ namespace Barotrauma } else { - if (updateableComponents.Count == 0 && aiTarget == null && !conditionUpdatePending && !hasStatusEffectsOfType[(int)ActionType.Always] && body == null) + if (updateableComponents.Count == 0 && aiTarget == null && !hasStatusEffectsOfType[(int)ActionType.Always] && body == null) { #if CLIENT positionBuffer.Clear(); @@ -1814,6 +1814,12 @@ namespace Barotrauma else if (selected) { picker.SelectedConstruction = this; +#if CLIENT + if (GameMain.GameSession?.CrewManager != null && picker == Character.Controlled && GetComponent() == null) + { + GameMain.GameSession.CrewManager.ToggleCrewListOpen = false; + } +#endif } } @@ -1823,7 +1829,7 @@ namespace Barotrauma if (requiredSkill != null) { GUI.AddMessage(TextManager.GetWithVariables("InsufficientSkills", new string[2] { "[requiredskill]", "[requiredlevel]" }, - new string[2] { TextManager.Get("SkillName." + requiredSkill.Identifier), ((int)requiredSkill.Level).ToString() }, new bool[2] { true, false }), Color.Red); + new string[2] { TextManager.Get("SkillName." + requiredSkill.Identifier), ((int)requiredSkill.Level).ToString() }, new bool[2] { true, false }), GUI.Style.Red); } } #endif diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs index e0990e3f0..d79cf7e6e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs @@ -14,6 +14,10 @@ namespace Barotrauma.Networking private static Stream writeStream; private static Stream readStream; private static volatile bool shutDown; + public static bool HasShutDown + { + get { return shutDown; } + } private static ManualResetEvent writeManualResetEvent; private static byte[] tempBytes; @@ -52,8 +56,16 @@ namespace Barotrauma.Networking writeManualResetEvent = new ManualResetEvent(false); - readThread = new Thread(UpdateRead); - writeThread = new Thread(UpdateWrite); + readThread = new Thread(UpdateRead) + { + Name = "ChildServerRelay.ReadThread", + IsBackground = true + }; + writeThread = new Thread(UpdateWrite) + { + Name = "ChildServerRelay.WriteThread", + IsBackground = true + }; readThread.Start(); writeThread.Start(); } @@ -61,7 +73,7 @@ namespace Barotrauma.Networking private static void PrivateShutDown() { shutDown = true; - writeManualResetEvent.Set(); + writeManualResetEvent?.Set(); readCancellationToken?.Cancel(); readThread?.Join(); readThread = null; writeThread?.Join(); writeThread = null; @@ -76,8 +88,23 @@ namespace Barotrauma.Networking while (!shutDown) { Task readTask = readStream?.ReadAsync(tempBytes, 0, tempBytes.Length, readCancellationToken.Token); - TimeSpan ts = TimeSpan.FromMilliseconds(15000); - if (readTask == null || !readTask.Wait(ts)) + TimeSpan ts = TimeSpan.FromMilliseconds(100); + for (int i=0;i<150;i++) + { + if (shutDown) + { + readCancellationToken?.Cancel(); + shutDown = true; + return; + } + + if ((readTask?.IsCompleted ?? true) || (readTask?.Wait(ts) ?? true)) + { + break; + } + } + + if (readTask == null || !readTask.IsCompleted) { readCancellationToken?.Cancel(); shutDown = true; @@ -99,9 +126,12 @@ namespace Barotrauma.Networking if (readState == ReadState.WaitingForPacketStart) { readIncTotal = tempBytes[procIndex] | (tempBytes[procIndex + 1] << 8); + procIndex += 2; + + if (readIncTotal <= 0) { continue; } + readIncOffset = 0; readIncBuf = new byte[readIncTotal]; - procIndex += 2; readState = ReadState.WaitingForPacketEnd; } else if (readState == ReadState.WaitingForPacketEnd) @@ -159,7 +189,14 @@ namespace Barotrauma.Networking if (!shutDown) { writeManualResetEvent.Reset(); - writeManualResetEvent.WaitOne(); + if (!writeManualResetEvent.WaitOne(1000)) + { + //heartbeat to keep the other end alive + byte[] lengthBytes = new byte[2]; + lengthBytes[0] = (byte)0; + lengthBytes[1] = (byte)0; + writeStream?.Write(lengthBytes, 0, 2); + } } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs index 87983d725..3937911a7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs @@ -291,8 +291,8 @@ namespace Barotrauma.Networking Port = port; QueryPort = queryPort; EnableUPnP = enableUPnP; - this.maxPlayers = maxPlayers; - this.isPublic = isPublic; + MaxPlayers = maxPlayers; + IsPublic = isPublic; netProperties = new Dictionary(); @@ -376,7 +376,7 @@ namespace Barotrauma.Networking private bool autoRestart; - public bool isPublic; + public bool IsPublic; private int maxPlayers; @@ -810,6 +810,7 @@ namespace Barotrauma.Networking set; } + [Serialize(8, true)] public int MaxPlayers { get { return maxPlayers; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaShared/SharedSource/Physics/PhysicsBody.cs index 7b7789791..8d4242e75 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Physics/PhysicsBody.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Physics/PhysicsBody.cs @@ -648,17 +648,14 @@ namespace Barotrauma Vector2 velocityAddition = force / Mass * (float)Timing.Step; Vector2 newVelocity = body.LinearVelocity + velocityAddition; - + float newSpeedSqr = newVelocity.LengthSquared(); - if (newSpeedSqr > maxVelocity * maxVelocity) + if (newSpeedSqr > maxVelocity * maxVelocity && Vector2.Dot(body.LinearVelocity, force) > 0.0f) { - float velSqr = body.LinearVelocity.LengthSquared(); - if (newSpeedSqr > velSqr) - { - if (velSqr > maxVelocity * maxVelocity) { return; } - newVelocity = newVelocity.ClampLength(maxVelocity); - force = (newVelocity - body.LinearVelocity) * Mass / (float)Timing.Step; - } + float newSpeed = (float)Math.Sqrt(newSpeedSqr); + float maxVelAddition = maxVelocity - newSpeed; + if (maxVelAddition <= 0.0f) { return; } + force = velocityAddition.ClampLength(maxVelAddition) * Mass / (float)Timing.Step; } if (!IsValidValue(force, "clamped force", -1e10f, 1e10f)) return; @@ -678,7 +675,7 @@ namespace Barotrauma body.ApplyTorque(torque); } - public bool SetTransform(Vector2 simPosition, float rotation) + public bool SetTransform(Vector2 simPosition, float rotation, bool setPrevTransform = true) { System.Diagnostics.Debug.Assert(MathUtils.IsValid(simPosition)); System.Diagnostics.Debug.Assert(Math.Abs(simPosition.X) < 1000000.0f); @@ -688,11 +685,11 @@ namespace Barotrauma if (!IsValidValue(rotation, "rotation")) return false; body.SetTransform(simPosition, rotation); - SetPrevTransform(simPosition, rotation); + if (setPrevTransform) { SetPrevTransform(simPosition, rotation); } return true; } - public bool SetTransformIgnoreContacts(Vector2 simPosition, float rotation) + public bool SetTransformIgnoreContacts(Vector2 simPosition, float rotation, bool setPrevTransform = true) { System.Diagnostics.Debug.Assert(MathUtils.IsValid(simPosition)); System.Diagnostics.Debug.Assert(Math.Abs(simPosition.X) < 1000000.0f); @@ -702,7 +699,7 @@ namespace Barotrauma if (!IsValidValue(rotation, "rotation")) return false; body.SetTransformIgnoreContacts(ref simPosition, rotation); - SetPrevTransform(simPosition, rotation); + if (setPrevTransform) { SetPrevTransform(simPosition, rotation); } return true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index 4ef8a8085..35601ec5b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -178,11 +178,20 @@ namespace Barotrauma Lights.LightManager.ViewTarget != null) { Vector2 targetPos = Lights.LightManager.ViewTarget.DrawPosition; - if (Lights.LightManager.ViewTarget == Character.Controlled && CharacterHealth.OpenHealthWindow != null) + if (Lights.LightManager.ViewTarget == Character.Controlled && + (CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen)) { - Vector2 screenTargetPos = CharacterHealth.OpenHealthWindow.Alignment == Alignment.Left ? - new Vector2(GameMain.GraphicsWidth * 0.75f, GameMain.GraphicsHeight * 0.5f) : - new Vector2(GameMain.GraphicsWidth * 0.25f, GameMain.GraphicsHeight * 0.5f); + Vector2 screenTargetPos = new Vector2(0.0f, GameMain.GraphicsHeight * 0.5f); + if (CrewManager.IsCommandInterfaceOpen) + { + screenTargetPos.X = GameMain.GraphicsWidth * 0.5f; + } + else + { + screenTargetPos = CharacterHealth.OpenHealthWindow.Alignment == Alignment.Left ? + new Vector2(GameMain.GraphicsWidth * 0.75f, GameMain.GraphicsHeight * 0.5f) : + new Vector2(GameMain.GraphicsWidth * 0.25f, GameMain.GraphicsHeight * 0.5f); + } Vector2 screenOffset = screenTargetPos - new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight / 2); screenOffset.Y = -screenOffset.Y; targetPos -= screenOffset / cam.Zoom; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs b/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs index fa5b9db8b..87934f63b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs @@ -399,6 +399,31 @@ namespace Barotrauma return ParseColor(element.Attribute(name).Value); } + public static Color[] GetAttributeColorArray(this XElement element, string name, Color[] defaultValue) + { + if (element?.Attribute(name) == null) return defaultValue; + + string stringValue = element.Attribute(name).Value; + if (string.IsNullOrEmpty(stringValue)) return defaultValue; + + string[] splitValue = stringValue.Split(';'); + Color[] colorValue = new Color[splitValue.Length]; + for (int i = 0; i < splitValue.Length; i++) + { + try + { + Color val = ParseColor(splitValue[i], true); + colorValue[i] = val; + } + catch (Exception e) + { + DebugConsole.ThrowError("Error in " + element + "! ", e); + } + } + + return colorValue; + } + public static Rectangle GetAttributeRect(this XElement element, string name, Rectangle defaultValue) { if (element == null || element.Attribute(name) == null) return defaultValue; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Sprite/Sprite.cs b/Barotrauma/BarotraumaShared/SharedSource/Sprite/Sprite.cs index b96a3ac8b..cc3e4649d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Sprite/Sprite.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Sprite/Sprite.cs @@ -102,6 +102,8 @@ namespace Barotrauma } } + public Vector2 RelativeSize { get; private set; } + public string FilePath { get; private set; } public string FullPath { get; private set; } @@ -132,6 +134,7 @@ namespace Barotrauma public Sprite(XElement element, string path = "", string file = "", bool lazyLoad = false) { + if (element == null) { return; } this.lazyLoad = lazyLoad; SourceElement = element; if (!ParseTexturePath(path, file)) { return; } @@ -150,6 +153,7 @@ namespace Barotrauma if (shouldReturn) { return; } sourceRect = new Rectangle((int)sourceVector.X, (int)sourceVector.Y, (int)sourceVector.Z, (int)sourceVector.W); size = SourceElement.GetAttributeVector2("size", Vector2.One); + RelativeSize = size; size.X *= sourceRect.Width; size.Y *= sourceRect.Height; RelativeOrigin = SourceElement.GetAttributeVector2("origin", new Vector2(0.5f, 0.5f)); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/MathUtils.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/MathUtils.cs index 72a5f2ffd..e45b3587d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/MathUtils.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/MathUtils.cs @@ -55,6 +55,26 @@ namespace Barotrauma MathHelper.SmoothStep(v1.Y, v2.Y, amount)); } + public static float SmoothStep(float t) + { + return t * t * (3f - 2f * t); + } + + public static float SmootherStep(float t) + { + return t * t * t * (t * (6f * t - 15f) + 10f); + } + + public static float EaseIn(float t) + { + return 1f - (float)Math.Cos(t * MathHelper.PiOver2); + } + + public static float EaseOut(float t) + { + return (float)Math.Sin(t * MathHelper.PiOver2); + } + public static Vector2 ClampLength(this Vector2 v, float length) { float currLength = v.Length(); @@ -530,6 +550,42 @@ namespace Barotrauma return distSqX * distSqX + distSqY * distSqY <= radius * radius; } + /// + /// Get a point on a circle's circumference + /// + /// Center of the circle + /// Radius of the circle + /// Angle (in radians) from the center + /// + public static Vector2 GetPointOnCircumference(Vector2 center, float radius, float angle) + { + return new Vector2( + center.X + radius * (float)Math.Cos(angle), + center.Y + radius * (float)Math.Sin(angle)); + } + + /// + /// Get a specific number of evenly distributed points on a circle's circumference + /// + /// Center of the circle + /// Radius of the circle + /// Number of points to calculate + /// Angle (in radians) of the first point from the center + /// + public static Vector2[] GetPointsOnCircumference(Vector2 center, float radius, int points, float firstAngle = 0.0f) + { + var maxAngle = (float)(2 * Math.PI); + var angleStep = maxAngle / points; + var coordinates = new Vector2[points]; + for (int i = 0; i < points; i++) + { + var angle = firstAngle + (i * angleStep); + if (angle > maxAngle) { angle -= maxAngle; } + coordinates[i] = GetPointOnCircumference(center, radius, angle); + } + return coordinates; + } + /// /// divide a convex hull into triangles /// diff --git a/Barotrauma/BarotraumaShared/Submarines/Berilia.sub b/Barotrauma/BarotraumaShared/Submarines/Berilia.sub index b1bb8a801..c97dab01c 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Berilia.sub and b/Barotrauma/BarotraumaShared/Submarines/Berilia.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub index 2a55dd1b8..f8b005556 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub index eedff8171..4ce13e394 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub and b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub b/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub index 18795ce2a..3486d0f92 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub and b/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Orca.sub b/Barotrauma/BarotraumaShared/Submarines/Orca.sub index 90d29b329..6e84aceed 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Orca.sub and b/Barotrauma/BarotraumaShared/Submarines/Orca.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Remora.sub b/Barotrauma/BarotraumaShared/Submarines/Remora.sub index 8cd38e92a..76b066030 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Remora.sub and b/Barotrauma/BarotraumaShared/Submarines/Remora.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub index 1ebd8172d..42f6bf116 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon2.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon2.sub index 51607364c..1221d0161 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon2.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon2.sub differ diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 44c564ebf..64cf3bf7b 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,29 @@ +--------------------------------------------------------------------------------------------------------- +v0.9.702 (Unstable) +--------------------------------------------------------------------------------------------------------- + +- UI overhaul +- Increased level sizes. +- Rebalanced monster spawns. +- Added a few new artifact missions. +- Fixed server not sending condition updates for inactive items, potentially causing the condition to get desynced when all of the components of the item go inactive. +- Fixed clients being unable to rejoin a SteamP2P server after they've left. +- Fix to inventory items occasionally getting mixed up in the campaign. +- Power consumption of damaged devices doesn't increase as much anymore. +- Player cap can be adjusted in the server settings. +- Fixed "cannot remove joints when the world is locked" error message when a character latched onto the sub is attacked. +- Fixed currents heavily slowing down the submarine regardless of the force or direction of the current. +- Improved name tag hiding. +- Fixed explosives that disappear after exploding (e.g. nuclear explosives) not playing the explosion sound. +- Fixed server list not listing passworded SteamP2P servers correctly. +- Reduced Daedalic splash screen volume further! +- Made tonic liquid purchasable. +- Subscribed Workshop items aren't shown in the Popular tab. +- Fixed some held items vibrating/twitching when moving. +- Fixed turrets emitting muzzle flash particles in an incorrect direction (the rotation of the particle was correct but the direction it flied towards not, which isn't noticeable with the non-moving vanilla particles). +- Fixed clients not relaying console commands that don't exist client-side to the server (i.e. custom commands implemented by a server mod can now be used by clients). +- Added combat priorities to alien weapons to allow bots to use them. + --------------------------------------------------------------------------------------------------------- v0.9.701 (Unstable) --------------------------------------------------------------------------------------------------------- diff --git a/Barotrauma/BarotraumaShared/serversettings.xml b/Barotrauma/BarotraumaShared/serversettings.xml index 072e124f1..2db07e73f 100644 --- a/Barotrauma/BarotraumaShared/serversettings.xml +++ b/Barotrauma/BarotraumaShared/serversettings.xml @@ -43,6 +43,7 @@ public="false" port="27015" queryport="27016" + playstyle="Casual" maxplayers="10" enableupnp="false" autorestart="false" diff --git a/BuildScripts/depot_1026341.vdf b/BuildScripts/depot_1026341.vdf new file mode 100644 index 000000000..cfae9eee1 --- /dev/null +++ b/BuildScripts/depot_1026341.vdf @@ -0,0 +1,16 @@ +"DepotBuildConfig" +{ + "DepotID" "1026341" + "contentroot" "ReleaseWindows" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "config_player.xml" + "FileExclusion" "Thumbs.db" + "FileExclusion" "*.png" + "FileExclusion" "*.ogg" + "FileExclusion" "*.mp4" +} \ No newline at end of file diff --git a/BuildScripts/depot_1026342.vdf b/BuildScripts/depot_1026342.vdf new file mode 100644 index 000000000..2e15aa6cb --- /dev/null +++ b/BuildScripts/depot_1026342.vdf @@ -0,0 +1,16 @@ +"DepotBuildConfig" +{ + "DepotID" "1026342" + "contentroot" "ReleaseLinux" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "config_player.xml" + "FileExclusion" "Thumbs.db" + "FileExclusion" "*.png" + "FileExclusion" "*.ogg" + "FileExclusion" "*.mp4" +} \ No newline at end of file diff --git a/BuildScripts/depot_602961.vdf b/BuildScripts/depot_602961.vdf new file mode 100644 index 000000000..f2236375a --- /dev/null +++ b/BuildScripts/depot_602961.vdf @@ -0,0 +1,13 @@ +"DepotBuildConfig" +{ + "DepotID" "602961" + "contentroot" "ReleaseWindows" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "config_player.xml" + "FileExclusion" "Thumbs.db" +} \ No newline at end of file diff --git a/BuildScripts/depot_602962.vdf b/BuildScripts/depot_602962.vdf new file mode 100644 index 000000000..a602f2d79 --- /dev/null +++ b/BuildScripts/depot_602962.vdf @@ -0,0 +1,13 @@ +"DepotBuildConfig" +{ + "DepotID" "602962" + "contentroot" "ReleaseLinux" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "config_player.xml" + "FileExclusion" "Thumbs.db" +} \ No newline at end of file diff --git a/BuildScripts/depot_602963.vdf b/BuildScripts/depot_602963.vdf new file mode 100644 index 000000000..87d8fc522 --- /dev/null +++ b/BuildScripts/depot_602963.vdf @@ -0,0 +1,17 @@ +"DepotBuildConfig" +{ + "DepotID" "602963" + "contentroot" "ReleaseMac" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "config_player.xml" + "FileExclusion" "Thumbs.db" + "FileExclusion" ".DS_Store" + "FileExclusion" "__MACOSX" + + "InstallScript" "Barotrauma.app\installscript.vdf" +} \ No newline at end of file diff --git a/Libraries/Lidgren.Network/NetPeerConfiguration.cs b/Libraries/Lidgren.Network/NetPeerConfiguration.cs index 7105eca0c..56836fef7 100644 --- a/Libraries/Lidgren.Network/NetPeerConfiguration.cs +++ b/Libraries/Lidgren.Network/NetPeerConfiguration.cs @@ -506,6 +506,14 @@ namespace Lidgren.Network } #endif + /// + /// Changes the number of maximum connections after the peer has been started + /// + internal void ChangeMaximumConnectionsInternal(int num) + { + m_maximumConnections = num; + } + /// /// Creates a memberwise shallow clone of this configuration /// diff --git a/Libraries/Lidgren.Network/NetServer.cs b/Libraries/Lidgren.Network/NetServer.cs index 22e2effdc..615d727ce 100644 --- a/Libraries/Lidgren.Network/NetServer.cs +++ b/Libraries/Lidgren.Network/NetServer.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Net; namespace Lidgren.Network { @@ -66,5 +68,33 @@ namespace Lidgren.Network { return "[NetServer " + ConnectionsCount + " connections]"; } + + /// + /// Changes the number of maximum allowed connections, closing existing ones if the limit is lowered below the current amount. + /// + public void ChangeMaximumConnections(int num) + { + m_configuration.ChangeMaximumConnectionsInternal(num); + + int reservedSlots = m_handshakes.Count + m_connections.Count; + while (reservedSlots >= m_configuration.m_maximumConnections) + { + if (m_handshakes.Count > 0) + { + IPEndPoint endpoint = m_handshakes.Keys.Last(); + + // server full + NetOutgoingMessage full = CreateMessage("Server full"); + full.m_messageType = NetMessageType.Disconnect; + SendLibrary(full, endpoint); + } + else + { + m_connections.Last().Disconnect("Server full"); + } + + reservedSlots = m_handshakes.Count + m_connections.Count; + } + } } } diff --git a/Libraries/MonoGame.Framework/Src/MonoGame.Framework/Utilities/Imaging/Stb.Image.Generated.cs b/Libraries/MonoGame.Framework/Src/MonoGame.Framework/Utilities/Imaging/Stb.Image.Generated.cs index 126855a2b..8a32c72d9 100644 --- a/Libraries/MonoGame.Framework/Src/MonoGame.Framework/Utilities/Imaging/Stb.Image.Generated.cs +++ b/Libraries/MonoGame.Framework/Src/MonoGame.Framework/Utilities/Imaging/Stb.Image.Generated.cs @@ -2467,6 +2467,8 @@ namespace MonoGame.Utilities sbyte* zout = a->zout; for (;;) { + if (a->zbuffer >= a->zbuffer_end) return (int)(stbi__err("overread")); + int z = (int) (stbi__zhuffman_decode(a, &a->z_length)); if ((z) < (256)) { @@ -4787,4 +4789,4 @@ namespace MonoGame.Utilities return (int) (stbi__info_main(s, x, y, comp)); } } -} \ No newline at end of file +}