From 15499cb7047f65eaa0bef14dd7d23622c9576985 Mon Sep 17 00:00:00 2001 From: Juan Pablo Arce Date: Thu, 30 Jan 2020 15:56:31 -0300 Subject: [PATCH] (e42047dc1) Tester's build, January 30th 2020 --- .../BarotraumaClient/ClientSource/Camera.cs | 2 +- .../Characters/AI/EnemyAIController.cs | 24 +- .../Characters/AI/HumanAIController.cs | 2 +- .../Characters/Animation/Ragdoll.cs | 10 +- .../ClientSource/Characters/Character.cs | 37 +- .../ClientSource/Characters/CharacterHUD.cs | 118 +- .../ClientSource/Characters/CharacterInfo.cs | 20 +- .../Characters/CharacterNetworking.cs | 1 + .../ClientSource/Characters/HUDProgressBar.cs | 2 +- .../Characters/Health/AfflictionHusk.cs | 6 +- .../Characters/Health/CharacterHealth.cs | 1020 ++++++--- .../ClientSource/Characters/Jobs/JobPrefab.cs | 74 +- .../ClientSource/Characters/Limb.cs | 27 +- .../ClientSource/DebugConsole.cs | 7 +- .../ClientSource/Events/EventManager.cs | 18 +- .../ClientSource/GUI/ChatBox.cs | 52 +- .../ClientSource/GUI/ComponentStyle.cs | 101 +- .../ClientSource/GUI/FileSelection.cs | 121 +- .../BarotraumaClient/ClientSource/GUI/GUI.cs | 101 +- .../ClientSource/GUI/GUIButton.cs | 65 +- .../ClientSource/GUI/GUIColorSettings.cs | 26 + .../ClientSource/GUI/GUIComponent.cs | 290 ++- .../ClientSource/GUI/GUIDropDown.cs | 26 +- .../ClientSource/GUI/GUIFrame.cs | 3 +- .../ClientSource/GUI/GUIImage.cs | 18 +- .../ClientSource/GUI/GUILayoutGroup.cs | 71 +- .../ClientSource/GUI/GUIListBox.cs | 80 +- .../ClientSource/GUI/GUIMessageBox.cs | 21 +- .../ClientSource/GUI/GUINumberInput.cs | 118 +- .../ClientSource/GUI/GUIProgressBar.cs | 44 +- .../ClientSource/GUI/GUIRadioButtonGroup.cs | 12 +- .../ClientSource/GUI/GUIScrollBar.cs | 9 +- .../ClientSource/GUI/GUIStyle.cs | 117 +- .../ClientSource/GUI/GUITextBlock.cs | 105 +- .../ClientSource/GUI/GUITextBox.cs | 93 +- .../ClientSource/GUI/GUITickBox.cs | 74 +- .../ClientSource/GUI/HUDLayoutSettings.cs | 80 +- .../ClientSource/GUI/LoadingScreen.cs | 13 +- .../ClientSource/GUI/RectTransform.cs | 54 +- .../ClientSource/GUI/UISprite.cs | 53 +- .../ClientSource/GUI/VideoPlayer.cs | 6 +- .../ClientSource/GUI/Widget.cs | 2 +- .../BarotraumaClient/ClientSource/GameMain.cs | 18 +- .../ClientSource/GameSession/CrewManager.cs | 1980 +++++++++++------ .../GameModes/MultiPlayerCampaign.cs | 4 +- .../GameModes/Tutorials/CaptainTutorial.cs | 27 +- .../GameModes/Tutorials/DoctorTutorial.cs | 25 +- .../GameModes/Tutorials/EngineerTutorial.cs | 24 +- .../GameModes/Tutorials/MechanicTutorial.cs | 12 +- .../GameModes/Tutorials/OfficerTutorial.cs | 6 +- .../GameModes/Tutorials/ScenarioTutorial.cs | 4 +- .../GameModes/Tutorials/Tutorial.cs | 69 +- .../ClientSource/GameSession/GameSession.cs | 20 +- .../ClientSource/GameSettings.cs | 356 +-- .../ClientSource/Items/CharacterInventory.cs | 35 +- .../Items/Components/Holdable/Holdable.cs | 2 +- .../Items/Components/ItemContainer.cs | 32 +- .../Items/Components/Machines/Controller.cs | 4 +- .../Components/Machines/Deconstructor.cs | 48 +- .../Items/Components/Machines/Engine.cs | 64 +- .../Items/Components/Machines/Fabricator.cs | 158 +- .../Items/Components/Machines/MiniMap.cs | 22 +- .../Items/Components/Machines/Pump.cs | 130 +- .../Items/Components/Machines/Reactor.cs | 570 +++-- .../Items/Components/Machines/Sonar.cs | 386 ++-- .../Items/Components/Machines/Steering.cs | 360 +-- .../Items/Components/Power/PowerContainer.cs | 61 +- .../Items/Components/Power/PowerTransfer.cs | 106 +- .../Items/Components/RepairTool.cs | 4 +- .../Items/Components/Repairable.cs | 38 +- .../Items/Components/Signal/Connection.cs | 251 ++- .../Components/Signal/ConnectionPanel.cs | 6 +- .../Components/Signal/CustomInterface.cs | 13 +- .../Items/Components/Signal/Terminal.cs | 11 +- .../Items/Components/Signal/Wire.cs | 12 +- .../Items/Components/StatusHUD.cs | 38 +- .../ClientSource/Items/Components/Turret.cs | 18 +- .../ClientSource/Items/Inventory.cs | 63 +- .../ClientSource/Items/Item.cs | 71 +- .../ClientSource/Items/ItemInventory.cs | 30 +- .../BarotraumaClient/ClientSource/Map/Gap.cs | 8 +- .../BarotraumaClient/ClientSource/Map/Hull.cs | 12 +- .../Levels/LevelObjects/LevelObjectManager.cs | 4 +- .../ClientSource/Map/Levels/LevelRenderer.cs | 2 +- .../Map/Levels/Ruins/RuinGenerator.cs | 2 +- .../ClientSource/Map/Lights/LightSource.cs | 8 +- .../ClientSource/Map/LinkedSubmarine.cs | 34 +- .../ClientSource/Map/Map/Map.cs | 6 +- .../ClientSource/Map/Structure.cs | 11 +- .../ClientSource/Map/Submarine.cs | 20 +- .../ClientSource/Map/WayPoint.cs | 20 +- .../ClientSource/Networking/BanList.cs | 45 +- .../Networking/ChildServerRelay.cs | 1 - .../ClientSource/Networking/GameClient.cs | 102 +- .../ClientSource/Networking/KarmaManager.cs | 58 +- .../ClientEntityEventManager.cs | 4 +- .../ClientSource/Networking/NetStats.cs | 10 +- .../Primitives/Peers/LidgrenClientPeer.cs | 8 + .../Primitives/Peers/SteamP2POwnerPeer.cs | 8 + .../ClientSource/Networking/ServerInfo.cs | 140 +- .../ClientSource/Networking/ServerLog.cs | 68 +- .../ClientSource/Networking/ServerSettings.cs | 151 +- .../ClientSource/Networking/SteamManager.cs | 36 +- .../Networking/Voip/VoipClient.cs | 11 +- .../ClientSource/Networking/WhiteList.cs | 24 +- .../ClientSource/Physics/PhysicsBody.cs | 2 +- .../ClientSource/PlayerInput.cs | 6 +- .../ClientSource/Screens/CampaignSetupUI.cs | 48 +- .../ClientSource/Screens/CampaignUI.cs | 59 +- .../CharacterEditor/CharacterEditorScreen.cs | 218 +- .../Screens/CharacterEditor/Wizard.cs | 323 +-- .../ClientSource/Screens/GameScreen.cs | 36 +- .../ClientSource/Screens/LevelEditorScreen.cs | 55 +- .../ClientSource/Screens/MainMenuScreen.cs | 180 +- .../ClientSource/Screens/NetLobbyScreen.cs | 345 ++- .../Screens/ParticleEditorScreen.cs | 32 +- .../ClientSource/Screens/ServerListScreen.cs | 288 +-- .../Screens/SpriteEditorScreen.cs | 208 +- .../Screens/SteamWorkshopScreen.cs | 400 ++-- .../ClientSource/Screens/SubEditorScreen.cs | 877 ++++---- .../Serialization/SerializableEntityEditor.cs | 109 +- .../ClientSource/Sounds/SoundChannel.cs | 6 +- .../Content/Effects/gradientshader.xnb | Bin 0 -> 1174 bytes .../Content/Effects/gradientshader_opengl.xnb | Bin 0 -> 1125 bytes .../BarotraumaClient/LinuxClient.csproj | 2 +- Barotrauma/BarotraumaClient/MacClient.csproj | 2 +- .../Properties/launchSettings.json | 8 + .../BarotraumaClient/Shaders/Content.mgcb | 18 +- .../Shaders/Content_opengl.mgcb | 6 + .../Shaders/gradientshader.fx | 24 + .../Shaders/gradientshader_opengl.fx | 24 + .../BarotraumaClient/WindowsClient.csproj | 2 +- .../BarotraumaServer/LinuxServer.csproj | 2 +- Barotrauma/BarotraumaServer/MacServer.csproj | 2 +- .../Characters/CharacterNetworking.cs | 4 +- .../BarotraumaServer/ServerSource/GameMain.cs | 4 + .../Items/Components/Machines/Reactor.cs | 6 +- .../ServerSource/Items/Item.cs | 1 + .../ServerSource/Networking/GameServer.cs | 25 + .../Peers/Server/LidgrenServerPeer.cs | 4 +- .../ServerSource/Networking/ServerSettings.cs | 5 +- .../BarotraumaServer/ServerSource/Program.cs | 7 +- .../BarotraumaServer/WindowsServer.csproj | 2 +- Barotrauma/BarotraumaShared/.gitignore | 1 + .../SharedSource/Characters/AI/AITarget.cs | 42 +- .../Characters/AI/EnemyAIController.cs | 20 +- .../AI/Objectives/AIObjectiveManager.cs | 2 + .../SharedSource/Characters/AI/Order.cs | 103 +- .../Animation/HumanoidAnimController.cs | 2 +- .../Characters/Animation/Ragdoll.cs | 4 +- .../SharedSource/Characters/Character.cs | 15 + .../SharedSource/Characters/CharacterInfo.cs | 12 + .../Health/Afflictions/Affliction.cs | 2 +- .../Health/Afflictions/AfflictionPrefab.cs | 5 +- .../SharedSource/Characters/Jobs/JobPrefab.cs | 74 +- .../SharedSource/DebugConsole.cs | 16 +- .../SharedSource/Events/MonsterEvent.cs | 3 + .../Extensions/PointExtensions.cs | 11 + .../SharedSource/GameSession/CrewManager.cs | 31 +- .../SharedSource/GameSession/GameSession.cs | 6 +- .../SharedSource/GameSettings.cs | 12 +- .../SharedSource/InputType.cs | 4 +- .../SharedSource/Items/CharacterInventory.cs | 2 +- .../SharedSource/Items/Components/Door.cs | 2 +- .../Items/Components/Holdable/Pickable.cs | 2 +- .../Items/Components/Holdable/RepairTool.cs | 2 +- .../Items/Components/ItemComponent.cs | 7 +- .../Items/Components/Machines/Engine.cs | 5 +- .../Items/Components/Machines/Fabricator.cs | 2 +- .../Items/Components/Machines/MiniMap.cs | 2 +- .../Components/Machines/OxygenGenerator.cs | 2 +- .../Items/Components/Machines/Pump.cs | 42 +- .../Items/Components/Machines/Reactor.cs | 48 +- .../Items/Components/Machines/Sonar.cs | 15 +- .../Items/Components/Machines/Steering.cs | 23 +- .../SharedSource/Items/Components/Turret.cs | 2 + .../SharedSource/Items/Inventory.cs | 16 +- .../SharedSource/Items/Item.cs | 26 +- .../Networking/ChildServerRelay.cs | 51 +- .../SharedSource/Networking/ServerSettings.cs | 7 +- .../SharedSource/Physics/PhysicsBody.cs | 23 +- .../SharedSource/Screens/GameScreen.cs | 17 +- .../Serialization/XMLExtensions.cs | 25 + .../SharedSource/Sprite/Sprite.cs | 4 + .../SharedSource/Utils/MathUtils.cs | 56 + .../BarotraumaShared/Submarines/Berilia.sub | Bin 284054 -> 284298 bytes .../BarotraumaShared/Submarines/Dugong.sub | Bin 202253 -> 206080 bytes .../BarotraumaShared/Submarines/Humpback.sub | Bin 196397 -> 196677 bytes .../BarotraumaShared/Submarines/Kastrull.sub | Bin 553389 -> 554004 bytes .../BarotraumaShared/Submarines/Orca.sub | Bin 193317 -> 197061 bytes .../BarotraumaShared/Submarines/Remora.sub | Bin 318598 -> 322079 bytes .../BarotraumaShared/Submarines/Typhon.sub | Bin 267136 -> 271369 bytes .../BarotraumaShared/Submarines/Typhon2.sub | Bin 285196 -> 284778 bytes Barotrauma/BarotraumaShared/changelog.txt | 26 + .../BarotraumaShared/serversettings.xml | 1 + BuildScripts/depot_1026341.vdf | 16 + BuildScripts/depot_1026342.vdf | 16 + BuildScripts/depot_602961.vdf | 13 + BuildScripts/depot_602962.vdf | 13 + BuildScripts/depot_602963.vdf | 17 + .../Lidgren.Network/NetPeerConfiguration.cs | 8 + Libraries/Lidgren.Network/NetServer.cs | 30 + .../Utilities/Imaging/Stb.Image.Generated.cs | 4 +- 203 files changed, 8274 insertions(+), 4950 deletions(-) create mode 100644 Barotrauma/BarotraumaClient/ClientSource/GUI/GUIColorSettings.cs create mode 100644 Barotrauma/BarotraumaClient/Content/Effects/gradientshader.xnb create mode 100644 Barotrauma/BarotraumaClient/Content/Effects/gradientshader_opengl.xnb create mode 100644 Barotrauma/BarotraumaClient/Properties/launchSettings.json create mode 100644 Barotrauma/BarotraumaClient/Shaders/gradientshader.fx create mode 100644 Barotrauma/BarotraumaClient/Shaders/gradientshader_opengl.fx create mode 100644 Barotrauma/BarotraumaShared/.gitignore create mode 100644 BuildScripts/depot_1026341.vdf create mode 100644 BuildScripts/depot_1026342.vdf create mode 100644 BuildScripts/depot_602961.vdf create mode 100644 BuildScripts/depot_602962.vdf create mode 100644 BuildScripts/depot_602963.vdf 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 0000000000000000000000000000000000000000..97847aa2dafecd13bac1766047672d9604027f70 GIT binary patch literal 1174 zcmZuxO>fgc5Pcgrjp?BYh(pB%3-y3dh?-J~_E7qfGyy@IkdG1&5_MAttfqG5I4Zp$ z^9K+oP8`Cym;MUGnLmJ#0zaTfgcRP`F;o>Jjd%9FH#58IwOd>3M@f8`0MzlO-S*s` z+wpTP$IO*H^T0ZCz5QIlb$rY5a~qwG)%I(axo3GYU%3h<(Xd! zb07efLBfDG3x%Qv6kF?s?{?#W8oP|!}t@q6g$!FrgUCO$lc zJ{(Y_Dd?OxPZ@ujWS)Ww5@-&%-U)@v^s&cWd2s8CdvE+q+XLg9OtA1FqWJI zhJk264KdNsk>Faw`Dg^x?-y%31XlsH=ug?V^v+-uCgPb4JDG6an!yAPqqx}wb~DiC zGkgbRE$YsUh!t!DSc|wYZyL~J%~Y%nj8GBQFp#>)tJRQ}^VV;S zbC~lMM(c?8CfGbMCA?USOFS84(^2jQ_Yv1AjrUP{6XnHc!(OR) z|0U*$$tZp9@k%|Ym$&3D^JPG%SLtHH3nrGPKM$kmA-M2@??zDg6kN_mV^H6IQFVK^ z&o2vw%A-mRjg3~JQmGYjQen?5by7om8uZxC_hgNR>AkdkoScX@yn09~ZL;llT`$iH z^7&k_nC2<|kA|in*n3sic6;UA)C_s)S@YPw;)mLEagJUHxHUerkGWzXER Q`E!9vR?S{758hYc4~NI63IG5A literal 0 HcmV?d00001 diff --git a/Barotrauma/BarotraumaClient/Content/Effects/gradientshader_opengl.xnb b/Barotrauma/BarotraumaClient/Content/Effects/gradientshader_opengl.xnb new file mode 100644 index 0000000000000000000000000000000000000000..480658200c4eff3d2e8d1dc2d4937ad2c0aae072 GIT binary patch literal 1125 zcmZvc-)_?|6vmx(g;J?#;t4GEriEaVv}hny3DIu7fTD^`s1lm0kT{jK#IEe5ON4kQ zo`%QZ5rA`&{#!d=RJOlg&v$%$oZ06OVV&?(LabsU0It$2wb@c_u}qbYkW!9`xT6$dXuRAQy%A#uOWWhkOnv(;RCQM96m-rxE+ z00&B%bPE7BC>I@vy|$^#9Gg1ppDxgwK-$?~xcdta7H!C1NRF0)b8PI~+(+DF#63W~ zW5hc^ddEl)kWCGYpDbgpy%A!j%-`3Akc;Z@t81PQmC_+9d-aJmv*40DbKNGyiuogw=s#-VR?a7Eh(4X0atAo^aXth z)4*f-PR~Jy8=zC&nOO3s-Edg3=v9*9TEDv2a)K4s-g%76=uyIadUbkwG z0xYi!?*t#q!Pv;&!!oHg5)n=nybJ)!*bt!Bh~UAGgxTAyJ$?!;fR}VtbxLJqHOATx R1$--rRiFCCxa1!y{{eZBJ;eY3 literal 0 HcmV?d00001 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 b1bb8a8018d630d07304e10d4ceb531ced385f57..c97dab01ccf9adf6d58012b64f224e154768fcaf 100644 GIT binary patch literal 284298 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ℜ*Boh{qSc{4p{wdNX^ih(tmm|Uw%luB> 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 literal 284054 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

pvj_JYt|S(#4U}EG}QPKDs)gPh*jqE-*T6#4rMJ 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 D&$`V( diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub index 2a55dd1b8bb4a1a6f04a2d76ca7f7faa53704cfa..f8b00555665ea31efbc7f4bca59c25758b22ea9a 100644 GIT binary patch literal 206080 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

N-V+&Qx%UELMX->b-y(oMIG&5I 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

w&9m?Hrvu6q!SPu68s8%VgI^v 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ℜ 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

6%vYbM-IDX-Mgq8ofs?@gfWlHo!#)9Y4 z?sN~OX}t>S#~o?m((H#}x9rdxKGE|K5);jB(%GA`?*aoCX9sRw2F36Y9NhaI9^~pT zH6@0gEE~qB7sHWc3ID?A|+ z7P}fMki<~Ju+iPO;L#bPsaF%Di{Lp)Dn$wReRG$xa+o+_3B;8@HI=7(dPGsNcj;c; zdvFt9P%$X{7Ju>Q@+Pffx~;(Vbe}^@lkq%#&tSXXY1tpt^9f-%>_+y?C+<;m+A`SL;nOe9U20}&fhArY zuiT8~9S#P@sW%3xdc(f5(~zVWEfG^uDD`dHtDbz!jp!C%da)1+AV_EIqmf3IIKi{* zBhPx!z}vMv|943Hdzmq$21l!`xITK668{=0eEO(Ulup+xN7CRIdEYV{VWWS-(*Sj} z)n8A`pE^JMBgwbG@@-37}vDyAU&`JAj(eg4D z6)KF{Fh9fZaIc3WuxzZiTdHu;@hkY80_nV%GlkD_@Ef6cQoYk~<4Ft622wF}B;RLz9^~jNjxau^>-jitNheS{ z*t6RVh1`dBR8y9;r-O`wDM~g}8x$2?1;p^bi*h^`p z9;teKJ$!zA++aZACfm|ifM*=spRU5B@_)-I`i^!!dgcM4)^cm z!=|5M2C^>FKM^#kkr~S+`KO2&cBA01SHo8w-ruiAU>KEwuxmXUd#AKZptb15>t%Qk zvD4)hsp7L-d>-RP6JS7p;)L?ILH+0stxpcX8!GJ{Io2?Q9(G(b{!}?Iy=C}1DTDRL z{WojngWUArja(U`7vi|m+ygDqvO2etmo{RHtmmg$YzYi&8>o_-lG6;`^yS0>#U$>_ z|8$`!T@mAC4_k&yVjaJrojz_9{gW?gHX<5Mp=nwIwztNh7$x>aT_w+kKC*U+k4%(4StIJlhH3f7}dw4 z91Kr`bi8WfgM<|T5|d_`3bnkCdi$I&x94f|T@S6~KSlnlH_UVL9Mtf_i8YBBL-}`8 zJYI6ZZ{Wxkcq=mfH1$n%n;jEa#JfgJu>l+N#dTDD+*mdg(#Y>GD>Nlrq}^*T-mW9R z#mTZqPd0Av%L+OPAI<7UaKDW(p=?FC%pbnDrtfQtxS;DG2LVK30q^+-4?m7y&?R-& zj;)H#TY6fg_RbXWoO{*D^3eA9~kf$R-uoYYeYR@4Uf z?6KdL*pC0&M=FIXGHT(0WvltB?2#g7Fc75C)!Ol@+FL_zJBTDWa(57y5447rB*KrN z*XQ_D@SLg;xj z!T#{{JE|vt0yqPQD2jZfG@kzL2l9ra3+ZXpD?v7MpmC5z%64)pcQWc1aCyV5U(qMd z)2zAM&{NJ<+esd(Z4j6nJHYHCv7WMgt2e_B?|Hjc!|hClFHi10=rX7XOL`GrDv!Bs zA#l(^96rqk)BU0odwi)?`#$A?o(W!5(oQCX$-p%$T9&85^P-SBNsHk#E@)x_=0m}I zD=8iOtLdL9@wyBC{hJIW<9f7Q+@3_Y^7W%@#FJ^`WZPbhCefFw&eg>E5Q zxWHJ^=a!WU`^ig(rlM(*;^EczQX_Y+HN9(938^(5B^i!1x#4Fo(Hm6muV?ah^Sfz~nnjNaTC96IT7Bg|S5)}S&o65aNcHD2 z^JjvqAiYBVd-KI!{xpqKE}hBn2!TaQc6i#UTk_4faCd~B-Qrqjuzjryw5RfVD?F;H z@E!tIK@dNsW=+GWDTu6Zr1TQJcbBhm2JCU$0^_m5<}+w}bwiG2#g?h;h1aiAz2Nt{ zjri+PZg5597}-44<&zD2U8hs*H2dPO8hV{4g0?&cG*_zk#C`3Hbxj{iqk6pro!buXxn5C;p0;H z#H8UqfFbfsSX3AXJbQm>wm9ajf0G)OG|ES%KRW_SIpRoO5+56OSuBO=c5BPu!*i+W z=6Cm$v0psw9pUg&xJ1`3E5Q>>W0K57q~@xZ?0rCSEPH58Kv9?Sjgyw&O~XTM#4>|V z_HHLNdw4_U%(1u$9jEn=)yX?7K_2}Qy-}xWOTL2YPZI-L$#s2zp-{#|BBsHT-iOeT zd|Wxcehd{;V2G>v&6)wTbWV6CU{%~FdgVW{;-+>GJNJq7t0k+I&85if3xi z>zPqWPBr4e(4+AIgQ9!b1xjXxJ7DNXxbY5A+i-yfZ!3KGj$c}Gxb1>Kz;P!ew|->v z_o~GWFZTHFDe2?8K6yFwF|JX0ZZg`Wem&*qd$WRHm)qDT`1_qTui*Xgmd(~DQA-#= zE*}KuyV(qKLVGtj;c%tNUwIboPdEwsPm6kl3(jYShV?t)9kB!`4l5ye6r*heF@*M9cw&tLlTs%U^wt1$fd>6^~@lm=i zGiDXfoI40lI?T#&j(L(}BdDJRYK`BI4Sd!16fB@d6(X@OL6c{Gd1mJ6j34;mYC>$mdY-jP*g>j{P)mAe(-z`dBa`gMRku+K&wW|I-oP=wf1v^0VPNEUE-(5BsF)D&Mvhb*i^jNZrFT4J&=U3 z2bs3U^9vSr# z`Ph=k8pnc;vqRO@VUkXTv-C+gmV605S!`+B5C(7I*mBt-3ZR~4$h1TIKmwlog8ENIrpO>be~z;l*82fJ4gxdvZ^cz~-g7X07t4w8UkCw7-wW3b9x3 zXHbAzW<5x9>%|sZZDuHNpt6Z+`Rb`y;>Ga6x%;hOw*;!d=t2Y^xtaTRfHuo_H-~Jw zH|4+I0J(F5e)HFJcoz1v{seQ0_H;lkl$I@9!zuzV7GoR{yxOQR^QT`W1t!8U!5^X`=)=vm?j=%D>-He3W(~czn;XvKKW@Ec+e(aGW2-<)nwe=bFj@g663Mnz~z+B}@ zKd10Y{Cg;$aW}l~SBP2sbNo4!iB#n_e|d=~ZE!5u->u;eU0mKBf4A7=d!ty*6Nh(N zK6h^dCkFVHRODN4O5HpUM2D99iYL(Mz3Ct7D(#3jd$}DPisZ?q65ivrxGx0R+HXg0 zXoHpzxQj8x;$d?&EQ?!u=WI|su?^aj7M=?fx-vWSCSmz}`D$c)=|VF5Sq93GF^-I% zgx&u-lFjbR&r2m&(nFZH^)rEG4A(Tn&VHqX2%Ey|Z>0xg3lC#1UmnkPK z11bhZD#;o+x`{;HvV-%$!2one1g+X1d)^b(XPcdMtoVI{n}KukB+w>{6?8-88Nu-fA3Q)(9m1`5_y{(X-U_3U4f zK~cnh?rjHG!AB^1v-|t}12Pf}f4rl7EaNSXw+2BET5jee7-uIycqV|h8@ytL$yW+d z78BLdsdSR?ver=U`e*xNeotdHps%xXX&B|5tq2HZ>9@e1C2syG{87L<+&sH&a{Z7^|C;FOdSv8GzeAU3-sAAy|AY?VHIoX0i|^yyb+{&@?g z=BBFRNS0pGdV@Red1dj=;%T>!cHD%0e*p2;qnaycspXE5}{ zI$K8a#Ny34E9iJpRDf{!F;eoK%2Gv0+!RKy2g}cRaVBr?7v(RLKI&jq%| z(ovVHMG7*ta5{%|D4@awj+-ulJGm9hc3y-h8$=)xuFP8P=*4dC#gf*1H#?c8sr+Z1 z8BBuy9exSOj&y+QE`_HoICUo`t)uTSrbksTH*wXIe${k(CJfR3j+bzH=VvYFj+vp! zI@v~O>k!F?N{63&NGoRoef|J?_mh!eehZg(Xgtu;3%NR5`UHh6zd?$?PhslzD8!m|dT1iG;VOa$;?}nnvt{5N z^rraW^b&yrg>?0tegLwD<*y268bZ?^`Asu)ZDO8X18WQz*4Gf!;{&Sp4`ezDZjU#< zPwsRAKC-RSQcjWwzLoX%nfxM^xjt=BC6zYB@aoM|Hz&e8SUacr&&}O1#AG`O_6%Qs zPj?Ao_V)sB_zU~V(3tN*@`6v2*)gw>d`rGi$Ja|;c znMGx41ftMZ2(nbv_f;&X{LN`FFlf{The`R-xu*i;B4R7fvKExNs#&6~SAIgvu-w2p!w*fdrW!Q&Xy_32I@QSCkq;RiYtWPq0`Q>=}*C2#Xa5Z@Fgi~bd zT%pr`MCp5WlOwJ**Jfb6o%>#dJWq;`9x7EGzqf`dzPse+3USqQOgW_ z4{VBq4$L5gRPSA`=}4}J3omJDh{;_mXR0p`Vr3NW!`3hC6Q{qvLY+A#tmfcvua%rK zijX~){VY|2-g3|A9&C{@%I}{%KTzFL;IcG9&lPkeBFgnJAXiE-KSw$6Gpa@P-r;w5uv^Bwyv3T zX8kp9)!~Hm`uA~BGrum@lVe;YM>;z7nc-U=_)*+Ck_T@RXcm3_;`h_G&$4rZBVK=Z z%O5PXg#-WXlRP_2RBD);t; zHJQ$vfDm^s-pWv9$#0JkYLRf!Er|W~-qKdWes4gqDx8|NivyFrMVZs{xbp8CNWf|# zX6AV(ST{X??+2|lmCgjO3wdE`;r?QCzd#1aRSdS`b5#GnkaAPuF&*dfdj(&PSUV=5=vey_w zp$AeG?K~Ux+f<4jFhw3hxi;(iF>g0#+#k2^1TUhlhH`U)s3cgUNKIXQ7v%GrS3}0E zc|b(QpN2qenSj+faYw^JiC?K3yht&1g(z}+!kT}n&`E@FU|tN~QUV2El55YfxgONr zhpK))OjA?rQ%?%}ReOPI4^;M!iHc0*F+XNQ_dzRo1Z{2sTo3$dRlO7p%4mlkc_X>G zKnI?eZ_Buk!Tp^DQn%+MD~r(rwIT#>flntX5i@-o=u{-919t@TlAlB}Zm;9cnDN&L zik^@NKE%`vIZlxuG0%gR<0Z>4pk=5AJ+ylcJ+dHZ9{dnT^K^+L7&+q*=91WYHzxKr z>G$VGjN15?)Ajci%>KIdw@a#2=b__x5$S;pRy6LkHNX%4$0wQ&zr2ZH$gzEHbkXGk z75=#H_nyh|Z7(tzTUXfVPl{-k)OX*{FNhy6x;&-jrocfML&r$1`uor!5Z6rPN)K4l zBm8;Bl3-%)S&nBLKH%MyEw@3Wupd;+o+gGKzBPP5?@4~c6p1kvP`C#EVP5mMw8D?*a(f|^#nQ8LX4zOC#xxY7Std#W_E#Rr zkHn>#WmqZcLHi(C&%x>#EP==h-u`luf}1XKj)>l$3TK_>Oo%YVZothsz8FS z(fzOdSs@{x#ffZKxNVz4itqA!To%e{2_(8ht{_=9c?f|_$IB}R7tWGh6iwp|+rg>O zMMv96jg4ym#NYbvcoF{o_F6RChFvZ^X@P-VVEX2uz1n~Ug{=3|)#O)7)VomJ5TrO_ z{v$I-mg?SdVlpLG+Ws!ho+g?i>wmO%gkvtb+OvK*;;y$X?VK8FXRw$>J2W$bex+TuC%5y>C+*EX zhKW@z>BB)`?=qa_qZwWNWxHsTfL|C%f;_eI!y3nHKA}1%BdR-HnQOrj1UVMA&_@+R z_%@523DqGpJE}W|47G<_(Oy_y>C^eh$YuN>o{e(~3%hKe=;8AL4iWo$%Z}EeGRE!3 zp^SV7#pZ{Gc|C+$Ig#>5fECu3H2+p^b+T#KsfPJ4roNH8HPWjn%b_Tm8!9!(regRt zW@)YumM1fRU%UsLDbSaPWgiiBTYdz+-PAPrcu)Gq`w3%m`#2^WUu-La5v(T>#kbN& z*L?g;hxZbi+MzcnZL@r4bmw-HWiAr0q;L}zCwCYqpJR3*g%_0Larwws9oV@FrL$S* zi^JF5H^*{=Jz5ZOCNHR*7R#iO^t)7r?(_M}zo3Z-)~*Gzr+4TxygLQx1xjD#W<%%q zx+AlYLi{CLVXMKH<)~b!{oH|w;xrL6onP|N6EU_|G{ z?383kTf>JdcZi5^3ZCE3V^JZ^?fJPak$2D0kN#->Zw&Yo$9FKFx)J|0v|_6FZRR?Z zbEpN}$fkSQy0JRrmfh_nQITJRFsVVxhwQhI6wB~HSAX;$yfLQ;BFAoh52rw-5*A}_ zHhPU~h_K-YCtess4Gw1da)oxCFnW`FH;dq-O3&91MKuYoP+A*Q1%*GME1R(*uOc_< zRAD1#Bn6N-L3xs;e4!pC@thy*E+;KqL{r@(AqaKoTj4L!BO4u1Ztj#^f!OCWSkD*m zC2AvIEb`d7Z|r#k)jm{3vI(5JLlHdI_}>RL%+$ksc1B0cU(^u@rzOkx=W9sHYn?X( zEGExbJ|XW787KG*0TjY=MovcnC8n+DDyyXA#HfZsRG(V4J=S~sot~$@(TM(&j)y(9p>`eGgEZ7 zTd@2fDD%ZkpI1%^dm0UOWwfg>N|^J*o)QC1strdPG(Y@@Zy$F<4QfIS?XkUHVEx^+ z{(3~_qeXkmCIpo7My$UT&GjS3tc0~nLJfNO|C!a z!Vd4kNP~Z6eiX9vEJvh>z4sq(Hb^O;H zYX~P*h82s@6@q`jE;2iRAJ+glgpRZ3-7aVNR1HjpyD2_n?`23tiXMp7!n_fnKfb3; z>@mkG-1U^`!QBz43^A&Ri`0iTIR>dfmn}?aDHYI-L8z`{pizEY zDJ*yL_7MemA^9+%ccl3dHva`fgFdmSUzKJmVY3t0FJwxGzGUwe#4hz59h7j~{>oo| zH_rD%t2K%bc(|tKw@g7EF^8+!9U~(YANmC)H=@~Omp<~2hf_heqz5_(D<;^ep(9dU zsbZ>hqt$)gT=zHZMMld6Z_ISxiRSzt^7gI&+I1M`D7FryuB z7vk6y=l+GvSPL;D*;;=MNE9~DbANeYuFY=4sPNPfja~RXTYvG+C10^(3LK`y>%|d` zb`BR#O*jaE?AWd4&O$SewOVgHztQ_wJm&TRQgf)(y8R7^g>PQeri7-V+$sjZJk9QY z+K`C4+h6W2Tuj}>%&VWX2w_VlI<*N6i1B+a6l#?(sLqa#NjetoFoIk@PP0bOhsCnm zjfuL)p{$$sXO}zQ$=S9;tmkLPs*Zkh?mC%bQrHCb>##~4sFoVYFyG(aX?HON8=Qc$ zPaWOhgxA!}X(6IMxzMYxFIm_@_~`Rn9fzbD>^v&&AY%DcAZwB?>hI|n!Nfpqyik6t z%fs(y+^QiVLbv(CzCa(tkS7rPXW^~h=rz(_z#}N`Rb42Q9p8qwWl7YVduMrO`=XU! z?Wk#pZ0FpKO&>cb|Bz85b^_&?Ua*(FUpdEd-s>^boYzBhQE0SUA7|?Zx6bAD#gGm# zbQ%W#+N#jy9_CLq&llr2w^cawc~37#6Zu6^!w*`oA`{|v1(aHaYnLkOI@H^F%Xdyi zPb_0|%HS*mlH>2T3>Wxn2y&ilY;_+$>JBW@sB66yf;7PyB{`rt4?&?D6h3dT+m_q# zXyauj1?LAj)VVbnZ8%r0*6!krchQ9`AVqL+C!sL(;I=QB=i>6Cemt_-BZ!yfd@r^Y z>xJZWKAh4yf}Muq2;y3WNC_e{P~7r^V9Vl7k_U@thqpUxz4A*S$pNP6MOa{;5PDWI zEilgen|HShH{TiTsXBsg~(Fi*VJY9g`8_0Jn)dW_MzRYV+Lpb*IktPK!5VHh3 z+P}BQla1uGZwd=iI)Ta#&y<<`tqClOi-A}}{rOTwRP}MHyZE0gcjn;wg1cP`rUzSQ z=kqR=056FxkIHjr$42>m89)hul8YVWk78uV@I?AeSqm z@#H#5X`c7f;CEVhK6hzHte&=FTz^A<`!(`4u=1+*%vdv&<#!XuAXV|ePrGv482@9Q z>#*+fUW(J?-7 z7!H*Yj=x@q1Z+5h3gy#ANeO0V`O^H|lN6t~?uXlShRa2g^6`Jn*&OJuT zOi6rFU7$`=CgvrTkZ^gU{OF?F=g#`E>!pW%I(go};W#hZ8~v$}-$=9r(U=KcbjrO~ zv-Gna@&gkoSwqIBe$}VIDcw&e$BSXwFZVLh8Gljs_rh%UH_1a4^G-j37<9ApAfO4J zOEid)2Yy^yFPDC2elf+xW~ZzKt{m-Qv|lz3Xc~|UK;1!F1Mi*4$R z$wO0D@N1e1c%&R30%h%#daZCrJohFct58^a8D}yKJX_!o6P?~^56T1GWN`x2E|6lQ zzw0Y2uCRTS>KmzmILTwtd(>}M1bcFMmU)$I1**(#ZwMS)T2r~J?K@;eO9>O_4fz;p z_h9*X+EX^Ns_6d0FXo7XbBum-!NX?znuVW~y^_63t_$v7p=xKZr);~D9HA4`Q)C#H@6x!_o@Kci?aoqGI~kz!L&CtaBO% zN<>=;O=_*mnf{gD@f?@yx{S7xINj!X{f^FrzpE^#ydZdUA4O)!YFnXlLqJ*_{46_4 ze>)NJIm9#qlrDKqpYgou8l(h;b@ zC0tVZW-_eRy*NjM84C|RSqyO8HEDosVh0my!O{glJ1+=gzsmK)!=mrg`2fQnmUIWH z8WaN&^&p>Z@@^5TmU|2cbgBQrZz{-%&7FS62kDSfYus1fhJC&>y3}H8nMH8gIHPhi z=W64U4f@ru_85T1@c0^yRTc>13@Ug#S!T|GZNUdKac)LOG}{9LEz0 zqPPnrY8)}6ZKu@jAy3|*G`ja+#mf#=1ASi*48b(~ea>p{uH{`)C8nvciBd529$DHS zHq(3)-p$V1kRSPFqH2KDR9IgmXF*KH%@wFnQqgxX)T&n~b-tO)d|EI9)NfFM0_7v5 zvqB$yNGI@PIY+SFw-X9{vk1vu+2k%m)h=h}QNVEH?zIZ&} zF9|VW3z(rth-*N>=DwQxJL`+70R7qhzN(Oh{QCV8ZJ&uxP+=I6*ey==E6#Dzqm=&5 zWvkGiLhQZNA(xNMeD<4SKVSAY+eOJKhu(hK`qriAQnV46f94l>%a-SbF0mYj{)J>c z;=8a~s0UPgahr`3VBkz9M`RB|{|TU81JG(Rvb^}Da@C-#UlLw5EAsX7l{&1527sPx zN{9MgG1&k-nH2!25&kUy_uTp_@7^kCmPj>Ze9_%pRI?eZF(0eHNfW;}hrNCf z3|e5xCGRaA4j7Q;(440YvM12NYyFw|V&91V>nnYb?_)=3LuroPS{XTS{mLLi^#Mo+ zZ0;!D!j4s1X^uLM1zad#wvlGroIT^|DzM2kk@raz@=RM6K@-r(Oe)0sJ0B@^5Pm@! z0^=2ESw*OM=;DJ=s^T<$y%iL+|T5%rC3RvRpPGX z!|xSEu|bPrKK-a$NbrC!H8c$qz&Ts%3I!7tpvbS%-yt?XKr#6?OpG-l^YLj8ww@gf zhYd*f8*mOlomg{X{3_44U)B=MLhpyXF*YQaPYD1tuTT*c`Vry8E;)SJVspNJ(k&>C zf%k>EKI%Na{S`*Ie87KKhSK^^1N*N?NDXcngr)~{+R_UP)mC)xSp1dmWI&Pm=e+Kc z2JSNx!4_@sbwsbKhM;eG-C$yStLr>6Pk{x$4upVtc#_c(REh#8mJHCPg^2~Iw)7g* zZw(k79m@j@mF%Za-Rh4W)3JE^Ng>2Mh)g;@%LV*uPVHKt6^$ zA$tg;)ETdKmOIuhotKHL8bTMRhdDKs!*G7M(({{;E+7P|tST33 z$|}8K+63?`0oCB_=5}D(>3ea_Lu)ZLL5*C;@NX;xXYg0jzA-};R#q!7QBjEjMDgjQ z?$Mx3NN+*Y2_*PSMAM!zRC?v`15`Esv@Wm_@7)Lt^?>a2j?0pI*;P?ZS(Z`)O2^sZ&uiKjeSgOP{OBsDqy&TyJ8-nwe+lah1jM9 zx&leHK({OsC8QkY7f|$=_Ug8A(fVkGxWaBR-;V;x>UOj*Br;G9Xkhn`o%t!~) zcIh}lJ5C4~J$W!=hlI(QNYbHIR&e#`W0Nmwt1<1*%Lu-8YoV#!1AiPFvFV3R@(qUI zCgLwn$^F;#Wy8}3onHHfA6cgPPX*?pH2(SYtABlfP-sAMy6sHoyzh2$K>7&$ahfJ)6J&rrf$P1+((Of8w0`oy zDZGX8xyIu-F@Qg+B^w?PZ1i+`?^@oi5aEgRXAgdLo0p{$^KOnQz%yJFcf;Tu)EzMU zdKYXTw;asJNEnTvXWC=3f7@fOeBP$*&wBC`9C#ae$7LIlw69EMs@%PiOi_E-RT zAvwRP{MNu(k4Pb@&*3sI0*tX@tE0!_J@a}~Cf@EIg5SoQjs3Qi)sLU_dD?JnZrptW zYPbob8TKuL3;7feFmRUJX|{q2>e<%wd+orC3{eB4;Z3Tiq(l zi}!pYLmE)PD%S$~J>3kLQ_Xe}QQn-B`Z(Mg0$TZ`8lZw{ZDZiunKL=i39is!L<;4D;2YN2T#9KvTiERW7*PtDhK89#uodSmle^C zyY|tZj{3%cJ{`)zH}798HEtoB^_yFtcWe24-IRlCD1)rd98!!~Jo9GQb{~7S0Ww$& zCi)Dop5UE0&*TimN^X^Es(Q6N6LcU9WWhw9ok3DvH)ksR-PklzoF9Kyp6r;RTCIwX z0{`)7AQi(wZ-4^pV0;^IhiL@U6;N z^0u*t##sF>aRU{5fkXoksez2m!q?C(B?sU%=DoPrr{WWVdLgE(;k;sSi=;F0&nZ?= zrtH~0748ibHSB18O*T!iN5h>&bI36)d_sxZ|L;5rvDeexvivYYZ!Rag%@zXBkyV^t z$6n^hl2)$quS(Y)NYwt~i`*?)_w9W}05|{~Nvu`BtI|upV|E?+a5rRs^1K%tt#}6z87)uEfd*Kq6 z4CG}YPj{JXB*0<>AzeJR6Y#kAn7!lJo{@kXl)d>Zj=zz2k^7GO;Ja}W46oL>1zNCP zcJ+@9>F)zxX}gloV+l)~{Alpy>{8f?%F8H`#rh!I8oD zJz%B{5mtGmh+x<%@RAvvJxk=@j;p03e9Qy|3T<}{gKTx@A40=@AW=p3FvRDn5tev@ zViiwyye?B0C_Zq!Jm&CTCXd&z3Q*c%w)I$#IA9W-nLY+H3XH0^GV%g$zl0`OQY7yAL~7W9rV z128DnZ1=$AfVAQAVmOX^=OdlixMm+p<&m=@z|m7K^_FK-Rw_iJ`XU}>+8%0oB2u?s z#U!Q5Cr6GA5theLnbV;@R)FiJPjaylhcDvYt3iKR;Znum7@YQ>&npuhboehx7uuiH$LY*KQo9q7MPaJ z@5=6?JYMuGMQ>ENV46Ad6SirGBnne`y)$biX;^!yg}!|P_!WjQWcLl1lF8eTP^{$w zFzuyB0D~i%eAGE?_K>T2pk`(-un9uNhOWf!m&~IOKAuJ?eKkBoX&+qV+Zmp~6#N!e zgfZ6SHS{O9M4iOsnJGqt0bcJ~d4^rTW{)wu0NB08*ZAsB2rl6O=DrjjjUr8CJ9c(y z8sbvbf_kriKyutU_qEKG&M#cTq8SH@_OiL-=N+HW>9R3QdKb(TP*`U#NT>1gr=?6?_4LSL%+76 z66{!ly-ns z;?O5rjzw&5u4%_hIUt||zi@nR1-9@Ovu=v1({2a#qW6}5nHdk?o5Hu-j4k@e4+0mf z*D9h{t9={g4KNSSrrZwazV?;<-KyTj7b)G(ZWchZx-TL&fN#A5Q3U&7;YV2PcN?Y0 z{uMls@XxExrCP902#hvVD%>f+nKgk_1Q3%@F0%M-}ulKcpSp0K=vt;1oF#hWi7u?eWKM7;%~moMCz2&rVz zf`&O#KoJ+cQp28{h%bSS?r1L#lTK>eexR3R8^F)#^4_~ZuzG=kP2L3jz_fe%m{27> zb4|#opP0yiyg_(Wd&hoUIh>W@5y4O4Laj}C7>(`*G?VnZUI0yy+p_bi8d=R}tzk$| zS(La!g3`;~MifIC101Y}GiJVwm4`s6Q{RvVRIxdW2D@rQr}Qb_bCulf5|m5B|J89! zU0tO{0;a?yx3*#FRD9IM&*?s3cu=D znOBa$;$D;Z+dSNq)#9vSVOUlp9_&7O z=M4gFyTrAIwlxdaXDqgW3*ML5=OlrrI{Ae^zs@9u0&LVVBGi!?2aWweTJr8Su~;WH zcz;OE?ao@xfQDu3=$GxL2yI>dC`Ueeu^brFB)AH~m2c>`8@6R7pf?05fCAw0J zBt@z!Y!eB&dzAowN6L8 zY5d8wLFg_5p!dDW0FCM(wPSjx3k$oG?{YnZmyawWa+~q;sE`A`^ggjF4yqXJ= zHMf7c+qCZ|@jzA{E_fz-T1sWxYxA<6MX&Jy3-=C;^j^FK>Th(xQJVfMhu5(gK00xGev*{&R>77 znbsPCQBU$!@<7FVV*UaFtq*Pt{;uszDv)I=671X3wxSn9tuQ6r94iN zAYUV0X`%PRyYCCqFiHBU^t#>BMS%ChxbAmKpAd%;$Y6Eue3hT>;_SDN*vz!^Hi!FQ z+yT2DI1<-m8Ude}`!O>gh&>AM)UQIh>9%6QuFBE+g8G4xwbw~HAgd1a zx8M6ulU(`5fL(}cobNmOxeOTmYWyn0Nqe7k3n2AzAu5g&ivj-N;l0#SOiw|vgwqY5 z=r<>wR=$9^S)#-Z!Hi@4ww6Jijr7rO!A1cp8R&q4DS4ewPmM>x?f%4B`5`238x>hv zABJUr6Gdfcc&}R|66J>z2nJqmbX3^}?ZPX&_D>jg{+d2VqMRl%BRQ}N-L4r)K+^&+ zr5Ip`1Cp|h&z=}xU){8uTLJ>-9bK2rvCw5ogzNvS0E1(g{`l_EysY3I&g}dL-u%=| zxVv37`lZM*%6rL_`z2(+8t0^7WdG*)^ERM#U0)-&WS4d zX!6(yp||f!XfA!HqM17ZVXu@Kn>paz1m_Y)pc~nLCYUkDvb@}!;RFEkaLn~ohae8p zZSmSJ3{VqBm!=|`7E4bj1JnFc=ZSbKqqhVj?d=Fyghou5Ni-6QJ^IF%IH!(jiz()h zh;J%8jZcQHeOp&8ALqQ|nXaW$xqgqfr%$wNDtu!}7r?3BkL+#Tq%64R^1l6xffn}3 z_P%@qqlU2!ytdyTbvszhPgU z|4;+E#p5dhLTKJe+{m@i6r}s5ekFz$+HN>{hVtfq`4NW`m0K z=R-et8rukaj7Cr!{m@qQlk8T0x=cJCZLZ-k1PfISP1|PQic{)H-MGQ4a$l0RslXRpXg8L}nFr6_c&BMF z&H&H{z}+TK;#_?Q`UxmH2lGR65$BJ4UM z*o$uf4iaTk4rxQDg>n4fMm@fclW6rVWJ^o0~beoKFl!2 zZ&}gzdQliasbl^HW&~zd>ID%^UeEUiGLPeJ)CQOfmA+3FF|r5J#%wBD&pi5>3>0WEBl zWQz<3%=MSN6cgT7>lNJiv*}A)iimVc_pVa&<%%scB~9@ zbrdrq4oZFDJ`)OF6U72x@98mGs?oCcw2=cXmOon;`hHFR$NY&_#>8JNW*FnUcK~*w zMY+?F1PaS??UNe8djO`rooa`a{Mz)JkNjOG{AIf1{-%FTEi!B9U%&ao{0sf_-hIAv zna2my(f_w4uN%_1yLcSc6=q;Gs&TQ1TuPNvEM$uchXnUnxE#iT_6ZZigb=ug$=|BUyJeOwpT`9P}!n`JD z7O`DHc%GITUS7net3Y?by3dK8+FzeC_Lo5z4C;ri24Ojno^quo~45wF~c z!D{|uztj@r`g6L0{1#ICX9zsFoT1h)%r|vZ%_p1qpDn0JjQtq!m^DZ70(~lguN9AF z8#54Ffr-As>KG+tMz6Zk3cm>8`MUZOui*&;_dTl(xA?#6<;3(*AD6z>_Q@qN#vknb z`$!0z#&ajUa1zPKvi|-KEON02EVOynCRxy@1@>CHVUTUDshL&!78HXYZvTq_XUSbYoral3X}E-w6Qs+WTUcxq%B}C@l^i@y`_6 zUA}$Zn4b7VY7bd`ri0+YmP>7{?>)pH?pgnFM zB;-@XgAY`z%yLbrT>uP7+TQ_(=O=>YdupSxEwrnv$?iSfa7Ap-d+BBhCC^_@nuNVx z1G~B-aM)73jj+56TZT@pjG*VyE7DFzQXvL3->Py8x zaP6LZLsv_4nesKB-W6WGEuEh&jsSNfHBnBe5sY{laQQO3i7NuffsLw3G^z{L#;P@i zGyD0A%R0pa5^UwaYK$xwAYA8IAuW0xYtc;2Q>&A(o@k7GoYV?Tr?M~dTO$YqPYtnN zr9Q~-7&9D-bOR`OmR0vquq&^&$2=%P4|rU2Rd7Vl(c#@q=c+p(omM7}2Jiksu8$(V zS*#ik>N!>+%c*$RvF*(z@a^a7C4YOKc!GMQr2=AO6>sAtfQu6=l z1AGm~nT#=uQR;y5g|j6c1Kh9)s*6P!uS?_&hYVVElKd6~cougzf)41z$FPh`%p-k> z(N2@u376L9dc8X>Fs3BbqySa6?<_nORNc8+zsnEmepBDGSVu`qA@%S=`)utWL8Ird z`X;{~E(YL%hvFvJ$d8l7J|lEMNsX7Xxrq=*-9(`_UR}#^ezs2(ayh zk3GQJx>DdWbGB`77lQ@MGD9h-uSam+8_YBd)hN*^vdQmp&*=E2#e+Qa7DBYQsTV;3 z_5jf7u)II)Apx3AWs7sc6XDoB%HIq(t#Xd*G7sRa|Dp(`sPHBU5VslV=9F3ym0yMg z*ZXuB$2Wjb^dlb|=6J_}W;jCwjR0HPQXUe_0_$Z`T+0VF5L3*_bM02?{fR zJ3@PWYv9FVT$2s`Bd|O2oH|fgoMPf*m89F2#^oCasn_yZkV_tkjp)0S0Ux5c`- z`Y+uX{_DAryu}-%S+>$X| zqD|8>oEG8K-_Mb|apMi1>m12A>_s?59x4YKxYp>;fM9-!70I>$lFcvkk6h(*j8R)M zoj^JL=`Pk!o0e|D$Yq}uy%j9Nvn0yht>7g&7Xp#gr2F~pASH+)ad%b|;p;}PE7|T2 z74c`6?r7k!v8H>0#u58WU#a8FD#&gJV&R|K4)p&|B|o>>p@0nj`Tupgh*;HasHNQ@ zAuf9AsW86RM^7r{^HC3ma7@#CSK&`&N97c&T*T_=<+1ymHhoO6*|oaN9b}+C{4{uq zXFM^u0AKi(`jJTjs{9EQ@F`^qRAC4S;en|aSxgl)ZCwU{lO zVEeYVutf;3IOBW^CS;;trPQ2@O#yB09WiaMT?;N6Tyz|8E@2}$=m83Ryfc_6)V<{H zMkp}z31q@IivJ=_GwfeEQl?nDBDYW^7-;jmv8B7IuD0F*#Ovov(mH=!*QLUj{r;3w zDzsX^TF1!mdtxHnLJy6Nt)?Jfs+1)v3j=}m+tr(zcA6VptHx!ogYE;Ny8&niDYa+O zjm!twpYT^psk0{a_?sey(TnwORsc8JXaE3#yM{`UBD-YFvRE|jq{*Pb941~FHIlLi z&mYrFJFg@+G2X%a1?HdUR(ZJGbSYYv-J9hXZQC17+<{?IP?_c+G|v2cu679@CbUYP zS)LgvLuG0=aT;;5OLGSke@1Fc8|XUl2_eU?Q<>A18`1Bz2rqIk21nc9jMT8j?_4eb z4sqw`oxXm>}y{5Bq{R3lxO+m+bZW{d+ zjX-8%=b;$3k1*Xp9YZ2Kd?w16JvbKgd&?YGmcZ_oM?HIlpU=t8$yXF~p~eSoY9Kd@ zPFwARX;xbT)lb8~l49t`2N`|KQugCF!oC2!z&irF6#Kh1ZoCs958);OWR&;S#OU+G z5whB;h4P;d%Uc=H6(>I%y7=ZN23TF|PWE7=JvA^P()L?QW5fCFYOvf_<>cA7Yk@Zu zBj}>E4hk^y-luwcerVHQ!DuI3dMmC5?ePz=1afHJP&Eh3@MV0!baueLGk-{s3^3XZ zLii{Ooa!!SNOdr!-w}^2!17ey`{SVBz8VY*()0-Ai+=P% z@FsqNix5jbZI8e3$<8AxGXbk6?cvm{M)Ph2C1y3YXLUqV%L(kiE2QMJJJHJgF}OE( z?%#~YP*oLk7}}n$5U1>aqVGWg`rckL`Y4>WI-JV`142M!k8q z*oReIfa1ZDo59QHA)Y#7ddRo8mPg9J%y1V#Gfq96D6*xCQQ>vSO07Oplg)CSpYer* z+8M>13O@+w$@n1q;v{B$Hr@fe#Ox#2uR*!ZsTi;eYBr}8L4Tu)Kj3*KU$RbJJj&<~ z=t4vgNUKiWTO}YQQJP56kDBfFV~7?sv)c*1|~xKb8~K4qnCW`wyIu|PklZ*^dZvs z*SjR@<8{@_fx(Fs+zIbb<1_w5IraSa@HLIl^rR>mHam;5mo_+ic50w-2u~e%xsU}* z@nx3tbyQ$=SnfOJ!3@*mxg!B-(HGs$b8}u5?3tw8k?uf)CX{c&QGeC(B0~HVg{Apq zH0cQ+zA)N2JSVgW83i9>SQ_yQ{(wIY(S*+@C{L(hnAY7P7{~>naRe3b(7KR$T^9l7 zltu)Om;qdlaAeH$6bB8dYPBm8PP?_p7{A&J0COUDx&Gl85)gTXF{Z#BG;`DIQ0}s; zDzL&AX@-}nLo+8JST^(cO<=&@X{`py%NDcnpO9%ZGdR_?D-HKy|0 z*V`@v0oX2{4AmQWB0HZp)?hj{s4w@PucD5oN3E7BdU|^0#U;OK?0AV_HP2zBuEo@T zHXVwMUd4}BL=^c_^@L?MIf4qZHuTgAZR<7K#B1Jn^()bM>!z*SQ_A3Mt8c#!AXw1D z$;W#_0qyhY-a$=}jG*SlW=S*1bMbm=pVw~gpp=uG1dbELFQdzOIP&;Tk~nq%X9x5ziBH@~L2J9jsORrL#0{)@&x=1#Be(le==+Zg}ZKYLbQnjv8Q zOtuV9@89Xb0J9lzabBaJKBj);Z@B7z1yF1hKdQs3z#>`|O$*Ah$!>o`26=t7T+QDV`A+gR|NPP|WpCNn8f~cGO`~=&8!~29W;tQnh)7D#oce5^eoufI~JPe|TF4 zVC>me0?096kP?d3kfOlMP?XoFU@yoSj{!Os^I}(#5@QCpPX;%W`>{w7pGjV+2Ihc> zXB`tT3e7Dk@iM1`*=yiJbTq)FV5*&hK>a|&<^{`*nAy-4;s1+3FA3*>1h`%L@| zZ1WxD;r0KHLnEEKso6buu=|!D(miH^$6304e|?KN`{oRdcxR!0smvDG?e!Yte~gor zn-7Pr3Xf!0AzUg?w^(zzykhP+K(ER&BNwodh!Sxn+F|P5x*H0e?spQRS{mQ9QaIW|Fgl- z?G>ZqtWPL}K4>TwS{PeAxT((62kXb97LD>_fR(ZgkQv%|bB(3l7flzz+V&&(g3bVH zLTHG-V02SJM=9dcL!-0;4z&dZ4IZN!G&sHt)~1*CvC-fwf_EKQcc39k67%PE1qHYp zEX;XXyv6;1u4WURJ5g}ia|@#T63Eo1vHhM0<-27U24d*efJ{Et+Mz(gB~a21o;zjX zV`wfKRNj*M6FL&Z7)tPE9Z5wz8?ax_#SUJ-lw7Cp%6S1G zMf2o_(nvnX>vLRQsVWNtdU%_KpqpYqcyn{@HWOdkn{5PCf@W?YOk$P@R{BvuSVpji z>h7(9Z0h~m6EMq}=&Y7~(>-4v)c7&I083Bd(j!%A5N*EwTnkg9vcU`T=|R)Bs&8 z)BRb+5`3Y(&03Z)VY{`USb+kn{pQ2CD1Wu`#xgGfEkJl1bAQ?4m}G@)X81~ zaItuRn25`=<*U{ARF{;fw7tU);*ejy4l~K+-PV1o9nV6?5uN}0lB`M9{H__FA_Ci0 zV5s~1M)sg1lkvXP>X~rxBux?&3j0C*#S4-T9*T9xYR+DdO0UfrHnfrBMPfzJ`|3ga zx_&>V7Vd=4dwH+}nO2g;JbydIB+Kw_I)NV3g*2Mn-NI~W6^`}*#r}Qd?HYOkajJS@ zBriU~p98N@D6;w*_md9Xrd)VN&VSS+y8`D42nOgrn|Fh~4XZvD`91P2Otv3-C8@vJGQG0JW%^b@fiE zfFgXBIqN_WRY3b6%4mDJSz=naactQaIgO2Cc) zm=2XVn+#?z6j!G0_y6fcvui3u+X`O0WG_%&;{Ga>THK$}syF%D3eqY}0;umip=yQ~ z1EgHT;^788Z4+}Fo9QckaGIioiI=kKEo9bZd9JYULx4q7)$s;Gn#+nF^Alf77yW)c zr7KB7m=>Y?ss44t`4V2+6EvEX*dEV{%wvCEUw!Ax5AuJjE{r%pwld3uJLry$LbI%w z5?VErh_w>-aE2YX{lp-chVWD9EFjZ<^iF7`YMUCnRkVD6rW4cxj2~yY;X$F)l0XV~ zj$jPypayD<>wz5NMV&sRwG^L$B+StNXBMDKnA69e3k*|`@W%jthhEquKV_a|H*la*HS9x>oDmOLS6rb0uS$EeZ!SKn% zz1(axjlAaruwL%y3k2s?9h3Aj6acn^uzegg|I2FzaVuUgd8dL)I$~EPCWX-c!7Zz( z{7^}+5xPI!&vB84`{}@=N=E?hVyWxspTFc(C{j|-5)aC>vz=Mt^vy#13mh!;-AJz< z%#yBg2*j8KAo%%syEktp-3Ih+>ZM~cpU@M9!e(&J9e?jqDaxL3EzK&wP>nJGjORyG ziP<=j_s108B=p%|aLste3f&5b^YrohKswg`I_b-V2aPbec3ii^PMKcp2^-S47n7X? z(M#wGCFuQDyL3)cKGJ0hnY6Q`t8GKh2!8~8sn7?u#C&JZ)=^;KRF|?A2-D~LDM>K9 zeF5Z|nD1r$adZ~lZUSK#{y{8oTLwvRC&&&B?*8jLx0{}}=QK%SX1-UROPmWrrnuqd z^hXY%Q@n4_&$UUD-%udK_TbBOxxxZqT!`VtA2$-YLGQ&et}mXWLA6Y#SEZqubY@?~ z-AVG|Ng4TFkUSibo&oM~VRZpRY6~lfhrEwPrWd}XuI!iE)-H2F-j~*3xekW9BtmG* zg?V)0Lrq5nd4bp2kGQPF#n}yMIf!L{9asW`VYy0%=zvxi3COuiq?lm>+5I|f>$yBs82ej>-x zLn_V@E_OR1avi|MDE0&S3S}?ze)Kx?_tc^po{QsW^Mr>$Ffn^bu1vQOqII~)`#P3p zcp@tI-lGU&dXuM7%U=O(3?Qr>S;@D#jDX!44yDIurUAUu$B1-<$+Jm&6=nUddQvzV zqx#)hbG)I9B_J7Bfrj;&Mi8b?oRGZB%x(+_3`q`5X?hEv6cXD5T=ujvJ^WWsAon)~ z0ElPx!H9vJa{&a9^sNkMN-pKCcC8x_?4TqFRT}+5g47zJD>76n)46qV%LL22`BMpd z%M(%r4l?u=M4|Vzln2-$x;S3s6?U@M={y}ezHgbu<2$TE*A_b#VrCH+-yZmn7>9Kb zMS~Ugnpo##9G*l=-?UOIHBS<21FuvXY&$uiF9G4dlT< zGqG%!Ukg-@MmXLi@fqDMf9QYch0_hl6j6$%=l4k-x)Ggm$sMuNS% zXH}#VAY6@awEB=k;OESx*2~F(=SA{+{4?T(vzpAsyL}FsuIe=(LO%>qVnW2=lTJ`uOBKl9N)D@ zYV)?LZrXmDxl$pt!{ZrHqx8qk2kzl^Ewg$SlSC@xU(ZR>nLV4eBeh%`+opshhLw!GZr|cp;>dtihlkC7oyiBlCgs2=qIFaNir#bs0yhi}OolF##Q=KnfR-h< z&6i)%O^d@UzyO94?o!w?01iBrhqabW9?&!cEFL^cu)gI3BZbG{OZ2hy79^Q8P86UI z0Kez=1!k?%lFWmN@&QIh>(C^cu_bE|oM6Rn6k5Cf`znir0WHpPl!8^TY?3k=nWl`I z=kU3uZ#8v2*(mrj6DBzE|(>K z4#9k}QN;$dhVL|>f|GyWG*4f>vIg&#tP0y|R`Z5mFMk8xsk%69YafQkjR*tvsBXEh z$o>&aH3@SmeAO4t&L2XTv2I1or1YFLTm`%LMZKS*^YDKMfK_PL9O3sH<&m#{m_MWe zma&)0#&3w=cJc?X0e_~`NWVThhW%b@bxRLmXAZv-zC?pC^L(?RoDZTBszc@p$shor zFc@RGZ&I)zyA9w~KRECK)X}PKPokfT=}_KJ-c>h5FKi(E5o45{k8(BzBEoaPbklER*T?|LN&(Kn+nLsTByqQhWPRbB;i93Y zi;Hya-Df3~S&Y{v&UDbVfbwbTlP9U&BqN>0rR*D=Ofk$Yq-dr06>LAU>G=ATj^ISZ z#FUoiuoSoGRQ!|!v4_zY`(;-2S*`6*AbRKhT&_}!pA1T7^9eyhE-pw&Ncf;e zcTj<;WoPzw8h90T?^uQGImv&~wo&0hcK}<*iQHZKHWn@4t^6cK`QA0v4CM!I-|Ble z0|mrSvW-70to&~J&QtZOAzhI>Iz2)6h2$kHvrs?i8Rv8B=Wc+I9*X$^=A`MvW$?`q4s=5Z|g@Xla zxLbzHsFb*0rWyEHd;p!1ypPIVUtxo4tGLdtFfi0yLAo0ZKQhMH2)xG#i(imAe-EzE zNo2V{fNArJKNOL01G|_?BsMr|12ig>+lTKKBtAQ?brp8;jmbX8{WF~mxm&TUg3n1e ze{*qTNsGKUWae!aTgJEW61XlP&sU#7-%}(BAN$SL=hy3;N^V4J5;VR_G8B7r9h$3O zwj|&4=J36mp*8LF4#A6z&Vv?ItbpC3K&9g>KkL%0ewUiBL7^_D_?=5u`Ihk7R@rb} zY^=SGG=sHVLWVVLc4*nB#k$-8q6SR4+(aF&+3&iHja5-Uem-Qb8X)xSeUmH$klLY; zNV1ma*6YKd2kw17(N)oV5Q+{EO9w8SnwotdT-tzEtkPz`sssGB-xz;i#zi$KvA!Pd z`egec-S_7Wa!3sRH9HK%9E0~TL-p%Z61U#e(GmDdYpA)i1?LUZ3+!qz z`Bf7_(vR~#UJO&5ABcfjlz_;i{Ap#L)y7`t23qI^nA2VfLtlX17*>RnkQnXV+e2#; ze_GK}Csjib;ij|QIa0I<8w_Nee#{F&Z|10ADl*97fpy0?m`Av+FwJ||s+ zBVWtLN+3vU7{6?ELZFUNBSGpfSB=YTYsZUo?&jPy1~rmt4M6X0)R~=lIS`-h*SmFR z;jdyz#{g?3bc{5UzO(NbPdq^RA(n0)V_%o{{>U&y{HdZ+w;B&aSX;YwL_SE*KRv!_RbYa1%H5I{h=z)Pwc~{ z@h!cbzG*HluQ0<5p>onR+@M3@_Ie^fmnwmVPrI@2Q-i)4Rq)}GIYb(njxj1?KTRMQ z@c=bMV;d#JX7-7NeE*SUvvK-byjld%!&+xAnHLJnQ|aquuOBVd#r=K5?{rPQO+`GF zlMHz}lP6=Ox9Lbr0df_KV}EF7pP+gCA!qB+JBSBr_`5nZyDA2O@jHo!$}IoxHgE{- z5MuQ1BX2L(i zfO^jf70)gXhyYK>T)heS7Xy1J*h4q-Ii^opLx*`W7;~JpkQ5X0LY4tt`YsQf-ga&(lp^ zF7tS8rR&DjL%uozX!IYPljdg`&gb6jDqQEl^0yy|7U|ElRWsEK2Z)?BtRVDTE(UBUg+m&_FrwKbSG9p`j1~jry9dM&+7;ygY;ls!G%^gmV&;5;&18;(vYFe> zYq|HuY+fQJ3Ippno3vSX_O+Ga8!sfzgKZ#srUun6YM)%j(~9rMiyut|A{7u;#RD^g z$lmuw>tg37pJqSpfjIm)Q3}2H0t_^aNhVL9+t+Qj6XQ0c@=^7$45yWwUWkqQ`IOp~ z^G5M1(7EVqd|M#VLXnv>0DmZUy{{^3qo-iDnxIF4SWxMZ)yer+$q9KzA_g^WmOH|I zThpa_`f{02=Qvj9(1O=kHo)Z;A#Y@-D?h~{19VyTvFvl_`UU@PbW_A*hw4o1Zs*$i zLW(L|qANl;v;1`*U@eu@-F^quk8E)45Mf4J-u{{_ZfFV)5#ukdR@0XWQv*N*v-8m> z#T+z$V~G!#@q<_#GYJRVDw##RFT}?h6oms4x)?QN5I)i>Gayj>Vk6U0UT73(Ir3a8 zykeIeR$`UD^_~%e1#Typ+788qKad3*BaBfXnQ(8wdgL|X^O+<;Y&BA0cMbk?e<-D89AL%}9dL3o242*_6Z(TkHIchVp;`C@}co2~Wov*BErMxTj z4dQX*6rJGnE(g()-;7XGuf_!S9L&gHHp0<&;q3b(pKl#x4X6EjX9}lgu56$FZ>;71 z_eL#;lb1`?$G5tKTYuIvt~6+Ya*Fb4Uou+T`fu~O--dnm?Dw*%QchQpx~~@ROi#z` zLL_j(5|gGtutmZS06-qLUp@dbDc1$E|Dc70QY<*yD2__|2q2}zUZ_7GHpKQ!I!h;e z;Vao#Nj60sD@E*Ffm%oc4GoU=lIEyyoxEWHO;{L&5CCl;XW17dN~9qK+WQ+RQS^>C zuVEF@KCVK$$At%hY5jmB#xE%ChZwRb3KAFqxYl%_C>uJ6Z;X41k3gJVZ=e|K69-Dg zgVcQG3U|Ctur@1@);+qMY1rf0KF|WB;q_bC(anmiy(uhcGqL_yVP?>eA%fQd4bZqzY`%45w!TW?7VVLEBcRsM$cr_SVBM#OeJ#(;i3#1AT+mioe5Fg=qQcm= zf~7UT83qNC%-#^)!7fCWwYI&V3NCQyqd{fW=+Vy)=Ntd5ku&;r5I!y!gWxgVTwV=d zSLz1LNNDjf=)xP}`h@0ukw=L|SlaKTlt$k4yXK#(>^#ONF$R}!)vRT=8nyZi#Wc@r zZ*$NkgmMA9X%=4sY>{srzDVV46ZAWq${3QQ*bs`SUv@L4ik}p?8<5J6aCSXK5n3Zg-n z)B|fTQg6@{*=6Wx%E=eBe&|t4{`q!maCoow49n(>=M9i0f_g86|MN7ij;tk`4KF@% z!jH8V8#U`8O%sYJQTXn}pUMgA>={IN#Whjg>1+<+{!W4xm=$2lnVIps$*;GHz~6h` z6RP3?)^X(GX6X8Nu4nIUb3u1TQ7Gfa{Z_<4VLuC|W(u$X_!||jC7VoiYX=4vohh2PO7^z8Cg-huN`>*3J1+dk zeQ^=NA)qdEVo(n_TaVq!` zzy}x4YI9hu*}TasettR(RN3AP;FgQ-1o3G{uspR%L?aA$)JipDOW@SdL;3!ZgHbxS zCzBC_(C#`nfK6u_FoGhYkn7~vj>*|kI)N{Y9^r=_grOw9i{%K%bg#Z6bjDP5Tyvoo z7FfK{D^KZG0c0oYh0T$AWkcv60cJlo5tlWaj@_?(N)(1^ml=&zLr)8jSDYZ~Uv#CP z0oO`A@zCAXeB#xOzNP;Dh=8v=f&Q*W#GrZ0wT~(ih)Y{htG~ijWr6N(-lYqt&VdsF z<2zA0aydG^jHitU+ZRhd;;H`1?-|G?wY-5Y`*nRKzo+s8d4(kAThY~^v1lKw3CuT3 ze$1pIW*pMo-;`jj{%lGl&x!A20Q;>N7YBee?dh2HC11*qG3+y2+V!pykgrpIISIEc zJHkhp$ln-MlaJ?~XZKSacF8=yx!h{n6C_XTa~_q<9B;V|R4Y_7PT!lKE{ue&aIYUS za5`dJ2P)_w z18O61_0FEF0mV-OqD>}iV}QB5Nv|{fNr?7*Ak~okEV#4#>lzC2nT+Pg9G8kec{8`# zYB1@5?3g$-7c(=5*_QeJC%=%9`I2wJ^X-fuFAGr*x&73N7#N6V8tq-EUkLI|9Q{(Ic!N+4L9!og*YEgsUg0~HI2lR7LL5LA)7k(nA`Hs{ zO{i5a-zM~@^?rBZ>@L6C=6Ac{<0|hrkzW<7jAkS#s*Gv5PUM#_0&cHH=UBD&`dps! z^^4N}UKC_k-sIHnT(-BHENi=8u|kwZTfX8!xFtdOf%QixuSN7*{#hlbJsVpTmNot1 z(15bp`BARE%&|xr7S#`%H{8eXPx}q0LTtY(%A^aJLJH&zD;b@B^6<>h8;>4YerwlM z2hRX{Jtmh(FKyyIhzZAOem&Qz(Q|tmPmsRI)R{Mqdi?l23H@8U6-5s=+tjk`E z?R{kZ$C#QR8H=|Jh&*6Wi14E@9Rr%4*7W-)b?bLB8mG+gvkOj6KE8*-d|LFP2XW)s zRpri3xbLy0yO)j5^&*aOEBA_;*orb{gVTKbjCzlX@gtSQ<@H9~`qaE8K4x75b!yVq zKnrWj$BFUTYk2(GrQ7iEBw5i6yK!+xq=AG4rTXi~yBTQRrkDOsnl>%Rpw-STcg?jE zY|Ze)PAxWt2gHPpgOb?csCBe;yjOx(LzA)I^FeO$1OOo&r=}cj2bcLh)%(JQa0lW5 z!fPFD9-J%>()P4HYg9jAU0;fI$+LTF`K!IY-U^H6F9h;hRW9scS1122Jng)Jy|!-h zauq$)!4=#AuNIfi{vkYXc_@urQfTq?Cmw_e69#jfpw5`LU)V${aHWquy<%czeDp*T zkul=R@uunwsp8UJK{P=hsPnqPSG47;HPJV9)l<_uu0Oap>>>0G`_t)^ck5y8rI@)qnmwY@aFN@HSV<+ zmKy~D1VEH_9BKQ~U9oG%%l)#cS|E>=n3Vn67L9xdT7C4lnPVM_Ptz|L9S}9iiQ80@ zgS0Fi!tLv|;^u?>-f|(R-t+l$DxQZLx}jy5PsUmSGahKTs}ofPnFI+gSlONj&u#Jh zZokRx+BGuDeWa48o%GmoWufwLig@?Y=KZL88ev14s7Kt(Rp}%Y5ylAt>@nzsq!r@3 zDE^fv>B10$L%LkD7HiG0N${}4LsJdA1^~^21E%%>7HOJBj02v{4H8(I{(*`BM}hj5 z_Y&_vFmDDdByTiKHf2*;Is8HbebBuTn|rR^zoX|1lj4H^@m-P+lI)tJJYy1EuK>}_ zo*n^1YZUd3u}j|A7@=s|c7xi8j>acsw52+w8~6h*rwrI@z!A1z8HR)EJxzyJ(3XM9 zx(i1LJj&qiy<6XHgUn!KF}24imIJZZb{YN`^v!>rF+^(`I8+zyS;Cb0^k5G;xB znxviu@u#kSfR}Ir!<6atz$3dT*I@9t03eW}<1N)^vR?|Fqqm&a%d`(C_X!u@su!gc zUfRU;%HEv|Kec8qdDxhI7nRmPegPE6!gVYYf=?hzPmH9#aoFx0g6<}XPaw!?+x5c5 zLBL0OB3r)^=T3@azv3)|3?W6M?C6i60ld}$Smov~5<4j*Vt`=ff^PrPG94n4~bY!7~5?BiG4$3c)Ld@l`T zjE?8}HaSqVv9nUNbM&%7M3YGXA%$1|bC@dEesDu_eqoXKaDVYyM+s~QE`yF;`A{OV zpHWdr1}LR^n~Ah=IZ^B_Sk$E|Tw@2=;<8^-E5j^9pF6!JX-%`k&*2a8T&!!lf@|)r zOjD_7?e-&KMj#2JW}<6c7>a!GExsTc380*jGHxxz+S``(P~MXmWj(-OFE++vR?`ir z?0_PGD0dS`$Y{018kt`L$VCf7%MW`%Hv#|a{5c`JA*!GgH+M+3d%g^xYgVO6^@bw}2-3CU}DGxxdYBjsm6{WX;RTNc*h_A;IxPgf8!11$U2* z6xl%4*zMWTm|f-jesi(WZeV&)AMwNGfqeoDqn2pzgGKI3z+RwoqGfi(0bx7L@ZaP6 zLb&)=9=cZ9>!%+jJVVQj()ci}IsP1dnLz|t4#oYZun8cf*BXOP0u%;xhSo4p^~jb0 zRfDIxfM7tiW9jmjmnU~nYT+A+FpMyJkI$1HHb#m~Z!G$X;pglptS8?+MwWByZ4?KR z#hcD)-SBqVP}2*c^sJ8GfOFaolf`Js$PY}eRCTOZ7!aULjXs02yEIpSEpB@Og03^@ zR&0ls%kE`ej=yIurMbShm9;r;&8qjWb4F917s4 z#?!UfgAJ0C)j!b98I=p?DoWwo_~fC!9$UW#3FevEjo;_gb}QxF!HTQ87&_6dQ>O0A znOmRg^}K??waP_wOjoGUH;^}u*RlCaPMb@t!ppZBB}keq6ctA%Pd*0-cAgQ`%M%DN z_dWkW03IZBgG7IuC#3i?M3rI#v8smhB3Vh-p}O412F(#66J)wbLC4!xOf;9w2^2OZ9 zMq=?X0!Yb)CWk=Wl*Ut|n*?eYk38IvIze4{^;4ozBOc)v5G*><`rc>9cwFZJsLW{3 za0Hl?G@Vk+-OsuA^8*H6R7!tAICg`=2^{f(Si88HkWr2fUeX_1f*K?PS5+}D-f+9K zbX2(ic3y;`u_FXb)~^Z3v)pc@0&ugQV}}77eMvBZmt{R|`L@~k7lGPrTigKzkzY)r zOvPTG-P&=GJOR{)q8Uwup`QRTo?eb{L&vbPFt)>&OE^-N^d6D&L^bjt*sUzDmsLW@ z0$B^ovIA{E9tzq~xRT2qrZtAGe5SP6kjX)0z$A@;GsXiyC-hVV!@UBMidRl8o=Tgl zr6xiy{0dmyy?Y7;xmS%TBosUVm3nr1oVAvZk+M6KuX{)p!y5-}HXkB)xXMgn-oM8@ zp;1O?M`=J}kS0vJT#rU{X=&hC1yM#@~yKkx?wsT%@OuG#*qROB2?x`Q=- zOe6OK<=!JCKm7w4RiAU45aRWi7b?iRe|Eiv6jD#z<{2O>und)C+f@Kgi2%mKoaS`Z z`s0lwES^-x1&Ff!vFE{^O=M740mgG0ddMc2bIqI?I4YuhwEUjoFse zT!%u8>??v~8N64o(!*6;ZyViyFhaoG<3V~(<2BtFkETTQW;7lL;N&c6D$C ztxn7>C$|PfY8%yl4EO+>0m&m#M@y3`DEWxnDQ|1;B%sm*lI`m2$=ONpS>`l%h*91e<>n%uA|aBfVq zwcM_dt58(3yb-+tI+AWeG&sTwbt{0Kd%;MEbG5CB@NK(A=WKfiY_%x{XPmF#lSxD} z44?5~Ys;|Ay#Dd^!_e@462M-6h4iK29ykj{;=j%@-V> z`Pz+SMzwBO{AMQ`FTg-dn&LZW+I}_nOaOMF*Tvu0(v?BCcr8HqexQLCLEE~$j}8Pf z;jUpIAG^d%EQ2B?Kb>ERY)12t#&-8YzSkvPo(ZtSpjcMCCrpek|GKGxC($X7QwI=c zUWio7f3WZC$Ty~sfCYe4EbsOLC4lvIy9Njp`P0zf`hB;^wXfasRV^jO2f*Z3kz|H7 zuTD4pInzXiEg?JNSiKZfWsxoh9N!9VPks{6QL0kA#d%ZwJVIHiVi1vbV#pYIzfjJi z=ydauPx@;S*CAG~g<>29LqdaCB|_#;Dy*0hA08FpTePtNeWF1DYw>8Q$?tS7y|`L_ z32iby@cc0AH}v%7{?cJ?YSY=d(?WgHq5cxKCMmw%|T90Urf&7ppve|Zyi-u%qBDR#>|qLCE)7m`Knt?0+(&n`um-cqabAAM zN!fA^2IXN%)Ku^PP^Axlfx!;B2M`o#01XYvlX|m%B%EH={)yH7R{|c%m$_U7?2$4} zhLHpB*&S`C6+!vMwc)*V-jjpZ^4R&solI^KOj=@fSnp0RHRr9t(Ij`xJ@I#PM)&KW zgD$)47XVdOhWnLN%C)3|Nf;}I8pu{P3@8|*8b&vL?jq<1AM_W)Wd;p_x+FXSbQb$k zxT8Sq;0+*PxwC=^1*U@%iM0_rLG?uB1?WP`Yu*-K9L;yf9 ztWFC*HVwQZINkQJL1-hAX!xK#2uwJ*+89t{m)DXNP(2n7_{De=taFx++$ksxErWHpk(s;V)PF4IYZ}AaOZDcaT`)$3%?? zmj*Ep0;mTk$#Ek@nffdgU)VRouSyz`TkUL#a;M)0f*m0T=bpIM>AGGZ?@W*8764tW92x0$u7S zY-aOv$I@#^{A0m@PbwpS!&_#0+A3X!;PJ!KT{RxBE=X2o7TCfv?Da;*l-d#-5F381 z801$8m2{_)OPvQSxc(GBSZ`kKCyeJDwU8n%ZAgY#>PLsW^JJ(_gfR&=Di&ON|cJCr>AE^z)lrqqnvFHKbzJ&D2s(InN6`f$NKF(@kchPGT) zzmRU1FePp+P(h_bg@rl02fVzR$P;!+nB+blVgy^I19w>Dwv&`vIHG4?7PUJ1x{$>0Y3=M9($AB`YF8^Re`SnBD14iby5 z?Ic@+H1Pre<)te(Hf~_*Y8~di^weeml`!uh`D{Uns~K&+9dz!OKF@y0v;>??wYT) zvuoDf^)~5ZPu(RBM_vwgA8OqC*bR=+a)|pVtdG&}c(wbXFXWy)E1UwTg+!fpj4 zmzun_swDxTa7>iJO0=FtaR;cw-bm*R!Q@LsIZXF`l(>0IJ36r%=5Tl1Pe~RaAC#2- zzQb)MMFFL0-Z24*s1bZM++;auBQ4u%Y*Irsy=%vE7|J;Lwcb^Cy-c;b*#I!8XPB8= zn$j89;7jFeu(2Zhv$b%YY@ad4-y*{u-)JfV09r5v%pV;J%$!>OtH9;GMS-6(z9 z?#8vs#UMyS-ajE%XmDlkB(oZS{ei+)nNws~C0=tN>S3v96Z7hmxl0>P}P_dGFw#q`vihy-d&hxY#86T2O7wlDK>a^rvO=r-4)Km&AX)8XV0Z2 zZuWMz)3lrp*pReIAO9g)SzI!`Kz+CmD6_*-L>zE@EHV0x5YaG%P} zC>*&1{m`ZMGcowKqiGLpA!5$Xx}yN(CRnzJe)C5<`-D{RRmTEA19AlfUYfGFSuTjN2ifVln@J63 zx%o@FUumnfsw5H=JvDY3%7guAGL`d45EcW^%?gt1j9Li zO}|E}y)g##b*UJR5=D>Ves71G^b7?+cFrBtVh#zGVu>UqDqNrWT@MWal)=Bnz}(cl zk)6RT^7zY5;GrgExX;7y*UTpEJBcGXLP15vUj`9CTF|QB_m&yJwN%ZtHEbc#&eET6 z{2tRqjj&#)3dr?nAhtm@pU2T|B{>JiFUX0Xx$ud^P#ENaX5I*swag=sqlKWbxHT+N z@o|0B@4=KG2j;5y?KC0^mWo21$76acsmr9XU(=_l{+?&`yNcpy31K0T&l@MT>2?5X zV@iy4?x9H-0%eK}=rlsF@Aa>;09>!M99j!tgBzDlHpB-ytDv|sU}Yl&j-_POgUjA8 zoq@m2th*xFMo>3Zlm@kY$jEY+&w+pz0RsGa0OSXl&U#ktn@or#{}k0CtCt!uhx-;jlEI(ga9V;HPZnGJEU4iiHMj>-?LhfVTI0 z=z|A&!)tNRnnRjH*Rd#BLP{@OHK;U#zkx%C%e)jRY!ICM{6vD_X)| zcv-gDLMY+`f4|=<{&=D@(iAdh>$@oEp$GC@9(UYw zL2Tdvyj%(DN$?e{`ugVNP7Sd}2(5G^P^|6I_w$Yr<~>qetcFn7uk-Um=YBo3=SQ|J zq+L0K@uDx7nvSJ9W>bSUZ}abuaouvj#w^{VqHE~1gLB1Hf8{s)WNeB{wz94>2nPCF zfk(uWzI%vLOxzdyNs>NVFb9xk?ZuRJ7Orln!y%btfIS8?*80_7pf?k^6aa0vKcN@< zakjd+9VclJdGk#^hGM#O@yaCn`NnCY&*z?zM{3N)&#i7LIKNT~-gn~3{LMaPmt48e zn6}u;RF}!hrwA==rt)y$gv|pULW-P)aCKtsup?LN9W*@t@P+bqxj~L*-L$5vB&Hl< z{Bh1hLqvJ*Q*QxrAjO}%R#?>geV@nnJ<*2(TG-L&g-HoiwL#W)O||GJ3inL3bwLHI zp^xrsJ;)D@IFI9-%HP@Bl`o9K>nu5!Rs(SnWuc-BvZp~qksGx%FI$`i5RoB6eSa-B zHA!6*^>3tsVzL~BPNDAvsoLE2WLipGo;4Ff=-}vktC%?7(4c7{Xt6tn9WX$RQm7iD zVZgr3@4kPmE}Rf!&h#>e`?>^qwN8|#J-#M&2O%+cWAXuwe01$NQ`uV-@EtvQfVZy4 zU{I1N?Gtuimf|Wvss3$|1GYZTtH=t{kXoEfAwOx}5`2`FL9U z3q$>k%5|X@%ozfiPvWI+hv-=uthF)8HmJp+faP;azKe&YWRT;rEs%(RBb9rJN!O&G zyEAnUSoEqK2bQur2{f8=k#)4@?Z=>Q-N+PkihBmes&$QUPnkqJDKB8o1RbF5*iW$& z<7O<$vU!eFoqyA_ziPChrX%EhNzALtSLQ4%0{eR($p zc=Gmh5;==rJBE{^g7-N|Qeu@Ijr(ewl*O8X-bOX7kSumTh$I~pAcBl#M2$3fFL4&| zO@>i%whx{HIJCDIS(=kegJCp1gUa;$Q3XnJq2h<9ZOiY#K8IIlz#D{O%8O3s;5X>? zA(6t8Wd4ux?+gHzn1#YRqK(9uJ5vLH@rHUlwcae-Tr)~aPtSSKP(lTuf?tSt(fLL( zcKmchE-tmaOW6*pI;ku+=c2CVyC5)#LrqEJ!y2}Y4^15;+1OoE6Y@`wQ_Rj+GG-nl zg+CanDlUJGsk>jItCDWdURQBifiRON7deKp>dh#Nz5OjV+~hrY8ZF zLSce5EJWlOUvB`mtC&c#+Y+Gf_NfEWauSC(62U#oRt)_vKKu*3N{l;C_4gw{Nb}Nb z_wcjn#9duEscA2hpP1}(R*Y8hQ)`bHjlsLg_Z+JTMVdzL7Od9{Wh^3)ExTCuBXaxO zM0s)D-NMl;taCF;QJn#p;+)3RYvQzShK;B_igel5oeq3Ms0b?6BGhW6O9$7!Q-V+C zcOpBezQ#dS$OR3;B4y#DFd2J{U8af4ML*9$Q@ zT<_)Qmxs(Y0mBShwvRuuxTE6~NUJtQ@bv*g1h$=q#VG9v^$BytH>joUByYkH+1{?0 zVKw#kCg{oZZTs#2*n9J)#+4;b^#6&N@4)Mr7cmovwyLy8pF0!m(1)#o2D)eFb;!1C z3vA2n75MZov$Pw_*p>_!=ed_gSaOxBD(jb7x$f;WoiaD7v{Gr-@bhG2J1Pa}K zQ0ccEwfFeT7nkQ<(6J2E>qZg_3k=$VbbbyfRSdAO<`kA78JOdZyN*6Z5i-EOG{YG7m6s@!b0mEq>`e)$NT z-EOX%Zb`Sa()sAu(aFA{)CSEHa8Yy*cX(}h`1E_{NNFB^w>0Al?7iS>eKLG@E#=@~ zr05{(w9WpH6X&!yEFH+3j$^XY!_Dp)Kef8XUEOkT?~iq_e0x~_dG~zRZyz*w?~ZqR z_93V}n|n3K`PyW`D&b@SFaRy_tPqq1gJfCv8`Rb`{9%inKyZntl))!*m)?BwXS zb^ME+DMy2YABX#;5;#(T($%YU{{9-?8I@-+M4cM0*?2HpJ>|!#dfvUMZ$55r{=UE6 zE*<=>Z}0vnKlhbk?RTYL-@FGhDs4U=R{m|5oAT93_ra^fLB6!D-B%lMbl(P-65u(& zyEfh1XR8b@8vT)R_ju{L4WoPV{jPKW9fSt+7|zoC;#41~wQlq1uGE$Flc(dx_jbp2 zKtpr(`}-L?V9kyrSJ+^vLId&l}) z-FZCOHR^wBO0CZxV4kkc{l515@aCYTZeI+~o{sqM$C7cld&2gsynOKY&i?ze{_A@g zbg`$k^Q-G_TLa%T`?k?;KHSuP-2H6+yZyagZJ$*7L$$+39AxUojs5$Y{k{EeUG?kt zpnWi%hx^e@zuW4n1K@FcH<#t@(K#Q2&K3>^?se^{_w@Yed6gUWqEXqbUf!`vd*`XN zeOTK0JplL36aAPU^e%q%F3-JPcKN+FZ2b7y?YQlF_3w}RQCYueSKRX1FYEHM)jPSm zch2qKzm1*d)8j8VKyPoK1J(EUM&+Z1c6heasXl2||8`XEojsK9L6ACamxj9s@>B2R zu~xnM7c4(}wgSe4-CN)gcfY;iznAsxC-=sBeta~K&_U<%=JAxb_8zuxm}cKQzxKi1 zvH!ht)<6GuSh{x=@DVHRHvU#jwf9`|&TmJR)@BpfB3DjYm&`udEdRW2UuoChOTf){ zOmJkhep|nfuB$)!#Yycqzq~8E2mO+)IMwsJgVq&OpH+TyQvO>y?YA0cdm9`bJN?1Q zcXh9Hao_1|-r8V78=elj<{8*hGw~M__3C)D^}}w zv){kEJ|A{2-16?%J-mud>JGlG(VE#M$eqr##UyuFs)@Hi` zn7;XNzB?Lrn7rc-&qw>`ch5(6-G7jUm^X_p+E0xsK8rXkhANRlSu)~hhKKgmtupeqyymNXmyghVEm%Y2gXH~ab-#deyo4X;u;aGg!?Hp7# zhu(d!F&u4!?f!>S|ErnjpcQitukJnhaPYIG-kesq8$ZB*#JxS`qrKgSp)!=8u4?^X ze9$_q@J?qNxN+t0L+7Yo`*r`!PRPCyR-o3k5cSCAP`71+!nve1DyD{9j z)xXXTwJoN#CRt%MNF)Aj=yLb+R)$Z z5Wq_DHjhD^-K4xWea!s*98BoXXlG^qxgZ9une_WFT68Lo&&lOPRj%q&%VJyUZ?o6k zd+*2c6WjbYgqb8SC0t#E@L<*p0P+?MH^*GrEV^QbF2TjKK)(Mc-&v&r3Rvqz=ImWHm1~0Q7&~o8nde$=+N+F{XSv`&tLNPfgQFDbF*UbdeI5e0 zYpde>zsZL1-+9~KeO){8SK-8x;Fy>N$vzHl*Rwa%<-4VeuccMlo0zFurRD+Q3&A?B zHUP-?Zs#HYZ#%vx+x7kOz710csUEDN%}U7Qpq*>8GfK|iyYT2ceQUIQ_I6LXGdwc> zTh54KI4^cOd^(Q|*EH|x0$FpA+izv9&7GCj0-ai&YXbNP)($9L8rM0C*N4bd%TEQnGnxBO#)hl7=>yI}oOTHGaZnJYh|`oKsCP=xuQw4QuPBl}6)Q!utq4_EwVbF{VRF;=FCa>WD{`=Rd@Jd+eKxWhTjYa$R-a&LSA5XDV!9EHsvk*&XmduANc0g)xURwB@@P$Zs=Wfs+r62_2lOb(y-fsF3{UzKX z-wGG;@K-i;?Z0(cf5mH?Kf|LRpWZI6|8jJ+i+g&D->k(c7@2syC*ACO{k%VYctv}3 zUYW`V-ENz^VZ3-8ojJ5<@bzr-cHf{)ot55evrMb_hZKXMJH{UumfA8*wbeGs;xf^os4&FF6opJLP z+|F|Lgt8+(`2f5@_MABH>Q9X=ZOhD11>#yddw0LDZYAfp3*oNvc|YaNB8Y06pYN== z9o`-t+uc75a(ea>@Za5)H5#v2mHxfSw^{R0jo*|opTqBNY`%Z+SUJ!5JU>)CySe^R zW;Zth8nah%{-1xkf?Hsdh7i%wCM8h-x!c`W`jBHD{@=TYl)m2Y@3-+kJ-lPbM6lR* zcDJ_)BObQ|_`~E@(QXi&S2-(T@e0~3K7CjSy!ym9Uv~ZO_ulrc z0L87{@BjS2R==AXZ|59$Ep1z_((dya^?z+uEnRoBubzFK$ZQfk<=RczZq6{`j(LB- z4zm555?`%+_`WxtT2_l>W?)`Q$td+(x9GZpEQdinJ5G-c(+&;WW24UEYslt1nG)X& zRwxkbUTmM5dAZjc8STT;aqVKDGVdva+;)~rMiBtmT@m->tol09>hW9*0E({A0xR?cRBxOOIN$TED7F!D?Q1xrqHrkFDCgV7n?Okd^!W!DGdF<$;= z1D(wToE#pefWg~l(CcUsAyxk8%@GJwLmpL;l1s1N)|~@_4-#VYS`8At9Jl^c_ArNO z{vSN$?QwUo-mZ0I;L2rG^Fqs%JnD|_$JfU5`D2+%+q=W2t5?!@rH33Y(CC#Kj$1nd z)Y-3KZ(Yc1uWdc!`EcI_2s)<=Aia5#cZhG=kH@M0q=H<_ZZI#05otbzHrO?E#0R#Uji8T2j`hi?o-wqbmDtLto9a z)~PpgB@ioc2>*sk;PnBTui(S#d^z%Q)Ax5r#mt-gWC9}D9nLeZ&WC%%Zf)2PZb_$t zoxhX)w{``)sgpHLb}_rZ%6H|UI}d*ykH)Mq(c8}ZN_V{Y6P4Bci0Hxz~5 z>S(wZ{+bI^^t3rtWwsjR5nh2QYL`u5^Gt|0M7q8oBeC*;?x}{$j=f8+-jKDhJC2Wz zGhsF8x98gTAINrS+{AKwwg7ra_ZFi8F#S{Afunro96Cz&$uy z2w~32)j*`WV!({ai;^JJ2{bVt`C}^j;Fx%>1dxF1=5^)vI+VI6m`=+NtK7qk?Pag- z`9;-zgV7!oJsu~R!e!n4e12gGuW4UYid3e=OCvK%(;LHj)!ghVsP{|ts+TXe_1)#^ zt}%3h7j?2Z&<7cdgVj)HD#($S0x8ZPy2J%TxC2?JgSdJTgVjaqhtQf+OJoBX>NE{#?&J*Mb|B0lGY zLH7}m963bz+dPHYy9CQ?HS#y>Y%aIXYx!NxP*v%)vwSdm(8xJrm;94u*6kTR#j8(A zO6D0H7lnF>9(_ok0BLu0jiFQYmex^4gmpJA$u|Up{#dYDGB{She$Wk^W9YC1aI#<) z#6ZEWt5`GuoTx}>w;H-lzu=h8L>hpOFoy2|=@YF?45{1uB9#8x?(McNVuROxZ#dWA zuDb^uo7r|X?*EW0->b&R4VX;BiXBn~==O@L99V7`V6S)NJWy3^#V6<|EvT{A*s{cYg$JxTW z{UUbq$;PJ$g;yJBWItto|Ew6K|1FY^`mt{kmUA>7>(F-v@9A@3^1F?o%5nm%1>W3r7u~=O8sl3zNJV*X<6tObM}ph5yd-xu@WKZ1P*^4o@4V4-MVU>^9E z(+tH>pE(tCzW$Ka1*L!pDF1DoC%K1Jpv!=N9h5Tlj@&gI9Rsu>!PnhMrSb!6!a%C- zBnqJegyRw>%oyUvF{rctS6olsdyL=HOzh#Wt_l0C!804-&Du0=HJ| zn&CuFEO9G0Jn@`008r{Ls?X4tW`X45mAQWNm5C%0`UnG ztiz@Z2s_DBtvq9lqWOnXS>wX1kT(S9vC=_A(}c>mz}5+5Z} z-eB*A}(Iq%Ic>Ft3dbqMf!}$IX3uaBoVwa1lESS;r^O6m26Uuf9G0Bpc%Ad6bGy*!*KWg zC`oODtFAblVft@N1><`|U?eMAv%+Y@wqZ^~+_OPR0IL_Wafd^fce{V+#CO!hqE_l! z9>Ti_4!4RgG*bz%P)m+_pmk>;SQ)9=SnBpTiW+DQ(CB==NJRT5q;tVGzh#KRHKX7{ zAi(LiFC-BD!j7P6zoH(4-1k2~5iBcuE&hAVhIA2wZVN4~XXUeqGzQm%3A#tGXwdMc zImRH=tO4}5|U8YM0Md}3P@#cd7)GQmFraoUg z)Y5Z}X=o&V%Y+Y(8Aan16YxWb5Mv|dqP-Bqg}x}aX;8aIns6Dv=G1N1xaF4j_#1_+ zGD6c&Bzf9!4mC@A8h{@wf4*VY%x_UFV^I$NNuQF+AwL=Iir%Hy92tu4)jM^fotE_b zW{`-laem#ex>1sSfXB6`({HtQwOkcv;ZV0Fq5k5M$395gr~$QeUqW(8z9hFpi${sx zh01GoEwuK;;I|4T6eX3dO+lZ=o_QI1WNu*}v}DS%iEQ z<*d~3U3s}bwOTaV@va~z67rP3pesD0jXNf~(*q`voKRc~TRPZA4{*8KC@L`|XKC^q z5;a(xa(=Pc9;vO5ClWEyBV1PP_ec78iyY#5%m2BEk??s0^w!>1sUV`~B4;1($rhbA z=*!9}qczVX<-4o+grPPau5X`*!NIllD&?_Jn)(QaZT=I~NA6y)fQew_7WriKD)H5{ z9l7{P6UXsKaHE(3uCP{SMS5Mev8>o0X6cayRSUb5qA>KHBwO1jBU|QbU{;;i`JEPm zkVT6M{QQiJ7FFB#`WzES8u}1DnW`Yf&K%&D=v)6%r zn_qeeG{8q<$U7E^#8_)n)%Pj(eXVU8Uun*(9%Y1Ffs+fO#wt^IosbYF)I+&N*I`AZ1YA8%QT z!TU)6b+8V6Jy_s0Xvh4ZVkCFZph}c~ds+}Y6ap-uXgr%!b#L(>fqNOohUKcEaR?my zF%_Krq2zfI$i>vdimW9j0z>+Qg+5zQTRx6D%BU#YybvS?eE;AX3{PkUMAyikm|!Q@ zLjulE)_Mw6Yh+dz5r z`jy6R-(6@@FH8|*Ke{EI8x&fPg$2S26&s9_`bsuOb}D`ETwM=P6Nr7DQ(3i?`X=T> z?X3+3OadtSz;V!c-YDB>r?2D;JezR>p(zPaBB7LY8iR&AF_`wZ@_(v0Zkx3}>mARN z->)d&uR+&I$cYsTL!sdVv#kI+DgQLXO4g;_jvDWUmiPV=E!@F+PI`!6x5e@R!Gf5T zQDL9p(#cF=%gS;*>%T;~_}zC*h7e%`pG_U~Rs2N_Y2#3VhTKpDTthBt)}c*$<$?I! z;bhr&x3ctob|c{g0u8^#=>tRDD%H3iFjx_pfi*GoH$4@Nks*gxRI$PE9jFm<3^Z6JAouYP=04;$6hM{gC3LoLXA2S@Nj^DpWCoSEE|*7bXc9&$fZ#pE3@GCIBukVjqtaT?&v7Y!ZW22 zQFeZN{j$K0WK zx-Jj<7>Gfme#{ypIIN7+B1>p5P>KAm;et_+Cy6PQeMVZVOoEzi1)Z;{Nx^%tz~WnC zDt+o;IAf8^ABVKi@P1lNDbH(0cR|h4k!Fk|Ad3X66{*NQD4I!o8he?JtS@-YO45iJ zEfow~jODQh1>>yrKg--Nu00CU90Kt(BVeDT0J+cD(nlNW;RjoTlk z^}LzN_8-$cz?))a_3O0L_wU*OZ$*8stGAb{%@PZXw3ap$&Hd_(e9hwE*%+8={A92n zq0Ry*d5EFx9kdilTUZob(4_*xdN1nM1rJ#_>h997%R}K9+iQXdN}mrO`(ad!Lueec z@fXf+j(_4E?1Suv zvF^j4{B;^7ux|?wiboph4NZdI=!|dv&SCuyRt*FE0f!U8sMlI#0s}CX|68#a)9=k= zFZBbN;UJ`3?62m-1R6pP)omoN;-CP^chhFkI7S!$8>EZZLj4vi8XTG+aW?YR^zPfe7;*M;c*Q|K=C|qW z;Br%x4{M&$;;iozH7gBKUI=?X{jp|GQ_YrP#!$(Yv0c{-G!)@&d`#;y20^DYL#oxN z*|A+WDjDJ3@e?is-hQ1TW*7;B{-*FC_0ab9FviX(najImv5A_4u&+Owd1%*g+aJ|f zaFHTc*wpjKlT#|sMxqDhBwuhk%xA499HN#ABm=MGmNheoRVqNMV1#U6e8UBfHZCpuCna zSjP0Py(}29qXwq6Xkg@#Lxy9|zGJ%Ba2OP0fmVzG4X4u}vqEc&#kE9ZRE|u!W40J7 zzSu?*QQiv>G|mPxZx0t$*P8tMmGG+_zX4+Z$3RYA)}o-oGCVw%38f?|-O zBXP(z(JJ?ljQj{Ay+0^rCe)JkA)fcUR9ei7^p3&Fx`{>T)L7nf_ho%X8pBbvBWvhm z1GW>5QFqy)G)*arQf?!X<)VpEDfI^`LPsV#ha(gIGEwyeOX~@_VXDz$)fnj8a5GU+ zm2c`|cABs3F&;f6@T8Vlu%+sDmWgUgYX3gOM?^<>SZI=z8i{CP0r%QL2KS28(T46OZezz?DowhG=JHKcj+h%+W~sFP&jYSDva3a5goHG~MV>{UVb*CQjv>Cx29xZ; ze*q8EC0Z$3DW+l-QnagVk{zx*F)Im?b6~v&K0FZuT~76+&?Zi@Qkr}o^x29u3)itq-L3w3lq{;ZKhLhvzwk^%VQI#aQc(i|STs4)Y1ma%S6|=I2 zPK;#~3R9zJ*4oJj*g+=FblB%*YIP@CDKRJ#O*S+ylue1)DBAKeyX=J_BZ~Wk%R+eG zHs~f=MX~>xI+rnYTbX;;l_}2p&808D6YH|WqM@W;`!WoRj(N=p+ooTQ9ouhY>z9JE z01B8CwO)rZFZE|2RRjY*M1lG z&blPW#2{?yj342gzw&sXT!QmaD;q6-Iczp*^1B4DGKDnNsYHI1tdnZ!fU}Ff^XVWv zg?WfMaWOe1Z^TOzhqr~s&eBUsT`ag%LBK?{Btko?L$^3W`%ec>;i2$AQU>k6JMt@| z{e4(q3G|JTjHTnBOqRfX(XuHL6+^`kfjeBZTR~9?bnYrNxw2lqMl7<@py-g2Dbtr| z;ok&XkB(KDyWGnUsg(B;FR#K>p z5}itv<5VXTxv?`emC{DiiQ08GNq}-+%`%lU%VHxlO*)CE;D6iw9d`nKQP*i(PVeu= zyNE?hDsd!>H6A!CH>vZ3MJ+9o52sEvbY^BDe}}ikPZute%*jGIk_Ig@6=#5rV?0JF zLMg(Kt0Io`lS#DYS1$FT4XKh5Q3FqCVFCsUwH8(rUip`FE)3E?%qh;rk~{=KRBbFg zCeNizEkW~7Qde@!1WhA(fn|5{VEn-3gW@+XbyQ*z7Il;(OV@9)b)26cv@=b7$OBf5 zFD?>6&;^L*0fy0GZgk$)QYXs3RGW=%CUpAk zPYYT^Bhf2Rh8+I4LjM*viYb{m!)b z{E53C$cqWm^p+9gaG#EH+%d*mM$~l69m+L`K6Yz6u@Dv2gvaS?S)gQ^ zmP9`xEP|0GkHXr*JPimm{58Jj{N`5bxaqo)Ix1_yd`CC~k46SDO9v4JhXfuO$cW@F z5Ofeho(Mgl_)L!TksIxb3D!EWzDBHb!lDq1?CY#EWi zi}H{aEFG#Sq$;i21xJUTmPNwp$C8L+oZ9dwp2#Nk3LhmM2=U{*{EeW>&O*f^wlGm7`M+sN%#mdf z9V6uhWG~HD$tSr%l$nMbe1W<`vtC+EZE##vtQiJI?x-qSG*;%D=-;U5>W>l_hT>`y6&t!hy)EKH#s+b z#*cm(NUtEGBjWVbKja2^c!w2tQG*QjvC*mOqEhUCva> ziGRyR*Dx_N(Oh;TCSIfrJQWLLAYr{r7$&@PK3Q~SZpZ>EwesHB= ziD)Gq=SW=0Rxr~p-x%sRfiWd&WVJ?(vwL?OBlCS{6-uf#R3iPt4^l@`jWFP}XktjQ zG>3gb%Fg1xO536&3q?|FA+z?(wZ}wC2e+byGQdg&iZAUz{0jV7KSw3=p=-Q3bjBcR zk5tLgbrXweMOY&cvrclU9VE=gS`2;5q-ejo-wd0zAu^iVGb;TySyW#jr#E-oWU&RJ z>(Dx?ad|xh(=I|A)njRWFQTAJYFMP$$>YSqqJYb>03)I5Q(zm*uSTL9KT$l*Y`clT z$hrP#2v7fFjlAk=o7H#%Wzg4 z5FZ9XJ!3cA;yJ(0wx_z)<>*@ zo2SZ(QB*DeFkYrA5Qs-kHB~>V%91!gM9t~@o$*31+*B-NW$j=RZIrAoSUJVP6~R(X zAEU0QyO>T$PK&hTASEE!Ym%yw<5i7BSS2Y?(!*Hvu5Wxcl z(u9610W)xapCqUj7XUE?cV;rB{{LWyEE_G2mPKW&GWnj1u7u@LOB7FCR8=fon=>d^ zj+I?iTLJrTcZOcCg)*I(it4Eu$2Cw&Sz%TBs|;mw5|219l~NjGoy;3AuFF}-cE^MN zsRBbEdW6?NQ&f`%-lSbtiad!jsjN3OA)n`sV0P8>Sm=!LEib%2ce9oyO>b~#vhJaK zz*4*nGBMmv$hdGtQ-aYCXQM64(MOH(yacUD*E0_Q`5J_+`Dz&1+kY86@Ko*uP^CFU z2ZlvYv7}~T%E*G{GHO7GSb+y&yt3?3VkS~Fw^bSdNJz*@=<_6yeg$>3DS!q}>VeWw6Z=ZegcnNd;= zjYcRLl%Z8p(|yUO%YQ&t$cCi~GrUlO)OvM=po#f=<%FO^$EX{`_U%FEQ>3LMJj;?$ zR9(&CrKJG}QT~1X6aP|DnU*;pBg4*=xe74;Wss38B15ap*yAmghE>U^updU#Qw;IJ zJC~1YpNXqds4{bv%B+xlBQKgClbEXg^XpPgJ-aWLk;_bQAsy6Kd?$^?85yKE zE!UGkMFBn7Iw<>qM<8%0Jlj>3mBiPj(!B9@G*~H4hEJArAlWYnF6UhatLdCb!^MDt zf{6eZ?ABK2Cy^t+Wi6qvNs#%`=2_ZFt@DEM0%?W+N*6_|q-L1N(PuJ6OGHaLBUJ|u z)1V<~(UkW|FcU|Axx>pV)2wYrN=8b;k|~EqN9&Y-a>8dp?8rnxgh)$DOJ?mJ&+ci$ zFH^tQx$hT#XHVXv$uFT|m$3~2d6Ca5Y*do?h=Od0qNhS*R`~-9bXKtcGBesC0O!ks z(uLL)pz9jlk;SU5w;*dm>B0!A<4>bla0RyVJ@YT8YNQYxubZTt;5=K|p1k|KIb#0i zaq80^7Zkd7r`_|T%+O}Ob{DSm=6U9EJf)WFHU1OoA6-W=DB;3jsri&}q?u$K?QSn* z`Kt>l2;}W@NQ|ISJu+1%s!o!I3L(NL(kGf&pV!MYp&kdVEiAfoy!||2o`d2nYvRso z@1ckW3r8%8A?cQ2R)g*$>I`*&To-bUadMhJJoL<2@F4<|yG!5In!OxWpTIu>=8oaA zO+@(?hErQxE6l=DYoyaKJMC8emefpVLj&xnvj3FX4=k+n2?jWdu<#|3J%X@t86?nJ z>XtN_oR^$<-;&=YF@!^GFuCtsY}{i+ja$xxQpJ^N^7+vaX@Ld_dEE)=w$yfPIE5op z(O_^$rxP7&?-cFb(w3)UpMJFMUie7c$tsl7bn)(1RfaHDDp<1ZE;Q(MJ}|H)C?8wF zI9SY&S8WGFLB(pyhMLoHOc*iepY}rNDW2AXTBK3hcza#OrCZm2HV)TEF^wmlU?`g~ z*}337py~Vor$nJGA0K*lK_nP~laOTYA{0LCQhPz&Z=zK8RjoOQsrS zwOkUT!?5E)5M)se*2qvOe6@g`La`GX&=VL`K=Ga;y=GI+ER#$V!8JjLw-0LeV$R68 zYl=?;ZtEmlVX{_z!olfoDH)XZz~yWoHZfxxck+oWRp#Ut6Pc#jz^A^DrBLBcC@iNQ z6x_``DqxSo74!D!N(_LPUa2_m23PvC;Lv1GxQg~Z3TlF75RfX(UN^!OVfU-a6GFs7 zt$P&jk{wKR|Dwa27*-o}<4vGjQ)^&_#gW+ru-z)h0nOm#?1G?(_smKSN*zLA{c2N9 zB7+K#rt*fzg7fPUEcjw9+0*&^kVhCg|whi@RZUxIw_?#L8cV>Hg`6F^j=M21C7ZxLObgUzmh#x^J!Od1Cy8yxvi z;0157yX>U!->F48E(=!ngrY=CPJSBuE>3!b6&as@NU_2LtfQ7BG1r#gfuzT*ARllU zYLH3Lk+2TM{30NrAs!G za4C2&Gp>}S_BsmLqoehrQ)yF$Ux~i;j%&TgXCsHws@Px-ifN zm@SCuT3|A@StJEbBM$Y$##qgk5*^YhGdSoHYZwe}3p=E12e!%~|1y$|!O2Sage48H z=|2qdbBJVUMvRNDzf-c!SyVt};1+EaZ3X9)2}7xi5QWe} zciRQH^GC(P_3v%Lg2~96iZ+CXSiyM31_h3OI<$%Y>I0DMLetM`7X^K4Bu<0|N^%Mu z|5)@n^8s;`l*uSoO?$!_+VPy|Xvq>I6_)Pk*kbMahz+8n zdD&{M9Pxp}fG5C~L>EJckqs%_rorg^UR!V=(Dp}qes8F#R*zA3(WA1yBd?&WV4yOF z@SpkxsonAj?3c+6i|gnaOaU#jS9Sm;+6n1#LA8hdY9xc85Y7!YyDHnZO@*ABljk7P zCcx}pcESE|go~sFd>`;GvQyuJ)-MqZzI$v_wjZ=M69j4dZrbwvtS|RkJZ)WO1Gug? zT{CL+V2{z??4On7hco|*k!_(jLf{VMaxUZy1@pxi- zFFx>rx(1#D(u{C|l;S@mINlWSPrV2UE?n?3Z0dtyjX1vVOON}CwEtsyr6J=CsKN2a z;qA-p!-W&>;a+*w#;t~3M>!_Ob8kLw*cLc@48e9^v2kSSRTYA8!yex&JA_tCuVSlp zUn99~&?Rrk@aB7)6;ifuV?ThxoqD?x%}sCem4BD7w!h1N6am1llVXucLQ>z%qdv8i~c>r-EXjnj+(W|8y+KcOcoNdOpnWm zDb1sSS4b2_q_9>-;JuM#sOMc;luia-t4!p+{AD67QB!qkVUe^|*eKd!sszEe#o4DIHxKKSpRF6S&@nM4R)k+n{pII{kuY2?r zRo~)yA=0l@jzX|6QtDS@48o3~$aaXbwEtaQXA)%Gv7M5ow_SU*%&vRTGg1|w_PKT| z&RICm{P42?A`cP=L-#14vhZ?aU+{QYn71Cx9uyr|Tme$&)~&Zm*Y!A|yhM|uvqL<_ zaDhjz><P)`D6i@Uf(a} zp#TyMaE3t9#8(773Qp4$k^^0e+o;pxQxeKs@w#Dchzi2?3^7k?Xir$u9imLB1aHXb z<>RS8q-3?@Tym*xs-aFdNLv_(|43cp46RsO&>8Zch-aBAjj76&8fbC;W#~v87VBF; zt%NHXvFiIq_>XGcwpea!kZECL(I3)sDX2ebni*I$Z5=>Nz>%>YQQ8}hAs^v~n7mw* zEP(saO&W`0THqVWBDwgGpCmH6>fAB;E0LM1t?7Y!7%KESguOAmG?WGUY~lWCSOe@!&N@9x?l`XB!h9hSSv$bv*IL zdL(8#uSm(}GH?ZttelZ(hxp37{=5#GD{CUd9Pz^WU$k9UfgGoygl{sZyl!3c^^|&7 z-|xE{X^;LR0^gthp8`!EyI*79X}6#d-yikgD%&6SM`MlW11i>+W5}M0vMyRo#-uBv zh>>vaAu(;s)CfqSp(2qQ2m|wrH^*Tkn!yWMdAu!!BDcdy>CUsiFPhfZlr&C9Y;?Qjc|=g^dm;^IS8iyrAJ&B zb7&-zGK#sED+M8@lX1lg-q7WAFi@*&lXUfVcmYi8-WfjS~JfXa*+ znkYN1*5BU`?F8*at)5DhPQ=lEK%6L^6u8R8I&cNFpQ_V4NR~v%Xn7>v;S<@M0oWUa z-4Bdb+X#xT$H9Q>ADZJO&<*z6wU$WLJsb{(d83((8di(MrS(ICh0MGFf&ls5cfp=5 z|HJ0&oo)wH7N!ghNHR;b-u{m_D3XW)?MM)){_t^c^M3NU@cQre=JQYN)%Nyhbu}{= z8`e`+)Z4x0@MDMcz%<6~%H(}uoD{9UUM?=SE9srfwlaEXK;jP^`3+>v`G^fZ$oj`M zixz`RoT1UA@I+aXFs1a!Ja5%Bb^3#ojz;1Uqh;fkZjG)exFwf_vJe)X$D<3PaPCzo zO+L^-Na<{RQp~tXEy#Y5gNmclsR@mv@j}N3@>9)d1sD{%1uF~jkd(cdjfoHkC7qm? zy5^y<>!ih-b5ut>Lp!Jbk3nyeW4;mnVBZ2^EQ(`&onKyztjZ7rGy5XTAcHo6A9bv_ zmQFx$G!y%8iud(bQ!|3Wz z$FP1D+cK1FaOGL^fZz@bMbQCsi6OKj@)@Z+T$nH=m)c2s;lU%~)P$eyXs}&SnB5gc zey3pv0orr0fOu#iwnTVvF#e=NMtPqy9cC$VJBeeOBLyZE3XVO_lU7n+GeU=|svrbL zu=!{uJ9a8i{_ornQS1QSI;nix60 z0v9E9rIFw95P2-5k?^#aOD+)s`42<;JZsAH-KI?r@re0}KuD=_JQ2Qk%_F!wfqN*gdb5v$QCVva=P+Ft)@!-e7EqU>9 zE|RWGs&P(;rwE4X?Ej_9?5F*$0sja;Koym2ikG6U-6apnK6xza*9j&Lj8)3#oDL%n zgTojcoMn0rB#se?{68o`iC@n2kM}nj8JgdZR2Q5`ZYE_Oz(S6tP-t7QIO0`(9 zXzFEjg>sA-aLs{_e)AaiI!^?_gD{B{J0VLHKd$G>ByvVA^#PC7E||)Ne>9a2`>{FK z?EMDy$1c7+36Lo(50_RsGCUt9r|gCPSORo{@D;{QXi#~&*55*xBn$i7}omOA*pj+ zKYGJ=pT`=RDgRG1|I8;l1vz`ne0brz*4QV1!m?K_H9mSS;r^{&O;6%DrP67Go##;=9o+T3n^BnBT~PA1B0rolc1!{s-!y+WKwvW zWBD&#+b8EqR&!JGC8`U^dXd~3Wv+1lkFWoRc4xZ!*!7Dat?c1-60EfRS`EMdp6E(@ z$}h)d4(WNcH{Afk0kaF;_Ze5WJUs4>>Yl_wKppbyUNGT@sK5U3?0O&$>SpR7L7Ucf z8@iL)^-VoO%ks{370NlFDV^6ptw*Miz$X>sfI2!apczpLVB}k)G)R4 z2SRolSdu6V3iXayiR4j`ve2dw3-}q8q=XPR%%alKf|3a>2G-Oha0Y!iV4C+GuQi`c zB_ZoTq>_5RAK7a?P-W_ec)zHUkQelTR#HyHH*(+>pCV?25gbuv?mHrx-XKSTLmU|d zM@TpeFdWTmg1bOS+z-a19#0JVPmsiuij`@H3PPl6v|Bx?>3u1MeB|DjpFDu?_O1 zus~E+PLLFmhEY~NQc{+^_Z?3|Z0ccDWpAdaWu}LRx1^Soxg}r;H59Kyiwep^GkGBz zf~=$-2MC45JpvFX`xQhJk`O_gn zg@(!!{5Gl4;}x@qY+Z5gEZ#Bj+3XjTek321|G?9bPORh!AYHJKxGw003J7kPY!B(P zj#ev#5$Fc%;ZN2cTxg^Qvmo&l_W!%+IuL#vb@J;X*e!#f@j!+qy-k%Nn0kJgaGK?sP%*PD z3+Ix*!X~$uEUA>y1tNVt{VY(eK#oA+>N>w|jJ5kce>VGGPyLh7b^!(0k;G$470_pT zmjkA&7oE9l0apb`senPHdg?-`k_3d#x0YNy`g$jCI=u@MPt3=}SI^fy2k2Sbmaobj zZTdMfW;*e_nXTBl?rD7R^|de03}Y@xV)sVQ(^B+R#BR&@Ai7DeUvur-!o6fNfA=<+ z#4w&_(@kfsSDBx5tI)03n9cZGEKi<`Nr3Lh*amL=(VO!##CP=mTh`5)p!sK7C&stonKvLNmT?!_gs|4tAi6!<+pu}N zqhD1swUOQ8Xy(?44xjQ5}XC}{p_vKn@c&v88axDG}r2HaoxACtNrA`#dEZ$KF zgWJWl(%_2>hQNJnjyM%Z+Y&v|%;mgQlZo%XwW{Del`Aj&@BTch5ez>x4VKhoszrB# z+u9+-l9%EK%*A(1z9DIFI9_?lX*QKdT4oxc_%FxT`#3xil_2yntuzV?C{+Mliok1w zD;yBQAO*XB>AnHDi2j)&;oXA=BEr|+i9f(u=vZ0@9}WX|E`g?o^JP&U{|VOY<5s*k zo%!yM#nA$U#351KR)8%-&ock>xGQfJITL<(99bVmbe>|)so*Ja7xYOqBC|_Ece|?d z?_ve4VfMX)j=Mb!D3L`0z6E3YV}r|pi$P++F_6c4D3*M~)2u{_H+tZEs{#g{tATJI zUmjx=HwIx(1{7<9myW3f5W%WfIJAarW{;08!XK;EY6@;F&h!`m;+n6Nb>ILkcCf}^ zE@336w(N0LJr$%p0NdlUnzp{d0e}PGa`X|QK0&Q{|2j&%2`3|rybs!NT!!+@4_KK& z@I>C%7QE|tqOtjkZ+U{9?MKe$b@~~@lkPY&bj%R`JUdv!5Fx{c*PwycctsAzB?x(}<7_UC~MGQy~0a1Q$mLB<_$xdpKy^NYW6levH z8^;$NmcIkymlhp_=w}lOu?{x!-JzrI@9%6{u#x;sHedGSZD?1G_sia zQEBBhPRo6Ra=&ByKkSsuYK_MvWH+~!2>$C=;d(=se?hRtV!_$SO6bKDlP1-35)KB$ z^XVgXIs)}V4$+3V?sDTL*>IRlQp93NA|Q*EK!I21BR%+eZka$6fFme>b^kLo)YM#| zB)~@q8y@_d5IXYu_pU(EhF(;d1mkH!3F@!rKbQ{yi6Rw$?YV;_IhvLT+8|RPh~l^; z3QFNTr3CT3RV7StK1tj?@|i^eEg77a09@3cIVV9yA1skr*4!fj4j`$l|1XUpa^9pD z06k!iO`hQieAW+q)VTb{OoZgyKVI5Bj94jcpo0ro{!Bv>Wx+m!-6I<7TC1IlvuwO( zM$^$?7MRh{fVjmFpTLlYhQ!ZqNb5Q<2(L?)wBqRPC53Tx_6sY($pBR{pq2^#sF+yl zGf-GaO?I~hmr~EE_*aBs)2OOogqz?XfK{y`e>g(}!ZSZ3tCSq_1t^kZ2655LseCF@na}63H|St)h+c|wsYb-PER#uwDFLnMt9jy&SyeRD7l$x$ z=ZW~33X83p;QxqaiZliIlZuQbFF7%++Y=tYG_WBtOC^e03thNsffE2m_E>ltQ<0() z@goaUlqN@UV_TL2=P^R4^`IwB2CFW}EE;3*TY(=9uH^zKDt6RXEI9uWL9Gcvflq_R zb@%~7(l86ZHmBF*L~=6FT_qH>Ra21^5THngS_6VI7@!9;;0HLKD#|)wpz9n2HFE5Z z*ACCVf|~SL0|^#62|epDUU(%1^7QZ)IofNl(Tb{rpOUc};5Ww zgCMbN@JU!zF!&Su#qWuA4m%ES*lug$=YwAIh0l~-)u+lZ z>tVPh=SX`f`Z^!|=)xLkWiTH|5QqxLDV2f$ z7_fqsERYzFO^RzJ`XBbZLAT-*zv+2U7#RTgD0e6_{%<1$-=j&g6CJwyapP2Go4uyHq)Aqd`h%izugUNcq8oo zWra{2>nn;hhB4Coqp8va7tM22h<)H9F08C77bZR0d+X5>+c-gEiQ4W8SY@_2=+a2m zBaLmbvYwUnt7GWR3uXZl_sB9x;vR{6pGDk5R+>lLvy2I>m;^pDoGz*xZrZ&@Q1R6F zMUG`X3!J}HOTuKWtFCb=PN_0k&0sEB&5#`HOl3?#(-1zx-bm}P&Q1y+-P1GeB^;M( zUWf^47)l&s1O{jl3nJg0f^`m>Y`mZ`vMv#w6{&I1un=WPW8i8`<|Xn(Ci4=Rmp+ks zNwCpeqF$VnkwiW6L|cY=Ns9}ns*EH(@~17{k4THFeyB1dL5~DI67)#W`&5D+GSNJO z9@aHUGhwnSkyWXnfEI%#GPS81_)IE9Ulfm5oPcMrM22k@9CFcgNxnnmJ4C)i9i$|%XbyXqJi+E$P)Wwt3MWPpxSFz+3Wi2Q2BHma$Z;aFu zL|#N*#gkX0S=B8@q8IVTVpBrON$Miei^!{3@`}%mL|)|QU3fy<_~1z7MdVd5c_l1D z;PgZGMzS{+NL;ZwNHs|ABDt$j3x!BQ6y7ggAqGc)MXpxN|gDm{+;W#AzQ zei0J0xWo+*n*(p6L}{*=J7I?t4K= zLuSOsXM;;y%zzhUDoz+CbMjM5F$26U4Gn%c{J?CYo4TP$hOSGh4t{d#g4M6s`{(RU z%*P@%5Too`=c2X4u(ge#U8fpmh*GiVnKEGEgKiI|%pE$RQ*C9??Pfi@yc}5>brWC9 z9K|th7T3nzkU4*QKV*CZxbWAy>tO4X3c|%D;b2rSqP8R6>cVb2%?;d(i5`oa*Gp&Q zcAcwA*BMp2u-M(%5|($JcBK)fC*Q|Z{GEBSlb7O7+;(Ts50FAo*B`eXzXLpg)W0!8 zzjBuPVo7{6@=qU|v2-?fky)+k02R0%>$+OeXI`r=V5_*4}#cu`bNX8H-bA_v8#=YuUzbW%1sIDNwgqP_ER7ALMjp{pR^!f}CC=i{tSB9kJ>l(aS< z3DzQ?5!^Ifm1*OApv8%dmKq$@Nh0_F5<%1RdQQAVpf-uCADK+DK9yJ?`S1PFBpDZ-l2ljZqB&I4h37a$vp$ukTsLpP60zPELd`L!WlO>=yWfhghaY2TlHdTA|739Y?Rm4*+lmhB~;Uy5#aqGFb#2T_({ zcC3}YSFbm-JLx(7KfOMfERveTNt)f6P{3(9T~N7Ko)RTmI9jVhiX3ha-wff?3s4mL2? zElB|xnzk<~ugCzk8pZ|$oZ(NR5%b>{W z*CMOwOh7m=KMtrL9|xk;e;ANS2^J{90wq`|Ji&tU(P2PW68TvbLzhg-vocj0pgb#d zDwq=n%vH*>V#skyV2zQh?7N8t!&b@rz^Fc59@zi{2{zhGL)hC~ZJg?gH zdOaQzQRMMrSzLleQY?wH6{n#}qcB1`LUO^18ktnIjzp9OqS$L{OHsJA#hFD=L{Ky@ z6eU7N6&35AFoV#D&}dFH(h`x2mTZz(L}JnWVv)w;+=~_`xrpSV1>_=)M+pE`E)x(D z5G?>iSk^J1Aw1*L`HUo@xrxYNi3+`{!6lNbiHhdsW(JR)pqQ$GU`=OyI^$0@n3tVq zaI`lf0J03>MJr6^#nmBTAfp@R@>PtB)gjR$I>E_0!Fk!}*i~NKI*5bMsTNZdukhJ&N78o~c5FZbCOzZo}*4K!2j&RbqMB;pc=+CsmW}F>z zOEWFW2;$od=fRAdD=$;|E8KNp^j;SW7=L^rOO36UnhDlRMKTOp-pR{5vb#v{A9GQw z?hwA;vU?AqyI!=imZeC#3dbNxF&A~$(>{i~oMUUt_R2bKp22U*wJhi~jh6s@eac)AyOj|h!QA-5gSey|a5*{vs zhnk!Z4>gP|Au=SkoR2MQcq+?7hCB)gQf085kZ?%C;Q~~MrPp#$p@EURv9l3Iq>*e$ zvfU(D$6n@)uOFKTZgvJ@l0DMj`(1lwhnO};ySZ( z9W~Y|GgSv`B(WW0JH&P}_YOL~)(3E><(0k1kpCnyF{ohFmoyOI)Ri<32IIq=M4cA& zA|(dA*eOVTnbZSLDXF0+4nu-PgbSr^->@Br86oX zn3+6WcP4z*;A@jjNJmu^+SUjD07u#8}l9dKBIE8-So_*h8NEWuxXkRtNqU zU>bW50!cA`K5?S~{(-?A%>GmW!Ul`tPsD8(JP{i+Ey&0b2FX59Oc9F`FGTp!Sh}AL z+zg3f6*=^ktz$E(+?B4gspYP`K|j$HHuDEQDkRa;7(DBGT>6IV>LhqJFu@DKGr=># zGr{wkz_YPrc#cJHD=m5lqe=?QhK7iY{*teX-T>>cLJhkQ0)ii%r6jEVGN$&iFiDHV zFvs4?1;1j8XVF^TON>h)3d9I_QH>%ND)|w z8VZ|TuWXmyCY%JtyDXH>^DR<$-onck+$4#Si{X@MrNqe89X=JoURGsIKAnMYlRHY) zZ%*Aw6?jkG87ubc_m|N>Y>Y?npX@(@;-uY+)fe-?EatV%Mp;ExBvt1E7|}cGCCpx7 zRNlq~?6t8ZOitadJRxWMBLeq2;t5}_P9@DlWfw+hV=c;+gWbiFZbgWT)3#9qEa*VT z@R9<;wnY1IJjWYBZz+hw+JY}ZPJb(uTVqHPv;GJ4pA$tRWBSQ;P8rPSaTz_SGxsE5 z64gP|lNDnE>3-80V&b&vATop6=_}7vJn7k*Cs9*&itcH$>Peel^`yP8=E;Awc%@T@ zj$?j+R%1U{9b?7`pb4Nq13;^&(0dbrRuSe1pb4Ot1JH&UyJK_NkT9tSNzf!guR1`R zD6_o@K%0DJ0h-~flL-B>MQB}*qXG=jZ;%X4GW4gAp$$yC{U#7?prL&=A)1sNA79B~ z#Dy5Qz!A@oMD!L((IiE$K1B1kf@m``2@yn-9=dQLIxeojxiAzGJ`+B#JU;7|{zmw$ zr#%ozgeE)TtiI6BBN{vhZm)scL!hx4WmMyqCaD^NvA&8mtuf?h&=Q%X)5FY{P&!Jb zwifxM{d3v1=QWG=73_MQL9+*owo$`S8)4&k`!vv#HbCOUXn;Jz;nYZbfcC(u?}5-2 z(2r)x@&)u`U|x7!9}PgN7vGN4)@tA_xMk^*ip9w>f^`Ibl2}X-9`L-Dzum&CuY7x~WWw76l(lcqfJtL=xzlCVX3+_H9+u!*3^pO{39sq>%7okTLxgfHh-! zYWPv?k^$=oGsLl47)wseC0w21wCsyuV*E3n8iRwM+gE(m`4$JdNsI;DiiEGdp+o=b zq}TI@^Kz;D0OxM%ofK2E*jEhIo$sAs`0+bwy72uM?` zGn%U0uf%1If5oCSb5XTnOpAert*YWXB2gy-!87@4e7rZK8cpEwYJvh5_9@If4p(16 zsS*b!l>vV3UcU&p;K%`3pV0wWktf7PEYBl25D$-o^>`s5lAG}4<3BT(ar~beB{7#} zY@#B8Pf;l^Zb3r^yMPJJDArFnePeC?gfn3}I`#ufgIq@_O(^~OgE<&VC##0i2#kc% zpAV%|`Hl=l^Rp_6W9`z?Dw%i$f^L?TippeuDk@QqV8*OXm4@9;ByI}-44S`!b4jH? z=sKanu`%ewZrM0++Z#J+?$!gX9ti3+w_OgHTwE{~bbGm(k(^yip4={1f<-fp*Vl}r-Y?ZE%V-rJ6zT8y46WiTBwFRD^P1Qy-VjT+z`OFS znH4v%Rdtqk#aBqRnvs%E+z{(E%e&$$q*~1&T5&^cv6w=;E7+@<(JMBDy)rbOzd9Cc&R(-<2uW7-s=qe?YRm6)e}a;N?dROMMZ zHPfADusUnQ;eJz4RD4x1W9eqI z7^f2CgN2E}t9hH%`Ix+Cq{$Z5VUxS{Hz=HA@PPJOx7p2D5t{kbpvu$Q!8Dr5*T;(0 z6WhfHeSyknFk;hZui@Cf!o%9+X2XQS!Jrk~wKKmhrrMg^Y#^@cY^G+%))4i|sWr^n zGx(s8+ybmoan7^58RKg#v)N!Psz^N0tR_!wc8m+-kS8}AY{YOMiX%dHvt!#3&)2C* z$z0Ni4bIff7>qD;)^7a$!e;4XOk%``C%5Tu9xl(+>KMa{Lqf+|#T%#z364&$tmfFx zL9_SdR{fo$qBwx0hw11tTg6vMwVJhYf^(jR$@6gE_(t)pR>$@YQvc*u{e5E0*6P?c zLHqvXR{d>aAq2nP>ew!cLxsm%^>+zlvo$-mOVIQ@xmkZ#Fd>IN1)!7N?AWeI<7+W*8 zJ4R-BT%X)-fX2p*?T!%|GPcR>25>y<%8gN)l0|7sm^FXKcE?Cf$)t!-E(+V#)M+9B zzDBCuEQtkgAUyiw%9cL$e1k8MYBg(PC}}8vt=TawN7eYmX7L81E(&L24v_A%n;qK} zcsQTjtPkd*zQXHEhA)w7Hfyip4QSS!vDq;=M=5=Bv%!Hwp0VArorYdhliLl>^L)m3 z$95W$Ca&O^A<4Aj$zhH-byjJUqMyRorb^cs zE$YZ;eTOt;WGaUdAcW|m&9ZvRSSRT%DU2?YdkFvp{H3QZo+_p;yT37HLEMrgWKUEf!xCUHX;nzzi~RRfXLyyZ1541qFyi@8X~^xpyPg zyVwGYjaV_pCpnG3nU+TJ#nhymv%f`;s-a~?w>h3gr(;CF~;#AJs_0dksf z5V@hKSso)n`(wg~JkF=Hb~#RvudNNNXp=h-=Z;hd}c-jX6x=R0&YHUrp|Thi*Yr+7~Vh ziROiAK1H-yl62^lBF_F(+Lx#MAECZra{E3FiRvIznjbsgBvB<4u_iSyxPx$Xn1&e& zVnXWe$9Yf&feMUFBe9-|#A6`%YKbOyh?x)uZa+vvj|RFRpjfvgO_6j(LLI;=7TgnK zlj0#tO}F0Y=S?|rf{pBYt&Z1*SKsK`ZBaG}`>oi$zVBn(3mx67U3*k^8g9GV8mtz@ZgHR0MZQ{~Vx=)$jusSp?;7a&wDsnDu3iSyR7^UTWD@;=$ot7O7#!%EU)qYg4`rE{oH?D_pEHzie52YRBgE zjJBo(j>%Js+n;z|&)E=3?Z%2$;EfJ`&I64v8l|IhLZ%M0sX?o{gl;H{8LY6yl*J1C zS*7r2=@u*hofk`F3C7};(D`SiuuQwSzf!wm0@*nKsb4m86pzjHL=U@N*;+ z9X;~H%B^C{nUbMP{!(YA)p@b-i=@@@32L#-I=G_YMC2NMWYJYDfmVF2MjuJ}Oa_BC zC@I!x@Q8yEo3og-a&(^-iDF-8bS4rJ9Ok%CH2I5xkCMSNv$sw9o)&&jcuvpry&!K0 za&UAA!QZodEy(_r{6$20bP& z+>W!ct*2=hnQ8}a*zmdENnFeo-1{W(xt8F_FZpwloeWI@1{?k?PQBW~>Cp6<#=c?6 zRi~ac1Hnyy8Y0^eH%vddKbKT=?OEYj*n^KY4r~Cjms3!Mdo{alhvSbR4E$d#Ed3!W zl6~yq^XbD6Qa5|ujcxXF0xIEMn}u_r$I`QE0t*M(IdIDg@&rE4k|%I=W<{AcD@rgc zaiO{`1!qO!^8a7n734Mu1HrH40j`RTu|cXTHRqm^AE0t;bEwq+cg8lxiNI>49%6F_ zDPpoSv%BD3VKul>GzyLy$LaEMII4AWjJP<43dqn|0tmX{IRC+MgrQMKD5zX0L=+OQ zK=ZA(2vNEioG}zxZ(hmam?e7WItl>197&#h{S+4P_p=4Q0!U#Z2PSdq-Bn{nFmj38L zFS5GXUFl{_(KWi!=wv!CRgYe;ng6ZVIC3by#-w{TD%NWiX~o^JB-Gc+9BS3*GawlZYOOh=)>;OizPSHt z^q{H+{Qx%w5LDsj=5EWrm4W)V=@%~`Pb*Drm_0hpS;+zwVC&38vpYz zZW`ufE%HD6^ruhOs#yP=#kLjw_FsSYy7==yANsQuYg250n(fbY7VB0g`EMF?PdTms@7Z~6vf}TXUDMj*Du+t;HKg)-~^#@0*v+TFmcA>z`!I|Gc9V`G5V{ra#*|vHj1GjK%SW^UuxO zpRV}*`(JtIa=o6nd>b2$Cr@HFgX3<%J|$Wv6ugkikM1Seakx*QU5mwC+%A2Y zO3C*cFON@0VMTkZ$j7wX37-oT$Bad8fsQtF?Wd*b13$*+$nw*@hXmH_=A+rQEb%P) zP63h2jLt~%^yM%!(ND`I2Px|y>N!qalxC4p0Np!tF@~pcc=)O4JjdJbw?7DFqOI0H z2QGNB71KnG)Nnt6i8-l}S}Cgk``mw@`|orAf6t+NQ8Qq^=WHM~M#V)H(@kgYuYQCa z)y&(X#cCGgK;^N(_m+m1*GTKa2n;6^B8-~`p|6$n)+Wq+B$lUDY>$B%V++ap< zlf~!!_hwkhHmJ3y_U(Tex8K2U$l9V!-YVcXMMKm1@(!xMu}{n(F|wkfdFe{fI|Nhn zcIYu$#k+67{Ho6Rid$Jw_Nrqa=_?!uuO7_TrX(h+^2HqILR!moTvUcIBe z5>GjQWB(5Eha-LB8yO$aX+j6(8hR#IFrAJ{Oww|X`4Xi{W%eA=U~&sqHtivms*+W%AzmG|0t> zLrTpZv2DRk z+fObkT_vIS1fbJ}py9*0uL31tuy{6<@vyBsU3fWB3=>3?RBhN{8eoF3@r`msZb**W zNhHdes85hW#Vj-T0~OCo63BeFiz8t-Lli6P^N<8*5LA4F2fAvePa_xil-tReC>l~y z0har9qwhO#`c4D-n7(5kEE|MrRqi)+KM0nVIbE2oHKA<_+lBoD0{gi`4bS)AVJYB! z1toF?CxQ$`nm_`u>+_@0`UU8a#Jbnzlq;aZhtEwuEX**j$~bInx~=FosQF;=H-JCGB6;+$*laa7AhI!mgh7;is!kNw~CVD_5rFFSp0_oL4f@n26~*KbbJmq2>_6( zAModujvht={dwR9-eDYnUS2XldK`P2CQ*{o8W4~YEbS-}862sko(@r~nGv%tkHlo%p48u1jKCKG6y zNa@7Cc`i%ahc$RX8&3gPsSK;AdorvQtR?E#US1{@+FNaqg|hjWtGiKsL7RcKBnE1^bH7(|7fFO|bnexwcYp%cwU=H%zXc#<^ncTUuN&vXK ztLWvJG3oi<29^yZ4Jkea7p#ma3O)(h&SVQs-)@#1dC=n;F8Z7HjbKU9NW^P@z)Y8n za0wK#C=GG^8|G=7hoiBj)v%}olBBw8rJueNvfq8g@NwujqGbB9uc3N4bx4qM&yc>u zqus0V=g3Rb`@0Lc`cV90q&lS^8z6dv(?hwM)v{4qcqpXUgONwn9#tv3Ry5e_yt1msfO%bp4o~2)4%rdwI?|G<#9zzhc&i`W+MIs1 zWSIeh)*q!@JbG}7C2ZuE_eG1()~{tb?qUuWCj%vJ>Xnd4wU`|tPbXY>6l4*yLa?yu$c{EqstUNL>8;Md5M*Aq`L8jB4c!#dVY;bT~h8($=U8KmWhPBlle!M+O(2J_aKUF^# zX=Li1_lX7Er~>NS%$8jOSEXe0ug+`aRvFP8ppPIoV)XSCdXUP`2X>#r8a8oof|v*m zCgH5=K`R^G%^rVLslNaff9%EltuO|}8&y`RL^az1C68V{*)T0zN1>y_Gu&vpmA1X^ zkOJ{hQTeI;C>*F=I*?z7be2~NQXeKu>pW9eI$j_9W;cP2@~T_q8M%+E30aj1z^+NT z!i->ri_u*af9fn&H_VV|&V|-k8jY40#(AF8{&3iaMIcBg8A4aPXv^v6+i^`pUE)e^ z!3lzMiRsN6t>OtnUb~_=SIK$kH#RSL>-Wu}e2B8TY3r5T!TMt>8e!%h|1wbIYmxuu zf-1m!=XTBziAERsAhCH$ErD@mGH?)qUf0tl!mLJ#@%0FbsyuLa3h6x2%@`lltC7;A zWG*;!_yB$BfPWZEWE!nF%*89tM zQ%BQQ25T;1%<4o(lXR1Zt@w7WXSSun{tZoa13B0y@Nx4@6At9i5Ax}@Ww#V0zp)Jo zHTBu;?Ux(TfQ_0d?=;9`dXyU?3F(&GaK5bwp)C()f(3mm;fa&6Tw?sdap`vs+a>N| zg#i6b++#iJh#u;~hbP}GrH|)WPs$i9@+|LkHKGeeR*sKeRmucJ5`FWM z{6L8S-h8*th2au#Gs2B!7qsVdFxnhx*0jds2nnf~4bE8{8S?V?A-!Ro=|hSe{S}eD zOZ?w07pC;d86T8BDaCh`{QJ)Sk1a$*(^Y_*ae`<@h%SS;Q*vd_Rs7o$eN=KpLV#Zv zrir)vfMo)-CF#MQxf$z1KlpaVT;w0S1RmC>E#e0E{a;Wa!>xbWB$T+L9UGLvKq1Dm zps37re61VU^WV?a8Rhri*tKA%T_9{HHJ2J@Mtk8#2^ zWaMI4DZ~R5?EHh~tK6b%<}2>}BKo%+Hb?F0bmB6;yYj3Os4`|#l^zUmak=E~5?Dq@ z%-)1wGR&v=eNcFqNF1;Q%l^mD;X+t~krR&SD)XeK7V3PWT_%IFO6gutX{de~gFSt< zeS%ZXF^SnpxsQuT%DnpuK%nuS4kzrYE9^Knkuk<6()O`rg0eGA(3&BeuMpZNBqu$T)>YqfgT<@oCnyY2xrt(o)l|rH;9@<6Mz#RUSV{ z8b;5HEbcStIlLFuqMM~}*x9kch~69Eu|cx?Fx>nc8hu~|=maXB|1wsquHVe_IG0J| zrdp%_KT~HYpAov#c)UU2-GnSz_KKW{G ziqATf;e(^NI$uoIUgO|jrVa=}D8-31)CukVa&z*P7l8-2FT-74e=*Mu0XPvjBMG6W8x=pwqID?jovM)K(4gYKxqUJc4%#(^P&2YuD?d&zc# z@PiHEXV6R?8Qqhg_BsYyCONN$u0STXkL#R*tTfa;8eZV9dkOg*BG(#Uojs49)NZup^WWB-)c;vlR zgaM;J<2Y^J+|(a1;2;WX`8w5q%dcGZfE6dvOMb7iYUMQ009@azv=1f~K&@arv);W8 zGkDp9Y&Z~PPZLB<;FWP{I4kp?I{uzz39o=jwkYM!I}CoQqjMF(3Ot7hAFfTh_F7T`79lC6l5rkr{DcrKUj31z?GL<3O~ z`kORgEWsXi9Z0pwdtGRsXD!DNkEAR;eZ@!@v;T+*@woGcYOiVp#`kBwz!V11n zaqOj(Cl|1f6hi4^;De>r`)2`%d)D%3|Mt4jrH;XBbZm+pmsfubs$*Y4is)-+kKL&{ z1IUNQjQV)JG$Tl<%fw*Z$clKWk-B3k2et*x9z_x@vwEQ5hT48}TjB)2izlx}4Bx|i z$YUg^VF}SeWGG?5HhI7DiL29L7ClA zTwUhRqBw!q`)~-`M3_316ZV!2nMDW0;Xr zJ0&++Nsde@mYR=zjY}+>4k-8fC}y&EgV`8RerwLZJ~P;19@l$#hfW61%Q!}?g37H+#ki(KaVHUA5(y7R#902T#54w z$asb}q52Cf=6!G$DG+$9unUMz%4F(i(_Bh@coM~)nZzj#MN1b{h{O~2T# zC_VEw_I8yftalE}F@Kjpir;ORP|Ys7N1bk5v>;^;9#X}Bn?tMDunS2acAlI_LtruHe35QD)x-ra} zuKTHU6xu6<2jjZ<%{^V|Y|PBQ6J~77Ks=KGvDd#?t_);5o(FP`XqUDmU1<6t?o#N> z1AoC%BGtOFd;AL=a8z zEawx4^fP=59F`hVgj?#Wd8?^>7u+Q0=B-Qn2nx0Q@V*AZ$N*TDakMrs*nZXEA?dwcxl5}wL#n``k7y;|p&5bpzF0i;TEOjLowG!wdfhtT z%&T~azWWdfg*7PK?6ygJ#fd?&6Oj`Ur{av39@xW+_uBTN;uk=d>agMYJvM3Ur(z zVJH$4>In6hg>wLc4RalW*V>`M_R)anI)qpB4%O-s1cBY|lakM?h7Slepq6~;oz?B& z7M(@FUt7>~r%o3`jdYDzq4lG8GK4M@019SVb3mOI*P+@IP(4do9k{4V4r$uY=+y~u zVZ@Vgx^UjWiHtRDhT0;;&y0aSSvv45!yhZQ`|+9c){3Aq!ue@P56ghi{f)^O$inXf1@hu$)pVes(R5K%a-vi9G$=lH`uj8X7q^P9+RVAxu2Zx7fu;kZMJFc-(?nQ47M z(HZ6AlS+AYuOOzAT(A|^NB(}4u^o(RyUp5S?{p=Ha>_ z`e8n@Yt!iR8e;lbsRL@)c}vGA`Nf21#AQEKq}0d&*puSBZXNMk`wEfIyhC8|UO2s)$ST&TfAQTWdb?7zrOQSCs&21(7~LQ(Yh5Z)Oj zx?9m+VRwi}nAuTV7Z8IJPdL2w8MR{Xp9{ST6P9lI?Tb4p<0@VKB3a%if@c~5EBUV+ zK6s{Od5*Uv4orQFpLtS{@`0eK-}iph;p#Or{Ge6&NX2hmMFadr%b^1$*ss7 zo-RZW%2?|*%Vp|Ih-0p16fLk+spI*xXWso9c9gbq&C!ht#>+$3_hsDpE9L6+$T6LlC5d=2QZ5Jw_QYW#2tuKBv91n2 z{%BQS*R>O{w+Gx$VMdT+Sny^TxHg}rs_^y=#@AX`j9dDZ2ZpPYCc)=8AZhG2qV^rM zCY95iM3PX|=ckdf?jGOFzU02X^HW42+XbKL_0Mn4pT#w}rv&G5o&u*aTJU>m73BHH zS^CNhw|3t|dPywX>I*-UCCmYihBN%(VnyWS9)QTY0L8J)GlafGKdv;7)yISuUZIgF z*c~9N2(LfC*QF~@@H{xzxTd*P2RiBd%=>y+WGqW93FQ*I?TV4223EVS!TJTQ0Y>np zMBWgPT=o}O;ZlL_1pLl8hE2uV!>@rm9@pq-eRN;0KYBx@*Mwi$uQ9Nvi^xq`b^34_ zM)LXz&TEcK_&i-0{TzIJH7Yv|C0u$}-Jln!)D$k6kxxb!&rP>uMUxZJA1AW>Cv z1DBb_Prgr)i_lw(ZyWeF+0Z0$s1iz@8v$F|KQL=7GMZ)xE5=Bn@J?&S2>mr!nRR5m z()->naCi;oM}(Y8!C=h}F(Irei_s!S$xeLIvDhH@pI#~pw=fX#GP(rl7!o}Z zT4AlCbPoIDSIY!J3pY(sQ=S^gY6)ns{O>0NVCfh@-`P-8Xnmw8Dyk-TdA2lD*gqpQ z;~brbyLrN2)W9hILrk%w)A<54>`R%`s}X@f0Tgz#ylxx9rT5&VLzp_z*^6%eKtKnK;Al5U!bJ$=uirq~ z)SZ^+Cs^tLlV!H+fyi#iqDGghJ&n^H%rONKcOh`;mp}-OzZU*Sc8=X8Vpcx;PKxWZ zL(Zd-oJxId8DWo}JBD+gMz7eT{(hT;Li$adAu>^2UgT7;ow>^cI?*7uc~c1?C>jeK(iceA~VxkJV|M)?a% zeSlsRQk+i+b8!l5vio=ME?UtinVBx8>PwRbHD*!GD>O>%>aZ3TCUVovz1PqRTWaE6 z#uUSm)eYt<=4ybpeho!E%3FG%j$b)!EDd1R(U zjC7Dv$CxAU3@8Hfv?_d@kQ&Is#NM89TE|(N>D{?RW~2qrTv`mu<>((S#*i#|4Q-h- z-aiBoAKLbi8E~ zA5mhgQ8V6|#_+raB|@db{*Wc9=t7H6G;8dt^GK)iygd~ZKqtLMKZW6MyMu^!LD6AZ z2LU@@gV@t^|D$dBC$TlBu*=81nY;g`pU$o*aAoAI!b?F#T7>@C`jwOu=2uzo22Cce zRNMpAm&k)HN-Z5dtQ#s8FE6UTRdcjPmq%Nmr9nD@J5*`pdWbRO7HUXXM7yj4t`+D$`rr9 z9U(<+Oi=W80@5tW&Tdn$Qebc1M~ZQ9c6)^%)Y)Mu$W};zpPj(VAby5m-0|b1y|5Xa zBovj1UEC>w7!&b2k2MS&_?h-LjjMam@0-yN)$o-=NXhtc)=%&Dh)ybp`H`1P$M6mQ zYG~6PAIsd~f;*E}PxgaNRYCggS9iTD!HHGIpX^6qr~Ib2(_8^NgtO-8>`1QIpt(CN z)CqmvqJDWc+v-SQ22S+Q#T>DcagBOvNmmT$m-k zkq%$#hGch*HxE~{4(Hl!J5UssD}Cnh*hBTwOwxiVrbKke(pRVNkIqTX7!=f}IV_@P zw%4o>DKiG?Bo+E6+HG~y$kankzWso4=b0~VS5X?L|0J#lUa+L1x^{)OZT^*Lc#52x~9W`@r`kinGb%=%qH(a@ow*%OJT|c z&J9M)AT}^ub2}uaLGx*D6_`5+yv*;-h42UH>UvVZv{qZd|6~njf10iY#TNsZpC1H3 ziI)J0BRLoVB;C2v=Pl#L5oC$suSMcLJ{3IwD|!jIE+3cMb=RTe|H6Bc4WoL=jd*tx)7Wi{Ntcf%+e&;klo^7f+u;2=Koa@}pRZ}vM6h+M5r3Fn14O@F4@$8cVWR;4QS<_W9~cCYy}T!H3nPb#?rSIM;REK(Hv>oD%S5)G6!$aF<##R^JX532-Iy`% z-hMFjjeG>Z*!Z1x#Y~G=dde1rYNp|Ut3>p9cs)19yIfr_lxjs|umzk_w5rUz+!%pn z_u9j{a+xEjzl9Pip!kl#6NkTjUARI`DW3KYoj0`k_aathcV$o zMKL?Tf5{yoJ!#Up9H>z9@#1+kqgzm8WL$X$ozb?=$NKOpHy+hSXsN;v?;8&j-Okl|-M*wj5&+)Orl7Z99W2fxPN2+`omZxi)@NoEQ ztD;^VAVu*db~EK^3T2o;yyDHD$NJ%zNWG=r16qKV+r{}%4WiIG=QpUa>kA6&SQJD6 z6gm9O0tirwN{0vjYP+6I#p7I!JS~fFFS|r1=V1c#fEADN{dT2lWi-b6-QOXXgJw~p zqLkn-ER40{T;0z*+J&5Wf%DuZ$Oqu3iLCIp${VV$XqKFmi3wNmJx&A7tc=^mMzuLx zG`7_syN0&g38LYJrl(%GDY=a5CGu+XylW9EMu?E>HB>w_73axhOtctnjfn2DeNOKq z=P~#NH~^H}%+wEM1Du8ppTroZIH2NU)j-dB^cNEtA?y~w1lwV%C{C)PE-i<3q~JC_ ztLIBQ(6sGM1+5Gy#yRrC7E|=HIs*s9M>D!{Y8(FrYhTsVR^V*4|yJx~_V-fHZqYwEE~T(`3LZ7^r0 zk-E;VIu3pE=twc~n`-X-dJydH3m|(L43#8r=GZey$BHRGt&ZSA9zZ!co}E@cbWakD zh=QPiHc$r4Sq>ajhXgyFs@C?4KQcY(5*X#?C>#eEAUp%G0(gXWpl3jX@LMU~b>VWO z@I-hsvknaTKvf9dSKaLI*VYO}HpH29DPdv@Dc&uvw&JZXJ}eWb%*pa=L~>Xc)nXj( z;-HlNDHd4ccp=B97UDi*^26rq6etNxhYDvD&CVp=^imt@!jI(iZx#g!W_ipxImz!j z6{AOl4XYBsBBteqRIWbSyDct%Fqz}!i#s7-&Q?XyrmQvbx|eMCfH@}lXq}|?_BYDV zK>zV)SCn+0ktc0%8MaDbgE>-)cJO|Q${vrqPOhJL{q4 z1BDq@re0~g#09k8B&l-W0f2denaMb8K)Nu1lg++GcXT=ZF;p5M^Qtb6Ko1B? z3{m-b$*u1!BF~lKLeFiyVFSu1s4HFUt%{3mf+iqI`qet?A{U! z`faKssR#Abp3E00Og_~)1&BIWJnr(Yn44@MzQQkE3FQO}9YR)SSgtv%`DQosD_p0N zr|RnZv?^K5{!!rqWCNf$(%I4)!ZD8X?jDJYeRejgx0Ztjw%6l1;~!^@7a-oDGt22` zgt>kvx}oD(Iagf3!n7$2UadsgDi%+^>FK`-wf&&-H)j~X6lvX4+C0F%1gx3bU&UwA z6dZ@q-SXkUoVOTJ1w3xD)!|kPRX3lC8SL#B7)xSzsf$h~Oi7(kKw;hTH~h+uwdD_l zH!WeDr%f^CrKam%t31*&fI0b8H4j_M@c*zAVe#cxBKC7BK8)E#mz0K zM!~-N?@zIo+i@=a-LE9)SQ7ctviEx&(u##lOT6WR-! zNuxKP4Egeem@jxD2Q&j2*qW>>C9q^qdT<|BeNIT%rxca9oTS`B_{tihsrLL$i$@u{fSUHl?6{a<_vKK-EOwZ>+q^q z==F!Qq9_>aYqFbT|r~nyWTH73dN{I2xQc-m;5oZ6mi>u zehFjr*NXfkYWYd>wC=u?+2)uuQCD9wb^F zWN*H5WG-k)Pm`xPiLs|iX5*aL=R#>Jzn@~e)cjlfkWHIA+pV!ICF^JAwswu4gc)Am zF1L8OTri6XH25HeNgznJQ(^_9N7vnP@)a~D0EF#7_Pj~L`mS0$kZD}+TaG}yAOhyP^$Xn1>KmFsc8kT%-U3dLRM-x3(ECV03sAw^Bdwr!~ z(DL&Q!)cJASjRw_|Jwke(9VVo_zL^)W%sN-`|B)N?fLuH7m$ApmgiHlAio2FM46#0 zvJXaOcY~2qg4g#+~l6VixNhQnFzH(i(^bbRwLhln`J&o@K@=$5U<0 zDL1h{PzY8CmU8e&GYy`=c@yeuvL9D`k&g;GdmQ^FI`j= z8htyX!F_X>Xxwt5y=V^-vQ^j8gt^PD*TfK-n72a^U^D<8H7~T+hNLURPrR3cg!knW zjw}HhPoo#{+blo9Isppa>(6ng1TF+=Y>!U0(L?L%H{M^wT91ON=?*=;wm{2afm&a) zxYlUiu+57xnf($kY*Ur699n#HEeO0YcH=mD{vcnP30JWn+>-CKMYep%MH`Zc>ldvq zY6vM+E_Vq}5$etl2b~cyvP4mFly$3T7-B?7*C2!D8;T*|0o>jazRW1{80X*lv6yZn z!kF%<^tOpjf(dnL?OaiFh;OL_&gywl-d+Y9xg<@3iNfB++C?WZA>N`Yn_O)C86(qL z%n+NtAv%5ZWR{Yp__gteC!aA4pZbuU-Fd~v%0hwmClaj~sx7rf!ojO`1THN~pBi(P zCfR}Dc>UE$sPsQEAm$~K4+4P+vk<{E3(u6{nC52_N?=xc zU1#hd;(gAS!!CTd&O^JTVv;6ofK!|6H_&D|glmy}Ti-)k!HvJr=9|JCDR}uq{G_-+ z#X$aULD5V;!?At{E9_dm4lYoSem>|>o4-7X^OJglBM&uqVM~dkctpiloxCr{3GUMw zU3Z_YmHj|>%U|ri(wLuH7Zd)>u}QS3(zv6wM?F-h=N8XkA*>`K zGmke#!JYlawARjO^h-gh@}suvnl??1*Uf_cG`KeYI$qz3Q0gy;yzMuCtnWFxq{zj# z^jh)qYH@Fh`0O5zZNZpB;N$hV3Lm);3yQX>tT%s|M`O577c#!7O9LW^n%9#G{dW7W zur%1aP(lTm+-=0E`nWtO+j=1|W4Kigdp?zZNN0|Sb}!H@*=_85e@%S_(M;;rXD2?L z$vuj=W5O$@W@uHGLP}C4eoWjx-ygl@UN`P-weqcGBF#OF3klo zj4JO^9uJdN7}@Z8f;ePWyjhP#pKqtIYL9mgukNlC*qBMo#B=YKqb&jmw0abF_m4vN zqLH)E=h!Htk;yu+WCcY_Q?SxH%V*n%555iVv_^-5oUE0IT!)O3J90$`krYe4TAJYg z{_6?+wNs5lPn0^%KDC%S`A56N*S9etd%;rHyLO0SGgxxIKZ#?|hRaREcTCYVc}An^ zd~Rs>su0H@Yfh4Y>msgh+1J9&7Y!9N#0-bVW)uw&S6675=rT>kaoqIfYv}kNB%Q~W zqc{LXKZpf6EydbD1hK8e+U`+2{nl-i+y8(5=4u2=k;ItJ0$= zl{(q`tI&(dS7OUyx_+Ltkd=hdFW$|m1)dQLg*;qLNfR}$7xRMRjdN^2=pNyB2Cn%{+4n%Ppu^ksG%i*P#h5A(ux zN!=rE0?zGI%kTv;P>s{=W8x4LJgf7T1&JEwr`fCaL9@J@b`Wftg%FZSYdmF7&EWj- zNu=7RbF+`xK>QQwsCre#CE;@3TS%!LL<)m~974;VGPtuJ=z4sKfBly_c17aC`A%^$qJ?C!2T&(iFx#R$g^$lr9$D zi_A}M1K`N4wA}Eq?XTM#K)})So7e>6OmAi;eiTQ;F6QdZzUE?--)sO_482CGI%>?a ziIPBwQbaYUZ(go@*Qz@vhBxD_u`K73o6g)E@k|ZroMt{7$&oHC z=01iocJ96S3<;%-VA!g_rSY*LX|l@Q#ePCDh!g*fw3L6wR(3x2nT#)Ai=K zoACUMAnml{022x{Nv*Cr{0bwXJDBStWvjA7A zP2^*4*HZWzJtyARnqA2sCc(#fu+I&6J@#wf5%!#hzIU0b*t6)B^MwTn?2H86Q-<8} z(%^mMBcvK)@V&~=ubT}+nMTB33C*v&(z@7-}NVaq}-2cO$eOw zyf*Id1cGp>VPs%^hqVH$jmEHk3}Gbfw&#p_v<%V@#G(TSo8wZgiCL|I^~t=3an~Ap zv@wu`m8Qxz?Vgum`TVMjF-S13T|j)&_#*+SYq6o-HZM#P^WC%P&!u8a7p%?yJaRn< z!`Q*l*~Z_U@8~fx%MMPKTJb-z?A-#k=2`k{Wy}-vJ=KdCQLnwvW|z9hJfq%ZjkFTE7N1uIc4p;?H?$@asn!iVbfCF!PUCQ6h?j5==T zL(4>O^3+#G26-?UnS#!9hB4K?(3<63R--hF<$!2Hrp_LRTR zk(lJ7N_$!1U(Klccr6KKS(RoiJhSGY^e%Co)<&l@Y2r89he>95$mzRtgN_5q~) z!wB0=*g!j}hvu01ZI+P?Z)X^v6$@rfN08_BL?Axow-ap#u`H0p;0DW#`Ge0NzznJM zv_}m_kd6f6+V4VmQ8sN3QT#5Ni*Oefy1=~H_T)rk&Hr-TDMv$HXAC|kgqo3uF=mdx zA8Nw8LR$$<$<1k+ODbdoBfEhIxn*p8!_yhkul+uM>=c-EQqh(4RL29htBvNW)-XX2 zG1tpm=hLteFzuuP$uyzRLl8~0*!}(8Y}VA*d^H%TVBl}4f7K{H`Af{^XSOF}XMGZ; z5wolnX02nJ$7n9K!gk9?hDdrFBUru0R(s(;cz8f&TTl?PU-p$NzRGr{2glg3gcwyO z3!tNskDm;*4(sUbrT-#gCV<^!An9Et0;?^#<2?G>`_~{On01A}JKnO%Nt|QT8kc8^ z_{+EA%Xa*i(xub)wY6BJvZCTQf62Zc%n#vm6*B8P{Sa2$@57aYira7p&V)^B!R_DI zo-IxTNcN`Sn8UalpjP4hBxZVFGzffXNOqGOlxvwhr&3(oO_@)~8$}yY{Q7{>ufnOUItdhL@jNrL<`=e10RxOZD{>(AvV>>y8BNBy9d&vtx?$mfJ&p4> zQ`p}&r@y!0b#F8l`pp-Bqyd!A;2Fh$D=!0To$;7~YzoZ6dmC^XaD@&A0CSIC(n{jA z%n-y)SSUf2@~4!EH_KUrAg{|pcMAY>U5{m6bKU-}1V88k`I3C?qeZnwls2CDCMJPC)ik!X9z#noto3zi@fz2yI@aoAOcTRUrqlUY2xfm4bQoqgTw6(*mmcg>Md(dBh@5vh?t=S zKDN2ci5cUQHA|kCR%%6Q|Nq}>ogY3kvKOx!o9wpBdGjwPXUlq*w)8#I&G3byyfHqnx?Lvs+=qhAc`&Vet;1WdzY1jB zhp~O1orbs?jtAtn$;@pV`sqlE1T6qGI|x~XACfj?h(L>U_K=V7N7z>)f@(KuxhYDV zh>0*4q6#&Qtyl>e(o1c-as(K8XbQJDpI;Xoc_T-=Cn>+gj>N0S`=opaMw()-eo{B8 z5F(?=%FaPjcV{Z>A(Hq3RbYRP3H@m;<5qFmURABPguooj(x@JpFQ6S*lS zz3S!B(Msxa`Y<(WqycLPvI$XbxI}y-PTVgENKwz4A{u+93kxnD!gf5s`$#4%2tj6k zHBA^U$wZ`vQ5xUY9+cpg(9tjH`#QE(wt_)nU|ZP<2Pei=RULF&EqMh4oOTD{DfIiQ zKVRGA90xK#tEvvG$JU9wMPrv77Y#716ajDlcUhdUy=f|PHtko+evt+~(?^ZrMcvQA zd~v7KeMf;jn*D5| z0)B?7YMn%n^fM!&7pgg;Z=iF8L`@};jhIeiRLqASnl9K@lbl#LMICPmF(8`#pWt#qI|>?s92|0LHNdm1r6 zn#+7Slp`QND~L%T=YFQ4?&ATFTT-p1LtpD`Zq)nAzwrhtOl z{rTxC6K8SsUTG0|^5ldEiD${{VMK-kHUKq1%D-{}%d&gghS8nirWKJ1>7bx-Fd{7h;$-1unfh&;VE1#Qo?j|Fyq83g<(E>6-0%s!`7brB?4q^bB)^h7ti#ZUPlAujMjZ z+u`}a2c*<#LSE5cLD4}COsmW{~)boZLV8sTiP)i2oVj|DvVE(yyk~hgzapIR?HD{9d z?|#+^R8xcq9yUNmDA`ot>}r0)a?_{$)xK4WXSh=7km6abJTxhqXs{Q}1F*d0U7mBO zpN|Z#HbBdnfhqiru6BW^aIIBEsY3mJM87~UNwX6mgZZtGo7u@)WunJxV;cHjP5d$r zCn;TaQ=w`bxOJDro&1y|hvj~LxO!CqP@90L`XN9R`VF+)T8;TWiXsUhVet(PU=GhQ zzYF{?r!eIw4HCyFo)qqS*ykGp_^%E@ zc^I0GWAW-^i}y`vV>#PoF={@_U{T$)C4;@>w~V`~J>3lR52}{#JWKkWs~4hN!uPRk zDu+I(-(c2X%bwl0>_N9F8NYK%zR9vJ?|W*|E3AooruS<0F6t4@hJkl6OARzZoAHEAlD77Up|$W zJI=jvQQNiuZr(&e;|o8;K~gkD?3O$1R}N+2GsK+DL@ZWHZS(vty^2&CIz@nfL;44< zFaZeK{V=fJGE69i>8ELUYV?vGg?BK0WjzRlVSppakqj5l+%wi_z9e=cf`i@ zGH$ERo6%LjP zp*_s|0BRzE3@d8#?Kqr!P|`4-zlZ4d)J<|2smU%-JS52S1cY6BO#5`5b?Jv#6(STN z#3}T=+YJLlMy!31SLIh`AVCxcJ0VIyE|Xd*YreF}_doZ2ldUwXDq5 zfx42qV+FG>Kt0EhwN0c%-7d%xSq;j9-^B@vX+T5=LGnBda1r*lY=t%+xK`!|bUpeN<+j-f_dz;_j=jDFVpAEFs+HlA{@d>fDb$mzlR_XmBxd^bP#VB!g* z0-K;9m)7NUi|Wlj5fusxDQyjfjP!nE>2$D_a*zCBH`@0CQbRyrt129BH&Sl~;dn>$ZG7?2fl0&9+EKL!7_kl4_?Ur+4dfn4?8wHe=*o+uB!^5Gc?!1$(o_T z#nXCOUI-X@n*bnMEhy!g!8iv#_N4oP-yhLab)r)GngMq!JRmA@%xNH&0ffGRvN@vT z`!2vrW@GW9hTh43=sm&vFr0j_1F&K}b0OoiAwyvTw87n`=<6uxLc8Ymu_($YMDf7+ zHC-IUO7lYWq;TU%yF}~pticWtNBB4e?}ne~)oC-H6q4MVK=tW&Y6cQ>S z!u83-v0=m_BaMPV1>J|G3m>Q~M3jPVmK7I{7-fB(sbP9P+S$@r=&Y4p#PBEWoYAT% zhV(!%jiNF4oU$x6_j)Uqpxo)cKf(i_>l?(uDJ|$`D>P&1U2pi!@aCUNL2Zb0hfH`u zIV7a=+F>U29i=;50?vEXVlcp2t!7$HwW{i|;?BS>(tuR6(HEhcT+3#erAXLdz5ew9 zk;k~qARe)y=|?M)e6NYiEjo%GuFV)6J*(|Khm$Ls7n$<_Hq{+ zE?7u*k4o!!VWwTvttMPg8_)Jh)e+iaf z4KF%>{YZ`JH&^Hal7iTmJpYQmJcMtSQk>-razT96Lf~}V`6TwU^c1|*MbO@f)H%o$ z3;vBUNIT|e_}lMuXITRoFCnRqtb}M&<$`vpTCdLKEu8x=Y;Gn8e+yRQkU(2MuAV>7 zL8paR()~e`pM0F`s>aQO&{WipzIjm}cIMZ~8tVbDQn} zo|;>~AR4C+x4w>-RiHTyVJU#7WAo@*r?f9JBpVVN)Aan@;6~9X#CPr{bUQ?0FKe-Y z0&8~Rmi|_k>|v#Dmh6mh%xP=|5F|$$e6^6I9eSEDUE(=9$9HPlH)_HWjVN06Q1Lgx zwiNTV5?RI0V`TllA>Uuwlm)50?m`XUq!J;e!SEoU`x1HNc@MRNv%Fzw)&E#|J7iz( z8jN(mAgsxEWQ=IqF#0P?+;_2iPq=lr%AcJ=JFI`_tnn=jAhLvOH~23gg9exaCe$6& z^PEUQqV$=mjtLk7E_)4oGADJ^*dj+fPEMeN9K$1KNMIOJB`~Ks%{%>30-+}cffTBa00BAM1 zxj6f&o*Hzz8G*3z-^1e%M58PV1rfElaRkCCvN%EiGgXzom9MoiPlIHJjKjuv^}`v4 zi>9J#_f0kg7GV8DThC#NbE)NU#SziVWE%*e9eN_-N^cf=jN5t4hB7!kjq<>P-ETXI zkFc-=K%UJi`DrPuw*mwoA<9^la*@!xh2_qNit}r?ifQ39@o~hZtVVf(j^}r6j5SM# zHWYP&^i>U?ZzErc=bi?mfS~hh1i!UX1vF%=4NG{%)RA_dg zN5c=;0(Xq!i6wR}ZNzQ~Ke-Xm+9{=}qXKr94nZ#}A}jL{nC>CS=Pm-w{h)>9vpFqw zf3NxPJFQ{-$P89bzq=oT?e*c$H!+BCF7?1|{06n5<-O)+*o|PHtNwV|2V~)ZX;Ljt zk28aU_hytZKr206l4G~u_&HYdI_^VN=s~EI3si|*E>V>vFcnC^CuO7HL1b?0iiVN; z?+{pA3fauqrlqY|ywdsOictIgHi^51g96w3rz_7ROd-pQpBoFZg-)OZq+qqWEG4w3 z=lS{MBN+u>peY(UvgEn$-Lys-lvvMwutgPg6*xPR4u3xzI-KP8=M{hF7ZTgO=?9I8 zW`k@dBTlnM-vG_W#0&H@YA}^wcTpYI?pikv5^PB($GulTu~k81W7hi{gkxK|8Pprs zUiRoyN&V##uitC)7Jz3qaI(AG`ptgx=xa;tkJTzjhWv~wv*e4D91W7lNn&dXRy=)z zp*2;n*t0*dsB^ksN9!9DIXNF4> zM*xI-`FZEDjGP^&df#sk$mGJ`xRfIYgPA8sZ6OV4ItYYsLOmzg*-UvSAV7qy{Zl=j3cLyKIH}c6d$35g@CX;Hzm(i8& zUlV=cX;+Dy``+J`wL-qzGZb9 zXK{*E47SPZp0;kA(;-op0~ohLM3AmvZgmWnEp8_2@LIEjkKHk0cIyeWl{#Z_6n$b@ zQ}4sGx4k#JR#d=Gl;e|nzt7JJ);-E$^$D-!8>~$lsbC(??JbZ5q)31Q40OKW*OvKi z9l>%qy#wptJG~V_x{=~X2!BtqmoJ|6$Tqz`82{W=JH+0cfu?r`z?ko%y>AR3=5WiW zHI<&zj*z1kU;H;e`HSRNYo)eKoKXfYHlt}Y&H_LOrU)aZ8w%oO0R%hgmlnvGggMR7 z)Kf0{mN)4-GScecZAt3bD~JlR)9JneD8Ss!PFW*A5R*wWi2D8#YLDT>*Jhs z`A5I4y;nO8Dd%mVU=IQyQbWZ{B8ko6I6$`HzM1r|bfjdYly$gbC-0&bP(|`!2To$C z(g_XkL*jp%h-Z|%MWejY85-*|ck-6q!${Dz@GU)FIRytBuSla2&6g${*f?of!FHvN zw`OQqa4#496^RsTbee|`*plf4(iTa`76_~vqJ57AzKkho_mO2$a^6jOs*>N5K)utc z+5A=jFY>`fzAc<;xhOUtBW6CHZx~53=p9bHZkDM;?uf!hkaPI;^{s%d#$bP;@KqJb zOvn2x=?`L-h5K1P$H0jT0|GzDAdg$OF03 zh^G)Bne8;(ouLBce7swtn4spDPDm8?u!=wWobSi7C)Oi=*j4L3xU~d6oe3I?2LP~~jzb+EB->N(5 zIHup4QV^~oP#;DoeJD7ponLt-^&M4#9pLzfJ3%!2k~*Cg8$+O(NNCn)i2{4W(*YO{zcGpz9m`&>-Rl>60*BdO0KdwAP``k#Xf74U6EF8IK7wY zk~<1CoB~^DU*egEAcGIu*Vf^8EkW3(FSu7CJs|Y?n@_F-y^Wro$6=SK{Iq%q#yO+|8EJ(WkTYLYYdRSqKoBNhM=7nh%fxB$ z$;|>kLh%F0s{^a+htfAF#t{kpG{Gax65bE;dlPAvZPNDu$kFog8Yx!ew1~o#y9XAcIj%*t1-xkvN)yxoJp~BRv zsvKBwg7gus_B)olFDb7VE53rAYS*FnB)W0zMc$GRq0m2K*5XO3~7 z^|#K3zxH%`_Dg)-IZ+c^S55bk<|4{%QPVu2>udUEp^ch(Pr*LWpdR>ez-T^lK5fxW ztGjY6^maS>KG0)Y6vtMU`og8E0xODhzap?NE`;Hf+$Am3h8xaL6%(PWCjCqEDZCC$ zZ@O^U-Rl~)ze8O9o-fkoAghi^)Tmcub+~MMoT$WZuE=+O{{7WF#OPRGr`lWyyw;;d z=_prLXpQH@su(`W!!dq3dq&iV2i5go<OOC9@i62_8)=e^j^wi19JgEZm2e>I34r<0U<0*%75~nUX*vqUxYU+H zl+%#RPA|<@QORFmSXYJ#uR5h$h)&Ud(Cn;P3moDZvK^ zj;_OTWHfh{=e@-sDDM?o9c1PsO>s8TZEv_u)8>#$~a+M)d`_tuO;H4M;TtW~zY5`~(ns2S@oFwBt#uyOTW}l+Kq|$zNgR z4OLuaX6%6e%AkC{KSYEES>JqTQIMKxp!rUUv!W=@P@!(206ke3m0K~My^BZ^N{uD5 z^MudR`g=O&EAqPu7B_i=!5Ouml2lGI$~GLxO_^WR>P$|Y#`(&k-ol01A^M}zSN#+)R<+dBHTR2(Za2G0A);c*XD1QOW@N!B+b>VU0l+#!T{k<~- zsD?^Pc>2cb?#!bT{N$mkW&4SdffduE^km&D<;T?qEee7xOB(mXac@k7LPb(3F_Kw( zzhOEP0csX24v}Nqk-&K=O0e8)zO$V%h~UvpsV|EJqy>Xysf4WDynxkEww39a1)V~m z?)lblX@sxWubcV2og?&CbU`bJUzkW$^`jv=O43sf2O(Y!)cFYT9?DgxtnhRdrQ~@B z8tY|gm5n0EtSt>+;HI=?J%b~N_D=oh>%?pwwM)^(M>?+wb=jsDz!=eZ`A?{%oO zy(tm#Z)X=YLCE0odHf1PdcuYHH}B`7E3YzKi{C36Y+0ZZP#ZqLDX-%`7S72 zDaACuSw+%oZ;e#^54hfmQQx0>dv)?u`p|0=R-G3OLY%(3wri;2MMxA5=6v9$?w;i_ zV8)=d@X`W)mQVe&yj1FbSJ>bFug!vx(V*yqlg@2^2vreT9Hd!+D$C@HNMPA*{H$6F zLQ+Y(&Us>;r#XV_1-mpIy(zzWn@j(yh8aHztZSTD=R^%b@#J(-XV}7!R8cfRh87Eq z*rMwN^0OqRlk#=-)`#`Tihhw6=-E$r;#2Ta+}v1Dz}k6t`^nFR?UZRSd(-l$ENgx% z#&k$Yyd!&Y(vse8^2N#UOP2>SyuiMEQhclsokxL!!1(5~#QiGLr2hd}y;-$TT5qHX zxn}x&V+5I}s&148kCvr~_`z!bHr5JQF0iXAF*I)@~lz#oH^x^glP*Dk|j69O7B zP`0@ho`x6|32HT#voF-*2%y1tVe4kPJzQr)7I+q&dY1@@j=S^cPSBM`@F?}Wh z0y6m1a^bA#J*+Gc`?mIbvkCRegVlp@aZ#Q$5GMdn`e~E1$2ssP{irsAOyW^grEP!& z9ejO|&B4m4Q8K#>d7)%uG6#C;^d+vy;89{Uu=Q=TH5Prv{}6h{$E~cEec>BTXv2tj zjy8Vgg+L%yIHdY1{rwg|1N2_=Q3I$Si{}Z1dHnwL)WrLJSfkHTT#qxpivj&CXg`Dp z_9GSkhpkQuBR#1*Y;f{#AOJ;=5#Mdt_mJskrs_$<897)Y2Wl~jr;6*~$oaz`%?g+7 zid5Aqc|M!#m!KGN*Dy{OEbrzwg^de4HC*>x$z%#c+aAMtJgw;B9DAUbkuaQ#3+<}y zPt>IRJtSIlJ{O&zml27ySzIalWx8hWU=7kl#qi2yI^8>xA9qU+lI?*B+tl`R-@{o# zLTtJ7i=N!L?$4P0dwA*1Y}Eu={Kx&cG$Omqx#qnRxO(=05%*Cwu&AaSVX=y#q{Sr| zE62ZjO-}Uw72)Dm$|OvCP!0Qb+S;!b?|pyG{dP*RtPR9l<)L<<@;m$bjR;PK%08`6 za5@#$&CJ~(4*RU()}@k8@qH)>t=VYGJsqTaKIGo6T50Tue%a^ii1Tj|92YJ%BG-8P zGBJDyDbHWxQm)(~0ea&k$C{C3Dba7-ip$b8bXI;R&jo$PwyaDM|JxUGUmD(%30YEp z;B$i-i80#C4??0efH&y=d4xcTjo^ngn9FnRaw zHAPjgz3bM}Aj(kjM#}1oT1y;vG}l*F8NI_byN&T&Bw5spq03k1W$!J12Z* zQupGwC6n40;R%~E{X3|ad0ZFrTr=)`7MF8o6tNNF=v85CPQ0MnNB#7TK@jB`<8Cdo zwn8Lz5e%PiO<-bO4bHF4+HC_wWwv5wooAb0{H&>ntCm;vy&4aY(G24ZRmYRX z^GGwk+6SLP{TouDYm*I|=2JrpacTsZiIpf*O5fb}(h~IiPQ2P{5`Otgig{B7h?YFs z1MvWYFJNFa>4CjKZ7ojl6-s}|d}gR|*L}w<8IwIq1G9pOzW0+TfqXyLqUre#U^kPl zOi@aopjyAyEI=hXuabRCtNkU!KAs<)1_s_|`=XAID&~B!>O18AWh7q=WrU5)9?t*!hBs^C6i$3&a zNXj6kv-bMF(6yh)co!`hEN<+4HxhnDRiA;(p3tdiOPE%m!9@n5hrzLcqMH|ooPRGv zEc-YfxznsW_umGvRxT5jzC+Yd2Rka_;2P|Oe=MQ+dz3N0kJG@gs<3q#7qY`N&O(t} zY1G@AyxnDm1#4#>HqN&Y(WZWDS6=X0Q)Nu?3HZVl)#XX{xs^}Pid`Ov^Wh7Jme$Pl zc0ruE+6^fVm$hpTeaA||D)~Ns@z)x`X#9Q>Z00iOCCvgckhr!D-WQg{pIXWN4z7KL z>zn`Yn(aG}UE#G;K6MCSD2o$~V0e_)(ZB|HTRB5=w*vAn2*27*a1WWrnnysTLs6Wz zuu5n&E>_h?JT>jGt&6~Y!;JW)-^70-9PteI5UH6Q+^1bt&=rn{)2iZGi$GPzR)GM; z`zT~Dkoa#9@4_>mpYy4W>)@}knu;dz$NQmPZaatp_J}^_>VBgf%rxfZBvzx_I zfpFL`x~}sZMKtyMb)nuQ?BWRr#~IGBe#?#)cho9V?)9b4Pme{);k;6PFF3nug1iwC z93yvc3q^@dk&#S2vPEwq*T!vram$P02)eawMO>#n@94K-n+1r$=b=Tuugk}%+R_T* zJ9~iRa+Tq;;bi1@%FjaI{K3zk@o{sRqnmsv?MH2VvwMEBm<@V;mTe~sa2{Yka|Af| z@_~-p8iaq$2V3v?3$Js76QM>H1kWt{?i{tD$*{9f%MPo09{7G z@vWJKp?dL4A{+Or62N9DLc9E@^ZKjQ0#{XPjwsfTz$S39$V`{f3+{gNQ&t?}(h=jF zZ-f7FIrr1OaznB9C;r~hLZTAtK>y$nGOnCv4O&=6f^@n?)AZWilZ1_G8V2^VkBzDY zGbU~6{0rDcKs?;i`j@%gFYC;aztgg!tkZ!M2-Wc4kNLujX=d!uN8g>6bg!qw2k`)bNY* zF8yPLWs<8K`Y@2Q#p2rkD;8mYVeU7l%wK@69nn1; zWwv@q12WshlfZzO7Mp2&5Ix?_vZgy9A)>T=Hs$%2AiyzV(MF_qeUBDOHvBQP$WP@P z1Cf|9%JK+?L%Jnd`+bEVpCG*X91@SV+<|x-y-iJB)iJ`k@bR6+DSs^+VoH5iU~*0~ zBjDh6$E>KdvZ`?|@b6)F2Bd3^;-VL7L_z2e@0`uUu5R`9S#}gdDVzgq6a-{l1AnsP zr*Ri1W7D~bA{8cDwMSW&*9D=d$|buL6a_e{-;)acwg!V2BW~*NYZu)}D*H@zev25K zWUVM^SvB*oW6B7w8CJYi#{RowAv{9Il`Uc2lJkYIb;c(_nEEaHegz#V z(mPS*B4}x8xhpLaM0qe;bP9_YEh$spmd3*{RA!$5qo;p)LON{mal+5d#I)(=5rN4a@Zojg?5572qY#DrslUi z67~dappAYWC&#OAN;LgCGb%mIJ{OhWU3$KS!-*WQnD*-ZRQo@U&SS|@7>c4F#DZiD zEXg@%b|jN?=Ie)^WmmavBlO-qr?8{}L+BxrP-D1x@|>MRuI!GwhB^rQek#6gA1PVN zwLS81lr_QJ+4*hLG|3Kg#BpH=Kcy`r1&F87oz%)#a$2&J-H=l&gjH*II79`UEt0bg zjv#AVL$q;_%5ja1Yrj-`lQ}nFc|Gx1apE=v${@MJs~?uPxKy)=6TL;v@(pLa_=)J2 zEn4)pd<~iFF9#?pJQ%3k!yKx zlUNoRa9O;S0{zmCo;YOu;u>SaS`HDM>L;@-4K>M?Y|Uo`yjB*s!G=E+9{FF=Qsb8` zHJMB^UJLp>q``p)WX54@9=+&=F#*5sCVAe5U4u;GcX)a~fQA&-=GyVH^rC!VNO`XI z>#T1`CfAK%upsv+k4MVR%^3Xc_54v6a<|-E%%hrW)_mxyuX*!Ra45#UUnM(Rw;25` zDp8_z%Wa`?ZimyGa`XsK8MI0oe|`n(J_yXC15jX!kQ;85G|u0sIJBB6aeet1-h`^U zthNeMGj%rBe6M}S-1$N9?IfNZkP?Q|5Ef1!&_O@s2!Lgg{lEe{j*1K6eFos5_C8-_ z%%eU~_%NN!B<>BGJtMmJz3BwNo~E2DKdACJe#zbSqxEEQyY|uwZfj1YJ`_0M{=V}t z3q!o+j?iIi*=B8JPNd*`%c2jgKybf5+Q^NnFszo@(Lp&>`0tQ{R$tMS7wh{}i>U0@ zsgxdId$6>xJ`;~^#n@JPa~fYc54LKUu2g!GSxv~ zpWv{%KP~(X0KR8t%Z(YlwMQ?by%z_2sw}L|bzlb5Kf|YIm>=7s6ud=)*=@us4JyLB z_2~0&c#1YbS3AgEJ<;rGr#yWqORFcf$v!*}-WERWOeZ?wq|MwZUdRvwW79~Sv9tyN zZcasBNsY$I+F_o;8bo^#&{DeXI7L=lAVI=;%W~Y=RmMdfj z&Tjwuao}3q3ZEyRmbEQ=X%p?6_@r6oQYhBZR9rd8qpB;^{jSwya&`#`73dHxC%g;SDdCer1{c)}G;Xff^QFGT+(8 zDOFoLmD*BR>}eidi~cO6JbX-X;hmjiE^GVp_{H1CJM%rf)6)BzZLSXbqgxc)zil?* z`sdBA&4_<$0o3q}6-P4fkhaE+@u&=b&F^ zfPIQ%HP3*AzF+>#cH*d_Wg@6uZj|T<%b>K7v^9*P{$RQ9U8lZ8w)9Etk(av^xu}Te z4!a|9aR@T*<}z->Y2LG$b`L&pYUT$a139A$axP_wK!KR~%m+W}VZ>Q{%4O@W8m#Ip z0r{)iY4$Y#D>Ad|mqa6tTB^oTtLl{^%2XesMcWzrv`x4uw@w_^kKS?) z*7vwaay4dwRl(!+TKN*W^n*kd0Dsv9ks^*r>-|X4`nx+sg48rjqn#*i{&Ld+;a%Rh zk*CL39yFU_W$gmy9o^=Yt}CC0eCzx(TZUO=6HyKuRc(L7bi2Td2#C@^{4nHJW6>a{ zbiFuCMIoas;7?)~4`QC9?S4qh&YgCG>ff5evRfA#?a|zo=la00?)}Ungmjr(ZhV+( z-ELUEPzPY%gBJ6r(a+h_Vb|mXQWXX83i(=k(f;znIteE3CH4WeKMN|HQ*SyW6hLKT zx}2P%S$I!w6|KJ3j;|kB9&fNTiCbev1~R|REspR{FB-19(h?Y7`V{(l-BINr_f)^f z?oS}JYs;}O8zeCP#w(hwSj+l_h%EHFV+Jg)WU>n33P`*|#Qn5!L87T8K{Eg-g(e6` zH~2$6w9=TrJ)6NZ)53RlnpaK?)8?!6=4h>=_|k|>t~Xukm8_x|ljIdd7^$ys$I2y)`KHKk!5sxnBp>u+Z3qD%< zN$N~I_cz|^jLlwR-yMu_zC=-ClQ{u;{gk-=$vEAiRQ*1+B9?&6H$F2I7|u1Z-pxk# z?rFg|_@6AXF^OXI1o6<%T2mQxYNh1jNVo?P?vZ@p%ohG}UM7+m0h=oN9@p-IAWOPd zL@i*hHMpR!cKY~Aj%r~*Mn-7)6Os6US$URofilxdqU>2r!5B0AZMR0oIcNF0>yNirm7(2AzRBX zw_%RY>wkwxNQlVW4E>j-usJTBjKqf(oOhisLL zDs4T;*Nw7<=_LTij)L?WX8M-#)F4@6_k9ta89x_@o0X?e+6e7hBB=X^545BPy``ZJ ztZHn0xxuEmEn=J;aNLB8R&r@2VB(M>`&tO>u+}RfdI2fBTbF zNRN^{*&!Cb?0l@*S0^9jN2rqT6h3@Ey(lBuK_5gy+wpcggoK0)wpUK;AOz-R-2pFKWufKbe=a?Uz^;6QRI2-SD32`|gfW<-zfyV`w%|6MN= zn~D1aKicuL;xHV(PqxjIC*LT;Dom6JKTl`5K=pvY`G zL+apVrHMxfewMBJJGOA647WGbosm7d$&ib>tW6;&vVt4l$f;Y63b1bb71x$Dzty!f za93Sisb=cE{0^rGvlJl9bpmeZ7(T~sS9&V_E=_T0_cQ0X{Cn(ZxYlf!+z7Wxsk-OV zWn*NkHI#$3@z;Od5{D<{)BoHpmP)@FV3`S;XdGAj^$RxETpka~ov_;C?uO6SMhjy% zK=^cz=tyQJjgn*PgHg0L^=pW68&=_Q!(Ao@fe2=b?PvY!JLgH_;JoA1MM;7G02D+9 z*-t0pm#<@yD5MG_a7OXk4)c)+BpIhuu*?qBQTr6!70@$@N`xNFn|pTZn$N%+;$C(4 zJe&-ViEC%pt{t|84np2fXNukV`&F=R&Z*=7F8}hCwSuHo#(R$qz!{7%eECgLRoTBYfJgO|*5f z9Ba=*5u43SkbSPY7yA1Qu- z4kQxG`OJay)bc^Q=cjZh15TDw{D4dLJNGZUp`vX(+-mS;^nCsP@Uq7V*4qxU3Abe??#yzXkeS@W z)4>xCNDhy=x1Z-TSdvUg+7IdaLrqjX=nc((F(DbG6G<$}8!fqE?_F02`*~_E%i>qq zh9oxyw@?N5HP>y$X6;$BNkLs>NHWZBkK*m7s<1_H_w^KMsl%F*O6v7pGb1oSb~?j= zP;y0yg#0b%$^FIh zUVNxUI01k9Sgw_md!XA=i68TxqT5e{##7k5nty^wt}y-Ke^asW7E$<>S9;V4!Xg4c zGQLPu7N%~H(GG(X1ijMOt-Lv2>%B0|8Do(bHdBcEb)jq0NS-=HS6r>fOFlQ!m8Ef(Y)*zr zGVYjLgFA7F&EBu5_zETnC(R-7HfZ1J^=ec*~oh@iIUQ8 zC7qB+j^7VM$h6fOBI$jJyG~x9OFBtA`A5&3ZlaYM zC~_G?loWS#aw#vHwJIQ@HCm*lIq2P@gVjP;1oUK%F|smV@?4Aet@m(Ufw0(O&o7!+ zNGC}dp4Acjpt^eb)3*pRCc$OpTRC-r%(&HN=0QP1+4CqxhTx?XTOkw6D3;G-vxAcc z1~Jd~h9=5-a}8Rv=5@=&9x#r_@Z|J>Y}am3u7vCTbDp&&wEc7-&^LV|h$=`=``%2t zqAwdaDL=8O-%wfX0>D8^HshkKPtFn&1XX{Cbk+G#3==6t^CE1NzwKsw$B=X{-)pCq zN}(RcKnPovG?t;kc)EKEl!9&)zw)okGYoW_2t8J7JDktu)}xB$LEf?90AR^V{5@>) zOBc)eX|vUaT7LM}H6*P$DzWz;>ITLk4*ie6sZHn+DkM7UDO({?n0H6K4wJldOL6K^ zdD|K;4a(gnF@%V4Rishjp1dR7Cbs2=+qVXM4dDWtNk6M*N=~QyrMs(Wm&Hx4HH6I1!diXN7|6Y31pl`rrv3-e}BW|zqK$>*!&2t@eQ%+PBQpS>hmqK zDfocj0Uo!0I!QTn{O_mQrNMzec6GUq<+oJ9iQ_rrKaY2YH*@<}8_GNul*y84d^c}{ z+B$W7gqHhh;Y?ybT^oMGOf96Zrjajdy{Y*dp!P3daB+S{d^Um|Y=*RYXoV+vY#71> zoq5rS$nVAIv#Kb8(!GRh6tRI(K^HoayG8_PP`q3R|r2Hp%f+S-S(oZ;!Pql2gj zmPciSPi~Wdq*JFIYi)@khTHLjBKXP+9n$ohPNFH}ncrh5V^A4~_YP7wVG_YgVWbR} zGFpD?yJ|hi@ZMzaH6pHQl$26fkd?$5*poIn56bN<7o6vMYw;2V9e+lQ*0%sNG{w~^ z(DVSD=eZ7``=F;-$`1~APX$Hl`fV3um!dtC5r@5Ur?I4ZNtHX}C_qg43jQz!JrTxj z4-EEERFkj$bGg$n z6pD3{JT+)i%cJ2J^eY1|>E_f{jaAo^zW`12Lptb+cQ*B>oad@c($_(N99i^SA4#$O zLc%8Fb!Eij2$POo#goL>3@!J&%G!cVE~L412rsl?X?t-?Q_?%IO!QDYw?5-+X=8}n z1*Ni32P>$?z*#0AP({J~%637e2Q^-WkU z3PN!?GaG35xuldNz=r_sYjK5G*y~OJ4!4#U69f z?cd=pQd$OSX3H^}&+-aWXvkllBwirPSzx|=cH@~goQSN5#Z0pGMQ+s_Y+@g1=wGl5 z831;58)%$BH>W*0%Q@G7s!;_uqQJ@kcw z%$-GwI$KCe)st?G`Dc+sc8vdWXxZ9EZG&v zFO-Ug9u$d}K|P^eafYOdc}NpSE?4w&BBl*9n0XLlc`<&`DpVld8^b}ZzSY$&p-ofWz20p#7z>S773S<5Cf zxE(h>RMM7kWpPx^`b=Yl#UtV%>u^S*1hvM&`wF9I7i1s%if`PzFN5T3B!xl$709E+1 z3-Q2>1%vLO$14pE9ErrYl0HR&==o%n(eq#vgFQf^#lV^+zJ0oT`}@W)T?6R+d3sw* zT|=a{KA9?rBD!$qxy6#dRE_r))S)S zt4YZxKW_0jI@yexsLl3**=@=5Njux5rD^95wdFZr{&mLG=Ho0W%Rv2@zm-G0`X~?x z)e~*$!HOvDsCrIIm{0J!#TLuM>u^H$1J0oM0nr2s1c(jdFtj*nssK2 zWc^(H3ni`(es14VRPVd?5g<(pZJtS`nG4Bif%tw;>12%hjm%hiU7M>oy9=5YT11Xc zrek3~K^@w}PpE#Xc-HClq~(V{MyB_4Hks1}6au@tBSUuOPZjTe$MN!FuENGOyUuFp zOn1)N>0os21lG8$`uZp)Yi7KjG!F&-{`cE7syv&4cfr+gx1yOAuW#5(_p}&d zejB-;1B|GpO2awg%B2lRNT8*&f}FzfQImqhiZo?E)8kER5o97eVbBXH{Y5PDZ^5Ft zeHM?S4S5LK*chG?8}R+i2=k1e2yqktYltkoQ>u{#k(pflSMcYgL&6eyejF*a;Xu@} z!l83)Dgw5>h~&Uckp0LKU~}S&FvgPJJ)DRAmZH?0eRn6Nhol^)=xfQn5k9yQ3$c?{ z0d?l63lAwagB?1UeQpebrHG3{HW$3{uP@~uA+R>IJz_MnuzE`?+X1vh?q4Ds)EQ>L zVlt&mk&}-0Tr+xGGZ~P1@FdTHiezmTp*cj@+tLEQZq#yDZ;&oQ@B<^wCTe;|mC|Ch zhaLYN4Jq-l4Sh2Td_HS>Lp&Yul+8I+B zt>k!q&MXu^&gyn75n0=G4OhE~+-eNh=kK8K@1ZcR2A&@#RGofql5sHg0wPDTK-TE3 zgHA+x4(s!=UWEO(-E((a{6{YF$(RhpRKiU^mN=HxqJA+;Wm_54hYrdyqEvfTJ*MMx z`o*r9DvXf`UnFXL5hH&5%ISPciHyH``fQTEo@8$l=#k3F179<{_>sS&ZWVL!L7*C9 z0_l;iBX&SQl>%|Eu}Qy%*y9nI4Wz;EK+s*)8pRCzac&nQM zG4bSZgAL8wDrf9*3#|?Ahu2m!$nWGZpn_SzX9J(_(9));YZ)gR9|i~(nvd~y6!}%| z0g7FCmhIYvlu%papjG~PUx+qwG3(6<_rMjz`^+hlBKZQEp@1h#fwUETpX3b_2K#yA zd_Ur6>2##EW(jY8&N&l+c?~#eLEb^U^^=j@&smLZwS}S+rAkAyQI(ZvuYniYl zK2k@)7_MPls9f%oR!-feBomkyf49RIQpa($Yr!mT5f}kzckP_(Gih)LAAQPuTQB*& zS9WY%{Pwnc^a?VZISC%R{+q^S4&nKiX%1`Kt`DKE?w3IuW5~n?4WRmV<#mOWZ=$tM zr^X^}9`!ucnw}RoD_^lKBXk`97_;fs_GZ7I3{4}OSIir4wetmZnI2=COTMi%b9uyz z0KQcmN%tJd#9srZ?AeJnmi3k`%^eCyB^J#pOa$^$P|vFl*VO2)hq|?y0ZiItaznC( z4E!*{38mTcbE!uAvil4`MZ>wi2@P2*{rz@f4r4z<*5}23{L_1%B4-GMxO*Z|k7!;vLQzg)W>7E z=C=wjw~x!Z&f=^o2tw5mY`=|MSkrZ{B?zuu<_+de+biC8`JdQ1K44Hbq0QM(8#tPu z=JGDpzlWme<%NPcussXxyIN^q;to3gN8`3#jmk-bvt*%+WOrjavsCxCu9_%binxIh z{%qEAzH8|*wHZh$OB(y#>1kxFMr53O5)Df~g^Qg_jdf(p zU2jyAl@~moa?m_hc)?<-&h|Nb+A?(H7;bjdserw+7M3Z%JjwFo%HsPMAu0^Bg1( z=C!t#&#{$mV7>^(E;v-%n}%QGn79NvoY%}4y8+?NZ!>0xP3kmjGC4=R@nP6XX2}nY zKc5Q-=rtk{I`f)U?zR>Ibjjf8Q^Q(Wl zRR&f#YAjio#QmTMCN36pa8;MWyNzh%?158gXXynb-RUN2W)?U*3?cM?Z-aaXi}It1 zY%l(fQTt@O6D1Y)`x%{2nl2Q92O{P*7CnFKk#CLc%necXLA;~&SDqSM8;P2UN?TIG zr))n}ius*w$&B!_+tNL;hpQ7q(p1XD1%DxhP%52?PF>p75>+=?Yw*9$3Oitlx{h6_ zpaSdVD*7M62sz0V4*5a_W(K1p6!m%;+pVhbWtE+$tMfhQ2nVA;0I%Cu*DZJlvI}M5 zR7JnX9GVOIjar50Q*X9iQTMPBAv4OuW;2?B`M!xOA=8_aF$z${_gEWt>#t?`s%bzt2ef2izI=n?hSh?EwgGL8ez9e~Tkk;0 zALR?109#~B>Uz;JZO+&wrPR_wh9+DDydy;!)#LreR%Bq1$JKEzKq>v%S{o&6d z4`RDP!Y!L<{I;PGZJqMH&nio371ulh>cPuj@3;EzMo~{79h(+lRdSz&4he`@vP2o|o ztrtTywg#n~N=0rl)nY{el7n-d?9j>=-ll3xd83p*^oPZ%R{(V zSQ#}5;4a$#Wgy2@6aC;{y|y&f-}T^U_8r&TYV0u5Y;UaRH02h#?<^am1*qa2O;lE$ z>|(Ppm)80zaOPE>U&wK-+7fT`;;ESws}sol5!TGmw_Fc{c*|*$4E{Q^{NwXsd8m($ z&f*9uQYF6OAvIDAC#fK_!@5p<;rG}3Qr>E)v3Ut>*8RyVRHm+K_PjXwn_H+q4^t)e zPK#)AaX(k3Wx^aK5mTjpu||t?$z zCPL||vXNX5Noxi(scWbE-X_@@nUJv%yJ?2e z_B#fi8Xj-{f(?IoKRe`$3L_~9t{d%07lAO28ya#?s8^3lkO4q_%_WXxv?tEHel)|C zXJ}s^5XaBi5L_83IH8Ig@cRi@agyt^vT3_ax+RF~UC1R6J(I#gqh_=uvXq^GD zMpW0Qh97Bwf=YAa^NE|db~xtSA}PGk0zGU_0>Kd$l8JeJ!eHw#ZN3LFVCE`H_xt#lJm!6UzJ9ljL%__@v z8ZaF7Rq1FcH$pFHiUMm7J)!QtzV;&wDHlZvF;mFztb#odqAK@?i~CkTLs`oKqIDDa ztzhv($OmZ2YV2K~qk1VR&$+)XKn+XYbj)LJD&umTmvxPBzdF%gEq_L#)2$~bp`y!3 zBZQEvZx8;qdNHe!ew2dQIj!qw>Kzi|-zd&weE;MS>-O9><_ZIPSoHyNC=_DYzb7Xx z<+$#xdHRa?55+6g0X3d(p8br^J!`a$ynj~jTKRT@f+h0pd9Dg!MXwv!sHG&+{bko;-ck#Az2G<}GU9^wt!GZvV7yP=y`5MR0#4=0awAr7Z_@_3^ zc~_4>2~y{wPZl(&0@rsuh3gbZnHf$IJjN`ow$N}qodl9*VpQOH2msa6d$aEc;JEb~ z2w68}9T#aYZrYLCBnHDoNCOvA#(YevFE2N1+no=Y{At;5ODow)KD`id1W!Mon;5U- zo2!V3wk|rD#v!opmGUrr|LvC}T;#9~P6$+`_Bu3Qa6h}4X`kUXj?(JW?z$_v^X}u> zTr`A&y>mr{`Y9%PIIycd8NR}Ozbn-t&m$^d3Tr{fRdH|-= zW#Zxa9-&4|oOZl5hIXK?4;pL65(bAIEolmFN|ScJFjH!X%Ye_!r^YiogHWS?}s`xEKPq^%^~bz2t4W4ltQ&RPsVo7*{@yiYqq?m_~{ zf4q@%2yE8x*Jf<3%ChDQa<|8vFXRcW$FQ{hU5gNoa0vu9@wJ@c@o!YH)iad{Swn{1 zJ=d2~b=?&U8!n3=#x{3!aNJyub=QkCCI^4oM{*I@XBa@+*vJv)2U+*TJ zobXT5k2Xir&7XBctrJkgOr#(4_#nO2A`%ua_~$W`h$h!(^UoN6+4DR$J&iytRsT*b z<}0EZ`W!ZXPmt*^P{q0c3F9iAV5D6Szr$S7y^)}A(jW>uX@l(?im3i}uBn6bA*t6| z;l@dFSgI;xemf2Wdn@0Mj>Ug?bi#qoDM!u39T7az3sFgM-pBc4tF@T1C7+4OFU@`^ z43kt}c3N(_6_U|lf^2_#rbBISM&6x;F~wJ{gCGsaJ5Bqy-K_W}y|T-5LUQ+leB++}niGwVj-TMyP#5dOv zp?c%juk%`ijSR6s_(z@TQQ?Ky$hM>H^WHq5LzEIeU_Jo$O>NJtSmMpV9^&+<< znb>+0Ssu8+H7+RgVNI2EKW70 zauei30!VW;yJNYpb3Y+8^dX)m`j zC_XL;A9CwNs&}NB4v7n40>9r5e<#QPjVW`&Bth)OeE)Fp1OD%eN@V0epch|1&*DgN zU#57o!vyPZ$d9DV2kTl!UW{o&V3V$L)~loYYA;K2J^m8STX)A z?$eI3$_V9yY{4@1eREK=>q|Opoz}OMRum4z@6EEQsNg>c=znajqE{1|0O z4ZuV+`+F|+%oh~>G)=rC0*6eU7^Ux@u6PR+WnHZ0_Qni>=83k(#|Y7* zR*zL-)xLsnx@Pa-Kgak0PK06Cz<*v7$?UWsFcg2h-~hSIu#^k>G~X}r_Qf`(Y3ZvA zt#cI`_WjveQf>pSiYeq0LoTg(y$SNDN~0Ny4!`I;4Vv!N;Vd>Dz0}OHFM&s}40&m{ z^!LY{4*DsO%mIOqI>UgOgFmvC9@?z1T~*cXhabPjQz4t;+O8m99{ijSB=g8fAU|73 zvl{r~xjC<6d27u!7(fra+y=q-Rd~Ka%XDOfa~@R#ZZ=&B0zK9g;G&~TikHTL;@`qX zehiX?%qe7?&f02!s7|rVQ}wGd{{3UGI>Ur@5@4qA?Ca?k?8eAU{m0G(=iBJv z$NXeL)0S?)Dc!sGg1*y_=3E$5?Bi1w?ut0Y@Y@a z;ND&aiLnovH$Lvy(4^^5C*3|Bekz&OCDo;nnxto>V%t=OZe!2zJGR#&mvy+nO@B)Y zmTguM{7rJ_iO6aaj}U8=LGw$JqiVLc(KFVq4dh;+*Ygv(aR3^2R9J90bRZJ|d|S;F z#04I6ujSmoRuz-S(}Vj*)&urK6lO$z2_qiI!?973h8s9n!1JXk<p$$C|0nkVx%dtKHM79(41vktf(|yA4y9;MUTkm zj9~4)&}ZG>>5SOknIG=aI!~^vw+Z?sue#2;IiZh`gmTbMNUI;Na&zZI=90Ob(=CCC zq5yh$Gk8HLzTkuVKt%F0;j6LhVp!oA z^o2whU1p-E_Ycci!Gn6;$V? zxa0ZCDEHMPrXWkKB8Es~C1h@(?#iNWPn)b0>YqC!wr^Znf2PG9&O}}olEsw1NAJFm zsp(|TqhiQ*45;$;OMb2Wl|!W_z^fB0{Z{ut9hYTppKPd}^x67ny7|W_<3g4i!uY+a zA2wF|QVz&MzoELb29P>-y;Oy;Rk;L3KzwPE)>+L6g})QXBS)FLsij9;$t`VsxUl4T zHbhxTgpw~yC?N}#+0o5cRL5zOb!8vxmxy4DnrCfh`?L=`Y$&z`jq0EnBenpsGO4!- z&JxS8>eoW)IK>#|#)|#7+`f*$EISgfjjvf8T2*^{~u&o-5mL%$QSOZ$s`@W)E zobLWwbM`^e(^=l@g?H`P-~T5|ZERWNgTlkpeI+RRkc3u|reUx|w{mAJ-?8*dKip~D zhxz?vs}}vlx+|&)wYo5_>en*Xx9>&ZS+#&_Y;PM;fC=NU^*rLIL#5onc+2CiaCi_S zxG=y9py8RNjU=!}MGstakTgB6XZer}MZUA6zSPyJUtYh~?XYz7A4g}g?kWt0(FbBc zaTwz6&J33pcb@)o?z~?M*~$LbYD?l*HUxPsm61i>=I`CqsZ-+u1kRg&H7E;71$Xe4GBf3q?Y;P#bn^G1pW4+@@&0=-`MSuiB0ryIZU z=M|^x9e4&c1a;=H+&|J25fd_@0O{x&1m8kL;Eg<^vmL|4W zg3I6L6e%kZ2ff^g0+nNd+(W>n-NW~aBv4S+bIrq^!gs%6$x(m=-CGey9KxBKP@nC8 zRFy0;z2RHf%*)mm_Op6I*Sz7X@)z^VOe83C|n00(sN)hLJQ$6sy7qpFfI0;6Hyo3uNq)FT7lsHW~R8 z1KEvnF2ANT#>Dv7f^r{#lsFm*BCg@Vy~fC!_Xx>H*dGGpy>C*zhgD|r$bi^(3!lbY z@Xu28M(D-A&T;gihG57Nvs27K0Af5_Mp39G z)Ad#gP7h6d(7k6H;CtPJ$FN6A*R`Ux@!|gx%U=eNHGJW#xZhn(@=u~sF|7gC@M%;k z`*!Geiy9xy)!(YVtYZmyo%mt!ea&|8-ePyr4}B-(iIERYTC8{Ega_!=2UYKJF4PZX zblC)k+ngTmFDH!i8)Q=)YtX(-DHGe9Jp;XmkqzMzp}67XZydvubSvN8qbGpn)?(4i zYWZolvD~D`poM1}57#k^pZcz6j#U~C)^c@m#F%$B`_X}8Mx8dS53fGI8+}*FJl8e} z@$^2#ye?CcEAvSgR9P%(t`SqYXuor`AFp?m-1V^YvbK%+$!dxD27)zzM3}|%Xf&S< zxx?9S+Qs=q8A+Y+Qni%?;4u?v0;>I%40zobJqw>+zdvVUYA)yAJ|*9&J+yPu%z)Z9 zc~{3^k4JaLvTm*P%uU)q6Tgy@-qh9V(;Exw)s>+wgS8ggJqLKDBI`_PSii6PTexx~ zCy&>4V{_Jb`KnGw<*&wnaf1Fn6(dBpjMgTbwVLxd(YN&r2=+uzIcS>RM8{JaW;1`f zC=A*Zi3*fyXH&H;I0}IAdjNn#!WS|IpT&5sDga`BZEo@0toy=2@SDofJ6EkW=N8}evzQm|EcpaBm@Nz0sej<=jjq%bvu&nSF%E>$oRH$c)3AgXyj#I zdkRUzP#oeI!Vsn!svM!x>VqG^L99`~0AY!NyHWa}{q$Vijj)iM$T#+{ug3Kkt`7%V z?G|QRaT0nhK?;-WWkws2fZa0M^sW~>XBGv_T5}8VReeUBG;H6w6D|$tmnz?Fd|#5f zX#!<)X#8^VS4LhUVy?Y1EK7HnE+{Fig@9HYW&VAJ{tJyG!+Fq;_0mNb$S=REZXnAT z?}VHZO56t6S~%%=X4$aw73DS5pqE4LCtc8+DdMBhj`3$!CgT4tzEZ7=*39V(fQ?$G*4X_|1pL48j#_u zBRy*2%i=#FK4Nj=rY2Vy`E9YCzF1HHJ4n3~+E5N5ij35KD&>7Kq%sMv&O=>&;2a%z zxj&7#214sDj3OH|zhvnMgGbjleDpr=l^dCdH?Mk;Kc?p6qD?FwYL(7H+!HfA2BI)# zFj2tMr{e7|C`9kb3*P{$V_N~j$sG+NRU}~0+K^jK$?I7pB!O;S_Z@mfMg0K@edoTr zCD({qm6epB)iDjoIw1@=#ZCl~`szJG?l>_y)FDFh zSXE#djSI-(3*-c-XcSQDc7;eBu=ci#Udi`^tFL)(PgT|O%9GavXyYyFiibv6kx-uV zfjQ{PdW{rwiR$V0LNCaSo>+-Y$I#;~U^qb_78hqKv6vH#nNX^*rv<_ZZ}Y86=_kI} zFO)ssIU&&6Y5Xk}=EmGHx1^fRfy#s;C_uccpeeg7K~7>j746`L1r2Q{sh_X(P(kck4JW%eOlxyU@_|=*1x=yuFQ75@(!b;jGxt%KF_!yw|i|QLYE_ z*q-#62O62-%`2}d^DkV4%1*MTNDfO=RcegD9!|ZJ%wd^KbU5puILC|-$VxO+7NSRH zGiX*lEUl30z-lzat`SkaA`XkdacYvJ&6fSjd?GUWBFlrleDO+SzgE=&r_MUf%F=tA zoK}5KUUw&4*S!{h9u8+b7;V2uEcf$xARLt7-}-mp+VshYT{yP(H;^k5)k+lG1O5zN zw-hBjN=MBxsk-tDy|{jlIk)*Br(^#Nk3WbVUIGm!UwJ(5Qq{-O*$VV1RDVvyc`$)< zv5@uA5%iPe5*Y?b4Bkc>nIDi%ZR(N?HHMdEofbt1m>;BjQ&KWqG=QO%dVHk=%UxE9 zD-NZDWbha0?3}X_V@@SYnF3EyV-)uNPnL?CjLy@e2kc6ot?qcC*q7CHH(igegpr*^ z=8vX!k+!oF+-+QNXoNleodB|u1jkPGw+2*S)j8iVahcizvHz|bt5vMAp<~E(=faW@ zQ3J4jYl4xZr^lZi$W+%k`fPz__y&K8@w7Ws4F__}#>*B}7w*H1e;vs|t6h9>B+}{o zK@gJkiwiuy5pF$F{1XZldaM=B4FAiwz327ca(8ho`sr$3BI1_&cwug(q;{F!=_85TeV;Hk%F{A59p@uS;Uwnemo-Z>r7yuvB8#q>UvYeLG0XWw^ zgpBzJOI`aps)@7mUv_wN%}uEFcPO3Auz>(d@@lbnzY18cW14BO!q`aC zCM~XAT2G`vfpbsyA%vT@x5c)xTISkFn;dvgeth20WoTv4yY}W5fYlBbKL75sQ^&8$ z=Z%rr)l8XMw`d8McjOnc3AHKf7)K+AKtmvBaw-latJWhUy9JS+*n8BgAEhy|*kVT3 zR(EnFfPe+P>d6f64@Q&(eswI5+r?WCT>R9dCc2Hzm$(cL8MANSx0}fqG<1f{ zso}YEcFWgg)grJpRC~sFct+Q1jDX}?R*va7($}v)K7!C9chPTy#;@wjZMO2kqh~#t zy7&cO(D;6`%_d0rMJNXa9vQB-pgwGaiq=(E)-^ zUc9r8a2qOUU$t0k+#*s4#PD@X7pyToqyLP3yxvOp3Eb*dNL{MTuK2dn&YPSPe0&f@ zsUu#^*Y6^(f}dQENLo6et5PI{y7e4rGLRxh@H#IL@Rc6p`>E;0NH|worKtwQWv_>! zogkyL+3Lbp9QhbYv8y2%gevevB8$sie4mXx59g0W!OFK}=!Os5xU$kvya@@ZEh(Wv zo+|ErX)!cg@|c3Friy@pdyZ7G(xon6c3jTDjuXd3{*@4*%ZXrEz& zJaI^XaiI^$H0xrFH=t1XBjeyYO;VI2t6J}Zri;aXuGj6pQUL5V{wfutBAk_Gz>{9<3b;O#F~WnrUmsoOdpuG%o8b%yP8BIBb(_;z$J}PPGe#FF!I+>$8nZ zw)7u;3c1LNMexuWxqX-z(vslum#%^L^%9t0P|XhW3Jv$owOJvakmKh@wlp#SfMj>N zEOD>2#=_gFzCm+^{b$w#MUf8w}cj}*T z7%8OB8j=tGW`TA9^t=IC6kTJ(ps3->yNOBgh!Zbm@068rLjjV}pNdE!}$TOJyw09P;HJ1B~gLz{ImXUggM*MvSp_jA}~St2O4Qjl!$?NqaoeDaQ7x`LrgB zolhL$BSg_@E>T6omDAiVrwqQE1sD*|NDQ*aWwu!H&AKu*z|JoXDm8s-Y+nQ2ZjQmI zsb9c^W-AzNk>Ak<&f68$=~sO}uSL)NC>N{{&gJLhMTs)r#O?naZ`>F0Vrr&dSyLO= z*bwVTutranBlgX#LfjU{UlELS?<|?ZMZe=9%}39ve3O%i1}6OAbWa(5U0a&a6;72s zTPh?yf+bLtq!&+oaj8nt|8`)@POy0m2BZ<-A>cQyvhWsuD{w|W!2CiP>w*XwTMht| zwlZ&?R#1R(g^u*x{Q!j7vX=9~*!Y%zyt;q(EEgLaE$y~`hj~y5LT>x2>d*!!n9!JZ zhFb&$VNmSJAkKLEdNrEU>`eWl5`mm)!6C&X%pV4tK#d zPynkQKMn4N=SySqPV6D<%THn)nYhmI71Y@ub7EK;krUz@F28vKjftS6eW->jAgFB1 zqtR%2JL4h#lYa@DhEAU8>8B;v?ZLScEA${8xR+5!J{aIAYP40XA2ZQ^U=&6BmTs}d zYD@=b%`hMk{F$XfqkAMR^xm?nJU>-8Bb6vZ>Qp!(;p19}{A0#wc~h&KnP>WY#^PO+ z4u%72t{U}MWLb1fm6m>)`gt&t*VR~js2foR9T77ai#~9jV0#O{IgpsAWr5FW`kch+ z=xy7>5qk^Tll%!8_Q)k`yD5WZu;%Y6fxiBZ<(oJ0fq^dvS1I!0>&dIRxZw+K9~@WA?gpp?yf~^VCY}o= zx_lPMIy{s{i|`(x=>tDN6z3y!9!ay@ziUz2wt~OJ6aB1-q`YfbMzNaKGg~nSbSbbI zi6z4xGTWCU+^P7QVET3(8nB45rYJU}+@Z>MCD#^g?T?c(49h#St~afd!9Xko-cdW- z@Cj!1XV6VYaU;}Ol4Ca4X&(2vALp34B>zJS1(aN?i#EuR_c6%B{xe`)F#k6el%?_c325u-?Y@w;`E9 zKwE_Z(gl1Fek9d3N79jv1M?_}j26C3Xk&-1owEU%9KfaO^CnLRkUX#+N8J{c|F>VJ z>~B3$bz}j6?Xkkg$a;&n+sN)ns2(I`qjiR$3FW{Z zk1DW7Aj zcfMEDv$KCBhHOe?wt-GYif`eiXG3l5ZAB_VRMw{47Ji+YmQs~AUk|hk{iXHs?kBs5&v4z~VMIz2rdtid8K=KzI7b=xNlTu~wNIbXMX?g6c_Y~|Ah|L z$cf_5g;km;KFtfH-&2SI+29QG>`U?+8bL%-B59oic(p-|eO^7!qcd9j825%dwB=ms z;9H&Qjdx|9H7|jr(q>%TwClFed9v!`KE%($m$p8Fz)~OO`*4gt+|;C0P<({wBeYP~ zws~2dobfu=WVmqIZCp!lvo3AE9VzI*`0Vv}I=77yx{IGwUbO*070cpoEUIC3^l9Tl z>1?7ZRk?my$S@Kg9fj9U1%R?wX0;L)Y7#s45ij;wH!3r-w)5(e3Xl|_X8P_IP$(K{ zjZ1m?pKW@<3tIw_;C@^AK|$g+UJkAeTQmjAWML8B-OBVIKd8iJsMy%JglNp+4v=nK zVjn;g$cvvjSeouWh&Rc-2w6}17i(GdAfI}~#2&LuVlbA;C(}2l!eq;+*UaK_G=n9) z?!lylX`3VFb3>0g09bH2eBACPqN+d0gY?PkKlLU*eqTwFWpF-(J6Nje9P=%}2jPn^ zCc3#H9hZ}Fd`|QgpnaeLy9vi66cYXLP|!D(pWY=r$pHJ54d`+&0zxTO%`J%8KL|L5 zX+1&}0D|ovCiW9eJlKuDbFjJ@6r1BmA`n<|2SBC((EdR6=(Y+x2vrNJW|-bEQ06O` zZ&g~&8MY)6X|bTr%P$?nMwix+og5Ta=83*!zIVtu*yHF3wt+Lz<;qi}m-DC(+?}^a2N?2`sts}Ki_ag)dl56}ox;I2AW7%-c)o!B6Sqt>FHr_x!FBh z<5t3VI2)$mz4?cH+?w>SdXt>u=LKQFB=JWO1{?m_ZmHHc{(|f#l(sa_ip74J9i<%6*mg{le`*%aSjJ7PqJF(b7Aof_YngL2-e8h4UMSF^ZP zuVwi{(iO~%y&7)ktv5mT_Zqpzc$T`R^{-K_No>w)6}Q6fQ~<8beoTRfvvX@mWFu@F zeW8yefpGeS08{bzFdZB>3*mxqc$c^4Q+pZNVS|_Hyi-T0?n8TEGJZ#XS&zyTw0t4i z!}47A=>jC}H7e9A;C5ibm<=M^V000NflNPkoAnyQ(R>l%eb8sL_T0kcMo`MaVUpSQZfQBgHP^0VY-vrxp1X9B1rNf^zB-kz%YO>K%6>?i^3=%ay_F2rRn&450Ef9kV`CZWQhY`GJyRF zU{dR5#Xn$NTnt45Id!3BypXv*NTk&*@EwpDDM`ezp+tv>6v#WTL@_WyeE8xjXF9SF z;?$!DBtVLhNeTdRdjYIx02>FX_Swqw!;nY;IgSKEB!U=TmsTF!C;YB~Krh*l;CrQ_1DdKL3fh$05pD4O6I*>}%7aD0x8!>hZ*v`$ zD2(l^rbEh!Cmj53VrPQD$Ycw%tJE>29sIB>^-Mvr!9CBAXEAjo^L}z+IE0(&*Lm zeT11|&R4cwC`8xV!dT3GEPcgBN^D~Hi5cx~fL`e##3C&Zz94{<00c4qCOta9i-O$> zbU!2Q+7JjUX5*hM?=4FOO8XA7*n^O!L4mkjJS1v^%?AT1jw7B11I6jVsGVXr>TlDE z0Oa5KdtnIoGlHr;FM#r54w3tltZ>Ud#d!_0Ja4glJ73GtAI5;YWCJ=+7qGVj?H|>$ zKr)9~Ea`^+wTKkr6yw#<;|W?kvgW6leEM*-ywDG5=erOJ!ze-%;`mE<;U;Dws{ zrFuad{OY(Q%z;@i_&5b7YqA?lT8?+@wz_vO!Mt`p{dQM@|Mw8y85$bu*a!`USmlC;M)B4}H@saSyx z?4^DJ9hAJXL;;q%Ms0fJ>-QTP*hU6~pXBF7#`k)AJ94lIrXwHJ)0Bxs^~$2unLY>T z#w>PZcb|`(OIrr(Hb<<>ldq>cl77L?ArKQ6u6x`c$H(Cn)c$B#R~(%USx+W9dEs|o zw&PERe$*KkerBfa;_rrmAch3uprl#+vC#yj#28>l^OgIfA9@?tXWaP9%DdXqA>85N zajg>dmVxHK)>f`j=qePiy9x@vdqZ<~&IY z$O9Bji`1}ydd?knA`nM7@CQ`nvJ#>saP*gaxbOZ7iJbgIUm)mi+$*Wai3rx7!tj{P z`c!aXN&_lNqj0Oi&o<3_SDNv=5`&W=1^&zZuj)HrY1Id+wRSG#YW|V~qLJz{J4614 z_{W8i$Z*t%C<1i9NL%=@vtaTgt@sZT=rMz}?;OE*x-2Bem>HWezls!e)J%dXrkKyd zXmlyWa=}i4fsG6f05BrhjH`DU6>2Sd)h@YZA;RKfV!1!&aol$OoH43VahHz>#Ee&3 zF`#ADbwB42tLj^ze^MR?&Hf>+g+OqALxH0vhwcT%Zo9I5rlHv_>#^#6Q)yvr#w-L4 z3jir68A*gN{;jnr8^SDvI-N?564u&1=K&QoElw=!h^=H~V`in3d31>D<12 zIiy?$z%`GPVZV)g+-1lanR@TO?+!RUt$M3+p|3zHh|=1W+;7cJvh6(bo4P99iM;v? zP*&%SDK=DMX}Zwc2m%;8wtjUuRCT9GOR(plv+18(Cl*Lb9GnUzqBIY;uw=*rtv=!t z)d1pElC~IFem&JMh;ML{BF4vsdIE&XABA?IFBlqAgeW7=mQn+-!L~I#Ew=N*+h2>- zp3P>#(sU&I>#X5d(PwDA6s-DKKGLc_%k7molCH)*=R&`IGfX?4X@76jQLg!A+RI$! z=onmUd8wM(iL66=o({T{VV)53{3c34ho?KE4* z=cX(k{!w?YlTlUaRHgSUp#P{U|1m}(n7Bt*63#0a2L=Xjz&l@AlCvbY@7L(azk@^J zx(`biM~ww~+@c?L_K`+XDhlG83ui}hQum5UylSxrI)Z%E^=ukYg;vBDw}<+#h+8 zw{ro^cnyipR>FAoA`!woI<^WN-K-M6!vYuArUx3^x<#@1AO3cz7Kv3+Lm4&tk|Lu zried$fu9nsF)+ixzOcC}c5mC;lO7n%n*g7zkk%K!Xig;O^If4poyu&DQw|G%c&QmN z`h#pmXn#3v{dHMs5(Zn_)lzoxZtEDI2R9RkL9f-h0Bmna&O9&&h57K@m1yFlF;=YE z^btVj0-&AfNP=$kqY~~pK<@qy;Z4kuYbW7+T3Zvm3fOrx$)bd8$yn^+=xR5Q6pE$Gg&UvIH|LQR^e)>d%$T6p8dc?hpc zRprH}}4U9IYFTDw*e z1mOvA@16lIIAhf(IeL6%z1Kb#9n|61ciD*TmF$jWP%J#p_+txh9|Tr9F6mg)8wVj3 zC~B%jqj|YY85u>#fkH4J&8Y_g5)B)liyv9Gb)*`XJ|5{0m83d-+Pw6zFs&pxzewqklR1jm2uH2M)d@K&)MSjDGmlY=9YCP zyU`P7r-ugc>ovcKV)^?NoexC_?(VdcV!v$;F=XTWX}5usG*GGnDHV`8`Xi%0+{Lpk z{r2|k`?w?BrbW-;Q&?p?&Z7&03w;1=RUMs0Zl9Rj!L&vtuEe9mvfmne@2r47x?@)t zEK@*Z?H~mqAMPkd$PC-b-k{1^pls^lndfN$zKr_AdQEXG{+H>fY-+wGb(71ZmWAO2 z{`c{pUmh7z$JOFZH*!oTpFtU8=Q|Cf;h5jIC>!P08@1S>Zk70AaVU|gyCt`U=m&x4 zg`{Ke!fBN4P67;k%*HGpdCR`)*Ijb}Q$Vc0O678$z~ZZK^nuAMBj>1%CbyhG*_ z$9rD+<|o%*6lI5eV!+YuOih{HGHvk}Rek-YjX+juZ;j{M1$M~4vmVB#4+xAsEIu%Q zp<2|QTG%Mxmm^T@NZK44uRx=6CxyBOU;4C#a0_hr805zS7JpeykrfG{g^Dmf5ZV(~ z7z~&$YJwKPoB8ty_?t6N-xBH}tZU3lxBiQb zPWb$AdyB_4LFv>@V9JTrFHw1fIofAVPVxQKy9i_DUx#DN@9jB}dx#Gdnqr78Q&Lbb zG8EiQE6Tp}UYyIr>HolC@SnK^Bk`lU@b$fRm(U~XY<_@hRAQWg4k}Mg=>FHiq&(nS&wT;=R!Kz0YKFzPE+c(R6{T9Cx(#M#R z^sAiF7^Q8dU&x*9dT+U;<#RKl-s#Cz*VjS9F*it3i5Tc)4NPKL(@{iS{{gI+ob=nW zDvwtP%yIk@I9F-w!Ri&}msZ^J5C8zc9}+x_*4C@7j1LB4!Qj1*K$N-GHvn^jhp{$SNmnrvV~LtQW`=LqrD+;V)L~dsURklh6nz`%7nrI%jka(13N7Q<8P-ER|Z6izuiCc zGkuXZsaGwp##_G}K9VJ-j^DN4eKkt@6jk!BOjDb#o%nEB>!ly5+k3Nu*LP}~EYWm< zt5Sqet>i*DoY;_C zPb6~`@T`iKqHW~`(Wie)!5P0+K<;FKl7&|~iOX z!J;o>{E{|XS?0O%wCR96K!ews%4X3{eu5SRMZD#2?||XsGR7%rV^f(3!`nYC@0{9k$`MMb0DZdN35^jak;%d zdVLxh_UAb@%YP(Uqd)-F-+ZgqV86e~#unEmbq&P0ccauzH>-l2u%WIw*55)8NRwpp@cJrz;d=sBcWzt5)_##Gmlc4keSI(5pViN=+7`O@ipfE{akTj}R9_Du#q0>YL>dT0!& zq_543I&V!|NY5dIRsg10`*DCf&sf&;IEa7rgClqaaBnaOJ_3SbOa*WXh=B%zQV^y zv%S1jnCrbw7_ZKSBB`27BB`LuPX>R_o*@L*9DV?cNhj2XI7lY#Zj0B#@E1VMKM8+9 z|DjGmmS3@JO9lMyxv+{1KBj{3%X}C*n)jYUN*mnVk^>YiN}9iQJn6k!5`hiwIEL)y ztJ8~^CyJP1>B^ng#dnp@EJ`8&bNR$1`5U0y5y|7gt;fPr>t_9YP;C5oPdEaJli&xr z=ASuzF^+@3WNDjX1b3{GDTd-@&b2N47dTfvjFau-T&UD7=4$)#Tu7ctwer-T>40a0&3qStJB$cG+%d z+AmQod1!m6kOL{7@`b1m$_hMJ$4~SOgH?X0}|==Rj=+nZs_L)8S1hlss2dV4vt8v zg3F+NJ`sN_ydhG?FOObPvrDxW8D|C0{jQ*!2KCECz7qM%hnwWL9ZB`F$6wXM!DZX6 z-<`Z8@2FZu4I`4W7~~~u4n&{df!Nw_n*r+^7sXk?X#i1zR|;z4)8xRuRPmBQyS9 z{(n0VA=;~0q|v|s>4(_KrZf1%!bDvN;7HMktuyae>e$+A|uxLekc zvB<K-t0ifO-EsOdd*Q;-wk?1&jR!@ zr$d<~#mvjm-_pjRZilhnXr_jq>r$`5ve+-Dm2qoY_Men}TCcyS1^R*zUEvZfkwgW6 zJ;8oz+b&XsC~~ndAvy-p{Xn;i0%#yhy=KfkKyj~fNvEM)2!L$&5aDOg%e#*O8^SLu zOw1}tZ3)8Tnv?wy65s!|1s~S>TfE^a3^zR*9y#oa9GyU*r-Ob+CzVc}Hn&l+7 z4RWc%!RNrT9|y9N8Po~sonb&$P57Nv%oexW_;gC*I8<8j!pIu?9i@7z-qq4cQfFZ+ zuEAWIs454Z#D}<8t+6LZBMK#owADXX^i=%2ia>hQP?)x9FJxQB8k^t*tt@MOb4;;M_06a78(`8Wfp8i-`o87-^$~-wU?@napBtcrg@6zs|tJ zF@|z-{NSnWkap>zr05HwGQ}+zU~Eu(k)CV~VmN)=RRaj8BD7q3n<;QKI-vmDt!8q0 zT}O$Y@@OP}o}jrFdg7uJ&ywMyDUj~GErQUmlZ#+dnv<@10fgEBI6lG7?&r_4hti)2 z_;G+nY&l1SPBeW?z8E_4g#si~KVMG4f7VnIYmzb+d1yh1eT%)u!GM1V&W~8v7LxrB zE!Ggm3>&Lqid-1enJ)Nk*!`5{lm??6ys(5Z z7u&6*-|vJhl+gbE+eD+qpUHx}tiYb)Y@(4&_MT+l!OuAQt8YB; z*}Fjd5y0eN(Nz^a9r5*1X$X-|vlZhdut`Ym;{qP$Yu=Z#Y)YfAfZIH82RHGAV&5D0 zz#b*6ruED55qza3+*DUB`Wc(~XQ{9}n+i70FKiU^nR`Lrf%9Hrbu#LhQJYVJEiGwf zB#EGeirXB&;+vam%obh8A~t1DkwI*_R;XSv-LOEPQr#rQT3p&)g@%_ojZI1f^F6TK z7R%<~sDa`Od<-LP38zF*9<&a0rV12nI|Py3G*3tlXUK>IV47?xtwyotf)CIbyZs|} z?It>UHr(G?b+g@*+t;TsHfsc4H3FwU>yXM~QRNeU;f>gnd;@m#B8i7YM%py$E~DCl zs#jMT`f|ToFl=$O5f!ta+H8gd6U#4NJ#PLy`XpGcKGfUm62{c&J4{rDK@rraB;)%{ zK1m=^TE6vm6>j^$*H!CX@3Q_1_!}Gp)pPOEvuSjAaP(`TSAA@76m%|Abm8I`v(6|= z1q?e3`1LzmR%#BA?VO!z-g4VfTnc9Nv?y&>{-DHl2Mir6Omu9oSMvQU_h4|=!i16_ z^Ju;m+DT*v2RoJB??=B76$*?iSQ4`8@$+*6llgXv-pfwv`LBo^KG9ahq>H_N9t1T4 znvZ|YY3Xlv3)fe;$+b&;$a-PX`_832CZM-YW7oGjguH<0kHimkGvA1=E&b&DJd!2f7uv{#? zh{9aqKTiUkTG<9$r3tWf5*&)AQVQkY(EB7yz*w<1tFS5#d36g36zXi^ z64$32%^HeaIk-vYd@TrPX43TpEz$`~)+@-VTfxNDHV+EB!!MLBdYr?P%oS zxO1Ql$!n{Q&|#6L^YN^@2m~Boc?He!+iA-dYDg=`L_Z~?ezx|>>ET0i9ENaFN=4#s z1jWnY`Ina;BGgZN>A#5cE3S2wp9nIDTrI?yOzF#9FiSlALLcXoX1^%HKgrWlufQMv zw6@B-^ov`cLmFb(tD4v^mT3BogE-Xc)rd7$?|BfCxAA*S*moSqqI{$`f~*cMOtf$n z50MW0oju?JW|ax2pN8HmdmyP)2HTpXWNX0pbP(1V{c3$RdHF*yXX==ns`7Ad$vy+- zPem0LmICB!i6a77)572U!Gq?&vdk{lEBX{xhR1%4TU=KbY>PR=pzu!ox}mpqG!^CbKC2T zS>zqdi0y_Gb%kT|kIbj{RVev7O;DixC#IDX>DBhR-e?p79BzkxK`hao{x~ zy78dt=ILkQn}3R-Fnjg~Ae0g)-nnrZ@(B_bdO5EsGiBHb~!(PcZc z9&rnd1KT5NHYc~66SXZ9%lPX8aaL4MsK`P%G)~1feau3S$L=e|v(}-RStZuutiKPI zw15&zU64fYj8dLwyfZH}r3Y6iQ`QGXZPy}Xgo_13RaEbM!1-6k7;x!C&4sy`y*_e| zumLAxOX=k#SuI}~h<>u`3kW4y3qd%ox#Jh-t}sFG zyE(BTjUi4cyFwf_s6VcQ<%>u$GgfvO1-*`AK4IYoaN>&m6S^VU{~YhbTN_K2zZv`z zoCkI4iV!rzUa{Xz1nTmt=#Er*6xucx3H6JNPqn@?n1RkwbXM)p#^v*4kUs^r#@++* zz!tLg(+8W9urG`U8-{A;9-0-|u}kfa%kC}#$E+m5desN3+u-*|mWU4L9pEF;K`$W` zt^bkVpH(&E0;mu%bfs?}Ck3LMYUfGR^Auk6fISQ(nUMfr)HK9CB3{BiM?C0ir%&Y*@Z)7=6t+|f#vyYfWZF%=?zW5=cGn3R z^IdmU@=-WZ>OwiJp7X~f%SKCKW(qvj=PLo3rgF|R{{D_!fdg3V zE)y)ay7sED^*L#lm*}?pV&P4fSAH(CxvbG&SCZ?#T2lpweCbit#$%6lw$Oe)X7rl` zGSDJ?@P4*MYy}K?qsbb6OwlyfDjT72meyg7Za-RYT1clzffXsd_zx6W&Mml?ubP4c ze|9?Z#hE0+PV{d@S2@j9f+4B+4Y-)tD)3aMD>0lBEp*2dU(k9VGp~}Fz6gUw+_xE{ zG@bv3$mT_|__QxPCb-T)Ep4^_6?d~3w4=Ng)w~jY_tF=PG~sK=V&+qQ+?Q@Kpt`%J zMS~s#qb%eU-{4VGj$p6bh660v1K#B z-E<)%O}#Im%^4-isFH>`6J>}Sil6$%zf>H>Ba}5)rQYbskD4x}nsLDl% z_JIqis~>;PxTzKXzllXg4b4=r|t0FNTrd^j~*XcNNY z`*Win)g3#y*4=%Ji~uAa!Db+ANkuQTgupiF6geMFVVwRxktwqV6Q;39oi!@#U`ZpX z(W7QSZSf{_ZKmSGSltn>Q!$|}m7S@A9Ix=NlUg*KAd^O#E%fYY!mKO(rUsx97Kp}l zcp|wRpPmd^5R!{ssT^{&k&ITB!1yJ}xB#yzC%9b;1SHn@11AUsmt{1!CLAC50NE^G zEzvu!;@nLyosC3h2z!}jPG89Kt#@Zeh_bfJMf1$6b>pvT%oT_5F$Dk6zZLw%v`r|o z-I;UX3jlfbnx6R8aFX4PXOkPD zq}^L=WXTNu9&dM7(`{7#op_5W--}66A0k05KoJ^;KiLlOIql3|w)9pm3x9ihM7S!q zHiFR|`+gViq2YE;^i0!0NI-K@ah2EV)%i0#oNJ)VGv9!nIjU{+1{YCQv`g;|=O5K2 zUQ7Y*UcnAQ#r?zy=UoFSFc&X>ob%EXTI0ju!|jm=Wr{^dyEi?aMX~i zVNK7eg$&`Wvw%!c-Md>mC`KlT$|?_MIlA+O^d;|$-sVrH>7(>EnG`j_>XtyH(mZl_EHA}iqTi|s#G(!I z{^50VU{ga@QsqwNMVTczb0T$_X^lpRk(S`PU6RhQD0;HfpR!-MH)Ar_0z2G}>+s0tMo@seRfavwbSvKi+nAQCi!k zO~8PPEpWHcvU#6PsA-Fi%tfthB;8R)NLeuyp$RY(N}~oCj)%SeXbrC{`%Kv~gSdVq z)?^h1E=~MijO`At;oPKCny~8HgnxGU(aVZtt5+HZ`P@#(Q`nEiolq+ceVi*z-ycSv z)98vy42lD8=M=rNu=9R`SW%9Xbm4W3eHbU;0kf;i-wQT10guW3&E4okkTHW&V4R0o zlSI)UQ0%Q9D@+Y&LsWWDbfRvE4|;++CXI}wu=aU0?r za#0nh^SSV_3BD>#1smXPUIsVgI5alZ2~wZO8TpctDl6c3*xISLDd1Ze(iM&+VBVn;;yz({}OJC!bEnKWVa)irV;{w^Ci!uq1H53IK| zTC2DIO*?`$!lpxK#-CyiRT{gO8~+lWA~kyvL#E#QxIlGMu#Q4yaj9c1M~;LgX5aX1 zQC=z_I>1}+tDYv&{na`sgtR5Mp)KkM;gDV{xDu?=1{#D(dSbLC_@ZBn2Ps=)qdKM# zGEv;vEIalQP($b;<|MQJ%O}GTSI|>{Kn#YI7F9g=oaqCKZL`7?em8F-l+A$NYW3sd z=?gX!1pbeFSE7|yO#q0jvK-=Le_|hNY~_l69+8<~Mrf3CQH=xm@-sT(v?R0V zwa|ws;>v9am{=^r6Vad8t&Tc2fm0+>YjZ0hyuzLUe{j(#P#!;*oI@CEp`^|M;R zn{Rf^bqI7SZ+l()9`XaX*}j#sCJttgE;?{wcUWggcJE@1m?^xplm4aQ^00wr@cZ0! ztDjceA!)6~yZC~`Q6NBkk+@Y~=!Hf|9*z$566xNLzcM2S`tdxlDFr8Cj=dU<+vDqU z&wqs5s|`nUrHh{5N}v`oV`RDN>o%yUC7)qwo4%@}<&YEKwkI8D)l7zI(SSi2M7)3EZPA+JK^44#)Mi2la zU;9?*V&~;W-e$^!Sho+0M;>Gz*0rp>;>aJ=`ILt^eeL0EmeixO-#9`NM0ukC8#xdw z0eFa>avT9enPk))8?^JqAuv&Md$owD1i%ikLJ8>4rhm0vo5?3Y0qld2?6?U?2#OOl zbnZT|rZrlMMh-JNRO(wERDf&O09=pI7j{1G6;^*Zhglmny{3&;nW0UNcZPi+?67_^ zPg1q9ovIh0>$I!r+S@-%+zj+1u&0Fw=>zL*PRbguhY9}yc1HfF!Uo6>ihtN&(O-ce z?v2)UgW|zf{~M2r7~X3XA@JfX>zHhV1>zPdKGrGZ;wdQY>39Z}OvaZK0U9W62l`wi7crIx6CLl@acz7m`Yc`NbgHoPaEK4jkK9NSZ*9G}W1QVmHNRKc9JH8Q zLk5(yWzV5wfU}c6BTRyrlM$Qmwfk`F-Ga!PIMdDQq8JOts0DctEO!&GwU`Mt(hgX2 z4yZ=WzH<%Z5|SjB->r|zdtrMc;CxR~K%>4;aB;aDu^A^P;cvv(u*Gb%pVh$jXvK3ygwHO zu(nizdGUOAV5~B|fL>*XkeX-EzOL*|ne8>CF=8Yt6Kmsx*1)w`L(8)CAMUtg3UZ@P zV=y30Dc5Vj(6jy$G`H58H{0{6;6jKF@TH@^ihyEDSd&?8heMyGIdC>eP85)zT4)yc zH*`xbkLd4OSD|7Q+=4Fed(XujGFHmpk*hI);L#IFq5iv;s!)dwH6su>=53 z<=mTfm}vyM&#L!~Rv!Zjs6$hzb*XlJEpS7)6$CBR?kpM|W%G^2Blks{uVc~zU!Jji z354);f;ULCl9~6lCitDtJJpW{Jf841U!For^HwpJF$1#73bY2Xx>F>P<%8~Xr*S)x2 z+hfv5w^?8DBu)H{Rc(t*@v;jICGGip?-lp$VerOB$qbx~%)ZDC@C|Zss~)h-G}((n zmoK#QxiF~a5RNe_Tqc3ov%q3?T{i+ZMIqa)krG@)lP&^x`Lf<{O(qBU7oP7;_{}Dl z@sk`0U&iDhBPq@;h2zmh43pbxJygxlJt~3-9(zMTI%ZCAE4DENnkV$75HEzx0;03i zCL~MWb^rdr^`uk%7%A|JSM8^;FDNfKB?f=zf}%>m7vaR3t*Bdl7}gUpX{mwlHVv$h zY}09{o#f-(v{hySs}bZBGrOvvS_w21TiJ({2@h@!an(s2C|!&@Z13&i4%Hq*&#;k{w|`+MUg+CB)J2HHuKEe6;;S$ret9pjlwcM%@vq=bXAdb+jZ=lI_z#+mwL=gvzVN2cH806xFsT=!mSUy zQ$CnyWGFC=kP8br76JFr3w9{Un{UsWpKQy#=kP`hD1pW8XFOKrN3wM^;0M+*t_?d- zKxp~D({~yX2{AnWU|8y`{QdHjW;o7?z2PTuHNs!W3SKJH`#M{;pQG!7mj#%GkCl$9 z@QEG1#{nvG!!j{c)^IZsDw^{0(nz1W2NIsfJ#z@gy5c+%w+p#Ax)HL#tH!G=A^9Av zi428_x0lfn;WLmx=$Ga(i3YIK*p;w2tvzpJ*;Vex4NrcbPo7nteen0k%RreT%UKC| zUTl;J{HCil$wb`lb>`b1DzEY#J?W1eUw`pIhj2ckUM|cbRq0L2EtV&Dw!U-ZXUg#S z4nu`-h&!8U=gtnfOZ5&MUcc35AXBzVa8(G!Y8DTMpU?-_+br9n$h=1ZrKMeZ+{MLL z!>ImBXrl;ka`JpiZx;q43ll|&5h1^nggv~E1jS(*@;Q?O=($q93%!r8@Fzs=(JT?% zSwROja{jq+i-=1q2(qGp!jR8KAtY@i0Y2H&g?$dt%LM}5x&S%%2{9Az5d0H%tu~px z(fW9k9jAj><>Y;o4=IAap>S4N3hw~R*_r~`@%^LnF5UKu@Ly7J>^Q>x`8WE+E z(xsWleS9rE^(u)u@$ZDZiEyA4MHy&YzW1tf$CrhFbTBk0~5!tM2047>PY2rQ! zzhK`Q-G|sd@68#YolHQyj)DrymOj)z3!BGVC_|qF%N0N4EfD;UyE)=NfD6NmV1E5t zp3esd6CIUZztl_#(wH5 zlXU)!B1CEY-~IPA1sG#OxWu76nDPGU6s}d}kx`p6h23toexNZC z$K2Q?lZmu4f?hTT?5r!jJ?l>nKK{1s4qwh)Sex>SR2SzmXHv`SJWE7Y>&hL7s;z6;*$87xOh~bN6>%emHN; zV#w?|K)7gaVl$2*-;LCuM>{{`TDp9_mD1%e{ft@ZmTOBGOgRYd9t0TPAOfMU`J$H9 z+a2dol`X!u#!RoSv?0{-h!Ton*@N)&x>adJX||z*N}|UB7DNrF!8y7V@=CXYlXPW^ zy<=i<+a3InzNdgJJ)>9$OXexlBV0AT&O^%V@p;<)GJ3IFNQw#?tl-ux3nu8xRm+G{ zio3?$zyNbybP+xvbfDW&G8N(+HX2=y#aqJsRVLbPh~xQ;MO~(*)!ODq4mvR~pw)PW zEVpIaa+{S{1!FF9L5+$Di)(sPy=bJL-PDRtAUeFuFH%WnkxHoFsz2IaN*e}jbZBly zzibWhT3Au>8trl64tgV39A#` zuoVAnIm_@~)o0}@FHA|>rfGJ+sushqd~$;ub|Itwip>4W{C(7tuAB-yy)IZG-zwJX z24N>GJMWD6wQagTFOGlrV_#uJ`u(1?{(Mj*auSjth%?xz58e^iz8AiDIfn3oHA;X) z@kZ4}3F>0AufIcrgxX%er1ky^n(4jP2{IoFqTk+>tH5(*1eLRpo0v_M@odsJ%@EM; zjO~D5ix>@}&NHm;yxy7G=QX5E`HUpl&Q>LH1k8OtAVH)2Rn!T=`1p7DU~g_0$`p0Z z6yoW|!}d7uP4?V%DLm8r_~o%DGa_9WB&Xe<)Ri)A|*x33^VM9ksI zjXp?zFxOeFc%4wB6VYH6Kd;MRpQ4E78l?(~f}jDU6HN*9Sdww_At>XIPu@VC(sD&Y zR_%&blewzgyvmkpvB#_)FS+^w8Bg5%pRj~}hf++(y`+U$q5M65r!ITmTZ{muoCOc# zcAjk@OX*8Sa)k|<(RWi4k)e}KU$pC;8w{;@`e*@G#liW7l_3jOHx(aq#KW&;cnz%) zz|)Lo5Cdr8)UzI7P~K)VVk~vT4BKzPl$Uy2#^+?ra_6S1We07~TaQMprJLDLb^gc7 zEz~w=>S#E2eF%r^1(>cir-hpr`x>G`ganv|1o#p#fe>T5OG(+zHWPM_a+P&Lov=&DKZ&54t6pIk8%W&5@WD^K8^%`Y#9q zQrq)L;`*Bx@_n!5va}{<8*uci&h8A?&!ZFgoU1ZYxJkuGsR2LCkk8&!fCB(C=Ysrz zKqou(a}^t%cz%iR+0-k)npCWlNS6#0YJ6Gs)_j!Y5rl1vQumW2rqRctFVCMqWt)N< zPTL-4%P6e0k8#O^wCbX+4sp>!(%7bDW%<;`^Ta0~P@21PJ~1H7zr+pNA6}M&A-{v8 zVDXd%i=x~%KrDioFU-%Aw)Wtxf`Fq>q?QDGu*hnRU3LZ|^#~D(Cf#qm5|A@$9OQ`~xI2$Qa6|TC z*y_Xoh(U(#gA&SKE<{rMh|FeD8CRG4Uara}*+mClx;Lc5)8N^0%MdHs<^7c|oYjSI zUWR9vd^WayAfbK=qLN?Jx6ML8pya{JP}6~;e*7D?_^S4eAUm!fNX9b;G3cN-o#B>D z^#X4(+yVEJ7VsNwyDyXEw?r#{)CC8IWv%FY1`{&n#1TN9Dxi8s0JUUo0B(hBcS@U|USFtpiu}M}0xeZ$Q0n_|sUqRj_SFnKK<{AY2ezw=6 ziW$`&U6MdkTfPG{zE!Ha16gDBfPP2-tZ4B2v-Mzmmya>N`)=Q&b?&)Af3zP(vZzS8 z`F#}?ytiFEZht;82 zrQ2HU5LU~+nXh4i2gLgC9gnzqp(jI%zIMQ)~G}*)w66Sf6V6_e}y?w zIySeiqkvIkp|@gnUR3el3w{`m)%6z)`iA(LPsl2ih)(>|#Os?U`2&PHMIK;17BzFc%D zfs|>;!_9(`qi@eovWX(qNRzb-410CM?QXur-5@4sc${=pDf?~#FoM^#?za84^oL5nA9PpA>Q@^d z{|B~3hz%Ul#pV>Yv?X9Wp?fx7|6bg36oRV>It2-g4<4|6UQH=w$w)t$alclWSX>0P zvf2c8Owt_poci96&JbTLiW&a9KImCDlCHvz(VWwtllz>jg(!8qlhOUk)wep`B3#%) z@DKkL+Ofl5CovfGsOK#&N>FQ`&-eP2A&pgNdfrzF#R|IxJT-#LC;NJ3+u7{8WyWv1 zhL*ovzcQcPs(HTqCg!yTP^dXZvJPC|w-{L#cwi1;Y>TpM0P|~#oFXiE?J}|*rJCXj zh>hu`8}FsHmi}jZR6WepU%!Ctp}h;OR`Ef*w);l6e1}fO^I=!Z4bOC*jm~{A+oJ%P zXGo1(78S|1?1g1~)dAc7b`Kh0N0=1U3~k)2s1jRo_z7njCY z!(ASaOUsK~b3ZieXmr?-rNLRyFq}Lv9L~p}>6!x67ez;h0yjltoGy7JbopVK{z2Dr z-$1vOZ(km&3}#3Ej?l|=`q`z)MJ9^?$a?hcN7m{1kkh=5lJb61+mPS0*7E$AP1WxQ z@-Nfv;;?vqBK)!GDMnF5cUJ3Z3AHdcmg@*YVIYHzp#~XJTx0&PhYd1)nbT@-ep@0l zDc>r!TM1Z#@?6KKh6ZKmnY^^$@euTppZYS4gIQC!k*Pf&Y`_xX!Sry0p}aAw0mB3G zpkivd7}Whh>r#BNo{msFJWu(MQWRkwIDc7-Hcnq)JABvQ)t7f|(CDfQpTmWp?rLFh zR>#+Gm59c;ka+G-u&$3YaB>?}Ll_p(r{pjDm=kl@pT` zA_-6GT~+1?MDhz2Qc(>)u(%qVR<7PKP?p-m*WmtMzfmZQ{*r}HKgEbZ(#dcS1&Ch) zuO2Hp%8iRvXFw@;4tu5XpBf?CD+$NnWY!A_l4x=1S%3P0dWYj&KS@lCxqQxQh@5DsAPThQCkJ^f^8@X^pQvj`z+O+EQx-y!= zAeu~6`Rt_IwzT7)V|UrhMDT71KJ}S5$%pu~{!L)mT|m?MYlzP7q~|?(=L3?|+Om6< za`88Bm(7TH*Lv$p_4VD)o5c5dzFJSZ*qKx>Xjti)L1=Yj_Y;dPKdXg?;p%TWj~OV9 zse~?#w`-&gS;7BWgJDfcjj%~;fIshoCE~Z_Xpf8l%;Ab_Z_UgdqPd_tGG2HP1Kt_nSx}qUz z1@5&9T&6&Vel{U&#d4GFo!RD;nI1GHcKru5HwdU~`>K}6V6-#(B$%4xgy3-5L76JfJM=IAHL*u3@_kDZMq%d3AD8~;Wp4z){WmbZx6O@b01)1hB)gp(bn zt9-S&#PT_lY;(dOs|r)T_o!pymZ|0(Ftrj_LCb*TPZ|j_Z|lB-H<>p4p#&I<#whjA zHJH-Z*rMTv(DCbbIB{Q>B{#k>+aAx1dJqKyt{mn`{)8Lw*I||sI^i8?{&sb-JXbO5 z`0H%ZVkU(vQmL5~L^)Raz+rr)dEKosfGS&53G7~(B5<27Br z_}i2lbNt;Q@tkkP!3y?Y+lNiZxR2dMVyaJ$%L;qZt~hDA)o_y~@FIzL_Z3H1Qa1xi z=1000&paII;oeM-4siM#ON)wk4ceFHE2)hC5>o)l%588nngTS*;e!qe2;H`b>^_n=2}f}U*0O#)#+*T|FE_d~{;uz1KpJ7)~`98dtw3j21SATF<8 z9h<`t!%mAFr@%LaA?shmZF#_|f1mv8Pd~h|Nqqk;=(mZ(hpl3w(00LHJ6LC>5z^>R z#`#h>!1KY@!c=g;K%P1uohb+8=ws+adD zVYvZ3Bv4mtGP7)ER-lFer;;xlYF*?9>;=^g6$3}-6nO$aSmr`Ho13G;7QMQ>&ERv@ zXa5XyYgveQ$|{lV6;vJ;xf~42PE#Pf=r!D_DJ%adI*Y`{fgp+=NDDD7EoSDOn9;K6 z^igJ;i5c1yj-MS~Ck4o&yjMUR)y$X~ILWjP;a zbR7IYtOS57ZY8!)AOkoSgBCa4ViI~+kWhf?k90M|md5NRe&knel<{KFYa+VPhvAw8 zNQ@KV&kft5AD`TEcBV}8DbqmWG39!o&Le8UMJ_)R-919jc^!Txr=2BLhOhn2zCV=r{B|(AY1&z0c0WjIH00$nVXZQr zk*)JHzzy0vX*~PHY9*;luTy_;FiI4)mNIJA%#e?GbHAuw6CP?*eBNHgzFBS10GW2P zH8nKj=Wwe^tukj~$!?|O+o%%k{OlOY*UYxB#62V>V9Rbv}gq!v&-03L08=F+9|K~YOPfPLe=K?;10yt*dLY8|m!+sdF@c@^g zv};OlfvK*X`t;q0a=(BxvbUfLLf$ZL)-7pjqs)_BD#v_j-HX2xWu>enY*98$k=a4a z&ly}{vMsIA_%?JgQ<&n{K)Zn-uB=efqToQ`FLzPexykMz;T6lDokC{qwLBoeU5MS6CIX>kO~F06@8#I0xrfs}Ed}srk`2 zR9?MRhyE~2&acu zTm9o!J!#zv>$fe&O5c9eDm*81p1y$zp!t}WzpdP1P*+ne>#{i`s^3Z~bR|^uvtuPm z`z%^Z*&oq)X8XM80=$Wh(1^}Zm6|H`SB^^j<;sR7zeq(PB$uTS;mlj;=KADIIBs8v zOf^*?=F_}83yiWCbwj6t6~^HOlUTr$R8w#?^xgxLaFtNhhX4SA0_*wsM6AtN98sO# z4i3Kxp4ZqWFB15`1V%lCqo!MDv+~!@=NK-TG1u!)phPq%z!G;+j<_NuxnY`Cg~o2h zRHzB9dCCMwB(=l2h52xHGgy*GnY_wgMdU^ivK>bjT;$`%!x2YFw8%K)qDGNrJOvVH#mKS030dsP34QBIpW9-a@6BT>lvmho3~EE48gps;-7vz&OpWcDL!i$Q?3VL?F_Meu7RE4K z=KynvGD_kOw8mj&&(Sc~SsoE}))SrlopQ=pMR97VaNZ2i=bgL1hdgwC;OqgeO-e_q zuaC9;p7(w>-1hqeZy+y~+>q1dIi(8U2Wi20;(7eJ4oE)cJ^{l*KuNMd#1*8it10b| zyN33&GCom=eQx_%2|d8HRHDcZ%`-GCxF}yS^iul#N~zLdNq$363Yi_~!jJo1ZPeIy zS~EShlF$wzl>%5N|HIDc{hPV<1TP~kC9H>dXDdpvsTjH}Bs0NYsK5O!3^mi*^oO@T z*V7X~AAF`GXGv8N#;-bm!3^7o->~9Ly%T8dtn~Rd&3)%VP=aYIE-=$jlr%hNQmjyB zNv#HRbknoBBwlBZ)xC0eX~l=Y?41TDuf$|lxUcWn!l@|0(5p_(yPrIQY^$GRdS0o| z*@(Yd*4#9fU#Bkqzke`Q<{fdj&}aFF=yZ5>D6YGt0OAhA)vIwuZ#s!S&dZEX!+GB& z^Y%Tme!7$;iEs|d2zm;hu=S9Q!=&0d`}Rs6|BCD73r#ww!@GVH*=eQ^$T)oBpeW8M7Y$a+0F{ zZw(up!lu!IcqJWHsxYOE9pM?O1a)CgtIuGjT{`iL@voV}4*g+HCny=<j9ly4`3tbM%Iyr+F-yhq( z@IGq`t?!cn5Uf&t2ik)K(H%xh3`(->wlxm+vdVHZ-$$H{`<`KyIP}|d7ng=}RSued zHuY;z>_=vBy$$2}B%8I6-uC9fc5ZofoKQr3@tP)%1FJaT9hr|O?I?c}<!_cKDjxwG|x2v}}XJ!;pcfu@YE=8$hETHiV z%JL$NgptdxddtBwGME>|ec^KDY5auS`jg+xtM5^7Omo=1n$T-3s{>L4)W#PfFutJf zG$A+Xy5E?5Py-U?e244H`zqwb8&VuX4Pa56gy~$FMym_~~*7j1P+Ux;j6GzWAl0 z9d-p{36FJdWYO)y0X)cZb}BwHW4HZ15OkrqkU*WsV_$ct9;`3@H0B|`!Ktp70hYvv zSIWxr;Q^qHx#l2@pOibU$CIA#`2AJaTXIdw+q3TL^p5n5$4#4G60UTpgK|$`4ZyJ+(|f&6aWaGa2q;7_@kib9JaAtuOt+e^zP1IO z-MH>rNCirb(vOd7a9B8C+- zkeJLk24-Is?oZ{Xg|#Pt2=o8mYsPutfGXOJo=ko~UJ} zbb~DV^FAGU=dr9a6%4x)_)Z9jSscI-f~}w71ys`_Oo&tDq>{6I=lPeP+ zt2cc=#pK06caV8hLmWf=6qfsl`Xt&@-pnK%JUSO9ab=AmCF(aBIhY_??`UT|9J5}4 zaOiis7~b$d$;4K-w?*koOGj8gpe+HrJQ zp{qvD?sLvp3g@86pYFP9lyxm>42u`EKpOkVm8u0yQT9<=7U5+hf(p5o6CAUEsqU+c zi2mIxTHiFcMNyO^!HeL*1eJtS{@hm*wq+geD>{EyNbh69G7I-)h(fNuF5QhH0i=AtaMiMgnx(OQV9mB2Dl`59&j{$Vx z!jSl_D>aYqFum}soE=4vUN_zmv#UOE8Ef&dsojn;BXgckpEIrckeilrTJN;eHMZeB zkub5o^r-`OR%YzFuc9XG^-TVEJn{5hx#A;GuZT|SPKdp!Y?Oo+EyavkQC-4#A2S%i zKat*Hk^^jG`v2}ri8P)1+>EDc#?LQaSzIY1``G^*?OQy)JUoe#)*D!vD>jlItJS_N z=kHNe@0-X2dB@tsN8LSLq%;s<)y&mVUd=YFu;fPZB27oHdk?aQbVtOR0F4r-mq_}> zH|mU+0vXTV5FQ9+h$E!8$24#6vl4FKX*NU?+`h%c?G{&`sfstF5|mog;+RT`{QoJX z5B)@r+yjP2GPH}kskiyxc2Z(oT?D?CWM0`HntHyM92=69%+3)i<;%bjhFbK3ez4qn zMbFA%!xbMe%`dA2sIzc;j%WRErMM>d6Po7>hXeIFl2H;ahk(KyZM)#5UjG_!eS;5$ zC@lRI*w3Kh_Q0Il=SW-6;m^a2v><3nZ7w;2mdT&S&OD=gGhyq=?qIcMI~YYRs9?Sk zPka2;VBb1iS)diR)?Rc6LL;j`$DT&x={kjvNelA>A*cl8oK?`bJ8DsyuPGINMrwPK zg1lOxWB{xomGyGn1}uiSn*+!A$=GK|0KIW*=Bp4($S7|AS^DKTt_OTEU(D;+572Gm zB^%jQM*euymH$>=QNub(&d0h%7U~0Kj6DDNoX}J~U=NaJguJ!b9ON_?wBC7JCu7P! zJS4$An`H7Dt1qN)I}?qb&wMk*+vc)xk|V9p(uVk7mm%?qyM}w0{38SwIk;i=|APes zOjKcwcR>F!b+#cZ)pY*#jm0`RV=FMz`_ly}<$Sy#`ejC|l65-<6;tBV=L>&aPH5 zbewz%j)a;upO<{YAYDlD5B_RNpvWkx3f-}7JuW!kqq=TA)Oa0=K=~_EKT9+tx6O=` z%C@`b{%@HIhWok=304ujY~V11R}rc>vZc-%Vjj2Q+F$tNn>??=U=?nH;eJ1WQCqz= zg%Ou6?G(YU-*4NFz&!F6Cn{z0^K0Bkb@;M%1ST_MoIrJEh*0#T!3Zkvb$2l@Uz$!j z7(8{5;xbg$$j&j&rMUIGepff3K5Jz50V1+%R(B#!-0n^nGw%U1#oa!97@Wuo=qO+z z$=Uy3iVWI_bw>R(5b(?(9+ptEQ{QKvrkSq(cLTLydiUWvlvvX#@f9@WOYSt*6+i38 z4F}b2l(!9}{_uNV*J$^fkGb2~)N2r5Z~xleuT}65Y5bDU&h`vXdZp!%?iZYABHXJ; zxJ76hhg(0CB>|t;lwEa4Qd8Z8Xlz4)y6WB+ws;T{(NW}K{T16_e^!q0h}Tb;z3-Oh zQp*QJC^h>sV#_^sRdUZ|ZC2$|k{DaV!%oQY`lUB=!S70Tf87M&;g;e+<7E$TK!Ol6 z_)1Kh)^W0rqk96+^~f1C^TvF4p4-MoB22X&rC9QFi~Y;Yr7o`~k3KbxYfT@o@ygWh z>Z}y?Bq-dh6O}iTp-*m@XxlP&0xMaU;SbjTy&Dg9(yH|f)amA|zL6Nhw{-Its)_<* zu_A%5{IYKU;zXQK9Zwi6)6+_e#Nn2<^OJwJMnQiQWQTfpe~5OgU!+P^>Y@i+ep6rk zhBA!3DlB3b$Q8&^wuXJ60<~Pvd<;Zbt2~ye<=K239*inS%s`-O*u4Hk+5k10S?NBN zd_1ii3vC0bCal}ArAs+^Mm0P%j;1^`mpX=iKbq@I}nKl((Alsy6QLrk;ze@=1&-ejYb|%|fY@@^j`- zpDx>!PeT4$zgjTy>$vGJ6XA`$qaRf#wT5vkJyf&MytM&jSzf9;)Mb*kS53|bdM~gk z2V*)~z{RbDiUaMW3{UFnuSun_pbN<*|KfNoPC>p&@4^5Uu?PMU0c(IOO8E3sn;5ET z55XQJLC(%!a`cQ0Zt2!b9%fUPgPp^GRY{Y{@w*u1R>r1S45NdyN>N7)$#V~=Vjm{g z%jd(8a(&BlA6b*iPA{9Pa&skeKNa>*t%u^(O~d(qf5Dsn9>jTg6^ zBq&tnC8BUrA$AxeoYn_!C^l^l=i+Yo;UVueS6$_;a$Rlbr z4h-RN4v{tu;#-N!+d>@bntCuh><@dU`|i5+M9LRj{K)cN`tvqKGL3e$J6_4{&U)2J z9mF2w3}w|O2ZiX)qvpog6`7>+%jit;D>G)^_msARUnzj?GZJLGdZByv^N({HWD;rc zNJX7AA{)lg2Tmxamum-;9`0vzBM1 z?V`DJRqZk2r;d)xcN~7A9vVJP?G)wbZe!{^0nxlDe9d@~s(s%5piSEdaio;#De}{a zGv4rj1`$_o-pYcEZhaBMPHouV!`S?_D zTus);_CG9gOxaZm@h_S^)S9pevE8|awvi1bqN(96w>aA_ya3MS+jO5g!;>DSUFZXV z0MJ$PBv50PpSQf6{C9`X?_6LdbI}4g+p{zl`8Vy36iO&;(;3T=bguiIb-e`Qo>}nC zsG4m(?!W7$P*K-hA~lAmgCBh)1xWToeZbv3TNXhmgTB6GSC{0QYs6Hek*K`+7GjCZ z&uY~>&GJX}C~Jf!=Mdb7&|}RRL@6aYyzTQvR3^nTriS=6Qf43FE}J%Ba&=cH`~S{U zuSP)g=5lM?xA~;mN4K{FzHj4x2i@{*Fck`AfeR?1w}xITpQO6tEg&e1u&Mv!vZR{G z9nV#MWH(C4H_#ZVqc*Q}x`=|8IE&h477YO<-T2=Ad0sjf>YjJKic9Pm+g^6 zEYTa1)|^Z}Ut<^QS8CPTCORVjyXTYfD9QhRO*M$a8F?2Rl3Tm95SQ|EsuCx?(~pj3uj(at+Ar;1BsKBLeOJE9PVtkziJU}y z%aMe|Has^jlY2eI!ZtJ|TLVKH0M_ z`)`oXk_^}AR_F&SQ1l1r0+(_F%9}#7{C}EGII+F@KTJwwoB}GIdJQtguCM7CD?_XV zK1b%cSKFSoZucO+88JFlonK8zoH&Z<7qwd+x7(h<>PjEQrcY$ox0}q2685;4^NTy5 z6jRzD^)tNNyD0|9x{WbpW~KlCUaePr1~s=t<}`{OnGRmVR0xF(Ao5<(*>b|bZt1DcjN%M9`UKj!sJ_txln{`nz2k(=M3GhY$#BT?S=g9iip&W(#Y&+;)P^8Hm@K@0?Bhbv_=9cJL}Jxz{UTBfBqFN*7^!?!-05 zr~N$oHCooO$^z?C098zvGnXRM@py2Ar{gE*$3UwOaH)Y97g;?>I<_3l*>Yi?)m#kF z7!I4C_vM$ssSv zLRb*(VrUj!7j4(tHj>S#Y8ZES2oE^ZC_dLwWo0%BtmVZ3x(qbR9jfW(+aT^4vnkVl zT`v-Q#5!z*{u-HoV&`-Zj149n!qmDp!};mtUCM~svC-%Mo}&HCSxka6l+|I&lC~^7q;JQRpu9>8`@U9;2Jz`<$G%lFt%-Rbwi1#UiD~hB{+1@wYUBdA3kN z)1_7SOSNn2Bq&HKRr_)Ke6i)6$;10J^fojoXjQqMh!XqLU_fH;7W+X?c@X*Fs+U>}wOeOh0l|B(-=NgTv`Vk`={=wakn055Vx zOSL{Fj83lquh+~ZLQnSnE6ir$ih9zD7D+r5k^b*Ftn`o{n*FjgjCbwhkp)GLkeE#z;8zUj2t5S=Qm-kfjW&(8PfOUr&oalLze@O9X;7q%s3uyKuriLkoKiuC^KddY&U~#Li0KME`~9KIsAGqk zF`DgFYz_lHI6O^X6>lV`d9%v9>YtC5KZVo7O>F9_8J9k+r7B6nx8Dmx)t3(OpgUhQ z;WU+kJ7CSX-^xa5L2-VN?lwipOg$n*%6On&JjTJ0eU$1~{x(xcXy?=RNWqwQUaNb@ z!>-gO)=TG<$(V6pq2yOuy<+dJ>T?ZN0gS!otHk^cI#*E6bRt!DlPvo5%D#A!8Y*748>VcNHJ4>)UQA1q&+VtbU2}wz;*@ zjz_(%Dg67NAX2efevY(Z0UaF9=lfJjXcuxjf1>dNyOYJokO@!=XG}FrPE`m{ww`{# z3{arO>)2ELz%-0(=iAB4Re!7&H60K90agIRB$pcS^_B{=h}r0FbP>%T{bg>BEPkj* zv3a>M_7oiZl5MZ_w=Sc%Ymn}Itm&sIfj`Me55)hdW=&LwmH#r%d}MdG*$RknPEH2; z;gED+>;$iv-u!(6p4qzfp6RDMx88GLf%z;s+Mk?W_X(ED7!eL7`eaTEocwppH2Z)<>#l|HQvb5r(}4K(*0oZ`%POUKs~<#dCklTG|RBC zpmwt`{{Gl`p7t<+w9@(i_|=PaMuYlLUtE3jop_?`uKd9zi~Wb*@!6gQ?R_ zWBRbBPlF1(@nd?@-`#HfdPG3Rw%Bs^IP`3w+zYT}83+*C`{y4--3VldU3aglu`(Je zVdP|stAmoT@ieDDP@?>eR^N2)Z*4QVv!Y9Y$)`eQ%j&b~B#z#e8zE+ig6+V_2} z`@H(&YJB{SLf;Rc|1S>B(N?7>YwP*6bbY@h2an`Po0W(k3GQn?%)Z3jpeJo?!-f{t z%f?BF-12gqewtJNXn@1>`YSit5QHJ5K#!Z@-@qSVUAPpl2dOA4DF%HD5VsF7NY5XV zBm5%ls+s?e5{11b6%3c~bo!{_i8ZNK_^Sj?>KFs_2w zx0@z?dFVa@=r_3|q2?bbr~_L7n91-#s|!WAuNmM7s8cxpOt3{W>q=>B_{Qxb8*rh= z_IBL7S>$s>_g4ROPkWY_4)ByEH7AyzvUlk*9#NiC$NM|~%-6iqcLu7QgQAfiSqJ(| zz=!d(c*GO3hp^1tD^?jM@<$8Pm;VGO3F=4sj@Tc~iqVs$yZ1u~&+yFrd|I++`ivIK z*+ra-|8fJ#2+LVG#kQVH``vs9eb@+=R%g(ONRoxQy!;@+;Qcs!NJj({`?b-fkOTRK3{{!t=}Y7=2q$uhBWSNrtHAS zbgR1>6}mK%3Q-^=zc4Mzr5qQ^{-{GI)`fZCpQF(CMb(i*wyzNgz%9d@8Gk^d!OoLv=pC5gd1B-y2yucFmaP>0LHP|S1O~Q7eyh0{xnezMm&bpS4(`=8|5PRGp;$Mj|z-UJh-n!n%PAw}9vENBIU)*o) zDoy|g%MX=mk>hUqMkj?^>~dWLARIv(uo>|J}{ z#OMu&-S%CS!s7F|hWAw5fBwlWN}(E*0RlJ<+VRdJbaDhM8Q&eAzv=KgYB!hX{GEO< z8?66l<`msa;rsCpBWaqTumT^%1Vu+fVNdWr9wVW{8NUKY$}Czzo+^@A+pEcgK^crl z@bcS*ffUx_;@Rj6$|bBdQRr^)F$koMvq=ulX7Ysar!_NpYVKWL5z>?0)1~TQ-yrVt zhNN2^Gjz~ckcEfF028b>X+hvh02RBiF&eoc{XuiLkLRCZR8CB3N9aPT!89=&>Wz=5 zzln;5#%+GMR%ME#2u$W<@c%AEUuU7dA-{f)0c*SwBMVU^eZ~0N5(s|T>(pSJqMQ)l zF2u4x|9c$2T|yM%wAbqY%pe96C?$A8L=v-lL{h+#VWm1pUDhLwVHIMUA>YSzKp~*t=P}7el zIX%^MN)#7Np3V6CD4*_A_5JNVcX=k0g-6RoHPdInibEa=Z|VW?lQUKSDnK0S+9L|NaQfme)O8XF{C5t#l8MlX6oeZDGL(^m>$lF4D>{7|w zh@c|AyObm!g__YBSLARVzgdt!hQ~Hzh%C4B6XvctfqBUqqO_PKDN(XO-g%OPJpcEJq-dHR$=7h*0R)euI==w8V;Q7;=8KMvF6y?uTOq}j zS4JdA(#0J?sI=w4*m;w$Z!eIMiv)c?CAYQ>_(aAu64g(`STkSutuYWgm91b!zX%H#&A#ATymXS*079p~I2K{(hR zQmU#JECGspiZ6n7Rr!LnWxX#Nkf6{I;Mp$7=y{uhQmx^}VGMsxItPDMn}4}34-;1J ztL*JVG4glrlveu3jd>5eW%KI@u`4qKaG=>=Y3Iv!U*vuF3`h;?SMdYihn&SMV&Lv#<&})0C>_E&&YWBsvy0M#V&j=+Bu@9M*j(>6s z8(ygP1-l$u0Z>fvL$Ys`a^WG|M!VdA|ts zI9)mFf6!IRzakfYad#)`K-@Uq$&p#|k+~lG%8S^yX#nTSn4XdLcST%#%@e=$im#3v zvv#hma@bWQP(w@eK;+RGC6cqTcVbD2OE)V3DJ zCYRt5_K>y8o(v{?SCJy#NNeWBYRKN^VW^+jC^V*6+KVL^MD!INHl0ih z6uq{u=VrwZ#meL!6Abo%VzOKd+M~0?!H$H zQ=6DjmYl(rA9Y1|HD3U4$p$+wny}`uz)}2ungcFY6BiLUC! z8&Nk;MW$dceWkuD0B#UDVP7Nsb@|rZ(;Sc?9N$`0{>U`0>C~=Ya$vB+FLDfoHn|IG zO6gDF|5!*Ux^XLmp=73=XAhp|c?JJB^T6~y;wnmuWG2t$o$l-O$g1dm43a#h>awW-RZfy zy-u^mO(b*y%OqOx*%0lXDAe`2HU){!<9C!DocdTX$?*kId7qgWy9M!RhQOfK&_Orx|Y^y?$hPU z@^{eG#|1YPN|ZAPYfGmWR2p$ch!Y2834A^+FC9qy+tya_!ck;wK^Oc!>k9yMmvy3n z#1a}u4aMseK%XvB2)AURPs^M$M}ai7i#6Hv-$*0s$Ov~W4wqBh!tBNAIKRa3^uPCn zra^E^(Ti3&U*rGnhEPe- zx4F{x)?R*S48vu4>S)p{*z9-%>VP553HP9odDW%(&GJLO6WUae^cx{{+o6u|lZW2F z+>5L5#93GS;(*aF%id$OurzrRx_n$GJo+x$j8ESe+E6G6m(er6Gh(~Dl&S0y^P1Wg zcF-wbUqjJ4=0MbJ9{wlZ5f}T4({@D^F)lx<3q~c=1Xs~IumVf+Ua7CFwCT8~wtkfMh>&^b=M|WZ zFKvEy9CV@soz2%9r3%-i^0Aqp)Z5fA8!oQ_cC)M~ma>k%3@*6ZdG{E>Ei_}Ov@k?N z8IQj+SRcqyt3Kk{Dx{8Fwa|Bd#Ka!?SWF1qloeMcozV&Y!oWbIQYLBToJ4RUXt8xv zW)5CulS87aO`q@Qi|WghhF!hb0p=x^M!H`**nhuzY)!_9q&rQtV70^y6TWxKO2YUV{jVx9+FG}A%RbMvCdnNrcCezb6Dv+%#&GHgsn(#G@)hnu zK;I&C;l%0Qv8N~*UL6)9=r&gidD2qJDjRQ5Ju3ByDy>xD?iS=5-2b;A^c71n)9Fi4 z@0>Y$oc9&}2&=rj$Dv2m%OvfI%w%~Yh@Z3t>6G<3vsLWVbwP=|`o{&@`W9Mc-?YAZ z3#~*mN;Fm9jdLJz&yv3}&%f^wHxU_)PC4tAzyJGrpOG6}Sq^0p{T^s~FQ?s6rQyCR zKZMy)9wqq=E9(m`WxzI~Ge4_(FF>-3GFu(Ca;iwEV6^@q-Bg!aGbhEbNO<9k7GtA} z9d>-A&}pj@JDY6BM<&j6$HtRYUrT=6qsi)Y1>AYaC&xFe=5=!!uOCyI?ZVql2`dxo#NiB@i<^`>MI6XE|7S{E+N*7QLVCib9Q4iGYtDhCn0I)RARPc#E27sBy1)+Bpc*%GDVc|b7ajgN)ZHW@#Hi;o{e|d7 zFZckG;>0%vEf%~fA*|4DZp2E1=lqrs5XZvBakky{GqYWRk~GX$hjWy00qeuN)FdI zz4`(1GmLFrvwaWx)_yuYGHy%h9|nbx^mjzd*X{+L@08YHnW*n_O$I8=*-8mh@NRiy5f3jqOlzuq$dN zmcI*?5X{A7nO3VS&%3n8kz)nOT2`T-)oC(Rp_#P1%?0A- zPGEGJw;}MlZUksJn3^?v9g$!$I`CwbrmfuM&>M^f#Bd!fnQX}_H0pJ~G5WBuCnOrc zvaFDCjdde4p@-_d3n9F-q+(o5tBhx124TREL4BzuaDknC3tB2R*t^>hRfx< zHEuK_thm0yCi=S!%bTOwIuG^$?)i&*e-9#AM3uf?&Txw}LrC%`mz^lx%um~|uIQc& zU@Ho%l%gm;62HEOn~9y4VRzJV2$x11;z{o-RvHhnS@~hf;+uH$YSh)^KR0SJPF5+C zezj19zx2KapF8>7oevk@&nBXtx92d8)L@>{?WW`yFgt4I-LQW(=I`W5i{n3Q_z03- z_2hBv>%JB<(L_BID3~KOCz6t#Q8R{Kksy%1YRu{eMU&|9s{W9o-ayt9hOi~_M#*z4aXL?uid56X1F<|0tI2rhpTQLRy^YlU@-7asz>XC;p zDz8yG^bLf)jE(XX32yr}(jfi0k#M1s1fG_xY@*BxwSj-6$e28)-YE!^;VBh>oX*cjflO7xUZB^Ek0XqTn4R2S9JL774`VOLqBTAXI#R$R4|+ESrG};D zL6bZ{y9a0u1g*;%gXAi9I9cInV;l(I_%OULR_r$Vb%t+Xnumd*o7UgENX4%BsU%=K zU-TeIm60z7`Mc;5QBV|>ln;dMfP+F<23nBZJFK%J?sC=1tpY|{FzeLALL+@n=-YnxQELWa!dJ#8 z)`$t@y1xq@wd=#<_g7jUtzjA~gI=|69sn_mGaayCz$4zc9|-KY>yoQ5nRql3LSkQ` z6mqEahFMV46_vW0i5!Dt)-EZoz}-gu%_9jc6+(Xe4uytoACM)$;wY)givdYFk~`a} zhiXoaU(x{7_~`O&2~jGvcjHZOB!uq^8r2&t*Cy2f7}%R1NZSBTxa*S?Dw9zR_Dks9`SJ@UH)pcx)mOp-ak z2x3`Q4M@Hq#G+;ZvSnH3)%Mneor6IBmZ$~-fM1?h3BnWFtZSrUim;g$xIQH)rn`X( zETB|0NwFq46gg%UpwVQURF&s5>($#JeTw(kT-)U&jt_Ecq4&Vt-dtIC z1iqwe@%8Q;T8yi(f`A=nb|^t_c{J3-zArs@?}~zsG=};Qgx=tSV+q15EGwu7Fr5M=W|)*3P6_x*r*_gO}unC zcHF*hBuLvz=s^51o&UjKAI^{i_Y1!DdfpUiY`23%usbHOLoBGc-P1q2;eWXmLbaKe zl$GA{E>_HuTx44z^LMz$yORM`x zd2(wA(_fc-_JSIRccZ!{$;gTnfm|QBXdN(ZoX#S}Zkt+(n%6haQQy2=?c}M!L70Q{ zIlc5jo9Vca*ZBYeJl-}3Kru6Mpqzs_h#@++e5`Zv8>{%w!=fAW4W4*CS1e6i=1b3{ zHnV5D)J!gKHv1iRvK6k~yC0ENd3lA)J}W;LaECGSPmH5F#*gzbd#)BT2a4AkA)m-eC(vlDh`3X(L$myLNA$45@3EuvXZ$4 zJbYjq`dOgQO!U$7&irfLUDO&VEA08?S7l`B@iEH&1j3imcde~p91Jnc7LfbOfgMo8 z@2lL^*3xrcb=Hs^BBmqLh>pau%xc0%CH-;fO@9$OyNK_KuDY)y+(~-+@2Ejj5LN-$ zK3o0UdA>pP#lWf&_J(=!eEvhbnDG`(`x~>N(_LSJb5>Sd4`!^FAHcZa81Iz^syNju zxH}8MiKI`5Y7u|c7b-lT({c!N&+|*=1Xp!+kRUcwX~RIR!xY!bVa0a%76us?dK7=< zec8r^eIy0fbXCCs|DG?LV)rT+ZP$tD#&gs3>+=i~w5L6>YyFCDsLmSY3YV{ijzkJ3 z`=gqdx=FL18YpG+g{hwD`C$4e@0?FI8ElTig>p!4idib40ctjG1<`Ue8QoZSsOKDWNpK_9g z)jD9M#_|Yw{-lb}YfpCl3Q`L{vZVw~Uw5jgt!dh2b_c712DG2o2G1ZdLZp|)lR!V< z2GG%XF4S34kB|Q{XvB!JzrQE-5*_+g$z^qUC z2`-L)+GBrCoS}yX2W>xAm-SIpE3=%;mU^Y|q5SMSKYwHh%B!Z`DR(RF^UkIK35)m= zQqRc$Zdg>8fn32o5}6wv&NGPnPw%V}AX}?%G9OxNb~*5<`G=*CA3~ z8RVp0a^z%#{o-6xJM>?_LeoUM+m&9BW^h%tPE}o5IBy51W3;AUJF8WO#D#AcDOltJ z&BOWcyL(CH2o5+0+X^=nInjgwYnbIu=mfWjkyJRBdKiLX&6)jq*~5dq5;Aja?G`ny?g~h{QP2*hIKl&mJWO`!!1w2dM#f`vY4`v)Jtc z-n#b+b0e_s$CHLF<%SDD=tBKVzW(e=s4BP)KQQ$qb}dGsO0ZtKYb+&*reL_Ac2Oip zZN$l$2P!6$;$nV<+)=9g=b6QHN<5@=3sJwgt6BB1eCn>YC(^(VRSmJN_d$6S4Vb88 zd8Uq0ORp2&?wE55R`$hGGSSNBFPoU*`2C$J(z- zHMiDOKOQDy({33qc^ao?9^z0E-#l_jp!R^KEOp{*7a*)74M{HnJmU*@NFJsT=wZFo zm?MpFr(aH$?lT&NbDcl{5vv74`^mZx!s{FAyKf@5kAM|OxI~;E?TL$WV zAF9b*d_Wq_L!l#b-X+<` z@%<%2W$~UFUt0EyI9GLxJ>?K%4TXZg-pOsn(K3EP;^Ur|x?zvFfcgox3QC$rhb+V3 z4V1a?EjjON3LEB_QSVT@n#)dJN>%|R>}`^NC428ZlYW=u9Te2rU4qyLeEPc$cm7bK zrdovJ2vdH{?OxSDJBb=f0_V=XT}WLKfBM{yB*M6Aq@-LuE9l;7rr4xo8jO~{D!hwP zW5_uK+Mg$8fG=90K^d%MN738Od?|(PsS9YPrL_-KgwlCko5KRe%NKmlAe`mXLL@-B zU;pp>*j&7Xn_{A(5ghXa0l!Zwf-5Z2yYFJ+71?`@=hiw_L3i_G&PY!Edbjjz4oZ=F zSo&TI#~ek4eA?OzQckX1)sTN50oq<98ov8yoZIhr{M6Im(~HX2uKZ8EqRZ(92tj<2 z9SIpQh+U34t-lLS2jRI$@ZBNI-R|l4DS3>_Y?n@_xbtY>r`FtA-jyKNQX@dgPojGW zja>Z1mg57lUm(P{QCxyk#!a2H%_=*Oc>8-uRhpL7zV9z&`Ro^RZBds=sNBSAQ}~-j z%yUl+#`?Fc%m=J6v3O5JjjHW9$J z1%v?*(vz1u&1$+8+dI79amtoJUVezR{OzT1kdyN9;aFZkCk#kNX{ucRg@f#Ac*r}# z5vbG7b3bc?U5qm(;qyti9sMlLv7bNmC_V)>Ie~OBn}y~#v$aslEAOAE#A4HWI_$xB zGc?Ng&5+qKg;WNxAia-w6@Dssf%G}Cc-;-zgi~spCs+@;GUtA?-M?wJWl<30IifU1 zU=Rn&mLVW(pBAWk^UeUUh`^@fD7x{}EekK2x1mB$HS03IhybHJ96!N4Q+jj|xM2n~ zHz)I`a8~^ysZw_DROaxU{3#W86^xY#e$-@2X<;58juv}te6J5@dx6{KHRb%_jHF!~ zg-#<>t2IR{UF7X;d$O!(UvyWyrL4L8P``oQf?)#RPdBm=dwlT`6|Uf@Jb7!%4RW;h zoNW3dca-yoIFh@NPtB@U;NC{U*BvNNjh6oqw0b$f&s>E!tceKoIu-z%e? zo#(LpDtEE9Kbvvy#2LMhV8l(cW0UBUgj4KoqC#` zjrwloe1ruM&=EQI2bFR1+t-+nkNJg)L!kGs>FpN zanLy4onR&=bCbO?+5_(qAF8R*$w=CHCr2Z^6mYH;%ztz;8Jssq-!RatS@qci$)+nT zcdZL_YwL(n0Fa;y$O#rxkRg}sYJ6(99pO+WhI*zlS;_TWL zW@wYb{;g^=L_*t3wWM|`06k5+_4{o}kVvRncGnvZkuo=$9YJGxk1Bk;RqwqB{>~Q< z+V8@)#`xwpNN`&}6-F*(rw`d0o2FhaVjHSAJ3Qm-umD0GinB=__(UBZXrTMg76 zQlNFzcf|RF0Ge!fm`dmn!Dq~!7zNk8A#|=`eS#3K8sl)yt@~FxSlTzmkq{)VomnI8 zcxr-@K@aTp?`c?<(?bb1hhbv$e@DQE(|yV^nNyk_E4Ln&abCSMoNv+RBg=Z40>ROz z;FjS4hn00#1m1osFTf0A0)&DeQlpV&IH#ZtrQJUd<0=$RnEiW?J1geBXvB zFP&w2BYwTxch_%(!I|+)pV|L;1(;J{Q%^8|d}d_oRx80*#*`rhSt0LUBft!TPie~( zwDk25!IPd)T*Ag+-wScU2XMfSs<1`ZH&x>v*Q@RoSa)yXg}iQs%SWGz7xNXS5}#ze zd;qcl0qI#%AK?qK4<6pAm=L(>ksIa@iRS%yble<|jh<)UV4Bn4uU92}x>Dg&MRP9! zrbF4=sa-e+<6#3_bX;ZP`e|@npRo_jY>x#;0SSJ|%5PknPjVve_{=*!zReRWnl`3W zh*)DRKzWjT2cg!{#=7$=;kPvaLFSHhe564r%iWWJF()qn9b>>L_#Fg!KVsm_m+}Sn zgGZ%KW)-P*=6!VTXJ0WRSthQ0g|29MLWSXAzPm`^*>zpMQOVREYxs|0dXsJ|?b@>NQ=9#} zt0tdMFDJF9u^^v~GdL);0?ijKVbXP?=OKnfN`WM}j;Y|gh+mbsMCWHE#q~MVu7gT` znbgod_>XT2T8@k{SnHEglJBR$x}wghRo&Z_ zbodGY8HRE^P#Shq#(9fJFDLrV;7pyvzm@%|Fs@odRgE;e+y~m)xF($by#`wnl#MjV zH*iCog^646nay+-tvExb}@aVJdpDA~TNUNdhGX-AWm;3UF)%4^KueV8ZcT*kABCW&=OqhZ8R<>ITr z`5o9a7do5JuG~*4_OfcVp=U?arLDtG3)j-}I1Mz_$K{;0%WN$(6)Qg`l!#FAF8of`9Q47qRaIqFV&~=Ku7`gIDTB zwa~8p-*-`{8sF_R7k(_O8qIu&*&rT6zPR;!yzv2M9U!tBARFMOA;A|Y$zEU`RFO3p z>A_yFU>#Cl`DN%CC$L=Ub6w5`DR-5cHSOMASK&fWikf38uPxxA$y&aoNl=kzr!pU05?DdtoyG>%aPck1UWL39xFs-4NUVj~NXJz=p>Xz^-z z&*e)&n6*~n6cL3KK%zlbJhkGx=7X@$RYP?RS;!YtM`AzRPop|8_8aXL-G=a^lDS}w zzarShs=(sCI4V+y5lad_s|*zH#C99Ti%%@C9JLaAw@9^3m_-{YTKQe|c2lZ0u-*3O zwP8PvsMJaL96t5tAj+b8lQg>V*3%t|T+eWqhQ#n`^S$H*#VKD<2fPDVb&w`2J{h;p z-7=dQ=_Rj%vOX>{EKjP7zq8qwjgcChE93C@oh^&NJ&MKA$qww?uI#UnCiAzxE26m; zwCf(#;3PteC-!?9s<^{(6F621@w_H%p&<86^Mw~3pg%CyHYqygC7|Iy6@)SOZFIlB z?93MkNmg!r#m%FXT|mC!Q{d_YiJWJ(o7(m;zUDrzglPRHpeYUIc7&Pws626zpX!E$ zV=3Q+jz#Tnt+rl^I%;d=+h(0Nt;zdWIgQvIOF}cyDc)) zOaxL&u}Y2%v3BlID(8k2ZU+)fk^0+O^tH z_!DtsY5&q2O@c4re`tw)97!B^dqHkSXc<^tH&O1naLVnEbL}7x^|mra!6hZ7zYms^ zwyZHBMH>Fh?K4SNr8OGBT8{6*_i_fE;U~FW@4DXgE(aTlV1Q5Y78(6&a%y<}Z}5S1 zoTh?ajHcJjuY4t@pmo6G@xeh!G2T{P3cGFu14W%^#M3Y4$=z0A3+-u?3PS4S5A%jYp*m0`Z6pJ^l1&8F@eV&DCt()1B!7Q!j4n)&G;tQ)Rn6(% z$Qc;0K6L@pzX2X|5N!(pG#-kjpk2&zdAZ{mkaHMhr8=Q=LMJf~ld~^?>rgLsKnIFc0 z97h4P<0k$LGnUYRq})FB3=0d;2#vj6zC3;5VlVGX@LYMyjerGxK-iB zc6Di)qPX%CB+;8ilXElM_;>%nc7fRd;@P%rnNK8@6;#{M!ZDM^Eo&}g+KX<%PMJMyV@DI!QS2POMN4^$w`UD<)>;o^ij)iqA zahOf~fN_N*BpX4_iuk)XTMw{8_z z8?WlB#psLIlgtySPa+9n-;B*iBw0UgBq9;`oc-0`6~6xn^CQFqG{iFfTYSVhNgdIC z>n(FxSYP{w9(4eIk!^nPz}Ki~Tc^fSh0+|BN+AmEYMnJf-ry9+(ipg$^iISWfK3De zuPV*&mII>bf|zrlV7Zjd*pWmm5*q%{CGfW__H@y>U!K0}GBS9a+XkVLY3}{So`@OH zs@f@$@&j5;j87!DVHn?FCY6*Mxm8lG+iRUH>I`8;a$29B+HhaF4s_rNRFQeM?Jc=) z352A1XFO1PrkJ!+@L_oxKh*@NAsT=_M-4O}VdIr;YfkGqG&z*0NfQT|iXaBq%T_?; zCp=so2nyE0T19i`yv?ZT=eZH`>GB)DF{NraScXnG`=nTN0+F%`nSdbz-f>hj*DdlW72`JDt+r4mWHn zs)s9Bbn+bKmD{w(?prDYdaO;=yGhXK)^85vD?=rQP~xvdIo|otOoaL2-o4i4h<$GA$JjJpS$jN&a+FryrKfe%vw9~Oz5FbEA6P?sEmy}HxBdeJ zpDsb{Ymd&Z$YED!?@VO7?E9O7o5^Ny&8c=q>-c^96|NmpUf5TZLW^o0T$%6YybQ_K z=CKWAW|;-Ys6}N+Kx-k;-&#wghia2W_kTYW27shTcipe#c5C$m51IoiUQ`urclvP@ zRk1*fR=;_{s@gB&CFEOY#Ot%-kzPYp5EA_EGO#(H49*@;#v4FTJJ8O-Ql|4GA;Vk5T(sS3ZUR8Vd%`9-F-aRD9+~8Zm({s{nC2)`ia=Tac#nCeumb@|aF{b=@ROsE zpuMVhSi=VU>wbLiXW#3gU5*+kik7B)DQHUa{jr~k*_pq)2geYSIh0Hk(${Q<{ov-I zoqyV$8@RdTn!sL8pc3u?JEl@m;m>&<6kSX#EyASx^lMSILSpwG^=fIe?r{h;MpMlj zq2mQ)NYbhQQY>Xs(|TU2bN1~=36{`0arnvDw^%?7MUA29yD-i)NFO2gQ-~kGisCWC)V4?qKqd1OoJP2rf7HLZ zJ|{S`i~N-NB;DoBKm+NAm62m!q`K?}p2H_sp7HUH%P7ldj+U(G0fy}Anb{L@jJUONULJK ze~e>da?MAPYwI>Kvk*thS>+~Mnqds z2>tX?tWlMxgw!?HvVY3(L-^t5!ajIKJq&~S6rdWcA8U!jxSL`VE zs)E@R{Se@dr0w$CkH3cxaEI;k8RM!KEkfiZL>JKTxG>7c*+sBe1Yf4uR{b<4Rt!`G zxW8W***>b*Zh`|phW++k8c2!ugueg;F`Zh%6i6`;_BiWc<3w!nc#fYyY#tA;K+r-G z3R0_g4Lp55aTv(bG9&=}jhwI`Y}Y9^Kf%^2z6){7C`r+Bf15_cxK3hDH=Y@G&e&y#eR*w~+vp$pqjX6HpkVNp1#>w>?U3i}zPm=0cAW~m9vVw8f!-}YZq_?{ zN>QJ0W(~|CvcU8k0~yh*W4wI2y4c<&Wudq(;;eqPln6&iuEtB3tLGx22+uhGO(~9L z65*8GmhUE;OJ9Nbof|ttB#~JnjQ;Q?fJm`@`4w10dR^~1F8P=skbcHcG2v{Z4(r0t z2dt?{eCBn z_Gx#x8*{0#F^9CjrgOxuCW0VufA(|@Uu3!#r6w6%NyIQE?&I2~_U-bE(dTALtAZQ= z8WhoGuH&^Gj6{JZOFrL!i+J38Nf)cZwp41;;r{%&ma?WFNo}E{x*-mcT+^2Lg}*!- zb-n!!;CKT*2oPbCf5n^Wx@?yyHh3AMsgs@?)VS~qCEnGo2 z`X}eM7MBDYZv-m;c@dgtv|T`J7!)_yarn7D5b1^|zjkFWEGjnjTDv{uN&W2g?A{zb zkIKfEB4m&H2#Z0+2lZ#)I#Be!BAluyT*_sh^{!evZcf@?cNZ_mN~w1Dl2E};x1IBi?BHOCGWV0e)?r?>a0 z{yACdslu8t*x&VFpG6Q0eqh(}vq{_c2UWi+<~?UNFV^=&YzvhJ-6ai?yBxPAfSO49 zx5H2PF3yW3fS=EpTs-&c-G;GWU(XrNrnT+?RaS3C0lR3gGpjCD z+^KW7tqqH#6Gq}OE5*x`7kMTXUgnOg(d%gN;J43bB*&g#%Zbm7GzmE!MdjC{0;1G9 z#@xw2I^ZDO$~%5&VNbR#2^f7Exa^~~shUkc1K@x?NBkDelt~(ZNy`qbzPGwxtEhS& z_2FF^P9HjY+< zI%G49{`TL3X43iQ6~=R|ZyMV<)4SvjHR^20yf)N~U5l*3p|e7$jV*AQ?_CTmb`q~# zHI)+RVD?6crK(J;mm2(oxqF9g6bTVR<|TNnS;#JT*0TGAY?FEC`1jLw*0JmF@j}3k z4(hCQyDwgrj^4}W!+&@4*V_Ip2r7!Etvz}?_b||yn~yORls%=J2GE+wYzP*4tN6}- zY?|u6k#XyqcK!9V+ywiIRT8wt!&+W`=zgB|*@q({a$NKT1i2Q5n1wx?p^1k-n<{L) zxY%B2h-?l}LE!^xYQyhm#FsrWpMIhlg5LP6Cl5>q5;~wrJOG!9$%sq(t~FlN7L@|G zp_2&T1|BJy;c}hskr3jBh~l=y%G=V4d+u4?#ZsufY_F`2Si`P#FSc`f-!HeNFDPoPsv(;5JEl0kI;xS=WKH4_OKrdR22dfN1(o3H2sh(Bx(vl2S0~?; zLBHI>t)f$_TmPx&5ewO*NhU$?#3fD`S^OdWx?EJ%x_jbIzpHh%brmvQdiv%&#(7gz z@47OavuIm_+Ctz)y3Z_PCD~4N&kMt};SLd?Vxv1uVPE(Cn1r`E>q|)irdzdD<~&8V zs!g%W>YwkdeyeruQ`9<_6$q4UW0aN z&>H=6vjpeXfZabeoUa(wUKA|TYM)b5&+H3x&TQAfj_UDKqCubdK~)l2iSnh_2Lx!q zT+pXe&M`|MW)i-U&U+I9Da{Eb^DyIeFjvDn;n-77bSBWr3YJ~F!HbP1NfHt1nl2YV zP~5?xV<_rJ;RWl^M(idxlFgz_Hy#?!k)gN-xa-x6^P**(b4DaBVgM^0`%pbXL+A*g z%i{a=TH5{e1l6gc72HsT_x=>P-VN{issie*chB*apCDDt>{*9%uGZ+{Mc`=5LlWJG z|3+l*%>Bk(H1qciFwL`TTCG;i{T9vXrqhi~1lzWiHWO2o+DXcjF(V;XO$k3*P+~S~ zT|AD6TGvKiPfeKrPhp9^9Du|_xypI@Dm|ow7-@_i1eg!adIi7^p6;=!u;b_8?qTFX~bu zT6TxQ5C0`G-qnLfc0b zoK^Eo<&$Qty}SIZ_ec;uJ#C~^lTlG(>zQ#K+IL5VUN>S_BmsPDQ6sOWr> zC{iflF=+Jc0HfP(q-`j=8HF3X_1Ki(H$jK4J{MTpnvX&-_yddHTG{K*b3utp6R-7f zi4!q`5V{Br0(tY`xU8StleDJ-Q|<@c8A28THKEAUlb4UN zRyk7XEa*(q>OmwZK{tsjXy>4hO(2N77&)fHl8dLMCdC!w%srs!u|02tvZ**7gbhdy7GQ(3o z8m{z};B{|D>p>p(qS>7S`)6}zSE!M@h#+g>SX`0~piV!i@P|e+I)bR8jTxY+K6&Kb zRcRzFx~IMvymORcn_zcT23Q~FC##%CV9P z1&R~dJPp^LZ(jfrE51leg&wzv=E5yHpI^b@+`kF$SM)nw&8;g2gw=~gB`EJ{(Or}n zG7S82-7^Me)+fwVyLQ`^_0SJFh!wTf+_M!R86J}|w8Ty_ZILS;lPno$%UUjpdwmt! z$KB|2$pC}9zmER9@9q~-e5KK(Ff{J<*gIntPvPH9ylu)rZf%0BPsIMlT~h3X&42xN zSwC;QeF22g1pi23-RFO9yzDRUeDLn6tHew4_Fy4X<_a4)DyzNi7} zOD=L3v>Db}eJ(ey_ajLjCoaU8a2kNj5%i-5050|bO(1Djyve?c{If$mmx>`DjZZhZ zPo)NVfu87`RojN?KenY`pryhdS7o)LTcSe3`RAWTbff7N2Vnw%+Q?Vi^#bU0T1q10 zX$TjC5hhKvdoZl$ja${aAEKI7xJS%h4EN@blHQHynA}Nz1QPDE52^Ip`qzn6aTTm3 z=<4l`+oM?b6SXzRQ-*Mfvih!#rD|&11|ao=e;RYE=Rkc_6?pjD*9NM1Kj&C{P%9mO z;q!)2dCnwiDqtF6nIXddNasfV!y68GNUAJ;sd>AtX@b{lNRgfh^89gQBE=4FpSINE z^^MIIhV#NXCF;%gV1G-KWS(hVs;t#^EgN=wkbZ|9rLnN@PGzV9244L=zr<-?mY5Qk+W1F%WA!^DYH2Z+C~1~Dh<5@4|$-I?L6ehFY*K2a%UgPPzY z`2e1O5j5S9Mkq=5xc-0EIHkO>3Vm6Z!RiynZ57cKBy??Lc)zW)aN~~T6Wn!)oi@EH zOL^Zy{kB>ajHTgXTS(9!Q74CI?MocN3wO!~Wi9cIDqauywvX%FLjOI>9wA6tC0=|? zaQoY454;HxR=zs^2**(Z0HggO)`LWry=QzF%Ei;MlD>mtnpA*A1m z`KxCd0!QbX<;hkGCd*wHAeN15Yggp0Qh3|O4px}TcqSOq5-)<1}Z8hTl_f%$=_KZ!H) zk|suuG-ZQBbZTd#ohtTi7w}~H`1kQ~jN^cCg3m{vmEDeM^uV?g2YS>gUiGB)>`M2v z)|W0n zeUoDfgeIL?I320XSDqx!|IcxJL71C{ro+kOu=faS#%fbrH*Heysez5~5wS&DUzxEU zv(9Gq@}#!%WbzMN`;qa6vX4U5Y276-_B;^Ukle0y=5(^STsDrW8#XroIC9+&AdU2!9NDG368_;;5d=5aTm)+Ve9kE01g{E`%FYt(zFkDIYKq;EUcqVS z8Qcg$+TB_^%gu3T0D`~J=Zgv|Nblrzni%Fvm`N7fv;2|K`3|xUv+v*8Uja+?l#dXP z|CQD#a94iFFE}>7*ZoX6K*{=;Lo++P%N=@>UI)pwAcEd^+axk zWYZGZj(GktfouY=N+AYe9Z4)@k#{9W>j1p4oqxf4O%7wn@$DOD( zE?h|U<|L?3c%^Ns2QDmX{DI%*mzUAE0LY#wIK`+S$$V5On}O^kt?O0g`A9SV$Z*UH z0;VV}1A%+cNRe`^uc{oO?Po{aX(G3n>{_|sq4f2&OBazi@lS?5S5?=$n3n!}SAX?g)*@@gxgP=R`~QUa>^2l5uin&P z{vbCrHx{9D6hJk}FpU&V7SQFWKu-`(HD!a(-T9)H5*qd#Nx9!!NAj1q09T4qBnaE# zU2X9#xBGRcsaoVey(YLEKaHqw^!HEfuse|DM~Whr>E$=nUKU>_ls?@G6MzT(VJz*k zLwsfTjijySzBsvL&vFmYYSXCaM9n*9<&BYk9kw`lih5pL5ektY zABjL$ikU*LC%Z}yKCLt81KOGyZ#Gm69&6M>v!w_MnyGrS5DjW`c7JmiVG|?P!2u|S z29ui!$FaYoqw({BJS_CvknL!I{$y}nhW_(6wLtG9j50Y$byuda2wjHEFTnedt_}m8 z2TMjx@S0(#*iX4)nw3$uWYa<5*B3TM3lfcv5Ke}tT`|SqMG3x9jJJPctk&U)`_jbU@WdHp7x95CzztB;ek|B=8{>U(I|^ zCmK#u0SYcm7vk*wkE-O>*kd%Iqg+N?cb=bO%)UsaI9jQexm6$afMZY)@b3u2dpl!l zJFk9ZQvw|#g?^+dbQq@z3##EEr_85bW!|5!A({sLb@%BJ=bl9irutG;@_s_Uj<3)~ zIZ@w|fdDp&+1?7%5q&a4`78zCl()h*lpfuYl3fHxdW`Bvh8yOd)@x?BADnLI7_UL8 z!ySPvUc){K*W);zv$hWkrQ&H4iWuAM3PQieL-CEyz8Mx`7z#A2)yCjYT8~({NsA9o zH7CAl;`aLDsqOJ)5KG-^)9IDVf2a``3Avh$%WJ?87)+=zHSKr>wL9q>URkD(nqJ^R|=^u!}VZA z(Es01fOO#hY5KO#m+g+^j9XhGZ6Rb5CwDf{g6{qQ_WW1#ytasc14DQz<;?{8H(!0f zr4~_rn8y%kT2z~Ogp2D44uU;pPU)z2N9hIP=xtl&earFs46FJZgc9ie->4c7u8OBa znCy?#$9~u)k5Y&0`YAlhT(gUe@6XVS`GZ?6pW-nzaZsP(sO{T3<-@jV%7HPrC+lVY z%D1#2rl`mL(>t3lKPQ@ise?`2_sL{4_G)$+7hT3K-#K9Z_C zu)UZmSUT9(&DrvjrGkGfMN!oe93fO4^#!))U_W-31M;)|EKSpc?fPt$F<);GRB!rN z7A3dW^aDm}y;J2%jiMb~Gr$rI&y||%az$GhjDAS%ymQCGbR+;2*+w?_$7z)w$Ud88 z1eLJyx$GO=g=gUg1zWGv4rFL4Db~Mr%(KwTV2&W%6;Cya zNz}bHY6y)FK7Q*H94@}C9L&F&CAwNedN4x}tZd9SXW4;&KUNiP1U-1o1?_WBW?UAF zJA^8eV{z7Ths;ovfwoSym={tc)YyHIQusFAD1lr$__t6E4}b5~t@P@6!|diFy5vCO zRj;k^ap~Syh`%c8c1^n3)}B$4wyZ9{)rYMP!x>z=Pee-17c%}NFNBk?%T^T#pa0Jd zP1U<&U~y(Mv}{>ZerPz;Y+peVzDbykVjWQ4$TCNNGCvvN#fb3L7+MwCAz^-M_lSJ= zcWm+zHYSRRkh68Ec0Aq2X3~t&?nta?kA$*0Zs2$eimx5fvU+W2fJ&T-rQo)Lfl9f5 z!@(o2U&!{5;JC0a#a?9g>AB{N1IEFGZ>C|`pHTnwVUyR^}E zHbJ{%CMF7vGAz4$a}eu@GQj{3sE*&fhD~xj575>(`3cP&=;<~nUlOw~O-oxyXT05g z($t#hBal9uDN%8~jS?+YrsluA%fx+rui$##=Rnfw2I!AtC`ITs@>ysC1vV#nXgJB^ zXByYN+EvEi`vSIl54u2fd1#OVYXLX|EV2E1PbD*}6WxP{s-{MjUwaHP)NrlxQ5)|} zj&NdiMW9-g2%tW$;wSBYf{PA@&pT&;hI6|ShDuS4k43AZ>7nm#XsA3o;go#dBUk0|fgEqUyD_ z%$1$&4MSK7Vp%cHL>-r8wvK_?azJzczCLisO}bpP)G-_(+Z;dy=~@=zSpn+XA`+Xv z3D(rJl>_+EDO~K`jSm{c6}B>=_0~(AgRQ;U5x!;NZyIXQdb-@G5eh3!EZE-QhjTzS z+T#C%$b>n=XI5ucwAd%!K(!F?SZZ7rbmY`gXNCs94A6Y4qP&N0j!kMFV}vMNo3srd zymeaIlbE8W(OvWzpE`G$TPnLXaX zHPr$M(hsl4^z2>nIei4rN|jC^7syU1Qzy-Ia~#EoFmw9e>f?+@O#s_zfedWn^fH5C zD-snDPHt97NkU8K+H)=2$yf7xn3cwt&a z;!%H5u3#!tPWGppqXFYcFh9YrC=?z-*xWJ+HLs3aSTaHUg`<)HhVSLji28VYQiHM` zi$haw^ykoNRXk+M9Z}d?+S@Pq4sq-Hz-H@O#}5I*F-wB}&Mv)GGVfN-fn$<2xr7F& zg>)+GE8FHR>}fcV2v@oAm*DveK(4`C(yvfZ1qbFpHKz9ZD$JOJ2hRMNd}{M7SAOEW z;5XQq|6_cco2_?FCl)^9r5G?fu6=(@mxK3t3p3)IY~Sq~k2N7+^P+(4dIRPvEk)%P zvRhxDw?CCEtnx|=2Y-EPR@t7*8{!M}ON?7isKvLugWpd5nwU$HEwtmG^~0~DsIK@K z!roPsgF_KICT(yIJByuvQM2FCJ36_I?m91MTA95%e(@peg6zDfpAE~Zx+dC9xii*r zru=R}Ck+#&Jqn!ExcK%GkHx4BxpM%=o2HaShlIGQTa{XmW<*PfYL~#6<3H1*qUrlF zb^HIsgKeEa;vmM)dq`cnx4(CI_EuqZ1^^q|bL@o}#l`zdC_Np{Ggu2(T8XNWFGSSg z9*=4~slKu{Q>Yr26o{num!7x2CPJl!Efc}Zh5d!YeI#AnPPL>@%Nsxiw7(Bz&%vaB zEBt8Q)2sFr#AK63$j9h7fCP-Ae=!VhMt0_>0G&VlJGY&V4P)bwV9*)n=P-^4M=0#b zPB`@g=eu$;pLC&Ka~zP8;5yO-D7RByKbKkv-LZM@nlFAjZj#4*X7IL}gy%xoEFvgr z;)qlKVL$IVf`<4@WwSWD@PJ`GsRBEtnR74I4IFaYYWr;*AF$?Q2PZ?$$fAj;{5sj0 za!=J9B=%MQJBcpfS>+Or1nYwcO`1{VBr3rQk;q3rJF8`)0`?Z#Up)(<;oOe*;O!a< z!j7A0hkOQnXUE;!mH<6Wh1)m`Yc23Jxz9=Qwdqn46gmkNC zVHb2L9})V53eKF#t=o{64}k*i<~s}9hDn3+>$54bDZff^=0y&hXd9>=pES;l^TDaaPbcM}oEUDiLpxE!_?Ro0EBQW*j(G)tFpDfOZihq zL#(+7N;YA6BRCN0wd+TkzeHwA-ZR9)+1AyHRnbU)Ej04@DYN)1NJ6WP()UZKR7T9T zf4N?>Qp;x(1j#SwoJ_fQU9B=~J$uUw>RNzM4!dcMP~lyH6yHP$Sow!c6I`V9{dYI@ zn(RONMpny-{cTlX_W7h;t0;L0O(#y_|MyM4;IDNP!Tys+&?8n*{A5oO$xxAQUx5Ig zJ<*Fzg(A79paN^s1-h@{nS0+F2Lv zRb&BJosvfF7p>oT%8xG77ArR7E+qk~$a-weHh{Qysy7-cqQ6De&p3=7k32&=U9z`I zijM>Sgh|G!&f2r!Sy=aXG=DNtjGHKzAKo7> zOXFN3Dk7!6Vi!t8t^KJiv}%H(+puC?NS5C{>KWCS7j53`-bK_b4O}27=JYpr{lw0A zCvcc&C<@DlC8XM`^sUI_+j7!hI0o%EfG#ZcaKZB-!#+o&T56xPdRJ+y0swNljpJZe zpE?Cg%NLFF3%$^kwh>In+^(#JTK0@W7;UG=jWKt7Jel9o_U=yG^$F1io>~Ou4ut1! zpD*EUToQ$kuF)&*&1$bAaG#|F^$`&POLtqrNmGm{Tn0}`|6vM7MLVm8`>+1s8J85? zdv<6lsr~sFzSo|!`Qq)&$nF`!S%CPrzTMA}jZaPop||L2^qMZlb)g=_EJzdKs9W zwf{G{k|cQ1GkS5oA0iOwp$YO1?>QC-&BHa(CCV?_xF8`^+vX5Wo>MN77a51P?P7(2n6{uiAH~ILt~_>MW|K)A>|g2@g69cZTO3fW|v3s<=Pdg ziw^~wpnDWFj)^41gJ^I6zI-kze{h-$fWX ziP7Fa&-P=EleqBj`i5D$8k`_8;OZB(SDz;`-QS(R5;(45Al5La8UoaxDIZ5YR8SiY;_BJMx;j;G~nOYW+KTu_t?F`_ULxp_W;iA1!If zL49c?oAqN(ot(P<@ZytEtbsH>W&_dgw&dX+s(aqpJ~4k1VW$JgX#CD{=agl(*Ref0Y&O1fqVX+ zz}Y3XOw+CQHw~8b*V4KEiBo8RHiM0eD2%IRwN~c$MU%RdJOefKCt-Sw17h^%gzgRT z-*Ilj6RyqkP7zPfO<};5-uyOow@0PN6lTO`nj6e+5Nx{maobl0t50-PniK1Y=k(WM z4bEi|^L|venRC5lUO(A2WS;JPoPI*?+OD)ef`?n&U?XsO*On$iItK&8Id9IMCJQ!w z(_A%Y!_Cq-8_tnO5;A?@K9>M%e3b4G?1Zh`JH8skMC&t$KjX6@p`q~4@EKBAyi7b4;afPvm* zM{Ng{5L^V2Y08b|zT~#Qs~IIQd$thGkt!F(D>RMM)f_m{ej9;wm6;6<`j!e0`3uZn>|cvrio1`OkNEDhL1vk%%0~3 z;XoYbW@~0ep6~$$NIsu8GyhM{%KF#3O-U54ki1i)hGKvMQ*dHSyIuIF&6=5q!dH`Y zku1<3SN=LKJN6l#e`2lcl%QJx^-?RI`46AMDmv;4gf52OylZquU!JQJvwc++V8@sV zFVh1Pk5s(5z(Lo@?Q6c7lE8yT4g?eu`>w^Dq)czc_r}EsBgudH*Rln0H68lf1}@rE zeOqG4GYjYFQ@s2-`FMr!lLWf-!a~)0{iAupuP$4VuL{V~41NlY2j7LLdo~V;Wc_7- zVVL`|_03kz^l+BzHoXa@qN_~!f>3YY0L>HnpM{Kjkhu8%wrQQlW&}SZ+pm@X_j2cw zDe93kIjfdf6BAB&7KOGls^EsfN?&Lk`?OfI%j5ipa725fTo0{Z^=`K$>Wg_kcI%p{ zV6Krd?QQwnVt@Tq8SD>z?yu(L0V80CFB~piMKQ`vZf#6@!%z_1cWSo(dXlsG-HUT2 zmXhVGl!K?;uU>1*nLa9q6i434m8nW&q9soCCmJC`-=TD)EELB z!E3Xs>;F0;R=p&sVR!hm*4*Wfc1RrKU>YpKj=jF9&5o(n$>B;E9jv41j%C+rIpYK`awcF&;g>5k*< zHvCcNI)(c?;8Ase(I)tAyX8Z&WbBI&HKdnc|**tYuM7pM2q2qL!6eqY>75dnpoE?G3Dq4M>AB`j^ zcox1d#RDgf7;^s4;{-&j4x}@d`gZIeN8sGt{=wjjllu6w>Yvyl>|*~=Jq+#nh@4|Y z#|p>Wjhx~e{iHr!cOE2=NWZi`X80f;isp+46TP~+%Hlu4g+tvRg%o+Sc5=GlXNe3V zcRADiKkZ=p$oTI|M4Juy0n_&}6j<|}Xp0V-T9GT`lhX@(nqOEOArhBx-K|l-^@sjQ zCB2Bl{xQN!sQZuKmTlE7l>TiwJJ^g={S9V5N55=Y}|ds@xw-pR>}<1tekO26JJfuNTHkSr;i2kDeYpMlOH8rkbn5YG!46l4@sr{1$^6q{A*s& zD^$8>{=mS+Cwmh+QGJW)5il;(DUL-peYm7JE}6&pyoqy+y6)Y z(NvxBxb|Ja2u2KC);}93yJaYwZnxW1htfyM>YMaz*nG zrh0{cjtoGMphG0u%K^@5r=vO2$Q5?F|2-_sRO)XSjEQQbXYt=xQDARLjm-0n`m^j+ zmYQBSqTajJtCaCCiF8y#YAY}4e2A{4a(&OAK8C0LeP9&gcZC`y@E5&HSs?T5W zn&wbnGWh@PSSIapkR6l;uDJG4xK=S_^E)e{BJ$-h=lTn^)AGnRzG$^%`&i=PRR`6t zt0BoCIaJSn(x+wBIK+y}Nv2nSl~n(%#&9et-W2cWxZqAlsDzF%=>Cl_CtGxPN7+$Y z1({OsL7nadGTJUp&4B0m%X~2=nM-`zQBc!9Sr<79xCOpOY+8fHI@3d!(-MV!plu{EFG-flf zEby2$$)LlogZ`iaT3fj{DPn)OqIp`$gHF?!(@+MUMWpvt!`jDD@9?28GLhg~f-$1j z?JuxOMUgkVgF$MA)2jVJaqW&W4d++F>+B0N_<1uAQNKSnYI)`tGzUqsjJfQ}I#ZP; z7b;^9I>MIQua&T8llhvtajd9Joa$~z{p5M~utL)gRF(+2^OPVT<3-uX`jCG?T{2AP zq>ovdT3|@;DB@M$bq1`@DXkQ8}iX=njcfON^xjr!l*hc}&_VPmv>j{L^W#VGs#W2WI$LZJQCLy~e; zbJ}>^UzfX=s3a2rM?kp0zftcin`v``5)ik&uM74d7#p6?s^(#QOw|C?ndGv`h1CLq znIs{lZ$#^ma`*n1&u`ZSye@`@rWAZD!^O68Pr0j%P)tH! z#l@Dz|br5`G&<)B-c7EgYSK)8jKQ_`s>!Cjf znA@&E`KhlBc&5c}Pjl4a2D0Wc9Pg+JapQ%LsO0lQ%#hd(Wfw@V0dXWiMeB%4)2mGR zRd~m-f#F`tIpOv(QYfe?t!%k}yw_;U-mN*Bt3QBH8}{S0=iPa9!BsuwD7DS+0TthA%-J^5K;<3-PfV=;awn+y2c7$}GTf;S^}pO!6^Tav2-a6~ zjcjDEs;bg_LL6WUN)kF6+s7sBcHu9sQiz`JDw{TBIgT`zsJkW?v6jN+(8Tv#n)8PH z{d6Wek5{(z|BwlkuMGKIv$xM*hGTt=jvO}m22vp($|t26Y=^a(Iw9(YG)3GVeXIj) zUp98k9$Gq#9QbO8+vx-vGFy$vSDYm&b{y578`Hp6Jxy zVP#hDdt<}(y3Y$1q!|>H+M(UYhBywPXP$lHA70>T$I9Oh@R|nYt)2`(NUjuJsshjU z(;kxf!sPrijucf%VmbYEQc>+sh*lqnAl;LYD1-(QM_CImgXc%Bb0-Zga?6AfbR?Z;k_}!4=S$0A;+}K&hAJY8OM!}~F;}StjHKi6K z4z+O{EH?u<`ZADKr=VlnvyX+Nq3ccaNch-T0z|sS-zbWCNLDtc|j`3v)U(~S~PD^rl4?0Oc+|Gn__r|)*?V)+PwxX3cC=`m&knWyxioHJ_5 zR)UjMuK5Q+x0Cip$y<%E?#bXx;d$a+`6H2uR3K*DjItrgu@0t_=1e#VeS{CmKK~O2 zt-fMjeGq{m)&oa=o{EO*<(2et3E4TmTY{WXX=m%C!|-$chBH{Hg7#tJ*TTEF<%Qph zL1|9r>JfPjEuQC)4V=lhI3;IYE_k3^JnY~MM!0sOlsFrdokpZ-ok_1mKF?o|!z7oI zR{wC+E44`*Ww%Lo@?P#pV;9Dm+)5Xn4Q?mr2v70S-)2km_Ha96Qrhg(9lBLCgUu-w zf3}v`-T<+*QqmH|U`2_$yLBOIIkxF+WDzpO5bc;8>vGd*xK5dhfQjA30aHfLh`_6G z_gI`aAJzf-`>YvtHmkD>p|HswwO>?N%WvV6cgHNWI07`;y?EuNrG|%wO@L1kLyUaS zaGzyqRPq{-?7=7nGZQeM<__q`{ogONI!-{|U!|x@HQO-#2<4yrYg;F?$J{g@yv!>M zA!&ji3A(6aiURV1KV*Qla3%>Z9jRhIiTSQdWK-Q$bSw{(qQXvzGlK&GNa9 zZCYW=}XC3}|>^?%b(9%j_3c3Gy9+!^U- zK>diwB#4MzLoxt>UM{aY9}-3>?I%OX9D0fiT>XN_vUMuqE{u(|=rwJc4Ej3`&SEC{ zEA?1Sr62l)@C}q@J<%aTHB3+h8LAtj>SRrIg$m}6jji87%BMAya?qgs9@yW4z4@!1 z_+33Ts)zOq&4+eHlf$2^{W%hNh;%nFlpNI3fmu#-h~T2h$Q$qYr*gv!Rc;m%1dS~w z9H@J>4?MG~-ZpZ;Z+0M!pe!x|)BoYuX)nj;^3XM# zeAC10V)u}EHkX`BU*2c>D>Iv^a24!_gFI3Uk+d@qDNVC-$ohnMej#{;3=mm^Bi??e;t8xQfn+-^%E*ypT&qWN9|yreFqb5tDQr)Ni>qORS?l zvuaHfL1oHUM3(E{I7}y7th?hi*N8NNG|EB%B>vRIj;!I_Lq2R5ivsvl`?L*#{3)MR zFLpP&tw;g=^Kg}CJB@4pm?@XmJZWmTR;<~|CKlF{5`R^po>GOh#n8*Au*qS8!E$cU zdc8@Q4uNcr8UCQ(??I~T0NO27V_(^ynt!tv#r{1R+ZyYG$&X9_eJ zGrARL;Ko*ymb>oLD5!`A-P-!>%a8|8lrS`)|I0LH&K8*BoP>a#p$^Wxj)#wy}z=$ zSVN|#F}yGh@XTZh{a>?Bm?kWL&1X#eEeELd=~-7OsJWt1{BeM{;Wdb_IQ+|rE%k(U_N*WFo77JYuVrJjPnD0TmJ4o>>?nxr3(=68sxN&Y zh5LqBWKN3hvUJx&9d-jt^s#pN0Z96{aAC;3YP0LtlBWdt2Nx*#hkpyx0T@8ae(O~9 zA-x?z)^pG#tR$ z1lIoEVB_)a$*VgrOJB&?n*;t<7it4DBTqY^UHQUV6sI&e#LUjzksl&{biW@k3#c?i ze*p&V3$^%gu1a%#I8#Ts?q!`%S3utZaD}Oq#e!#L?36GS@P*Th+v(&({i%egS-h%VEXLPg_B^6UUjnOs2Dm0{fd%xw+~ ziHC<-8h0J-X1#@SwP>Se^5t48VOYvuB7|pKYYgj9%!fJo7@Kk%*y@mPD2id-y(jS> zkb9leSeSuy+4j4vpRq%cP#^X)I3#LpC zV3z%$KMo-@SjDUbg%vv@^#-=TgnYdXUY?P{mlvYB$k0wrV*KB~+}-$C62N_l(5z1na-5W(H_F`KN6p&8HDjCEX@tA1h- z>6+X3p6M09bhxFW!YJ=DGxrll)hBj2mLSE<%u5^FJeP&G=I{wY%w+5*6cNqFR>k`I z0W|ImM0G_rG~(JS4D=zdv@AC9!23Hwpa9hXlnAE`u!`I*TyHwRFzB$PdS_I*Uec~$In*o|3)>44j?kCo`4h`eWEM zMsD5cYT zK7<&VY^HjN?zr*{h( z>M1b29|H~W;Rn>!UgfC>@##W4=MTS4e~PxA3EGQj z9m;7S=6N9&T2wCnw!{q1RSuMs(R4bO2u-h?R(3j{x#+xaoJ*ysykn)fEVAYQZ2+Bx z{Zcdx(TX2Y1mYu(3B~UJ9S}&o@L=P?a<2|@Bf;#qgzRv9(rcEm|VnlAJQ$zpwXo?H%=9%D&FN5(+?4f(Vth<|XxT!2)W z{zCOf;B0wpl`Wp-k%c0;%@FfB-;5S#iLq5~Rly9J@BFB5yrIs!NcIA9aJhv(pEfag z0R2ztJ`y}Qe5ilUpI#X@sM6%aSu_17R;^({qqgcdnnXIFl@6c(C5b6~o=^fGw)Z4m zx&;prSS+vUUt}lZ-+Y<_Rr2Ie8J6<=Iv569azx%Q4x2+n4gGR+&Qequi{Lr0EBx#n_2}c2{(!uafSoIZ#6%O+dnVEiz`w*`H8@XFs0>cb4o#=8-Z)>5H_( zFqOyK)g=PWj5X2S)`BoJ_YN8$J9DGD^rk_=NBBxdgBB`}6Fwg({6GeuhoGXt-->Jj zT4_ar=fCPB{NMX0YjkcSW(@6$(W*A49jyTA8Ch#8Wi6gF=!x5xv15ymhBJT(?N#5Y zeE8`bQH~=TMvdBLny%9bSAuU#LRCaS%u={ZQ6dzmuK3g^7SMWcM2OelVV+F}{t@(! zM85whySpP!Xs@0J_4KX~$EPSP_}AJnh!ph$({AEpo=%Rz@ak8vByMdz(2#qT#pq>j zLd5R6m6Ox&KAKWdl#mn{2aTV39=a!P0)i>if|MoiqIZYP{v+uumSa_;DEvSSa2w+8 z(8vsT>Bf2bOU|vzAeBlw$lhyx3)w%((-g0xbWJwv9Vl$g17yxkdl^XuAt9#LPglwP zB1qQ0!DHNza6Pg*I(!B?sd!zt_ZF2$M5ut;3$Iu+8LL|9*6h6Us#WMX9n5TB#$FAL1{IUrrYkZsF8p`nVh>LxM>tksn<6K zubSD{R8Dv$K6&oLg&+iP=4P~m{tP|iq1t8Yue=+wo;_eiUhyjzwv z=&8F1U+>g@&^*JhAx{PTV0yDlX7~`T+_=5?EVTOjV7_7Mr!@yCH6D_OKqu?N81>(a zE;bGEdnT{%a61*9pVTj!A@kw1$W@I?msJEs1@#uUYL{o+FvfoSWg2B`yGcZ{=8MH) zkY6gR69wG~UUHC5v4}ok5N`}(Vo5oT?zX_M=y=4j%HbCM@>5&6TWk#H``81F6PLzWTU?Wd0Vk)|Hs&QcJoNW&u`}#XI`< z0ND{#y{X}!X#R+&pS+%tg($xt+_D0I@<#J3MCFKvqYlE0>S``JuQz}`T;%e+F`i}n zYrB{`$n;?=0t*~{G&&LYjoc$jp&7aNhvPU83iZDF9-UrareHEv(lW5(JmPlJ!*jnh~NbiamCKMwl2P`iUc*4Jz~M3n&=R=ksRmRU`su z5>va!;mzw7dBm;cY=i<{t4#8+P8>h*uu7lrDRn3Fli@j2L!Xp6&oM@F;-+e60obl+ zONBNg<0I{{>)7v7Q5BUtL<}18<=E0_Hl?o`<1JLs6p?a@#`5cLr7FxvHQ{lz<4)oE zct2^QU~y{zx*rjIu!8G~{%z1*Ks_KjUlGwoDnNcAV2tsb=Nib|?eTFmhudZ%5Oc@X zkobJOrB`qe{NCO?GDffBnOjnT#(DAN+x2l@L3b#Ox;($S7%;)G>z%E0$UO4SdYag7 zQQrQ3u*dG`?6J>egT3GHON2dpOxK}LH1Oa|dzD~VH$N~og^^d}mPedUs$&cE1OVEo zH+b=E`%5Rj_~3L$=E?xrzVF}RG#nK)WjjKVd^1$W@%}y69*f0HjQz_xXQX`_0Nb*o zNtxbRhg1>Lv9qTr0lIOK#0oo2$4Slw3aQ+ns}gQzgk-uq!Oy(#BlY_kw%Nbke5WGL zzdU%j9meBku>$8jVJ>^FKg!=^@|IbOPPCEbth#kGbxUiFSAXL1Heuj@Z{h>c8;P;C zglu2ugP+~;aWl_IPZxMvHHk1_c$;L@ImpaH=G=>u(s0P}<{mT5P~XuW@D<6vlwXhE zKV+1W+p%Ag1^D7wnj)nZop35ErB9Elq6@rAnQfZ&wI`@xo&aZHkNY_2?m6(2rMh(FNw+tdKb3I%%TY9{Q#nUz+cOCf)O{;TPU~rZExMe z8E>VVPSEv5j+D`?hja_3Q!v$u=vF#WeU%nFqyeW_mp>Dk+(ERiEaFEt%~Q2CSd}w6 z95vrV-q_Z%1Wm#lCR4%ftueF59wsd2mlf!(4KPk|835q5Mym>!!I}da#1zrm^3^a9(^rz5Q2rsOFH^` zk2rzdl`zO@Q21O)Z0}=M+gd(yfoFGrvG2#sr}ERny+)J1=csgiX)rE2I$xKMJTQb? z^g_VvuvSuV)V%ElC(A`G_J#Cx3ey1a+s!+oG)9d`g%ZtsS#jLZxwoBhAu$P?x;MQS z2lj{2Lv^T)cKG`p|MEg4g?6asCgBYFM@sf3f zzse*G5I{e$7#fS-_CI+_cxe0^B_0@CUBV(RcVwEwemMO+1iH5Y`#q=HockS^?oX&j zWzsx0q`9OB);mL9sCZk~g+25B^1(@%#+9B>CRlT3sHzm4%0fnj_OfJYe@Sz+x3@+jJ7I16;H2#$h!a$VU2qE3h4fu?G^Glz(C)q% z*N3cf&(}GsoIq*gL#egsIFQ+edULLB&XiM3*R<3y)ivXeLTy&e>mu!RF_kb3W?^Ke z>#v`tP_LpBqmolcMENWH+=2Pp*=%33qTgLW^m#QD?MYD{O!>TA1z(rAh2aY|>;|bS zX=SXH_f#z>gionm2RW+wft-0hBbQhc4gk>eSE>JwsS!`E&TrsHm+pG#j=HDjopi>} zHM<(JonaZG*#`Xq@piGL%T}O35dSd%=3-Jet>ER*1^{-mT^&R6q18$dmYr!;0vn(GNFL@4O zgGmU~8~csN@&ppkI!NX4yEwc7l)o+dM|NLXcOmFUPOH`)LEV?mD{;e2Stkth<=fnj zeqKDo!R@qeSFEzaPF>`b@hBiy0jzr0rzOh`&7zvcK4{7|e`|ioqC(FjU!pAUFQTI! zGI7{%O3rwyotE@Dt0#ehEKnu+&BmfPU?^Bw1 z0LRWhKAh1#G`JoF|A@EFqpl~{JhHQV7c=auB(~D;RNKi2%l4uK|X*@3@*W8n9%C`&K z$@!va&U3HM)nGz*?iCI0VHp63J;HK1f)N|Wegl?xwh1P+3F8DPYQTzOx19avAjA)g zG1w2wFt`ifQ!zs)P}V~eTb1GGTQtv3hZ?1%pg+QDPm+~O9eaJr$kYIgW}-wqx+EGL zFlG)dD#^<`v{x9zZ0$thvsOmQZj)j_Y0(Ejfo1xRMrA)jF?`I_@Qx2!5Y~>)zq*zJ zGki-ej0WGB=3MQ+tNFwzXBnb2x3uYS{1Y=cr2N8}TPgZ2i4)F|e7)GFY<7e!Mt)N- zuJ!f#{V8P5Q?PLUswVJ-U_ZRHQ$G7Nseu^`Rbv>Zxse!2GtJcHar8H6weCQH_fJ4! zhWq^@W55#|*>C|SU_}xCR=LK-w;wyxvKA=iKx_=uJH@}1-_5euIPmxRO(PS#a_R~= zoLlozT;Gl4MK}*Ir1(m=)y!1tB88lF^Bg^^5-^yCK;lGR=e8XFY;)C@lWKcHmPIg9 zpN4r(R@u}=!AN$KbaUM~o(Y;&@y6<10Ga4qbS*!D_MV0nK0w=y^WR`~)eo^Hrz98d z1hIvdCcV1-`eZ5^(?YLhdPWD`9v1S*+09&^b1;+RsqzIV8zRYvGXL(EqqM;?(2NB) zKVcz*_>E=Cu>x3Dgr+0ZBBBigUXT5ji7nOJDqL{-n1Br)TLSa1TAhYmkC~C>bwfQE z6ZAQkF=T#lN~l>A@|yAt_m|(YUzq%(L2c4JSD!fC`2c{~W~W2#w*hsdE{TY5ER4K5E_Et!6P?hr%n;Qz&0@6=0NaR+Sr1H+iclzJ{R}QawopF*H%_g1_(O`aMqjC9 zBrvyM-*8P+4w4^HmijaCvr$}0d1^?Q1*!u{!*)mctJVTDTs+56syn)I z-PC9v`6Z+@%9yXGcbz1GxEuePJhaEc>YF3j7-Heh9PTyFg8WdO7gOzWlyBDkAPbaVSLPr9mAbPq4w)4Qv# z8=9Yl;X8t_;$hSyem_O3UEi3dte&38VQ%6||HTcP(?yB5(4^uYA^%bVmkyMm+k}DP zO1}W-7sjHeg9!Gh8~l}z-WQjRebifW;FToh3+0Z#IB1#nD~Hn?h|Vj==u$!p7jAqQ zBYYu~Zj*GKFXnJzNycQld(y=r1lgg@wBKA)akcPq(`aX`Ye}OWIf>il|AKXr_xb*RGnkWESCvMk2 zz13jz7ncEanIrpIQ64Yyyzck?sJ%$;+@@;GD|o2ibW4O?qBg*#Y!SmH8lf4mD?gv20RR})LeWO2=!1c|2+~P72bAR^Ndw1ed>AR(NPeY_ZW|~= zIR!SOmsiTg^*;_o`nr@um+||6t8cdienOwHymT7u^pU?Xv0E(>14bA0j}-k~9xHvv zuq!nAu*=pvt;%5qyZw%yKKW_2PI{7Y`KW9><4(7pL@bmnrR^6BDf<4icW;vYxncH3 zw&(8xwpVs>r}M5u&e8Be+PJ&irBlH8Hra<8*`7p)xn!JGC znRduNg!x(E%4pO!znhQaBGdEmirLJ)utw960EwmI08EiQyOg$|2S38e^Wxu4xGDbH zAGh1&-(VjNarH*J&}Xz9P^aCzu$!%?SBa@S1cB2dN z0EM@5$~UQ|>2CGsSkS8~?=1ZiEcscN7s;!}FO8fsq)AxHn7_=AxMeDYSm&~S?yv8t z0|k$Tvbj!f41Bjtj-dOOOEOdK?E;dElR98Vske2JdoVtx%|3dgP~XZPh9q=RmfZn< z>wBKWO<(>nfUZuVRQS6lcOPCs!_?4}sN^u5<10$7JcRxPGh6 zZgSGz2wgHUNN%i@fIzjbsUd%1N;+d&_Sa3n(&IR^W>Y@Mjyi29Pe9$C>}}AxO0ccd zo1J*Z3SwoGJDO+CDBJUaX6;LIYC^BQr#W{5+ukoi>!&E&zN*3*_+s6&s@#U3{8t!n zI`7`2kQw3eBm3A!Q9`adA5}cjrA$@=Bp9qS2m-GHyQuvEoq);N64d%c{imzZAZ0__<+#Ezar}Y^EuzDoJO20MgizI<2`=rgDym@X zOs6kn@G&{I->m&gwJ`H>7|rHzE&1pW;mvmF3))w|<|F|==F3NN1_x23SmG>Umh50f z-nkIbYH{gS;^3Ml%>t1&?P6PhHO}M}Wm1(cjhJQkX={fdYQ#jqDZ2aili(w|iVQ<+ zXJD66gE7H#w%AjWhegBpAm4LC%ZAFfEyEE%{4WsNDHJ zI5s17FFi#A-lMXeIlkPYMs41uRCMEh;{jL5*5Ti!MS%cb`h4O+cWt;9Z#2+2-!JEL z_YJKaaMl~i^Xun`s!7ArS?9zCT5d9FmG@uU=Gmzm*tnzKUo1w>#on6~{0!9y`@O8mV zCD(*C^L-!YF_h`v2kQ5qz&fdis!0b6oI&I&&0v)cUBAbn5M#>d^!MpS)7Wgf@Y^qbs6leM2W>FFQ^s12 z!9q|<--H}@R3&(yq%)=@knQJuNmZw8qTGZ>-F5iNywc+&oT+epz35VHGwNelTkU+QPWaj6 zq2PM?4ttq!&^;3zE!yYS{5@9(P>^cVFr#}&!c!2}eYMaN3Lm}M7I zxSe76yNlbH4`n}W9!wkNqY>gH4>{Jsrcr1q&$cn4iR|hM^_=?hVzvtIBQEHmDYadf zR!lMOnRCmhmSWSb(i$#csbIyJ?Rz}Rt$9v`wLMZDpHt%X6JrgatcKb4k!}7eUJw%M z?SI9dhyW6h#mG}HCyi6#iItSB={$`gCV7U*r(45P!#h0obx9OD| zOlJsrgzc;*uPu)fID?H>TXjUjBRMbJ$&{Q(CaQmL>*Q%;)Hfifo*z!Gvy8lu4yWSy z6F*+1d~%fI&CsLj@7doF60nakclPC0*N-%W^TQZQr6W0Nh;f`tgOkQH-J42?rt$nj zt;nyV3<1kJmRY5`PB_x2BMN@xZ@I;Yyl60Y<9d=iZRR35O9t<6N*S(vgRkE!uB_`t z6O0!MTBn6f?9RpXnIi~2J}@u1bwa>Z%KdbgVxZQKa6sMde%2}%#a>Z<`-BfoidQ97 zO4Kgl3@3i0aBoFb2Xu4JD*b1W6eY6&7C5ZW?Sc#G^c=h+Sz9?mss!95zco3jP{T5KW&q$MYclId>gi@VU38wf}qhd-qstBTn>r3rjx_l(0M;6eZ*b zy3!WOyJi5#h#EqXD47{x+70lhn!xL(a;qk!8!)2SqPk~iDRR;}RePNz6sH-yj zI{9+Mo5-l7VJ(ebo_NiC6h#8E9@=mD9XCGl+FOY!rCZ2KaIcyf*%gR~c|?AHi|#0= z5#o{I@XC!Ucu5E->vbVe&9#uEztwRw=1hdwj%<&^UgESkO)dG_0qnqmQtx+ubbTNg zzN9x1plFil9mb)Nmocg*AMey`d8}* zIiV`uA(TVpUw)TRkZhEf#8oI{J_(eIr;2*Y-TfqfP zx@|8fwly0`fWK>?!Kx#VV{Z)DK+0~>YsJg^h3T;5V^*$w&=`GTxsAFpW2Ue0K};7w zTgo@E@T+pVvlhxq9I##wP_X-p#5xt}s+T|f;*BV~x#rU2Ozi<(5k z7B4MAXBiu`BzmOW5m)>5@~n52iZ2gEvS%q1I(t$w0gy&7rKcQf+l}`JG-xY}WvRO| zQdf{ZY&K%8H0*NX(P?VmSpMQqaWX!u&6)q>-5+6+(u4TPMa~V@&VuctAua{|{G&SF z;duX>r{nU{nUayni7SOv-9|mD(r3VqwtRofGfgpOzjl`Hfna<;#Yj@6-FfUCe?&yD zemNo8#Qv;T3IaGPP!!m{L4^`IP|jU^y%ds)GXTtWhdrw?Skiv9(Tscv?18AF0)7z* z;`dVHWw?u(6j|GQfYH%jYIy}zBx!vZA;LtL6j9|4CjK=si%sqwC;+^z zbp8pztEEGoA|>#+-EhJik@$uca}={V*QI<1jD4pI6MwLB8H!Nhp~jS&)KuG-`3(0&KlWC)`0?cF_Tu&8lNd4aI*9|6r{M7Ynz`5MP7Rxr z_=-W6g0WfpH;ZA}ENtHF4J9TV1P+Gc7wU?;{(EXf5Y0CUU2ow3cKHDUQ8ZGNRPxhJ z#2(ZjtswNMrguu;C1u1?0t1Fw+`kdo8acBywBHj`C3xv;((wGvFLmrh?8?-cG&!x! z8K&c3`C>1nK;!juKLXX6)+FHqq{pkH_^rnO#5OgVujSa(s|c7u=*GqfTcV^^$#_Ch7;po^MatzY?xp>-aJgdU zL}Ar+Fql3b7R!eyLjI>QaY)q+#3KxsN$M(pM}g%X(twsS1+HLpv8ro#RYh-mP^}+q z@o{*mR6N6h++d!3D&>x>U;t_B<_nUm3PeN^VNQzWN4VhR;|E1#p5u389cUWQV5Fdz zS<(SEt4c-K?K#|)wmrMf(7*S@%V{DZLEsx#qND(iPr9y+`&4A+wilv=xk7Y|a9dJL z$icst>n+Hu8|^HX=4#G7VZ84)b^)OX5Iw}BGB4{#?u#hzGDsdfw!6lAMGnm^8J4C= zSePY9ut|W)Prka6=bJYt1_d6sE5=GYpZGwGH!*(Lsw^J@>aIppF#Up~2;FID9@%U6 zEDInR0Q18!2LA-jRRtF)2nRGuMb1tBcp7s3)f9WJC16|%;k{zi6eP|=o{Q=Rz)qw<0K)jg) zxFJ1mrX27a#z2|qisWgc7RR1}xkhgoV`Sgr==(s5 z$E07%hiR=khCjY>q7o_8I%TP~-fkXB3KnCjHfu5xziD`5#tMiE-y(69K)UUYE)C&E zO_t(j(28PDYbUi&%0l^gUw)%O0Pra6N8cj;70>sGoH9VXT8gg-8Jq4&RToQD)$ISK z-dRYW#v}uvfkw5m4y(NQ2;+;`)HLSes&^*b)B07-x%}@s5z3z^$Pn8r*7}Wb5Jdr8 zep?fvjl=K+qL`=|^4X)8$zR&(z|#f~?Gf##%|HmF%@2#pvfhO*GzBUT1`|bE1?rVT zpy6vY9h3|*7N1)s%(gcLHm{bbX*FA$Td zad906nHV{Lrr;CMpXcr_2t$;o-<>1DBk`s-5*eH!8v3J(0j*^=3(d?{7#7%3ckCNE z_1L@#X2R_tv9z<&gp+4{KSG&!Ls(UbHAt-g)r;5|X+E|H0Mv(My~%SWhr^Om)(V1+ z98F)B9=g^1WS@*mg67lB;#k?fQ7RG7o}`*VU<`F5ji8{!jAXa6OM&&*ZC5X7AU~=o zP#Cd?gP-DUrxa<~vb>V1uxNzX>dN#cx#q5j)ubNZzZns#Bo87{ORt=b--IR{3#-(- zlW<}DZk|maW0-b!I}VZ)cB98j>Qen#Xv{UWCoJ;DQBgJEtH&6gkvP0QV-x%IEp3|& zRd1eQH=tMcAUfzdk;jC{KE4TmUq2Ms>Eroq%lVcV=c_OP_V@R|EQob&>i-IDLgYp7 z-COT`Pvz;BW(pcW=gj=n@opTa6iV$f7u4UQywp|HxHT4Yyxa*~z zEi*yeLdy=K_)B8dxoX+-aym?g9;+A)z|XV7pmj;L20sWYD&QM3B{7WoZyvV`e$?Dy z9#y^}5j{oS?*M5BtloX3NsyHYm*#mcCzzw? zL*<1}kZ`${^z&q5j*p?BkfFSiIzKDR_j>enOq*4&gEf=fb`-5rafh;__zeHPn>Fjp zd%Ot?$^uze?TRIU@y@-q!hup}D5cpk2VV{?&3T5D)!T(n3Maf)O(t1^w5erY_#%G~ z`MeeK1A7XuZSZS`&nD9O@PUF0#qsxy_mdT1V2V&=gBv&k+zTP_z6Evy<$ z7Wf6`|6alUp?v5aciRxwZxujY;;`WaI)B$xSk!kb?x~fu_*zr!uvu*`g!uEh5$R2T zgZk0}+oK(caJ_moD+D!C0f6U00a*^75)Hf+URL&mmezVaw2%Xna*fnm_;l4#NZUjN zVhWf6bZ)}U;ozDxXP-gdK#GTE{VY}}?$xYOzSIL**RXhbqxg_G>)c=l>)h3+g9kKv`4xT8_af5s3HtEYlX$p8_(^fwbL%FZ{GP`vzrCe2-#k(s6?AK#-80 zZY~3w-kK2}X~KVTD;9{jwolK43g4mFP)Y?z76P`b^_!$Sdqu!J;r9m==G-PJ3pldl z0!qTBiZPOJD|R@Q#2)Zf6H37jWWJO)`Iw{Z=r0t&Ja>ziOImswA%;UTXHN&qu3k1k zY{UJY@J|mI{9{}b-Y1_R?ap`-ur$JxuXVzRTS7JkL(c-1Z#9}C}XjH&@Yz72cfOlbjYp%$g$uGD!Zh?Zo&N2mBk@7($poO^FxxVSdqHE?ZOFD z742%PhGQ!Hv0BtIA}rz7Nk&;0&zrpR4!?J|bY>1RQr(At{@7eg}@g znABb~FB}R3v@2}7sYyL9MI@n2VHJJEzr*u<&1=I(!2?2<5B}E6bE>T6O#|GSDGDJc?C*lwl3qHk$KO!-`BN5dOkj_W_FNQ2THsQ zo=g*lgC`8?)wF2!wcv2r0hVLxzX$daMo|;l(%7_Gds*xWYY>Z#>UCYb3KI`5&X>+c zuYY%=caI8BVzCFdEtk@GcIy0XZoMnVC9#ZaH$$G-RmbmrRjdwzU<=;qa(3^ z`pTt{{5{6bJ%3{#iJZco2N{f=`G{piJ`D?^;;AB>*eE&1s?r3so`_j-;cr#FR4>p zOVtu3NWVhmcM1?=?t1VkL`{L2RY|uQvC6X_V4XH=wS$P=kaRrt5b0CM% zM;{6LTPd|}7ug~{F5tBUS$jtm#w4zR@7|_ap4$yF*dASdbQO(CtCKj#ihqk_yt^RR z?XFDhAL76*TiDsll`6mo^oqe0I0#&BGw2?6$Q>A`p{;15fbr)?b-?#$6GwS+IHYN3 zz9d1y3j>?H8TUuKWn?2BCLqc1>t*!8l%y{kM6kMsb*_0*19Cz|LHvn~fDEPig$caS zxN{vCar%(Zcv-(60YoGzp`8W zXz|$1c97~^X^WSiWo5kK{+T-nI{sS&n0O`AOoq6e;ZhH~De}|}oOaMq`WLrzl(^=K z*aC5#O0H8r)C-u7{C?BCX*e9W-wSKwXle2gC1UACh)gV^b0`omXK3$eaG$c8Bejl1 zZ^-oF=<)Vf&*}T+CAx#4D#Lf}Cq>PXkGI}?2zz#f5o(?0vKZbdL$X@c(m>IoR<7zm zs8TwPqjD(F3OAY*+dI&x6&2*BFEMVa;b?eJeJ62rjxaobWz=B+H$ce0Wr!cR+%&cg zS^!z8Eb`a=?B#yqCi?OtEVwIX1TQp|HYviC(;=S)g!QcnZRYtJ&x@Q{p>O9`Nq=F7 z3v}(CDV7N~m&wY3zeaf?Q}~nT$$TMZU8EdZ_22JzOWgzDnmMQ4kDjXBd{Zz@(}XO7 zO|rv8DRgQ+3hvMob$%3DbG{zJNQ?NYE0R+NBRR$&3yy+n1X;wx z=Dbbh!t+=`zYh8^SHAAo^&aC}730q}{AA;aoIb*Ux|fmzzX?Aw?xCjV9}Y~cw|%KR zBlsuxK6Ht!J}q1|TI7F~Wo0jQL=&K#iYwAzp0(mG9vEdAEak$VyEsNc(u>m{Yc8=* z$q6C=>TrYOl}Xr+&kzLyFd)U9Ym5!)`|adq9GO5K)Z1!0w;S|Aj{I? z{gM;Kgz=(I$KM>+j-b=cl7E|1<7vzuPin3^jDU0e%LX3x>Gu0$i7+TD(}K8lKa*O8PKjmR5-TJ? z>`k5F^2+bEO_D={sq1SH!h_$lhO$H!tviG`W%5M@Qgq5L7Y5j9)Rx`C48Lf?OdotU z8E%1$B`piC8dJQ%s)IuPgJ@$5WroT{jiMuZ^NhCG-&<{JE%BMG8iUW(xckwA=%TrB znJo$A_&cFbwxj!1n~}bnZ)zf$Pgx!pXC1#an6)xHa)+$nD5xir_`@z9u~_ZO_VU^J z6N!EeV|mI=6!EVy@%r0j7X1V&mwCJe(#F1pT2iGwi||Q5nQlRz)~8mN%0#WH7KE`j z23*RERno1AyR5loMH17@X_^?T#T)!5UTOpu_Ls;#O1G@_lMTHu9md2|Ia{>MrJqjA zu9yVK^Odl)09xO43~|nAYs%MqSPz(%WxKb0C7N}@Uek5AwCYk?s^TaBO5u}Hr*uuF z7fL5xnBFZjIw&oLVN(9xcwTE&lu;VK0#(~oLDg2p6MupvovHE+=t!rEtwPaHh(P2P zEs^K02xp?cRAAKCZj2%FyV`9K>S~?WrUN`$gQiB*HPmIz^5UAB@{1u1{<~7fOmIH1hM>(AbWDP1V86@NlV`@iT+ctb28ohU#GcTd^nGO8duj5MAMOmo~)l39Z+tI@A3@r2~Td`vq zf6ATr5iwW7C3(lW^U;UJz_&6_cki?7KaS2KK~f+Jq6cDuQ?SI{sX}(RyL0-XXW0VX zkpD--E0RoBA4@`VkA^8deo~!gRI~>xDx82;llqSB)_={^)-y^ANK&p^fLJB;<5UkG zR$zQIwSIUjsI&smH;MlWJL^t+z{U>Rib};!HbM^xX_*fN0fbOoIZ_0_fTOQCvPG+r zi6v+SIhp3~u$kcL$DOBKICxY8)fypTfY{Bmd^I%!ONQ;-UceAxzH^Q!Um4Abt6^Mo z0$;6}C)15&81MaUc&C=}re#9bpg5JrisY-HF!Aai7t8#v&JZWwF>Ou2M}QK#VNXo! zz*aNpR4t<0D=)*JId+zuPkBUDbEms%ca_Sno4h)57`Mvmxp;Ve1;QB$mWR%;yzkj(3EKK?)ox(1G zQgDp&VQnUOn?LdRHs4)Y%?_w5K9QV7i7QZ)8Yshk|Vq90#&!a@=zEGt<>OMn9 z&lW)6vedVA4Yy4pIqy5|VOwFWF3TUK=jidfqU|Gk5)%sY*@8y15E6YSky*52Z+UF> zOMWxTJOIjOM{r;%C4B$^3|2s9SwirsqhPRvwW_MnxunR`QFR*xS4h%#^E_|S(Zu}5 zo4VtP4D_m&Ufv3|8t!b(d*Z7=OCV9%boWc2R?f_Hr(^ZGr%1i3|e3VffZ`HJOg zj?w2O!q114wv56J_gJmn${7hzgX42b9fe~;@Q`q>?yBR*prVWwI$5YOyCkJ!$R>SZ zmTLy4EGmjUb?wGx`+&2wuu;iYrN3<=cC6jApB$p2eF4)91r15l5n*ne58Kh=-35_< z)(bKy<(_eC?s)v;?lH}Vk36vXf&laZ*`?i9BEvC3%-bU!3wH2wT-rbRLI0Sd!T4Z} zonG<9ouWwgC;(ELRy46A2-TNVr(PsC71uq12o$2oC{|h2RGCOPmKmns8f)5f)r!lG zKZs=uTLn(SlCe=me-z-r^c-o5Toeb^BZZM!8Jepth(MNQ@m=IKfzqM;**dr(SM#^D zj7!J3UZxbcfV70a!mu`P-M14=ByF~vptP=dI)5&4FhCacG%dHDa;@rKD!WdcfUrHC zznNCL$7#9Nyw<>8y*orDY~TiT5q3y9{Dpn1zlXS^7-yAf4h6M_OxuZ6EH0~n5CEW6 zVZ&%xc!M6ubMK3FXXcrG6yI&D zx~a>7niD*J z&qthsIXV(TOu^P*!|wX7`2bU`KHiN{DyuW8j2)`NpiWYPIZt399y{++)1X84H{1Ot z2a2mbdC-4CjaWaHejv|k-htHkX}r5BtM1%>Ow@cfsS;4curw5CNoUG8-JGUTjg>UTo z(F&k=(nu!h50~v|q$n3N*-&A{%zJQ{d_guHuG(jiZ&G%LzUha4U(9v^dc_d&kRTMo zp~lH-AB6i=9{VATPj>Tfiymr-X9$&YD0>FX*W6c#(D#G?n@tOCOXCFi122>E&j)f-Yp#652% zsikmkNJLh`L}i^qZDtgzG-=p^ZLU-2v)No;%Sf2e4E)!o$twJv}DX5emZmD zssSWfnFgdv2E=Jwtc_Rn*`~Un{N#=ua3$!CL*Ww4CPVkzg>T34MH{oEKS`co1lxQK z%3~7~b2Wel!2?G@O9@`s5V9PHmciRvemPE_Q?}eVRj~MEK?JwO9aEOm8eEKoh1qXj z1ry_~7r!g51drU79|{uSM{&d6;Tc=OQSBUx<{AR*Q|L#yS$$SC%>aKopYBA({xO6N zDgu{lzaC}g)c7d!D?PHq?qB7Bvh8S>2)Rb4B>d?H2sqJAlVJS1JTgXLyBWj!dV78Z zDGKN&y+O?e3d9G1Qg_HNrU#!avjMuw+>*n0bFzN{6k#s=q+EilN(>k|oT4?xA*A;= zlVR+$2?FG==6VzO$o%)V_rrlj-NjNMO&86K`A>9{dG3PPpnxdKvrPk!N^0uNSI1*O zcBD7+%78vA^J{x#q)_|LU|4Dhl6n|;LU@w%!ctC*F1G)EH_JPwYGUO^T!&p1iARn? zc&CpFc9f+7`(Dt}!PDT7_*qm^`5i_X(wk<{{1TL~1m_4&==MP>NCWmt3Jx-*qrvR-8?X`_$vUu}lWPjrr znHnI4m13&DO_)nJj1gU7VPs+;F#ESzgfxKA*S|lBXEF;LrHVIP0ApC@ihuszy{w#Z zHaSc=8V3lB+snZ4Tkut%JMy?SRn#SXI3^H@@ruMP+74cl)#(p-L#eu_|0lIato-*kAp=IofY=$6cevIGxXi0yMI<=R!_wwEzJPb6O$VZtSUccpP| ziKk;xO$YXyv8#`1m-1RPtebv$9yYCpzkhFRB~~$L@F^-PF?X42o)AAO?yob_U5Bni z;azDfNX`Z9J+45Prh7$L zp!s_Z^$TIcOLKCC4Kg;7Dd^~*tE zFRcN2u7=3)HQqX4^bguX7-lXT1`?0!fAit10S>o(^?nafk6Da7R8~&nP!WuG9SVYH z04|_QKj1=rXwyH{^S85&iN&Qj2Dk#%dQs5aSy`?q-mnuxWh^XfEf%f*n9}9QF6;{T3xMkAq zcLG*ok^`*=g^%mQt%E?0CX~7K_XZVun6b7U#CB7Upu><7P_$)frwxml2Uoq#&W~?i z1J55e7e?pM;@|u{FBt;}md^DPL4D8q(kvjIdwaw18-HRCU-D|zZQ;OFn%G}K#6nlA zZNN);!(JH?a2ilBhsgIA=6Xsdz}YtAwY!Z7#9HpW4p*ykPlb=gh<&*{;K#abImSU1 z^9kEB0?5~y-$ShW7PBY6f&RI4q;$nX?9w|;20#1}wu@WEt_%nu6f z2@uVyRq_Z(R-wDHGKPX(YQ&$-IA7_jAb7dOf&rXs$X^?mf2xJL!z68Ak-HFyPBdX~iX)-R-? zdx9-dN@BqR<4hWW!x-RPNHu3}>!??utPnSbU$050v+UuuS+>uQ0|0;$3zF25AJ%q` z-&7fL5gG@Bhpav1D>T<5T4>$obX|OZ4WPmdT69>9#msBbBDey@wH1XGIvnklhd5Zs zbEOI!a3vLA%_n_s2L{D8tp@G7J)X@JrAZQYv^Ui%FS;8Gd79$yeeqb|PMj^c3Y*4a zz((MrU$kdpxt*%7&ey=A%vRdb*b&qnQ?hPebg+thc^)xX#6JVijB-Ax__C-S8)j!4 zsp-J#WRb~qyvZmtguM4TRKMr@J~C~0^=oe{4^uNU8%8$P+(x_^H^z(omsXcpoe0-~ zo9NMAe>XTCcGVT^x35yU-%#n$rpVj6DmPUR2Z}tv19OyAV>fbsf zxBrDV&rxegu}PhUvL#Yb&47wd!Rd+m^=Sai(qrQS7VGIStM}^g+aug~v8+X>eu9zk zVh7wSNg!LrSVu!K0g}@R)%GJVQ|TvqfN^+(AU1sQ1=mEgrQgea$6Y&Coke~v>v_GL zMojPNRxE#u4mJEcB%1RrwRkhNW?YHd5{bMkg7emD4SJEt**!5w4L;>oUOey52 zlUo@&mqjS2i}Q+Y7)dy(n1Vnat0}lT8w}Ds{@MlT0JE1JUdXAaDrUyU!x&2}o8h>E z`yG@F&6W)gwe5aOcsm?NUYM#aU1V>g_^UN1@1p2NHQ{w6Do9&kumj)AX*oU0UKNS&=S!0@!gZ(nA~r1-yiuytGQb) zSx~hVlO5oxCOm!UQa@GjG7&0QJ`K6z8oP=+A?{kY7~NFd_GI@tp}-%bUo@$XTV1eR&FrF^!0=74*p< zf4?lNgD#x4&P8Q+&Pyv9N7ISOZ&b^LB`gbcwh{wzXXydsvfwMu5ZTvdfA9_C^y!zy zejG&WX{h7%td=4^vEy@>Pes56o80rUbYu&s@HKw^oF&DMwixK2E|Ne}q5P@qHS>jl zTffs9(mB4>_QhE7wvBmYDjEg zDtL?H;T(XShk3G`6;_nn!z#`0;6lq)yPIktx<5kQn=6tivSeV~K zZqZDC)NA@cfz%Pu@AG7g?cEXHt?;-D(`QFZ%gUcVRO&*EKLB_*-p$xgNGtCMF0~RM z${V#rYEQOnyBOpbxxX<|FpMsX6#n!hp^o1-hKIXiiGQ<*wCI_{AdC-=zSOte{VR|A zYwR9WV87+lKU2@BnbC*566^Cg&q!biP9B8T45@xSE<_4Luihw}zOh;FDL0RsUzAo- zvPy`T+HWE-a~>yD4aZ!S5fj^7krvpSl}MwD{-Kjt9qgLMxF18SHe_jqj#jk3yg)2Y zbnBC@yh0qXi~HahRS}){ehmyGEuzseg+oa#F!AYjB2znT;8xv8Yw9MxRl}2XjnX6J zwc#CToyK7Ko$J)h^yjc7c|}zb)(%$#>CJ&cMY(7>>c3&X%jJ1+YzEA&Cj7X=clNkO z5jekI6!2oR6SaDeQzT#)@ACV+Y1d&r1F2I~{Q6MTf6y* z6yjM-#Kl&X<+xYMv>$;o#!Au}j}*D7vp9V-^+rXEQxEd;vw=7 z{XGjxRM&CD5OP_$+uG_9aht_i7@8IH(=5cjN=W~)pG%ugq7oer?0R!;$~7VX#yQy zIk+jqj*WEOXO;#&9GHGfyrWSQa=>ckH-w7(`4PlehfQI@OFp?_D zQ}$izG!@eM0QFc-5?`dMsZJ{q@X!24sf&jJDPzf`ZO`B;S=;#@zMsbA!_PK`C@*LF%Ot(j0{1kM;yxY+x)-bS{#TqQm(I&vnLCN<&+nBh z1tYtZd!&PoJV+=RjUhiwu9MbL?DIvp)e30V9i~XK-PV|}-}f6NZT%q;^-A~P{DyC8 zgE-Zs#^15tq}B4DaWhG^ot#8V*Z6C8pF(!W7QiAKEH*P(_+uRCVSiBuiW<= zb8+-$H_V)qx2{wY^bnqB2jMCnS!f%yEH$znjoM2|H|M{WA28 zU@MYKt!-yMs4Mq3Zm&9$%T(-c$`37RAdDC-_htN$;hy}UR?ay*BJIq?XZ6|70$rBX z39gf9{vJ|ez+gSI{!&0sJwY>m(>#suWe0GIXSxR`B^Mq;;5DkmKv3Ex0HAt1JfVdu z47dhvvo*|k45r+l%a+h-)+`C+`)lLc@l}T94Mj_VV5rjujz=53lqZb`XAxD*n!eEn^7jx0r1OZGV4=<9ra1hSuRGRqxhW=;iY{!9ngIda-=@fEs2If z(-_s|$)J1ED+}SAlwKb?i{x-4=Q7+beYGG~m+Pz03xh01kFz%1R{1`Ec(H?=%TgAH z`CsKa9SicR47_Z5znj%*X}rqVq4|~By~>A%NwCxq~*L8pL7 z6Hk^jHwlj)h2v$(w)f}<05QY|;-25rIQ@)3zn^zt-`|4za`Lm;(LLw|2neWoQ^&Hn zV#3tzkx_2}{XXfb-?4yRQqOTKF}DKGJ7>W_)Rzgwt6g3MR8my?tnNNEH~TxS;EfJN zy?v+;AG~yh|Js#lpJ)Zy0tC?l+nCgRG3hOc15W4i*XFuY8A_{nWl2-?WukBLTTe1I z3(N-~MO0mQsF1j`l5;lc zP`N+^3%eXBSrg#CV4h#Mc+>@FT#6HVh`E5?z$1`QI})Wbk;L!y`uXp333S#|DH_q} z!RGnBc2Y)`=k43xD@>o%WKIijoiN5mKoyx|t9{0P$Ap_Y4Nh;sm*w$G_ltoE%=eD@ zAE^6enqhIMH@xW_R7g)YFstLJ+-A!J2xrLIK6F}pi9*3$IYrYy^9qCuBFt^EDJ_{Q zc3r=%T=Zg9VbF#qa!$4F6YE|^T^|XIZS>d=1WuYMhl_AXL`S*^th`0{M?6>xfA#BR zrP*Y@h4lgJ0j>vCuSwRVv7!NGW`46`0~}kHCt18D9EEIDmJ|I|U{^-M^V=!uBmN5O z`3k_#fue9RPQofDIup?azD4bW0gVL^F`<9=z9P^AGqi^o(#M9jTRt^LFxjxjij2Q^ zW}u>!z-}zVbDHJ4O6>Y8na~IKw5uD+T&5wSGgQT4`EO&&Ozt3|`$g~QxnSq_;o7vb zVx4X1T>K@oQdQEL=f|0LZGr zB>Wh=d{`TGDr3A-84O3sR5_d^@1%YsnO)|oW?;N{?$SgQm(r~$O&DK4<2^;R3ov3k zdm*wtafM$2n&lx)+g7Gq6&d=@Tq~K;U19`VTw=bzS^)uSKjZ1 zRR**dBpWjLp=+m~?j|sn2Z4OAm1yTer>MVSOpvMnG6V~0)RA)?hRr0%jQqtkHtN|m z@5^Qj)Tt6?KV(L)LTU);u~6g@p7b3Y|Jj`HM#zu)D859U%PG^|2kPNNKUkZ&-)N_#P%>}7=l|`QmEdgWjS)UTduyB29R;FXlKrvmEirVJU;5jAffe`m^wO$~8uYJj* z;)3G52-D^3I~vO#GCD3dM6ZI=7BtN4nqGfRnH$$m{`CyCVtK@0^7x3D#?LP3Zp>S= zm5u4>FjNkaAnvy_T686Hv-Yc_`7JQ;0@USd4IPL}Qe=$+r9&@tZnP1fWQ23;&2)A` zEx+wJ^Snr$)S|`{U$KDS@yG8DZ&6&yDixi|r(1sfoyXB)N4XZuK&+;dY~^ilt@CA+ zUBLuM)p*0Y$XZ%dJ;L_%8ksU{Kz5A-Z8%LLgj8n-xy`h{Rb?L`NVWqsXle-_C`(?@R-u(PESJ##u=MZeeD|~s{ z*SLT0sKME?0lXH>So zB;C2k#9fX8*DE)_iHa}$J>7L*#Xi@x2y{uOxRO`y1uwtn0(*;Fk)re3axeiQ;yH+ z1Yp`PujH78&_WS5gVviX)ZpNb@5%gfzFF^+=P!(AdiPglwN&lu-0XZzGF|uKXgTwm%kp0WL~~VBA>)-!o}XECB2%N*phL0j0cv=UJ{j* zB79T#JyACj7tsGD}X-p+*qk9}B*R+tJD$VJVBM$S* zW@C6Jps06f&r&`F32R^BmsQ}y#zPsS#>*7-@%7=5o$P)8o=oYY`|}Y~6TeojpnXUj z(fus*xT|WdU8mXqS)1g!z`z>pfL zg;z7bs9WV;m3KQvnsMnU8i*!+@lh>`=FDuEW|5jZkJ%z5FGQ83(Bh3~ne~Im{`2{e z#s2w(%?9TAWdI=ck$moYxa||Y*;4+**{R@M93MANn+#XHQ4q>^^Wa`IRkz$yex@7d z*W7_W#;pa;qlQXkDyHCMfzOp~iSXFK~^*x8KLwEu&G|&Vo8jWox=dq%56A7W5(x2P>+;7N>yB|G*4lV(Fj-1P(XgZv7GZO?Q z*T)wq@&%F{z>u34Xf8w`>0A$Vv#`H7)xkG>iJoLr7n=Uq`5U!$sJLJLlXGGPr2-$Q zW3=qekc^In)BBdHOTQqx zb~dP*_u!r^IV&o<{P@ZE3)uT>HK4Vdrl-PeL~6JGjwBSxXZH;>IHqH>un28J|5gF# z2BJQ+J9MKC^TBqN^fKJLCty+OPNRyFZ#DCc$LASn^$E z)G0%fgN%fK(-;hEu7g#C_o;NLRBA-FmJZO}IDVjQEO3X8&fJR)t#9nwYNc-vb67qs zs=C`jGIMO_qx?lZat^FiftkYFQW`~pq)a_1#`0JWI+Mf!A5njcUP+Pzk%uY0(wSdV z#M2{D_)LU(iNBsb4P;NZfS>4_>6F+T*qO}LA%+KOB!4%aIwTj$ob7TEKGX7$U;*?XhMa(~KpZ$52nDXAY<*&eYfOd>b*7DmnfldqPrMYiZpgSr zM4Kt_sSXJpG4J;TsaVzgu5_>)d`$|QSbG??d@2)cFd-%x$Mi=+1_jx0zy$QwQCBIp z&u)}09wV&Pc(d_9pq6IdK4Aju+T38K26FaG*@HIvDXQ(p+a}HA zmMU2Yr?cJNOe*|dTc!0_h=PCLUQB=1=%+XteO8>ve`#|2ll3$|6!QpD{#3DFzLn0_ zu@9Z@owq3Wt&glp1LX@?EU|@BdAotg42%VAON<-wPn=84Io`(eU6f9w&hsygiG7u& zGX`N;ca7u#8r8b}rNWhF=V?>X0$e@?Z9O zN>SZ-BRUcDx9ig_@jD;_dm9D?8Mv$d&E#ZcmMa7@azB^0A4gO7${(qw)Rj~i`BYM8 zsZG`)lnjmon16oO(@(NrFGYHv>pVHkE~=Rz=9(+lfyK-DRm$S&HQ3xY`W|zjZMp2m zyuk8ob~*(3W)~Ty9FHvDvbDiJeJZaw$QiH4zfjC@tGX6s2A;L13287-=M2S;JE5}~ z1R7KNVu?od01T)>JPbT8+mbK9ePxaV6|lMcr)ck-HJ)hi*0=Gdtcd{cF4@ViwiHX~G9y#>4!%3gwW0*OiB|5=>PyCSU~Cnzp;h&F2xB%-+*2hg zdLD5G>yIbt?ZGhnM3M(1_qNJpZ0q7{gNDc0T!d@;YLIcwcCV@QaO2<)fwlqoT*_U9 z1rC!aw*qvhj{uNqDLl?`C)z6O&|2xS;~4W!us3Pw*Mu=Tzz(YPFH{7UBs}EfDowTy ztuwbZ&5dZtMlTDR>+291)ZQwdk=^=oKBg#1zS8WVU4A*u7()^Gi{}*jA-~>B#IIZ( zmi&acV1I+B=gfy0MnYet&~RXtqexNaouYRY%GbWu8#!*Ngy1Z2qY7u8{nc>2w@nFd zB{<%X>xb~`y>CjavY;x=#NAAz`wee|(FSnh)4M`arYtD$r{-RXO1)?x+0bGA3JU!= z&!ZEU2|}o0cln|W@9H`*7fG5O5=bCd2+j{)XAJ&1zc4)r*sDIKLsmr_r{<697ym42tg6c7a##O)9tRl;`yHk3< zU{B&aoY>~s_a=Iv>*v#e%UWC&o`IgdNFGhE9naRZH$-1#Fge8fLCbfH)tPPaSE404 zNTiX?F*EJyyd$Q)2U1mls1gWuSu8K$g_zRt9`!A;RQ2RvDPpv?gzZLAw>D|*Gscz$ z`cgt)B_gFk#}8Q)T(5;$tP;q<1J477##DgKkmn`bk@MncE-sf+CDd0<4<*yE{`Z7>e^0V`7 zvqkpcZw${|eSQS+)h%Glz4q^II7BTktb&Go@Uw(QPF}5iE`m-Z4jH)6G%B~o;IYjx z`+U=D7XUzE7|r&e7kYrhG_pu*2+Z`V@@Y=U$=cRRORMGuJkIh8DOPvA^6mP3mPi`K zkK9baSc>yol={3)KpletyfWre;j?pgi-dmQXV3H2{h}kz0XveUzJfvd1-u~{ns(|S z)}Q1e6lqE5SoHU(s<$)`6OXVk#di>Hn3mNFbj;N~zi?ju4HzIlonAORe1#a z4aEU}NZWa6yBS^wKq$d1VK<*d<}nY`+;f!U#@4@u2`9<2g|;MCf9R*_x>Zn(DVih2 zwFa$LB&T&a;3}#QuSK(_VVT$n+$sJ;12!@}V*1N1p>Ye-_KX zUDH+2pqIO4Xv}y$hE6KE9`l4GD*T8`zxpH--#(KDKBUSia-36#=G52Ux)c0wlUaPy znkgpE0fNI@&|n{*y~UTT@vP|cd4JZPR7*r^ND;e=Ewd{A1Y`(C!z+cxUyT&d^*6Nz zFT)XYzXMLLt)l;WRD~ItL>8vug53NA*DHZ#Go82j`$gznntXH69u{Oh%{?ws0dw&z zIKu?uwB9GM3vg}CrTqED!h$q1Il>DH8e?(nrp2O1Xr`%`13?%i_``VZ#Q(z}2v^Mi*|r zTr%{qGN;c&FsZv{z6M?!4s1v~e;*%^iVcwHH7KKsAk#0kNNk8=BT}<4=D)dt^2tas zc2A?&A%|oB>+2e^YAmysaf87%cy7Qr+0gWdIHOJj#uW7PqXUag;cO7Y%{p((xZtx| z4g%=+pDEKs>5h5;!7#=ySbeodF=4Md{Y2x6lp<62gvkPvR!?(=Io%2{Sy|BJ1+P$% z1)D>9y66f9?0=one45uqD=5*HxZP=8Fs>$;vmD3g;OnHM25}dUe_EokebV=tMLY4% zMy zZlRMdd1Zu4e?6xrNuL1FcJg)pX=b5R>;d zV`)7$fvctMmu-Nsa*R8*d_=&t0|Sy-+0vf$g&%xGU%n}r&XWFp2&P>XOA+#BeqE$2EKB?qwK^O{zIa8G02EbD=Y;&! z@PsnX^N>6*WRNs$tstF^5tX7Sbk0*o!gXBfwGrmrOdQdox7VgwEuD4!+x%ju-oSoN z8<+g!=)Bcig~0&&Kn(OY(t9rkHcaneI!}MeT{0w}9W4Fj9D^h)`kftC-ql-5u{~P- zlQ;BC3IV%Vt4|uatK+ZgVi9Z2sFEZVC-l}3O;M! zZcRCI7d_`-Bjvry(o<58yzig^Qnva#APY>w_VWqea>7U}FFx84Gw|P0)ybDD;pW9N zZ7*8h9o8Cf%QQDk3uW;tSrzL;Vw8Is-HEjpwq82e0PLD~5ptKd@fqzzx$g3(4m>*> z1NIrA5UnJasTjFHwlgjj^JC4p0+JNorPL>PB%B06$weUgZ+(yHzz-U({DFgUmWrbl>t|bOf#7Z5~_C8VvZ!O(O<3a(+VEO zH^Ez;XWBEBp$&Mkx4_3-bDIQgT(m?=XOQjZH~b9(Rds4(>>!A5(g+NrSR8-FX^%*K z9LG7-%7ln0wZe!rPs6_8F1=dcVD+cqYXh?puAr>_4mjQbM>_QK?H2Vh5JXwSsN7a7 zV~gr>etLaic&5*BVB;`JU|`E?_L z%jY!^v40(K0pJ}SQFqimOf3;5Qcj6e-bE0$F;TI&FGqa;iy7dvRJ=nOcWjmt?aAYs z1S_G=$(BM|nTZ%`bYO9hg zg1feTEHWok?~V8|Z9dEN+A%BDSf*X^QWd&teSkj0C&Uksj{T~Q%lgJ9i4zf<6Rqw) zSP23cGLg4+t2gt-)!UVzm46#v?d*}Q+g?sl_Tj&LhiQ`q&m@#*Smz`fiR_ml?C6|E7&cEjp&&(_IfwEvzNxP6Y@9%2yHaUek zeIrBdD(czm!AP`+S~*e}ZK!r&x{|Dk62LuOGXNOV4qB zHA(w_3)R@4tmtDT}Jy3Z-}I=Js{ zaL2ePXFXZcU{}~o(iox;ZD#|mhiIqqTkY-Uh|rF~D&7P&7t#bMwKtbRwT7p1&Ggn^ zvsc%zHj>^M5`GxuX*G5L^L89K8jnu$WGWSocJS3j(&!Gp-Bw!`YC6B5u#h&`p^^N0 zl~AV4_=O2NR{}S--Y%njvbE~62aXKp!tldK_9i{!@1ap$USUzB_JQy<8?u;Q zK+KNIQWfydgmI-)w3+1{*(=G8u@c|B-(0a4ehjzIQ=!_LhKRxAB%pF-9bb}7_U@Bq?y1uaHdXr47+OA?Y`>0lLVwap_{Rr)7bE0o&g zIUG36N)rY|PRK5PZVMRDulIL)xgHu~NPu+$zj{Se^?1X-qP8W5Ep!?ZRs|}hGW*JZ zXf4i4P> z{F8odSqt6|6oM&9`b}s3h;a3%m*SWaj2`Y{&bu5)=kaXtM*^vIPZ!NrI)Tcj{h%ZY zm~C<#j(BOjaPr}Bz3I0c$8o-Jpm4FA-;P&q=*gz#Z3vu!=27Va%^{+=RkMXD!AfIt zT?Fn%Js{;rVc2@$4HacVw_pPctQ@&@KQf6x-z`2qX;|^ABscf*b9}2TEZ@-GL#BQ( zcrarpO;tq~5k8cBi;x^dg0z5=_bI~OESfQdHOmc@F9`#3r?cmaCBLuZ7BjYGW%*4K zTC@vd`OR)J2S}mR)A8U*};}gCB zK|sF04<+2#AGdS|y-^Z;r5Z*TKM{!URJdkMmtK^mWdP^O~%TR_&ESjuI5U*N=+`y77%PH(h4ETq94G* zpo|$hJ#4^%knC4H=LKR@uReEN%{0cm2n<%KymY4Vhm*#IV^oG7C7)Q@#{eS44p?pI z(D7@7X|w*qj9Mxm*)?8UTII6~KV`5yaXsg0a4CmtgJOoh3G7soMcf$GXKX#j*CN56 zD?U^l+Jm~qA1tSY5`BsMWKO-2l3tBS6CjaqSiBypMOn`rC3BITBkODPgv*q`gfm2FsW8EaZIqO*sSF z^GgCMWx}rh9*&QV?M8Y5+e|8e7W|4AN%;W!lYFR!j)FcJ449|*EQN&a1I$mtQQq=R z&$k`Ejm_7yY04kIJx%Thx|cXUYYE0;;D|+`x!>fdMZDrXWZiWYp8+HPeP3ULszBi| zkU?^D6x_J<^DoF5cTVOyRDQjKfo#j(&Qx@Ti|aSq0faD(KTt-O@-0-V@{zy%2i$i- zKOh7~uEjUBv^n-bZJ{hOx2eZ^_-0L=2!zQv6CEW?wd<`L(J0(|B+ozn_ax!5V0xLS*uyqmW|T%A|1TJ0L>k_Bv^CQNX5Bq ziW4t%++we?r;F#Q$G!zhmw{S-oPAAzHTE}1a&jaQlgQ2CTqBhM`+j3fH8U3otgsBVshL~w?COy( z2`TUsBjyqzvXwkP?dY{p{jz#$#k9F)k--17s>!QN@&sxnFJBLI8e8$fY@gOW!Y89> zplSg#)Zd~aN%Lxh#(ZuaUsL!AOb)$Q-X22Y0)EQa)1Xhy84q#HHzqmm^B>%JeE&nOxw-u)iCZ_(7T z>^MPS$C?6xhlb#}Q85kYfPcUiDT@;WWjDV7FLq>Y)xsVB2KjCz=JJz07eur*d3z7i z((yYb2p*raA2X*t;LMXaUyD5OL*kT(!_dGHDD<(tLI_1ylHyd1aNsjgMYNJ!o#rT2 zdo40N%NYx~b^4hOFC-I!2QqatYhtt=osQ%d<~w3K62P{! z=EE+;eU>OR#J!I<>DPO$?xa1Ngr3--%S_w}P0>t_fvLf-`aoh$`M39FhuU3CdL*~X zYY-j3XTfV7e7=qaQ&f(9rQ-Bw<4UW8*wnoylQhMp_k|}m+Z_gqHiw<*3Aac zSai19mMS_p6LCM0!OWb2aB};PyIe+lwH|i&3=9H7K3^HJV98baS#(lafq5FBd4@~IEA640{vw{tD{I&NTiIu z^-l9Kg5}VyEZMhlRJUF|JU+(VY~@NhFCmv4WYL8(g}^u;&-3C^UvVAH#J*|)FT$H= zfZ9q#YMoba&K%l>f{8ZNJjWFCL@FNEtp0W!A zW_|JUr@Ptoo11d^5BfI)3v18xq*a+|cBOqi)oHE1kS}iM!tX20g(6M{gAmRYo6F=~%FRer&@jK!@+cm_@3* zWART7fTCWOA*~hV(X*HphKVJ#b*ujNpO035c7s5?^Yf{wr<09Pf_KLowN;{j-_Pw| z{W}5(-z11d2yZWpKgLPlMiW=@-pNcR?N?y^vX=^$c#kXhWSZ0W&>btF{kFL^;CDHI zx3EG8?fqzS!|X3xQ+l19(L}s}T;azDGi{oE$x{CuC%N?=FYA-JRd4uU0IRt2nMFLC zJ#XPqADi}l{%`Zyc^e2W&=EeXg)8w{>NKyf$0ms8INTzm-)fqEz>iId;%IA{Wa^BF zip-(L!u-2UKqm&R_9kmNURJb@;;RZf^m+dN;xqBoS?P81D(Z)$A4}DeCl7JdM4I2% zFuyCN84pcT@QY598?}L%FoE>9Pj&icP_SLtx{FG6dD060Eg;9pEMg*PARA(2c81_P zW9;7~w-={tyQEmKiUcr^C$v}BBwn1ip!Zk*wCIHpT*hU&CN+uXyv>U;*nQ&*L`hNx z)O&w^M3iu53~EhD;M*??_pLQ|Cg!!2&s@Ww@7y_&og?`zzV;x@6Naqw zq(J=emPt7({cJzuyHA0Z{?zZNG{+Oc^tURy2R}Q75*0EWs`>*VjRu{p*yYP>KJ;#6 zXn0<~J$e(_i##y44$U7}93ty4ZNB7Ql$K1V`{Y27JRHKO^{G9G6D#ryQkAJ7k6!lA z;W1;GJVp}=<>j=nv5R`}wqh{5vFzi_K=frWk?g$DB0=|8&9Fc1&zswbT)xCtUMe;E zv-FZ4QHzcKL8pw>`^?E|uj{eD)8e^FPR?*~TT zj@@JH(Qo|)0k0xLZTpk9(Gn80>mxD+^6m4|x+qHNrEwj3-Sgwba4H(N4E)aAhaqku zC{ebEct$3`BeEi=vbjLjQ!EP@E$Mxnqsh8loA2YZc}+o3oY|;iSRXGVk015*uJ7t7 z0D2ILI9CoB`jK|bw-52Nta;zT=Y$zg_Gvhm4yKUdnGRw@>-#^)A2ptQXb%e(tV zO+J2MqVu~uxB8xhY_MhRk{N*y8XBcUJKr0l)39fSdOQX9{-t;I7NcXB@+hxSf%mNu zTMS;s9ErfNuZY+v<(gQ$ZvLHq(r=apWR2lk;@BVs3*25 z?L_bk(~0IR?0RUTxAv@hp=tnLlq{nxyhL3tsEf5N^+w8#F+g)`-0C8o`}9cAd=z*5 ztsEAFOf{(yql>a&R9S`4xsXj&4rQ7=<)MAx(^Q0TdhF(@P)GhVy$EMf3}A4t#+TONVc`^YHJ)E3@wH z@q%#GCDYU$=0#h!tFgY}vnb+anK@{?O%=wFC!# z&j5qt&zBMq^HU3d8Qv@Kd=8jBm6pVWJ0!iu+WId{vQ4g;h-JZ)3$kqZax z=+W5Gx0vU=v2q@`=Axn?VCEEMQ7uoT@Ew|Us`6`3Sp=O{dK4L8Hlpi(m1qv!knXv; zXr%7j5UARB-vZU}<-0e|dK!M>cupmGt~v5e?pT<@P3u1WKKOvWjRR+@jP7t8!!G>_ zA+P!bXSSNBix<0WTdsZ)Yr+Ul4Nz7teetGvyS=@N$>G48X8>!Ga-T5utp1K`5WKK} zKzkg(*uK)Lk3PG`aO1CS#;AiZF1D}cN~}3g(})NP2cB~B@A!IK6LVzr83z8lW48y> z;(9091tIb_9dgH$L|D4MqSNH^d2U9dE3@}GhAVX30q(NcBCN~nlWb?QSg-FkdIK|J zmRM7QipICeor~?Fn=FJ1y{;9s(CSK)uQrW?XeIig}Lr~t7xRn|D zALT7ngK>PSo;pw#ox2tJZGY!E4J2Ei*TlyD`SLL+VSZOm7nKtC!D?hnrA>FQcUnz^ z;QiJZ8$K+8Wm(6nHb=e^k73Ai_wl?-a&b_ERBEm{1ZZ_s0&fby1r?Iw2ep{M`>)i9 z@&qX$+Ef&nO?#W)i?6@csls1LXrWK=t({eUwSrNr65oT)_idU{Ls(yazpF@HINcj0 zHb1~eR8Poqt zPHErV9<~p^k**_}#Wg6LD6^BNNBOrN7aED@_H)}TV?Ed3({J;hTJYk2lMcx<1>Ug_ z_D=of*dko|Mgf%l!kZKwDk;X{SmOuYo}atQ(7tn4KXTg{U%4STtZ>dNJ|FTm76O*( z>tQL_=D%c0I{|_8$3^S5edqPB0Kq=8rX&0kG(31IbWz$VwG~CqWJfX zn2|An?hIh{OrhzpUy>Wf%?)A6Y<7iHxz7lpLwj@7TvwS7D7l0g8lE9KW(e(=*^vH# zl+->bz_RfXO()NuxZ>~o3Ds5jT6-T4x|Q$`H~{4Zu$FxTRNU(VN>3wLGB+-MKWB^A zt`jHzGkfz#H<2yp-Pa-Upq^yg-oGfq52!p&$-*_fv)-t5%z0U{{%oa%04 z)6ZEzQPNS1qI@7TdJFby=8hg%uX1&+Xk!#e*X9S(e$!x6K!eBI1={s&>*36WWWGCp zkA;70=r%?*|66Ig7{qT*Z6THD(*z4^E6>VUP3S99V0VlqNz2bqWT;Yx>-8;@?#`s& z&NsBn07~~;D2`#;%&V3l`h^mjM9+G$9M>>dD3oeb!Z(W9^oqkKNzV738KOIEpiYsc zVkUbjHsLdMjq*+kk6!dcDDaPH>sR3`3P6jEi%o1=X*$8@od+(u5tkjAqTCDFAeq$w zkFg3%yNQjEySHwrbuGl@F^u?TsdE{Vd+? z_ed(y{$$zm6#miK3IAx-J5J=8;qy#FSRz z5B?tBGa*0@#-_)Ef8WkWanmv0N?2G{;-=i;*o(5?CcD10ew!60z`aWvvB_c{Yl*-=x90b1P;)3{5XpX6?)lr)g z;w9JGKLFa|J5x{1IVrAqt@Fls38`uWo9t1J&&*K6;vB;bR?5vr>>uH`f26F%q!zj2 z<3$g9#4+N7MrfeKJl^o)cd9Pcjlx~jTC_7lscqef8xD1B<^6t!y! zso!Cn+rN68en321nh0+pNMm%lt)bqKM&{-@c2-2-XYP>e+%vLIFJHt|US2;WTys{K z5dGV^BY@((+4<_Z+6uFYL{ZEzwzEOh;0yz1l*cXByaqt!CLTXsoRH=z2l}@EkozV^ z=s6$NU9MgzodUot{Fs4dQXwYvvVxV+A9(X;&%Ya8y4G9l2Req+Oe30w%%6lLn$AtIYC>AIz}|D*CV9r%^6R{MJ43VKOEl;m15Os0Tm_2AFSwvryGHIsITaDSyJcSUCf=2( zF#0u0Yn>a54&Kzar5?3TjB+8`o+$e?cyA+fM~qYNa#qp7GO1Z`ZTn~2CKX{gg{TSu z<{gx+lZ5g-B+Z-F;JaZv()ndxL#l%){DWHcnPUL)N_&K|Oo}rDQ)cZ3c}Vxm25|u3 z+!JvHWft5Gj?o8D`+Xx6NP9 z&?mpI_eqg?t#Ff;ScGN}g-ZSoU(~&qPo^6RKCAk)hd*&RF}X_H9nxLzAB=+R2rBJU zWtRTrj=<5WGwUY;xx_b&)>*GG=)2w`!C*dJk?z8O>#%E6i-vQr$-hq$)XsWqhG78vCr0*O|$enjG{PIP0)Q07+IcL zbOL4T>u=#uo zgQZCyCz$}v*P!F~opZUPyYBdRL6xoQ!)c?CC#;`e9J670rzMiYY4LColK5jNXer|5 zg%V@^h4w3qh>m%}!l>K3ocX!7q%C6jOY@1uCsRdq#rD2MFQP308$&ChI?#H6Yj@tW z&l|MP=R~p7wneovLuLVWu%HJ4h`y!r;B`B{f z{t9lKF&^oCvN>cI#L&roT9&H9f#_qS2ZqTWjy!(&cNy*uUwmK zWN>>w%0fZPUf9nNJGdhhU;W&2R;T6rUP3Tq?Q_1@MQqS*wbZ9Lg!Q)M6lPW{ zKlRRLQZ4hoM(%oCd%?KmBUH5Y7|2{SRXUTN;8vI~f<9?e$%>-dE_ zeER99HEb=t6Ro2?UcEBRRnpVp)~m}uoWp&g)*LzPGw$HY7B-$ALjyt@Q+2w~4ayX;i{-z95|5g#hX(%LswdG?!vBr?U zXTcm-2*rBgOy`ah)ftrrJbd|}RK;t>&1rS*zBkt`vyaj%-1|fIzD_Zk;z;&+n$Z&c zeBr_6LgD-@7ZPq!oaXHlY_`mG5orVQpmJ>xFw?eE!5y-B;6XGrbLNPdC3 z*DYQBvJZ>srwL*hu}C8d)i26M!O9ogG<@lPau?lmsxjgwEr_bq5m0Afk{tpY9w3UK zwQwfp7$-n~LgFlJMn41_pY4}uO>C@KZ*KDxm$InGi+cVF2^ii6S2dNyQu3GbdO8TDP-=}m{ILrME_(h?j1U!Isa8Tx5^@FCI*p(wz#m{fv&7P|}Y2%ef) zvBS8ejZXmE_+D8kDR0X08DPqmIXN1R)dRhBG0ML`x$l;!@G`8otTlWstl z{iwq{uPR*G<2bAWWGp()SrSty*BQn>UB8{AA!?)&p>1vLzqGZ6)SB|C1*K( zd-8145n#*2m9;S7tggpu{P1dwBG7j7p{(Q^G9|e;%Kp+DMF(Qy)_4;Kyv7UwYp%2R zXM!%etD*;sQG^v*Gbl4-Ng4_WuG%GN?JlCqa!J(%4-UvQSV3GS_9$ltg8!U!z* zVNmx?C}61Ds*&=0-N`Pui&j0y`SxEciE>E<3mSeeWlJr6T+3uC0E0Cq9Hp%xqqJ_9 zt4uSd&=`rrY|}Z*+o;x7!>dcJ%y%}F(pja$j?%t43lW0-df&t zVkb_xbN$5zFyK}6dyRPHeO}5A45IjE3AeJ?Bxir>H1HN2&fxV|1&l8_j=>0EGep~Q zIzR!^EBsuwVy)8>1Y5KVULVU}%YXB-GtVYQlP(pV%xKP%W?X9L=R)qpBL{q9rS5Bi z;ruI2z`DmlJZ2$|Bc%1~-}nfh#a8e-DXp?90N^Mr@`4zu=gTtB{F!rg$oxjLKy1;W zM1aM85h#|81XCMv?st<&^wh-O*?>UX%Al_kEBSMY-QR##w&`CC(M(_ipAo=56>pk68n^XKh4#1v<* zmNC`r%0cQnVS;~l5}u}ywkc}PWrBh$-ztnk?&`YzsyW-aPK#fvzumZhgY~hwb0Iq} zUkiFSC&X@2uNSIGS}U)OdrSE0Q#UI*VO2%XGG>hceTOZ2hclA~N1W9S`-p$i3V&v) zY<&p zWZfbVFek8dS19c@h(_brZ&U8~y&O17P_6DcKlexQ0ovb-oPP3DjAGi%CKo4*GM{ax zs2U%9XcU?ab{LE^&@bi4J6KjKzI`yYvuR46WUPUD!R-DMP;Y*K|U#|A;i>Ax+!cW}5Sq4)8^@W7u zHf)-w&o=y88AsX7sD#QN-t+sDSJW?+juRv{j6XE=@z@-I+?5p=S6%J0@S;$g#^p+~ zoxbGnx^sTfOMiziZYH++D%fT;Qe1m6ezHrJ+%c>3@E3H;Q!F0v_Ntpxy;^6+q~inC z^Ny%I4v416TeF>R75J6JkE0*ZVLS*a31@@jH5>I>ntj{rIp{Sl-B}69BTByYZzw$A zgVXgHiIn(7DRS!L$f&xE{-H>G>TcfMBGa_SLuGkR113cwqnn6lcXpr)i>mP@DOxOg zzZDK0-Wk#qT9tBN1!~|{Q<`1g$UELlcW#XQm4U{yLp4OxgUJ(`M`XT+dQ-d3z@!1JPtp0gWB~OU zD9}uh%KnDt6R-mv?0&!-*%NY%YU&Y!6jfkm^Y5Y&~v*xEA~B8$8!l1K1_PyC0TF0~$*f;A4;A4Dv%} zqqG~W;YC!NC8CO{s6d|=$7j;LHR2LJQ+%RCA2cGl8&(dW5q|oT?S?8&AW;& zUI?+_FL-K*L!6S|7UhZ2An0vbQErH6l91HLsII7EDctj&EMtU{0C|D(Z!XGiT%U?kDpxAaS-Z%-+(v9ar$oBr2Qq&HCCGFt^ zRusnUlqsDuKkZdl%8X3az#vlc6(LTV-d`+fYf^&kjn2lhn0M2QhRR?VB zO}VEgIh=qnM-Dk>%}fBNt!pujz1)KGzmdC>UhDbNdKx4{cTz@~uD)gCH?MmZhmgQMPy{J~ z`zvXhWWm$vOL^=E+^jv!Z&GdB67~*R>Z%2`)imdCw}gr5kq{p&c-MCWDmDUZPBh+F zaujD!a;gNdAs9$VGL`>+KWH#kOEX%Q4or5<-NW|+XZX2B|PZS6q^_^buuMp0;5Jh%}xnLp;rQ9zT4s$gt7c6 zi%WUGMrfA7Tf~Ccze5e5CxTdk>|_Nc+6Ld`>-bn>(5~M(#l3;Y$@ynS%N)4!bgPa} zah^p#pwIv&Jg@-JyoMMJ2eD4QF&fC7Xa9BN?iKu=TU)iBSBBv%)GvtOZlvetB7VlpeL zR5iAP*3cV2Q(fw*Q*9f8iY4kVJ_n6Z&`HMkHC)_i?SL&mne%v;ypM*&5MDgfS3#I= zNB>+`*R5|SMB3AlB-i9`&=%p72~?Z4}rhUUWCkFWm?aOr2wjY$UIw~FX~5N%CF% z5vua3G;Ls@?mD}qVb3@Af^IZT)i0->6)?$trVyz3RHBFY^b7XHGU3-Z&-$Sb_N>R@ zt>51GdJ$9?vnGEMMIPyO%g~7KE}RhCjAI~E@r6e`1?DKy9vF&Joh|MCyc>bEN97Bs zRLNUrwM~+ku6k+%aIi~MsPSfd1(;)BztqJ^&x>_u2IdF1@e6!lZ8P26&RMVl;V>(T zg2_^1rMH6eh!QTo)GzIXefpKJH&3|i%8yj;XV6@k2C7))clcrrQNRgd+ZctfNcYMC z^h49JD|#&JA|N-sS5dz+spw0w>R;a;S=CZ0zMA*fGVXQOf*=K7T2?P2;)UMfm-dHHAO`UB>!&(#a+=jD^t-)+tji*1GRjk9WQBkL#@+0|I6)^| z*2OOtkVWH9#~LmKX|mZSIjN=S(@D*nt(_|7l?YHJqmTQNIK7H%&pu7uXl|0#u9uyI zhYM^DZO7{_L5u{h}0!^GRdQTs%8aGbj>rSKYS$(~-Ao%EP8*dy=Ee~+-k*XDb1 z-dk*>CL3@T_T)?BL<^SG4s2H}cP}N<`%{=7Gf}5EUv5=?q!ZzAsFeLAYAyMGZFx~9 zl=B3@4Kp^zFj@d8k4cp$3Co$Ge zFum(7Efh#!N1R5GMQ*fw+7vf*K;HetsiYe~{*?B3D?lj8n2)-jH^S+s^_AcJt zRvCVg?O^@|+3FqnL49AvK2ci&3XGC}G({(Ruc7h)h~gUeKRv;VtP{4S)TK5;ylG!* z2XzeoXOMbtjt~e43*1{X!snBc=gC)8HPlMjO>CIPI2b`T3~Z@)Y3@J#>VSe|mcy}H zc#gUfNm9)LP^SxM>1pcgqg)n`?U??O9n574vZ?ZmX8R)DzuG-yX#nQ&m?|y6_CPq8 z(cGoN0s2YV%d@NYPz<9D;ZJ-kwN7XW2t zx;MEr0%+6T0_F|t{GD*rj-JTK4HLYnB{5V?VByC&J4A>+Hy3$*tng`YY2?*fRVP|9 z*-2c6fj)(E6>BN&34D{mec6UVn-&bAFHv2+o8KUhKcx%P^Vg-E&s1Af z?BpUg$jko38fzTNnQ!J}@Ez%=cx$5ljq;2mEFb#s7?JX*`;%T2k0!+r_W;eTsLGshRN5JL}tJ7Lh30W>xpHnpr>JdU=WAD<-^SBm^RA!;CK8T)E*TfQa2F zlO0+5{MYdaNXjtOo=?RR4a)Dd5Cr1O18|}qs6sI==6s>6oyef#>we1Z(KXo38-4q=NkZIECcWsL*Eov8B-62pFJ;Pwrbb20p#fGDz( z$J^|i{6T|-@jH|Gh`%f*>r@qL?aBdR%X;gVLu3y8I@7wRhM5M(F5LQ8f;1nngn!$m zC3De!Q7I1Q!SiFkzn_+kj{j4U=18!FW7spt8cX-hP`L`3eZn8 z-B(uq7Kx#<39dA zFRPePVbPY#Wj&WMsk|@j>o_KiL0AHEbaA{=yFzomzp(<5I*O9x$MG}Z;IntIE21*` zqb!}5eAwvcG<5avAf@Lm6AkAqCO*IfE>r~kep}n%${GNo5$w8*6R_OE=A*I?;(gsw zfs-*WPZzT4`+ZF!P5kbS=*VU?Y&CwW2bXeg^HZ7j#5qgQ@10Xz{sgz&)0u4G&*GV{ z@z!n!i}Fi$6bwVQM@1%gF?oWqA}6ZVOuYB$(U3#CN!7%z&Y z(X-WYV6h>Aa}%mQbgnVB)8QZE@|wN0ORP_0TM4Sgh}_N>No7Sr*w0NEYm@J1o;Jph z_#LX_j>5*%M%!n*sp%(ZWffRnBciK4N8=O)A!@-J2`(cfU8En1)r$N@r{mx`4%7^q zzMhuwVUadVx$QAVuku5PZe>0O5M@^D)X1%RVJsB(DPIvYS~9 z1+Hj79|!p3xBJ@aj%;U|FX6XEmuBN&oGQ;8IL5%N#&YFd8z=67E17CjQ=7TYocF{* zjlafyNuv)KSD}VVIiigK?BEb#p7gbb3fqKr{$S|U_8JUG5b;aR0^q9()Q&-uVQjQb zzQYJB!Fc4}ap)KX#owv*ewJ&W6uxY-qA8Lu-Q{0y zf>#-U>2{1`QedpjxGxj&Gevy&-!EY7Cf&J`-X+kt_7kAlzq|0gmX z#}T=eObKHT`cYu<``+*PV@72Dxl0E!raTB|CAdGMZ}F!`-VW-5o%PL|v{7Ss2gOI{ zHEmj4y#i|x1JhMz%6QDFJrSnCJHX_+wSTEOlq1`0>%&UvfS`<&W9cP{L^i;?U@pmn zuYbl(#5#9M%Z89bL6SfXw+oJO>=j4!#1(|_@O7!<^qf>zU zd8jydquAo0uI<*m!j^6#LtTygaWEARsw_yln43C%2{WPow3u;}l9xxMQ2HP6nhpTt z0%Gnmalf-s#OMyk1dcz?864@zdKs-&8CFYv8U1NkkfxhLOW#={kHfBxqj^&1u8ZGS z@%rCee@)dYK^ZFf)1diT88PNXysaTm^6_5Ug5G*o%g=3{pS3mWF^hbqa-Hr|s(kR1 zD}?q2HweC*b|Y0MBs@eDkv<>_Rg0kbnBbBRW^#EWO>H!Uem6zdKmHb+}rx4W8IIjspy8zMPyDc=LcD>BmTyw3f8H4kZaJt}k=ZN8{nRFlf3S?c)t z1idY3Kmwz{QtX@z+lyW>F^Ax=0buz7E6jez(-Q0QcTU433c{SWJrO#IbJ+QvVY8FU zZiPWbslT(Oj}e}@n>^@hVtP&0F@Y(@JVw!4gw<8GWp@#j;3ACO$F&uUwAu?hGAk^~D%PyYt-qXsJA!DtaH zP%-J9cWte)^RMY-^8_{qSZa7^OD1u?q?wZE2L?H z#iW$syYgH4awE&tn-LymE{m6?e4!--i_Q(~+gspv9Lr|Qk2p@yHjc!6E1>wo#0BHW z`jNyy$I!wLRMpj4ClX6L4#`R*qgUCy2~VsGC*BD{;lCWbSYHif+%g-S0t6eQecSd} zJLC8su-zK}9Ew_-<(D5;Ad8>|e|t z8P=Am{ug=k!+Ri25F}-gOLem}F_-SA5qrsY^1f&HnnB@%Wn3okcVbRGON}`z`{j-Y z;gW%OC;xky%ytD?rI{zuid?}=o=s4UZ1eBc6u^l1}afPAmkraCX0azjg3A&t<(o%keXSkOKxx7 zzGQM*F4O+JEvls?P~R{PvdQ7K7~Rd3>14bH9q_S4AV}kIAoEcnAfK_}6b761P(8yH z_6ndusimYgG#vYil8E|fk#c5xz$dG9*Wu7r12pj-cc|qFh4-tE$SuNi-;|4R3AVl5 z=Bwp#Cke{%H4>Ew9`WVW58W%=`jsOxU9WFmR?j1qcS{lWoAC+jVb4%)tJ;O_uT~b( zu_5{+WI#yHh1^508JZQrgV>-cat`Go7NAaB1vPXVx^m>C+2Z1kp8sgix9c}kp=M~Zx+zg?e2MA8pmt+m@v zpklBPjlZg|@AdkrA!65N;yCZX5n0&OQ~1*B1k=~YuPP=z!gIManunUSnqGIZ)lb`Y zJ+5%`Al`@`dJWZ4U+2(1Myubr86s}*QP3@Z!X?l%Y zmktN;Jsv&J5bFj7Zyf&`sKGLSSHTKb9*X&ho4D#{OQT>?DLDcbgtJx1OlOj@5&SaTV7_q5 z*}oTlJ$@1>AT}Re+#5? zmbQJIN%(`Ob1VVCg((U+Drd8_K5n5kucjT{u3r`XTv5Y_QhS;D%i5+95GfIuT(K7O z=BT5n!9NAz3aU3?`Shg~P#}&1g}m_aZpq;$b*Gc~WVaL*vYc)zo=!Hm=kr`-RWUXE z4I!m5^J|f+8}`b^O*mk5V1=0xPZQr&dbjv9^}-mb{%V7jQO-K!e97w2dP zYVZP+8amxi=MbM%2I$xTaI_a7ksgLTf+mzcd#?)}})zK>p)ir-; znW6Ftg8&{V@(s+@wLAAZ07wR~`wGI>ztZMIR_P}5pH@^-m4}-d-2?xXw$4|d741`~ zlV3M8wK4F8O?rkJee}OWizYAtj8J<&ZdUs71BLbAh2Ai&Hf{&M0t_!UCLY0S3{pbe zhi7Med8Tquy0k{W4;RzrDOT+Tztnb*1Wz8_LgVH2Sq-07}XqoF>Npe64> z%tSD)``Z5)8OwSu%7em5tC)|=5|MFC_~xJC;R--&y|M6wx04Kv-IM*><@fWi(6^&O zokD`97QV)&=Zb8)Ru*guDRi27bBX3%^j1x&*yd$46S5dhpJ=^GcT{IB{&i*uZy(5v z7qR{c^DiZ2`C8s#2DRav2h_)AG8~siLkFT#TPm7zn)U&|aKyIT(Y!R3{OaxL((-ju z%Ty`ftAimL5>0$y^^-7E9uS#`csOpM#^-7GF-`b$Lq4R@k;1F0!2l}$zAm7LG40p)-#J1ya{k(3?COUaX2%fb#e2|dIn4Tf`Qty7J?as^oZb;tA zp(U_ODPn6g_Uai&SSwK_UPdV-4^Zs>e`jFiBPQRaX zYk`X{`UmeJ)IyQ3ah-X(u(+yQl2ma1e2r}a$uj>_j)Wj;J z5?k-MDkVUwdfwchyB7mZYDTp;JP)meQIQ0^fB-WTw%n9(LyevNd9?zG!KzduhL2GS4`!cUJ z?^_8sr~E8^^x8`FScqsGA#dEUmXeN#6C7MHgN2XJ#s&tCl$}6SE7qS#cdDwg11kGo ziJHQhB@4%0utU48*C|1{B*tr7fBNx}M{IprhgE1AXF6{FjLKwJM}?GV@ea(6s_iU8 zK-vI7U%@)U`*`{bdu!m=2{rk7cVQqxfZ&^NCHm%MT?afyS@(h?+s5MhcV=tp@5;`% z$-_>yIp1EP+wnPG^z4r~NZ-i#zQBq^mR%$4nG!ocKF!#n7?SSf8pj)VJU{-~!~%sU z0z#8x$ZdNZQFl2}*$C86t*0PtP+dxmmzl8>uN?0e^@V~#XHaYhPeqnrr68qyxASLr zyz7WLX(p}K=uKy*(B%rbk`9|)&sCXs-kKw`S&F3_sCUARH;E+Qew?MKdH<+*X4u4B z$Yco*Fj~}99c*XMG3i^z6lzK$tafrF9FY!6KM&8)Hhpt$U;ewbq<%MVko{e^hA4^p zy8A3x^!JMv4D5GQ&@dg4^|qE}(~$8D)DK zFN}aQYTHrN*tR^%*W^}A&i0ZyiN1KPY{BT`NZdqYJ$J=4D}DI0`(QC4@dH*1n2U@| zo?Q-p&o$;f&g~_23~%ldD>NT{c6^Jhju<~UzR~{W>QuVFiztvIiG4Qp=T5>PGk+J< zf;n-fP&~p+ra6w~YLZGZs#HTe&oHYB zrz0+rvWfkL<$UlLYHw z-XfvXS3IL>`{ySaI5N*x0BS1scavX5H0wuwU0V6^bXVG$DPjY_Fa8 ztyvZWrmeKmH6H7oM|l7D`@6@J2EI}2@Mq5Abbq$S@OnHu!I?TK#f2r&QUc=jC0I>uG8#|iA7X@PvtEDZ~}M3Uptj$!VNMbLX5oj1bEDcfe@D^a@1HM2UkFKxQr^JjV7TX70_| zNoQphuNIfRZ(lDb-d|&H-}&LUk%ioH4&U(KDOsdhRT#=!Cr~ZQ*;RjhHo8dhB6qlSMnrlX+*J&9}10C-%H#piCv(@AgP5Q*S9DX z^uefht9nCkGJ?BbVXxwn9Sev40I6>sxL7Fz1ovnx+D>qp8Gh6E$NpsPJ;l0%!*$bi zAGEWh>lb}7KcLeC(Hg^(L@xpJbBtEAu1tV=$8J2zn#f~5l~btRuPZk<;6-tnLN&Ry zDprEC9RRi$1nbYPY#l)yAPQGqm8+7#?`SaEMrzu0jW{bn#TYdbC-nu!p;o&-TMZw)Vbe21)SJEcUxav)uD`ltAE-R$_);D_Kg2@x=xNALy-&7zLMY5m6lG5N1*Kmn; z@nYu7J0Y-?6x#4oAArD{m2Au8qTH(+4OD{@qA-MPnjM|VgmvA5`Y1jFn+cLXqQhD9 zaDULMEZw3kqu>>?A?(J;;%v(ZB-JP(3nNd%#_WE3ZULO3?^petI|R7N&kmw2`h2zl z`Wy$keSklsw7p)8oDq9H-xdV>03qn%lAR^uEL9<_^GE=zuEr^jGoY*T%+V#hHIxMC zn96vgW~om}m!J(7f4>#icz%W-mSrrK)*O$RzeyM<>as;sR(R*vZI_fxx+l=uda@1L zdWUUWuE;bY`7%lDXBwS1z?y|g zOz&NvZ{vcL%;z*!vn6V$a$b0l&*af`e%k1w+6L4u008BkJgPIRc4WH70(iLLWnt>? z=J(sF*X%}wxyquE1)*CJ8IwGL*(3mI#Z$0L7qHX~L^cXXTg=$@SJmf>+R_e7&_64S zt`(r*7!lIc9XiEza=w8l#?4y15O%+hifU(0GdIx$pT(gAx3c$w2_9SP9k>#bod539 zMW1J8U+W_reD zSZYYKnQPHF$ue*CvNPc(I|xmpQr$T|8y>YSS90Qb>ztu_`TWwUf!yaTU+if-jlwvP zapo<52_xl#D>-?e`Zk@%Tf|{tNS_zG3j?{-K$vMR6D&yZp*@hv~Ya}ZhC$h8Hnb_#equu=i z@M`&1o4uko+7;4vKf!Ohymmz_3O$rsF%dlfJO;A$+HSJIq*Nrno7uIx@EX+?yZ~*#gp|HFt>y3xOYf*07>{~7QQLh%Fdx>A)EymXkx1O zF)wev#|Ub+bTD|mr+*z(w+9Ba3)0W`+waoc`G*xn1L8-S@*>%ve&*xJLD!vk8i?DcedxV{B4V5) zW!n|3SIdxlGvAaJ$FB7Co^V~n#WY}=F{^(?8*^*>O|_Jc6b~;yT`Cr>Y>h)N!9Vun z2X0jKt}qitLlIZfb=75*T-FbXZs$Exa=>7Py6+bFbI6{b8ni&XyVPJr(LoatT2O;m zX*ZR>Iz1voLNYpUE&zx9T&1L>zSdu&ptwO?%IMEzHM8MS_h0n0KvU`@6Xj$kz&~X_ zr%_{|oyeSmVe(-OA3JceM0Ar3@|0?*t=WlAkGOdOmP06tF}>ynINUJY=I)L=R0pv; zLf6%RZluT~-0>-8M)#B>r|`Dq10ps!yqy%LtXF+?l_HY)(o}-8>MgdGA*fF}txENR z-xI&WSZ)AScb?+r5t8M$zEy=6MF@+nAUu(42vRf>0EBqvi6hMv;DQQH(uSpkB2&fzU0P zs|56oyH3@u^3MS!{9wY`P?xsy}fzZYf>#DdGG*%hW1ohvjF%gEcjX-<8?!L1nU);mPHF-p>FLp( zd3O~gm(^xpGW6>i^?X*kq&H0<+1 z8AVdx#gLFGy@i7CsPB#C(|qyQDErR(S?zd${q_S*Lw&WshqJ@^{o}y+^VL z=zUg|umR?MxBiB!raDv)2Jq|)As_Q=(Bw~|s@?{_kmezqHJJBrj>Gee^D#M$FQESlb3faXp6>l?%gXW=T|WX`YZfpcUJ3F z<=CRd#QGGBHrVW*I$q5m{&66a@}v}|cUGR+JNZi$rga-3`?^X(d%yk~<}+lN76jx2 zkLucowmQN0uull!=!AP`hAxnj%ZXO>gpmt!``nU)M6K1ZGXAdOGnQvQDZO`!l78Ez z?kh*>6r@>+t!y2d)ANl#UN>p&j}&K?#KAfqG@;iAn0 z!~fPbLv9NxwteFM{H!~8tcuHaN2#|Juv`q(tNnc-y2`&@@hQhS<2Ot7NEt?T>@!J4 zqc6Yjh zb!a797A@%#Dj|;y-X}d}1~8n?L8kec0s8J6j+PEQe+vh|40{|Y&brgIzU9P!R}Cf3Q^_5~sHJ>cg>^lq<;PZOS;;wU=Ov@TV}KpmrynDbhvzU+FlY<`GqMxH?Cr-K82}Vps>7L{Hw{ zTRA#x>xJ}E`1*V`l=4zDPWS^z6$-iA$YEmxa)O787LwL|#72wIy6r7X(lslw$KK;h ze(GggWY4BMO32i^9ekv;52fr7Uav$GCXxtl>H{nRbD{&$j!+bD;^D?AHJ9B)`fr`vN&ha;O%E{)&vwzlyW9_L3A*g zSqw`Yh8NkYYlI|;q*UX!y32Ec61t44QZ0E|5o?JBXsy?zGFQ%`>KR@EC}EXh!gMY- zce_8ETAqFBOAAiOXM!&3vs_!WMsH~7I`nr*;cYY*j`PMby$b{*_b(@;hOc&r|7!m0 z`NG1)APBJLq%bcpCWK$;@4qdMM|A!Yw+p5pI9btzU&{VI_~Un$d0AaI?xw-?%i0%R zDa!qOCT2Mnu+Mwtf?V%7FbL7#)mtGN>6R<;>ZUS!x-1Tt>jz>5fVoa%|&LaQ5`ivZo9I*Vd z&D(x$U%rjey_t6iw0M|-!D(&gR72MJ6D$nnA#tS)F^rPow@$y@j*Y&>+>ZIQ6S8>{StzFt}K6+f~+uNOZ81+vcQ!GI7-w<_uSeBs!HPrnb3}IP` z$`XvySLoH9Sh-RKmd9nzOMYJ6Ca%W$qP2HrBm9n5Q@tESKA%(bYa03{f_!(P*LC{$ z?8!A5a)Rfcn_rzK?M;XWc0ek4cwfE@Kj0c$g}K@pl6~W*__)Wj;cWQRJldtTjGQ-q@e{Q-_QmbD*lIPnvwR8;%-G zlvL3=2(L@+U-3R7Z4Y@-gWUiko5HQ{_MJ|s4O7p?7R0X8xvOFl!2L{|36K_jS@ zq%%^HM#WosoLJEoRppX5I7#a(Akl|8#tQK$&vZNnQ-6Ln5r{D z#xkY&?Sm)<`q@=3ejAyFvr*+<_omY6um#t`^!|qknp8WR@x5MZI~c=<9^GoOzSt|f zbaw6rO0_TDEJQIwWxiSkR+pb6UjN7i3L4J!F5#}U5c%elU=!1#t$p)0IFGx+Vcrj{ zzl;{+iO9ZDdi(c0pSDHv9yCe^tE1$_0WU40B!Wa`mnYJPpMP1ni%$%GbBIANR#gM_ z_|UguV_@|T&y-;3pUAtw*I+}@dvTaixsw6Q`#Q1a_o=isZfD!Wa~Lc-0(rpgVai=i z=@b2c?~Jq`0_!=2@S!27oS#~P1z17Jv{>E{;z%4-ahf=1cF+d&MdI&96u9-;gges4 z=ZG|ab`&vvt^5S@^|u(8lR!f@Y`A?Im6p5?T3UUrUs<4X0u3eHG$Q-=F4qpT{SZQA zstSTYU$&RA_G0Y2eEbed>|>gOBSj*xD*Q>|O|yP;uO|HG>|wYj)T^-Q&<@i86Om02+6~LS~#tOKy;2R_fcBd2_aDvm0F$WhCZ_;A%jy(n2|EQ`E-5KKNHcxLoT#7@|-q-=3ulv z;n@j6%?As4XZZIs!}*K6xJAwtczX8H+v5w-k2ewnP}S`Ok`(LO`_UE|*&Nt8ugR@W z)?iequDA!fJt9d$XZVID1LZg@o&ZYyI*3b>DXpO8WQZK_GxqVVQRuoO;L=l09EUbE zc<7@i-LE-XLS(d~Ij}D?A@vDZD-aw$05!zE@PmK#{>GVSd!DxTru6AWr>lPRw}W}qEfX^A+verA z4l+MRtqfq58v%5+qq#w6(M-`S;y_tsZlZ&sBUQ@g6MrofOy19q?Tjx%=k{>l=7E`lVpA z4SAGY|L)c#^~x6&h&tZDf*|5`gqxRc)sUjTLo9xVT4<=^D=;MDldsi>1RkJSEevQl|CeX8 zDLg*&_yMbZ?|NGlfwIC`{W5wVHF`$#JgrXx((t9)e)>$U6USBCHi4gt5FCj% z7ttN-3nYIS*qF`>Axlf@ioK zLzv%ZSgwK@hi6v4zV7&*T7Q}XqiR=~#SFTbLY_2m>MtUi0{+f^qI}(^Y)W@x8?dhm zQs6nK|8Xj!N=&)={v5N3J%vR(&q#+yLg)>wNxAt9UaV_8p9vp^fRbCw{XpfRL46?4 zDRl+f+mqvA-UhWN__<8448|A?s?*wz`EZ6Oae}CxGV}UWDRX(*1UK%Fk&@=LkUKh{Z zF+OdpoiAh8j<87YtJ%)tTBCbgE%CJPp%XFGSnQ*|{SVsNRqU8wey-@OQk_BNlfT$v zkCsj|0ho|z0LSh@;6d2SB&LjXNUdR38pv{OY zD@*K6D=o!s)?<0KGbUI`fm}z!!Elk~o2`06+pTsTABY8M-3cvEWAby|xEGk92CeKQfhPjsgC@<$!IsMlSpxQ*r^Xya4Erg^DN5PBj>cz&#>Mh{g0xvNN^AcfZ&5TKyZ%1 z-Tj8U1c%ozdt6J%FwAdEO5Bw@=0-2V#xSatC-Lnw2?c zrc00?1~p|J_@HCaMw2nqi#!cJ*^CTWt52cce2=Iwo7xl$-0Am6OhvC6I&r~M)5ton zYHYMQfV}$YF_A;jahu;w+k_|whX-Zi*L=85f`h>81qnJhd6~TEH%1g{Gh6Yxy!k1- zYqL7!JX@5#k8Hed8!h3}wh#+ie#=bCr%lFlYkia>rW8Ke^N8qmYmhod12oG~O~Z}c zeUbs#E_nV%Uy#TEI~{*a`l6Z1Yq+4h^v_-5nLebJ=In;n=xwV$3jJxmx9&u_Mn8RX z)L*QG9!^~2eLGQAW%V;qo5hUgD_hVv#C(S3x7_!1{G2+90Pwdqd2xE9u*q8OnQ5Vt z#X2g4udWSRrUdQBJI0nG7vQP#Zl>t2+8@g{7O*tsv&cWFkXM`*>ajKoPWq6W`yokzjVpHX>LBCOJWKs;C6g+ee zHv8HOZ2bx$D5dxc+#ZRcIf=z1$q!CaLx65UF48L9v|Q&C&ki#jT3cl9@Fq79jHHT- z@8c-A&HD!L0~hTQ`~P@AHk3E@7Wn<1SEFQeYVPYP!5W}J$8Gc9SM8jp2D*fm&SiCe z_ou~BM@k#wyJZA%SF6p34~DSY173`ZgG59{p1+Cvk$iQ9I+>$plJnSul(P`z)92?+ zq5eHYsfhGk*-ww{MakGf;c_s^mSowl()r%^dLW z8Frw)4Lc?SCgmpG7q5Mu`F^NaLp-pYWTg&u$_ysJXTNEK@q+P8(zd5F$9Gp6q$2 zAZGmU9p;%w!e(nMIjAXN%fi|W8@v<1HvC@p1J}l9w;2>a*fq`6J@z|{(9Sn=-wZOt z^J9$Jl?YN42?B5d;3$ZSYtUlB)@pP!{HQ4MEGqO(^sY&ZetUAVDRtyM(GYRM4Jv_m zTzNTJ;bJT33yY}&y^usVzcW1o zq6(IKzM;y;2syt(iDrRJzUBFw-Bu3b4h1{n#s3AObr~R4Wz2awcY8y98N&+H1Z}?x z!>SG+6N@m;mme!`8tH|GWM z=1rP?Vy)Dt*e%>$cBTdGC)%zAb9qWYCt5wkWtX({7s>#bG;>+N(P)}um6`|q^kj!+ zT#Jm6KpDg@oH>i&s@}tlaEP|z?RoAlB75*i`IGJ1m?>?8TlMXp&RCeyPw|4|BkIkv zVDjQi-a+zJ7dyN2`=FhD_gE&DMk{mSKvsQ)S)a+GvL7nP`Zrv_v8HSeA3FMU_u)p{ zB<*d9)0Z?GZDdRbgFQ`OJ9M>n#Cw=Sxm1E~K3kz5Cip?2tk;?^2Z7Go*<&JsizSN# zqUZi6Q9tC^K6#S)bX?F)luwHAJa5ZLpXMla2B>*gP|ce|u%$KY$upgSX%5go3{jBXRMdf@BjYahQRG+gMn zqrTAxZns@``Ltci+q+APxa=9gunXO-FHBcd!B4f_@5myQX+w5T98HVgPG@vGR*79# zOn7;|#>PLUnq)>nDmVAl$nl0PwA89y?Tgwb`Dp~rT4F}rDV(%;(Tv9Y=xrz= zfU?R9E^uGz?Tk<&P!QKaA4mYH8d?3AX1N=eInRWOyf0x?-(rJkNBV7hJqA3X5Ead1 zjcYS?1p1&C3>ngCSlZ}7<#M7_z9{VIl%LIuFyD6uxVs$`OsE5av^V2-fr|EYWmJPA z-LF}4gj=?l{~<_K*b-3GDr=3rcD$jEH)8wxQacMH{zNm zVJc0ToX)R!9I$1eupRcH3ck&-!~QSJ5n;@eNc3Y+vGya4^=sT51-cMZY7CCnDB*}p z7>7T2c!*ua>`%A0vm?Do(KRP^N7G|TWI;jN^kL?DpoctZ#)e~gbFxsc0YjWS3jb-e%x{c1H;Kq%^A%I9BmMj|QW`fv{{fjj zoM)bQY`?dkhJj2~yNVj{$KRlfnhJD0AJrRfOKyE3a6eSBJ z@!8N8nW6$0g$V{g0*i7QT=O*je9?Y;DL?w~xda2l96KDKMdb)VCj0s}gG&tjr20`z z0ZH4soJI2HymN<5v+$Tlp;24CN##m?BK?hKT`k#N_fWJ_lVI&=;`POWszhA$L5L75 z&2csN%?HKdhm&u%*>yBbc&oUP)&vQcg~}X;lInbz|@16P8CR!0dE33#T< zTJo0}2CjXg)j^M$;gBvb+FvG*6D%QJgQ(C)r$f5R&9EryBF{J4Kstr%(EG|mM+G(%2bK< zmj%}8ZZ2Px|tou;?@w|8hu?$ zu0TP5%G&dV_htq>%H6Ct{Ab{5)2EuLHkN+#D*ajAzVLczhlxo=9l>%?{P$BFq5s(- z{{SA>gs%4aL}NC-{_-83IAD$$>>R?4?T{G*!Xhkz6#J_xW$Oyh2u(`8jU3J5wd}p%^>bmzlfr@H81GA@Y~* zx~xbOHCOhffv4#)*tUxrV7Kjz0d|IV-(@U^$zIQut>3_5?P{I;#5;5A&4B;}BFNAI zdA$rg7U?JS*UehCA4G++bf7!%3o1@Fa!|N zByrH{BS$6J)ZO$>lq}&tL9@4)`4!?hbJ5%JBZchc`N+;mDo4fXDAozMef*+?>A&70 zIs(u{y28v-M}jA4Oy6(l2}<41Y9&;mdI+do(e3q3e&lON!11orSV3)ISxAh2#qz?3 zJ*Szt;rww!2`}`xx6hPT3puO3dg|cK zxG;@+3J~*ajtAoDw2^PkW+xVtX@16i%VbQyDsLv_Z69m2k74z?bN_5>rw7gLTR-;t zTPa7indVxLC4z*yAZwM$AV5N1+|%U{a|2)Q$sL@Epku6)k3;XQHOYdJ>7eiF;`FxH6`>fjTwa;Ey-?NsDrNG2 z`z~Dk7)|WlOvuue-7$F<9>%;H$C0Rzl8sjUwH81rmQHH;pG!8EKYTT zC~F*>u!GV1mENSRXCq|&m)ZM_n5OOK1~EpZ?7FOFZS}k{8Ip{G&#lc8@6p?4vyou` zD(w@0wH{C?+8PmGWA4P}sTNN$#er_lzmp_*cSuj%Ud4PPIQ=Or^1?Ij=7H13Ep-s97{Jf7IV=ffFc% ztfl+Kp3-*ygtq`B&i|)jWA477w3^@fRNyN^r_X?1V@&byf|;c76F8$1T{675D&hy6 zX;iis-$4X@_@X}Ehh(i|@w^`laRR<6&DqK4@dMdJ$Ub}ALDEi=4_o!-;mm&!tM{$*jOdZ4!`kK zb`ihkUHM&P&6559@wv~8Ys0)GKX*+wkuf$q;HNB9`E}+rHB73Hf;%g zaF^eW85%-OrI{Jz8^iuGVtf;=L0aj1h;~zEidLELIO#AVRPpC%+)r@1Cy{RK@(#sl zu~R>Ll!8(+I8x>7TLMXvxEXC0(#Yao{)Fl6HrwV}S-%W#8a1kjNxHY=fbORI>0WZV z<`h^|M%1~@L{0h zZIzyvq#`~}q?^MB9(vRZGjntr%Ur|Y&3W0%Pg=jxt`OfG zX(kRQI^F0wUpHz5F)N-)XVc!o-qyaD6uG+7D{i0jm$T-Caqu$>XvoURDL=dK9Tm?# zTrftUpBR=3fU^Y>OIFi%%G4tghs%i@^We(xXKfU$OXHr}p74#R%tZc7oYqf(rYNt! z-x%V&a`gL6f_cc&?(L~Z{z&_C-x>$sqBRL|X%{!;1-|^fpj!O0oA_j;ElsQUa6zx2 zUfZZ_zJxAtoxudbI*!FG7$lGZ`D1dC=&{1 zk5SyoQirVqZ!+F|3NFPUbaKr40gRb0=9wHX#@$MIs~PbAZJs%WXCWUQ?rEO!ho}x& z#e}VLki_-Eu%)Giy>RRi+^oX;78l=wP z^Bl&l;JmLX6KGU4hCSvwM7t2>E|O(aGVLt~X%$sni9c>OJ%Y*Oj%}q2J9H3QFAgj^vGaoZ1c4K#fxK+s9xdm!jv#^Wmslb*L_h}ftJ7n zKHKcmIR2uqt%eYUk#DtDOoNbln(_iX>dnR#QyGwXOsFQPFZDo)+@u>e3Z&n$Ivq6r z!cDq<=+W&zjO_&&&N;pT$!qrkf?0$wua9v|QYG9R`3E-sdau{ozP{&IVQlP&*$dEoTQaL6~eG zGY(fH8GEZx!AJ|PMu^5Eg!=KVj{}L4^~9JRrX&h$Q=cM>5)=g=4{&jZ`V8I7#C5dF zqPx8W*}xR}JB{zi(MGG|!+9LUSgDK~rA)K`lJw)u!pm{<)R3~b>aCRth$((304Z)V zfZQH3gbO;J`=@dB*k?G5ybIRRMXHTX<9*(k-#8X4e19EcyRl|LR+o3_VfZk-3wb?e zkAxcS3AYG+yP5bDQ)aTuYcM| zbQoyOrbA3CZoSiF^Q9qHJUH!v_G>8E&Vh5#ZZy!r_N;V8(VB>G(>k4%NTW zm*m#K(!}{olQI%o71L%l0Ol}Q@v-gxzk^RHMzV9%Iz($b{ouR&G2vB5c;CpkCe)eX5zg+l@ zz&gQuCQ2sf4iml@qEGns@>Z~4Njth5ciCjqmT7Dn`gWC(U3*wfRZVzd>0y=aTR;m* z^!yz#O6Iu7^Q?f{`pi*xY87N^`L(hFD#`VI3e81hS@Rp)k!ITmEG9WVhWNX?6VJMc z?gTc#n8LLM)E#Qwv`p}!_IC%{+Kr!bs^3Ii-Y-2d}EEP7cPr9VT0e04ASJ*tZ;kd+bBJ+EURA@X&W^~q>s6j-3 zzDcWhDaK*ZracBI{ZuB-THRir19~m&VHdOMhQlL2etsChRc-l+>YON?Q}nG6HwkdKp(m%P@W7G~LYcqO zq=aq46TmmMR3NM2{tJ_^zMGyi{mF|^Lwmgyn$NIdm0VO|*2vgUw|H;^eGERI>H! z5a<%@rrcYJ)XbuJOjK~XIG8}df%yaM3qwBdK(bIkm|0rM%mS^Zc5iA{)ed`5^3Em* zM9sjO^O+7Rj|QtU0xJg?yE?SXj*Pou--dMW(k7Xl@f)_F+JL&`wPX1nf$Y*zAYUy| zeg;vFCVs(nBY!A>m4Qs*XK}1hc#ERglRc;Smi@;Upb(A=b|k&hzMg-Fb91o!!*z&zG@lp+o=YyUT8kO{)Q=DQ2Gyj^rHCef}mu8AR52g^){gb+pPov z5G|bR0*1CQLBKmQwK7WnYr6%Rpe9<@ZV7M3%~}W^R38j`QCt@S86nn7RFmr#g={eW zn{NuU>)Z5kXH9XGcmnfrfsX4r%DmLTqE@GoG%c8}1(rB9`i@06{pFMVRCBJB7<{hd zo0Joh0%+|F*qmH@+8D9@<6^w?>fn;6pWgKGN7w4N14g;gHF-$|RmMr_HXwr={mE#S zd@gmw?UtXW;b0+UcUk6XcOm{63F9^V`02}R5Zz~}!tIF&yi*)?Dox58nCH9OZ*C)g zMpiFJ>SmkG!^p?G%C}d3Nf^-riNi%ap(b+BPJ{G$yjF0lF4-75;X0OiH6?M~&mzF2tZ6My?&n*=BU{ODd#*s+u z0mBNIp0N$}>L6$SJKCG>$9F`c7|6K2>xu{g4d^|vxcKP3g@oF{R4YU+Kg={9gzMQE zrb^uJsr?s=jtYApzPPZqB~+dHY4^sMN}yx`Iz`!CVuLZ3kO(SUN9(*4la*k5kD1GcQAK37)LxF zA$Cu3L3uo+7Ew9CR=)FK9?ijoPTV-bTp&`EfkDh0KA;cS1L3m%klpJLs<1Wx6bK+? z`}Z|+F?&;WqR0BOwWqM)vTUwfx8zqNKbTsSiiPx;ghu0!bga&5@yIR5>s>E{X;@jC_^?qwZX| zEErp&p_Jl_I)3npK2SbD(9f0uH-p_T00X$-UAYj`+Qen5zQyHkfsJoInKLvW2pTai z!-5)l1|4c!Ey4_F@9zbD7K&<~A4fyR%^Oz>$SfUyf7Xmrc^3d~?^obJawn5%w zJMpbb0+b%2gf+~euegiF!Tfpv5e14u4T^Xa0OTDQBZM%@idtkWH!~2ka#%AkBod09 zeCe%dc;G|Dl)xQ(OaM$NR4{*7$F^p{U~Z^<6uCeZM+?9-ZHqx(+Use@4E>o+Jwmew zc?dy|-ZG&lP=cMuL$lAYZt^-90)@q2CVVik!U;IKKczKKSJnq2mjf3ak*_1ZE{aJh zG7-cmulV<8Fs@F1W9O%xdsWae9Tm@nk+-{K*&@wD8$1MmwY36_M#=K-H(?SLH|G5u zDX#vaG^3Z74W#6ERl_kaCtEvq??f8`?p#3g8AnK2$EaC=+l}jqnL^F>sGyG3j@J^( zJO(oBT-52B)@HSHNtL|5`X!4)KC!zLv#pUpDK^-(16g;DG%VOQlEW|}I|Li!PNK_2 z1P*ew)U;Z%C3RSCW;_Ri`gX{8J{*1#CxTxhLeuPXPh{z(v3zOav3BV7X~&(!I;g6J zKqX_mj-g^bp%-!wnQ~0h?VLb02Z}b<6eYYC6mTbx;H#y@K)QTYvIP}-QErGBBFb^1 zW4h`Tf1DCglhlo(IV8bjgwQ^fB?E=-$cN&SYurIOzBaWtNcp6Y`dQ;Dk`RtVVSLtx zm6V$@8$nyGX?~cwLa)0G6=Pn)z>L-qEKVGPhSIm}vY{a266!rLhgRXd=p2g-I?3O4^fI8Y7*>>R+PxWY>Lo9o%~RXpkki74*JbP* z7`AFee*2+AMbl8ATbm#$+qM@vg9<0G`*qCgH?nPbP-$av*c{TfQqHw>)$6MVhP+X2 zIQ!h(?x;9&X(*oWKaNl;AHgJzn~%J0guhz-dPmQfbA~zQt&1WMN=>k2YANXgIEtl6 zJYo4Bv0~>{)m-BLTgf$PNZ?WU`p=Odc;7hCin2bX_^?yVX+a=RZu}n5At`4+>Ol6m zm(@Ya)k5sO3b)+jMA5%E?ko{5qZ#ijGTQsD7X#hK&EfVPZXx>_fX~53)>M0@xD%fl zH2DuYc!I*3_6K924t};s?4R2{#}*bn<_bG*7!`fm8dcI(1f|pi&aiH|_f3E^;sx$N zRV=fya4A_+I!6iBocba-FxXmB|9?{l4st;c;w>lvZ9QkynLFa_051@#9V(lui#d9j zNo)6a-|_&Xphx6gnkZbO3bRk4k8<@bx@f+QJxDFK4TsyCTv++^B(Zh^h^cW8yN$ny zj3ofwq>!|Y*NnO0Jw9BYF)k<*pXwJhXR5>iKS030cKD&5PGt=qYX#!U{qW{5x+l{F zR>WAAa29Y?e*QPFI@Xi0`@ydgr+DEHhNHQF-BpM$e0ip5inq?flp~Xcyy<6)D9xUu zI_X#{EIE%TxC+Ra&G5II^;RDqW}Dp%sF05KrKso;mxqZ5V#XELRN-1*#5eHkFl*^%s?7wJgTiIstzdA&ggdIUGF>dDOMc5=w&4%}>f^ks; zx}I>V3Rz<YdD15!IYcBqM9Jg9|(sDTo9MqyDgRu>R=F5(LxMZchcMt#p^ zy$85ce)v_6m0T;Z^C^%8+`m+=OVUY16(VYq6T9kxsm}LU-QNDH?tpKn`vJZ&z}?B5 z?GsRTN$$3E^d{a^(2y^XL^?F$ozMUTN){>^tI;vxXKM66GQ-P9UzPR z&>^Y|@rq1OqIyp<3GPgLpeaa^1Xy)o2G~4F{%{k`zyoO8w*^g5408YWdA|vp*wH7%WJZ1gY#GAS5J30RUZq zDD0Mv{&sC%p`Cb`kQJlO{k?*!Ru3T=>IET9s)IDtT-X9(#RKVdVr(fK~(ebNgka~YtHN0SjyslF$} zX%+K#keGxM{!m7FlzuMFKW+`FI}I&jaeWG%_tx9Me6lcW8nS zn`h^ta8K512qytKmwNi~XuCDG4FjUj%q8t={UWsO>FxV#6FO27+EY;zFQ@4>z*^Q; z*Wq)K(?D37@BO@W!+l)Sop)Nr8m@(sN4EG^vv+mf4N>a5M-a#O<r($8sOgYPlcCjLBm;d|A14N(9Xb832m|a)%%0=Oaiu#D=KyrVk{M zp;7x^Zx??4wAy81e|@@d4kN++7#yE6tSt2iotwSsfOx5@@3KXey?L`lB+kR%aY8u= zL8T|`3^=z`>4k=5B4zY*k3eQG2IufNpp)p$&c_WHeYD@B%joNP0S8yCas0pi$gRdQ zuZpte=N%y}{WqIV&+f(ckPIyRS&Aq&*OF+wv1c}KN9DDQqka)I^76NLn&;Bfu{e#K z18Gt>Q4DR1o$~sV*a>SP>fRI)Xpmy(X8C|2MaT$CMW^JC?%P7$gt65nV5O=zi&`q7 zNq%Cb5gt=v=tyIE8JqsF`o6J?&X}=6wgs4|9-o0h1cOW_dr-D z)P|QjU_-egm(2G{6?dhIS^XFX2ea6P55E-_%0%DxhX+K3la(ygf{8mv#q3|edm)BY z=^d$E^^+E2Uc`uU>yl^106rOM^}oqMq5%9ou;Co_HQ`S}LKk#Xvv73oMcrzY$^(8e zRg@Fwk-L6YuBZ41Q7C|fK__%!4KAI`=}g&~8xX1t;w#pfNHywrgBFPJY!q+4?Gn;R zUQ?=o?@8$^WBa`c<^L$H}N-I$Lb}^$LFTD(Nvcl&#l7=iy#cs z_le4nU)1P4dMRq(bRGB!m8MMOvc-mw*<08v-y=^Vp>T#4{Yq|bpZqS=BD0(WcDNf& zh09FgL`=~4fYD6_=xs6f2NP%G5FCIZEh1n|9AlkLadTi-XB*hlMKyKWtxPD^?DHAe zWYARBh52bDQatU>386B;y-k_0$Y_x9h0Ro*s(_0fQh`+rl&m%tZKFyfJmyT#20MCu zB`H8lPFUq^P^`brfPM%q^A!E#51gEpH`FLMe*;a5!}2j$F&G&{R+wst5+SHPCdvj! zS&MM%<|mTzIkpdo$*)vaNL;z|`a&AVQJ5pC?;shYC3*4y27=`G(ghq16%xa!LRsC> z%u0|I<=zB=hw^d!$W7ag#{)1+u)Y9rg^%+M5THv*U;&9DeYQ3%s|W$fi)=>Ic@qa+ zVu$eOeuNFP)Vied3{t-9!*GN*JI;%t3xHZuQl3L(db8>Sivvs%MwlLER1x8ky$A0q zBdJ!;zMjXiR`eRfQTh%JTv~}|!2wX`aQ6Mich0WpF@=cH5WxBBdp>r4ePnYw%(-fw ztp+|=KXDq~8<~~l_L6cOp@q?##|G&tiD8zd*F(XtO03!VMswpTQjp#Z}r4Bq7> zQINe|CUz)Y-zc%!NVu}xWVR$7p^>Nt0ZkPD*Y9x9<5r?5sLX1KD{#CX8xNOrH){?JIg`Yg<{3uORLl+IU^_H(S9H%=!TQWr{rI zUt2&roDE2z{?HUBV=F!9o$&&0olxVqX?#d=TBFGpu@oB3cL1-VzV;Jc?ygaml5g3! zp~ZTRgw+UA#y@wNZiNrvfPwS*=1EN1a1%Z8_j-ch;*+`Vhl2)1dn}UAN3-{h?+TS% zoy9bO!kzrX@$mYsVVe1Do6%UA$*OVoIciOYCP{kv1M33RLpiC^46*W=wGMtw`_dXi zlRs_9n(LkfGo@)G>vE%RuqZj0B;Qj^R<*mRo_|9!zmBE%X#5>pRq)^foZGdmm{9w= zf`@+j%tDQCgz4aH%pY@U>(WATg zE2W~`lCM#mn6gAS?btBVMZc_L88bJ}j-uEvY(}x!Q>OSF$MizpfuOB4Rxk|TXR0FW ze0~KsEs$34qc2P1pHHg(Z!q?%8HZ_Pjb???gPkS7cKV?adu|3qwiMVodF!A#>vKil z!_KmYe)aFMo{#B;If>hqc-NI^dsu|CPyc(M0rPQ%@WCBV-X*Oobe?NidVHxYM6sXO z1%|^S-ZzGDww?;A9ZmYKVu4y!etqgIZZ2!e)h#Ir8m+}3s@MiW zI)DvA|F7keuVR}5aNzVIq;Eoci%Kj_KuVr7BeBH1PXC3U^|(T~_V#6fnu|axC08ZU z-o!x`X?GlcI+1VywDPkjp+2>~Dzr4ya({pr-SLB-)RXy8u~pBw=S>^^*4>Gn=A_NcKNKS+Za!?tcL9H$XQZW7jQ zP}0cIs0=MPl90p!DlDVBc)=w-DA_xOV!9E37qPewP)zpg7)Wx5T!KKtHVpLiVrhRc zMUO}ORAcQ4ESnG-@%LWR|BcFuY=)HBT4t^`rl-wCrf)wb!71JfrXOhACyHb<0Zry0 z3wx|9KNurGxc^z#9xt65Pyy-F1e3mB5*>A0{iG^eb2Uca8MGS2!+zTEmkE129?`OX z9^r-YbKX|tryA*PpxZ;j2_raE;D+Gs%@jFuZ@C50g*2tU@BZW<^4i|ZXWeMm!j@2_ zl&e|Td{j7V%wE%`yau*w;U;+5CPv8#o2a`^JoJf#K%^thjOY#Wu|s=wiY8A+FPqwj zFV2)H!j+@utyuj%JlK}T2$Z1C(9AM z&{sS$s`4fnQZiMYunnZ&#D?(yaHd-D@{@d0S(eSswa&fUj$gcg>G%#U07Bw1~#D?d#y&QRCdfMV19^!0(1fJYN7PF}$M z8RRWJ52tTFb(s_*13QI!Pn~R^EXV6Nw_=;UV*Y>PcrJ4DiSNaB$?UU7if%bsJ)7DN#r? z-20U5*PZ{^d#|R)jWlcUek1ljROl8pAH0j5-UyNa2oDg3FgG3Wga_e)U%&ZQm0D7d z)PA;mrb{YHMPwq)$tTY_4?vLKnFjBozdtZ%TQhX=E(LE4jWDVFzV|#?W*#5Wxl1l0 zGVrjFiSjzcCv~}N>(mH_)}k@Ar}6z(1*=clFD0yxnCWFxpnW1t4@egxpULm7rAdf< zb?ke%KIv(O&@$4s*PgA!iJ6KpiSg?y42F3ght9w%y+vS!4m##kCB7D-)SD!YAL<2n zJx{Mco)y7lBO6Z4J>>qy=ydAIW|Cp=Y3w9a4Dx7lozSq|nV_m7jV@%rUWxc-(@;EV z`W5$YM;wk$1KkQFL>O2Sj8>4NT|-1afv<>58iunObA3mz8ufn8ie_f4en~f*|Q@8isy|!E&vR%sNEz3LzXz~$(uDx7Xd-Bz&mfDF5pjLej$W$z0Kk| z-{rFu=3Z~G=H$XrpPgAzD|unolJyGBOtm7bW#QNgh9ZjH(C5+4$s6{(oQBHaR|Qu| z;__P0lDReDy>C}eFF;%&T{3bU;KuNQgHFb*277nfV2R48nakelRp(ksubFHQV&??Y zF&@U;)R*=&9g%xE!${e73lA|&L~1pjTr~v96qOvVQlp9;*D>d*&|*EXo|1~ld=I~D_7?^ zm+{=5RHJYs;Pb*Z zNgK30;J{{t1=C$t?$l{3kl7H)s5v8zHaC9lPNP=aP1~l|YDp=d2(P%0Z@HGgA)WG? zA|E;fwz#;#{liLmCJlPynLek>sqFAQ0+JEHZ0eX9#+Gbqg*}`b34h+)R!7OVj7Cj% zt1l^s$*;yhTFQimsf3lMA=9(&()V||F3I&!Et0*&cggpuWUdKrOC^qXsxE|I>uBS* zI%$jbyqhzYncKcAtpkJu#f)@WFfY1t2NdbzFUI@mYfs4;oX^~ZKobWX2San{d4sr@~YmYLF7$gd=yO|6E94h?Wo;FK+bkCjF z_*isI`Hr9wW!%UsH#)k5YV9RHIt63iAVQW zhx=RJP=@49r^ed5Z2EbG9q$fDv6_BIwR+<76|-yp?rjRjjxKRFy-VJb*Ws3sXh#dH zdyn#xY=9c>X(gAOtSWda3Z(diC&97lt0l~ZPSV@FEG7x| zv`}43-rwAGoBHeH(Xg7vTpv6UWoRp=PTxkP?3Dyf9J6$Tir{|U7oWPkWJ#y6Th7Iy z-o<2NQR8sEx(J~yZ|t(;Dj|8p4e|D9asYm%7?Wso=kVt{_3&$ad;4crjHlz){i|l+ z>4n$Y;DcA2WTIx}Wfj+_v!w4@BmJ3n-C9s|rkVD8J~!M__u`XLAX_JO#6jtT?tC$m zP=T$zb)rdONS+;9+`M=JeEJw;aU!AHJ!YV%I|F;2r_No=5*WER6RgjwY8ER>3KbvwLWlKbs(V~3Wp;3H#?L2u&SU_%k zZx?CqOmjRionMLOL=l!!yIYpj*DE*ilM7LH?{@YLmKs&i;n0WIsVX3U%w??<2L)^1 z9tVlj1Mi#@R{bR_&3CBN+8h;r#7XzVw$#4JHkxU!I#air5AWTjxjwT#)Oz}<3>XQe4arl@Rg?>< zvs(DXo`|n7K!cvNxZiw&>Ye674eg7fAo0gM@16^yG@sP3&G2RY8#vL@b= z<7kOnEy!Mdgth`d?zw93$g0EdO%wBMmQroJIinrgPD(Jck-7*E_vcQqWpFPllrpc%{F;v(2NPm)UTr8zNxzV<3d|5%eOc85f4wb+scvwZZV<$* z4b5o2i3iA<8^j5j8{09V4|HWU*L7GKuA|3V?dX+8PG<}9qSR$)9=d1A>A~PscZDxX zOwM=~zYx5k-`q$nnhvwzG1zUhZ45K%26<~VRT3T$J}Rj&D);LYKcwPhB~6rRq1rc6 zqpv$R#MxC0HQJ3%KQV6vwdvht`waaC$ zsy+qNMjdK3yeEsNl!+LaG;fyVK~@mK#1~~A7A>T&RUSNKV~01eTB!j#b|XSZ5>D&U zphq-OM7U%c=p5@S1HBCI%-G6m^`fB&jAR+^6Km^_al9?CPmw1%zBMG#aOCmQg6zC- zcHn(H(j)E@l2sr?kgA#5QmbskI-+YpMW$Ai6{?4~)qyw{v6DSt3QreH`0>URBo$J! zqMjgCccDJC;`Bja`_UH1iaNR$c8PsD=fRt9y6jUGI1SZRM7Z(sV&W1Bq71w$k`%oh z6lwt~mMI)$W-pwpb?#5n^eNYxqDK@yw!}LJoC7OdbK)G~1I?I267))syrUJXs4EhM zYx90zFk@=57!&>4N~&j8B!KmNFuCH1Y47=!dJ6s?t052 z&@oW2kB40@)XTklIw}DD?ve6#?MT+!rNmK8ubR3y_fjbyGJ4{m&^i_qQ2^r7%z$&TaUjO^hR&no0C zR2(VDWUXDPX)^)KDyL(q%8L+!H#Mf|J z*zvkNju?Lrhl1z$`$-A746QoblRILZ`9$WveegIYr5CBrSy8ih5#M|r#@##2)$C5+ zxQJ!NN6)TeHoUGBHn7R+5E8Bd_ihwa-Cb-Rt#C(g}z(nVx3ud z)N4})q92Wk%!SfvcqC4}>xiJQQ;4I;`U-ZFF|UBOcpIZ=F?ilpA`ZCW39;{H6G!hF z1jivVkJGTsQqI+Kx7P7y8voJa%`%L2^SWN9I>vGZmSi6%N02P-NRlQ~jXZ6s)` zv*9dv-H5WCURAV&i@}GOqPk?pHiRiMivvW=I)$h8zCZyQ7;+xZBz}$~BC&Oy;TPup zJgi`Ms%>#el1`UX)YyteVWCT)_d6ekopu$;LEbNCri#_dNj)V~jJ{O!C4b`iMW(rB z=S+&J+NXAFgoJT3r5<|cRXc(a^P|+bn%I4-vCd2ST4qa;1Bmf40~~-RzO{_CuYNEi*?scY+^4Qx`}oYn#FF%TXYBhPFrGeMDBco zb9z}cE`D2f^RP-Az3MWu7b-+xCu~$4&Um5;Ut`EnfSyLa3A3ST-u#Zq-&8T{(}c^Ml<|8POAr83 zdfuhFcwhLNhIVx*UEX+?y%<`!UGZyaA;{Fbb>;JU*3ZLuLzbYgaJ=@rXGFl5pbLmD z+~;R_(?a}q+%IcZ4h?HWwjrv7ro2P>{wD8QpS<{iIg@pOu`5^=(MT0v+k?GcshjgG z>#_^>k|Xe;dJ9=&cA>G%aqnt&xYqYXQ0kTq zLzBk+jx@74hR#)zu@J8VQyMlGRgSaPgn0Jyq$*g^Q@Y>4u(6DS!^<%26i_&L`PohTeTvMd-+8~>^e&+ zb6Y=%JN67-`mH*{+rjf4?BDj*^>VgUYl;lzo3oPokyP(1lJhT#Oed)xD)ID=hCN+^ zJZjRc!<>1kn41&X>lh;WaU2KlRAhx)df+?2gxqCRHj-z2c)6wnO$z9W9BlTrI9gkZ zr4l~KgVCxp17`i?4pucKh|7k=a)1+7IaSt63{^D5WM|*L>wS1jB2m97s*nMkcU!MI ztU-B7sl+$b5LD2~WlCRfBy~yYzof-Nk%iafHuav zWtrliN3=J)u{=;gG=o%Ve-pFvMiZEetG^nd`0$p)|Y%M!_n)S>OGY$c|?ru`M= z3JdF4)vJ>zu!9*Gk-z695 zX=hBk7q#iWk;_MVSnhFRNLT!5MQd~`cRPyV;IE2cghHEh#_abkz2LE#v&O`vF?}_r z5-VlV$_GQR9`bOYrpk%WD>0;PfZorjIpydvMY2Tt;U?1=dL44Hu;E;5Oj1%CY__`{B+uou`D3e2~tH#1EHQ z_VMruZ@wqBoIv-5uXFOss@F|%;ryT!U0-2}%CobARfcz{c&2VkiwHSL{ug=5_E+`N zA#CiKYx}AO7seAsP6h=}9H(1M`sOb$5QQTLa$*?GdI~#<#2%0JxA!oIC9BxKR4rw9!IFy@MIN}8@#45$HeSAy)*&jC6!Fo zb&4&9HJM!Da#+Q9w&K|DYi#mzb$?&#dw%4~{@}CLRmc*omL<IUiV2^H6jb4BK@t zw{{@dwBJsq7EeLYj@CZb@j8jD(SU4+YY8#OsH+jQ&-T^t1(qa**R+njdAglxtzCIr z(zNd21#gcPm19RaEUD|w_d9AH6{=jH232*TggXO#fAWz~ajOXlB@9Gk2&etnPA%4I zhUjH)re(sOfP=ORh76u5V2R?sHrX}ovby!W#47BVODh*~{95taGuQP9VO9swWv5Z& z^ib=4UQ&=kcMgeOLDDg(x-%UC>jS^WGxO^O?rcmNYi3_Hw(wUQ71OCrTIy0`pDj1qV8$*ci>fFH6gO#K(;=_Z2I!F-o0qkMMsZH($(HHp){7H@<) za@jzb%EyAH1I+LaFAWv|NqsM{{qE~jiQ42G8205JOIbe{L~HbDa+&&YyOGr^VuXRL zV*GuulWod!BhdBz?17>aquETIq9FX?1RZjY*MooFnU_)Ur(i;MQ0Bu%XM05E8qZHM zSz(!u*zX71G*N7=q$xTqNWq@wnk(U!8Dq*q!j_Uy&Ef@PC%KM;4AioO=0SUHsCAmU z9Mw%Qgo#WS$%2d*qL#~Tu!M9=k@*p_%}H+ZsMGS0;_s`W zrlesF2i-JerZl-AC4`c;!hTa<{Mp|9E>+?-rF>ger}u&7r+w@EAU=b&6sS0pAp0@P z^Yv+9!TUm||Os6c7?^%il|V?cuz zZOVkEd$nDuyG`?_ld1P)8Oef(@2Sxt7p7+NJ2nnvKjVvk*JW1PXDLJKOE5GTCD$Z; z+he4e+)lT=m~1y>^qOZS9ZONOTPuLvF^|XfNfi%sUe(whNI)WOcc*gG=M|0XZ#a+b zbQXECbW1J_tc~H=#87{ToqO|)o1fwN2^>?43wG`nU=5t1#@^|3luNHT_~IWoRvjkB|hN?y?yX#LfX1h#r^w=9c4yntgOJj7n zj2LbdVgOr|Up_oS?v~lHudM)uT{sJzA9}NCsX<26MshlnhIfyEx?gVIWAYHibGV@D zhz^fN35h)udTnMaqG&(CpsMCbPonE9yFvK%nY73KNyYlTYE%{9z#I002Hzr@-!=F_x|4ieX0BSL!X`O{5i z{OoNLKnZ+N$ydo~lT?@0#n<7;VA9E9G9Ft<%t_ug6m)d1-nW&k#Jz5x^jpO|BZUZy zW-7kv*@=)-+HUZgiB6`O;2PQLNkuia2728=dd8X^PX$InPtz zBhkX|8H~f!J4!(e%Yvi9Cc)Yya=u7-ECxVIr`##pRobWOK_XZ$3L4zM9PG;bZ@F?; z7LnRmp%fu2`Lkipdleq^IScVyT|IZH+mwe7cubb^hRgYap|$bMBaOkS%#IW@Is<(<9YPIZnAN1F^&VO5H%Vx)6@tDrtoXSJ#c zhED=`U$jgg)hL;XpLuCu%^GejNEwEz`65teo;LP0QNkzhCMt-?Gb0-4<&W&euqu|% z;Sxn1>m7O`D&h5vAElo+KJnHDfqrg7$gmd3W~p4TTKVh)&g?XHiCD&g-&Mowh^N0B zZ|cJ?Y98xbUXhZtMOHxHA^VK0_QG?jUqh@4C+=eVlL(2KY?LVbya4qI=O9n7Ycs8^ z*r%jh;<<(^hUE6-q9e87Se55#4(*0i?>;+aHT8^ zs4g}6oN@-5Yaz3<7EhKBW+ZieV&kRtXw|62X~AwrOS>Z**!ROa$p`6}m~|o}e9G@9 z|AwrQ-q!q?BRd_9h)aiqh1IbxSm+8UaFv7MAGTV9rt2*@COAN4ha1C|j@~7+QZ3}?A$+~h-^qmEJZvZZO zhz>uRc1?CWw$2EVLlEFCc&VBu44>amV#0l6a#8c5WMntN6o$2pN}H$Cvh!F z;&^Cz3gyS!2%2&5pJ%!p&&H3>*BSNUQ(m#IjWH5s4v?#g%JbF@hJQmsIKFRe-L4^N z8Em9JqbEz@>3yjt))#Wu@0{y!eNmp8beOmyZ&b0G2Q_J&%wWY%!YmwP_dX5C+p_wRQc0sk9K9f| z>)PrxeKjuV7|ZL>dJV%+Ouia25BzRz5Gc|sw{DN&RiJT@#qfQ0oZ`i^N~_s#H`aB){_V%r7#9uFfMH6upzL- z8BEeR1IZcWEF>NyBHL@o(nUx2?oN^{ZQi3i?;2~4ahT55I8UpthVhWp&o#$wB8K)6 z3n3h0-$sr_RL3++!Zrm0d~kPGPzTRdKKcG&u``D$1RT5|O=HZlt56zU9gbi!v&9yM ziBcGwUQ_JjI?Wplz0Dx4rk?l{SjSajp_rCC`*5r|d_q0$KH1?8wR2(>mqDB7`5t^~hPb)7>B zvNO&(m&<&eb_i*CQxlD31L+50FL%Tz(@J?Vco)9siq&~r8_=EOW*pg?Zk0mj36g1i zW^3`GFK0|2Pvf{>a}l93!vjO6;84SmebATuHk6%Z;au#@Ew*7(o+J4=S?QDMTa!)l zr69)RSlYE<8HQXXvXfh0Hk^g$N!}@-cp6bGUzZJ5?iU6UMENCIJ@D7+$^;NAfcGiFSr|Bxq3QU=fS;VJ5~KD)PU{* zAHKh2u~IOWUDAe7iIkPi7z9LJXXk7_TVrqU-HLecJWY`cjicmIon+0LEAqSqC9`;! z<7Lvf$62k1_iztPLSD2j)6eldv6}NYw}q!^F1RtrTxT9qu3AIdJ2JAk`tl1dZDq&1 zbx@95Mh=YSF?fz(IHjoE&>P5txmZG9=+KDq?D8@&r@OK!Zss%Q;b{ktGn}$3|;3~V!AmtI0`77c( z6xZdSs5RnLSJ649gp7o;_dZb*NX@_|Dki2=12AqV37t+h3XR+)D72yqK3zyMiaTFo zXBM@`l73%qqu+@+yfv$)^=0xfaSn##eAMpAg_Ncxs9sY6W|Y{Nu?b~;2RgJb80~^R zK(fZ+t7|qT77y7c+bE%F-kp;ess@TL!O1>xl?ECLy#lH7JtgJlcDwU__ttN#T8DTe zTXnLVAD8*WHr{)0@KJ zy%*l&bM!L?kue5_6yB6VRBlOAabAs^T`*C-z{i9wApN)L*dr&u>lCSCcH4IQ!smSw z!F!R;@^chwu`O}RrthxHyI75cL94@XB3{t4z;BP9A*1R{ zAR)==RjlbxpWD&PbIz!( z^|-5(LoAI?_tjUc6G3>5NR9GQr!AR4+2i!0^)T`aUg2#NQf?TI2c+v@_ecZ<%OON` zignj6yMJC)9+r`DN4?n^oW_D^q7#$5b*Lm3TaG5zsbR>AaT%nKpE+CKYhLvojF}2x znXAr|(9xM}A;fYSA30X%h>g=!dc{J7Ml3m2r}h}H$?)u!Gjwny={_C=n$0j>GG3YX zHS^`tJaBTd)2#DcB%`l5SeFIuuP}woE9Gw@q%NX(2I81lYXe`FkRkI;0SKV^t4}tV z5m}bM@^TFs7Rtfi^?r(&n|qYi4<6_jxos>OytI6Ioia6_`E8)ICrrdbumUPSjv zt*R3;E?Z)xJWZSZaV-LVjGf>;Ib1kmzWjuot$)BUP$haQF-q3tGZhHu#k`_N_e{L! zeM?qpkBAt3H zsFvd^5bB#C;Ud0HntxJVw>+FFE^b6Hi(Y51RnJ&M-jsO`GPctqus0eF^yL^#Z4%%K zq+=ciCQ@bsppmTL-rT`6Vum~Gj_52zqrLyY+bdJ_)P>LyQUcoC67BsG87T^rdzEV) z5V7m){hT_nm#sy4T>~rX-NRfx6v73Jnj||%?u_!SvtO4KvD30wU}(ER@B`OTf12G(`dG4vVc0yY=!~I# z++SXmawB(O^Z2-{PHNV=kTz=O8lNPztb4EmA<4sV3m0Et(1U48vaB+eNN@s^QTSD| zEL~}YL7Q8r=L{j`@Lh!u`h@pf2s!sjK4`9E_}4+e?{M^kW3jI2g|xHV3b!RegBbnm+lb^}H{) zwdY;o?v9J5udsDuToddJy=%7ZME16v%YA_%W`Q-JW!CFJtuuqu*e4ib%@;HhP~8#? z@7+JBqAy>mMQO!5!WB&QDq)8yIEOR{rl*6b$RbGc%;F&HvZ)F+_c2t2hWoVqvFtD4 zbbHQsW|;F=rFR{|Q$npB;v~)>lP{-6WzOpii7%MMMEHs&i$BFGh2J_$08{acsuzUR zY81L!ak_LEWWX^AD!qbuT_A?U*^loNxh|8y znx4yqt|(3_i$ZzSIfrM7KUEQT45qiZ(nSK(fJHsQR5{W>Dv**xxAcaeKs! z--j2|ge#-LIo}Uqj%AN~@TD3io=xs0Y1+}Xp39O^$p~3a0(C#2?iyhfba}uG zotgg9gM9^LkMrG&;QE8zY=&^sa23PXDqrusy$F+-mUkJZwgJS0$*YhGMsr&U=$=6- zh^&t-l+6CaWo}B}J(|fa_>smN?Hc$EDISJ?J(lyb>r&BmXL~nkVA#MqWnb6ni9f(} z!MKz4bd~VP+bQO%len%dq&A`3KAY5cBgh?b|4VF*)tkC1+edsJWegEF9Nt#2<^1D( zQJMxnxFFpV)jmddY2E;v<|%gD&A-W-=IQh#etbgzON_raB>DU7=#;5~gqUzwNOXMLwAw13(H z?~&9}WDhXr{{CL?d%f@VzSsL_)`LwF6{b5i7=eGk zeEh>Vf>YbeqrKgJ_<#TJ|LfDI|CHve{nSNm_PZZ`_*8-va4z#Q8-Mph7p-$Pwq+MJ zKYWt7-~E7+_z$1PESZ1z!+$Uo@fk(2&nUxuMp@#APfgj?Sqdsq%nzSlWeOT9yW&f; zLexyz51+ao904sx$sEPaPsgVu`gn(ezYSwKXG!1mpnHrYKmY6n#@4N1aQ%3cN#Ffe zB~Ua+WtWYAqC#5EW#54w5#)zYb5u;f`yuJuHtN#PKb!OCrYv6b51-O<8k*>s05tKJ z|8B3W`*F6;xMV+$JI#jq^}8RC|HFJm7GSG>G;!K^o=g;tO2a^^ZE8&G=5s93{1A0 z(k02ppVs~_n&+=f^uKR9KO6aNndZLzGO;{LvQJGEXAKzpm;e8txi5+)i=!D7m)Z3B z>(MX6i~zxuQ}T+&0x)FRd@CC>P}+~vYnj2m=l~a$1t2fbBKrS;fB)gb@4F5x1pv{E zx~%!s^uK86AGh>Ywv}UMCu6pyBUq&IM@|KU_}I#z5S$E@>nFtmbDn-y|I>U7U=%#4 zI}BO+!>9hs;zwXZ|Bt@&c`3u>6iIeD($}q$A5KX%pVQx>-m4Kz2i6A zqcH5}4gS1@M*fPfzQ*ZCH|VeSLo>|Z)Ef5dts#F63_rDo|9Wc#`d75}byNR7?Z51e zUk4Rue+yLNPl5WM@E>i+ACFtv5S3rJ>{FV3kV!vAAC;yd``C)e|3SYB!Y>Nb4EP)n z%M9qUjrLzFqcP;ap7%3L1xi7`Upk*(V>Z3|26RV)!+E)<%h&o~|4((m>enOXFXv8k6mfVC&>8qw!tDo~N&5LdVt z7LxqOTN?D2?djKV>1Tqe*DHo?jg=$~X3y8=aa_5%8xrRp(?bICud2qa7~-=}3x?3$ zizenNNL%pZ<7b-Aof?j)t$L*|CD{kwB+ZNMz66xpZJzh_Tlj9gPnJ>S7v%u$f0!nGGVFol?_E+B6<{s(G z8Kj38&`-MJ=I-WO>od_e0J5U0q`2%15@5+Z*Sx^qe`W&_O_9 ziJ^Tp(oeTjmHl0I`Puz#kc2Wa@Fm$HBpCjbU zyAj&8u6fj_VSdENMcB{RCfD%Y&j66m(tTZ4$VU-ArlfoH3wB#Xs+PK7_lC<0En8MlT6E_x<(*x@}!i9lKIyoD1HqK zE@98&$fI9HC=5O)Co@;0TbG4W38qp$=L7GIEj{faS2*|D0iO>n$1UMsjsCelnm9Km zm(HItBV?S2|ZJ}>pDFeOhQefx$ zjDsWXvxVk-$h>cbeR1CSP<&nuez_oj5o`f{s@i^HNf_{Y89?=w=`I4voxN@BUJ+kw zgLOyrx*$JuZtzNcO1mU{d7SeKf1Cr4&3ySOjQTu$p*?23{?|&GkFBz=t9igc@yKkk`<0~B(; z0{D66zdvgZ^FlF8jvw!hZ6c1n%qR9psdGFIEQQ4QXx-;T-@763y+7{n%g&t6tb8(5 z5g>Ygp3DMdpUDymMhSS{-*9K&f5d1qd!o$g3dlPXurrG@cXoTB0|(Ueb|{Dx==$~^ z&ye1_>|9&vzOw=QZGXYDzZ01aioM>AU^2dI=KFp*9>Kl+f^oYGvU?yummWu>K$_)Aj%#i{NE-tXnHtsrLygcAKt zpllnl?_D-I*@Si4=+;D!-5UZl=zYgy+&1v}b(Zyx1@mo582C-JfDdVMh9~7cF2P_D z^G9fptj1@FFsS%PAuXDu7laQG3|RDsW}YwOB!KG9g8n@t&-Y`}qk#F5;R`@XIM{;? z=hG@a<$G~`H4aA^^w~&Zd+q~^;1gii>rD)aRuBs4_9On>@C236_W>K|vEuV=t9T_r zTL{qug5yD@eBk9G|Ae5t&LIu>_*#9#I2?{5o$ASVI2S%2=D%=PC35$~bzWo2hPsLz zc&sL|zN!vDAqukyU$~h&&DQlv3KB)PDM+(_~Sr909$k99>NJ?4@S8(og-5xyR*vAQ=ad6w{^&AiJUChxSQ^;YJj%Vfu z`VshKK)nRdY(%jEAChWO+<95!0ozasZ(_Z``_w!B0$$UB&!>71F%Z^9)p7zMpJA+R z4j7%qJ%YNub@x-$&au!T$7(fAGwW{ievUD1J(EPfRM5Yke+bCXEebm?p_Zv6(SZmw zC_GH*lw+sYxRV!T(;~$>J)GAB8o)1Zy!ECWml)VNFG=k<0)sliLwHx17Yv+1n4>-q zY{|f^6E0C2R?=8TTBgzkzuEl5;3RU3BHipgj*)P1@lHjv5z8~e-}|%IIlRho_xT7e zp`zk1S;U;7drvk$>*0Js*Om^|63-saqq5p$iQ=-Fewv9Uz5`7ftfZBdC0xBDC>}ub zw1NB9ap7``A0y%IEjmjiF(p5_;z8}OmdK3`OjC?_9)b*+>;{fZ9*#OpTeIsiR%qF2 zh1i~hAgZCBvg;lnOym|T5d)fqcsV^V^C-L^zwHBzetoOT;RZIU##{d80Fdbj@HNx@ z^4Gipo6!AS?fyuBu)$Ko&FOr^kV7_ye+-KEwut-yUopuFUC@~JZ-TmYQ-KxY7vbl@ z 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 Io3u*`0F~fIO8@`> diff --git a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub index eedff81716b1f96d382036084967985c0fa844a1..4ce13e394fc4e2a45204d1674d7815c17663200c 100644 GIT binary patch delta 31648 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 delta 31365 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 YyI&s8Zs}I-yTw2L4_Z*-wP?@^0MQ~3zW@LL diff --git a/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub b/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub index 18795ce2a0bedebe89b2dcf70de3136bbf89d3af..3486d0f92bff24e770cacdd0363db95029051c2b 100644 GIT binary patch literal 554004 zcmV(vKOd!|#T-E>S9O;m(%~<>ylcD&}zuw8VuSehi>rY;6+1ku|GmZcG zms=Nq{;y4cn(a>lHqXVFCuv{&N%lR-xl1e+y12BgcbPnXYPw}zyD0-pR!qt zdAf@A&p!Q0#v6Q4)%*W|m-(Nh-|Ok9>Oal?e{6roY5#K;>-}eJ25|QO0iXWKr(*lF z&C|O7z4AJN;a11E)y@1T0ULI3mSoNU{pVd2^Pgt?Gc@3|d!6imu4eyx-tABEn~Sv> zz<84W&jiN)Crx@V+WikWy4(KePd{B?Y<;mNV^;hfW!X|1;$O{7V4urT_cA0&dRV-IoL0wmh509n9MdZgNr; zU?l(gGq1(j6jw8V5B~G7#^Hvy5PKAauR- z@xR1qJ-HBnGc-g7<_#_3fSv4u zC9-+QEBi4dp{=q#<`oeeX>@(;=u=glrc0XONSfo|D8BnXng%CBv*9@3ZiLybs7(QC zmoAl?4w~%LPOV5f;`o_vk={cc->BgCy~u3x(kt#OfnT_UUz}9`ed)!&ifbaUi!~YC z{dfE8I|dS`3E;S8dPJ4~yPuRt5#RlDs@5_%&iVTx`t9V;Kl`cFb@A%o{d_r#ICTIY zwu{Ia)qgL7)|~M9XB@`$&qbuK63ATq_uyuFTJFEY$-S8GxWD@~)@JPzRs7%I`G4Q%|3A<6 zC7o&vK~zM^`scsTEXS3clbz*wuKMTeaQ{5}k!WS)kOfE0onORsMb#ERbiL8eL?{kn zfORP2I|=0+j73nGn0|w%6&kGlq4&WaMDuGy*{5jEFx>~`i_|iieuH3r-R3Vl!pO#` z+^-Idf_$9JPrPyM{YvuC#iLE>9>0emzB>YaGyQ{tc|zh!d|aQkXg4Y=6S3HTSTy;E zy(G9_EhoGwuR#%i9U2vEzpOgBiD9}ORT74HheGW{Z-uoiG=H<-nZ(C{AR-+8xGV-| ziAh=Gc6A7TUO~8`gYw1;SRD3#xL)L1?`P3sSh^nqg;5Mwkdgd4&Xd=a5%1(V(B>&; z@4wSsOelrM7q9SB{2h1YbtUqb=D(l)eQS;#ZKFZU^_C#{>WDJ~R~mhAU*sL28@&as zmQ@ZLR+k|LJb}0z74+u^r`f0)B--z4g0|M<6Yh`jo0`^deo@^e@}^BGhKti8)!2LI zd@MUxC0bt`yr;D?T0LK@Xn&@qf3vq}7Q~cI<@37qZuwBdy_I%6grqr}l zclf%=KSF+|=JnPKFeY0(cywi-*UOrQfbqO8MpB^Jx|tnSDu_VT3wq5H8Z9bWYLP(2wNZ|BX3zC@Tz7Kd)6AU{`Pf&{-xGKo zt|8*X7hxx}mw2Nwo8tH7WtAW68^dkVg{&P@jf9<@o#3ju_=TDqmm&WLal)^Y#&%5$ScWV|s^3gy9NjjwYtm^@`K6p$PVJT; z-}I=6(Hin}D7AKsz3}75X*Kk^i-$waPeP-P!as~?u);+hplf#@KGga6yY69?ufwNl zvXeJtjz{pXR=avpd>;PO|MIr#D7!cI=fcG0bnAX0`Dv3JB9jnlnHRnI$x7^zZnC0L z>^#x@RzF8s8`x&6rArX*%>133hwI+2^c}~a&f}9OiJUa(MI-)6D#UZz*XIDJ6TIwo zsxMqYP^mZE?x}eeCZA4&|EXg3Ct;R_;H}?pfCZ)6Yw~d@B&RS`t4zar)|7rd@^(k!D`;XsU*A1gt+0u8`=iK-dF=313CC_SUYL zbgucyxJHlakkh_lHL^0o&-mW=GArHQ@^Y7n?|i*P7;dG0ZiU~RiD&lq*F8cvzEkEP zUHvL@Oy#xxBVNCjpdqELa;-_Nwvm3ub%ghYit3n6(xlg>Cg(0Am13ikJ)_SamUZ2p zb;LWa_um%DJ|(exJm7Kh4-TNT@LsBhv!g=>N0FXG29kP7TH3~)G<00N<#AIPJ!^7W z&vMJ#(-0^dBfViZ)7u7~U`3=qGqcKXE6^PS8>Ij}syFHZTq4Y`K!}_tsPu6@#9NUd zpHZeX|LT79(SuLr7eXv>4iaP@?ouT$63Vn{tifxq*>?i$F|Q*0Mdz^OxSTcPjdOJA z)giS`l~uTevQkiCs&lNWb@x_xHx;~w7SnaQ@_-Q1aWI5gUs^ei?%F)sL0yJ8;)Wg6 z*bMi)`@_c{_7Y|mHlIxkrr)U?zGn0n3$7izZ%bnAFLJV`KppNCq%B!B$ zNrK>lo#EZakiQHTQFRq5hL^-5Ht{;Pt3Xk@@)rVG%l`^JOmp$59xpK3x>wJQ62B9jHBLR@2$T$7H(r!M%$s`}HJgy`LSUqOtjcO@B*A5Ap2 z3KwEZ)4Z7T#}uhwV8QR$aBV6(b}kVj~GqweXxPBUxp?4h6Y-KmEsU8fhNg6 zgDsM{%jfCnqHJT3)@|_X#}$+A<+H`H`m>xlw-Bxrw^RXn7u`}W&h9O>j=5Y<7oVYc z_0F4*Ykp;Bgt2QuYARERUOp)V8+L?ey<7a28g6DznIZqI-Hwros^nSv*%M{8ZcOWq zrw$?tb1jo#es%41=ht>sgb$IGrOhgoMfvDG!#JI`%M?Pg+D_ubk!BkHgMEr_2uqGb zQa&O8L75{hHndPYV7`8XG6{;ynmzTB&6SM*2=a>V?OlIW3fq^@?E|Q^OWlPI?sO3@do?>4lpvvvP2zo?VN`6|aN>tpp@Hk8CwN{8INr@bo5{?fV2^1TUv;xncp zyZzv1rnIKwlpn>{&>v$^C7L7^p=CTl;6iL56i!Rw)FohE+}c@REtb0yQuwJ6InqYX zO*{~y$AYzAUgY4;7kL4+h!cro$dtW`At}c=Tkd)Uk%i&n$fEK+Z z$#;;DN*)d&{Am8{C*lJgVI`#eir&2HDTcNvMzEYhu=-6lsxnw&GOAp{*j1`O7c~SM z=y$Lv9EI_zdUeLoNoYQb!}N+iv<0QsgF&tYD@gJ4W>8I}sP4)5E?NnH5oI0~Gt?jn z$!X{Iz%EH}P()ey`Ym9!)9*uWCxyqoC=KTMcQo1y4&%G$x_UInZxejvaqTj33HwqN z+yvjj{AhpYXVQZ{PyS+R7wM+^rElUH!Bbnvdby(9Ou7=?Gs-q4*=3GXkPgge_AbZm zn2114jWo3wwicczg=omRw(^jt>3NzX3A*5GXuOJtWLP~C&99z+I?6z5ReI^|N5{U7 z8rk?OyM~Vm_m#nr#*B%mRptY^hS_KDCM{jFP{QmHK>0%0%u9{U_vDB;#s*!LsYA(3 zi>t3$X3YEUO|SYQ%CGneKMUx0ycYltpdFw%9b2rY1;?MmD?^HQ0*7-r+ zt&&^!2o1CBw(oBywrFf-E4omQ`fda?(Z3NxX^WS5vHw&< ze7F@@Q&%JHgpvHb!@YzcsC$=0$TmB!?c}8Mn4<84Qsk1~>oh->`u@r^JLiJv;VSz? z+*nFAm000g8$IEwoG>{^qnk9~4+^1#5~7q{Eg}2r05mR{W*uOneiZR*Hc`;Gttlma zPJ6vQW0JM+CvMb8utr{KJ)b##2QR5#A@S-%LU5du!l>4(t5)yQe_O-kN)SxfG%9?v zcOK}&c+jfolAfl=kL4IN=m{^-{~9yemFgE%u|nu+tVu$^SkKRUYMia^Af#hzav4h< zmsqS3=rsA4Drl4w=M1NO2|N{Oy?Nzs3h<4JyX3cc@KOxS>sesWE!-x@~lB`pK~Vs>dp-6ZnQxpjk01SXq#k(p=NzK z?K)kG2!mJ_QBvxPqO8_BQH=u4&lvv{=>uRZ(pdB+s8O59`*dxlo&g&2-0Hm&EMC<{ zef0p5YNz!ULw3TX>8Cj#q_wou?MW&Lw633g)YFI_>q~)D4!$VvU3Rh*c;IpsD4*1Jr!LHPl;fdP-i`kLNF6xXGH|XldoBCBwddhn)^E zf=S}Fi&tCauQyT5`9bp-amO3BUN4N!%gRGj6KHh%hDHZYuzSz4q8pzWp`i(yx3TFh zsa`Wmsgt7eD-=ct&`19rkqRu6by zQ3mP=VxrU0g=5dO(Cj8Xlut_aHziV`J0oeMLBeI!KT}Hr?=}4-4HTH- z-FV&`nvL;?4nGw(T>ioYZ?Zf@tCr6)en{NE8Eb%!QDd8xv7C@tN}o7G+OKKh?F!NP zVCPrGjTOj9j53DvUZr9js8AniF3_tjWm)Ek{kEw6xr=5Xg9;WsOy|yD1E!z@V@fIQ|F=TEWV2YK zsm~ayc(!k^yiW{1bzIqQ#R$m~hY+`bYi+Ix^Qp_SRehLAeAh(0G8TOf!cw}+Fz*h4 zR@*@5FFdcszKGCb8=z>hhzeDX+>xIt|)~Zl>;lunuxivBhQ@*Ct3}zJb zxdX*NWje#)7@%8R zZaVL&OLNOATCW!+UkEQh$^3X}d^UP7*9*wUK(q5$PhOr=?6tUxrJD9pVP2-834fGL zGw&e?_g7MpYd<>=Sb9o2zN2~dxKVo*jjFP)!`w4EaF?tqA{hq``V}vpavKIH7TmIL z1pIne04rj3y>>M>`=H6J#(8w&JJ5t*F!Ptcc>KGM=0i?XoNeA6S~=F&fiwRGzUZI{ zEYfXG-M^(qXpt<@*^z`vi?#_agJCWs!q00{3Wt*@9eyE}2qIeDBz-%Tq z>GN%8BL&E*39H+~5Ra)B$bes@%_0W&nFmUSP>iU}(JIWWXh=9GMC?oMAbo(H4f zHTCLXZx=uiVv*Pa77C1oa71SI)6+6>%Y_%D;K%Y23A>%F?-Q|iU6ht2wKYOlbz$2C z>1tPqrW9FwrA^X|t79Pxh(+`|Yro;9W~(`<4Afs-ReWT!!k6 z+yn8+%82Z|j=P1I8jj}`#rh!u7-dN0D?V~= zx~~0ef0%VFTXZaed~g;J@JCn#J}w^k#XxU>&WeRJ)5a&n#^L@~T1)XjuXcoyhCb;> zhiq|#yT%?@`vptCqrkv6f}ziq>2Z<%J(S79k8;4m$gC9&`Vc~&k7wr%L}BxGLi2kR z>qn{>Xs_}TD(8~etrGq|2ef^2$at6VCxnP;FMm7C^f1Ji5xjl-gMsT54wvk=#&Pm zQUJ_3^k+hF`wKCjWbI4TvlJs56^=;t6`c_(fHH(u7RXKuNn0~XUqhk(O@x>90clh3 zaF5Lv68s9S&BuTH!Xhu?pnE#tHyPU^@(RB~PL_}Qm-U&h!cioBw+&+0^q>GRuA~X> zl_PyVId7N9i~jqR%1?0bI`5crM8CbZmv8m7;>?-*#@RG3+jgJl~8D^l^oB zUvqIHA#V8DW4AX-|F|K1Zk-CN>?w81tr3`C7@X4!?+x6=il5QN1jyNOrZ6Y%1n~>; zS||D#6cl$kec#Daq2upW6}|)3+BW%Q80sw2m*Eelpez4T+ecs77L>YqHr(Oxdz`e| zhoZTW!BZ4IS@8wM$bq>Qmu!L*)NBauvp#>{(a5(7Yu(bzZUw4doUP!@P-|D0Li|)W z2-M|FJOKDFpF<+Ks@`A7Kubh-(u%;x9pHaJB^Jzqu>SSTvPO(^_9MV&XC`G3<{`@G z{et;7&{P056-IuI6Z#d;o*!2xH3zjqpscMdwlG2mMvelZRro;QBIThW4ooO2Y?2!> zm;L@2r1nihYB*e{h#MZne?k*VdqRx5%b;}%h+#;eVil;*!|TiW4(bi4^GTX1^}QrL zdFY3B336XA)+nnCkTQJPkQ8`9;Lg%kI~}(|0Y7#DYKRO2onIHy$M&$BMt>^uHfTgQi}u7|Q#A4-p;E9VWW06D$c( zPQ8;6n!NwvAAiV)=nXt}08@yg2E{G$J{|WCZtK(IX6qokwa$l?xK7do$}Q>zMaXb6 z@?fcO0jE2a=|1y8ig=FToC9WnLd?G=LkVXOwp-*IzE#E57ab| z3|=BqtUVA@WL!)`PUoNO~vLOnvNDaZ7nFCPb8mbUS>eb+Z zPrjLR zrMnkU!ncn=TT{E}ah1`?G35sv6CKsOZm`oe09ujN>p%;ngBg%Av|1zi^XZj7li*YaJU=cvT6V}D z#TMdQ;5yR0i8FPc8($r+F(6356}&Itk%#Gz5= z{yta%Xe{Z0I{5vIcdpj!DZZYF$_w*EQ$|ej^E==Qou+Bqh6OAI6h*^3ys@-~4&+OX zW99u68;S+R@B@mw1L-P4KD%0>H0J}~_8R@|Er zNFeqaQRLEYW!qK>xbA#-|CMq(!vX;-0I=Q?xK`CEC;htc7Qzxc+99T54;GfH%(6i? z2DGgAd=ac3D2P@3V44#O%l>$6`$Gengt-&GFA3zRpo~-YZlxi(eK66UfVKI187E=M zEVV`>V}Y-PnNBqQ@wc=A*g{)*Lu}2 z?P;h-`1uv_Z;(ODZ0PrcdG-h;p-0~`>qEEjrMU=u@!SHAO0wC!_4<|bFNG9?hQ zNrx@ z`LOeqRl?lKZ-2y=T38S16CaW>WsrJjaK|U(mwE@aSOXc2n|Rbe3eY)#o0IeNclqWx zypq>RDJEq`Y^u<%iwx@Vg5TGYCyUkWfiBfQMR|WfS>Xeg<56K#GEg`_OaDPm!(3W( zXu(Hg`fFF zK-8)w-(ouuajN_u25*0T6afR+x%{ahXna|)-JUR-mcV!J%E3%Q>uGmlR0w!ozAJeX zIiNl^SbJVpf~8mVCFqL}^CI2>9hSeFrVJJGbmt>R{Vn-*5A1vovmR6cvmJh9*1LE> zd-7|dcMMlR)Yx=#KqeheQ+Gf0+58J?9f)Kpj17F}Y$<8wU0sERzkm@1HOeYy{gjl$ z*#b-aK~9Kx8Lub9` zf~@syUnITkb3>LD);glm&Fw~W)Cx>j``y|i@$ML-Ynk+;j59^*H6;UJ`pA1NRtfzL zPkBIp18RLq*NwhvAFay>YBIn)>C$p)Xj}~2sL<>+EAVJi8GQvHbE?g_(ck-Jy2I!F zi#|=1dcZ#=vdGqI5joH3?%!y+Lbi2`uqQwa0WZUYp)Rpgo zS5}%S&44%u@M)T02*IQqj@7=c)?|A~{Q#kqCSURs9i068a&Hzc@rgP}J_k{NV<$ka z6Zn4lq1ZsP>WY=?CgsJ9UHNL57?JJNfKW7e2*1g-^QJ#g=}k7ej|A zun%cCQ0lTfz8ENSFjbVlY!4c@1pN05^cycxsT_K9&-4|98Nd=MK?Vk=@M1?P{e?kX zm*wT>2eRLk9w%oI89@TF-6KnrKw4JmZ^bs5nIF5z$@(wk3x;4g2K=Oa!f^&<5`Y9q zBjHx*&*23&t3e)`iMYI~RH{IiFCIXXe)F*h6mlf~{i5Rhu{9!B3?I^& zJmWLV*D;GTK&bcaE)6J^2W{QF_R|DBr=;N&j8PP1uXq8k+;TCIA+?jW?;!U@W2Y}4 zn*@uSZWA&XotS^Ms^7oK$+XNr=gyr(g92R;ZWujxhRBU8KLgIZ+X#Vc959%lAJHYh zSX#y*?!K*&IW5r71vRfE+thtryH)je0hH8ojsM9V%xlHKZhlh=K=>D?sG*w9t{Xcd zWAw%xl=>!|&U>#`kMM!v%9j0jpGHdD?x@L@P(#+v%DJ zEX>&VnYTUt7j%pwDClvO$t>t2Rmy!I-PUb}AIeZM5rwDgOCb1$4!^>;l@VIhL%vqD zL0AMq$a@fCcpyaRr(Q+XQhMFQODQX`L%IA`>oGs!pbsT5%pd&_w(!w-eF06-Rg@%uRAH|+*(kb&pFe&Wv|#|f%;v?;tE9Hec#R+|zK9rEa} zMp9(q1;>Cf_WP$$xGt!)+w=!RexxW5{hmJBLlFIoHEN5C*;Wnk5e45uU$WnWJ9GIGEWMDbj%f>(4?y4tN)B zHNDZj);z$HIDtBny!%yqmpx{f*aGCigq62T>N$TK3ZHTHuHJK<0>%$5#QBiTB`9_0 zC*eU%Qx>ykXeQSPDm2z!liDCd`~6A-MXCN0{Hj+Fw3zhCI<$qT7JceMzvoJ$e-%AJ zejg|>2#`17x4z%t8w>IJT3iq|+T|h;ErDD>e#$vJhh3rDMYb=a4U7v+-ESAa4v=FQ z5dP@h`b)3aXV|8MsL}j3!1E6G3WH$j5ba5P-JCM5;L3M!F}eB)4~X zSX3dymd!lR>d$r@zvny)-buxtlqnE7<+y;S-WphnLIiv?{G)!pX65ptgD2B3Fnjj3 zT+Mdq5B`NfX7?}zNLy=Gax0MmamW+oJ5xjD$BhHlx%V_-^(kptx-nHlftp(uTFjro z0Kj%9Fn7AZ)Vp9>t|y{56nT+ZEhB=LFDwUg$}dl|AschInA| zoz?&ezXIk?6j5Ml%=1$@;tQPM3+TFkKs1)0cta$SM)x=%RR;vOL6q?U41(cO0l1hI zhw%z@eD*a!sq%cDhbgJxDwHM5>+HP+GX?Zg^1{Bpy4!AZf@ELwGi{7WTd-(E@R(C# zis}6|edz9`k`3-7)9fYWHpur!x^>lXx?BMs;r)7EB;=SsR72{51G&;-IsoA^djlbc z8I%vnN!jniCog^2q|ibrWlVqo^^ygKmwHlM=>#y{Pm^uGY$C)DWiIaLRHS`!?L15y zDCszZ_ul9aP*l-$3Mq{jH#xBH4l+s&8>&3kV>j7HJo|vY1axd#i%Dmz6Rq%ZTPc|1 z69n2izdM>!NQDNs6&<~qI?n{j0i2)I7)|Rtt16*rP&iSheTG5AcqY_Q8JRfGS?u*A zSw^(?C1Wb>Edpevi#8cZeg)#2^w&4UlzN{I!?yV&3GYehM8kzpK$`&!wJxP239-@D z)$Q)uXn_EJj~F}t)v4>}$-0{zRG%;2^vjd{;9S@)?gj55jy3{Pm89TEco#Vg+K^VaKp&=gdOiTFp@I8HzceKN0br=MY6U5=GJMW?QH@THHQ z)VG5^ST&!jI&;Q*s<1EgR-M;MeC1@xodl$H*i^Tv7*MNi|7%=-?E-U4Xz~NtrigcY zehY4zL0G+MQ|I-r&H1gAo8OuRDClIU=%ne?9r-wQy&>{pvyn64=x_whSMggmnR`s< zDG}VtAUe?n;LpdMzm=IB7d!bkt^6q2{$h@;@ zv^gwHb;j#an3jSYW+sauG=1kficN0=hYrii=p=8y7!8s%>yDEk82RdnEG;$ zX$>17Iy`M_&j|Z(iyM1*KOh^TUgInt!Ovw^rtbC}|GKEw%(3gu$J;ZmwpT|g^hi*T}7dSt1iNgo?Y?&4yumG+84jK9m6Y&_1?ff|K)Rjt^ z%)osgLLl?*w>fR20xudO`B8zvp~Uo9Ye8 zw#LsMu;nJd8ipTWEkVL>R7!$evb%Q3Vp7d+u!hH`hG}jR@bMF@gqRpuK_K=iV;(!Z z5c$#H)bC7OGFd@NRS-bH2u!FgcCLOm*U?(PZIAg1Lqxk!R|b(x?0B(U$SUVY zn&9Sx<~fKXN1%OW!N=Pb;_dSsNoIBbgr;qa#q`^>ZspGB4V{#ez@%e;08C%GbY-rL zQ&WZD4tWQe6c7RQ0@oiftFr`|nIh%8$<|AKaV377o{z2{lEyj(h@1fX<%>2+u!iKvqnG~a@DQXYd{^Q(`&-D5SKia5kn(f?SeuKCg zz{L`0p;nsqamNCSAuRyDm}HQ}^v9-Dn2?^+BgS3LZG#T8L~f~QNdvisj(xuz?~bzA zL@?ZdyL`iJP5KR%H>b}Ae|?ZD+PHk|Sj`RWA5!1~T7@wg1AGch3(U(MM#YS@4|t>*7_v|b8-XA7#u3%Vgu z|61SrOZ+T&%`WAyk`j%Ix*3Xy`%Z}3-IF5+dElVkz<#?0di2N zHQO^KDPI!wE~=K|8!``IseUGx$a30l#P7sR#fgFhP77_}Spm4k7V+^ba&z#4)ODn< z16g`me#SYsSCk-g4CuJlgwXt2vcy1><%V6H3w)b#%ZEm{g>zO_M zVm0yeR#W4`51#ZaM^s{@z;Z3C^!ka zHjM*tq;L9tt7NfV@31Vc!RJs#>g2z?pZ(h}edm1{Z2QA?qnUME_3YR0z_`;Sgzu}T z&c@_WvuHfM6=g`*53Su!l$(3LmFN0P8vP=CUjDLqV)I6HV=7~}0u@EzujFOr8!oqQ zvr|OOk}L8nKKm3DZNHxW?_h1ZNKmoq{*YO2K8AZQCp06Ms`e7e0vZDat3U$@&n^(kGM}GqWVCGtamKhP z(7HbN6KKW5D{|~0Id8fuwc>=Tq|(b;PI_x{;S4ODcevqVEr@M*`Fi%HD;@ehUvX?6r* zb*0QC(^(_J!gwzOlA^hD*jrSlRSl^v)G2~O$=CkV`DIPIzGqvwks1Yw+x34<< zZvW*&+Qn;p3i6Z(+C*=+;%Wm|^gIt35Zzv$iDuTu#cA<)FCu#NplKbhL7P)>+r+Np za5`@3&#)A}<#nE{zxd}v3^n+NC1uV%yWDsdb4kC#RU+*3-yl{D{ zW(IY?cf+xS^+yZlCg54sIRhzlux4_uRd4~}#0qeQ#Lnt*`UghpbBLlDA%sD2FxNxs$+Y&@8iO`w&`rujUpC`#_3zh%3M?3sNE{A9@b&$|oTZCUv!w&>#wwMJg zH|b^70V&!%1Q5|;AiHBtz6KtCpIjC7mT$k^h|y?vg*>Kd$A@zFA^&byV;KP&@|K;O zRvjLzHzKhZ$PY5@$zQ*lsX~%V2b;%nzy-C*ahg2xdo<(vCQX7@WtC;vZ^v=_ZQ)>< zc-wV-iUS2zHwPH5FTmbf^MJrqz6DI8U+Y$t(-ty$M|>_Q;*YkgZOR3Wnmn>>WkKfV zR?Ww?gzSB$pN}c6@Zz!jM8oqt%j{|q4G5Aer0)8Nl?2L=qf>x-Nfe< zwvR(yJ_iVmN2`CS|E%)hdwTVXU9hllz=ky)3rL517k&P_Iqx3}9WJzM#afR&riiN? zv}!1%>>}mX7Qvtes%`&X^WAAL{VG~`{(zeKoyGh_gim;4Ef{w{aq9FBga|UppwD>Q zLYBice;D$#PD`^0_hY_GvC*=?Tazo8h#$wYK*~XGwi$wp^Z<$4qSi|x&br)BExWFo zV15oymj<6d&@}FZooz;n?Oc$eWIB8vXf7F{y% z&~n-A*f&w6RB3geSAArrB!ySnx#RI9Y1i33*52Pv|4Orr& zP5stLncUn3jQgq+w9yW*#>{|(bw6*OJI$ibeeo?VdpUSvsoXRQ5QdV>46P)A73xyu zuORxnv-dan>i4obv}?LwAwBmuy(DU*^1wemG4}h=!YHhb5u+IO5xY{Hp{q{7ly2`( z7)1mMb4K=nVN#G6wAa=?dxx7=Nr%Uo1XS%evxN0|KWZq+cfu1uiOX+Skw9W~$G< z-x1BENmxv0JQtmpexC|=hhz`8;>>|g|3zxB1(!SiWKj96N37v}+FtxatM($j67#V@ zXH~a!+VT)sXMM3k72HMuke<4ubCKqW5Eb@e=wu+XRp2&T#EiF?;S_GYV3=78z{(;S5YobK%d!p@VgwLvYJ|^(Xy~?{2ye}xgM|H%Z~vP12P$4kQ_oEV03oe()1qwcHD~9e(f@yt(kRrXJV!vwLhhO8`(?1^v<&t3fE8WWKpu00E1)ali z`wD@sy8t6!{2*bMNK7LTQ!5+4^ew;H?;n7Ibs zz~I-fCod5+xV6f3zE8#7hu=W#J3+V5l)e;N=~|2)6Uz2}ARfl>b4n?oO5Ym#K~QHY zZQErj-+VVqKM#bls0RghG@I-RVf%8v3A7iIv;@FS!^Cj7vD#?2ZLE9hmq$VxnlTdO zTkKDkDx=qbH4;U;Rlb@9a%7r~l3HAwm}H146v;{O7tn0STVTsu!p$ptl7iBvmW5CE z^p*j8t=vN0kytyhlvig04dyMoaVZ9}FIG)>Uusoi9mcUwaFwus3`7;}y~0dir8s;= zKJbqCsv>;1VIUAn1Bzq6LYuB>+yCx~ZC=8sWs{Rskcyq&N@Q%vk5T&&OF>^ZOG1pF zgA~AP{;{~R@6;r3l zjp#1q@@!h_K%j&VFy8e#O&e~0Op8yK)p=?u+%k%IO|-~}d{)W~@t-n(1~(ENT3H4V zZFjnKNcf0TYk5fI6O-tT&CVR?Ttp>5X2QlX(~N8AHG`7 zLw&H_j*Bc?>6sBSiuf+Gg@-R!J7a}eI})e%S;TV)o&cZ~2h<>w?dP`U)sVX1^MecC zdX854cxdFqpo3qp?w*ysMb}y;K?VK!!B&`B?wNuJuil^8}c&#~Ik3run(~y2$tEBL{VD%0WJ9*d2}# z7x!5h7g9Sa!aI-nFsi!Xrs;0S7?m2g@`m`+{s9(ja)2_Su~Y$fD)cVv(u2H%aTxLd zLiPihucaU+>AuKJKm4L86z7BDFyJn)YI9;dQa}Q*=EEoZD0%UOA`t;P%vntG78m?M zk-r(r?iI{GJERu}aby`>!w_ZSN=zfy49R3dQY^OEF!u#aUybijHQM-+DOP)Ogas&~ z;U@r)^4qZ%RW#aohv{kxF+6F#2CMW|HXUsPIw|b=ZPt+pghUwh;}$>~4@0me-Dtk> z_m5j4QBH5h<%fQ4ba_8ZR_1H#H9HQ1HedX$P4-QNpL=w65NK$M`{jLZH>BCPXJS&# zxtOpfZuntV3gH;#kI@81y1oV7WK7QhX}G+0ZF(qO+Y?NU#;KV${WrYj*Bb<0vQGQ% zY)*r03lsi6gza;hm6dqjoyb+qs}2BRr$RX2pnOU=V3WrcqfCW0HyDrtYjKUBn@5bo z9}h}CUFuopKz|P8s2YRP8t5!TpyYLsZQB*}+QP!=2!wf!O0`>213mc5_(SpOIgHHU zWja0C@NfJ9=(X;m_*Ju$sHnf-2h*7ROrU6^r0_=T(MatV-U3_}2ZvBxf6{hHLKON9 zk2aNckudW!nk9~Sda!#FL`uIa3Q3powL5WytnJ@6~9k1R~&lkD&dy0yi%Bm#6 zPk^9_qLG#uYRYv2a9zi^Ez9Gl9Lw*QvKJW*F@Vwq05?F$zaKz7b2ih0*dp9H(g$Rv zY#Kgsb&$V>^&xQ>lj1~kz)sINM;(cQ)tCcp( zoTt`vfuC<-B{1cFAGfF%DdS3nAz*43n~ zYX-6NpU=HqNt8x83JRWJxJGFlCp-^WusumeJgq_agbtEqydQPH#KCg_pHx|m!DX=l z02N(I=Br34WBs(a0VQA)q{_J5CCrnvX`g$B%DAxiUu42$tJSs9!IH%*jWIi5Ob(z| zO5c?5knl^csJ=T62fJWt2dL@CXNk2;k?!UiTm_dG$9)W-w9QK*XR=M|FN%#F4N`w1 z)_z+NqijC?r1?7G5H;3FYMQrH8XZS?r+i`zQrl+&o|Ad>xxt=SLIioBLHD8xd|4uF`t_askdYsrS(i9v4qC}urqXZS_QBM7NaB(b8{iKMe!;{2GG@b(cI-5J-=-< zEd$D)w%*@%&7^N-Ndc<`M&0+Tf(ho@$q9MSXFzXBx?*th1DJZ%7bsZavfa}l;9tX& zEBCDuple4|$ioJ52)rLl4-QKtZ$HIC=6PK%BAGdT^PZi*Ie+|ej64O9`Mje=Abeq+ z=K4DE(gxXzSfdUWysj9k7Md0S9E8x zfQHn>K*F2$PKg#>*zF!>^+)^#Y?`KNb0(^X_6EjwD=+T}#FZK@p~6?O0%@kMrSJ{! zerxw@sFw(bW1H$diyvxzb?>k5^;*O2=3NscsL?9enOYGoMP@D!m^Prf3Xr4Gg7m73 zvN64|fR805=m3H`17G}A zlc|tAm$Ks!kU+!;tTcDW{lT~7*eF6ufCK>@Kmr5Mh{4o+o^RZ9GfEyI4KA`sqo>v5RQ7%-vH&(GeldA^wz~63Z^XZ47SlnPgeFb_>drn7$p~eL4&xJW|}N7OxxUTN|s?k8y-mWnG0dj zyVQV!_jhz6nm2iE>6p!opBlTV{Un^~Wq(iOt5Y94!M@K2z|DrMiyiJ^-o@kPdnG0G5joML$61v7%S;^Ry(IShV3U`K{eE3HOClDE>EoZ-q1 zPQRAmmbUKK?NY@N0CrUMphIlcz1c`t>r1(J{RmC9y z4c#QH7)7TwcO7Dat}D$7!73X$fp$i2rG-!Tt~XX8N*Z^}41dM(ykm=O42*AOHkHh| z084K^QZ$6(!bx>cciMa*Jxcu*TVFo|uhH{9YjvUrSTm}W%uXx3Y%j-pk$3Pk1+`O3zrtp-BQIJDx)Jnn%Ki4W++6wim2<_OL1<#3^F~| z$6@2ZWhMpJ*E&fk^SV9`+Mz6}cYJQ0WX$hUir=^ze2)|B(Vw1;WJp!;H^^SM-S{$% za05E$zwR?=kN;k57F3t1IrW{%zs<4#Ek&|M-$0tDK=qt29|-1G<7_(XSMhoqO)5BS1*OE1^6LsJCL?3Brk2XBlEVf;dy;}H3T4rEwDN1TBSs=$ z@tichl~meq-_80jeHtdyhhu3bbnVk3D==%G&&zO#?Su=uXQ--4;(j+tM8lANZ#^ay;LQA!QtyYwFz z%(+$nKEimTO}x`P8%GlNSuIpTD9givU1AT}<~uJTN2hVc9h{*ZOhW^72v`Qj{%Pdjo8|4rvnS_ZX-obZrte5&cgGT3okfi>zdm*;;9L==?nTKZ zCV|Hc;9K_o+^*-u!1r@*enI78fRLA4&Q+0PbKB~rTF)aEESV(Xij^^P-&iX+LapiV zoO`x`46A4lWoH*agqA{n)PFL!0yW+I!i=g~!RxRmknE1B_m=l#90!N%KKa&^uM^~Cs=)TKzbz;(QzT51NDS1Urvohz0@7B>q7dnI z?E-eCy@GPM!0pD2)Y;tcxBIwFK`q4~z4CtH#1@O_pb_sEPewT@->R;fJK6WGvR%!@-bB6P}%6S(d~ocN>RA5(%t~50;PEPuwZieWX7g= zHDTdSWDVIsG#V-W zr6D(#I2Ki=pj7fK0QI(-1ISZq=4M3i3m_=`)d9OZ;U#AqPu-OP=Y@gsL4Do?XklC3 zIXyD1JOld55a%50suEAGPrz>g-Pvi^_ae?A8S|vsn%^03*bB$^GJ9Ycv~<`wT4!~L zZ&04?6`ctO{!QysJqrRc;;~sJVU;6V?w;qC1d?Ht4fINqbkN>Z$r1D>7}d^<5<=2b zRo&u!Gtfb}?~c36vxI1|*ojiQrSGXzoERwOA=drp?37Qx)F=emyc{Ji%Zh*RsjiK{ ze2pJv(e}epFYx-ZEnzF%>jdhIU}tT_^2(YiPUv1D+lq~ksgsaXq>kv{pyBm0wq~Rt zS_f`&5D8}&3;75OQ05k#%}&{3ZZDCXnttzkO^e;&YG)tA$xNv0lE}(2Hxi7yV2T0A z`pb3Wohl*#3gRBEKymYe2;jjASGcWe1WyG-m9>!7_j_8?Q(#~G?=?v9Gfwkv;=@xM z?rfjz1#Do}Tq^kt@1CMj$Bx%u3_zO;7I-Qy8XaW0gOxrMA%dPB1B}}5w;yf@gWmT= z)1QQ<^dEdFfMC9O4U9IL0`8d~nF}fcf+0tkz017PryL-zd6i?zsuZWpQH=#Tenlya zH?~Y1T<7Tl#bUj6x*~M_tJ(O;?)%Z)5f2zya44Wp{S9%Uaf_pePPkqa+d3&lQ2-6O zz*D{T%w;C=8cjc4U(Q%UQRMBts7zR27B!!A9!A7&RPa+nbo|X2``9q5(u)gb56Z@s zf%Af5OlfIv-gtm6D?w_{;v^cIbAX4CToyp;J@*L94Uo$N-e0F#22eExPdTz^zSz%jcw-f-9mZ0e?!$ zz}uX)b|(V?gRjXeu>Rbd&UtSi1u+6B55isXKI^cgVfK#OeVkiJt4kZH{=FYaY+Obvn{Y``EDP zUnD|DQ&bkX*Pzr(w`kHp*;uvB7U-XZ&)g00ie;oPw2AUiT-z_&d3ip5O?1|j{?|2J zsR?bX4=nH#59rIx4=yN5YhHHpS@L3C0XXE2NY?`^oMb2_m_mMlUC2V{#*!5EJVJk6 zpg(>U_pjyJm*o9mjxqaaN(WM`tSC|o(z}xSo*vy$9x%Ob3U21y#_8c~Rm0Q?a<`)p zlw=V31(e~-Z|;74!~~0-BM(|a6gYZ(B7oa!{fPo3@^hmkZWjprl;xfH9t?dV0!?r{ zHb+m&J5ZcPGzWflC|`n56o91QKki{+jY($p6d|?*bnfm_Zxpb`Z5Ta-bG=pF+8yp8 zQOpMIcBJ}}*i!o#0W0TT8H)rjy=4J+t((`zJ()S+oJ2v8f^IO4?`u`n+@ipDo&kd{ z8&KW9dgUTXT9)WzmpWX@G7u_Zue`j91JP#-qL0RTYeA7=FOZ`EJ=rtHhT1Rar3WeN z;j`bt9s+N8rKSQ$ky55iFPK$L`fW3SK8@=|)su|Fw_Iw{-1`11I5EdC@KzW0i*XjN`N8>l-w3TdgnxfVNER^ zJ1Yyq;FyI0hyw-$8?z%m10)ggnbA2Pqe=esQzK4&ktZYMdJGJjR;GGv51WM*?DxozL06FlJ-;%;4BeKtsa; zM@I?nCL5Ol&kRKX_eiEz@GPxZik&NcT6_d}u=hGda;8^g`!0#=(4qRGDbM7qA_w)INI(&jqDI6RvmsW*Gr_rB-8f4>%L50ut4NRrXf2+#L z3qmX?>pw?c)CE*kG{dVqm@b=cfHSy*Rg&2lhy_nL`hAy+dW(Ur$hrB`XwAmxwYkFY zG}S?dv9?N7VV}1<^!AVW1|=CF*~D&sJ!h4vW9J+N1h6zrvNeW&o>PaOh5-w%GT)mo zR<;4t77j%W{kL z0dL3>eX}PbFdx21-rW)VVtQOZ!0e~<5?v^O`jB6o8mSYM4HgbZx^|Cj0Rghc7~&M? zT6TEog3OlNa#>y#m<3qDT_ohNd+bU^q5YMR#1Tm(z1R;EwR#KVV4d~It7u!$i?B;# z`QsgBFDqzU2CxMx0cjK^Y&iblc$Zl|xx?+ZG*8;{To~3?NazVSDJGcNE~Y~=X8)D8 z^jTw=v~6y;Dq9(=qgns{ub{>hrZ=_hcR|T_54)h~#=4@iFOWJxgoT5U!5uF7hkSQw zn~&hA3P8b<&3A#<@?Wm# zx+`QKGn`jX2L_)8o_w63V{W|H`V&7YYLEw(oCQ)&sL1;%1OZA6L(jGmuwu+QTqmHQ3Os_KCm1h!7P zwoY_K_k1-iKBfu~vgZ_Rw0H8N(+&UXMmbAi)~tTpqH_O3j&N)bn!?V4-RcVC;h{OFc3cs|s15 zn*$*;U5M{Ub2)xvgZ}KAn&Njs?D9fZC&0B7os$$k(Wk?kl`f-`GT*i{P3+CsKPX0f z)*?81+yJe2*1zeSvt$dpD1KOu!^JE`0E2~Ginu5X1{Bi?36w1ERVOnP8EuTiShTP5 zuEGO6al7k@8VG!CKl?ZXUKY((XpB3d!AWWT`&1Xj#S^AM$qWaFQq*UlVNURrDzOco zPO496P@w^VnCV;0rbj6}aL|^l*0!F_Y6>m|OgpXt5up8R2x<{hq`XzaN1VX9`{0l(I<%I;i%t(MMf{n+iB8!9x#LA1Y5vnol)5e6P)@6lJ zgn$Yi><#e-7z#KkyV7|Ydsg;zmoKLU(vGqCDUyZe3m66lbh6n)9G9Yh&r@_jkt1A_ zm&UJ`*5CKj@1J}C!PZmUGd!BCDw`D{o8`GnITpDeUG{#T@)r)XCo;B+B=SCb`Z^x! zpvIuoN5k)IaI4vVeloMV=pKFW4)z-wZkC_SEq;Or%|#%Xs(yq7A1ndyXro}R%K}hN zNW^3gRrT$a)n$6~hvFvs^KK+cC3>p{i5SW-qZ>mjE>1g;u-RwgDH{xQFdlsCD$I}f z=*^4UstnaY%*QW3Z9`7$W%C#JAlFE%)$|xni7L-No$Y`0X z)GaATV+1^oBdr7hN;mkrFUxWo83jLbPm+a)B#CvL*SsHuWdZ5!QxpYR5cHzt$J$3# zh%pIV(}GSP2?V9cc7!n{rDW3HF{7 z-G8bfN0JNTbTOYB`qMPhkZo z#@*A>%?dj0iqeDRg~y1c;C(WGiQ;wghU27&F6PM8^=H{)!N z5=s4tPK{tqjApXi#(&Ae~{a$iVqTw%kOz>gfV6jE4kr_Zg8ANMxB1iSbQ9-EMb_!=;EVz*??rq%{0Za&e zP;A2G`(Di$(9SQpJU29+M$ohy`!T-&u~Z+W6Jl)`l!A)HD9{hEDY3DZKLHJ>H&cT6 zW?HhX>GUmkexxzeI-RK(k@V-qqRa}{Cz{-|%I2^@)h6|_io1{oO7#2M)ZPZrP%Zkb zv5kND_n1Yh$1|)JS>oZZx){`H#~JsRTJ7S^E4BJ&UU%Lq1r`kY3-l-?e5{mAf*sek zbe`P86|IBW#&3XsKuuE)kt0J1ZG}vJc~55yS^=)0eD4tmg3|=t6$h)T!@)R<(d4NZ2jjC6@nBp;UH`rN+|ru;l-f5MXj((||l5>8H@{norc z6~lMb!hTFQ8kc(sJ%chOwckA2 zldPD^=Z;%7k1hMiyQK#K#B>r#&|XM(@ax;**?~`?qKuQ;J@Bo`r^U1az%d%#g%tZj zL8S^+*URCR53K8GI2})hKRaBNWwdtM_l(;UhUj+UVK4#GVH49mW|2M@_aoxYZ`V** zrNASicuH|uzgREEpCzz=-GSayNBI2)R1JjAO3p8$e57A_t4<6= z-f5gr52kGd`j{_uum#B1QhL)yc?d8O8I8nb;;F=~L58{E^C^`*+n*gu! z4iG-2V^iBsNsPB0Xa7r!Cw}iC-fDvSLF(beakv6yk@GrRV^>|C%v)}Pnj71Nk@*;) z!jP61ojEsFG*k%~Ps>GV)UdU-1rIhrNES&o;iHb!!kr7*%4<~S@E}h0Lv{MAHIe-r3>@K z{E#?D0_rgG*pYilns(eaxfOG%aOLcNP^7E;AQ2Ub&k}%PNLgwr)A05Jm$ci|P901kG*f6K=8&$n8uqdsQ@o~~|aN4C7=ll}t_uA{P!>zx9>+>xwzDTd6sTr3F zMkg?e+n`BIJzxCfGQji5Fsrv?vn#f%t@|)ZR$6jzHs}v=D97QG^TADAPDCw6{(asg z^>fBq-Rt=f0)PtP8Hvy230tiSI@5K5yN?YgRR>ew4h+Z?UG4=SXy`Zg=dOt;fwOm` zGrzaQ^7eL0hARd16TgL0un;DKzKfQZlJBS;rTuSas{&CCS2)pP9}(WAqQP=-wR00yvpg% z4R+7n0zevn1hR?kvmA0)*r<-;fllH0ds{k^q1Md(R+bP{6|Y1&Yn9jy=&5_1>iNnG ziLZ09o(aQzXQuw+d7^ph@hGdF1gRS6MgxF-RxSKX)dyH2n){`R%?k?C4P5Kv+}}q$ z28LAV>8CanDx#_KM7Gg!ex{+>w-g0?9CV++3_Ha@gS6d#7l>SV-e?*0wezbik(O%& zzZhuz!h!+Yp}YwSB)3!>o&{BX-;Z{Zn=rIZq|=3}>zEMVDj-)O1cpm=^nQZvA@L-l ztJ0`mvr}k5&q(sJUGR%L*P{#9lMt5P&Gk8ed{dCmj=(e~2wdbW6(Jek53n1fuoEI4 zY<|HlX24Mqut(C1pH~;$N!Ue92m(2p`mx1#{4i5%stBilHF|Wk=_x{bU#YsHFlSzVrSP{H>CO~GqR|!PV zNmCqhD8tR7`8w8i_Vtr56CVI7&T#}c$o6OnR|Vhu%@6DRE05%BG;Zd(H)XLuu$N!a zHhjz1KK39IiPI)~Y_wDuXb3bU1^^R863$^3Wfdde(RzPGbUAMlu{z4~OF}*`fYw0_ z#j}z;T^v{70j}QXda+fR8nr<-*Y|6=-lZFKMF69>-gLJ!)-U_%Y*a-zMzF(=5Ay%h;B3sh&K7>dYif-l?R0n(eG(h z`(iX#PeT`spq`(f&<^VJR>lAY2sHLf2})3T!*i#!t^t`zpRGeffQHGyLOsXfSrw&o zm#H!X^;s7VrXJ!8qD;SP<~QgzV?~4qrBkO@F@jJW>5;|I|MYX`ZDT}iOhcuvAdhSn z>?Ughvjvpkn*(3i9V9W>sTqk_`6nY{9b zMAvFE`0oSYH>F$ssXRx;2H^#W1OVT)p)U2gFr)Tjjk_%G`y|T9+X|K6BCh>?6i`r@ zuByHGmhfMhcVQJ61c0{meuYAM$eDEBSyD)Az{8{H`zTN;O z=X4_3$5~G3k8rKqXaLk;_?oj|PqVXYJ9h`?QcE-QX}jz;!OS|>haW)ca?_Rq)95v7 zeBNFhufE<*{EkS?LoWI6VQRW=$n%;up%(yN_4C!<&%lB^NoB1kj`INvGmPu>f$IqA zaB?t00(wbq!q!3x}kU2x7jgDb;t4DuO-XibzVcH6QrD0;22qTsa} zM!f{dAj^0NKK1+8P?ez8f{B-;`vxe*zcm0_z+%Q$POHMA8bMFy(!BaxN>q!CCSTgJ zb{VSUfC!nwIQ&32sG_c06n#De#&S5s-rL8f)W6bP3I)-n z@tjOMZ=F7dO!#2HKpDli75e~123Y5v9s^*i;ZdL(wUiA~C(n#s{J#$*(zbnJ08g7M ze}+upL^sbG0C3PXEKJ~41&x$n6<&S3NyRb*K$ie^L8_6MeOH1%90UME5!;)JV!R)@ z!jz8B6R%`J&8f%5g0w_9YQsJh<|g`M01{!)4}E@N*AdN7VI!2j)Ji7Ypz6 zVaOVbi(1gnkT|SX^F4R!G3|FWSmp2pSlSI z&*v+jnLzyX%deHkl}$76b%bkGTx;%(q1Z~Rfkp; zESP}jktZWz-5At($RrqF7BT#@=V|6Sy;LGzUI58rRD)AJP2iAX4-XQ1n&F3dBuvr>^50?~p2B zuR1=?aeUg}8ZB{rJ*tZe%+3F-W}@?{wE771FC4can+VGfOYU(L+xPdbytI|R&qB-M zFR47Oxw&s?jIk*=U$2{bq^eVwmk~Nm^6iU|8W+gls(!c5R13*%n>rtNUaNu=PqD;l@0LHlD{D55I&cEf zKANN&=Z64Xfr|1`KO@`5d0H6syeK0E{|P|)ci;S5n*hqAt*R@yObme{twv5fNq8`X ziW9hf#Z`B1cmRDDpQPgT6QAYU2RobwncUKWa!ZRrZjl&`RvD$({{k&6-SPVdBy`Pf z73U;YH1J9R$gAmI>!1D=EtrIYui6<9H;tZxcGrP0H+4xrUew-sr}GX1&{+_FjTuuq z%d1@tGz`~f-v>hdG=`@M^f}rq4v#vWA7>>D^btciSD$%brTRe#H%`!{?NzzNd^7Pf z(tG}ReBjZDc%J(pn!ZPXS(Oxo9f9`$1h8;p`|0d?KO9Jt?<9ME{^B|Adge!pUCSN= zy*X20bH1AXd7)=c;V^Vylgfa>5p0H-+bR9iwI0*)6969LWJ?f*kBBS-t*Zult^UfB zE}-;?{*tNF?DS;qY+U_L4ZunK5AQhCLz)ap0GKQJdsD=t{Din|vpK2BQx1;LzFYXyEb!U_ua7TWRO`g*(M3V;l-&nX0SyIu_1b(NjiTN&OR z>R0T9;|m~*nDTJx5x_*j&mEU$xXu>{ZyB} zo1^1Qu*qkqG-qB>@Uq#h4t&fy6w(SG6U9OYGndreP3IIjxg>;eBwt&IFCjka`cu7M zP?=`pM;L9zzK#DM)@quShr9r=>7ttm`f+iAV!X=CU11{T1+>nUJMR}ZA9^kexH)#o z>s^iaB?I?$gr4{_0C#F(*bDZZ7DUAE>(W#@;76n7P3C0CziO>+HANtxO`zcTm$;-s zlnTKBl8Vl$S3*Y_#^Aq3-ye~fcMW>;zV!}rX5yl-RTm|+PKC$cLjr#ks~Im~Ccv=(G)!SYH20UbW(KUOn+(^TvG9Xvr17q-Sj+-h<8H*Bj#ZWWiiP zL2Ou*?quX6;tG!ASVj1gp0l)NTw}cTY9;& zDlXtqNRNDsajEy;7hf0t-`j#TdASXJE(H-mzni11VO6ukan6v*8UMH+uX+Ymi&>Cy zW4b39Dg_#hfKsjLXSTUr6~$$r>&8LAv(0L(1NfxBPk9uG{_%dc+EQLfs)pG}P za}FsN1A)_ZtInIiyOVg|hYU+$az$(lCt`3ga%Jp$ zp?SY5Or{0M5Y)641%D$|pJi*n>m3S!oH;-I042#AG+oa=c$V2%mOQ@qHUp&zgX=#{C<)^|pTt-h-w%7H zS|D*{s5@;tfmVi+fxQmti(h{6LDqAsNYGhsUn#V#>a*8Ut!fh@WN}Cy)$BH(bpRWA zMNs@NO1$HjfY(}H+GfQs?%-_D;)0^?da$rF4s>?r;NS<3p0g3!u_+x(DN{7j7Kp&e zWNyYIh!u&NdWsCp7*Bw;(*rncU6keZRYe5jhs+0a+!|1e*a2`zl&xNtdj(sTwPlNR z0L5fXPWgrN27@ccJ{l7?GEUGZ#M>_Z8eQn2b|2`Q>|Ik}w(# zb$I6}c562d?S#%V<^J4V0fL{xMY>f~N#g!~1JK9&_4q!zGXoIuicLNg`O^DMO$u00 zprYZMe9uCQ(e#2nK&csgRq61wEqO-JZ~V>5^|NOK3Ib#~lsKP^q*`q7O~cs|xILFf zcnZp$(>o|`c1k%InjOE=5=XZK>3v_pr|TZPa3U^ z=*JkGY8#yi%s2=E$$4V^knMwP2{dNt zHcFJtCEx+{2Oxo5c)>KAmSCx~+600xX8mC1`^~j81v@w3A9r&0Ln<2|dZ)M3nQP=p znP&eD0`M}xfF2%=vfi2Hd}(Ae1ysCyL}-CtW9VXNGrA2mxh}a@wyaq_dm&ib!fhwd zh$v?2B_gRI#XGRRF2*h@I|&Q_EOopJC4^NvJ%QQjWwTq;84OkuHej6W)3c2I8os9> zqYwK|cEALR-@B+TBHdor8|C*0Puk-3rU49%j#pfQcJS1UvxUw`6&L=qucrHZ0_6&J z&4pAtN2qnxVpwRyNdxzNB^(_r2_!va*UkiXP7HhE;d1~XTLEqDi z1Kd&17j70X9#nLTy6y>Zsl4?#gMR|id)_X0-s?eh>l2s{2OB4p_}a)&pf-R=t4sE* z#&=gHudZ~JF1}}_eGr^|APjqe80=|c3QlKM5+|I%oP zx4!C(iY$Nrz(+aZB9uv;0~T#o4mR2 zHMWBA6A;xfht_x28!8sjhcHRTKF@UZ`*D2dZ#2w*j%ruE5&O$CiC*R$;H&n_WM66d z^ujaB><`VOlD@{wq@^_T15NcSlzq`WxA~qK_j1c$+6BbglY$|6tQE#Z!ai8FjuPrA zpsj=L9AHeLr{rI-le$6v297*SP#s)ZZqk~o9&LW<~d@Gp}p zplHnuEncV#;de>(oEJ)8>=}V?t#NqS+_cN|Mt7u%-@`G;zt1M;yTn1W&pF?=fA7nb zr3?&`UJ;X1dK7?W;MG=4WkS9g+Lx&sJP_Te0c~U_Z})Rw)MVS$3k0h8hdSl)-k-=S z`Ul3IBHiR6j}Kln?jQKPF5oY}6#=3ihx-yDPQW|mO1ZL!AquF`bZJqc9|=gEvpX_` z2=`}dV6F>W9E%(JQ;Y4>g*1xSEQ8;)!QI2<9?GHO`rqTZBzXn>=7ngb#aYu%3`L^V zkn^d1|K(X8=AG!9O+PP1RJ#kgp>2V=T>L1ZceZCnQy+fGr#RU z{1EkU{%)@;8b+n=?zJld!-&t)pOJ4&S_C=ElQw?&&3a2!F_>flRJl5kkV;4iyvbL| zd+G6XcPyoopRp8xd(RKMGxW9~jxOIBiw_aYc*iQ)wvamL$FXV|3xbyk1QHA7hbty{ z5#z621D?87;hKuPA^?ZE?&HZbSEmn<%dh+kCm!EYF*Uv_0UH)n@vj2dii@~{ad{Qu z%sNgRc6{R{shzM@JOi^QMpG<{8seLOMg;r&Ntx&aXEg>PzyeA49uy4}FJC<8%O_R& z*0(!ldyi;bo7Mtew6q6caj(*5*t$VN>8%ZZt-8Ly$X@^# z7Ue9d_9kDq1BPIUJ8e!N&gJx9uffN$s*-h63dxYE)e#&8;M4S@j}E=qKy|=kNf`13 z3u>j|szqqmvKcoVfne62CwV<@RpojW!WqqR++D-BfK1R)iMgV&!mYI8KvL?q&gvf` z`~YZpI=KC+ZW640xAp=NcnvhY$|J%rmr5w}b&{rFpNh3yC$8Q%yQ3vI%SZuX4fV6- zn$btP`McP}gobhlI?enRSn~M0M`NX^lMNB%rHWJoDmLME0$76jLVn8(4K$aZ-;LqU zEH9#6@adH?F=ogaN=MkvmvS+ua9GRtWi6}tZ3kd$duT|fW_W7R z;Jw=E&3#S+*5%ge2u23W;~F7p@~s;j1tBCk*|T4FpW?%?-Fy5Bimr$Kr~#CuEon$H z*=ARU^iYD9B2RE6Sd{kcR#3}ZnB&1k{5}$0t`S!U*Q`8wIX9hj8_PB9? z`Zh9&r6fKi$UOTBDitna+vVTOX_OdA^P5C-3;#Z!((V;UaMw#=r>c}%%G3KlmI2<{ zV2i+g^CscbbP|butFQV@H(;o*&qiMZ5TqN(Y?o}^t9tj{jkLPX(gnX?@>lFU4BI1K zvLc`m3FJ86HKer*jSp9#f?3`?Y{UR2tHPbz=g2i?bnbj2(-hFHdY*Mx04{><_p|vr zl)Ll83(tW$lC~067?KYdje?&*ceyjI#;Gl#KZn$O1-(U))zLrvp78wrRBF^-C*ti`KG4506x>}VQmVg<>w2VNxp}NvkObEnS{wlDUDpTnBk?ug#*5N zia@p6;|FNrMPM8Ot~1crMFf(uf;33a`r$kIejjnL@GR}Ua!Kr=cU3)*X+GJGV%;{% zRna*zkP8D*HP=Hpsit^HFyp`#ouB^QmL)_Lku->gqKM9a76j~p7F=`OeE9E~%Gn0# zi!^VOH-8q$TZ!BvOd4xZ>>M?cumSQ-h<@0h1xE<%H-aO_1eh#jq8|{DrEZOuiyUsS z{Gtb&j7^}mU%ABY1=T(GI?tDoOzYRK5)mX``ri-LL}?0AxetE&oDwWVmPhzH3n|me zdL+xLE<-pcL4Lgm&NbQM@{=vkh7{SuSDU|`s80}L zX4KXJ!#4f0Wb*GfZCBiWi-v`?#JOlL)hY$VZ95>m$Z?L59gaZ$22!;Y)gmLNJZyiq zlp+TsUzkjUUUrC=E1nPh^sr#T-<0IV!~Ds^)8RmJjDfsSq_xTPNxEQ_{rIB$rZ8rV zKxbeb7$N^Gk==@MsR1;Wc zz#DPiNHWJp=u`00z7+4muL~QqA5xFEFUKLC{i-HLTN{+tg_z;wgj*cH zk~Y`b&mD`vd49*54&vlO0>;Ni5BaLdqS&?Em$T);>RdBbb`lHrHmJ6)OjaDT1LFP8rIXU(9cnKLTGsBtS zPq}&*NoQ`X^Ij2eaR@r7=vT0X3W5)W#i)sUf_s6r?q|Gh06S0BHu;ztgHncH#+Hqs z2f)(VV82rPUADRH+33K&T;rbuu;XQfTBID%?!dW^8>C_5;i45K*_(_t_C=HFbPNwzDPSMWY$Onsi=2ZkRu14^BGk#I-xGE~bh;wxU`W zrh8_hpW}-zUwF0r+jfFsrDn%$s1}K#{rrGkbfR{PQNw2Y014qYf)ssu-y&M$Q8cYkwSgwRK*CGDhi$(zb=+RD`_;w^bL$hE)kw{(|%OeLQ8hL|3Jq3In3Z4UM)CatF* zXums}d0=-bbCsD=jXHaXrXhnzf+M^KxHZ!EMknzE{hfCe1$^`y3&{xKwzl`#@i&c2#5vCV(dGR;;8E|SbtfM(P$b`(db#j{`G(ZmR ze+d~hurV};#HUUL6>J0e;3_bmcfJXOsbjDy+Dd1eD<%VezrYW{+tT*tJDoc`>2Z%^ z^su3Ym)Tz&)Tjl#O<0@${?r_9E8(IxFie3{Lp@%nayDdakS?^IIxYtX z_&S=j;_ZimQ|0gbP0MQCL3uS95?^b!J|0;5w7?2?a9%&Vj6_Tx0;v@_DHm*iEv7|# zH#)g<=5Oe>jhR80906F(9TBMsq!u#0c`dX}28K=)lqO%Z-?peAsQJDrFgYY~C$4z? za}OVE?@MZ9K;`|RubxlEiu_GeMj1)=rBsR}zBQ^Q{0y{FrZY%Eegm^bUOqYW7=Jf? z^sM3|y>TNsI}p;_AoNOflHd+Z^aTC~F*=+>EqU{17!S^^%*M@9`k~vq!Qb%bB?DRU zIQEyXY(&7vI58`{RTQBu62(t+6yJ?*55h5CW5h~lyt*|uX}7llJ4Jv;kTEdC5DNy4?A*4zpZFWSAic>@+L#$8l4X4~k`DR-4djEJ*B5;}~ip&gl(Wmw0NSN^B ztX7&isn#YTDPct{b5XSx0{t1aYRp9Jm#oh0x^|4^wd(EG0>p6g`^{g*t=<8jkvRQ-biDfp6QJIqzDo*y3>4HY!j3Riod>Uh>g5nJgB+>J75#6*ubmv|c^QF5>YIS37c$$@6e0qCt zv$qkr!J!ici_M@g43ABuPgp^5pGT1tCv*F>`FGn@%3`&_rNFwksX7S#Ijiuan9~{G z?^SvNj+a$hS+T%)+*G=KB~bN^dB4Ny;tA%@v3FKEMBbe8+RiId>-mlk^AQ$I#{wXO z{n=^hp<4xcdAF=f|Zs%vXk2!(o6m>+1tO12d;f^<(OzC?0ANp(37k>nzx>Z=PcxUTJhe)s^n1)B0Jz zjf9hG6mhbh=wGREVW~EOI6JrfLw%#)154mMrYl(WrkCaQK=QE$%law&01S)6jeG0X zlu&NQmsD+rk;;($`1hyoSLnhlCJyF(*!|o)Q$|6cvgeUk;i}lptaXepFA>xa%>KTh zXYxPREqcGG$EQuy7K}zpP*h{N2glgK0y>ECz-J`O#KkDm8kO$k5a_gpQ|@DRZ13A} z6J26f{`)0eu;F_@F>0FZ*hNUItO+?&T6Diw6B(q_IyN;C33meB^G8pX-OtZjo&1^Kq&0 zErE0G1WWz74ewJf$8_#l@SR2=jDS2<{FVSej!lJqG~mWI>UyNU(gkd74*W|3Qc=`_ zslHvU_x5*3I{;mi8I0Nc{o4JYR61bOscQ2B4RGW3u&V7B-_u|)_NlU<+E5d_k57Ir z{QZkl6AtOZyMRM|d}hbdXXublm0I*C&$}Lng=R^LgTCN9529B+tbw(7KOKK!iq18* z@w-Qe{V(V!UzxD z=}p}kC&~x#h`sf7P<>rdWtD?#(|7=J@nb9OOmZKRJQXu^1SDGuS<;+F;FnF+t6676 zyxbi79@g8!zm3IEe0;HvaJgSCK9<^+-arTDA^h(#OAA;_mc!Kur>uA%VLrfLjHX{T zd=ao)FV0YChs~f0p5J6<K%fqC-RZ*a#HYTOkNjQ#j1iyXi1!E9oVa} zV^r6zBb4l%E#3zjDB-`hF5J(j*tu$B93ZCg`$?#f(9pYm#$x=~?)0ulgP&4UM~gJu z$P5XJ#29!$>fd=O{CJ(ZlV|*82XMe~46e9HkRnW&mUgt|fL;wLAz4t>W)R(ld~Cwr z+Ot(fak4!X=W9=Q0SWL7>zkt&@eU$x1QtP59(0 zJ>akb&Fq`K375R_xLr)Kr2if>`5qgcbHY!Neic4Od;^RXCM=J7s{o;ABA6oH{O6VY zl5Uo1>`_Xm)2!E4DnQbJY;|TC5YR)?4^S-og`Rb-Er}U};OnZd%%WdR!W2nWxZ_K! za(-24EmNXhQqg?>MKYLc4u3)U0G0271)fFIWwr@R{7ru(ALS$USe~hF{kT&;AU4j; z5eF~Xp@jnEtb7&&auZo@|3N5#^XWHUTXrRcU;MUg*u-3&zZ}~IDam`gb$Yw_fN+DG z2L`9ZI#qU#Dsh!y?2-N+xK)zdTfg zW^?>LI4wLu*e6j{;1b)Id(?P?&=E9Zb+4r^8o`{l+XTaIznzAhi^y4P2jd<iciD zlb;Ha$=AY!Mhpb>lSpl*F(^*n8>Nr%EkLZ=6-iD1%ca7D@lOQazMahpY^7jk0uHdd z+7}p_WON25_hGHDN3qVtPcR=$jVIx&ZW%A@+qniOny)s2wMn)fhNGL|4UZH)VAWmd z8q+{ugH1%|3l0Z8wo-PKt%HgWnu?H*eO=a%faq)X^FqyUzKvKD1SMoZqXa}n9f#fT z*bU!vz!Hj$De>D@+!}vn?Ib@}`FE4$Up^?RTD^Ddk0BPTNftRMgxpAbk;cmrV2q%n zw^9FwqGwI?XT=su!l}}{aJ(>az*J|-a6oXuROI(1FAx;{Vq*}(W!ZY>J4Uqr1uMS= zsQm_V>t3OGFN%$0k74MPEEJQt8AT61gDF@1+0dNp)#xv5eYkvG-UrWOGxUWcny`>1 zv|1XYf3C`{TZQLuj<&H=_%X}-fSBL2@tFtwi$)GZrmgdu^8J&DtrEvoFm-BQxsk6^ zj6ijJ*by{1lAz*N;~8fDdhbfJWkvACv1J~#xrdN#DMm*B zVLsxC3S~2S^XS$c_ZY3_be9lj`scwJegcxV%JXh3d!2H(@(&X6uTSu`P*-tlG%?r! zg_<)Gyi=g4C0yb2X^VH((!R{zXAQE zSb0%vW9UbwWfOT54bXYO(w9)guD1YbC2`%DW%^zb;>timCH6gyRQ$YBA0dCao#V=s z;<#^ms1-|W77w98<_iH?3TGPM7}?3qf8(14UZUo%uNu5-Ci=uc0G1eCruQXa)=-qOD;?|LsL#wxDHt7O(5g$YbORr^ zi48{RJ~9_}&A6=}b{VG><-vr41#V{)FwnuRp^guHge>L%ZD{72`J|c%n)plRAK)!E z2$>!n%R4|SKJVE5dFoR58}vD3P+WEbFrKZTcZf>J2_rJt$4a6R^McVXh`5l>AB|L z*%h?OZI`55Q-HF$;v7e3oI{qHcu&nMBCa}YKeb>sWBcaC6sgOtl zAtaizs6@7SxRiCOM{hxE&($04rROZLTk4{6V@peJ;2H$V#L->|?EMbCS~*93DEZYm zVibWg=3eLCSqt!?57`mDO5Wr*p8ahv0VS^~lQ~$as?XQ0SFJT~{gJx~huAI{gNnb% zqQf>iR1wrGBH%0K45ugj=Ulg_e4Ur=S4&!gFkdbz35*ayf9punaFzu2`{hO+EWW>t z#H~J%&DJK!!gpDM}`E0CfsIF6_FF65hk6y~G$ zvfb$+j=m};H-}5Mr@{DZ{t$TUh0s;maOCPhx3RX@GYsGNJ%FP%RRa$ zLO+R^{KQJK!bXw_FEWm>B+!7u-XU7v*lF@VR12o0p@MKN;(zJLU#*_XKXQGJ<7Wcckxm+U0lD)QL@ew6H6ULxL@^ zU))(KHBHX~u<3>;=4Z11a|pkTZO!%fB~Z^N9dflMNB7HsC`kB};*)sKbuMG10DE-- zZeS9k;Q-z;R6MyQE1EiKSoD>}KIM}dwE&Gx7rs9O}64gpGN99;97sx_JP-sS$+3I5nWeK1r{ z!hnVt1nA9O7eRb}$QFIooS^8ejsEzQ@y*~f6o={ae!rf&NMe>4-@ixPF|q0tXLF)L zRQFckfiu`q$nZ^6yO*18ciLwL>cAU(3K2O>lk@aiCx!Uc+1UIb0ZCGZ(TTD^_o&D0r>7S~ia^td ztI|~fbiYPmpsgUcQxpd%y7l`kitOmz(~T)6T#InNjI4OUEXoU>{*k(X2TN0nW?%LR zmpWNtP|>U#_}T;}eZh|NGkyT{1IGml1{@fFYjzwL)Tb#a5E=%pz@#_%}F-O(Dzn>t-m!>w0wnwuiW zkaAP4Rf-z=XQf)K59e*OoZ2qn9BDq`D87&MJVcSTR`cg^Zc6xQSN+M)9Kv2HG2?vK z(rgS}KgBtAjR5OSk=z*&cAknOvwm9?bedppQ1nbaUx|t#aJLrqm$P5>gTC{ovbhnU z3Qw)V4D- z3zAd6;x$G(1p)iX9s)|X!B=C)c;dc8C5*Ey^Y?qvE?9zR%dsF!cXkpkV6%bL-QUa9 z?t^B_lwOUDWq5yG+um6f!1s>A_O6t_FfrRi_S<&*=THaBC*iQK@%nlKJcm#6qa%m< zuv&U2LVwS?wdD3FHY}xtWIDux@@27CXhki;1V6~*%8q1^ZDp1UY~=d1O(G6u!=2!b zo04I~Hj>B}r;vP_o}76&-PcvNwZR&|{07#F7(EeZo|T+&Um(OqyHvH+uj^KI;v%f8 ziK7)}88S$|5VU=F5m6QH1TvBt!Gms@{$jW5RW}6-pUZ16JT(WvwpAs9F?f&jQ;fOq z51>KAe!09~NdW7J?oV_Had^ptWW7bjn}6^ZB&inYFojl#q5n zNyMC%f-&v8yQo`Q(Dv@D@jK;M1=w+yNDD&p5?R_UaK|?3!NE27IhzHjJ{hdMP5gr( zEfH_!8T!MOB^ip*Ux!&}uw}%4I--9+Onln{@OQ(XOGEQ7W>X;{{eDvPmHP14su}Xr z9ehqvuszU2WyMEoR%&U! z=<=O}$F>uKw+hwQ$`lBLpI@1EM5om>$Op-)8P`tup)5FscuNbqebJ)j=pv2Fb(ad;I`umJ3-0_ zDZm%>lD2sfEAmn?&f8#YbS&uo1v; zyG&X7@Y5pvbBHoXU=~3UhZAsJS^;gVs8T|GY zKEJKI!Drz!H_M3bAbxf|%E3J`rdkM2s$3LU#s7h|@VPzJenxOF^qhS{Ak*fQ5W9wHmr$p{IK8(N+{;{82*E;2IS})5|7i*aMfj}a9upu07GIk8EWwKN| ziPSnHJl*sNetik!W0juD2kJ3Ly9-p=&*xCeHJf&)wz7-9uuLD?PI|xJu+e~`bYCUy z8N&mZ?vEF_WX0g|$s6NQj*pg>P@mkD29xDlSpD>c@6!5m6+_IP0+T{BDdzes8x7!YNci(7t%=^a_TB zjy-2-sLW(D+M?5K-27YqTEOi7-1$Re=780)iD#q+rZ&Ycm6r-G4S0rl39N^za!vtO1Oo5;{2H^Uqx;706Mr(3fX1;B98(PxtREaa z=Q@~=Idbc$n%r^ie-~d6IGJx#WimK|>`AizT;X>z(Zp$+Zkhu%zyNUI9bkHQYqR3S z16YRTF#{_FJmqE5sH{Ta2(zuF>p7hzuz^hH11#ZbO2R-XOA*Wn|np?xmQ&lC2rn>h|iqfN|7n?Cz{=(aOH#E;X^dYL(1b6&VE< z++%M{@T_5?#O?IjlwPUhKux7)_rvnRe6M|QvOV~kub0gtPJ{(LWSveBlBTTt`OU)M z1XZGs&xdI2cIrFbJmU069}A`5WRFS5LZmH10=s(dO<_9$nEZNhztQ-;bTt80MF9Zp zZuG8U?T(0gADFyfv2=}i=~YL-J970|9K>WA+~8Cbje4R~{+`lgoJquAd$Ze=9`D9) zci2Xd4A+*%qG_%-;6a>$C<^(rK0J|I!?(LdiLh{cA)qeN85X?aD+0ph=N`Ri4{Wx> zKO_z+J89kk+T;8VeGt0i7wN7T)y-Q8KCrKVsS8rO_STFP{~haW+d@M)CBA_?!uAMA zxufZJD#I12!9p}+t0yet74}iF);6974Eb!jlD_1A@2SpG=|bRt=fv;R*~R$pWwGjF0;7NA~COhW~%ei zNM8qh7%?J}9Z!MFUq`+@TZ|%K>m??p@`jMw9@ie;Q7%YC`C}ht11K?1a{2p)YTnc=7P}4e{(cw zU|4`A>k9kAsY@>oKTmqFKURnZu3Wl%SOsc3i(VcaEP6)k<8679kG_VgY;zG4NSzPr zGKn6@+4Z{2LNm-2$~Z_l_Tg7r*cZ%@U4)&pqhC8%_kX+<5;Z{byt^n0pN&?AQZP+IAKSP04+Ogy;ioB@)ys z=FBe@tO$P9W6|(PFbuhqnG+VajKl;;k4lMK&rz7=efF7C>$)cZlA1PSMyh~`YXn7=bpfu|&S^CH z4fqq+a;69akM)EZ(18y-SX&LG=c@l~XlvBE{N`NVc8hl%_4*5_>Ip#V1WH5IxDH;E zR2x3*iLFB5tQ1d$ifNcfVIM5Ab=+p(*LNWF{5dFC`of`L@wV^i9fqJlX>B@St>h9M z@c|9LE$p6lCUL1)kB))9)g&!k)3sK~IoLsAsr>$yf`+zvLQ%yKJ(2n+&bdiiXQ$V`t zrb?Siy-B#zC6N5dt6%Hh3P`PQiY7nO=9MdR(1CLz&cW-a4TcLOm*_|3643YMbO;^# zpLkbGnN!qakWCom?>K$3!0aB5O9CO5EN~1X3d(AI%bU=&D0~NVn`0(eEw;(TZ~3PI zgP<`fNQoaH0csND4WSZ2@~=R)FigP?A7V~A9PN61OV?&PJ7ENPFY`~#=cqdoMT-+u zd1Am^dvXZOe-uT(leg>3@crvSt>D9EOgra!F5&~msRm5zAiHg?pcJjoxE$|_O8|9Euwc;~BD}%euE?s)yo@K%Ts1342RJ%Wv|6r36D1Vx8+?{35Ndks?G-+$4*_ad zP11y7Xn27p95No;hPfYZ(;54m{pR*a+-g*PJ#6!?BnSF=p@3=75h!gDJQd#2O|lBj zmk|Agi%xTP@_ckwe?tKx!4Z$hAh>M#li<>_Q7Q0TXXP%J{9~g13%G1JHogYy{q;<^ zXo%#7_pfCESJ!LXTOM>Ae5_wDEaeaEh~7C_dle=aj}J(@G z-@xv6My!EbrX5s25eV;VqBXgye@r_NSD*oSoELQNl#%skH$1oq6TIz-&Pd z@l}t3;(h$BwB?Ur<(3}cbjw7fIbTSyyvJ@Bh|;&4?ln=oOnVT0wM+=WcFg0MsD=6` zo4O2!)ST143n~=rVshaNfVYU!U>!~=sVc@Fx zomr+Z*i}MTV(bu7KkBMM7N;+k=e)xk$3w1oYCYso5TAzIt)yJVHy-{A;%~ZrW;k+b zJ>#lxe>DPXm0x}CjPJbGfK_I3w5!Ocnp|@7>AIR@-vwt*cSE)nRncH@@%^bBpbKQ3 z{+l?>F{aaDF0)sc?STKqnk;8-16I{y^2#6e*2~*&ID?wchJmx!z2I`l<@9}Ptt3*C z&IiZC$6bPYTG;lt>$`FrT1^WgX&U423BHaW+y7u7i{GKu7ZFiL?n(!4P{m(9*FaP^ z&5JsJQh-_ev_*u8UVdS!g0W6lf2sWX38(>ueW4r78x&|$pUAq4o~YNHNVlJG;p8qKn%1z zA@0thA0yuXJv35w?YIB&J+wF354T!6;Ao9+!ENks@Fq+_KnFzoP8 zganv`Z_YZk)yb#$R>$ye+rVNvoW>DmqWbztn~6Cl>wtt#`rOu)iiRSzT3@|K+Je2^ zb9qTL^|J2LinJ0r5Ow(lpBOp5na$0dxeBS7Qm%htTpx3Jo)%mNd~u>qe0HMLz27T&uH zD0*G=<$VBktJ;nTMIsS6AScmH45Q4PboVEJo9eWlhtnUrW}JthGbvHG&~oK`iCdo8 zPTJ(fGl{Po5Do)BV;w4{y$0yux(z3$ZNVg{Dxt#?nZrj>;O7!>Sk+W^7ACToSSSyP z>pkBpc9^Z#0hz`Idja*f9#}8zb#vBjj^n;b+|H(US0yB}`y-6}+phE9r`tf3sf8uG zb_4|$CPw<9p5Aw7U*ec1DJNBQHFm4u#_e+XUa=S;F!|78w0w z9PXgEM*#gp;%r5e`4(Vo1hA(lrZU1R`-PlF183R=#mz@RogWJz-F$vuwo*Ag6RNgo z;>a-`A+o#vSfKj7oMSWdKNO##6vqMJc*kn8fe5D!W0g~Rvg>DXJB-rHSn>JMZqwbO z(U3#Rz7=YN*&Ubz)>s=!Tk}$SGiMy!Kge)!j^PG(I8+->6vihdMsXMAI z1Xm$rd-c8u<`pfYl7krHq*WUAnfWI>%K9?>g_g2_({K)K-52~wq|@TwF|b2XlzW)w zVwwTdo34%iYc3I(?~j9?NqUsjRk@=`p)vXS6^{X^x;=FP)9QgMbXVl*+wp6qL2Ir_ zAi%RFPJEZ-L9Tib&gFK^3su&7O@fwG#_yJWY$>egO0yum>DHAIEtJflc1*)eU5(Ey zqs<DRADdvLDS*905DUBYp@*g1RTt-fY| zHal@`eZNzN75r%>|0^EO_N!-pCfgf?P z-i$^!uKKQs44>@N9J4ou?~(~mknQJ+ZR&#|= z@WSr~FN{E%3LS>p`#Xz;{u^m?dO{0{rFX+}Y@Z!Ai2%9ng%6Y$s=N7)Xs#T0zgN4T zxJo{M{d#IS09~nXg#LKZ2h}idJ><3EtBa8xdfOR0Lp+w_!a}RT7XQc~)zP)MGCPe^ zMrT+797sQFi`)gOLiUw}A}IM_m#GW|55onxu-XEHb|6lvI!z-Kn-Y8Khy zpEF35Pjrky0OU4Gr}?$nVVkj{)|u<8`QAqP1KYrs0uyze!4u>DoxHVb8x}^qJKa<|%M?YM$9a7JWcuw-@KP%Nc-xOrEoF&H=YZ&- z|9P*!a;X~`KTgnW2A9a(M~R2~yylJ$j90kgul2 z-?xO46i$Mdc)>IXu>-=AVM3TR^=Ud_cLNvcm$dlQ0sG@_v`=^1^}6_2EG)wp9p}3I z*jJi=_AE*&{EK#ISNer$8!ymb6W`9f_?XD;F`%SvIq`&H;4QB^7z!>F+C=qKifaUD z$+yKhBfX59F@R=2l=+Ic?HB~2>dVHt*0W9gm%yu>g4ttu*ex$3b_Mc&MW-w2+v2$~ z9(OB9`jd;dqM;=R^3SxXXufK0Zs)Bhj@%w^+x`kbf!r;V+tNNCPH~EB+uLQqxcNbu zv|P6y+*XJ-0GSm8glK~2r`*z3r1wqQmhC1Nd#}j~*U~~b0a_KbY3BZto?dY5zHJJy z?I5WJ`QFVu7K4$9pIiTHg4Ug9_n9*(V|fFUOWT=Yfw-%F^Bb=7L0?U3bo zfU)pYzK3<1N>8dFwa}w0Q?&uHJj7}0K7r!RMp<5e{g$rY?tQmQMcCwJW_K+LA+?dZ zZcXxcj%86RI*;9Epf+_*Ob8H{1qs6V-5{=5-7}Tb|;pFiIdvd=mb% zSNV9^5&KT&oIS!;b0YZ_`dID09JqzB4nN7t7AV4ahIe?`k%CTV+lACicZvv0hg& z7>;|8Bn6NQTA8C?XL6iREDHo#y~LD+N; z`Dh}_xyx^SMHMmu(4LvP0*CvLGz;92obi;^GFlT?|2XMr@NQYZI_+DQN*uk`%hP#> zq}Yob9QZ;HiIg|{Bmc0`hD{euR?wOqXwTfbLPq|_HGTWAOYWJl{hWYo(}KW-h))=2 zWYB8{Z#jkW&pC1u^OgpJ94kW_s{o|?{WuYZT{9n6JX|McXh(bXpGD6-Us4ZFg;DtOA`hM-8uo&!Bs5sn*gLt zSRSxZJAlL~z3JrQP1_!~MnxEftMc7QFHYVK`FjB!=uWI&5Hz3i9i z(0~4%t*Uz7RB&5aGteN@Oas8LYT|HUg~YdRz(He*X1e(MY*_?(2&HVkd{hHF@-$o!!&5A~;%+1J-s40i;^B&X zymla6Ho(nOJTDMUb&b|O&&k9i3{pSInhb}PJorZs)J!#{F$mE z8MiEb#~Q{{REtBp(HF~ z#Rd%+*zCZkv4sfRf=MVEI+rv1ckV|a~~_fyeE<0?10vv^ZSz7ZT-M2 z;BVKRW`5@C{vGyv>PBD_Ha{s$tho;xlj;ieHnGqfSFrWf*J9Z!n&C}vt)a)Z*8Oo# z5Ujiy>i=&smsS_gUi!j3m)>xBr>2cV-W5NUPGF`DJ0lEPgiU9f4*rccxdcd#kQYdc zs?lkYSI!6yhHj0Vo&t#Qoiq~a3&v3^Q_pYZD+K=1IAl^HqP`6O(@0NLL%r~p8LLba z4Yj}gIt)(1B4)F5(F7WjEgw3-2dB#T4^-z7T>n7emF%kRt89EWH zdHgVD_pZLjj+$IteajLDdWQN%izH}aa z;pSIYmUX&v_1CY_f{P6a!J7gTi6t2*n!heZ?yla^2GJ{Us z@QAu)YbL$GYkRi!-ITiN9pLf}``angkZ=~#_ zz96ZYUxlh(Yh_lRK*TdY8;wHyjA<#$Er)<1b_u_$}a&(*KJ9i`s^C{9= zZy+)si+kNpT+K)-YnTepVjgcGYza{hMei>*iR{^04(z7tH4?f=mIvXv@#697&#*rv zTcVy)uD2z9ER87{QsCbPPKHB*;vqQ8NC-+STCTa3{iu}()A=M&joW?>?Ugkjo!344 zU8VyLs0#7pIM6t%(+M+<#@zS#3d~-63hSoG7(E1*yN{b|hgmKXDMllSK@g-~CZ*B& znct`1FSR{UMc)tMzI{U&Sw6HPY~}%@%pvg?bWqWF9ZUlrx*UVoXmqZC#0AwRK(c?! zOMPqWLeL=RPiY8v;Uqt#-^asDf&nFw0DLWsb-n~a32je`sQ^D4 zrh){fBZ^O~fC&3LOx!&9XV`67{i!TOL0_4x32W_wVu!MWwG7>WVX^exf$j8mi#lRy zb+x$2WiJwEmwaY4s8{6M#NEL0AbO4{K++F>Ackt^81iM zl#>N&R()-EIbHSU3tcZm%7M8AK%CSUt`ECa_#;^qdk2B(d2Me->C64T;>jLVhkFucXWk6`SwePQ5q0ckQ~v?@ti|FB)EV&>Q=kTY>tqm<+0~`4FHN=P!%r7F z%Nf7Zx#ObQe5cE7t=`SW<*c>K=m7uvWq2bhl3L=y{govRtQVCosc7Qh3tLyNt2B*b zF8~-N2yOnf&U#zPF!2dPy{qkKR67rwVN17ViXDJ$uE?{tXFwre`evZ!bf&W#J+x4>5kx&x5W(F3rEqksgOakCH)cU$KwtO^i0J6El3ga;R} z^ZPC)<9_sR+CU*Se)@E-hikImoY@YZ-l} z&EV1y0sSkAi2$8iD_qYs1=*@Jr-6M%P6gM#DW7_$#RB8qt-NsCZ&2S~Fmp8zarPj0 zv1b_nXWA_LfLX2X8Z@=(i0p2*BDa0ZNt%f0w4TMt=EE;4n@AE)g7_%iYeQkbKA