diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs index fa96db75a..adeb499d2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs @@ -168,10 +168,13 @@ namespace Barotrauma public static void Draw(SpriteBatch spriteBatch, Character character, Camera cam) { - if (GUI.DisableHUD) return; + if (GUI.DisableHUD) { return; } character.CharacterHealth.Alignment = Alignment.Right; - GUI.InfoAreaBackground.Draw(spriteBatch, Vector2.Zero); + if (Screen.Selected == GameMain.GameScreen) + { + GUI.InfoAreaBackground.Draw(spriteBatch, Vector2.Zero, scale: GUI.Scale); + } if (GameMain.GameSession?.CrewManager != null) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs index 74060629d..2a4a64976 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterInfo.cs @@ -41,7 +41,7 @@ namespace Barotrauma Name, textColor: nameColor, font: GUI.LargeFont) { Padding = Vector4.Zero, - AutoScale = true + AutoScaleHorizontal = true }; if (Job != null) @@ -213,10 +213,10 @@ namespace Barotrauma } } - public void DrawJobIcon(SpriteBatch spriteBatch) + public void DrawJobIcon(SpriteBatch spriteBatch, Vector2? pos = null, float scale = 1.0f) { if (jobIcon == null) return; - jobIcon.Draw(spriteBatch, jobIconPos, Job.Prefab.UIColor, scale: .5f * GUI.Scale); + jobIcon.Draw(spriteBatch, pos ?? jobIconPos, Job.Prefab.UIColor, scale: .5f * GUI.Scale * scale); } private void DrawAttachmentSprite(SpriteBatch spriteBatch, WearableSprite attachment, Sprite head, Vector2 drawPos, float scale, float depthStep, SpriteEffects spriteEffects = SpriteEffects.None) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs index b0e0891e8..761d082b3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs @@ -150,6 +150,9 @@ namespace Barotrauma private SpriteSheet limbIndicatorOverlay; private float limbIndicatorOverlayAnimState; + private SpriteSheet medUIExtra; + private float medUIExtraAnimState; + private GUIComponent draggingMed; private int highlightedLimbIndex = -1; @@ -237,7 +240,7 @@ namespace Barotrauma get { return healthBarPulsateTimer; } set { healthBarPulsateTimer = MathHelper.Clamp(value, 0.0f, 10.0f); } } - + partial void InitProjSpecific(XElement element, Character character) { DisplayedVitality = MaxVitality; @@ -259,7 +262,7 @@ namespace Barotrauma barSize: 1.0f, color: GUIColorSettings.HealthBarColorHigh, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical", false) { Enabled = true, - HoverCursor = CursorState.Hand, + HoverCursor = CursorState.Hand, IsHorizontal = horizontal }; healthBarShadow = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarAreaLeft, GUI.Canvas), @@ -271,12 +274,14 @@ namespace Barotrauma 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"); - var healthInterfaceLayout = new GUILayoutGroup(new RectTransform(Vector2.One / 1.1f, healthInterfaceFrame.RectTransform, anchor: Anchor.Center), true); + var healthInterfaceLayout = new GUILayoutGroup(new RectTransform(Vector2.One / 1.05f, healthInterfaceFrame.RectTransform, anchor: Anchor.Center), true); + + var healthWindowContainer = new GUIFrame(new RectTransform(new Vector2(0.45f, 1.0f), healthInterfaceLayout.RectTransform), style: null); //limb selection frame - healthWindow = new GUIFrame(new RectTransform(new Vector2(0.45f, 1.0f), healthInterfaceLayout.RectTransform), style: null); + healthWindow = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), healthWindowContainer.RectTransform, Anchor.CenterRight, Pivot.CenterRight), style: "GUIFrameListBox"); - var healthWindowVerticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One * 0.9f, healthWindow.RectTransform, Anchor.Center)); + var healthWindowVerticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One * 0.95f, healthWindow.RectTransform, Anchor.Center)); var paddedHealthWindow = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.95f), healthWindowVerticalLayout.RectTransform), true) { @@ -301,9 +306,34 @@ namespace Barotrauma CanBeFocused = false }; - GUILayoutGroup selectedLimbLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), paddedHealthWindow.RectTransform)); + var rightSide = new GUIFrame(new RectTransform(new Vector2(0.4f, 1.0f), paddedHealthWindow.RectTransform), style: null); + + new GUICustomComponent(new RectTransform(new Vector2(1.0f, 0.3f), rightSide.RectTransform, Anchor.BottomRight, Pivot.BottomRight), + (sb, component) => + { + if (medUIExtra == null) { return; } + float overlayScale = Math.Min( + component.Rect.Width / (float)medUIExtra.FrameSize.X, + component.Rect.Height / (float)medUIExtra.FrameSize.Y); + + int frame = (int)medUIExtraAnimState; + + medUIExtra.Draw(sb, frame, component.Rect.Center.ToVector2(), Color.Gray, origin: medUIExtra.FrameSize.ToVector2() / 2, rotate: 0.0f, + scale: Vector2.One * overlayScale); + }, + (dt, component) => + { + medUIExtraAnimState += dt * 10.0f; + while (medUIExtraAnimState >= 16.0f) + { + medUIExtraAnimState -= 16.0f; + } + }); + + GUILayoutGroup selectedLimbLayout = new GUILayoutGroup(new RectTransform(Vector2.One, rightSide.RectTransform)); selectedLimbText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.08f), selectedLimbLayout.RectTransform), "", font: GUI.LargeFont); + selectedLimbText.AutoScaleHorizontal = true; afflictionIconContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.92f), selectedLimbLayout.RectTransform), style: null); afflictionIconContainer.KeepSpaceForScrollBar = true; @@ -327,9 +357,21 @@ namespace Barotrauma 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 infoLayout = new GUILayoutGroup(new RectTransform(Vector2.One, paddedInfoFrame.RectTransform)) + { + Stretch = true, + RelativeSpacing = 0.03f + }; - var nameContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), infoLayout.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true) + var textContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), infoLayout.RectTransform), style: "GUIFrameListBox"); + + var textLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1.0f), textContainer.RectTransform, Anchor.Center, Pivot.Center)) + { + Stretch = true, + RelativeSpacing = 0.03f + }; + + var nameContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), textLayout.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true) { Stretch = true }; @@ -338,25 +380,29 @@ namespace Barotrauma onDraw: (spriteBatch, component) => { character.Info.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), component.Rect.Width); + character.Info.DrawJobIcon(spriteBatch, new Vector2(component.Rect.Right + component.Rect.Width, (float)component.Rect.Top + component.Rect.Height * 0.75f), 0.75f); }); - characterName = new GUITextBlock(new RectTransform(new Vector2(0.85f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) + characterName = new GUITextBlock(new RectTransform(new Vector2(0.85f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.BottomLeft, font: GUI.SubHeadingFont) { - AutoScale = true + AutoScaleHorizontal = true }; + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), textLayout.RectTransform), style: "HorizontalLine"); - afflictionInfoContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), infoLayout.RectTransform, Anchor.TopLeft)); + afflictionInfoContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), textLayout.RectTransform, Anchor.TopLeft), style: null); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), infoLayout.RectTransform, Anchor.TopLeft), TextManager.Get("SuitableTreatments"), textAlignment: Alignment.TopLeft); + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), textLayout.RectTransform), style: "HorizontalLine"); - treatmentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), infoLayout.RectTransform), true) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), textLayout.RectTransform, Anchor.TopLeft), TextManager.Get("SuitableTreatments"), textAlignment: Alignment.TopLeft); + + treatmentLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), textLayout.RectTransform), true) { - Stretch = true + Stretch = false }; - recommendedTreatmentContainer = new GUIListBox(new RectTransform(new Vector2(0.9f, 1.0f), treatmentLayout.RectTransform, Anchor.TopLeft), isHorizontal: true, style: null) + recommendedTreatmentContainer = new GUIListBox(new RectTransform(new Vector2(0.9f, 1.0f), treatmentLayout.RectTransform, Anchor.Center, Pivot.Center), isHorizontal: true, style: null) { - KeepSpaceForScrollBar = true + KeepSpaceForScrollBar = false }; lowSkillIndicator = new GUIImage(new RectTransform(new Vector2(0.1f, 1.0f), treatmentLayout.RectTransform, Anchor.TopLeft, Pivot.Center), @@ -370,6 +416,8 @@ namespace Barotrauma }; lowSkillIndicator.RectTransform.MaxSize = new Point(lowSkillIndicator.Rect.Height); + var tempFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), textLayout.RectTransform), style: null); + cprLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), infoLayout.RectTransform), true) { Stretch = true @@ -443,8 +491,12 @@ namespace Barotrauma switch (subElement.Name.ToString().ToLowerInvariant()) { case "sprite": + case "meduisilhouette": limbIndicatorOverlay = new SpriteSheet(subElement); break; + case "meduiextra": + medUIExtra = new SpriteSheet(subElement); + break; } } } @@ -1062,9 +1114,9 @@ namespace Barotrauma var button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.9f), child.RectTransform), style: null) { - Color = Color.Gray.Multiply(0.1f), - HoverColor = Color.Gray.Multiply(0.4f), - SelectedColor = Color.Gray.Multiply(0.25f), + Color = Color.Gray.Multiply(0.1f).Opaque(), + HoverColor = Color.Gray.Multiply(0.4f).Opaque(), + SelectedColor = Color.Gray.Multiply(0.25f).Opaque(), PressedColor = Color.Black, UserData = "selectaffliction", OnClicked = SelectAffliction @@ -1100,22 +1152,27 @@ namespace Barotrauma List> treatmentSuitabilities = treatmentSuitability.OrderByDescending(t => t.Value).ToList(); + int count = 0; foreach (KeyValuePair treatment in treatmentSuitabilities) { + count++; + if (count > 5) { break; } ItemPrefab item = MapEntityPrefab.Find(name: null, identifier: treatment.Key, showErrorMessages: false) as ItemPrefab; if (item == null) continue; - var itemSlot = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), recommendedTreatmentContainer.Content.RectTransform, Anchor.TopLeft), - style: "InnerGlow") + var itemSlot = new GUIFrame(new RectTransform(new Vector2(1.0f / 7.0f, 1.0f), recommendedTreatmentContainer.Content.RectTransform, Anchor.TopLeft), + style: null) { UserData = item }; - itemSlot.Color = ToolBox.GradientLerp(treatment.Value, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green); - itemSlot.SelectedColor = itemSlot.HoverColor = itemSlot.Color; + var innerFrame = new GUIFrame(new RectTransform(Vector2.One, itemSlot.RectTransform, Anchor.Center, Pivot.Center, scaleBasis: ScaleBasis.Smallest), style: "GUIFrameListBox") + { + CanBeFocused = false + }; Sprite itemSprite = item.InventoryIcon ?? item.sprite; Color itemColor = itemSprite == item.sprite ? item.SpriteColor : item.InventoryIconColor; - var itemIcon = new GUIImage(new RectTransform(new Vector2(0.8f, 0.8f), itemSlot.RectTransform, Anchor.Center), + var itemIcon = new GUIImage(new RectTransform(new Vector2(0.8f, 0.8f), innerFrame.RectTransform, Anchor.Center), itemSprite, scaleToFit: true) { CanBeFocused = false, @@ -1242,11 +1299,11 @@ namespace Barotrauma private void UpdateHeartrate(float deltaTime, GUICustomComponent component) { - heartbeatTimer -= deltaTime; + heartbeatTimer -= deltaTime * 0.75f; if (heartbeatTimer <= 0.0f) { - heartbeatTimer = 0.5f; + while (heartbeatTimer <= 0.0f) { heartbeatTimer += 0.5f; } IEnumerable newPositions; if (Character == null || Character.IsDead || Character.IsUnconscious) @@ -1278,7 +1335,7 @@ namespace Barotrauma } } - currentHeartrateTime += deltaTime; + currentHeartrateTime += deltaTime * 0.75f; while (currentHeartrateTime >= 1.0f) { currentHeartrateTime -= 1.0f; @@ -1287,16 +1344,20 @@ namespace Barotrauma private void DrawHeartrate(SpriteBatch spriteBatch, GUICustomComponent component) { - GUI.DrawRectangle(spriteBatch, component.Rect, Color.Black, true); + Rectangle targetRect = component.Parent.Rect; + targetRect.Location += new Point(6, 6); + targetRect.Size -= new Point(12, 12); + + //GUI.DrawRectangle(spriteBatch, targetRect, 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(); + Vector2 pos = new Vector2(heartratePosition.Time, -heartratePosition.Height * 0.5f + 0.5f) * targetRect.Size.ToVector2() + targetRect.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 (pos.X < targetRect.Left + 1) { pos.X = targetRect.Left + 1; } + if (pos.X > targetRect.Right - 1) { pos.X = targetRect.Right - 1; } if (first) { @@ -1317,17 +1378,17 @@ namespace Barotrauma 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); + destinationRectangle.Location = new Point((int)(currentHeartrateTime * targetRect.Width) + targetRect.Left - targetRect.Height, targetRect.Top); + destinationRectangle.Size = new Point((int)(targetRect.Height * ((float)sourceRect.Width / (float)sourceRect.Height)), targetRect.Height); - if (destinationRectangle.Left < component.Rect.Left) + if (destinationRectangle.Left < targetRect.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); + destinationRectangle2.Location = new Point(targetRect.Right - (targetRect.Left - destinationRectangle.Left), targetRect.Top); + destinationRectangle2.Size = new Point(targetRect.Right - destinationRectangle2.Left, targetRect.Height); int originalWidth = sourceRect.Width; - sourceRect.Width = (int)(sourceRect.Width * ((float)(destinationRectangle.Right - component.Rect.Left) / (float)component.Rect.Height)); + sourceRect.Width = (int)(sourceRect.Width * ((float)(destinationRectangle.Right - targetRect.Left) / (float)targetRect.Height)); sourceRect.X += originalWidth - sourceRect.Width; Rectangle sourceRect2 = heartrateFade.Bounds; @@ -1335,9 +1396,9 @@ namespace Barotrauma spriteBatch.Draw(heartrateFade, destinationRectangle2, sourceRect2, Color.White); originalWidth = destinationRectangle.Width; - int newWidth = destinationRectangle.Right - component.Rect.Left; + int newWidth = destinationRectangle.Right - targetRect.Left; - destinationRectangle.Size = new Point(newWidth, component.Rect.Height); + destinationRectangle.Size = new Point(newWidth, targetRect.Height); destinationRectangle.X += originalWidth - newWidth; GUI.DrawRectangle(spriteBatch, new Rectangle(destinationRectangle.Right, destinationRectangle.Top, @@ -1346,9 +1407,9 @@ namespace Barotrauma 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); + targetRect.Right - destinationRectangle.Right, destinationRectangle.Height), Color.Black, true); + GUI.DrawRectangle(spriteBatch, new Rectangle(targetRect.Left, destinationRectangle.Top, + destinationRectangle.Left - targetRect.Left, destinationRectangle.Height), Color.Black, true); } spriteBatch.Draw(heartrateFade, destinationRectangle, sourceRect, Color.White); @@ -1515,45 +1576,43 @@ namespace Barotrauma 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) - { - Limb indicatorLimb = Character.AnimController.GetLimb(a.Prefab.IndicatorLimb); - if (indicatorLimb != null && indicatorLimb.HealthIndex == i) - { - tempAfflictions.Add(a); - } - } + var tempAfflictions = GetMatchingAfflictions(limbHealth, a => true); - 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 negativeEffect = tempAfflictions.Where(a => !a.Prefab.IsBuff && a.Strength >= a.Prefab.ShowIconThreshold).Sum(a => a.Strength); + //float negativeMaxEffect = tempAfflictions.Where(a => !a.Prefab.IsBuff).Sum(a => a.Prefab.MaxStrength); + float positiveEffect = tempAfflictions.Where(a => a.Prefab.IsBuff && a.Strength >= a.Prefab.ShowIconThreshold).Sum(a => a.Strength * 0.2f); + //float positiveMaxEffect = tempAfflictions.Where(a => a.Prefab.IsBuff).Sum(a => a.Prefab.MaxStrength); float midPoint = (float)limbEffectiveArea.Center.Y / (float)limbHealth.IndicatorSprite.Texture.Height; float fadeDist = 0.6f * (float)limbEffectiveArea.Height / (float)limbHealth.IndicatorSprite.Texture.Height; + if (negativeEffect > 0.0f && negativeEffect < 5.0f) { negativeEffect = 5.0f; } + if (positiveEffect > 0.0f && positiveEffect < 5.0f) { positiveEffect = 5.0f; } + + Color positiveColor = Color.Lerp(Color.Orange, Color.Lime, Math.Min(positiveEffect / 15.0f, 1.0f)); + Color negativeColor = Color.Lerp(Color.Orange, Color.Red, Math.Min(negativeEffect / 15.0f, 1.0f)); + Color color1 = Color.Orange; Color color2 = Color.Orange; - if (positiveEffect > 0.0f && negativeEffect > 0.0f) + if (negativeEffect+positiveEffect > 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 (negativeEffect >= positiveEffect) + { + color1 = Color.Lerp(positiveColor, negativeColor, (negativeEffect - positiveEffect) / negativeEffect); + color2 = negativeColor; + } + else + { + color1 = positiveColor; + color2 = Color.Lerp(negativeColor, positiveColor, (positiveEffect - negativeEffect) / positiveEffect); + } } if (Character.IsDead) { - color1 = Color.Lerp(color1, Color.Black, 0.5f); - color2 = Color.Lerp(color2, Color.Black, 0.5f); + color1 = Color.Lerp(color1, Color.Black, 0.75f); + color2 = Color.Lerp(color2, Color.Black, 0.75f); } if (((i == highlightedLimbIndex || i == selectedLimbIndex) && allowHighlight) || highlightAll) { @@ -1610,22 +1669,20 @@ 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; 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) { - DrawLimbAfflictionIcon(spriteBatch, affliction, slot, iconScale, ref iconPos); + DrawLimbAfflictionIcon(spriteBatch, affliction, iconScale, ref iconPos); } foreach (Affliction affliction in afflictions) @@ -1633,11 +1690,11 @@ namespace Barotrauma Limb indicatorLimb = Character.AnimController.GetLimb(affliction.Prefab.IndicatorLimb); if (indicatorLimb != null && indicatorLimb.HealthIndex == i) { - DrawLimbAfflictionIcon(spriteBatch, affliction, slot, iconScale, ref iconPos); + DrawLimbAfflictionIcon(spriteBatch, affliction, iconScale, ref iconPos); } } i++; - }*/ + } if (draggingMed != null) { @@ -1647,7 +1704,7 @@ namespace Barotrauma } } - private void DrawLimbAfflictionIcon(SpriteBatch spriteBatch, Affliction affliction, GUIComponentStyle slotStyle, float iconScale, ref Vector2 iconPos) + private void DrawLimbAfflictionIcon(SpriteBatch spriteBatch, Affliction affliction, float iconScale, ref Vector2 iconPos) { if (affliction.Strength < affliction.Prefab.ShowIconThreshold) return; Vector2 iconSize = (affliction.Prefab.Icon.size * iconScale); @@ -1656,10 +1713,6 @@ namespace Barotrauma float alpha = MathHelper.Lerp(0.3f, 1.0f, (affliction.Strength - affliction.Prefab.ShowIconThreshold) / Math.Min(affliction.Prefab.MaxStrength - affliction.Prefab.ShowIconThreshold, 10.0f)); - slotStyle.Sprites[GUIComponent.ComponentState.None][0].Draw( - spriteBatch, - new Rectangle((iconPos - iconSize / 2.0f).ToPoint(), iconSize.ToPoint()), - slotStyle.Color * alpha); affliction.Prefab.Icon.Draw(spriteBatch, iconPos - iconSize / 2.0f, GetAfflictionIconColor(affliction.Prefab, affliction) * alpha, 0, iconScale); iconPos += new Vector2(10.0f, 20.0f) * iconScale; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Extensions/ColorExtensions.cs b/Barotrauma/BarotraumaClient/ClientSource/Extensions/ColorExtensions.cs index 191f5bfff..3de8f949c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Extensions/ColorExtensions.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Extensions/ColorExtensions.cs @@ -11,5 +11,10 @@ namespace Barotrauma.Extensions new Color(color.R, color.G, color.B, (byte)(color.A * value)) : new Color((byte)(color.R * value), (byte)(color.G * value), (byte)(color.B * value), (byte)(color.A * value)); } + + public static Color Opaque(this Color color) + { + return new Color(color.R, color.G, color.B, (byte)255); + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Fonts/ScalableFont.cs b/Barotrauma/BarotraumaClient/ClientSource/Fonts/ScalableFont.cs index b545e192c..74a57080f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Fonts/ScalableFont.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Fonts/ScalableFont.cs @@ -198,10 +198,6 @@ namespace Barotrauma this.texDims = texDims; this.baseChar = baseChar; - lock (mutex) - { - face.SetPixelSizes(0, size); - } textures.ForEach(t => t.Dispose()); textures.Clear(); texCoords.Clear(); @@ -223,17 +219,15 @@ namespace Barotrauma lock (mutex) { + face.SetPixelSizes(0, size); face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal); baseHeight = face.Glyph.Metrics.Height.ToInt32(); - } - //lineHeight = baseHeight; - for (int i = 0; i < charRanges.Length; i += 2) - { - uint start = charRanges[i]; - uint end = charRanges[i + 1]; - for (uint j = start; j <= end; j++) + + for (int i = 0; i < charRanges.Length; i += 2) { - lock (mutex) + uint start = charRanges[i]; + uint end = charRanges[i + 1]; + for (uint j = start; j <= end; j++) { uint glyphIndex = face.GetCharIndex(j); if (glyphIndex == 0) continue; @@ -307,107 +301,118 @@ namespace Barotrauma currentCoords.X += glyphWidth + 2; } + CrossThread.RequestExecutionOnMainThread(() => + { + textures[texIndex].SetData(pixelBuffer); + }); } - CrossThread.RequestExecutionOnMainThread(() => - { - textures[texIndex].SetData(pixelBuffer); - }); } } public void DynamicRenderAtlas(GraphicsDevice gd, uint character, int texDims = 1024, uint baseChar = 0x54) { - if (textures.Count == 0) + if (System.Threading.Thread.CurrentThread != GameMain.MainThread) { - this.texDims = texDims; - this.baseChar = baseChar; - lock (mutex) { face.SetPixelSizes(0, size); } - face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal); - baseHeight = face.Glyph.Metrics.Height.ToInt32(); CrossThread.RequestExecutionOnMainThread(() => { - textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color)); + DynamicRenderAtlas(gd, character, texDims, baseChar); }); - } - - uint glyphIndex = face.GetCharIndex(character); - if (glyphIndex == 0) { return; } - - lock (mutex) { face.SetPixelSizes(0, size); } - face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); - if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0) - { - if (face.Glyph.Metrics.HorizontalAdvance > 0) - { - //glyph is empty, but char still applies advance - GlyphData blankData = new GlyphData(); - blankData.advance = (float)face.Glyph.Metrics.HorizontalAdvance; - blankData.texIndex = -1; //indicates no texture because the glyph is empty - texCoords.Add(character, blankData); - } return; } - //stacktrace doesn't really work that well when RenderGlyph throws an exception - face.Glyph.RenderGlyph(RenderMode.Normal); - byte[] bitmap = face.Glyph.Bitmap.BufferData; - int glyphWidth = face.Glyph.Bitmap.Width; - int glyphHeight = bitmap.Length / glyphWidth; + byte[] bitmap; + int glyphWidth; int glyphHeight; + Fixed26Dot6 horizontalAdvance; + Vector2 drawOffset; - if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1) + lock (mutex) { - throw new Exception(filename + ", " + size.ToString() + ", " + (char)character + "; Glyph dimensions exceed texture atlas dimensions"); - } - - currentDynamicAtlasNextY = Math.Max(currentDynamicAtlasNextY, glyphHeight + 2); - if (currentDynamicAtlasCoords.X + glyphWidth + 2 > texDims - 1) - { - currentDynamicAtlasCoords.X = 0; - currentDynamicAtlasCoords.Y += currentDynamicAtlasNextY; - currentDynamicAtlasNextY = 0; - } - //no more room in current texture atlas, create a new one - if (currentDynamicAtlasCoords.Y + glyphHeight + 2 > texDims - 1) - { - currentDynamicAtlasCoords.X = 0; - currentDynamicAtlasCoords.Y = 0; - currentDynamicAtlasNextY = 0; - CrossThread.RequestExecutionOnMainThread(() => + if (texCoords.ContainsKey(character)) { return; } + if (textures.Count == 0) { + this.texDims = texDims; + this.baseChar = baseChar; + face.SetPixelSizes(0, size); + face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal); + baseHeight = face.Glyph.Metrics.Height.ToInt32(); textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color)); - }); - currentDynamicPixelBuffer = null; - } - - GlyphData newData = new GlyphData - { - advance = (float)face.Glyph.Metrics.HorizontalAdvance, - texIndex = textures.Count - 1, - texCoords = new Rectangle((int)currentDynamicAtlasCoords.X, (int)currentDynamicAtlasCoords.Y, glyphWidth, glyphHeight), - drawOffset = new Vector2(face.Glyph.BitmapLeft, baseHeight * 14 / 10 - face.Glyph.BitmapTop) - }; - texCoords.Add(character, newData); - - if (currentDynamicPixelBuffer == null) - { - currentDynamicPixelBuffer = new uint[texDims * texDims]; - textures[newData.texIndex].GetData(currentDynamicPixelBuffer, 0, texDims * texDims); - } - - for (int y = 0; y < glyphHeight; y++) - { - for (int x = 0; x < glyphWidth; x++) - { - byte byteColor = bitmap[x + y * glyphWidth]; - currentDynamicPixelBuffer[((int)currentDynamicAtlasCoords.X + x) + ((int)currentDynamicAtlasCoords.Y + y) * texDims] = (uint)(byteColor << 24 | 0x00ffffff); } - } - CrossThread.RequestExecutionOnMainThread(() => - { - textures[newData.texIndex].SetData(currentDynamicPixelBuffer); - }); - currentDynamicAtlasCoords.X += glyphWidth + 2; + uint glyphIndex = face.GetCharIndex(character); + if (glyphIndex == 0) { return; } + + face.SetPixelSizes(0, size); + face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); + if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0) + { + if (face.Glyph.Metrics.HorizontalAdvance > 0) + { + //glyph is empty, but char still applies advance + GlyphData blankData = new GlyphData(); + blankData.advance = (float)face.Glyph.Metrics.HorizontalAdvance; + blankData.texIndex = -1; //indicates no texture because the glyph is empty + texCoords.Add(character, blankData); + } + return; + } + + //stacktrace doesn't really work that well when RenderGlyph throws an exception + face.Glyph.RenderGlyph(RenderMode.Normal); + bitmap = (byte[])face.Glyph.Bitmap.BufferData.Clone(); + glyphWidth = face.Glyph.Bitmap.Width; + glyphHeight = bitmap.Length / glyphWidth; + horizontalAdvance = face.Glyph.Metrics.HorizontalAdvance; + drawOffset = new Vector2(face.Glyph.BitmapLeft, baseHeight * 14 / 10 - face.Glyph.BitmapTop); + + if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1) + { + throw new Exception(filename + ", " + size.ToString() + ", " + (char)character + "; Glyph dimensions exceed texture atlas dimensions"); + } + + currentDynamicAtlasNextY = Math.Max(currentDynamicAtlasNextY, glyphHeight + 2); + if (currentDynamicAtlasCoords.X + glyphWidth + 2 > texDims - 1) + { + currentDynamicAtlasCoords.X = 0; + currentDynamicAtlasCoords.Y += currentDynamicAtlasNextY; + currentDynamicAtlasNextY = 0; + } + //no more room in current texture atlas, create a new one + if (currentDynamicAtlasCoords.Y + glyphHeight + 2 > texDims - 1) + { + currentDynamicAtlasCoords.X = 0; + currentDynamicAtlasCoords.Y = 0; + currentDynamicAtlasNextY = 0; + textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color)); + currentDynamicPixelBuffer = null; + } + + GlyphData newData = new GlyphData + { + advance = (float)horizontalAdvance, + texIndex = textures.Count - 1, + texCoords = new Rectangle((int)currentDynamicAtlasCoords.X, (int)currentDynamicAtlasCoords.Y, glyphWidth, glyphHeight), + drawOffset = drawOffset + }; + texCoords.Add(character, newData); + + if (currentDynamicPixelBuffer == null) + { + currentDynamicPixelBuffer = new uint[texDims * texDims]; + textures[newData.texIndex].GetData(currentDynamicPixelBuffer, 0, texDims * texDims); + } + + for (int y = 0; y < glyphHeight; y++) + { + for (int x = 0; x < glyphWidth; x++) + { + byte byteColor = bitmap[x + y * glyphWidth]; + currentDynamicPixelBuffer[((int)currentDynamicAtlasCoords.X + x) + ((int)currentDynamicAtlasCoords.Y + y) * texDims] = (uint)(byteColor << 24 | 0x00ffffff); + } + } + textures[newData.texIndex].SetData(currentDynamicPixelBuffer); + + currentDynamicAtlasCoords.X += glyphWidth + 2; + } } public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth) @@ -429,7 +434,7 @@ namespace Barotrauma } uint charIndex = text[i]; - if (DynamicLoading && !texCoords.ContainsKey(charIndex)) + if (DynamicLoading) { DynamicRenderAtlas(graphicsDevice, charIndex); } @@ -470,7 +475,7 @@ namespace Barotrauma } uint charIndex = text[i]; - if (DynamicLoading && !texCoords.ContainsKey(charIndex)) + if (DynamicLoading) { DynamicRenderAtlas(graphicsDevice, charIndex); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs index 33bf7ab64..e6dc30273 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs @@ -12,7 +12,8 @@ namespace Barotrauma { class ChatBox { - private static Sprite radioIcon; + public const string RadioChatString = "r; "; + private GUIListBox chatBox; private Point screenResolution; @@ -26,8 +27,8 @@ namespace Barotrauma get { return _toggleOpen; } set { - if (_toggleOpen == value) { return; } _toggleOpen = GameMain.Config.ChatOpen = value; + if (value) hideableElements.Visible = true; foreach (GUIComponent child in ToggleButton.Children) { child.SpriteEffects = _toggleOpen ? SpriteEffects.FlipHorizontally : SpriteEffects.None; @@ -65,11 +66,6 @@ namespace Barotrauma public ChatBox(GUIComponent parent, bool isSinglePlayer) { this.IsSinglePlayer = isSinglePlayer; - if (radioIcon == null) - { - radioIcon = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(527, 952, 38, 52), null); - radioIcon.Origin = radioIcon.size / 2; - } screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); @@ -105,7 +101,7 @@ namespace Barotrauma //gui.Text = ""; }; - var chatSendButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.7f), InputBox.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonToggleRight"); + var chatSendButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.7f), InputBox.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonToggleRight"); chatSendButton.OnClicked += (GUIButton btn, object userdata) => { InputBox.OnEnterPressed(InputBox, InputBox.Text); @@ -339,7 +335,7 @@ namespace Barotrauma showNewMessagesButton.Visible = false; } - if (ToggleOpen || (InputBox != null && InputBox.Selected)) + if (ToggleOpen) { openState += deltaTime * 5.0f; //delete all popup messages when the chatbox is open diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs index 569346151..7da77c269 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/ComponentStyle.cs @@ -133,7 +133,16 @@ namespace Barotrauma case "size": break; default: - ChildStyles.Add(subElement.Name.ToString().ToLowerInvariant(), new GUIComponentStyle(subElement, style)); + string styleName = subElement.Name.ToString().ToLowerInvariant(); + if (ChildStyles.ContainsKey(styleName)) + { + DebugConsole.ThrowError("UI style \"" + element.Name.ToString() + "\" contains multiple child styles with the same name (\"" + styleName + "\")!"); + ChildStyles[styleName] = new GUIComponentStyle(subElement, style); + } + else + { + ChildStyles.Add(styleName, new GUIComponentStyle(subElement, style)); + } break; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs index 8e0484b13..033c40afd 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs @@ -78,19 +78,26 @@ namespace Barotrauma public static readonly string[] rectComponentLabels = { "X", "Y", "W", "H" }; public static readonly string[] colorComponentLabels = { "R", "G", "B", "A" }; - public static float Scale - { - get { return (GameMain.GraphicsWidth / 1920.0f + GameMain.GraphicsHeight / 1080.0f) / 2.0f * GameSettings.HUDScale; } - } + public static Vector2 ReferenceResolution => new Vector2(1920f, 1080f); + public static float Scale => (GameMain.GraphicsWidth / ReferenceResolution.X + GameMain.GraphicsHeight / ReferenceResolution.Y) / 2.0f * GameSettings.HUDScale; + public static float xScale => GameMain.GraphicsWidth / ReferenceResolution.X * GameSettings.HUDScale; + public static float yScale => GameMain.GraphicsHeight / ReferenceResolution.Y * GameSettings.HUDScale; + public static float HorizontalAspectRatio => GameMain.GraphicsWidth / (float)GameMain.GraphicsHeight; + public static float VerticalAspectRatio => GameMain.GraphicsHeight / (float)GameMain.GraphicsWidth; + public static float RelativeHorizontalAspectRatio => HorizontalAspectRatio / (ReferenceResolution.X / ReferenceResolution.Y); + public static float RelativeVerticalAspectRatio => VerticalAspectRatio / (ReferenceResolution.Y / ReferenceResolution.X); - public static float xScale + public static float SlicedSpriteScale { - get { return GameMain.GraphicsWidth / 1920.0f * GameSettings.HUDScale; } - } - - public static float yScale - { - get { return GameMain.GraphicsHeight / 1080.0f * GameSettings.HUDScale; } + get + { + if (Math.Abs(1.0f - Scale) < 0.1f) + { + //don't scale if very close to the "reference resolution" + return 1.0f; + } + return Scale; + } } public static GUIStyle Style; @@ -106,7 +113,7 @@ namespace Barotrauma private static Sound[] sounds; private static bool pauseMenuOpen, settingsMenuOpen; public static GUIFrame PauseMenu { get; private set; } - private static Sprite arrow, lockIcon, checkmarkIcon, timerIcon; + private static Sprite arrow; public static bool HideCursor; @@ -155,21 +162,6 @@ namespace Barotrauma get { return arrow; } } - public static Sprite CheckmarkIcon - { - get { return checkmarkIcon; } - } - - public static Sprite LockIcon - { - get { return lockIcon; } - } - - public static Sprite TimerIcon - { - get { return timerIcon; } - } - public static Sprite InfoAreaBackground; public static bool SettingsMenuOpen @@ -263,13 +255,10 @@ namespace Barotrauma t.SetData(new Color[] { Color.White });// fill the texture with white }); - SubmarineIcon = new Sprite("Content/UI/IconAtlas.png", new Rectangle(452, 385, 182, 81), new Vector2(0.5f, 0.5f)); - arrow = new Sprite("Content/UI/IconAtlas.png", new Rectangle(392, 393, 49, 45), new Vector2(0.5f, 0.5f)); - SpeechBubbleIcon = new Sprite("Content/UI/IconAtlas.png", new Rectangle(385, 449, 66, 60), new Vector2(0.5f, 0.5f)); - BrokenIcon = new Sprite("Content/UI/IconAtlas.png", new Rectangle(898, 386, 123, 123), new Vector2(0.5f, 0.5f)); - 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)); + SubmarineIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(452, 385, 182, 81), new Vector2(0.5f, 0.5f)); + arrow = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(392, 393, 49, 45), new Vector2(0.5f, 0.5f)); + SpeechBubbleIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(385, 449, 66, 60), new Vector2(0.5f, 0.5f)); + BrokenIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(898, 386, 123, 123), 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)); } @@ -300,17 +289,33 @@ namespace Barotrauma string line1 = "Barotrauma Unstable v" + GameMain.Version; string line2 = "(" + AssemblyInfo.GetBuildString() + ", branch " + AssemblyInfo.GetGitBranch() + ", revision " + AssemblyInfo.GetGitRevision() + ")"; + Rectangle watermarkRect = new Rectangle(-50, GameMain.GraphicsHeight - 80, 50 + (int)(Math.Max(LargeFont.MeasureString(line1).X, Font.MeasureString(line2).X) * 1.2f), 100); + float alpha = 1.0f; + + int yOffset = 0; + + if (Screen.Selected == GameMain.GameScreen) + { + yOffset = -HUDLayoutSettings.ChatBoxArea.Height; + watermarkRect.Y += yOffset; + } + + if (Screen.Selected == GameMain.GameScreen || Screen.Selected == GameMain.SubEditorScreen) + { + alpha = 0.2f; + } + Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw( - spriteBatch, new Rectangle(-50, GameMain.GraphicsHeight - 80, 50 + (int)(Math.Max(LargeFont.MeasureString(line1).X, Font.MeasureString(line2).X) * 1.2f), 100), Color.Black * 0.8f); + spriteBatch, watermarkRect, Color.Black * 0.8f * alpha); LargeFont.DrawString(spriteBatch, line1, - new Vector2(10, GameMain.GraphicsHeight - 30 - LargeFont.MeasureString(line1).Y), Color.White * 0.6f); + new Vector2(10, GameMain.GraphicsHeight - 30 - LargeFont.MeasureString(line1).Y + yOffset), Color.White * 0.6f * alpha); Font.DrawString(spriteBatch, line2, - new Vector2(10, GameMain.GraphicsHeight - 30), Color.White * 0.6f); + new Vector2(10, GameMain.GraphicsHeight - 30 + yOffset), Color.White * 0.6f * alpha); if (Screen.Selected != GameMain.GameScreen) { var buttonRect = - new Rectangle(20 + (int)Math.Max(LargeFont.MeasureString(line1).X, Font.MeasureString(line2).X), GameMain.GraphicsHeight - (int)(45 * Scale), (int)(150 * Scale), (int)(40 * Scale)); + new Rectangle(20 + (int)Math.Max(LargeFont.MeasureString(line1).X, Font.MeasureString(line2).X), GameMain.GraphicsHeight - (int)(45 * Scale) + yOffset, (int)(150 * Scale), (int)(40 * Scale)); if (DrawButton(spriteBatch, buttonRect, "Report Bug", Style.GetComponentStyle("GUIBugButton").Color * 0.8f)) { GameMain.Instance.ShowBugReporter(); @@ -521,7 +526,7 @@ namespace Barotrauma spriteBatch.End(); spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable); - var sprite = MouseCursorSprites[(int) MouseCursor]; + var sprite = MouseCursorSprites[(int) MouseCursor] ?? MouseCursorSprites[(int)CursorState.Default]; sprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, Color.White, sprite.Origin, 0f, Scale / 1.5f); spriteBatch.End(); @@ -1761,6 +1766,18 @@ namespace Barotrauma //move the interfaces away from each other, in a random direction if they're at the same position Vector2 moveAmount = centerDiff == Point.Zero ? Rand.Vector(1.0f) : Vector2.Normalize(centerDiff.ToVector2()); + //if the horizontal move amount is much larger than vertical, only move horizontally + //(= attempt to place the elements side-by-side if they're more apart horizontally than vertically) + if (Math.Abs(moveAmount.X) > Math.Abs(moveAmount.Y) * 5.0f) + { + moveAmount.Y = 0.0f; + } + //same for the y-axis + else if (Math.Abs(moveAmount.Y) > Math.Abs(moveAmount.X) * 5.0f) + { + moveAmount.X = 0.0f; + } + //make sure we don't move the interfaces out of the screen Vector2 moveAmount1 = ClampMoveAmount(rect1, area, moveAmount * 20.0f * rect1Area / (rect1Area + rect2Area)); Vector2 moveAmount2 = ClampMoveAmount(rect2, area, -moveAmount * 20.0f * rect1Area / (rect1Area + rect2Area)); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs index 032830d2e..6e1b33015 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIComponent.cs @@ -656,18 +656,18 @@ namespace Barotrauma public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle targetElement, List colorData = null) { - if (Tutorials.Tutorial.ContentRunning) return; + if (Tutorials.Tutorial.ContentRunning) { return; } int width = (int)(400 * GUI.Scale); int height = (int)(18 * GUI.Scale); - Point padding = new Point((int)(20 * GUI.Scale), (int)(7 * GUI.Scale)); + Point padding = new Point((int)(10 * GUI.Scale)); if (toolTipBlock == null || (string)toolTipBlock.userData != toolTip) { toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), colorData, toolTip, font: GUI.SmallFont, wrap: true, style: "GUIToolTip"); toolTipBlock.RectTransform.NonScaledSize = new Point( - (int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).X + padding.X), - (int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).Y + padding.Y)); + (int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z), + (int)(GUI.SmallFont.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W)); toolTipBlock.userData = toolTip; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs index a0bbc100c..013c7513b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs @@ -41,7 +41,17 @@ namespace Barotrauma private bool dimensionsNeedsRecalculation; // TODO: Define in styles? - private int scrollBarSize = 25; + private int ScrollBarSize + { + get + { + //use the average of the "desired" size and the scaled size + //scaling the bar linearly with the resolution tends to make them too large on large resolutions + float desiredSize = 25.0f; + float scaledSize = desiredSize * GUI.Scale; + return (int)((desiredSize + scaledSize) / 2.0f); + } + } public bool SelectMultiple; @@ -162,7 +172,7 @@ namespace Barotrauma /// Automatically hides the scroll bar when the content fits in. /// public bool AutoHideScrollBar { get; set; } = true; - + private bool IsScrollBarOnDefaultSide { get; set; } public bool CanDragElements { get; set; } = false; private GUIComponent draggedElement; @@ -171,7 +181,8 @@ namespace Barotrauma public GUIComponent DraggedElement => draggedElement; - public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "") : base(style, rectT) + /// For horizontal listbox, default side is on the bottom. For vertical, it's on the right. + public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true) : base(style, rectT) { CanBeFocused = true; selected = new List(); @@ -196,20 +207,27 @@ namespace Barotrauma { this.color = color.Value; } + IsScrollBarOnDefaultSide = isScrollBarOnDefaultSide; Point size; Anchor anchor; if (isHorizontal) { - size = new Point((int)(Rect.Width - Padding.X - Padding.Z), (int)(scrollBarSize * GUI.Scale)); - anchor = Anchor.BottomCenter; + size = new Point((int)(Rect.Width - Padding.X - Padding.Z), (int)(ScrollBarSize * GUI.Scale)); + anchor = isScrollBarOnDefaultSide ? Anchor.BottomCenter : Anchor.TopCenter; } else { - size = new Point((int)(scrollBarSize * GUI.Scale), (int)(Rect.Height - Padding.Y - Padding.W)); - anchor = Anchor.CenterRight; + // TODO: Should this be multiplied by the GUI.Scale as well? + size = new Point(ScrollBarSize, (int)(Rect.Height - Padding.Y - Padding.W)); + anchor = isScrollBarOnDefaultSide ? Anchor.CenterRight : Anchor.CenterLeft; } - ScrollBar = new GUIScrollBar(new RectTransform(size, rectT, anchor) - { AbsoluteOffset = isHorizontal ? new Point(0, (int)Padding.W) : new Point((int)Padding.Z, 0) }, + ScrollBar = new GUIScrollBar( + new RectTransform(size, rectT, anchor) + { + AbsoluteOffset = isHorizontal ? + new Point(0, IsScrollBarOnDefaultSide ? (int)Padding.W : (int)Padding.Y) : + new Point(IsScrollBarOnDefaultSide ? (int)Padding.Z : (int)Padding.X, 0) + }, isHorizontal: isHorizontal); UpdateScrollBarSize(); Enabled = true; @@ -224,12 +242,15 @@ namespace Barotrauma dimensionsNeedsRecalculation = false; ContentBackground.RectTransform.Resize(Rect.Size); bool reduceScrollbarSize = KeepSpaceForScrollBar ? ScrollBarEnabled : ScrollBarVisible; - Point contentSize = reduceScrollbarSize ? CalculateFrameSize(ScrollBar.IsHorizontal, scrollBarSize) : Rect.Size; + 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); + if (!IsScrollBarOnDefaultSide) { Content.RectTransform.SetPosition(Anchor.BottomRight); } + Content.RectTransform.AbsoluteOffset = new Point( + IsScrollBarOnDefaultSide ? (int)Padding.X : (int)Padding.Z, + IsScrollBarOnDefaultSide ? (int)Padding.Y : (int)Padding.W); 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))); + new Point((int)(Rect.Width - Padding.X - Padding.Z), ScrollBarSize) : + new Point(ScrollBarSize, (int)(Rect.Height - Padding.Y - Padding.W))); ScrollBar.RectTransform.AbsoluteOffset = ScrollBar.IsHorizontal ? new Point(0, (int)Padding.W) : new Point((int)Padding.Z, 0); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs index d5ccc022b..983b32e6c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs @@ -1,4 +1,5 @@ -using Microsoft.Xna.Framework; +using Barotrauma.Extensions; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; @@ -62,8 +63,8 @@ namespace Barotrauma 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 static Point ItemFrameMargin = new Point(50, 56).Multiply(GUI.SlicedSpriteScale); + public static Point ItemFrameOffset = new Point(0, 3).Multiply(GUI.SlicedSpriteScale); public GUIStyle(XElement element, GraphicsDevice graphicsDevice) { @@ -76,10 +77,17 @@ namespace Barotrauma switch (name) { case "cursor": - foreach (var children in subElement.Descendants()) + if (subElement.HasElements) { - var index = children.GetAttributeInt("state", (int) CursorState.Default); - CursorSprite[index] = new Sprite(children); + foreach (var children in subElement.Descendants()) + { + var index = children.GetAttributeInt("state", (int)CursorState.Default); + CursorSprite[index] = new Sprite(children); + } + } + else + { + CursorSprite[(int)CursorState.Default] = new Sprite(subElement); } break; case "green": diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs index 13ba4cbe6..37fd18873 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs @@ -85,7 +85,7 @@ namespace Barotrauma if (Text == newText) { return; } //reset scale, it gets recalculated in SetTextPos - if (autoScale) { textScale = 1.0f; } + if (autoScaleHorizontal || autoScaleVertical) { textScale = 1.0f; } text = newText; wrappedText = newText; @@ -132,19 +132,36 @@ namespace Barotrauma } } - private bool autoScale; + private bool autoScaleHorizontal, autoScaleVertical; /// - /// When enabled, the text is automatically scaled down to fit the textblock. + /// When enabled, the text is automatically scaled down to fit the textblock horizontally. /// - public bool AutoScale + public bool AutoScaleHorizontal { - get { return autoScale; } + get { return autoScaleHorizontal; } set { - if (autoScale == value) return; - autoScale = value; - if (autoScale) + if (autoScaleHorizontal == value) { return; } + autoScaleHorizontal = value; + if (autoScaleHorizontal) + { + SetTextPos(); + } + } + } + + /// + /// When enabled, the text is automatically scaled down to fit the textblock vertically. + /// + public bool AutoScaleVertical + { + get { return autoScaleVertical; } + set + { + if (autoScaleVertical == value) { return; } + autoScaleVertical = value; + if (autoScaleVertical) { SetTextPos(); } @@ -309,7 +326,7 @@ namespace Barotrauma public void SetTextPos() { - if (text == null) return; + if (text == null) { return; } censoredText = ""; for (int i = 0; i < text.Length; i++) @@ -337,12 +354,13 @@ namespace Barotrauma 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 && + if (!autoScaleHorizontal) { minSize.X = float.MaxValue; } + if (!Wrap && !autoScaleVertical) { minSize.Y = float.MaxValue; } + + if ((autoScaleHorizontal || autoScaleVertical) && textScale > 0.1f && (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.Height - padding.Y - padding.W) / TextSize.Y)) - 0.01f; + TextScale = Math.Max(0.1f, Math.Min(minSize.X / TextSize.X, minSize.Y / TextSize.Y)) - 0.01f; return; } @@ -490,20 +508,30 @@ namespace Barotrauma /// /// Set the text scale of the GUITextBlocks so that they all use the same scale and can fit the text within the block. /// - public static void AutoScaleAndNormalize(IEnumerable textBlocks, float? defaultScale = null) + public static void AutoScaleAndNormalize(bool scaleHorizontal = true, bool scaleVertical = false, params GUITextBlock[] textBlocks) + { + AutoScaleAndNormalize(textBlocks.AsEnumerable(), scaleHorizontal, scaleVertical); + } + + /// + /// Set the text scale of the GUITextBlocks so that they all use the same scale and can fit the text within the block. + /// + public static void AutoScaleAndNormalize(IEnumerable textBlocks, bool scaleHorizontal = true, bool scaleVertical = false, float? defaultScale = null) { if (!textBlocks.Any()) { return; } float minScale = Math.Max(textBlocks.First().TextScale, 1.0f); foreach (GUITextBlock textBlock in textBlocks) { if (defaultScale.HasValue) { textBlock.TextScale = defaultScale.Value; } - textBlock.AutoScale = true; + textBlock.AutoScaleHorizontal = scaleHorizontal; + textBlock.AutoScaleVertical = scaleVertical; minScale = Math.Min(textBlock.TextScale, minScale); } foreach (GUITextBlock textBlock in textBlocks) { - textBlock.AutoScale = false; + textBlock.AutoScaleHorizontal = false; + textBlock.AutoScaleVertical = false; textBlock.TextScale = minScale; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs index dbb21079c..185a3553e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBox.cs @@ -75,9 +75,8 @@ namespace Barotrauma set { textBlock.TextGetter = value; } } - // TODO: fix implicit hiding - private bool selected; - public bool Selected + private new bool selected; + public new bool Selected { get { @@ -457,13 +456,13 @@ namespace Barotrauma return currPosition != null ? currPosition.Item2 : textBlock.Text.Length; } - public void Select() + public void Select(int forcedCaretIndex = -1) { if (memento.Current == null) { memento.Store(Text); } - CaretIndex = GetCaretIndexFromScreenPos(PlayerInput.MousePosition); + CaretIndex = forcedCaretIndex == - 1 ? GetCaretIndexFromScreenPos(PlayerInput.MousePosition) : forcedCaretIndex; ClearSelection(); selected = true; GUI.KeyboardDispatcher.Subscriber = this; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs index f8791c790..9e0a4c14f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs @@ -30,10 +30,6 @@ namespace Barotrauma get; private set; } - public static Rectangle InventoryAreaUpper - { - get; private set; - } public static Rectangle CrewArea { @@ -110,7 +106,7 @@ namespace Barotrauma { Padding = (int)(10 * GUI.Scale); - if (inventoryTopY == 0) inventoryTopY = GameMain.GraphicsHeight; + if (inventoryTopY == 0) { inventoryTopY = GameMain.GraphicsHeight - 30; } //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)); @@ -124,7 +120,7 @@ namespace Barotrauma 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); + AfflictionAreaLeft = new Rectangle(PortraitArea.X, HealthBarAreaLeft.Y + healthBarHeight + Padding, healthBarWidth, afflictionAreaHeight); //HealthBarAreaRight = new Rectangle(Padding, GameMain.GraphicsHeight - healthBarHeight - Padding, healthBarWidth, healthBarHeight); /*if (HealthBarAreaRight.Y + healthBarHeight * 0.75f < PortraitArea.Y) @@ -136,14 +132,6 @@ namespace Barotrauma 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); - int toggleButtonWidth = (int)(ChatBox.ToggleButtonWidthRaw * GUI.Scale); int chatBoxWidth = (int)(475 * GUI.Scale); int chatBoxHeight = (int)Math.Max(GameMain.GraphicsHeight * 0.22f, 150); @@ -153,8 +141,11 @@ namespace Barotrauma 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); + var crewAreaY = AfflictionAreaLeft.Bottom + Padding; + var crewAreaHeight = ObjectiveAnchor.Top - Padding - crewAreaY; + CrewArea = new Rectangle(Padding, crewAreaY, (int)Math.Max(400 * GUI.Scale, 400), crewAreaHeight); + + InventoryAreaLower = new Rectangle(Padding, inventoryTopY, GameMain.GraphicsWidth - Padding * 2, GameMain.GraphicsHeight - inventoryTopY); int healthWindowWidth = (int)(GameMain.GraphicsWidth * 0.5f); int healthWindowHeight = (int)(GameMain.GraphicsWidth * 0.5f * 0.65f); @@ -168,7 +159,6 @@ namespace Barotrauma { GUI.DrawRectangle(spriteBatch, ButtonAreaTop, Color.White * 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); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs index 2745a3ee1..0049ea9e5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/RectTransform.cs @@ -293,10 +293,15 @@ namespace Barotrauma } } + private ScaleBasis _scaleBasis; public ScaleBasis ScaleBasis { - get; - private set; + get { return _scaleBasis; } + set + { + _scaleBasis = value; + RecalculateAbsoluteSize(); + } } public bool IsLastChild @@ -336,7 +341,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; + _scaleBasis = scaleBasis; this.relativeSize = relativeSize; this.minSize = minSize; this.maxSize = maxSize; @@ -348,19 +353,23 @@ namespace Barotrauma } /// - /// By default, elements defined with an absolute size (in pixels), will be treated as fixed sized. - /// This can be changed by setting IsFixedSize to false. + /// By default, elements defined with an absolute size (in pixels) will scale with the parent. + /// This can be changed by setting IsFixedSize to true. /// - public RectTransform(Point absoluteSize, RectTransform parent = null, Anchor anchor = Anchor.TopLeft, Pivot? pivot = null) + public RectTransform(Point absoluteSize, RectTransform parent = null, Anchor anchor = Anchor.TopLeft, Pivot? pivot = null, ScaleBasis scaleBasis = ScaleBasis.Normal, bool isFixedSize = false) { Init(parent, anchor, pivot); - this.ScaleBasis = ScaleBasis.Normal; + _scaleBasis = scaleBasis; this.nonScaledSize = absoluteSize; RecalculateScale(); - RecalculateRelativeSize(); + RecalculateRelativeSize(); + if (scaleBasis != ScaleBasis.Normal) + { + RecalculateAbsoluteSize(); + } RecalculateAnchorPoint(); RecalculatePivotOffset(); - IsFixedSize = true; + IsFixedSize = isFixedSize; parent?.ChildrenChanged?.Invoke(this); } @@ -370,6 +379,7 @@ namespace Barotrauma Enum.TryParse(element.GetAttributeString("pivot", anchor.ToString()), out Pivot pivot); Point? minSize = null, maxSize = null; + ScaleBasis scaleBasis = ScaleBasis.Normal; if (element.Attribute("minsize") != null) { minSize = element.GetAttributePoint("minsize", Point.Zero); @@ -378,11 +388,15 @@ namespace Barotrauma { maxSize = element.GetAttributePoint("maxsize", new Point(1000, 1000)); } - + string sb = element.GetAttributeString("scalebasis", null); + if (sb != null) + { + Enum.TryParse(sb, ignoreCase: true, out scaleBasis); + } RectTransform rectTransform; if (element.Attribute("absolutesize") != null) { - rectTransform = new RectTransform(element.GetAttributePoint("absolutesize", new Point(1000, 1000)), parent, anchor, pivot) + rectTransform = new RectTransform(element.GetAttributePoint("absolutesize", new Point(1000, 1000)), parent, anchor, pivot, scaleBasis) { minSize = minSize, maxSize = maxSize @@ -390,7 +404,7 @@ namespace Barotrauma } else { - rectTransform = new RectTransform(element.GetAttributeVector2("relativesize", Vector2.One), parent, anchor, pivot, minSize, maxSize); + rectTransform = new RectTransform(element.GetAttributeVector2("relativesize", Vector2.One), parent, anchor, pivot, minSize, maxSize, scaleBasis); } rectTransform.RelativeOffset = element.GetAttributeVector2("relativeoffset", Vector2.Zero); rectTransform.AbsoluteOffset = element.GetAttributePoint("absoluteoffset", Point.Zero); @@ -438,37 +452,37 @@ namespace Barotrauma protected void RecalculateAbsoluteSize() { Point size = NonScaledParentRect.Size; - if (ScaleBasis == ScaleBasis.BothWidth) + switch (ScaleBasis) { - size.Y = size.X; - } - else if (ScaleBasis == ScaleBasis.BothHeight) - { - size.X = size.Y; - } - else if (ScaleBasis == ScaleBasis.Smallest) - { - if (size.X < size.Y) - { + case ScaleBasis.BothWidth: size.Y = size.X; - } - else - { + break; + case ScaleBasis.BothHeight: size.X = size.Y; - } + break; + case ScaleBasis.Smallest: + if (size.X < size.Y) + { + size.Y = size.X; + } + else + { + size.X = size.Y; + } + break; + case ScaleBasis.Largest: + if (size.X > size.Y) + { + size.Y = size.X; + } + else + { + size.X = size.Y; + } + break; } - 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); + size = size.Multiply(RelativeSize); + nonScaledSize = size.Clamp(MinSize, MaxSize); recalculateRect = true; SizeChanged?.Invoke(); } @@ -684,6 +698,44 @@ namespace Barotrauma children[i].GUIComponent.AddToGUIUpdateList(ignoreChildren, order); } } + + public void MatchPivotToAnchor() => MatchPivotToAnchor(Anchor); + + public void MoveOverTime(Point targetPos, float duration) + { + CoroutineManager.StartCoroutine(DoMoveAnimation(targetPos, duration)); + } + public void ScaleOverTime(Point targetSize, float duration) + { + CoroutineManager.StartCoroutine(DoScaleAnimation(targetSize, duration)); + } + + private IEnumerable DoMoveAnimation(Point targetPos, float duration) + { + Vector2 startPos = AbsoluteOffset.ToVector2(); + float t = 0.0f; + while (t < duration && duration > 0.0f) + { + t += CoroutineManager.DeltaTime; + AbsoluteOffset = Vector2.SmoothStep(startPos, targetPos.ToVector2(), t / duration).ToPoint(); + yield return CoroutineStatus.Running; + } + AbsoluteOffset = targetPos; + yield return CoroutineStatus.Success; + } + private IEnumerable DoScaleAnimation(Point targetSize, float duration) + { + Vector2 startSize = NonScaledSize.ToVector2(); + float t = 0.0f; + while (t < duration && duration > 0.0f) + { + t += CoroutineManager.DeltaTime; + NonScaledSize = Vector2.SmoothStep(startSize, targetSize.ToVector2(), t / duration).ToPoint(); + yield return CoroutineStatus.Running; + } + NonScaledSize = targetSize; + yield return CoroutineStatus.Success; + } #endregion #region Static methods diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs index 8fdc01a25..3d7f9c843 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/UISprite.cs @@ -101,10 +101,9 @@ namespace Barotrauma Vector2 scale = Vector2.One; 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); + scale.X = scale.Y = Math.Min(Math.Min(scale.X, scale.Y), GUI.SlicedSpriteScale); 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); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs index fdb531895..63f966936 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/VideoPlayer.cs @@ -20,7 +20,7 @@ namespace Barotrauma private GUICustomComponent videoView; private GUIButton okButton; - private Color backgroundColor = new Color(0f, 0f, 0f, 1f); + private Color backgroundColor = new Color(0f, 0f, 0f, 0.8f); private Action callbackOnStop; private Point scaledVideoResolution; @@ -62,8 +62,8 @@ namespace Barotrauma int width = scaledVideoResolution.X; int height = scaledVideoResolution.Y; - background = new GUIFrame(new RectTransform(Point.Zero, GUI.Canvas, Anchor.Center), "InnerFrame", backgroundColor); - videoFrame = new GUIFrame(new RectTransform(Point.Zero, background.RectTransform, Anchor.Center, Pivot.Center), "SonarFrame"); + background = new GUIFrame(new RectTransform(Point.Zero, GUI.Canvas, Anchor.Center), style: null, color: backgroundColor); + videoFrame = new GUIFrame(new RectTransform(Point.Zero, background.RectTransform, Anchor.Center, Pivot.Center), style: "InnerFrame"); if (useTextOnRightSide) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index eb4e8b326..a0df47916 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -480,6 +480,7 @@ namespace Barotrauma LevelGenerationParams.LoadPresets(); ScriptedEventSet.LoadPrefabs(); AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions)); + SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings)); TitleScreen.LoadState = 50.0f; yield return CoroutineStatus.Running; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs index c01beeae5..3a3635029 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs @@ -29,8 +29,7 @@ namespace Barotrauma private GUIFrame guiFrame; private GUIFrame crewArea; - private GUILayoutGroup activeCrew; - private GUIFrame crewList; + private GUIListBox crewList; private GUIButton toggleCrewButton; private float crewListOpenState; private bool toggleCrewListOpen = true; @@ -51,12 +50,15 @@ namespace Barotrauma { if (toggleCrewListOpen == value) { return; } toggleCrewListOpen = GameMain.Config.CrewMenuOpen = value; + toggleCrewButton.Children.ForEach(c => c.SpriteEffects = toggleCrewListOpen ? SpriteEffects.None : SpriteEffects.FlipHorizontally); } } + const float CommandNodeAnimDuration = 0.2f; + public List OrderOptionButtons = new List(); - private Sprite jobIndicatorBackground; + private Sprite jobIndicatorBackground, previousOrderArrow; #endregion @@ -87,16 +89,30 @@ namespace Barotrauma CanBeFocused = false }; - crewArea = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform), "", Color.Transparent) + var crewAreaWithButtons = new GUIFrame( + HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform), + style: null, + color: Color.Transparent) { CanBeFocused = false }; - // Based on the sprite dimensions - var buttonSize = new Point((int)(79.0f / 126.0f * crewArea.Rect.Height), crewArea.Rect.Height); + var buttonHeight = (int)(GUI.Scale * 40); + crewArea = new GUIFrame( + new RectTransform( + new Point(crewAreaWithButtons.Rect.Width, crewAreaWithButtons.Rect.Height - 3 * buttonHeight - 2 * HUDLayoutSettings.Padding), + crewAreaWithButtons.RectTransform, + Anchor.BottomLeft), + style: null, + color: Color.Transparent) + { + CanBeFocused = false + }; + + var buttonSize = new Point((int)(79.0f / 126.0f * (2 * buttonHeight)), 2 * buttonHeight); var commandButton = new GUIButton( - new RectTransform(buttonSize, parent: crewArea.RectTransform, anchor: Anchor.CenterRight), + new RectTransform(buttonSize, parent: crewAreaWithButtons.RectTransform), style: null) { OnClicked = (button, userData) => @@ -107,7 +123,7 @@ namespace Barotrauma }; new GUIImage( - new RectTransform(Vector2.One, parent: commandButton.RectTransform), + new RectTransform(Vector2.One, commandButton.RectTransform), new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(551, 1, 79, 126)), scaleToFit: true) { @@ -118,69 +134,36 @@ namespace Barotrauma 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( + crewList = new GUIListBox( 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) + Vector2.One, + crewArea.RectTransform), + style: null, + isScrollBarOnDefaultSide: false) { 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) + new RectTransform( + new Point(buttonHeight), + parent: crewAreaWithButtons.RectTransform) { - AbsoluteOffset = new Point(-HUDLayoutSettings.Padding, 0) + AbsoluteOffset = new Point(0, 2 * buttonHeight + HUDLayoutSettings.Padding) }, - style: null); - toggleCrewButton.OnClicked = (GUIButton btn, object userdata) => + style: "UIToggleButton") { - ToggleCrewListOpen = !ToggleCrewListOpen; - return true; - }; - - new GUIImage( - new RectTransform(Vector2.One, parent: toggleCrewButton.RectTransform), - new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(891, 135, 78, 126)), - scaleToFit: true) - { - Color = GUIColorSettings.InventorySlotColor * 0.8f, - HoverColor = GUIColorSettings.InventorySlotColor, - PressedColor = GUIColorSettings.InventorySlotColor, - SelectedColor = GUIColorSettings.InventorySlotColor * 0.8f, - ToolTip = TextManager.Get("crew") + OnClicked = (GUIButton btn, object userdata) => + { + ToggleCrewListOpen = !ToggleCrewListOpen; + return true; + } }; jobIndicatorBackground = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(0, 512, 128, 128)); + previousOrderArrow = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(128, 512, 128, 128)); #region Chatbox @@ -381,37 +364,84 @@ namespace Barotrauma characterInfos.Remove(characterInfo); } - private GUIComponent AddCharacterToActiveCrew(Character character) + private void AddCharacterToCrewList(Character character) { - int size = HUDLayoutSettings.CrewArea.Height; - int iconSize = (int)(size * 0.9f); - - var characterFrame = new GUIFrame(new RectTransform(new Point(size), activeCrew.RectTransform, Anchor.Center), style: null) + int width = crewList.Content.Rect.Width - HUDLayoutSettings.Padding; + int height = Math.Max(45, (int)((1.0f / 8.0f) * width)); + Color backgroundColor = new Color(36, 37, 34) * 0.8f; + var characterButton = new GUIButton(new RectTransform(new Point(width, height), parent: crewList.Content.RectTransform, anchor: Anchor.TopRight), style: null, color: backgroundColor) { - UserData = character, - CanBeFocused = false + UserData = character }; + characterButton.HoverColor = backgroundColor; + characterButton.PressedColor = backgroundColor; + characterButton.SelectedColor = backgroundColor; - var characterToolTip = character.Info?.Name; - if (character.Info?.Job != null) + if (IsSinglePlayer) { - characterToolTip += " (" + character.Info.Job?.Name + ")"; + characterButton.OnClicked = CharacterClicked; } - 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) + else { - UserData = character, - ToolTip = characterToolTip, - TooltipColorData = tooltipColorData + characterButton.CanBeSelected = false; + } + + var iconRelativeSize = (float)height / characterButton.Rect.Width; + + var layoutGroup = new GUILayoutGroup( + new RectTransform(Vector2.One, parent: characterButton.RectTransform), + isHorizontal: true, + childAnchor: Anchor.CenterLeft) + { + RelativeSpacing = 0.1f * iconRelativeSize, + UserData = character }; - #region Sound Icon + var jobIconBackground = new GUIImage( + new RectTransform(new Vector2(iconRelativeSize, 0.9f), layoutGroup.RectTransform), + jobIndicatorBackground, + scaleToFit: true) + { + CanBeFocused = false, + UserData = "job" + }; + + if (character?.Info?.Job.Prefab?.Icon != null) + { + new GUIImage( + new RectTransform(Vector2.One, jobIconBackground.RectTransform), + character.Info.Job.Prefab.Icon, + scaleToFit: true) + { + CanBeFocused = false, + Color = character.Info.Job.Prefab.UIColor, + HoverColor = character.Info.Job.Prefab.UIColor, + PressedColor = character.Info.Job.Prefab.UIColor, + SelectedColor = character.Info.Job.Prefab.UIColor + }; + } + + new GUITextBlock( + new RectTransform( + new Vector2(1.0f - 4.5f * iconRelativeSize - 5 * layoutGroup.RelativeSpacing, 1.0f), + layoutGroup.RectTransform), + character.Name, + textColor: character.Info?.Job?.Prefab?.UIColor) + { + OverflowClip = true + }; new GUIImage( - new RectTransform(new Vector2(0.4f), characterFrame.RectTransform, anchor: Anchor.TopRight), - sprite: GUI.Style.GetComponentStyle("GUISoundIcon").Sprites[GUIComponent.ComponentState.None].FirstOrDefault().Sprite, + new RectTransform(new Vector2(0.5f * iconRelativeSize, 0.5f), layoutGroup.RectTransform), + style: "VerticalLine"); + + var soundIcons = new GUIFrame(new RectTransform(new Vector2(iconRelativeSize, 0.8f), layoutGroup.RectTransform), style: null) + { + UserData = "soundicons" + }; + new GUIImage( + new RectTransform(Vector2.One, soundIcons.RectTransform), + GUI.Style.GetComponentStyle("GUISoundIcon").Sprites[GUIComponent.ComponentState.None].FirstOrDefault().Sprite, scaleToFit: true) { UserData = new Pair("soundicon", 0.0f), @@ -419,126 +449,14 @@ namespace Barotrauma Visible = true }; new GUIImage( - new RectTransform(new Vector2(0.5f), characterFrame.RectTransform, anchor: Anchor.TopRight), - "GUISoundIconDisabled") + new RectTransform(Vector2.One, soundIcons.RectTransform), + "GUISoundIconDisabled", + scaleToFit: true) { UserData = "soundicondisabled", CanBeFocused = true, Visible = false }; - - #endregion - - if (IsSinglePlayer) - { - characterButton.OnClicked = CharacterClicked; - } - else - { - characterButton.CanBeSelected = false; - } - - 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, - 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 - }; - } - - #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 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())) - { - CanBeFocused = false, - HoverColor = Color.White, - SelectedColor = Color.White - }; - - if (character?.Info?.Job.Prefab?.Icon != null) - { - new GUIImage( - new RectTransform(new Vector2(0.5f), characterIcon.RectTransform, anchor: Anchor.BottomLeft, pivot: Pivot.BottomLeft), - jobIndicatorBackground, - scaleToFit: true) - { - CanBeFocused = false - }; - new GUIImage( - new RectTransform(new Vector2(0.5f), characterIcon.RectTransform, anchor: Anchor.BottomLeft, pivot: Pivot.BottomLeft), - character.Info.Job.Prefab.Icon, - scaleToFit: true) - { - CanBeFocused = false, - Color = character.Info.Job.Prefab.UIColor - }; - } - - 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); - - GUITextBlock.AutoScaleAndNormalize(listBox.Content.GetAllChildren(), defaultScale: 1.0f); } /// @@ -548,32 +466,26 @@ namespace Barotrauma { if (!AllowCharacterSwitch) { return false; } Character character = selection as Character; - if (character == null || character.IsDead || character.IsUnconscious) return false; + if (character == null || character.IsDead || character.IsUnconscious) { return false; } SelectCharacter(character); + if (GUI.KeyboardDispatcher.Subscriber == crewList) { GUI.KeyboardDispatcher.Subscriber = null; } return true; } public void ReviveCharacter(Character revivedCharacter) { - if (activeCrew.GetChildByUserData(revivedCharacter) is GUIComponent characterBlock) + if (crewList.Content.GetChildByUserData(revivedCharacter) is GUIComponent characterComponent) { - characterBlock.Parent.RemoveChild(characterBlock); + crewList.Content.RemoveChild(characterComponent); } - if (characterInfos.Contains(revivedCharacter.Info)) AddCharacter(revivedCharacter); + if (characterInfos.Contains(revivedCharacter.Info)) { AddCharacter(revivedCharacter); } } public void KillCharacter(Character killedCharacter) { - if (activeCrew.GetChildByUserData(killedCharacter) is GUIComponent characterBlock) + if (crewList.Content.GetChildByUserData(killedCharacter) is GUIComponent characterComponent) { - CoroutineManager.StartCoroutine(KillCharacterAnim(characterBlock)); - } - else if (crewList.FindChild(c => c is GUIListBox) is GUIListBox listBox && - listBox.Content.GetChildByUserData(killedCharacter) is GUIComponent characterComponent) - { - listBox.Content.RemoveChild(characterComponent); - GUITextBlock.AutoScaleAndNormalize(listBox.Content.GetAllChildren(), defaultScale: 1.0f); - listBox.UpdateScrollBarSize(); + CoroutineManager.StartCoroutine(KillCharacterAnim(characterComponent)); } RemoveCharacter(killedCharacter); } @@ -584,9 +496,7 @@ namespace Barotrauma components.Add(component); components.RemoveAll(c => c.UserData is Pair pair && pair.First == "soundicon" || - c.UserData as string == "soundicondisabled" || - c is GUIButton || c is GUIFrame); - + c.UserData as string == "soundicondisabled"); components.ForEach(c => c.Color = Color.DarkRed); yield return new WaitForSeconds(1.0f); @@ -598,19 +508,15 @@ namespace Barotrauma foreach (GUIComponent comp in components) { comp.Color = Color.Lerp(Color.DarkRed, Color.Transparent, timer / hideDuration); - comp.RectTransform.LocalScale = new Vector2(1.0f - (timer / hideDuration), comp.RectTransform.LocalScale.Y); + comp.RectTransform.LocalScale = new Vector2(comp.RectTransform.LocalScale.X, 1.0f - (timer / hideDuration)); } timer += CoroutineManager.DeltaTime; yield return CoroutineStatus.Running; } - 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(); + crewList.Content.RemoveChild(component); + // GUITextBlock.AutoScaleAndNormalize(list.Content.GetAllChildren(), defaultScale: 1.0f); + crewList.UpdateScrollBarSize(); yield return CoroutineStatus.Success; } @@ -671,15 +577,18 @@ namespace Barotrauma { if (client?.Character == null) { return; } - var playerFrame = activeCrew.GetChildByUserData(client.Character) ?? AddCharacterToActiveCrew(client.Character); + var playerFrame = crewList.Content.GetChildByUserData(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; - soundIconDisabled.Visible = muted || mutedLocally; - soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally"); + if (playerFrame.FindChild(c => c is GUILayoutGroup).GetChildByUserData("soundicons") is GUIComponent soundIcons) + { + var soundIcon = soundIcons.FindChild(c => c.UserData is Pair pair && pair.First == "soundicon"); + var soundIconDisabled = soundIcons.FindChild("soundicondisabled"); + soundIcon.Visible = !muted && !mutedLocally; + soundIconDisabled.Visible = muted || mutedLocally; + soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally"); + } } public void SetClientSpeaking(Client client) @@ -689,18 +598,15 @@ namespace Barotrauma public void SetCharacterSpeaking(Character character) { - var playerFrame = activeCrew.GetChildByUserData(character); - if (playerFrame == null && character != Character.Controlled) + if (crewList.Content.GetChildByUserData(character)? + .FindChild(c => c is GUILayoutGroup)? + .GetChildByUserData("soundicons")? + .FindChild(c => c.UserData is Pair pair && pair.First == "soundicon") is GUIComponent soundIcon) { - playerFrame = AddCharacterToActiveCrew(character); + soundIcon.Color = Color.White; + Pair userdata = soundIcon.UserData as Pair; + userdata.Second = 1.0f; } - - 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; } #endregion @@ -724,14 +630,12 @@ namespace Barotrauma else { OrderChatMessage msg = new OrderChatMessage(order, "", hull, null, orderGiver); - if (GameMain.Client != null) - { - GameMain.Client.SendChatMessage(msg); - } + GameMain.Client?.SendChatMessage(msg); } } else { + DisplayPreviousCharacterOrder(character); character.SetOrder(order, option, orderGiver, speak: orderGiver != character); if (IsSinglePlayer) { @@ -741,10 +645,7 @@ namespace Barotrauma else if (orderGiver != null) { OrderChatMessage msg = new OrderChatMessage(order, option, order.TargetItemComponent?.Item, character, orderGiver); - if (GameMain.Client != null) - { - GameMain.Client.SendChatMessage(msg); - } + GameMain.Client?.SendChatMessage(msg); } DisplayCharacterOrder(character, order); } @@ -757,41 +658,102 @@ namespace Barotrauma { if (character == null) { return; } - var characterFrame = activeCrew.GetChildByUserData(character); - if (characterFrame != null && characterFrame.GetChildByUserData("order") is GUIComponent existingOrderFrame) + var characterFrame = crewList.Content.GetChildByUserData(character); + + if (characterFrame == null) { return; } + + GUILayoutGroup layoutGroup = (GUILayoutGroup)characterFrame.FindChild(c => c is GUILayoutGroup); + + if (layoutGroup.GetChildByUserData("order") is GUIComponent existingOrderFrame) { characterFrame.RemoveChild(existingOrderFrame); } - if (order == null || order == dismissedOrder) - { - if (characterFrame != null) - { - // Remove dismissed characters from active crew - activeCrew.RemoveChild(characterFrame); - activeCrew.Recalculate(); - } - return; - } + if (order == null || order == dismissedOrder) { return; } - characterFrame ??= AddCharacterToActiveCrew(character); + // TODO: Move the character to the top var orderFrame = new GUIButton( - new RectTransform(new Vector2(0.5f), characterFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter) - { - AbsoluteOffset = new Point(0, -HUDLayoutSettings.Padding) - }, + new RectTransform( + new Vector2(layoutGroup.GetChildByUserData("job").RectTransform.RelativeSize.X, 0.8f), + layoutGroup.RectTransform), style: null) { UserData = "order", OnClicked = (button, userData) => { + if (GameMain.IsMultiplayer && Character.Controlled == null) { return true; } 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); + CreateNodeIcon(orderFrame.RectTransform, order.SymbolSprite, order.Color, tooltip: order.Name); + new GUIImage( + new RectTransform(new Vector2(0.4f), orderFrame.RectTransform, anchor: Anchor.TopRight, pivot: Pivot.Center), + "GUICancelButton", + scaleToFit: true) + { + UserData = "cancel", + Visible = false + }; + orderFrame.RectTransform.RepositionChildInHierarchy(3); + } + + private void DisplayPreviousCharacterOrder(Character character) + { + if (character == null) { return; } + + var characterFrame = crewList.Content.GetChildByUserData(character); + + if (characterFrame == null) { return; } + + GUILayoutGroup layoutGroup = (GUILayoutGroup)characterFrame.FindChild(c => c is GUILayoutGroup); + + if (layoutGroup.GetChildByUserData("prevorder") is GUIComponent existingPrevOrderFrame) + { + characterFrame.RemoveChild(existingPrevOrderFrame); + } + + var order = character.CurrentOrder; + + if (order == null || order == dismissedOrder) { return; } + + + var orderOption = (character.AIController as HumanAIController)?.CurrentOrderOption; + + var prevOrderFrame = new GUIButton( + new RectTransform( + new Vector2(layoutGroup.GetChildByUserData("job").RectTransform.RelativeSize.X, 0.8f), + layoutGroup.RectTransform), + style: null) + { + UserData = "prevorder", + OnClicked = (button, userData) => + { + if (GameMain.IsMultiplayer && Character.Controlled == null) { return true; } + SetCharacterOrder(character, order, orderOption, Character.Controlled); + return true; + } + }; + + var prevOrderIconFrame = new GUIFrame( + new RectTransform(new Vector2(0.8f), prevOrderFrame.RectTransform, anchor: Anchor.BottomLeft), + style: null); + CreateNodeIcon(prevOrderIconFrame.RectTransform, order.SymbolSprite, order.Color, tooltip: order.Name); + foreach (GUIComponent c in prevOrderIconFrame.Children) + { + c.HoverColor = c.Color; + c.PressedColor = c.Color; + c.SelectedColor = c.Color; + } + new GUIImage( + new RectTransform(new Vector2(0.8f), prevOrderFrame.RectTransform, anchor: Anchor.TopRight), + previousOrderArrow, + scaleToFit: true) + { + ToolTip = order.Name + }; + prevOrderFrame.RectTransform.RepositionChildInHierarchy(layoutGroup.GetChildByUserData("order") != null ? 4 : 3); } #region Updating and drawing the UI @@ -833,7 +795,7 @@ namespace Barotrauma if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || prevUIScale != GUI.Scale) { - var previousCrewList = (GUIListBox)crewList.FindChild(c => c is GUIListBox); + var previousCrewList = crewList; InitProjectSpecific(); foreach (GUIComponent c in previousCrewList.Content.Children) @@ -910,7 +872,7 @@ namespace Barotrauma #region Command UI if (PlayerInput.KeyDown(InputType.Command) && GUI.KeyboardDispatcher.Subscriber == null && - (!GameMain.IsMultiplayer || (GameMain.IsMultiplayer && DebugConsole.CheatsEnabled)) && + (!GameMain.IsMultiplayer || (GameMain.IsMultiplayer && (Character.Controlled != null || DebugConsole.CheatsEnabled))) && commandFrame == null && !clicklessSelectionActive) { bool canIssueOrders = false; @@ -1058,51 +1020,54 @@ namespace Barotrauma { if (PlayerInput.KeyHit(InputType.Chat) && !ChatBox.InputBox.Selected) { + ChatBox.InputBox.AddToGUIUpdateList(); ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f); - ChatBox.InputBox.Select(); + ChatBox.ToggleOpen = true; + ChatBox.InputBox.Select(ChatBox.InputBox.Text.Length); } if (PlayerInput.KeyHit(InputType.RadioChat) && !ChatBox.InputBox.Selected) { + ChatBox.InputBox.AddToGUIUpdateList(); ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f); - ChatBox.InputBox.Select(); - ChatBox.InputBox.Text = "r; "; + ChatBox.ToggleOpen = true; + + if (!ChatBox.InputBox.Text.StartsWith(ChatBox.RadioChatString)) + { + ChatBox.InputBox.Text = ChatBox.RadioChatString; + } + ChatBox.InputBox.Select(ChatBox.InputBox.Text.Length); } } } crewArea.Visible = characters.Count > 0 && CharacterHealth.OpenHealthWindow == null; - var shouldBeRemoved = new List(); - foreach (GUIComponent child in activeCrew.Children) + foreach (GUIComponent child in crewList.Content.Children) { - Character character = (Character)child.UserData; - if (character == null) { continue; } - child.Visible = - Character.Controlled == null || - (Character.Controlled.TeamID == character.TeamID); - - if (child.Visible) + if (child.UserData is Character character) { - //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); - if (soundIcon.UserData is Pair soundStatus && - soundStatus.Second < 0.1f && child.FindChild("order") == null) + child.Visible = Character.Controlled == null || Character.Controlled.TeamID == character.TeamID; + if (child.Visible && child.FindChild(c => c is GUILayoutGroup) is GUILayoutGroup layoutGroup) { - shouldBeRemoved.Add(child); + if (layoutGroup.GetChildByUserData("order") is GUIComponent orderButton && + orderButton.GetChildByUserData("colorsource") is GUIComponent orderIcon && + orderButton.GetChildByUserData("cancel") is GUIComponent cancelIcon) + { + cancelIcon.Visible = GUI.IsMouseOn(orderIcon); + } + if (layoutGroup.GetChildByUserData("soundicons")? + .FindChild(c => c.UserData is Pair pair && pair.First == "soundicon") is GUIImage soundIcon) + { + VoipClient.UpdateVoiceIndicator(soundIcon, 0.0f, deltaTime); + } } } } - if (shouldBeRemoved.Any()) - { - shouldBeRemoved.ForEach(c => activeCrew.RemoveChild(c)); - activeCrew.Recalculate(); - } - crewList.RectTransform.AbsoluteOffset = Vector2.SmoothStep( - new Vector2(-HUDLayoutSettings.Padding - crewList.Rect.Width / 2.0f, -HUDLayoutSettings.Padding * 6), - new Vector2(0.0f, -HUDLayoutSettings.Padding * 6), + crewArea.RectTransform.AbsoluteOffset = Vector2.SmoothStep( + new Vector2(-crewArea.Rect.Width - HUDLayoutSettings.Padding, 0.0f), + Vector2.Zero, crewListOpenState).ToPoint(); crewListOpenState = ToggleCrewListOpen ? Math.Min(crewListOpenState + deltaTime * 2.0f, 1.0f) : @@ -1157,9 +1122,9 @@ namespace Barotrauma /// 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 const int assignmentNodeMaxCount = 9; + private int nodeDistance = (int)(GUI.Scale * 250); + private float returnNodeDistanceModifier = 0.65f; private Order dismissedOrder; private void CreateCommandUI() @@ -1176,7 +1141,7 @@ namespace Barotrauma var startNode = new GUIButton( new RectTransform(centerNodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center), style: null); - CreateNodeIcon(startNode.RectTransform, Order.StartNode, Color.White, Color.White); + CreateNodeIcon(startNode.RectTransform, Order.StartNode, Color.White); SetCenterNode(startNode); if (availableCategories == null) @@ -1197,7 +1162,19 @@ namespace Barotrauma { if (commandFrame == null) { - CreateCommandUI(); + if ((!GameMain.IsMultiplayer || (GameMain.IsMultiplayer && (Character.Controlled != null || DebugConsole.CheatsEnabled)))) + { + 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(); + } + } } else { @@ -1207,16 +1184,16 @@ namespace Barotrauma private void ScaleCommandUI() { - centerNodeSize = new Point((int)(80 * GUI.Scale)); - nodeSize = new Point((int)(80 * GUI.Scale)); + centerNodeSize = new Point((int)(100 * GUI.Scale)); + nodeSize = new Point((int)(100 * 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; + centerNodeMargin = centerNodeSize.X * 0.5f; + optionNodeMargin = nodeSize.X * 0.5f; shortcutCenterNodeMargin = shortcutCenterNodeSize.X * 0.45f; - shortcutNodeMargin = shortcutNodeSize.X * 0.6f; - returnNodeMargin = returnNodeSize.X * 0.6f; + shortcutNodeMargin = shortcutNodeSize.X * 0.5f; + returnNodeMargin = returnNodeSize.X * 0.5f; nodeDistance = (int)(150 * GUI.Scale); } @@ -1265,8 +1242,7 @@ namespace Barotrauma 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"); } + var colorSource = endNode.GetChildByUserData("colorsource"); if ((selectedNode == null && endNode != shortcutCenterNode && GUI.IsMouseOn(endNode)) || endNode == selectedNode || endNode == shortcutCenterNode && shortcutNodes.Any(n => GUI.IsMouseOn(n))) { @@ -1345,8 +1321,8 @@ namespace Barotrauma private void SetCenterNode(GUIButton node) { node.RectTransform.Parent = commandFrame.RectTransform; - node.RectTransform.NonScaledSize = centerNodeSize; - node.RectTransform.AbsoluteOffset = Point.Zero; + node.RectTransform.MoveOverTime(Point.Zero, CommandNodeAnimDuration); + node.RectTransform.ScaleOverTime(centerNodeSize, CommandNodeAnimDuration); foreach (GUIComponent c in node.Children) { c.Color = c.HoverColor * nodeColorMultiplier; @@ -1361,8 +1337,8 @@ namespace Barotrauma private void SetReturnNode(GUIButton node, Point offset) { - node.RectTransform.NonScaledSize = returnNodeSize; - node.RectTransform.AbsoluteOffset = offset; + node.RectTransform.MoveOverTime(offset, CommandNodeAnimDuration); + node.RectTransform.ScaleOverTime(returnNodeSize, CommandNodeAnimDuration); foreach (GUIComponent c in node.Children) { c.HoverColor = c.Color * (1 / nodeColorMultiplier); @@ -1424,21 +1400,19 @@ namespace Barotrauma private void CreateOrderCategoryNode(OrderCategory category, Point offset) { var node = new GUIButton( - new RectTransform(nodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center) - { - AbsoluteOffset = offset - }, - style: null) + new RectTransform(nodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center), style: null) { UserData = category, OnClicked = NavigateForward }; + + node.RectTransform.MoveOverTime(offset, CommandNodeAnimDuration); 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); + CreateNodeIcon(node.RectTransform, sprite, Color.White, tooltip: tooltip); } optionNodes.Add(node); } @@ -1516,7 +1490,7 @@ namespace Barotrauma AbsoluteOffset = new Point(0, (int)(1.25f * nodeDistance)) }, style: null); - CreateNodeIcon(shortcutCenterNode.RectTransform, Order.ShortcutNode, Color.Red, Color.Red, createContainer: false); + CreateNodeIcon(shortcutCenterNode.RectTransform, Order.ShortcutNode, Color.Red); foreach (GUIComponent c in shortcutCenterNode.Children) { c.HoverColor = c.Color; @@ -1547,14 +1521,13 @@ namespace Barotrauma 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) + new RectTransform(size, parent: parent, anchor: Anchor.Center), style: null) { UserData = order }; + + node.RectTransform.MoveOverTime(offset, CommandNodeAnimDuration); + var hasOptions = order.ItemComponentType != null || order.ItemIdentifiers.Length > 0 || order.Options.Length > 1; node.OnClicked = (button, userData) => { @@ -1576,7 +1549,7 @@ namespace Barotrauma } return true; }; - CreateNodeIcon(node.RectTransform, order.SymbolSprite, order.Color, order.Color, + CreateNodeIcon(node.RectTransform, order.SymbolSprite, order.Color, tooltip: hasOptions ? order.Name : order.Name + "\nLMB: " + TextManager.Get("commandui.quickassigntooltip") + "\nRMB: " + TextManager.Get("commandui.manualassigntooltip")); return node; @@ -1748,7 +1721,7 @@ namespace Barotrauma }; if (order.Prefab.OptionSprites.TryGetValue(option, out Sprite sprite)) { - CreateNodeIcon(node.RectTransform, sprite, order.Color, order.Color, + CreateNodeIcon(node.RectTransform, sprite, order.Color, tooltip: optionName + "\nLMB: " + TextManager.Get("commandui.quickassigntooltip") + "\nRMB: " + TextManager.Get("commandui.manualassigntooltip")); } return node; @@ -1787,7 +1760,7 @@ namespace Barotrauma }; if (order.Item1.Prefab.OptionSprites.TryGetValue(order.Item2, out Sprite sprite)) { - CreateNodeIcon(optionNode.RectTransform, sprite, order.Item1.Color, order.Item1.Color, tooltip: order.Item2); + CreateNodeIcon(optionNode.RectTransform, sprite, order.Item1.Color, tooltip: order.Item2); } SetCenterNode(optionNode); node = null; @@ -1801,7 +1774,8 @@ namespace Barotrauma var needToExpand = characters.Count > assignmentNodeMaxCount + 1; var nodeCount = needToExpand ? assignmentNodeMaxCount + 1 : characters.Count; - var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, + var extraNodeDistance = Math.Max(nodeCount - 6, 0) * (GUI.Scale * 30); + var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance + extraNodeDistance, GetCircumferencePointCount(nodeCount), GetFirstNodeAngle(nodeCount)); @@ -1827,7 +1801,7 @@ namespace Barotrauma UserData = order, OnClicked = ExpandAssignmentNodes }; - CreateNodeIcon(expandNode.RectTransform, Order.ExpandNode, order.Item1.Color, order.Item1.Color, tooltip: TextManager.Get("commandui.expand")); + CreateNodeIcon(expandNode.RectTransform, Order.ExpandNode, order.Item1.Color, tooltip: TextManager.Get("commandui.expand")); } private bool ExpandAssignmentNodes(GUIButton node, object userData) @@ -1840,7 +1814,8 @@ namespace Barotrauma }; var order = userData as Tuple; - var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance * 2, + // TODO: The value 100 should be determined by how large the inner circle is + var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, (nodeDistance + GUI.Scale * 100) * 1.55f, GetCircumferencePointCount(extraOptionCharacters.Count), GetFirstNodeAngle(extraOptionCharacters.Count)); for (int i = 0; i < extraOptionCharacters.Count; i++) @@ -1854,10 +1829,7 @@ namespace Barotrauma { // Button var node = new GUIButton( - new RectTransform(nodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center) - { - AbsoluteOffset = offset - }, + new RectTransform(nodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center), style: null) { OnClicked = (button, userData) => @@ -1867,6 +1839,9 @@ namespace Barotrauma return true; } }; + + node.RectTransform.MoveOverTime(offset, CommandNodeAnimDuration); + // Character icon new GUICustomComponent( new RectTransform(Vector2.One, node.RectTransform), @@ -1884,41 +1859,14 @@ namespace Barotrauma 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 + ")" + ToolTip = character.Info.DisplayName + " (" + character.Info.Job.Name + ")", + UserData = "colorsource" }; (extraOption ? extraOptionNodes : optionNodes).Add(node); } - private void CreateNodeIcon(RectTransform parent, Sprite sprite, Color iconColor, Color containerColor, string tooltip = null, bool createContainer = true) + private void CreateNodeIcon(RectTransform parent, Sprite sprite, Color iconColor, string tooltip = null) { - 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), @@ -1930,7 +1878,7 @@ namespace Barotrauma PressedColor = iconColor, SelectedColor = iconColor, ToolTip = tooltip, - UserData = "icon" + UserData = "colorsource" }; } @@ -1975,6 +1923,7 @@ namespace Barotrauma return characters.FindAll(c => c != Character.Controlled) .OrderByDescending(c => c.CurrentOrder == null || c.CurrentOrder == dismissedOrder) .ThenByDescending(c => order.HasAppropriateJob(c)) + .ThenBy(c => c.CurrentOrder?.Weight) .FirstOrDefault(); } @@ -1983,15 +1932,15 @@ namespace Barotrauma if (order.Identifier == "follow") { return characters.FindAll(c => c != Character.Controlled) - .OrderBy(c => c.CurrentOrder == null || c.CurrentOrder == dismissedOrder) - .ThenBy(c => order.HasAppropriateJob(c)) + .OrderByDescending(c => c.CurrentOrder == null || c.CurrentOrder == dismissedOrder) .ToList(); } else { - return characters.OrderBy(c => c.CurrentOrder == null || c.CurrentOrder == dismissedOrder) - .ThenBy(c => order.HasAppropriateJob(c)) - .ToList(); + return characters.OrderByDescending(c => c.CurrentOrder == null || c.CurrentOrder == dismissedOrder) + .ThenByDescending(c => order.HasAppropriateJob(c)) + .ThenBy(c => c.CurrentOrder?.Weight) + .ToList(); } } @@ -2149,7 +2098,7 @@ namespace Barotrauma public void InitSinglePlayerRound() { - activeCrew.ClearChildren(); + crewList.ClearChildren(); characters.Clear(); WayPoint[] waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub); @@ -2185,14 +2134,14 @@ namespace Barotrauma characterInfos.RemoveAll(c => c.Character == null || c.Character.Removed || c.CauseOfDeath != null); characters.Clear(); - activeCrew.ClearChildren(); + crewList.ClearChildren(); } public void Reset() { characters.Clear(); characterInfos.Clear(); - activeCrew.ClearChildren(); + crewList.ClearChildren(); } public void Save(XElement parentElement) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs index 8947b90f7..ba5551d9d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/MechanicTutorial.cs @@ -98,7 +98,7 @@ namespace Barotrauma.Tutorials var repairOrder = Order.GetPrefab("repairsystems"); mechanic_repairIcon = repairOrder.SymbolSprite; mechanic_repairIconColor = repairOrder.Color; - mechanic_weldIcon = new Sprite("Content/UI/IconAtlas.png", new Rectangle(1, 256, 127, 127), new Vector2(0.5f, 0.5f)); + mechanic_weldIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(1, 256, 127, 127), new Vector2(0.5f, 0.5f)); // Other tutorial items tutorial_securityFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_securityfinaldoorlight")).GetComponent(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs index 54027a35d..a520f11cd 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs @@ -95,14 +95,14 @@ namespace Barotrauma limbSlotIcons = new Dictionary(); int margin = 2; - 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.Headset, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(384 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2))); + limbSlotIcons.Add(InvSlotType.InnerClothes, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(512 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2))); + limbSlotIcons.Add(InvSlotType.Card, new Sprite("Content/UI/MainIconsAtlas.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/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))); + limbSlotIcons.Add(InvSlotType.Head, new Sprite("Content/UI/MainIconsAtlas.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(634, 0, 128, 128))); + limbSlotIcons.Add(InvSlotType.RightHand, new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(762, 0, 128, 128))); + limbSlotIcons.Add(InvSlotType.OuterClothes, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(256 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2))); } SlotPositions = new Vector2[SlotTypes.Length]; CurrentLayout = Layout.Default; @@ -165,7 +165,7 @@ namespace Barotrauma slots[i] = new InventorySlot(slotRect) { - SubInventoryDir = Math.Sign(HUDLayoutSettings.InventoryAreaUpper.Bottom - slotRect.Center.Y), + SubInventoryDir = Math.Sign(GameMain.GraphicsHeight / 2 - slotRect.Center.Y), Disabled = false, SlotSprite = slotSprite, Color = SlotTypes[i] == InvSlotType.Any ? Color.White * 0.2f : Color.White * 0.4f @@ -532,7 +532,7 @@ namespace Barotrauma } } - if (character.SelectedCharacter == null) // Permanently open subinventories only available when the default UI layout is in use -> not when grabbing characters + if (character == Character.Controlled && character.SelectedCharacter == null) // Permanently open subinventories only available when the default UI layout is in use -> not when grabbing characters { //remove the highlighted slots of other characters' inventories when not grabbing anyone highlightedSubInventorySlots.RemoveWhere(s => s.ParentInventory != this && s.ParentInventory?.Owner is Character); @@ -622,32 +622,11 @@ namespace Barotrauma } var quickUseAction = GetQuickUseAction(item, allowEquip: true, allowInventorySwap: false, allowApplyTreatment: false); - slot.QuickUseButtonToolTip = quickUseAction == QuickUseAction.None ? + + if (quickUseAction != QuickUseAction.Drop) + { + slot.QuickUseButtonToolTip = quickUseAction == QuickUseAction.None ? "" : TextManager.GetWithVariable("QuickUseAction." + quickUseAction.ToString(), "[equippeditem]", character.SelectedItems.FirstOrDefault(i => i != null)?.Name); - - //equipped item that can't be put in the inventory, use delayed dropping - if (quickUseAction == QuickUseAction.Drop) - { - slot.QuickUseButtonToolTip = - TextManager.Get("QuickUseAction.HoldToUnequip", returnNull: true) ?? - (GameMain.Config.Language == "English" ? "Hold to unequip" : TextManager.Get("QuickUseAction.Unequip")); - - if (PlayerInput.LeftButtonHeld()) - { - slot.QuickUseTimer = Math.Max(0.1f, slot.QuickUseTimer + deltaTime); - if (slot.QuickUseTimer >= 1.0f) - { - item.Drop(Character.Controlled); - GUI.PlayUISound(GUISoundType.DropItem); - } - } - else - { - slot.QuickUseTimer = Math.Max(0.0f, slot.QuickUseTimer - deltaTime * 5.0f); - } - } - else - { if (PlayerInput.PrimaryMouseButtonDown()) slot.EquipButtonState = GUIComponent.ComponentState.Pressed; if (PlayerInput.PrimaryMouseButtonClicked()) { @@ -994,13 +973,13 @@ namespace Barotrauma } if (Locked) { color *= 0.3f; } - var quickUseIndicator = Items[i].AllowedSlots.Any(a => a == InvSlotType.Any) ? - EquipIndicator : DropIndicator; - var quickUseHighlight = Items[i].AllowedSlots.Any(a => a == InvSlotType.Any) ? - EquipIndicatorHighlight : DropIndicatorHighlight; + if (!Items[i].AllowedSlots.Any(a => a == InvSlotType.Any)) + { + continue; + } - quickUseIndicator.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color, quickUseIndicator.Origin, 0, UIScale); - slots[i].QuickUseTimer = Math.Min(slots[i].QuickUseTimer, 1.0f); + EquipIndicator.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color, EquipIndicator.Origin, 0, UIScale); + /*slots[i].QuickUseTimer = Math.Min(slots[i].QuickUseTimer, 1.0f); if (slots[i].QuickUseTimer > 0.0f) { float indicatorFillAmount = character.HasEquippedItem(Items[i]) ? 1.0f - slots[i].QuickUseTimer : slots[i].QuickUseTimer; @@ -1012,9 +991,9 @@ namespace Barotrauma null, Vector2.One * UIScale * 0.85f); } - else if (character.HasEquippedItem(Items[i])) + else*/ if (character.HasEquippedItem(Items[i])) { - quickUseHighlight.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color * 0.9f, quickUseHighlight.Origin, 0, UIScale * 0.85f); + EquipIndicatorHighlight.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color * 0.9f, EquipIndicatorHighlight.Origin, 0, UIScale * 0.85f); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs index e1703048e..59189e560 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs @@ -117,33 +117,38 @@ namespace Barotrauma.Items.Components else { //if a GUIFrame has been defined, draw the inventory inside it - - 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) - { - CanBeFocused = false - }; - Inventory.RectTransform = guiCustomComponent.RectTransform; + CreateGUI(); + GameMain.Instance.OnResolutionChanged += () => { GuiFrame.ClearChildren(); CreateGUI(); }; } } + private void CreateGUI() + { + 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) + { + CanBeFocused = false + }; + Inventory.RectTransform = guiCustomComponent.RectTransform; + } + public string GetUILabel() { if (UILabel == string.Empty) { return string.Empty; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs index 92a0ff8d3..b3955b14a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Deconstructor.cs @@ -22,68 +22,99 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific(XElement element) { - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + CreateGUI(); + GameMain.Instance.OnResolutionChanged += () => { - Stretch = true, + GuiFrame.ClearChildren(); + CreateGUI(); + OnItemLoadedProjSpecific(); + }; + } + + private void CreateGUI() + { + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.90f, 0.80f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + { + Stretch = true, RelativeSpacing = 0.02f }; 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)); + + // === INPUT LABEL === // + var inputLabelArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.15f), topFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.05f + }; + var inputLabel = new GUITextBlock(new RectTransform(Vector2.One, inputLabelArea.RectTransform), TextManager.Get("uilabel.input"), font: GUI.SubHeadingFont) { Padding = Vector4.Zero }; + inputLabel.RectTransform.Resize(new Point((int) inputLabel.Font.MeasureString(inputLabel.Text).X, inputLabel.RectTransform.Rect.Height)); + new GUIFrame(new RectTransform(Vector2.One, inputLabelArea.RectTransform), style: "HorizontalLine"); - - 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 - }; + var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1.2f), topFrame.RectTransform, Anchor.CenterLeft), childAnchor: Anchor.BottomLeft, isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f }; + + // === INPUT SLOTS === // + 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 }; - 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 - }; + // === ACTIVATE BUTTON === // + var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.75f), inputArea.RectTransform), childAnchor: Anchor.CenterLeft); + activateButton = new GUIButton(new RectTransform(new Vector2(0.95f, 0.65f), buttonContainer.RectTransform), TextManager.Get("DeconstructorDeconstruct"), style: "DeviceButton") + { + TextBlock = { AutoScaleHorizontal = true }, + OnClicked = ToggleActive + }; + inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), + TextManager.Get("DeconstructorNoPower"), textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow") + { + HoverColor = Color.Black, + IgnoreLayoutGroups = true, + Visible = false, + CanBeFocused = false + }; - - inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), TextManager.Get("DeconstructorNoPower"), - textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow") - { - HoverColor = Color.Black, - IgnoreLayoutGroups = true, - Visible = false, - CanBeFocused = false - }; - + // === OUTPUT AREA === // 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)); + + // === OUTPUT LABEL === // + var outputLabelArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.15f), bottomFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.05f + }; + var outputLabel = new GUITextBlock(new RectTransform(new Vector2(0f, 1.0f), outputLabelArea.RectTransform), TextManager.Get("uilabel.output"), font: GUI.SubHeadingFont) { Padding = Vector4.Zero }; + outputLabel.RectTransform.Resize(new Point((int) outputLabel.Font.MeasureString(outputLabel.Text).X, outputLabel.RectTransform.Rect.Height)); + new GUIFrame(new RectTransform(Vector2.One, outputLabelArea.RectTransform), style: "HorizontalLine"); - - outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.2f), bottomFrame.RectTransform, Anchor.CenterLeft), style: null); + // === OUTPUT SLOTS === // + outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.2f), bottomFrame.RectTransform, Anchor.CenterLeft), style: null); + } + + public override bool Select(Character character) + { + // TODO, This works fine as of now but if GUI.PreventElementOverlap ever gets fixed this block of code may become obsolete or detrimental. + // Only do this if there's only one linked component. If you link more containers then may + // GUI.PreventElementOverlap have mercy on your HUD layout + if (item.linkedTo.Count(entity => entity is Item item && item.DisplaySideBySideWhenLinked) == 1) + { + foreach (MapEntity linkedTo in item.linkedTo) + { + if (!(linkedTo is Item linkedItem)) continue; + if (!linkedItem.Components.Any()) continue; + + var itemContainer = linkedItem.Components.First(); + if (itemContainer == null) { continue; } + + if (!itemContainer.Item.DisplaySideBySideWhenLinked) continue; + + // how much spacing do we want between the components + var padding = (int) (8 * GUI.Scale); + // Move the linked container to the right and move the fabricator to the left + itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(GuiFrame.Rect.Width / -2 - padding, 0); + GuiFrame.RectTransform.AbsoluteOffset = new Point(itemContainer.GuiFrame.Rect.Width / 2 + padding, 0); + } + } + return base.Select(character); } partial void OnItemLoadedProjSpecific() diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Engine.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Engine.cs index b7a639180..cadfb6011 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Engine.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Engine.cs @@ -59,7 +59,7 @@ namespace Barotrauma.Items.Components string powerLabel = TextManager.Get("EngineForce"); 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, + AutoScaleHorizontal = true, TextGetter = () => { return TextManager.AddPunctuation(':', powerLabel, (int)(targetForce) + " %"); } }; forceSlider = new GUIScrollBar(new RectTransform(new Vector2(0.95f, 0.45f), sliderArea.RectTransform, Anchor.Center), barSize: 0.1f, style: "DeviceSlider") diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs index bd9ef0053..4f7b83564 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs @@ -5,6 +5,7 @@ using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; +using System.Reflection.Metadata; namespace Barotrauma.Items.Components { @@ -25,7 +26,6 @@ namespace Barotrauma.Items.Components private GUIComponent outputSlot; private GUIComponent inputInventoryHolder, outputInventoryHolder; - private GUICustomComponent inputInventoryOverlay, outputInventoryOverlay; public FabricationRecipe SelectedItem { @@ -41,95 +41,125 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific() { - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + CreateGUI(); + GameMain.Instance.OnResolutionChanged += () => + { + GuiFrame.ClearChildren(); + CreateGUI(); + OnItemLoadedProjSpecific(); + }; + } + + private void CreateGUI() + { + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter); + + // === LABEL === // + new GUITextBlock(new RectTransform(new Vector2(1f, 0.05f), paddedFrame.RectTransform), item.Name, font: GUI.SubHeadingFont) + { + TextAlignment = Alignment.Center, + AutoScaleVertical = true + }; + + var mainFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), paddedFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) { RelativeSpacing = 0.02f }; - var topFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.7f), paddedFrame.RectTransform), "InnerFrameDark"); + // === TOP AREA === + var topFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.65f), mainFrame.RectTransform), style: "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)) - { - 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; }; + // === ITEM LIST === + var itemListFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), topFrame.RectTransform), childAnchor: Anchor.Center); + var paddedItemFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), itemListFrame.RectTransform)) + { + Stretch = true, + RelativeSpacing = 0.03f + }; + var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedItemFrame.RectTransform), isHorizontal: true) + { + Stretch = true, + RelativeSpacing = 0.03f, + UserData = "filterarea" + }; + new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), filterArea.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.SubHeadingFont) + { + Padding = Vector4.Zero, + AutoScaleVertical = true + }; + itemFilterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), createClearButton: true); + itemFilterBox.OnTextChanged += (textBox, text) => + { + FilterEntities(text); + return true; + }; + filterArea.RectTransform.MaxSize = new Point(int.MaxValue, itemFilterBox.Rect.Height); - itemList = new GUIListBox(new RectTransform(new Vector2(1f, 0.85f), itemListFrame.RectTransform), style: null) - { - OnSelected = (component, userdata) => + itemList = new GUIListBox(new RectTransform(new Vector2(1f, 0.9f), paddedItemFrame.RectTransform), style: null) + { + OnSelected = (component, userdata) => + { + selectedItem = userdata as FabricationRecipe; + if (selectedItem != null) SelectItem(Character.Controlled, selectedItem); + return true; + } + }; + + // === SEPARATOR === // + new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), topFrame.RectTransform, Anchor.Center), style: "VerticalLine"); + + // === OUTPUT AREA === // + var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1f), topFrame.RectTransform, Anchor.TopRight), childAnchor: Anchor.Center); + var paddedOutputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), outputArea.RectTransform)); + var outputTopArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5F), paddedOutputArea.RectTransform, Anchor.Center), isHorizontal: true); + // === OUTPUT SLOT === // + outputSlot = new GUIFrame(new RectTransform(new Vector2(0.4f, 1f), outputTopArea.RectTransform), style: null); + outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.2f), outputSlot.RectTransform, Anchor.BottomCenter), style: null); + new GUICustomComponent(new RectTransform(Vector2.One, outputInventoryHolder.RectTransform), DrawOutputOverLay) { CanBeFocused = false }; + // === DESCRIPTION === // + selectedItemFrame = new GUIFrame(new RectTransform(new Vector2(0.6f, 1f), outputTopArea.RectTransform), style: null); + // === REQUIREMENTS === // + selectedItemReqsFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedOutputArea.RectTransform), style: null); + + // === BOTTOM AREA === // + var bottomFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.3f), mainFrame.RectTransform), style: null); + + // === SEPARATOR === // + var separatorArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.15f), bottomFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true) { - 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"); + Stretch = true, + RelativeSpacing = 0.03f + }; + var inputLabel = new GUITextBlock(new RectTransform(Vector2.One, separatorArea.RectTransform), TextManager.Get("uilabel.input"), font: GUI.SubHeadingFont) { Padding = Vector4.Zero }; + inputLabel.RectTransform.Resize(new Point((int) inputLabel.Font.MeasureString(inputLabel.Text).X, inputLabel.RectTransform.Rect.Height)); + new GUIFrame(new RectTransform(Vector2.One, separatorArea.RectTransform), style: "HorizontalLine"); - 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, - 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 }; + // === INPUT AREA === // + var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1f), bottomFrame.RectTransform, Anchor.BottomCenter), isHorizontal: true, childAnchor: Anchor.BottomLeft); + + // === INPUT SLOTS === // + inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.8f, 1f), inputArea.RectTransform), style: null); + new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawInputOverLay) { CanBeFocused = false }; + // === ACTIVATE BUTTON === // + var buttonFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 0.8f), inputArea.RectTransform), childAnchor: Anchor.CenterRight); + activateButton = new GUIButton(new RectTransform(new Vector2(1f, 0.6f), buttonFrame.RectTransform), + TextManager.Get("FabricatorCreate"), style: "DeviceButton") + { + OnClicked = StartButtonClicked, + UserData = selectedItem, + Enabled = false + }; + // === POWER WARNING === // + inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), + TextManager.Get("FabricatorNoPower"), textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow") + { + HoverColor = Color.Black, + IgnoreLayoutGroups = true, + Visible = false, + CanBeFocused = false + }; CreateRecipes(); - - 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, - Enabled = false - }; - - inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform), TextManager.Get("FabricatorNoPower"), - textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow") - { - HoverColor = Color.Black, - IgnoreLayoutGroups = true, - Visible = false, - CanBeFocused = false - }; } partial void CreateRecipes() @@ -138,30 +168,34 @@ namespace Barotrauma.Items.Components foreach (FabricationRecipe fi in fabricationRecipes) { - GUIFrame frame = new GUIFrame(new RectTransform(new Point(itemList.Rect.Width, (int)(30 * GUI.yScale)), itemList.Content.RectTransform), style: null) + var frame = new GUIFrame(new RectTransform(new Point(itemList.Rect.Width, (int)(40 * GUI.yScale)), itemList.Content.RectTransform), style: null) { UserData = fi, HoverColor = Color.Gold * 0.2f, SelectedColor = Color.Gold * 0.5f, ToolTip = fi.TargetItem.Description }; + + var container = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform), + childAnchor: Anchor.CenterLeft, isHorizontal: true) { RelativeSpacing = 0.02f }; + + var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite; + if (itemIcon != null) + { + new GUIImage(new RectTransform(new Point(frame.Rect.Height,frame.Rect.Height), container.RectTransform), + itemIcon, scaleToFit: true) + { + Color = fi.TargetItem.InventoryIconColor, + ToolTip = fi.TargetItem.Description + }; + } - new GUITextBlock(new RectTransform(Vector2.Zero, frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point((int)(50 * GUI.xScale), 0) }, - fi.DisplayName) - { - ToolTip = fi.TargetItem.Description - }; - - var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite; - if (itemIcon != null) - { - 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, - ToolTip = fi.TargetItem.Description - }; - } + new GUITextBlock(new RectTransform(new Vector2(0.85f, 1f), container.RectTransform), fi.DisplayName) + { + Padding = Vector4.Zero, + AutoScaleVertical = true, + ToolTip = fi.TargetItem.Description + }; } } @@ -175,6 +209,29 @@ namespace Barotrauma.Items.Components partial void SelectProjSpecific(Character character) { + // TODO, This works fine as of now but if GUI.PreventElementOverlap ever gets fixed this block of code may become obsolete or detrimental. + // Only do this if there's only one linked component. If you link more containers then may + // GUI.PreventElementOverlap have mercy on your HUD layout + if (item.linkedTo.Count(entity => entity is Item item && item.DisplaySideBySideWhenLinked) == 1) + { + foreach (MapEntity linkedTo in item.linkedTo) + { + if (!(linkedTo is Item linkedItem)) continue; + if (!linkedItem.Components.Any()) continue; + + var itemContainer = linkedItem.Components.First(); + if (itemContainer == null) { continue; } + + if (!itemContainer.Item.DisplaySideBySideWhenLinked) continue; + + // how much spacing do we want between the components + var padding = (int) (8 * GUI.Scale); + // Move the linked container to the right and move the fabricator to the left + itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(GuiFrame.Rect.Width / -2 - padding, 0); + GuiFrame.RectTransform.AbsoluteOffset = new Point(itemContainer.GuiFrame.Rect.Width / 2 + padding, 0); + } + } + var nonItems = itemList.Content.Children.Where(c => !(c.UserData is FabricationRecipe)).ToList(); nonItems.ForEach(i => itemList.Content.RemoveChild(i)); @@ -197,7 +254,7 @@ 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: GUI.Style.Green, font: GUI.SubHeadingFont) { - AutoScale = true, + AutoScaleHorizontal = true, CanBeFocused = false }; sufficientSkillsText.RectTransform.SetAsFirstChild(); @@ -205,7 +262,7 @@ namespace Barotrauma.Items.Components 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, font: GUI.SubHeadingFont) { - AutoScale = true, + AutoScaleHorizontal = true, CanBeFocused = false }; var firstinSufficient = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe fabricableItem && DegreeOfSuccess(character, fabricableItem.RequiredSkills) < 0.5f); @@ -361,7 +418,7 @@ namespace Barotrauma.Items.Components selectedItemReqsFrame.ClearChildren(); 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 paddedReqFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.9f), selectedItemReqsFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.03f }; /*var itemIcon = selectedItem.TargetItem.InventoryIcon ?? selectedItem.TargetItem.sprite; if (itemIcon != null) @@ -375,7 +432,7 @@ namespace Barotrauma.Items.Components var nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), selectedItem.TargetItem.Name, textAlignment: Alignment.CenterLeft, textColor: Color.Aqua, font: GUI.SubHeadingFont) { - AutoScale = true + AutoScaleHorizontal = true }; nameBlock.Padding = new Vector4(0, nameBlock.Padding.Y, nameBlock.Padding.Z, nameBlock.Padding.W); @@ -409,7 +466,7 @@ namespace Barotrauma.Items.Components 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, + AutoScaleHorizontal = true, }; foreach (Skill skill in selectedItem.RequiredSkills) { @@ -427,7 +484,7 @@ namespace Barotrauma.Items.Components 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, + AutoScaleHorizontal = true, }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), ToolBox.SecondsToReadableTime(requiredTime), @@ -506,8 +563,10 @@ namespace Barotrauma.Items.Components activateButton.Enabled = canBeFabricated; } - child.GetChild().TextColor = Color.White * (canBeFabricated ? 1.0f : 0.5f); - child.GetChild().Color = itemPrefab.TargetItem.InventoryIconColor * (canBeFabricated ? 1.0f : 0.5f); + var childContainer = child.GetChild(); + + childContainer.GetChild().TextColor = Color.White * (canBeFabricated ? 1.0f : 0.5f); + childContainer.GetChild().Color = itemPrefab.TargetItem.InventoryIconColor * (canBeFabricated ? 1.0f : 0.5f); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs index 75580ab4f..cb72b3f01 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/MiniMap.cs @@ -26,6 +26,7 @@ namespace Barotrauma.Items.Components noPowerTip = TextManager.Get("SteeringNoPowerTip"); GuiFrame.RectTransform.RelativeOffset = new Vector2(0.05f, 0.0f); + GuiFrame.CanBeFocused = true; 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); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs index 1244202f7..f0384d4b5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs @@ -55,7 +55,7 @@ namespace Barotrauma.Items.Components { CanBeFocused = false }; - powerLight.TextBlock.AutoScale = true; + powerLight.TextBlock.AutoScaleHorizontal = true; powerLight.TextBlock.OverrideTextColor(GUI.Style.TextColor); PowerButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.75f), paddedPowerArea.RectTransform, Anchor.TopCenter) { @@ -83,14 +83,14 @@ namespace Barotrauma.Items.Components { CanBeFocused = false }; - autoControlIndicator.TextBlock.AutoScale = true; + autoControlIndicator.TextBlock.AutoScaleHorizontal = true; autoControlIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); 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 + AutoScaleHorizontal = true }; string pumpSpeedStr = TextManager.Get("PumpSpeed"); pumpSpeedText.TextGetter = () => { return TextManager.AddPunctuation(':', pumpSpeedStr, (int)flowPercentage + " %"); }; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs index 71b31a810..6a204d051 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs @@ -75,7 +75,7 @@ namespace Barotrauma.Items.Components 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) + GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, isHorizontal: true) { @@ -90,6 +90,7 @@ namespace Barotrauma.Items.Components }; GUILayoutGroup columnRight = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1.0f), paddedFrame.RectTransform)) { + CanBeFocused = true, RelativeSpacing = 0.012f, Stretch = true }; @@ -104,7 +105,7 @@ namespace Barotrauma.Items.Components RelativeOffset = new Vector2(-0.02f, 0) }, style: "ItemUI"); - GUILayoutGroup inventoryContent = new GUILayoutGroup(new RectTransform(inventoryWindow.Rect.Size - GUIStyle.ItemFrameMargin.Multiply(0.75f), inventoryWindow.RectTransform, Anchor.Center) + GUILayoutGroup inventoryContent = new GUILayoutGroup(new RectTransform(inventoryWindow.Rect.Size - GUIStyle.ItemFrameMargin, inventoryWindow.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, childAnchor: Anchor.TopCenter) { @@ -126,6 +127,7 @@ namespace Barotrauma.Items.Components RelativeSpacing = 0.02f }; + 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") @@ -142,16 +144,14 @@ namespace Barotrauma.Items.Components { CanBeFocused = false }; - criticalHeatWarning.TextBlock.OverrideTextColor(GUI.Style.TextColor); - lowTemperatureWarning.TextBlock.OverrideTextColor(GUI.Style.TextColor); - criticalOutputWarning.TextBlock.OverrideTextColor(GUI.Style.TextColor); - + List indicatorLights = new List() { criticalHeatWarning, lowTemperatureWarning, criticalOutputWarning }; + indicatorLights.ForEach(l => l.TextBlock.OverrideTextColor(GUI.Style.TextColor)); 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 relativeTextSize = new Vector2(0.9f, 0.2f); Vector2 sliderSize = new Vector2(1.0f, 0.125f); Vector2 meterSize = new Vector2(1, 1 - relativeTextSize.Y - relativeYMargin - sliderSize.Y - 0.1f); @@ -162,7 +162,7 @@ namespace Barotrauma.Items.Components 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 + AutoScaleHorizontal = true }; var fissionMeter = new GUICustomComponent(new RectTransform(meterSize, leftArea.RectTransform, Anchor.TopCenter) { @@ -176,7 +176,7 @@ namespace Barotrauma.Items.Components 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 + AutoScaleHorizontal = true }; GUITextBlock.AutoScaleAndNormalize(turbineOutputTextBox, fissionRateTextBox); @@ -248,11 +248,12 @@ namespace Barotrauma.Items.Components Font = GUI.SubHeadingFont, CanBeFocused = false }; - b.TextBlock.Wrap = false; warningButtons.Add(text, b); } upperButtons.Recalculate(); lowerButtons.Recalculate(); + //only wrap texts that consist of multiple words and are way too big to fit otherwise + warningButtons.Values.ForEach(b => b.TextBlock.Wrap = b.Text.Contains(' ') && b.TextBlock.TextSize.X > b.TextBlock.Rect.Width * 1.5f); GUITextBlock.AutoScaleAndNormalize(warningButtons.Values.Select(b => b.TextBlock)); //---------------------------------------------------------- @@ -266,6 +267,7 @@ namespace Barotrauma.Items.Components Stretch = true, RelativeSpacing = 0.02f }; + topRightArea.RectTransform.MinSize = new Point(0, topLeftArea.Rect.Height); topRightArea.RectTransform.MaxSize = new Point(int.MaxValue, topLeftArea.Rect.Height); new GUIFrame(new RectTransform(new Vector2(0.01f, 1.0f), topRightArea.RectTransform), style: "VerticalLine"); @@ -284,12 +286,12 @@ namespace Barotrauma.Items.Components } }; AutoTempSwitch.RectTransform.MaxSize = new Point((int)(AutoTempSwitch.Rect.Height * 0.4f), int.MaxValue); - + 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, + CanBeFocused = false, Selected = AutoTemp }; autoTempLight.RectTransform.MaxSize = new Point(int.MaxValue, criticalHeatWarning.Rect.Height); @@ -300,13 +302,14 @@ namespace Barotrauma.Items.Components // 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), + powerLight = new GUITickBox(new RectTransform(new Vector2(0.87f, 0.3f), paddedPowerArea.RectTransform, Anchor.TopCenter, Pivot.Center), TextManager.Get("PowerLabel"), font: GUI.SubHeadingFont, style: "IndicatorLightPower") { CanBeFocused = false, Selected = _powerOn }; - powerLight.TextBlock.AutoScale = true; + powerLight.TextBlock.Padding = new Vector4(5.0f, 0.0f, 0.0f, 0.0f); + powerLight.TextBlock.AutoScaleHorizontal = true; powerLight.TextBlock.OverrideTextColor(GUI.Style.TextColor); PowerButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.75f), paddedPowerArea.RectTransform, Anchor.BottomCenter) { @@ -324,16 +327,17 @@ namespace Barotrauma.Items.Components topRightArea.Recalculate(); autoTempLight.TextBlock.Wrap = true; - GUITextBlock.AutoScaleAndNormalize( - criticalHeatWarning.TextBlock, lowTemperatureWarning.TextBlock, criticalOutputWarning.TextBlock, autoTempLight.TextBlock); + indicatorLights.Add(autoTempLight); + GUITextBlock.AutoScaleAndNormalize(indicatorLights.Select(l => l.TextBlock)); // right bottom (graph area) ----------------------- new GUIFrame(new RectTransform(new Vector2(0.95f, 0.01f), columnRight.RectTransform), style: "HorizontalLine"); - var bottomRightArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), columnRight.RectTransform), isHorizontal: true) + var bottomRightArea = new GUILayoutGroup(new RectTransform(Vector2.One, columnRight.RectTransform), isHorizontal: true) { Stretch = true, + CanBeFocused = true, RelativeSpacing = 0.02f }; @@ -347,7 +351,7 @@ namespace Barotrauma.Items.Components RelativeSpacing = 0.02f }; - relativeTextSize = new Vector2(1.0f, 0.0f); + relativeTextSize = new Vector2(1.0f, 0.15f); var loadText = new GUITextBlock(new RectTransform(relativeTextSize, graphArea.RectTransform), "Load", textColor: loadColor, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs index 0e9266229..e72a1048d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs @@ -72,20 +72,24 @@ namespace Barotrauma.Items.Components private readonly Color negativeColor = Color.Red; private readonly Color markerColor = Color.Red; + public static readonly Vector2 controlBoxSize = new Vector2(0.33f, 0.32f); + public static readonly Vector2 controlBoxOffset = new Vector2(0.025f, 0); + public static readonly float sonarAreaSize = 1.09f; + private static readonly Dictionary blipColorGradient = new Dictionary() { - { + { 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) } + 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) } + new Color[] { Color.TransparentBlack, new Color(254, 68, 19), new Color(255, 220, 62), new Color(255, 255, 255) } } }; private float prevDockingDist; - + public Vector2 DisplayOffset { get; private set; } public float DisplayRadius { get; private set; } @@ -132,29 +136,28 @@ namespace Barotrauma.Items.Components } } CreateGUI(); - GameMain.Instance.OnResolutionChanged += ResetLayout; - // TODO: do we need to react on this? - GameMain.Config.OnHUDScaleChanged += ResetLayout; + GameMain.Instance.OnResolutionChanged += RecreateGUI; } - private void ResetLayout() + private void RecreateGUI() { - GuiFrame.RectTransform.Children.ForEachMod(c => c.Parent = null); + GuiFrame.ClearChildren(); CreateGUI(); } private void CreateGUI() { - controlContainer = new GUIFrame(new RectTransform(new Vector2(controlContainerRelativeWidth, 0.32f), GuiFrame.RectTransform, Anchor.TopRight) - { - RelativeOffset = new Vector2(controlContainerRelativeOffset, 0) - }, "ItemUI"); + bool isConnectedToSteering = item.GetComponent() != null; + Vector2 size = isConnectedToSteering ? controlBoxSize : new Vector2(controlBoxSize.X * 2.0f, controlBoxSize.Y); + controlContainer = new GUIFrame(new RectTransform(size, GuiFrame.RectTransform, Anchor.BottomRight, Pivot.BottomLeft), "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); + // Based on the height difference to the steering control box so that the elements keep the same size + float extraHeight = 0.03f; + var sonarModeArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f + extraHeight), paddedControlContainer.RectTransform, Anchor.TopCenter), style: null); SonarModeSwitch = new GUIButton(new RectTransform(new Vector2(0.2f, 1), sonarModeArea.RectTransform), string.Empty, style: "SwitchVertical") { Selected = false, @@ -192,13 +195,11 @@ namespace Barotrauma.Items.Components 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), + var lowerArea = new GUIFrame(new RectTransform(new Vector2(1, 0.4f + extraHeight), paddedControlContainer.RectTransform, Anchor.BottomCenter), style: null); + var zoomContainer = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerArea.RectTransform, Anchor.TopCenter), style: null); + var zoomText = 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) + zoomSlider = new GUIScrollBar(new RectTransform(new Vector2(0.5f, 0.8f), zoomContainer.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.35f, 0) }, barSize: 0.15f, isHorizontal: true, style: "DeviceSlider") @@ -215,11 +216,9 @@ namespace Barotrauma.Items.Components } }; - 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"); + new GUIFrame(new RectTransform(new Vector2(0.8f, 0.01f), paddedControlContainer.RectTransform, Anchor.Center), style: "HorizontalLine"); + + var directionalModeFrame = new GUIFrame(new RectTransform(new Vector2(1, 0.45f), lowerArea.RectTransform, Anchor.BottomCenter), style: null); directionalModeSwitch = new GUIButton(new RectTransform(new Vector2(0.3f, 0.8f), directionalModeFrame.RectTransform, Anchor.CenterLeft), string.Empty, style: "SwitchHorizontal") { OnClicked = (button, data) => @@ -241,14 +240,22 @@ namespace Barotrauma.Items.Components GuiFrame.CanBeFocused = false; - sonarView = new GUICustomComponent(new RectTransform(SonarAreaSize, GuiFrame.RectTransform, Anchor.CenterLeft), - (spriteBatch, guiCustomComponent) => { DrawSonar(spriteBatch, guiCustomComponent.Rect); }, null); - sonarView.RectTransform.SetAsFirstChild(); - } + GUITextBlock.AutoScaleAndNormalize(passiveTickBox.TextBlock, activeTickBox.TextBlock, zoomText, directionalModeSwitchText); - public static readonly float controlContainerRelativeWidth = 0.35f; - public static readonly float controlContainerRelativeOffset = 0.1f; - public static Vector2 SonarAreaSize => Vector2.One - new Vector2(controlContainerRelativeWidth + controlContainerRelativeOffset); + sonarView = new GUICustomComponent(new RectTransform(Vector2.One * 0.7f, GuiFrame.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight), + (spriteBatch, guiCustomComponent) => { DrawSonar(spriteBatch, guiCustomComponent.Rect); }, null); + + // Setup layout for nav terminal + if (isConnectedToSteering) + { + controlContainer.RectTransform.SetPosition(Anchor.TopLeft); + controlContainer.RectTransform.RelativeOffset = controlBoxOffset; + sonarView.RectTransform.ScaleBasis = ScaleBasis.Smallest; + sonarView.RectTransform.SetPosition(Anchor.CenterRight); + sonarView.RectTransform.Resize(Vector2.One * GUI.RelativeHorizontalAspectRatio * sonarAreaSize); + GUITextBlock.AutoScaleAndNormalize(passiveTickBox.TextBlock, activeTickBox.TextBlock, zoomText, directionalModeSwitchText); + } + } private void SetPingDirection(Vector2 direction) { @@ -380,7 +387,6 @@ namespace Barotrauma.Items.Components else if (transducerCenter.X > Level.Loaded.Size.X) { outsideLevelFlow = -(transducerCenter.X - Level.Loaded.Size.X) * 0.001f; - } if (Rand.Range(0.0f, 100.0f) < Math.Abs(outsideLevelFlow)) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs index d3a5447a7..700028d02 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs @@ -103,16 +103,14 @@ namespace Barotrauma.Items.Components } } CreateGUI(); - GameMain.Instance.OnResolutionChanged += ResetGUI; - // TODO: do we need to react on this? - GameMain.Config.OnHUDScaleChanged += ResetGUI; + GameMain.Instance.OnResolutionChanged += RecreateGUI; } private void CreateGUI() { - controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.36f), GuiFrame.RectTransform, Anchor.CenterRight) + controlContainer = new GUIFrame(new RectTransform(new Vector2(Sonar.controlBoxSize.X, Sonar.controlBoxSize.Y + 0.02f), GuiFrame.RectTransform, Anchor.CenterLeft) { - RelativeOffset = new Vector2(Sonar.controlContainerRelativeOffset / 2, 0.01f) // Based on the relative size differende of the steering and the status windows + RelativeOffset = new Vector2(0, 0) // The y offset should be based on the relative size difference of the steering and the status windows }, "ItemUI"); var paddedControlContainer = new GUIFrame(new RectTransform(controlContainer.Rect.Size - GUIStyle.ItemFrameMargin, controlContainer.RectTransform, Anchor.Center) { @@ -156,15 +154,18 @@ namespace Barotrauma.Items.Components autopilotIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor); GUITextBlock.AutoScaleAndNormalize(manualPilotIndicator.TextBlock, autopilotIndicator.TextBlock); - 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)) + var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(0.8f, 0.6f), paddedControlContainer.RectTransform, Anchor.BottomCenter) + { + RelativeOffset = new Vector2(0, 0.02f) + }, "OutlineFrame"); + var paddedAutoPilotControls = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), autoPilotControls.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.03f, - ChildAnchor = Anchor.TopCenter + ChildAnchor = Anchor.TopLeft }; - maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.2f), paddedAutoPilotControls.RectTransform), + maintainPosTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), paddedAutoPilotControls.RectTransform), TextManager.Get("SteeringMaintainPos"), font: GUI.SmallFont, style: "GUIRadioButton") { Enabled = false, @@ -200,8 +201,8 @@ namespace Barotrauma.Items.Components } }; - levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.2f), paddedAutoPilotControls.RectTransform), - GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, 20), + levelStartTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), paddedAutoPilotControls.RectTransform), + GameMain.GameSession?.StartLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, 30), font: GUI.SmallFont, style: "GUIRadioButton") { Enabled = false, @@ -227,8 +228,8 @@ namespace Barotrauma.Items.Components } }; - levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.2f), paddedAutoPilotControls.RectTransform), - GameMain.GameSession?.EndLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, 20), + levelEndTickBox = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), paddedAutoPilotControls.RectTransform), + GameMain.GameSession?.EndLocation == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, 30), font: GUI.SmallFont, style: "GUIRadioButton") { Enabled = false, @@ -256,7 +257,7 @@ namespace Barotrauma.Items.Components 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 = + 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; @@ -269,16 +270,16 @@ namespace Barotrauma.Items.Components levelStartSelected ? Destination.LevelStart : Destination.LevelEnd); // Status -> - statusContainer = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.3f), GuiFrame.RectTransform, Anchor.BottomRight) + statusContainer = new GUIFrame(new RectTransform(Sonar.controlBoxSize, GuiFrame.RectTransform, Anchor.BottomLeft) { - RelativeOffset = new Vector2(Sonar.controlContainerRelativeOffset, 0) + RelativeOffset = Sonar.controlBoxOffset }, "ItemUI"); - var paddedStatusContainer = new GUIFrame(new RectTransform(statusContainer.Rect.Size - GUIStyle.ItemFrameMargin, statusContainer.RectTransform, Anchor.Center) + var paddedStatusContainer = new GUIFrame(new RectTransform(statusContainer.Rect.Size - GUIStyle.ItemFrameMargin, statusContainer.RectTransform, Anchor.Center, isFixedSize: false) { 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); + var elements = GUI.CreateElements(3, new Vector2(1f, 0.333f), 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++) { @@ -288,9 +289,9 @@ namespace Barotrauma.Items.Components 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); + var left = new GUIFrame(new RectTransform(new Vector2(0.45f, 1), group.RectTransform), style: null); + var center = new GUIFrame(new RectTransform(new Vector2(0.15f, 1), group.RectTransform), style: null); + var right = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.8f), group.RectTransform), style: null); leftElements.Add(left); centerElements.Add(center); rightElements.Add(right); @@ -338,36 +339,15 @@ namespace Barotrauma.Items.Components }; } 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.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 - }; - - noPowerTip = TextManager.Get("SteeringNoPowerTip"); - autoPilotMaintainPosTip = TextManager.Get("SteeringAutoPilotMaintainPosTip"); - autoPilotLevelStartTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]", - GameMain.GameSession?.StartLocation == null ? "Start" : GameMain.GameSession.StartLocation.Name); - autoPilotLevelEndTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]", - GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.Name); - //docking interface ---------------------------------------------------- float dockingButtonSize = 1.1f; float elementScale = 0.6f; - dockingContainer = new GUIFrame(new RectTransform(new Point(160).Multiply(GUI.Scale * dockingButtonSize), GuiFrame.RectTransform, Anchor.BottomRight) + dockingContainer = new GUIFrame(new RectTransform(new Point(160).Multiply(GUI.Scale * dockingButtonSize), GuiFrame.RectTransform, Anchor.BottomLeft) { - RelativeOffset = new Vector2(Sonar.controlContainerRelativeOffset + 0.05f, -0.05f) + RelativeOffset = new Vector2(Sonar.controlBoxOffset.X + 0.15f, -0.1f) }, style: null); dockText = TextManager.Get("label.navterminaldock", fallBackTag: "captain.dock"); @@ -416,16 +396,32 @@ namespace Barotrauma.Items.Components UserData = -Vector2.UnitY }; - steerArea = new GUICustomComponent(new RectTransform(Sonar.SonarAreaSize, GuiFrame.RectTransform, Anchor.CenterLeft), + // Sonar area + steerArea = new GUICustomComponent(new RectTransform(Vector2.One * GUI.RelativeHorizontalAspectRatio * Sonar.sonarAreaSize, GuiFrame.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.Smallest), (spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null); - steerArea.RectTransform.SetAsFirstChild(); steerRadius = steerArea.Rect.Width / 2; + + // Tooltip/helper text + 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.5f, 0.1f), steerArea.RectTransform, Anchor.BottomCenter, Pivot.TopCenter) + , "", font: GUI.Font, wrap: true, style: "GUIToolTip", textAlignment: Alignment.Center) + { + AutoScaleHorizontal = true + }; + noPowerTip = TextManager.Get("SteeringNoPowerTip"); + autoPilotMaintainPosTip = TextManager.Get("SteeringAutoPilotMaintainPosTip"); + autoPilotLevelStartTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]", + GameMain.GameSession?.StartLocation == null ? "Start" : GameMain.GameSession.StartLocation.Name); + autoPilotLevelEndTip = TextManager.GetWithVariable("SteeringAutoPilotLocationTip", "[locationname]", + GameMain.GameSession?.EndLocation == null ? "End" : GameMain.GameSession.EndLocation.Name); } - - private void ResetGUI() + private void RecreateGUI() { - GuiFrame.RectTransform.Children.ForEachMod(c => c.Parent = null); + GuiFrame.ClearChildren(); CreateGUI(); } @@ -706,7 +702,7 @@ namespace Barotrauma.Items.Components if (PlayerInput.KeyDown(InputType.Right)) { input += Vector2.UnitX; } if (PlayerInput.KeyDown(InputType.Up)) { input += Vector2.UnitY; } if (PlayerInput.KeyDown(InputType.Down)) { input -= Vector2.UnitY; } - if (PlayerInput.KeyDown(Keys.LeftShift)) + if (PlayerInput.KeyDown(InputType.Run)) { SteeringInput += input * deltaTime * 200; inputCumulation = 0; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerTransfer.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerTransfer.cs index 32c411ff8..c010891d3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerTransfer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Power/PowerTransfer.cs @@ -99,7 +99,7 @@ namespace Barotrauma.Items.Components }; GUITextBlock.AutoScaleAndNormalize(powerLabel, loadLabel); - GUITextBlock.AutoScaleAndNormalize(powerText, loadText); + GUITextBlock.AutoScaleAndNormalize(true, true, powerText, loadText); GUITextBlock.AutoScaleAndNormalize(kw1, kw2); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs index 5f33deade..0486d3c53 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Connection.cs @@ -184,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})"; @@ -197,7 +197,10 @@ namespace Barotrauma.Items.Components //stop dragging a wire item if the cursor is within any connection panel //(so we don't drop the item when dropping the wire on a connection) - if (mouseInRect || GUI.MouseOn?.UserData is ConnectionPanel) { Inventory.draggingItem = null; } + if (mouseInRect || (GUI.MouseOn?.UserData is ConnectionPanel && GUI.MouseOn.MouseRect.Contains(PlayerInput.MousePosition))) + { + Inventory.draggingItem = null; + } } private void DrawConnection(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 scale) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs index 6b9c2f67f..734020e22 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/CustomInterface.cs @@ -10,33 +10,52 @@ namespace Barotrauma.Items.Components { partial class CustomInterface { - private List uiElements = new List(); + private readonly List uiElements = new List(); private GUILayoutGroup uiElementContainer; + private Point ElementMaxSize => new Point(uiElementContainer.Rect.Width, (int)(60 * GUI.yScale)); + partial void InitProjSpecific(XElement element) + { + CreateGUI(); + GameMain.Instance.OnResolutionChanged += RecreateGUI; + } + + private void RecreateGUI() + { + GuiFrame.ClearChildren(); + CreateGUI(); + } + + private void CreateGUI() { uiElements.Clear(); - var visibleElements = customInterfaceElementList.Where(ciElement => !string.IsNullOrEmpty(ciElement.Label)); - - uiElementContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.65f), GuiFrame.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.025f) }, + uiElementContainer = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) + { + AbsoluteOffset = GUIStyle.ItemFrameOffset + }, childAnchor: customInterfaceElementList.Count > 1 ? Anchor.TopCenter : Anchor.Center) { RelativeSpacing = 0.05f, - Stretch = visibleElements.Count() > 2 + Stretch = visibleElements.Count() > 2, }; - float elementSize = Math.Min(1.0f / visibleElements.Count(), 0.5f); + float elementSize = Math.Min(1.0f / visibleElements.Count(), 1); + var textBlocks = new List(); foreach (CustomInterfaceElement ciElement in visibleElements) { if (ciElement.ContinuousSignal) { - var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform), + var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform) + { + MaxSize = ElementMaxSize + }, TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label) { UserData = ciElement }; - tickBox.TextBlock.AutoScale = true; + textBlocks.Add(tickBox.TextBlock); tickBox.OnSelected += (tBox) => { if (GameMain.Client == null) @@ -56,12 +75,12 @@ namespace Barotrauma.Items.Components } else { - var btn = new GUIButton(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform), + var btn = new GUIButton(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform), TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label, style: "DeviceButton") { UserData = ciElement }; - btn.TextBlock.AutoScale = true; + textBlocks.Add(btn.TextBlock); btn.OnClicked += (_, userdata) => { if (GameMain.Client == null) @@ -77,11 +96,12 @@ namespace Barotrauma.Items.Components //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.RectTransform.MaxSize = btn.Frame.RectTransform.MaxSize = ElementMaxSize; btn.TextBlock.Wrap = true; uiElements.Add(btn); } + GUITextBlock.AutoScaleAndNormalize(textBlocks); } } @@ -128,12 +148,8 @@ namespace Barotrauma.Items.Components int visibleElementCount = 0; foreach (var uiElement in uiElements) { - CustomInterfaceElement element = uiElement.UserData as CustomInterfaceElement; - if (element == null) { continue; } - bool visible = - Screen.Selected == GameMain.SubEditorScreen || - element.StatusEffects.Any() || - (element.Connection != null && element.Connection.Wires.Any(w => w != null)); + if (!(uiElement.UserData is CustomInterfaceElement element)) { continue; } + bool visible = Screen.Selected == GameMain.SubEditorScreen || element.StatusEffects.Any() || (element.Connection != null && element.Connection.Wires.Any(w => w != null)); if (visible) { visibleElementCount++; } if (uiElement.Visible != visible) { @@ -146,11 +162,12 @@ namespace Barotrauma.Items.Components { uiElementContainer.Stretch = visibleElementCount > 2; uiElementContainer.ChildAnchor = visibleElementCount > 1 ? Anchor.TopCenter : Anchor.Center; - float elementSize = Math.Min(1.0f / visibleElementCount, 0.5f); + float elementSize = Math.Min(1.0f / visibleElementCount, 1); foreach (var uiElement in uiElements) { uiElement.RectTransform.RelativeSize = new Vector2(1.0f, elementSize); } + GuiFrame.Visible = visibleElementCount > 0; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs index 0f8101213..674ebad69 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs @@ -94,8 +94,8 @@ namespace Barotrauma.Items.Components Submarine sub = item.Submarine; if (IsActive && sub == null) // currently being rewired, we need to get the sub from the connections in case the wire has been taken outside { - if (connections[0] != null && connections[0].Item.Submarine != null) sub = connections[0].Item.Submarine; - if (connections[1] != null && connections[1].Item.Submarine != null) sub = connections[1].Item.Submarine; + if (connections[0] != null && connections[0].Item.Submarine != null) { sub = connections[0].Item.Submarine; } + if (connections[1] != null && connections[1].Item.Submarine != null) { sub = connections[1].Item.Submarine; } } if (sub != null) @@ -253,11 +253,15 @@ namespace Barotrauma.Items.Components { MapEntity.DisableSelect = true; - Submarine sub = null; + Submarine sub = draggingWire.item.Submarine; if (draggingWire.connections[0] != null && draggingWire.connections[0].Item.Submarine != null) sub = draggingWire.connections[0].Item.Submarine; if (draggingWire.connections[1] != null && draggingWire.connections[1].Item.Submarine != null) sub = draggingWire.connections[1].Item.Submarine; - Vector2 nodeWorldPos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition) - sub.HiddenSubPosition - sub.Position;// Nodes[(int)selectedNodeIndex]; + Vector2 nodeWorldPos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition); + if (sub != null) + { + nodeWorldPos = nodeWorldPos - sub.HiddenSubPosition - sub.Position; + } if (selectedNodeIndex.HasValue) { @@ -352,7 +356,7 @@ namespace Barotrauma.Items.Components foreach (Wire w in wires) { Vector2 mousePos = GameMain.SubEditorScreen.Cam.ScreenToWorld(PlayerInput.MousePosition); - if (w.item.Submarine != null) mousePos -= (w.item.Submarine.Position + w.item.Submarine.HiddenSubPosition); + if (w.item.Submarine != null) { mousePos -= (w.item.Submarine.Position + w.item.Submarine.HiddenSubPosition); } int highlightedNode = w.GetClosestNodeIndex(mousePos, highlighted == null ? nodeSelectDist : closestDist, out float dist); if (highlightedNode > -1) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs index f20ae801a..55eee788e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs @@ -131,10 +131,9 @@ namespace Barotrauma protected float prevHUDScale = GUI.Scale; protected Point prevScreenResolution; - protected static Sprite slotSpriteHorizontal, slotSpriteVertical, slotSpriteRound, slotHotkeySprite; + protected static Sprite slotHotkeySprite; public static Sprite SlotSpriteSmall; public static Sprite EquipIndicator, EquipIndicatorHighlight; - public static Sprite DropIndicator, DropIndicatorHighlight; public static Inventory DraggingInventory; public Rectangle BackgroundFrame { get; protected set; } @@ -291,7 +290,8 @@ namespace Barotrauma int rows = (int)Math.Ceiling((double)capacity / slotsPerRow); int columns = Math.Min(slotsPerRow, capacity); - Vector2 spacing = new Vector2(10 * UIScale, (10 + EquipIndicator.size.Y) * UIScale); + Vector2 spacing = new Vector2(5.0f * UIScale); + spacing.Y += (this is CharacterInventory) ? EquipIndicator.size.Y * UIScale : ContainedIndicatorHeight; Vector2 rectSize = new Vector2(60.0f * UIScale); padding = new Vector4(spacing.X, spacing.Y, spacing.X, spacing.X); @@ -534,88 +534,77 @@ namespace Barotrauma int itemCapacity = subInventory.Items.Length; var slot = slots[slotIndex]; int dir = slot.SubInventoryDir; - if (itemCapacity == 1 && false) + Rectangle subRect = slot.Rect; + Vector2 spacing = new Vector2(10 * UIScale, (10 + EquipIndicator.size.Y) * UIScale); + + int columns = (int)Math.Max(Math.Floor(Math.Sqrt(itemCapacity)), 1); + while (itemCapacity / columns * (subRect.Height + spacing.Y) > GameMain.GraphicsHeight * 0.5f) { - Point slotSize = (slotSpriteRound.size * UIScale).ToPoint(); - subInventory.slots[0].Rect = - new Rectangle(slot.Rect.Center.X - slotSize.X / 2, dir > 0 ? slot.Rect.Bottom + 5 : slot.EquipButtonRect.Bottom + 5, slotSize.X, slotSize.Y); - - subInventory.slots[0].InteractRect = subInventory.slots[0].Rect; - subInventory.slots[0].DrawOffset = slot.DrawOffset; + columns++; } - else + + int width = (int)(subRect.Width * columns + spacing.X * (columns - 1)); + int startX = slot.Rect.Center.X - (int)(width / 2.0f); + int startY = dir < 0 ? + slot.EquipButtonRect.Y - subRect.Height - (int)(35 * UIScale) : + slot.EquipButtonRect.Bottom + (int)(10 * UIScale); + + if (canMove) { - Rectangle subRect = slot.Rect; - Vector2 spacing = new Vector2(10 * UIScale, (10 + EquipIndicator.size.Y) * UIScale); - - int columns = (int)Math.Max(Math.Floor(Math.Sqrt(itemCapacity)), 1); - while (itemCapacity / columns * (subRect.Height + spacing.Y) > GameMain.GraphicsHeight * 0.5f) - { - columns++; - } - - int width = (int)(subRect.Width * columns + spacing.X * (columns - 1)); - int startX = slot.Rect.Center.X - (int)(width / 2.0f); - int startY = dir < 0 ? - slot.EquipButtonRect.Y - subRect.Height - (int)(35 * UIScale) : - slot.EquipButtonRect.Bottom + (int)(10 * UIScale); - - if (canMove) - { - startX += subInventory.savedPosition.X - subInventory.originalPos.X; - startY += subInventory.savedPosition.Y - subInventory.originalPos.Y; - } - - float totalHeight = itemCapacity / columns * (subRect.Height + spacing.Y); - int padding = (int)(20 * UIScale); - - //prevent the inventory from extending outside the left side of the screen - startX = Math.Max(startX, padding); - //same for the right side of the screen - startX -= Math.Max(startX + width - GameMain.GraphicsWidth + padding, 0); - - //prevent the inventory from extending outside the top of the screen - startY = Math.Max(startY, (int)totalHeight - padding / 2); - //same for the bottom side of the screen - startY -= Math.Max(startY - GameMain.GraphicsHeight + padding * 2 + (canMove ? (int)(movableFrameRectHeight * UIScale) : 0), 0); - - subRect.X = startX; - subRect.Y = startY; - - subInventory.OpenState = subInventory.HideTimer >= 0.5f ? - Math.Min(subInventory.OpenState + deltaTime * 8.0f, 1.0f) : - Math.Max(subInventory.OpenState - deltaTime * 5.0f, 0.0f); - - for (int i = 0; i < itemCapacity; i++) - { - subInventory.slots[i].Rect = subRect; - subInventory.slots[i].Rect.Location += new Point(0, (int)totalHeight * -dir); - - subInventory.slots[i].DrawOffset = Vector2.SmoothStep(new Vector2(0, -50 * dir), new Vector2(0, totalHeight * dir), subInventory.OpenState); - - subInventory.slots[i].InteractRect = new Rectangle( - (int)(subInventory.slots[i].Rect.X - spacing.X / 2 - 1), (int)(subInventory.slots[i].Rect.Y - spacing.Y / 2 - 1), - (int)(subInventory.slots[i].Rect.Width + spacing.X + 2), (int)(subInventory.slots[i].Rect.Height + spacing.Y + 2)); - - if ((i + 1) % columns == 0) - { - subRect.X = startX; - subRect.Y += subRect.Height * dir; - subRect.Y += (int)(spacing.Y * dir); - } - else - { - subRect.X = (int)(subInventory.slots[i].Rect.Right + spacing.X); - } - } - - if (canMove) - { - subInventory.movableFrameRect.X = subRect.X - (int)spacing.X; - subInventory.movableFrameRect.Y = subRect.Y + (int)(spacing.Y); - } - slots[slotIndex].State = GUIComponent.ComponentState.Hover; + startX += subInventory.savedPosition.X - subInventory.originalPos.X; + startY += subInventory.savedPosition.Y - subInventory.originalPos.Y; } + + float totalHeight = itemCapacity / columns * (subRect.Height + spacing.Y); + int padding = (int)(20 * UIScale); + + //prevent the inventory from extending outside the left side of the screen + startX = Math.Max(startX, padding); + //same for the right side of the screen + startX -= Math.Max(startX + width - GameMain.GraphicsWidth + padding, 0); + + //prevent the inventory from extending outside the top of the screen + startY = Math.Max(startY, (int)totalHeight - padding / 2); + //same for the bottom side of the screen + startY -= Math.Max(startY - GameMain.GraphicsHeight + padding * 2 + (canMove ? (int)(movableFrameRectHeight * UIScale) : 0), 0); + + subRect.X = startX; + subRect.Y = startY; + + subInventory.OpenState = subInventory.HideTimer >= 0.5f ? + Math.Min(subInventory.OpenState + deltaTime * 8.0f, 1.0f) : + Math.Max(subInventory.OpenState - deltaTime * 5.0f, 0.0f); + + for (int i = 0; i < itemCapacity; i++) + { + subInventory.slots[i].Rect = subRect; + subInventory.slots[i].Rect.Location += new Point(0, (int)totalHeight * -dir); + + subInventory.slots[i].DrawOffset = Vector2.SmoothStep(new Vector2(0, -50 * dir), new Vector2(0, totalHeight * dir), subInventory.OpenState); + + subInventory.slots[i].InteractRect = new Rectangle( + (int)(subInventory.slots[i].Rect.X - spacing.X / 2 - 1), (int)(subInventory.slots[i].Rect.Y - spacing.Y / 2 - 1), + (int)(subInventory.slots[i].Rect.Width + spacing.X + 2), (int)(subInventory.slots[i].Rect.Height + spacing.Y + 2)); + + if ((i + 1) % columns == 0) + { + subRect.X = startX; + subRect.Y += subRect.Height * dir; + subRect.Y += (int)(spacing.Y * dir); + } + else + { + subRect.X = (int)(subInventory.slots[i].Rect.Right + spacing.X); + } + } + + if (canMove) + { + subInventory.movableFrameRect.X = subRect.X - (int)spacing.X; + subInventory.movableFrameRect.Y = subRect.Y + (int)(spacing.Y); + } + slots[slotIndex].State = GUIComponent.ComponentState.Hover; + subInventory.isSubInventory = true; subInventory.Update(deltaTime, cam, true); } @@ -1168,10 +1157,14 @@ namespace Barotrauma if (itemContainer.ContainedStateIndicator?.Texture == null) { containedIndicatorArea.Inflate(0, -2); - GUI.DrawRectangle(spriteBatch, containedIndicatorArea, Color.DarkGray * 0.9f, true); + GUI.DrawRectangle(spriteBatch, containedIndicatorArea, Color.Gray * 0.9f, true); GUI.DrawRectangle(spriteBatch, new Rectangle(containedIndicatorArea.X, containedIndicatorArea.Y, (int)(containedIndicatorArea.Width * containedState), containedIndicatorArea.Height), - Color.Lerp(GUI.Style.Red, GUI.Style.Green, containedState) * 0.8f, true); + ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.LightGreen) * 0.8f, true); + GUI.DrawLine(spriteBatch, + new Vector2(containedIndicatorArea.X + (int)(containedIndicatorArea.Width * containedState), containedIndicatorArea.Y), + new Vector2(containedIndicatorArea.X + (int)(containedIndicatorArea.Width * containedState), containedIndicatorArea.Bottom), + Color.Black * 0.8f); } else { @@ -1186,12 +1179,12 @@ namespace Barotrauma } indicatorSprite.Draw(spriteBatch, containedIndicatorArea.Center.ToVector2(), - (inventory != null && inventory.Locked) ? Color.DarkGray * 0.5f : Color.DarkGray * 0.9f, + (inventory != null && inventory.Locked) ? Color.Gray * 0.5f : Color.Gray * 0.9f, origin: indicatorSprite.size / 2, rotate: 0.0f, scale: indicatorScale); - Color indicatorColor = ToolBox.GradientLerp(containedState, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green); + Color indicatorColor = ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.LightGreen); if (inventory != null && inventory.Locked) { indicatorColor *= 0.5f; } spriteBatch.Draw(indicatorSprite.Texture, containedIndicatorArea.Center.ToVector2(), @@ -1201,6 +1194,14 @@ namespace Barotrauma origin: indicatorSprite.size / 2, scale: indicatorScale, effects: SpriteEffects.None, layerDepth: 0.0f); + + spriteBatch.Draw(indicatorSprite.Texture, containedIndicatorArea.Center.ToVector2(), + sourceRectangle: new Rectangle(indicatorSprite.SourceRect.X - 1 + (int)(indicatorSprite.SourceRect.Width * containedState), indicatorSprite.SourceRect.Y, Math.Max((int)Math.Ceiling(1 / indicatorScale), 2), indicatorSprite.SourceRect.Height), + color: Color.Black, + rotation: 0.0f, + origin: new Vector2(indicatorSprite.size.X * (0.5f - containedState), indicatorSprite.size.Y * 0.5f), + scale: indicatorScale, + effects: SpriteEffects.None, layerDepth: 0.0f); } } } @@ -1296,6 +1297,10 @@ namespace Barotrauma // 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)))) { + if (GameMain.GameSession == null || Level.Loaded == null) + { + yield return CoroutineStatus.Success; + } 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 a29077494..b0634c374 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs @@ -44,6 +44,11 @@ namespace Barotrauma get { return activeSprite; } } + public override bool DrawOverWater + { + get { return base.DrawOverWater || (GetComponent() != null && IsSelected); } + } + private GUITextBlock itemInUseWarning; private GUITextBlock ItemInUseWarning { @@ -523,8 +528,8 @@ namespace Barotrauma if (Linkable) { - 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); + var linkText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, heightScaled), isFixedSize: true), TextManager.Get("HoldToLink"), font: GUI.SmallFont); + var itemsText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, heightScaled), isFixedSize: true), TextManager.Get("AllowedLinks"), font: GUI.SmallFont); string allowedItems = AllowedLinks.None() ? TextManager.Get("None") :string.Join(", ", AllowedLinks); itemsText.Text = TextManager.AddPunctuation(':', itemsText.Text, allowedItems); itemEditor.AddCustomContent(linkText, 1); @@ -535,7 +540,8 @@ namespace Barotrauma var buttonContainer = new GUILayoutGroup(new RectTransform(new Point(listBox.Content.Rect.Width, heightScaled)), isHorizontal: true) { Stretch = true, - RelativeSpacing = 0.02f + RelativeSpacing = 0.02f, + CanBeFocused = true }; new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall") { @@ -575,6 +581,7 @@ namespace Barotrauma } }; buttonContainer.RectTransform.MinSize = new Point(0, buttonContainer.RectTransform.Children.Max(c => c.MinSize.Y)); + buttonContainer.RectTransform.IsFixedSize = true; itemEditor.AddCustomContent(buttonContainer, itemEditor.ContentCount); GUITextBlock.AutoScaleAndNormalize(buttonContainer.Children.Select(b => ((GUIButton)b).TextBlock)); } @@ -615,17 +622,20 @@ namespace Barotrauma foreach (RelatedItem relatedItem in requiredItems) { + //TODO: add to localization 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) }; + textBlock.RectTransform.IsFixedSize = true; componentEditor.AddCustomContent(textBlock, 1); GUITextBox namesBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), textBlock.RectTransform, Anchor.CenterRight)) { Font = GUI.SmallFont, - Text = relatedItem.JoinedIdentifiers + Text = relatedItem.JoinedIdentifiers, + OverflowClip = true }; textBlock.RectTransform.Resize(new Point(textBlock.Rect.Width, namesBox.RectTransform.MinSize.Y)); @@ -710,11 +720,11 @@ namespace Barotrauma HUDLayoutSettings.ChatBoxArea.Width + disallowedPadding, HUDLayoutSettings.ChatBoxArea.Height)); } - //GUI.PreventElementOverlap(elementsToMove, disallowedAreas, - // new Rectangle( - // 0, 20, - // GameMain.GraphicsWidth, - // 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) { @@ -761,7 +771,8 @@ namespace Barotrauma List maxPriorityHUDs = new List(); foreach (ItemComponent ic in activeComponents) { - if (ic.CanBeSelected && ic.HudPriority > 0 && ic.ShouldDrawHUD(character) && + if (ic.HudPriority > 0 && ic.ShouldDrawHUD(character) && + (ic.CanBeSelected || character.HasEquippedItem(this)) && (maxPriorityHUDs.Count == 0 || ic.HudPriority >= maxPriorityHUDs[0].HudPriority)) { if (maxPriorityHUDs.Count > 0 && ic.HudPriority > maxPriorityHUDs[0].HudPriority) maxPriorityHUDs.Clear(); @@ -777,7 +788,10 @@ namespace Barotrauma { foreach (ItemComponent ic in activeComponents) { - if (ic.CanBeSelected && ic.ShouldDrawHUD(character)) activeHUDs.Add(ic); + if ((ic.CanBeSelected || character.HasEquippedItem(this)) && ic.ShouldDrawHUD(character)) + { + activeHUDs.Add(ic); + } } } @@ -867,11 +881,6 @@ namespace Barotrauma } public override void AddToGUIUpdateList() - { - AddToGUIUpdateList(addLinkedHUDs: true); - } - - private void AddToGUIUpdateList(bool addLinkedHUDs) { if (Screen.Selected is SubEditorScreen) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs index 796482cc1..f485e4d9c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/MapEntity.cs @@ -1,4 +1,5 @@ -using Barotrauma.Items.Components; +using Barotrauma.Extensions; +using Barotrauma.Items.Components; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; @@ -733,9 +734,10 @@ namespace Barotrauma var clones = mapEntityList.Except(prevEntities).ToList(); + var nonWireClones = clones.Where(c => !(c is Item item) || item.GetComponent() == null); Vector2 center = Vector2.Zero; - clones.ForEach(c => center += c.WorldPosition); - center = Submarine.VectorToWorldGrid(center / clones.Count); + nonWireClones.ForEach(c => center += c.WorldPosition); + center = Submarine.VectorToWorldGrid(center / nonWireClones.Count()); Vector2 moveAmount = Submarine.VectorToWorldGrid(position - center); @@ -785,8 +787,8 @@ namespace Barotrauma else { editingHUD.RectTransform.SetPosition(Anchor.TopRight); - editingHUD.RectTransform.RelativeOffset = new Vector2(0.0f, (HUDLayoutSettings.InventoryAreaUpper.Bottom + 10.0f) / (editingHUD.RectTransform.Parent ?? GUI.Canvas).Rect.Height); - maxHeight = HUDLayoutSettings.InventoryAreaLower.Bottom - HUDLayoutSettings.InventoryAreaLower.Y - 10; + editingHUD.RectTransform.RelativeOffset = new Vector2(0.0f, (HUDLayoutSettings.CrewArea.Bottom + 10.0f) / (editingHUD.RectTransform.Parent ?? GUI.Canvas).Rect.Height); + maxHeight = HUDLayoutSettings.InventoryAreaLower.Y - HUDLayoutSettings.CrewArea.Bottom - 10; } var listBox = editingHUD.GetChild(); @@ -883,6 +885,7 @@ namespace Barotrauma { rectMemento.Store(Rect); resizing = false; + Resized?.Invoke(rect); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs index dd34c8037..121bad258 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs @@ -122,8 +122,9 @@ 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))); + buttonContainer.RectTransform.IsFixedSize = true; + GUITextBlock.AutoScaleAndNormalize(buttonContainer.Children.Where(c => c is GUIButton).Select(b => ((GUIButton)b).TextBlock)); editor.AddCustomContent(buttonContainer, editor.ContentCount); PositionEditingHUD(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index 7fd043161..8161724be 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -2423,20 +2423,42 @@ namespace Barotrauma.Networking //because tab is used for autocompleting console commands if (msgBox != null) { - if ((PlayerInput.KeyHit(InputType.Chat) || PlayerInput.KeyHit(InputType.RadioChat)) && - GUI.KeyboardDispatcher.Subscriber == null) + if (GUI.KeyboardDispatcher.Subscriber == null) { - if (msgBox.Selected) + bool chatKeyHit = PlayerInput.KeyHit(InputType.Chat); + bool radioKeyHit = PlayerInput.KeyHit(InputType.RadioChat); + + if (chatKeyHit || radioKeyHit) { - msgBox.Text = ""; - msgBox.Deselect(); - } - else - { - msgBox.Select(); - if (Screen.Selected == GameMain.GameScreen && PlayerInput.KeyHit(InputType.RadioChat)) + if (msgBox.Selected) { - msgBox.Text = "r; "; + msgBox.Text = ""; + msgBox.Deselect(); + } + else + { + if (Screen.Selected == GameMain.GameScreen) + { + if (chatKeyHit) + { + msgBox.AddToGUIUpdateList(); + ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f); + ChatBox.ToggleOpen = true; + } + + if (radioKeyHit) + { + msgBox.AddToGUIUpdateList(); + ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f); + ChatBox.ToggleOpen = true; + if (!msgBox.Text.StartsWith(ChatBox.RadioChatString)) + { + msgBox.Text = ChatBox.RadioChatString; + } + } + } + + msgBox.Select(msgBox.Text.Length); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs index 37c70df02..a8844d9b7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs @@ -326,7 +326,7 @@ namespace Barotrauma.Networking return true; } }; - workshopBtn.TextBlock.AutoScale = true; + workshopBtn.TextBlock.AutoScaleHorizontal = true; } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/SteamManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/SteamManager.cs index e7550496a..6b2f569db 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/SteamManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/SteamManager.cs @@ -1383,6 +1383,7 @@ namespace Barotrauma.Steam if (!task.IsCompleted) { cancelTokenSource.Cancel(); + task.Wait(); } return task.Status == TaskStatus.RanToCompletion; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Particles/ParticlePrefab.cs b/Barotrauma/BarotraumaClient/ClientSource/Particles/ParticlePrefab.cs index 974e07cbd..067269913 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Particles/ParticlePrefab.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Particles/ParticlePrefab.cs @@ -152,7 +152,7 @@ namespace Barotrauma.Particles } } - [Editable(0.0f, 10000.0f), Serialize(0.0f, false, description: "Drag applied to the particle when it's moving through water.")] + [Editable(0.0f, 10000.0f), Serialize(0.0f, false, description: "Radius of the particle's collider. Only has an effect if UseCollision is set to true.")] public float CollisionRadius { get; private set; } [Editable, Serialize(false, false, description: "Does the particle collide with the walls of the submarine and the level.")] diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs index 17b39fb47..3adb061d8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs @@ -78,7 +78,7 @@ namespace Barotrauma OnClicked = (btn, userdata) => { SelectTab(Tab.Map); return true; } }; outpostBtn.TextBlock.Font = GUI.LargeFont; - outpostBtn.TextBlock.AutoScale = true; + outpostBtn.TextBlock.AutoScaleHorizontal = true; var tabButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.4f), topPanelContent.RectTransform, Anchor.BottomLeft), isHorizontal: true); @@ -161,7 +161,7 @@ namespace Barotrauma { UserData = "mycrew", CanBeFocused = false, - AutoScale = true + AutoScaleHorizontal = true }; if (campaign is SinglePlayerCampaign) { @@ -170,7 +170,7 @@ namespace Barotrauma { UserData = "hire", CanBeFocused = false, - AutoScale = true + AutoScaleHorizontal = true }; } @@ -210,6 +210,7 @@ namespace Barotrauma 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 storeItemLists = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), storeContent.RectTransform), isHorizontal: true) { @@ -256,7 +257,7 @@ namespace Barotrauma TextManager.Get("MapEntityCategory." + category), textAlignment: Alignment.Center, textColor: categoryButton.TextColor) { Padding = Vector4.Zero, - AutoScale = true, + AutoScaleHorizontal = true, Color = Color.Transparent, HoverColor = Color.Transparent, PressedColor = Color.Transparent, @@ -454,7 +455,7 @@ namespace Barotrauma textAlignment: Alignment.Center, font: GUI.LargeFont, style: "GUISlopedHeader") { UserData = "missionlabel", - AutoScale = true + AutoScaleHorizontal = true }; var missionPanelContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), missionPanel.RectTransform, Anchor.Center)) { @@ -468,10 +469,11 @@ namespace Barotrauma Stretch = true }; 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)) }) + { MinSize = new Point(0, (int)(150 * GUI.Scale)) }) { Visible = false }; + selectedMissionInfo.RectTransform.MaxSize = new Point(int.MaxValue, selectedMissionInfo.Rect.Height * 2); new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), selectedMissionInfo.RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black * 0.9f) { UserData = "outerglow", @@ -676,7 +678,7 @@ namespace Barotrauma var container = selectedLocationInfo; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), location.Name, font: GUI.LargeFont) { - AutoScale = true + AutoScaleHorizontal = true }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), location.Type.Name, font: GUI.SubHeadingFont); @@ -686,7 +688,7 @@ namespace Barotrauma new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), TextManager.Get("SelectMission"), font: GUI.SubHeadingFont) { - AutoScale = true + AutoScaleHorizontal = true }; var missionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.3f), container.RectTransform), style: "InnerFrame"); @@ -784,13 +786,13 @@ namespace Barotrauma selectedMissionInfo.ClearChildren(); var container = selectedMissionInfo.Content; selectedMissionInfo.Visible = selectedMission != null; - selectedMissionInfo.Spacing = 10; + selectedMissionInfo.Spacing = (int)(10 * GUI.Scale); if (selectedMission == null) { return; } new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), selectedMission.Name, font: GUI.LargeFont) { - AutoScale = true, + AutoScaleHorizontal = true, CanBeFocused = false }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), container.RectTransform), @@ -804,6 +806,12 @@ namespace Barotrauma CanBeFocused = false }; + //scale down mission info box if it's much taller than the text + float missionInfoHeight = selectedMissionInfo.Content.Children.Sum(c => c.Rect.Height + selectedMissionInfo.Spacing); + selectedMissionInfo.Content.Children.ForEach(c => c.RectTransform.IsFixedSize = true); + selectedMissionInfo.RectTransform.Resize(new Point(selectedMissionInfo.Rect.Width, (int)(missionInfoHeight + 15 * GUI.Scale))); + selectedMissionInfo.UpdateScrollBarSize(); + if (StartButton != null) { StartButton.Enabled = true; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs index ca7d456dc..5820c166a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CharacterEditor/CharacterEditorScreen.cs @@ -1897,7 +1897,7 @@ namespace Barotrauma.CharacterEditor } // Create the areas - rightArea = new GUILayoutGroup(new RectTransform(new Vector2(0.15f, 0.95f), parent: Frame.RectTransform, anchor: Anchor.CenterRight), childAnchor: Anchor.BottomRight) + rightArea = new GUILayoutGroup(new RectTransform(new Vector2(0.15f, 1.0f), parent: Frame.RectTransform, anchor: Anchor.CenterRight), childAnchor: Anchor.BottomRight) { RelativeSpacing = 0.02f }; @@ -1917,6 +1917,14 @@ namespace Barotrauma.CharacterEditor CreateFileEditPanel(); CreateOptionsPanel(toggleSize); CreateCharacterSelectionPanel(); + if (rightArea.RectTransform.Children.Sum(c => c.Rect.Height) > GameMain.GraphicsHeight) + { + fileEditPanel.GetAllChildren().Where(c => c is GUIButton).ForEach(b => b.RectTransform.MinSize = ((GUIButton)b).Frame.RectTransform.MinSize = b.RectTransform.MinSize.Multiply(new Vector2(1.0f, 0.75f))); + fileEditPanel.RectTransform.MinSize = new Point(0, (int)(fileEditPanel.GetChild().RectTransform.Children.Sum(c => c.Rect.Height) / innerScale.Y)); + optionsPanel.GetAllChildren().Where(c => c is GUITickBox).ForEach(t => t.RectTransform.MinSize = t.RectTransform.MinSize.Multiply(new Vector2(1.0f, 0.75f))); + optionsPanel.RectTransform.MinSize = new Point(0, (int)(optionsPanel.GetChild().RectTransform.Children.Sum(c => c.Rect.Height) / innerScale.Y)); + rightArea.Recalculate(); + } CreateButtonsPanel(); CreateModesPanel(toggleSize); @@ -2686,14 +2694,14 @@ namespace Barotrauma.CharacterEditor } 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.TextBlock.AutoScaleHorizontal = true; prevCharacterButton.OnClicked += (b, obj) => { SpawnCharacter(GetPreviousConfigFile()); return true; }; var nextCharacterButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), charButtons.RectTransform, Anchor.TopRight), GetCharacterEditorTranslation("NextCharacter")); - prevCharacterButton.TextBlock.AutoScale = true; + prevCharacterButton.TextBlock.AutoScaleHorizontal = true; nextCharacterButton.OnClicked += (b, obj) => { SpawnCharacter(GetNextConfigFile()); @@ -3151,7 +3159,6 @@ 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") { OnClicked = (button, data) => diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs index 8b7d7ac27..78577f46d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs @@ -157,7 +157,7 @@ namespace Barotrauma //(= the background texture that's revealed when a wall is destroyed) into the background render target //These will be visible through the LOS effect. spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform); - Submarine.DrawBack(spriteBatch, false, e => e is Structure s); + Submarine.DrawBack(spriteBatch, false, e => e is Structure s && (e.SpriteDepth >= 0.9f || s.Prefab.BackgroundSprite != null)); spriteBatch.End(); graphics.SetRenderTarget(null); @@ -201,7 +201,7 @@ namespace Barotrauma spriteBatch.End(); //Draw the rest of the structures, characters and front structures spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform); - Submarine.DrawBack(spriteBatch, false, s => !(s is Structure)); + Submarine.DrawBack(spriteBatch, false, e => !(e is Structure) || e.SpriteDepth < 0.9f); foreach (Character c in Character.CharacterList) { if (c.AnimController.Limbs.Any(l => l.DeformSprite != null) || !c.IsVisible) { continue; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs index 890df0f63..e7f67856f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs @@ -784,12 +784,12 @@ namespace Barotrauma }; shuttleTickBox.TextBlock.RectTransform.SizeChanged += () => { - shuttleTickBox.TextBlock.AutoScale = true; + shuttleTickBox.TextBlock.AutoScaleHorizontal = true; shuttleTickBox.TextBlock.TextScale = 1.0f; if (shuttleTickBox.TextBlock.TextScale < 0.75f) { shuttleTickBox.TextBlock.Wrap = true; - shuttleTickBox.TextBlock.AutoScale = true; + shuttleTickBox.TextBlock.AutoScaleHorizontal = true; shuttleTickBox.TextBlock.TextScale = 1.0f; } }; @@ -831,13 +831,13 @@ namespace Barotrauma if (child is GUITextBlock textBlock) { textBlock.TextScale = 1; - textBlock.AutoScale = true; + textBlock.AutoScaleHorizontal = true; textBlock.SetTextPos(); } else if (child is GUITickBox tickBox) { tickBox.TextBlock.TextScale = 1; - tickBox.TextBlock.AutoScale = true; + tickBox.TextBlock.AutoScaleHorizontal = true; tickBox.TextBlock.SetTextPos(); } } @@ -1827,7 +1827,7 @@ namespace Barotrauma { UserData = selectedClient }; - viewSteamProfileButton.TextBlock.AutoScale = true; + viewSteamProfileButton.TextBlock.AutoScaleHorizontal = true; viewSteamProfileButton.OnClicked = (bt, userdata) => { Steamworks.SteamFriends.OpenWebOverlay("https://steamcommunity.com/profiles/" + selectedClient.SteamID.ToString()); @@ -2694,7 +2694,7 @@ namespace Barotrauma SelectedColor = Color.Transparent, TextColor = jobPrefab.UIColor, CanBeFocused = false, - AutoScale = true + AutoScaleHorizontal = true }; textBlock.RectTransform.SizeChanged += () => { textBlock.TextScale = 1.0f; }; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs index 8ebe3ca95..58dc10929 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs @@ -185,7 +185,7 @@ namespace Barotrauma { Padding = Vector4.Zero, ForceUpperCase = true, - AutoScale = true + AutoScaleHorizontal = true }; var infoHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.33f), topRow.RectTransform), isHorizontal: true, Anchor.BottomLeft) { RelativeSpacing = 0.01f, Stretch = false }; @@ -279,7 +279,7 @@ namespace Barotrauma var filterTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), filtersHolder.RectTransform), TextManager.Get("FilterServers"), font: GUI.SubHeadingFont) { Padding = Vector4.Zero, - AutoScale = true, + AutoScaleHorizontal = true, CanBeFocused = false }; @@ -1608,7 +1608,6 @@ namespace Barotrauma if (serverInfo.OwnerVerified) { - DebugConsole.NewMessage(serverInfo.OwnerID + " verified!"); var childrenToRemove = serverList.Content.FindChildren(c => (c.UserData is ServerInfo info) && info != serverInfo && (serverInfo.OwnerID != 0 ? info.OwnerID == serverInfo.OwnerID : info.IP == serverInfo.IP)).ToList(); foreach (var child in childrenToRemove) @@ -1637,7 +1636,7 @@ namespace Barotrauma var compatibleBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[0], 0.9f), serverContent.RectTransform, Anchor.Center), label: "") { - Enabled = false, + CanBeFocused = false, Selected = serverInfo.GameVersion == GameMain.Version.ToString() && serverInfo.ContentPackagesMatch(GameMain.SelectedPackages), @@ -1648,7 +1647,7 @@ namespace Barotrauma { ToolTip = TextManager.Get((serverInfo.HasPassword) ? "ServerListHasPassword" : "FilterPassword"), Selected = serverInfo.HasPassword, - Enabled = false, + CanBeFocused = false, UserData = "password" }; @@ -1659,12 +1658,17 @@ namespace Barotrauma ((serverInfo.OwnerID != 0 || serverInfo.LobbyID != 0) ? "[STEAMP2P] " : "[LIDGREN] ") + serverInfo.ServerName, #endif style: "GUIServerListTextBox"); + serverName.UserData = serverName.Text; + serverName.RectTransform.SizeChanged += () => + { + serverName.Text = ToolBox.LimitString(serverName.Text, serverName.Font, serverName.Rect.Width); + }; new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[3], 0.9f), serverContent.RectTransform, Anchor.Center), label: "") { ToolTip = TextManager.Get((serverInfo.GameStarted) ? "ServerListRoundStarted" : "ServerListRoundNotStarted"), Selected = serverInfo.GameStarted, - Enabled = false + CanBeFocused = false }; var serverPlayers = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[4], 1.0f), serverContent.RectTransform), diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SpriteEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SpriteEditorScreen.cs index 8a267922e..3fc91dcf5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SpriteEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SpriteEditorScreen.cs @@ -162,7 +162,7 @@ namespace Barotrauma return true; } }; - resetBtn.TextBlock.AutoScale = true; + resetBtn.TextBlock.AutoScaleHorizontal = true; new GUITickBox(new RectTransform(new Vector2(0.2f, 0.2f), topPanelContents.RectTransform, Anchor.BottomCenter, Pivot.CenterRight) { RelativeOffset = new Vector2(0, 0.3f) }, TextManager.Get("spriteeditor.showgrid")) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SteamWorkshopScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SteamWorkshopScreen.cs index f49c37cd9..78a1f11d7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SteamWorkshopScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SteamWorkshopScreen.cs @@ -868,7 +868,7 @@ namespace Barotrauma t.RectTransform.SizeChanged += () => { t.TextScale = 1.0f; - t.AutoScale = true; + t.AutoScaleHorizontal = true; }; } @@ -1096,25 +1096,20 @@ namespace Barotrauma { 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.TextBlock.AutoScaleHorizontal = true; tagBtn.Selected = itemEditor?.Tags?.Any(t => t.ToLowerInvariant() == tag) ?? false; - Color defaultTextColor = tagBtn.TextColor; - tagBtn.TextColor = tagBtn.Selected ? GUI.Style.Green : defaultTextColor; - tagBtn.OnClicked = (btn, userdata) => { if (!tagBtn.Selected) { if (!(itemEditor?.Tags?.Any(t => t.ToLowerInvariant() == tag) ?? false)) { itemEditor = itemEditor?.WithTag(tagBtn.Text); } tagBtn.Selected = true; - tagBtn.TextColor = GUI.Style.Green; } else { itemEditor?.Tags?.RemoveAll(t => t.ToLowerInvariant() == tagBtn.Text.ToLowerInvariant()); tagBtn.Selected = false; - tagBtn.TextColor = defaultTextColor; } return true; }; @@ -1387,7 +1382,7 @@ namespace Barotrauma return true; } }; - publishBtn.TextBlock.AutoScale = true; + publishBtn.TextBlock.AutoScaleHorizontal = true; } private void OnPreviewImageSelected(GUIImage previewImageElement, string filePath) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 255c2a553..7cd362f63 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -38,6 +38,8 @@ namespace Barotrauma private GUIComponent showEntitiesPanel, entityCountPanel; private List showEntitiesTickBoxes = new List(); + private GUITextBlock subNameLabel; + private bool entityMenuOpen = true; private float entityMenuOpenState = 1.0f; public GUIComponent EntityMenu; @@ -45,11 +47,16 @@ namespace Barotrauma private GUIListBox entityList; private GUIButton toggleEntityMenuButton; + private GUITickBox defaultModeTickBox, wiringModeTickBox, characterModeTickBox; + private GUIComponent loadFrame, saveFrame; private GUITextBox nameBox, descriptionBox; + private GUIButton selectedCategoryButton; + private GUITextBlock selectedCategoryText; private readonly List entityCategoryButtons = new List(); + private MapEntityCategory? selectedCategory; private GUIFrame hullVolumeFrame; @@ -61,8 +68,6 @@ namespace Barotrauma private GUIDropDown linkedSubBox; - private GUIRadioButtonGroup modeButtonGroup; - //a Character used for picking up and manipulating items private Character dummyCharacter; @@ -89,15 +94,10 @@ namespace Barotrauma get { return cam; } } - public string GetSubName() - { - return (Submarine.MainSub == null) ? "" : Submarine.MainSub.Name; - } - public string GetSubDescription() { - string localizedDescription = TextManager.Get("submarine.description." + GetSubName(), true); - if (localizedDescription != null) return localizedDescription; + string localizedDescription = TextManager.Get("submarine.description." + (Submarine.MainSub?.Name ?? ""), true); + if (localizedDescription != null) { return localizedDescription; } return (Submarine.MainSub == null) ? "" : Submarine.MainSub.Description; } @@ -214,11 +214,8 @@ namespace Barotrauma 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 - }; + subNameLabel = new GUITextBlock(new RectTransform(new Vector2(0.3f, 0.9f), paddedTopPanel.RectTransform, Anchor.CenterLeft), + TextManager.Get("unspecifiedsubfilename"), font: GUI.LargeFont, textAlignment: Alignment.CenterLeft); linkedSubBox = new GUIDropDown(new RectTransform(new Vector2(0.15f, 0.9f), paddedTopPanel.RectTransform), TextManager.Get("AddSubButton"), elementCount: 20) @@ -238,52 +235,36 @@ namespace Barotrauma new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), paddedTopPanel.RectTransform), style: "VerticalLine"); - modeButtonGroup = new GUIRadioButtonGroup(); - - var defaultModeTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "EditSubButton") + defaultModeTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "EditSubButton") { ToolTip = TextManager.Get("SubEditorEditingMode"), OnSelected = (GUITickBox tBox) => { - if (tBox.Selected) - { - SetMode(Mode.Default); - } + if (tBox.Selected) { SetMode(Mode.Default); } return true; } }; - var characterModeTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "CharacterModeButton") + characterModeTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "CharacterModeButton") { ToolTip = TextManager.Get("CharacterModeButton") + '\n' + TextManager.Get("CharacterModeToolTip"), OnSelected = (GUITickBox tBox) => { - if (tBox.Selected) - { - SetMode(Mode.Character); - } + SetMode(tBox.Selected ? Mode.Character : Mode.Default); return true; } }; - var wiringModeTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "WiringModeButton") + wiringModeTickBox = new GUITickBox(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "WiringModeButton") { ToolTip = TextManager.Get("WiringModeButton") + '\n' + TextManager.Get("WiringModeToolTip"), OnSelected = (GUITickBox tBox) => { - if (tBox.Selected) - { - SetMode(Mode.Wiring); - } + SetMode(tBox.Selected ? Mode.Wiring : Mode.Default); return true; } }; - 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") @@ -294,7 +275,7 @@ namespace Barotrauma new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), paddedTopPanel.RectTransform), style: "VerticalLine"); - var visibilityButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "SetupVisibilityButton") + var visibilityButton = new GUIButton(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "SetupVisibilityButton") { ToolTip = TextManager.Get("SubEditorVisibilityButton") + '\n' + TextManager.Get("SubEditorVisibilityToolTip"), OnClicked = (btn, userData) => @@ -306,7 +287,7 @@ namespace Barotrauma } }; - var previouslyUsedButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "RecentlyUsedButton") + var previouslyUsedButton = new GUIButton(new RectTransform(new Vector2(0.9f, 0.9f), paddedTopPanel.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "RecentlyUsedButton") { ToolTip = TextManager.Get("PreviouslyUsedLabel"), OnClicked = (btn, userData) => @@ -536,7 +517,7 @@ namespace Barotrauma 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.TextBlock.AutoScaleHorizontal = true; saveAssemblyButton.OnClicked += (btn, userdata) => { CreateSaveAssemblyScreen(); @@ -567,7 +548,7 @@ namespace Barotrauma var paddedTab = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.96f), EntityMenu.RectTransform, Anchor.BottomCenter), childAnchor: Anchor.TopCenter) { - RelativeSpacing = 0.05f, + RelativeSpacing = 0.04f, Stretch = true }; @@ -576,22 +557,28 @@ namespace Barotrauma Stretch = true }; - var selectedCategoryButton = new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), entityMenuTop.RectTransform, scaleBasis: ScaleBasis.BothHeight), "", style: "CategoryButton.All") + 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); + selectedCategoryText = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), entityMenuTop.RectTransform), TextManager.Get("MapEntityCategory.All"), font: GUI.LargeFont); + + 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.17f, 1.0f), entityMenuTop.RectTransform), font: GUI.Font, createClearButton: true); + entityFilterBox.OnTextChanged += (textBox, text) => { FilterEntities(text); return true; }; + + //spacing + new GUIFrame(new RectTransform(new Vector2(0.075f, 1.0f), entityMenuTop.RectTransform), style: null); 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(); + OnClicked = (btn, userdata) => + { + if (!string.IsNullOrEmpty(entityFilterBox.Text)) { ClearFilter(); } + OpenEntityMenu(null); return true; } }); @@ -605,20 +592,14 @@ namespace Barotrauma ToolTip = TextManager.Get("MapEntityCategory." + category.ToString()), OnClicked = (btn, userdata) => { - entityMenuOpen = true; + if (!string.IsNullOrEmpty(entityFilterBox.Text)) { ClearFilter(); } 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; }; + entityCategoryButtons.ForEach(b => b.RectTransform.MaxSize = new Point(b.Rect.Height)); new GUIFrame(new RectTransform(new Vector2(0.8f, 0.01f), paddedTab.RectTransform), style: "HorizontalLine"); @@ -636,7 +617,7 @@ namespace Barotrauma { entityList.Content.ClearChildren(); - int entitiesPerRow = (int)Math.Ceiling(entityList.Content.Rect.Width / Math.Max(125 * GUI.Scale, 100)); + int entitiesPerRow = (int)Math.Ceiling(entityList.Content.Rect.Width / Math.Max(125 * GUI.Scale, 60)); foreach (MapEntityPrefab ep in MapEntityPrefab.List) { @@ -762,6 +743,9 @@ namespace Barotrauma UpdateEntityList(); + string name = (Submarine.MainSub == null) ? TextManager.Get("unspecifiedsubfilename") : Submarine.MainSub.Name; + subNameLabel.Text = ToolBox.LimitString(name, subNameLabel.Font, subNameLabel.Rect.Width); + foreach (MapEntityPrefab prefab in MapEntityPrefab.List) { prefab.sprite?.EnsureLazyLoaded(); @@ -1000,7 +984,6 @@ namespace Barotrauma if (string.IsNullOrWhiteSpace(nameBox.Text)) { GUI.AddMessage(TextManager.Get("SubNameMissingWarning"), GUI.Style.Red); - nameBox.Flash(); return false; } @@ -1069,6 +1052,8 @@ namespace Barotrauma linkedSubBox.AddItem(sub.Name, sub); } + subNameLabel.Text = ToolBox.LimitString(Submarine.MainSub.Name, subNameLabel.Font, subNameLabel.Rect.Width); + saveFrame = null; return false; @@ -1102,8 +1087,7 @@ namespace Barotrauma nameBox = new GUITextBox(new RectTransform(new Vector2(.95f, 0.05f), leftColumn.RectTransform)) { - OnEnterPressed = ChangeSubName, - Text = GetSubName() + OnEnterPressed = ChangeSubName }; nameBox.OnTextChanged += (textBox, text) => { @@ -1627,6 +1611,9 @@ namespace Barotrauma Submarine.MainSub.SetPrevTransform(Submarine.MainSub.Position); Submarine.MainSub.UpdateTransform(); + string name = Submarine.MainSub.Name; + subNameLabel.Text = ToolBox.LimitString(name, subNameLabel.Font, subNameLabel.Rect.Width); + cam.Position = Submarine.MainSub.Position + Submarine.MainSub.HiddenSubPosition; loadFrame = null; @@ -1700,22 +1687,25 @@ namespace Barotrauma msgBox.Buttons[1].OnClicked += msgBox.Close; } - private bool OpenEntityMenu(MapEntityCategory selectedCategory) + private bool OpenEntityMenu(MapEntityCategory? selectedCategory) { - entityFilterBox.Text = ""; + foreach (GUIButton categoryButton in entityCategoryButtons) + { + categoryButton.Selected = selectedCategory.HasValue ? + categoryButton.UserData is MapEntityCategory category && selectedCategory.Value == category : + categoryButton.UserData == null; + string categoryName = selectedCategory.HasValue ? selectedCategory.Value.ToString() : "All"; + selectedCategoryText.Text = TextManager.Get("MapEntityCategory." + categoryName); + selectedCategoryButton.ApplyStyle(GUI.Style.GetComponentStyle("CategoryButton." + categoryName)); + } + + this.selectedCategory = selectedCategory; + SetMode(Mode.Default); saveFrame = null; loadFrame = null; - - ClearFilter(); - foreach (GUIButton button in entityCategoryButtons) - { - button.Selected = - button.UserData != null && - (MapEntityCategory)button.UserData == selectedCategory; - } - + foreach (GUIComponent child in toggleEntityMenuButton.Children) { child.SpriteEffects = entityMenuOpen ? SpriteEffects.None : SpriteEffects.FlipVertically; @@ -1723,7 +1713,7 @@ namespace Barotrauma foreach (GUIComponent child in entityList.Content.Children) { - child.Visible = ((MapEntityPrefab)child.UserData).Category == selectedCategory; + child.Visible = !selectedCategory.HasValue || ((MapEntityPrefab)child.UserData).Category == selectedCategory; } entityList.UpdateScrollBarSize(); entityList.BarScroll = 0.0f; @@ -1733,14 +1723,9 @@ namespace Barotrauma private bool FilterEntities(string filter) { - foreach (GUIButton button in entityCategoryButtons) - { - button.Selected = false; - } - if (string.IsNullOrWhiteSpace(filter)) { - entityList.Content.Children.ForEach(c => c.Visible = true); + entityList.Content.Children.ForEach(c => c.Visible = !selectedCategory.HasValue || selectedCategory == ((MapEntityPrefab)c.UserData).Category); return true; } @@ -1748,7 +1733,9 @@ namespace Barotrauma foreach (GUIComponent child in entityList.Content.Children) { var textBlock = child.GetChild(); - child.Visible = ((MapEntityPrefab)child.UserData).Name.ToLower().Contains(filter); + child.Visible = + (!selectedCategory.HasValue || selectedCategory == ((MapEntityPrefab)child.UserData).Category) && + ((MapEntityPrefab)child.UserData).Name.ToLower().Contains(filter); } entityList.UpdateScrollBarSize(); entityList.BarScroll = 0.0f; @@ -1768,9 +1755,13 @@ namespace Barotrauma public void SetMode(Mode mode) { if (mode == this.mode) { return; } - this.mode = mode; - modeButtonGroup.Selected = (int)mode; + + defaultModeTickBox.Selected = mode == Mode.Default; + defaultModeTickBox.CanBeFocused = !defaultModeTickBox.Selected; + + characterModeTickBox.Selected = mode == Mode.Character; + wiringModeTickBox.Selected = mode == Mode.Wiring; switch (mode) { @@ -1855,10 +1846,11 @@ namespace Barotrauma { if (!child.Enabled) { child.TextColor *= 0.5f; } } - + + contextMenu.Content.Children.ForEach(c => c.RectTransform.MinSize = new Point(0, c.Rect.Height)); contextMenu.RectTransform.NonScaledSize = new Point( contextMenu.Rect.Width, - (int)((contextMenu.Content.CountChildren * 18) * GUI.Scale)); + (int)((contextMenu.Content.CountChildren * 20) * GUI.Scale)); contextMenu.OnSelected = (GUIComponent component, object obj) => { @@ -2411,6 +2403,11 @@ namespace Barotrauma hullVolumeFrame.Visible = MapEntity.SelectedList.Any(s => s is Hull); saveAssemblyFrame.Visible = MapEntity.SelectedList.Count > 0; + + if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Tab)) + { + entityFilterBox.Select(); + } cam.MoveCamera((float)deltaTime, true); if (PlayerInput.MidButtonHeld()) @@ -2615,9 +2612,11 @@ namespace Barotrauma GUI.DrawLine(spriteBatch, new Vector2(Submarine.MainSub.HiddenSubPosition.X, -cam.WorldView.Y), new Vector2(Submarine.MainSub.HiddenSubPosition.X, -(cam.WorldView.Y - cam.WorldView.Height)), Color.White * 0.5f, 1.0f, (int)(2.0f / cam.Zoom)); GUI.DrawLine(spriteBatch, new Vector2(cam.WorldView.X, -Submarine.MainSub.HiddenSubPosition.Y), new Vector2(cam.WorldView.Right, -Submarine.MainSub.HiddenSubPosition.Y), Color.White * 0.5f, 1.0f, (int)(2.0f / cam.Zoom)); } - - Submarine.DrawBack(spriteBatch, editing: true); + Submarine.DrawBack(spriteBatch, true, e => e is Structure s && (e.SpriteDepth >= 0.9f || s.Prefab.BackgroundSprite != null)); + spriteBatch.End(); + spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, transformMatrix: cam.Transform); + Submarine.DrawBack(spriteBatch, true, e => !(e is Structure) || e.SpriteDepth < 0.9f); spriteBatch.End(); spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, transformMatrix: cam.Transform); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs index 15f332f9e..2c442a4b0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Serialization/SerializableEntityEditor.cs @@ -277,7 +277,7 @@ namespace Barotrauma 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) + new GUITextBlock(new RectTransform(new Point(layoutGroup.Rect.Width, this.elementHeight), layoutGroup.RectTransform, isFixedSize: true), entity.Name, font: titleFont ?? GUI.Font) { TextColor = Color.White, Color = Color.Black @@ -392,7 +392,7 @@ namespace Barotrauma public GUIComponent CreateBoolField(ISerializableEntity entity, SerializableProperty property, bool value, string displayName, string toolTip) { - GUITickBox propertyTickBox = new GUITickBox(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), displayName) + GUITickBox propertyTickBox = new GUITickBox(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform, isFixedSize: true), displayName) { Font = GUI.SmallFont, Selected = value, @@ -412,7 +412,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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip @@ -453,7 +453,7 @@ 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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - 1, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip @@ -476,6 +476,7 @@ namespace Barotrauma { if (property.TrySetValue(entity, numInput.FloatValue)) { + numInput.FloatValue = (float)property.GetValue(entity); TrySendNetworkUpdate(entity, property); } }; @@ -485,7 +486,7 @@ 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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip @@ -514,7 +515,7 @@ 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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip @@ -547,7 +548,7 @@ 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, childAnchor: Anchor.CenterLeft) + var frame = new GUILayoutGroup(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform, isFixedSize: true), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true }; @@ -608,7 +609,7 @@ 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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip @@ -661,7 +662,7 @@ 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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - inputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip @@ -716,7 +717,7 @@ 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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - largeInputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip @@ -775,7 +776,7 @@ 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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - largeInputFieldWidth, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = toolTip @@ -838,7 +839,7 @@ 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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(1.0f - largeInputFieldWidth, 1), frame.RectTransform) { MinSize = new Point(80, 26) }, displayName, font: GUI.SmallFont) { ToolTip = displayName + '\n' + toolTip @@ -910,7 +911,7 @@ 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 frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform, isFixedSize: true), color: Color.Transparent); var label = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1), frame.RectTransform), displayName, font: GUI.SmallFont) { ToolTip = displayName + '\n' + toolTip diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/OpenAL/Alc.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/OpenAL/Alc.cs index 3159ff805..195731d78 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/OpenAL/Alc.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/OpenAL/Alc.cs @@ -120,6 +120,27 @@ namespace OpenAL [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetError")] public static extern int GetError(IntPtr device); + public static string GetErrorString(int errorCode) + { + switch (errorCode) + { + case NoError: + return "No error"; + case InvalidContext: + return "Invalid context"; + case InvalidDevice: + return "Invalid device"; + case InvalidEnum: + return "Invalid enum"; + case InvalidValue: + return "Invalid value"; + case OutOfMemory: + return "Out of memory"; + default: + return "Unknown error"; + } + } + [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcIsExtensionPresent")] public static extern bool IsExtensionPresent(IntPtr device, string extname); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs index ccb47ec11..15f0aa097 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs @@ -195,31 +195,39 @@ namespace Barotrauma.Sounds loadedSounds = new List(); streamingThread = null; categoryModifiers = null; - - alcDevice = Alc.OpenDevice(null); - if (alcDevice == null) + + int alcError = Alc.NoError; + + string deviceName = Alc.GetString(IntPtr.Zero, Alc.DefaultDeviceSpecifier); + DebugConsole.NewMessage($"Attempting to open ALC device \"{deviceName}\""); + + alcDevice = IntPtr.Zero; + for (int i = 0; i < 3; i++) { - DebugConsole.ThrowError("Failed to open an ALC device! Disabling audio playback..."); - Disabled = true; - return; - } - - int alcError = Alc.GetError(alcDevice); - if (alcError != Alc.NoError) - { - //The audio device probably wasn't ready, this happens quite often - //Just wait a while and try again - Thread.Sleep(100); - - alcDevice = Alc.OpenDevice(null); - - alcError = Alc.GetError(alcDevice); - if (alcError != Alc.NoError) + alcDevice = Alc.OpenDevice(deviceName); + if (alcDevice == IntPtr.Zero) { - DebugConsole.ThrowError("Error initializing ALC device: " + alcError.ToString() + ". Disabling audio playback..."); - Disabled = true; - return; + DebugConsole.NewMessage($"ALC device initialization attempt #{i + 1} failed: device is null"); } + else + { + alcError = Alc.GetError(alcDevice); + if (alcError != Alc.NoError) + { + DebugConsole.NewMessage($"ALC device initialization attempt #{i + 1} failed: error code {Alc.GetErrorString(alcError)}"); + bool closed = Alc.CloseDevice(alcDevice); + if (!closed) + { + DebugConsole.NewMessage($"Failed to close ALC device"); + } + alcDevice = IntPtr.Zero; + } + } + } + if (alcDevice == IntPtr.Zero) + { + DebugConsole.ThrowError("ALC device creation failed too many times!"); + Disabled = true; } int[] alcContextAttrs = new int[] { }; @@ -241,7 +249,7 @@ namespace Barotrauma.Sounds alcError = Alc.GetError(alcDevice); if (alcError != Alc.NoError) { - DebugConsole.ThrowError("Error after assigning ALC context: " + alcError.ToString() + ". Disabling audio playback..."); + DebugConsole.ThrowError("Error after assigning ALC context: " + Alc.GetErrorString(alcError) + ". Disabling audio playback..."); Disabled = true; return; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Utils/LocalizationCSVtoXML.cs b/Barotrauma/BarotraumaClient/ClientSource/Utils/LocalizationCSVtoXML.cs index 11849a5a3..6f412a170 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Utils/LocalizationCSVtoXML.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Utils/LocalizationCSVtoXML.cs @@ -18,9 +18,10 @@ namespace Barotrauma private const string infoTextPath = "Content/Texts"; private const string xmlHeader = ""; - private static string[,] translatedLanguageNames = new string[12, 2] { { "English", "English" }, { "French", "Français" }, { "German", "Deutsch" }, + private static string[,] translatedLanguageNames = new string[13, 2] { { "English", "English" }, { "French", "Français" }, { "German", "Deutsch" }, { "Russian", "Русский" }, { "Brazilian Portuguese", "Português brasileiro" }, { "Simplified Chinese", "中文(简体)" }, { "Traditional Chinese", "中文(繁體)" }, - { "Castilian Spanish", "Castellano" }, { "Latinamerican Spanish", "Español Latinoamericano" }, { "Polish", "Polski" }, { "Turkish", "Türkçe" }, { "Japanese", "日本語" } }; + { "Castilian Spanish", "Castellano" }, { "Latinamerican Spanish", "Español Latinoamericano" }, { "Polish", "Polski" }, { "Turkish", "Türkçe" }, + { "Japanese", "日本語" }, { "Korean", "한국어" } }; public static void Convert() { @@ -81,7 +82,7 @@ namespace Barotrauma continue; } string xmlFileFullPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}/NpcConversations_{languageNoWhitespace}_NEW.xml"; - File.WriteAllLines(xmlFileFullPath, xmlContent); + File.WriteAllLines(xmlFileFullPath, xmlContent, Encoding.UTF8); DebugConsole.NewMessage("Conversation localization .xml file successfully created at: " + xmlFileFullPath); } @@ -94,7 +95,7 @@ namespace Barotrauma continue; } string xmlFileFullPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}/{languageNoWhitespace}Vanilla_NEW.xml"; - File.WriteAllLines(xmlFileFullPath, xmlContent); + File.WriteAllLines(xmlFileFullPath, xmlContent, Encoding.UTF8); DebugConsole.NewMessage("InfoText localization .xml file successfully created at: " + xmlFileFullPath); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Utils/ToolBox.cs b/Barotrauma/BarotraumaClient/ClientSource/Utils/ToolBox.cs index f482c401c..4d14e506d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Utils/ToolBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Utils/ToolBox.cs @@ -114,7 +114,7 @@ namespace Barotrauma public static string WrapText(string text, float lineLength, ScalableFont font, float textScale = 1.0f, bool playerInput = false) //TODO: could integrate this into the ScalableFont class directly { Vector2 textSize = font.MeasureString(text); - if (textSize.X < lineLength) { return text; } + if (textSize.X <= lineLength) { return text; } if (!playerInput) { diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index cdcfe3c8e..eb66cd697 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.9.702.0 + 0.9.703.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index d6414dc0d..de5014235 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -11,7 +11,7 @@ AnyCPU;x64 Barotrauma ..\BarotraumaShared\Icon.ico - 0.9.0.0 + 0.9.703.0 Debug;Release;Unstable diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index 4f701d93f..ecced590d 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.9.702.0 + 0.9.703.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index e14f65a74..b40af5df1 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.9.702.0 + 0.9.703.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index e1f5e4e95..1e2c5358f 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.9.702.0 + 0.9.703.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs index c251f7908..8497f6b7f 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs @@ -248,6 +248,16 @@ namespace Barotrauma } } + private static Client FindClient(string arg) + { + int.TryParse(arg, out int id); + var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + client ??= GameMain.Server.ConnectedClients.Find(c => c.EndpointMatches(arg)); + client ??= GameMain.Server.ConnectedClients.Find(c => c.SteamID == Steam.SteamManager.SteamIDStringToUInt64(arg)); + client ??= GameMain.Server.ConnectedClients.Find(c => Homoglyphs.Compare(c.Name, arg)); + return client; + } + private static void AssignOnClientRequestExecute(string names, Action onClientRequestExecute) { var matchingCommand = commands.Find(c => c.names.Intersect(names.Split('|')).Count() > 0); @@ -406,11 +416,10 @@ namespace Barotrauma return; } - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - ThrowError("Client id \"" + id + "\" not found."); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -430,7 +439,7 @@ namespace Barotrauma client.GivePermission(permission); GameMain.Server.UpdateClientPermissions(client); NewMessage("Granted " + perm + " permissions to " + client.Name + ".", Color.White); - }); + }, args, 2); }); AssignOnExecute("revokeperm", (string[] args) => @@ -442,11 +451,10 @@ namespace Barotrauma return; } - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - ThrowError("Client id \"" + id + "\" not found."); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -466,7 +474,7 @@ namespace Barotrauma client.RemovePermission(permission); GameMain.Server.UpdateClientPermissions(client); NewMessage("Revoked " + perm + " permissions from " + client.Name + ".", Color.White); - }); + }, args, 2); }); AssignOnExecute("giverank", (string[] args) => @@ -474,15 +482,14 @@ namespace Barotrauma if (GameMain.Server == null) return; if (args.Length < 1) { - NewMessage("giverank [id]: Assigns a specific rank(= a set of administrative permissions) to the player with the specified client ID.", Color.Cyan); + NewMessage("giverank [id/steamid/endpoint/name] [rank]: Assigns a specific rank (= a set of administrative permissions) to the player with the specified client ID.", Color.Cyan); return; } - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - ThrowError("Client id \"" + id + "\" not found."); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -504,7 +511,7 @@ namespace Barotrauma client.SetPermissions(preset.Permissions, preset.PermittedCommands); GameMain.Server.UpdateClientPermissions(client); NewMessage("Assigned the rank \"" + preset.Name + "\" to " + client.Name + ".", Color.White); - }); + }, args, 2); }); AssignOnExecute("givecommandperm", (string[] args) => @@ -516,11 +523,10 @@ namespace Barotrauma return; } - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - ThrowError("Client id \"" + id + "\" not found."); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -546,7 +552,7 @@ namespace Barotrauma client.SetPermissions(client.Permissions, client.PermittedConsoleCommands.Union(grantedCommands).Distinct().ToList()); GameMain.Server.UpdateClientPermissions(client); NewMessage("Gave the client \"" + client.Name + "\" the permission to use console commands " + string.Join(", ", grantedCommands.Select(c => c.names[0])) + ".", Color.White); - }); + }, args, 2); }); AssignOnExecute("revokecommandperm", (string[] args) => @@ -558,11 +564,10 @@ namespace Barotrauma return; } - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - ThrowError("Client id \"" + id + "\" not found."); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -587,7 +592,7 @@ namespace Barotrauma client.SetPermissions(client.Permissions, client.PermittedConsoleCommands.Except(revokedCommands).ToList()); GameMain.Server.UpdateClientPermissions(client); NewMessage("Revoked \"" + client.Name + "\"'s permission to use the console commands " + string.Join(", ", revokedCommands.Select(c => c.names[0])) + ".", Color.White); - }); + }, args, 2); }); AssignOnExecute("showperm", (string[] args) => @@ -599,11 +604,10 @@ namespace Barotrauma return; } - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - ThrowError("Client id \"" + id + "\" not found."); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -1571,11 +1575,10 @@ namespace Barotrauma { if (args.Length < 2) return; - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - GameMain.Server.SendConsoleMessage("Client id \"" + id + "\" not found.", senderClient); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -1600,11 +1603,10 @@ namespace Barotrauma { if (args.Length < 2) return; - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - GameMain.Server.SendConsoleMessage("Client id \"" + id + "\" not found.", senderClient); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -1629,11 +1631,10 @@ namespace Barotrauma { if (args.Length < 2) return; - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - GameMain.Server.SendConsoleMessage("Client id \"" + id + "\" not found.", senderClient); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -1658,11 +1659,10 @@ namespace Barotrauma { if (args.Length < 2) return; - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - GameMain.Server.SendConsoleMessage("Client id \"" + id + "\" not found.", senderClient); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -1696,11 +1696,10 @@ namespace Barotrauma { if (args.Length < 2) return; - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - GameMain.Server.SendConsoleMessage("Client id \"" + id + "\" not found.", senderClient); + ThrowError("Client \"" + args[0] + "\" not found."); return; } @@ -1738,11 +1737,10 @@ namespace Barotrauma return; } - int.TryParse(args[0], out int id); - var client = GameMain.Server.ConnectedClients.Find(c => c.ID == id); + var client = FindClient(args[0]); if (client == null) { - GameMain.Server.SendConsoleMessage("Client id \"" + id + "\" not found.", senderClient); + ThrowError("Client \"" + args[0] + "\" not found."); return; } diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs index 727947c01..9565e3adf 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs @@ -107,6 +107,7 @@ namespace Barotrauma ScriptedEventSet.LoadPrefabs(); AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions)); + SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings)); StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure)); ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item)); JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs)); diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs index 9069c1946..dc3a1d4ae 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Reactor.cs @@ -13,7 +13,7 @@ namespace Barotrauma.Items.Components public void ServerRead(ClientNetObject type, IReadMessage msg, Client c) { bool autoTemp = msg.ReadBoolean(); - bool shutDown = msg.ReadBoolean(); + bool powerOn = msg.ReadBoolean(); float fissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); float turbineOutput = msg.ReadRangedSingle(0.0f, 100.0f, 8); @@ -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._powerOn && shutDown) blameOnBroken = c; + if (!_powerOn && powerOn) blameOnBroken = c; AutoTemp = autoTemp; - this._powerOn = shutDown; + _powerOn = powerOn; targetFissionRate = fissionRate; targetTurbineOutput = turbineOutput; diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index db79485db..0dd7868f6 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -327,6 +327,12 @@ namespace Barotrauma.Networking #endif if (!started) { return; } + if (OwnerConnection != null && ChildServerRelay.HasShutDown) + { + Disconnect(); + return; + } + base.Update(deltaTime); fileSender.Update(deltaTime); diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index fdf2b7c3b..8ed3c8daf 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.9.702.0 + 0.9.703.0 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml index fce51ea89..97c5d3597 100644 --- a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml +++ b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml @@ -103,6 +103,7 @@ + @@ -130,10 +131,12 @@ + + diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs index 95b2c5e28..e0cd0198f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs @@ -296,14 +296,14 @@ namespace Barotrauma } float multiplier = MathHelper.Lerp(1, 10, MathHelper.Clamp(collider.LinearVelocity.Length() / 10, 0, 1)); float targetDistance = collider.GetSize().X * multiplier; - float horizontalDistance = Math.Abs(collider.SimPosition.X - currentPath.CurrentNode.SimPosition.X); - float verticalDistance = Math.Abs(collider.SimPosition.Y - currentPath.CurrentNode.SimPosition.Y); + float horizontalDistance = Math.Abs(character.WorldPosition.X - currentPath.CurrentNode.WorldPosition.X); + float verticalDistance = Math.Abs(character.WorldPosition.Y - currentPath.CurrentNode.WorldPosition.Y); if (character.CurrentHull != currentPath.CurrentNode.CurrentHull) { verticalDistance *= 2; } float distance = horizontalDistance + verticalDistance; - if (distance < targetDistance) + if (ConvertUnits.ToSimUnits(distance) < targetDistance) { currentPath.SkipToNextNode(); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs index 3d279cb85..14bb6e791 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Order.cs @@ -74,6 +74,8 @@ namespace Barotrauma public readonly Dictionary OptionSprites; + public readonly float Weight; + static Order() { Prefabs = new Dictionary(); @@ -172,6 +174,9 @@ namespace Barotrauma PrefabList = new List(Prefabs.Values); } + /// + /// Constructor for order prefabs + /// private Order(XElement orderElement) { Identifier = orderElement.GetAttributeString("identifier", ""); @@ -199,6 +204,7 @@ namespace Barotrauma 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); + Weight = orderElement.GetAttributeFloat(0.0f, "weight"); string translatedOptionNames = TextManager.Get("OrderOptions." + Identifier, true); if (translatedOptionNames == null) @@ -243,6 +249,9 @@ namespace Barotrauma } } + /// + /// Constructor for order instances + /// public Order(Order prefab, Entity targetEntity, ItemComponent targetItem, Character orderGiver = null) { Prefab = prefab; @@ -257,6 +266,7 @@ namespace Barotrauma TargetAllCharacters = prefab.TargetAllCharacters; AppropriateJobs = prefab.AppropriateJobs; FadeOutTime = prefab.FadeOutTime; + Weight = prefab.Weight; OrderGiver = orderGiver; TargetEntity = targetEntity; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs index caf7425cf..cf3bc553d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/HumanoidAnimController.cs @@ -1407,7 +1407,7 @@ namespace Barotrauma target.CharacterHealth.CalculateVitality(); if (wasCritical && target.Vitality > 0.0f && Timing.TotalTime > lastReviveTime + 10.0f) { - character.Info.IncreaseSkillLevel("medical", 0.5f, character.WorldPosition + Vector2.UnitY * 150.0f); + character.Info.IncreaseSkillLevel("medical", SkillSettings.Current.SkillIncreasePerCprRevive, character.WorldPosition + Vector2.UnitY * 150.0f); SteamAchievementManager.OnCharacterRevived(target, character); lastReviveTime = (float)Timing.TotalTime; #if SERVER diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs index 40b7dab76..287e0704b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs @@ -138,6 +138,8 @@ namespace Barotrauma private readonly List statusEffects = new List(); private readonly List speedMultipliers = new List(); + private float greatestNegativeSpeedMultiplier = 1f; + private float greatestPositiveSpeedMultiplier = 1f; public Entity ViewTarget { @@ -1069,42 +1071,32 @@ namespace Barotrauma { get { - if (speedMultipliers.Count == 0) return 1f; - - float greatestPositive = 1f; - float greatestNegative = 1f; - - for (int i = 0; i < speedMultipliers.Count; i++) - { - float val = speedMultipliers[i]; - if (val < 1f) - { - if (val < greatestNegative) - { - greatestNegative = val; - } - } - else - { - if (val > greatestPositive) - { - greatestPositive = val; - } - } - } - - return greatestPositive - (1f - greatestNegative); + return greatestPositiveSpeedMultiplier - (1f - greatestNegativeSpeedMultiplier); } - set + } + + public void StackSpeedMultiplier(float val) + { + if (val < 1f) { - if (value == 1f) return; - speedMultipliers.Add(value); + if (val < greatestNegativeSpeedMultiplier) + { + greatestNegativeSpeedMultiplier = val; + } + } + else + { + if (val > greatestPositiveSpeedMultiplier) + { + greatestPositiveSpeedMultiplier = val; + } } } public void ResetSpeedMultiplier() { - speedMultipliers.Clear(); + greatestPositiveSpeedMultiplier = 1f; + greatestNegativeSpeedMultiplier = 1f; } public float ApplyTemporarySpeedLimits(float speed) @@ -1440,6 +1432,7 @@ namespace Barotrauma public bool HasEquippedItem(Item item) { + if (Inventory == null) { return false; } for (int i = 0; i < Inventory.Capacity; i++) { if (Inventory.Items[i] == item && Inventory.SlotTypes[i] != InvSlotType.Any) return true; @@ -2339,15 +2332,16 @@ namespace Barotrauma } private readonly List aiChatMessageQueue = new List(); - private readonly List prevAiChatMessages = new List(); + + //key = identifier, value = time the message was sent + private readonly Dictionary prevAiChatMessages = new Dictionary(); public void DisableLine(string identifier) { - var dummyMsg = new AIChatMessage("", ChatMessageType.Default, identifier) + if (!string.IsNullOrEmpty(identifier)) { - SendTime = Timing.TotalTime - }; - prevAiChatMessages.Add(dummyMsg); + prevAiChatMessages[identifier] = (float)Timing.TotalTime; + } } public void Speak(string message, ChatMessageType? messageType = null, float delay = 0.0f, string identifier = "", float minDurationBetweenSimilar = 0.0f) @@ -2355,10 +2349,15 @@ namespace Barotrauma if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; } if (string.IsNullOrEmpty(message)) { return; } + if (prevAiChatMessages.ContainsKey(identifier) && + prevAiChatMessages[identifier] < Timing.TotalTime - minDurationBetweenSimilar) + { + prevAiChatMessages.Remove(identifier); + } + //already sent a similar message a moment ago if (!string.IsNullOrEmpty(identifier) && minDurationBetweenSimilar > 0.0f && - (aiChatMessageQueue.Any(m => m.Identifier == identifier) || - prevAiChatMessages.Any(m => m.Identifier == identifier && m.SendTime > Timing.TotalTime - minDurationBetweenSimilar))) + (aiChatMessageQueue.Any(m => m.Identifier == identifier) || prevAiChatMessages.ContainsKey(identifier))) { return; } @@ -2403,15 +2402,25 @@ namespace Barotrauma { sent.SendTime = Timing.TotalTime; aiChatMessageQueue.Remove(sent); - prevAiChatMessages.Add(sent); + if (!string.IsNullOrEmpty(sent.Identifier)) + { + prevAiChatMessages[sent.Identifier] = (float)sent.SendTime; + } } - for (int i = prevAiChatMessages.Count - 1; i >= 0; i--) + if (prevAiChatMessages.Count > 100) { - if (prevAiChatMessages[i].SendTime < Timing.TotalTime - 60.0f) + List toRemove = new List(); + foreach (KeyValuePair prevMessage in prevAiChatMessages) { - prevAiChatMessages.RemoveRange(0, i + 1); - break; + if (prevMessage.Value < Timing.TotalTime - 60.0f) + { + toRemove.Add(prevMessage.Key); + } + } + foreach (string identifier in toRemove) + { + prevAiChatMessages.Remove(identifier); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs index 89e418f94..093de4d3b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs @@ -619,7 +619,7 @@ namespace Barotrauma { UpdateBleedingProjSpecific((AfflictionBleeding)affliction, targetLimb, deltaTime); } - Character.SpeedMultiplier = affliction.GetSpeedMultiplier(); + Character.StackSpeedMultiplier(affliction.GetSpeedMultiplier()); } } @@ -638,7 +638,7 @@ namespace Barotrauma var affliction = afflictions[i]; affliction.Update(this, null, deltaTime); affliction.DamagePerSecondTimer += deltaTime; - Character.SpeedMultiplier = affliction.GetSpeedMultiplier(); + Character.StackSpeedMultiplier(affliction.GetSpeedMultiplier()); } UpdateLimbAfflictionOverlays(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/SkillSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/SkillSettings.cs new file mode 100644 index 000000000..f0814daed --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/SkillSettings.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace Barotrauma +{ + class SkillSettings : ISerializableEntity + { + public static SkillSettings Current + { + get; + private set; + } + + [Serialize(4.0f, true)] + public float SingleRoundSkillGainMultiplier { get; set; } + + + private float skillIncreasePerRepair; + [Serialize(5.0f, true)] + public float SkillIncreasePerRepair + { + get { return skillIncreasePerRepair * GetCurrentSkillGainMultiplier(); } + set { skillIncreasePerRepair = value; } + } + + private float skillIncreasePerSabotage; + [Serialize(3.0f, true)] + public float SkillIncreasePerSabotage + { + get { return skillIncreasePerSabotage * GetCurrentSkillGainMultiplier(); } + set { skillIncreasePerSabotage = value; } + } + + private float skillIncreasePerCprRevive; + [Serialize(0.5f, true)] + public float SkillIncreasePerCprRevive + { + get { return skillIncreasePerCprRevive * GetCurrentSkillGainMultiplier(); } + set { skillIncreasePerCprRevive = value; } + } + + private float skillIncreasePerRepairedStructureDamage; + [Serialize(0.005f, true)] + public float SkillIncreasePerRepairedStructureDamage + { + get { return skillIncreasePerRepairedStructureDamage * GetCurrentSkillGainMultiplier(); } + set { skillIncreasePerRepairedStructureDamage = value; } + } + + private float skillIncreasePerSecondWhenSteering; + [Serialize(0.005f, true)] + public float SkillIncreasePerSecondWhenSteering + { + get { return skillIncreasePerSecondWhenSteering * GetCurrentSkillGainMultiplier(); } + set { skillIncreasePerSecondWhenSteering = value; } + } + + private float skillIncreasePerFabricatorRequiredSkill; + [Serialize(0.5f, true)] + public float SkillIncreasePerFabricatorRequiredSkill + { + get { return skillIncreasePerFabricatorRequiredSkill * GetCurrentSkillGainMultiplier(); } + set { skillIncreasePerFabricatorRequiredSkill = value; } + } + + private SkillSettings(XElement element) + { + SerializableProperties = SerializableProperty.DeserializeProperties(this, element); + } + + public string Name => "SkillSettings"; + + public Dictionary SerializableProperties + { + get; + set; + } + + public static void Load(IEnumerable files) + { + //reverse order to respect content package load order (last file overrides others) + foreach (ContentFile file in files.Reverse()) + { + if (file.Type != ContentType.SkillSettings) + { + throw new ArgumentException(); + } + + XDocument doc = XMLExtensions.TryLoadXml(file.Path); + if (doc == null) { continue; } + + Current = new SkillSettings(doc.Root); + break; + } + + if (Current == null) + { + DebugConsole.NewMessage("Now skill settings found in the selected content packages. Using default values."); + Current = new SkillSettings(null); + } + } + + private float GetCurrentSkillGainMultiplier() + { + if (GameMain.GameSession?.GameMode is CampaignMode) + { + return 1.0f; + } + else + { + return SingleRoundSkillGainMultiplier; + } + } + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/ContentPackage.cs b/Barotrauma/BarotraumaShared/SharedSource/ContentPackage.cs index 9b7aee2c2..b40ae00f6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/ContentPackage.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/ContentPackage.cs @@ -38,7 +38,8 @@ namespace Barotrauma UIStyle, TraitorMissions, EventManagerSettings, - Orders + Orders, + SkillSettings } public class ContentPackage diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index bbb889b45..90ff507be 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -290,11 +290,41 @@ namespace Barotrauma commands.Add(new Command("startwhenclientsready", "startwhenclientsready [true/false]: Enable or disable automatically starting the round when clients are ready to start.", null)); - commands.Add(new Command("giveperm", "giveperm [id]: Grants administrative permissions to the player with the specified client ID.", null)); + commands.Add(new Command("giveperm", "giveperm [id]: Grants administrative permissions to the player with the specified client ID.", null, + () => + { + if (GameMain.NetworkMember == null) return null; - commands.Add(new Command("revokeperm", "revokeperm [id]: Revokes administrative permissions to the player with the specified client ID.", null)); + return new string[][] + { + GameMain.NetworkMember.ConnectedClients.Select(c => c.Name).ToArray(), + Enum.GetValues(typeof(ClientPermissions)).Cast().Select(v => v.ToString()).ToArray() + }; + })); + + commands.Add(new Command("revokeperm", "revokeperm [id]: Revokes administrative permissions to the player with the specified client ID.", null, + () => + { + if (GameMain.NetworkMember == null) return null; + + return new string[][] + { + GameMain.NetworkMember.ConnectedClients.Select(c => c.Name).ToArray(), + Enum.GetValues(typeof(ClientPermissions)).Cast().Select(v => v.ToString()).ToArray() + }; + })); - commands.Add(new Command("giverank", "giverank [id]: Assigns a specific rank (= a set of administrative permissions) to the player with the specified client ID.", null)); + commands.Add(new Command("giverank", "giverank [id]: Assigns a specific rank (= a set of administrative permissions) to the player with the specified client ID.", null, + () => + { + if (GameMain.NetworkMember == null) return null; + + return new string[][] + { + GameMain.NetworkMember.ConnectedClients.Select(c => c.Name).ToArray(), + PermissionPreset.List.Select(pp => pp.Name).ToArray() + }; + })); commands.Add(new Command("givecommandperm", "givecommandperm [id]: Gives the player with the specified client ID the permission to use the specified console commands.", null)); @@ -823,6 +853,7 @@ namespace Barotrauma var reactor = reactorItem.GetComponent(); reactor.TurbineOutput = power / reactor.MaxPowerOutput * 100.0f; reactor.FissionRate = power / reactor.MaxPowerOutput * 100.0f; + reactor.PowerOn = true; reactor.AutoTemp = true; #if SERVER @@ -1514,8 +1545,13 @@ namespace Barotrauma } } - public static void ShowQuestionPrompt(string question, QuestionCallback onAnswered) + public static void ShowQuestionPrompt(string question, QuestionCallback onAnswered, string[] args = null, int argCount = -1) { + if (args != null && args.Length > argCount) + { + onAnswered(args[argCount]); + } + #if CLIENT activeQuestionText = new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width, 0), listBox.Content.RectTransform), " >>" + question, font: GUI.SmallFont, wrap: true) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs index c0be2525a..6588014fc 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MonsterMission.cs @@ -77,6 +77,12 @@ namespace Barotrauma Level.Loaded.TryGetInterestingPosition(true, Level.PositionType.MainPath, Level.Loaded.Size.X * 0.3f, out Vector2 spawnPos); bool isClient = IsClient; + + if (monsters.Count > 0) + { + throw new Exception($"monsters.Count > 0 ({monsters.Count})"); + } + if (!string.IsNullOrEmpty(monsterFile)) { for (int i = 0; i < monsterCount; i++) @@ -92,12 +98,22 @@ namespace Barotrauma } } + if (tempSonarPositions.Count > 0) + { + throw new Exception($"tempSonarPositions.Count > 0 ({tempSonarPositions.Count})"); + } + monsters.ForEach(m => m.Enabled = false); SwarmBehavior.CreateSwarm(monsters.Cast()); for (int i = 0; i < monsters.Count; i++) { tempSonarPositions.Add(spawnPos + Rand.Vector(maxSonarMarkerDistance)); } + + if (monsters.Count != tempSonarPositions.Count) + { + throw new Exception($"monsters.Count != tempSonarPositions.Count ({monsters.Count} != {tempSonarPositions.Count})"); + } } public override void Update(float deltaTime) @@ -108,6 +124,16 @@ namespace Barotrauma //keep sonar markers within maxSonarMarkerDistance from the monster(s) for (int i = 0; i < tempSonarPositions.Count; i++) { + if (monsters.Count != tempSonarPositions.Count) + { + throw new Exception($"monsters.Count != tempSonarPositions.Count ({monsters.Count} != {tempSonarPositions.Count})"); + } + + if (i < 0 || i >= monsters.Count) + { + throw new Exception($"Index {i} outside of bounds 0-{monsters.Count} ({tempSonarPositions.Count})"); + } + if (monsters[i].Removed || monsters[i].IsDead) { continue; } Vector2 diff = tempSonarPositions[i] - monsters[i].Position; @@ -148,8 +174,10 @@ namespace Barotrauma public override void End() { + tempSonarPositions.Clear(); + monsters.Clear(); if (State < 1) { return; } - + GiveReward(); completed = true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/ScriptedEventSet.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/ScriptedEventSet.cs index d21cefb8d..333974395 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/ScriptedEventSet.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/ScriptedEventSet.cs @@ -39,7 +39,7 @@ namespace Barotrauma private ScriptedEventSet(XElement element, string debugIdentifier) { - DebugIdentifier = debugIdentifier; + DebugIdentifier = element.GetAttributeString("identifier", null) ?? debugIdentifier; Commonness = new Dictionary(); EventPrefabs = new List(); ChildSets = new List(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs index 677f6aac8..424665d8a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Deconstructor.cs @@ -72,7 +72,7 @@ namespace Barotrauma.Items.Components ApplyStatusEffects(ActionType.OnActive, deltaTime, null); if (powerConsumption <= 0.0f) { Voltage = 1.0f; } - progressTimer += deltaTime * Voltage; + progressTimer += deltaTime * Math.Min(Voltage, 1.0f); var targetItem = inputContainer.Inventory.Items.LastOrDefault(i => i != null); if (targetItem == null) { return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs index 3fe0406e9..7bdd7bfdc 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Fabricator.cs @@ -10,8 +10,6 @@ namespace Barotrauma.Items.Components partial class Fabricator : Powered, IServerSerializable, IClientSerializable { - public const float SkillIncreaseMultiplier = 0.5f; - private readonly List fabricationRecipes = new List(); private FabricationRecipe fabricatedItem; @@ -130,13 +128,6 @@ namespace Barotrauma.Items.Components if (selectedItem == null) return; if (!outputContainer.Inventory.IsEmpty()) return; -#if SERVER - if (user != null) - { - GameServer.Log(user.LogName + " started fabricating " + selectedItem.DisplayName + " in " + item.Name, ServerLog.MessageType.ItemInteraction); - } -#endif - #if CLIENT itemList.Enabled = false; activateButton.Text = TextManager.Get("FabricatorCancel"); @@ -155,20 +146,19 @@ namespace Barotrauma.Items.Components currPowerConsumption = powerConsumption; currPowerConsumption *= MathHelper.Lerp(1.5f, 1.0f, item.Condition / item.MaxCondition); + +#if SERVER + if (user != null) + { + GameServer.Log(user.LogName + " started fabricating " + selectedItem.DisplayName + " in " + item.Name, ServerLog.MessageType.ItemInteraction); + } + item.CreateServerEvent(this); +#endif } private void CancelFabricating(Character user = null) { -#if SERVER - if (fabricatedItem != null) - { - if (user != null) - { - GameServer.Log(user.LogName + " cancelled the fabrication of " + fabricatedItem.DisplayName + " in " + item.Name, ServerLog.MessageType.ItemInteraction); - } - item.CreateServerEvent(this); - } -#endif + if (fabricatedItem == null) { return; } IsActive = false; fabricatedItem = null; @@ -190,6 +180,13 @@ namespace Barotrauma.Items.Components inputContainer.Inventory.Locked = false; outputContainer.Inventory.Locked = false; +#if SERVER + if (user != null) + { + GameServer.Log(user.LogName + " cancelled the fabrication of " + fabricatedItem.DisplayName + " in " + item.Name, ServerLog.MessageType.ItemInteraction); + } + item.CreateServerEvent(this); +#endif } public override void Update(float deltaTime, Camera cam) @@ -215,7 +212,7 @@ namespace Barotrauma.Items.Components if (powerConsumption <= 0) { Voltage = 1.0f; } - timeUntilReady -= deltaTime * Voltage; + timeUntilReady -= deltaTime * Math.Min(Voltage, 1.0f); if (timeUntilReady > 0.0f) { return; } @@ -254,14 +251,15 @@ namespace Barotrauma.Items.Components { foreach (Skill skill in fabricatedItem.RequiredSkills) { - user.Info.IncreaseSkillLevel(skill.Identifier, skill.Level / 100.0f * SkillIncreaseMultiplier, user.WorldPosition + Vector2.UnitY * 150.0f); + float userSkill = user.GetSkillLevel(skill.Identifier); + user.Info.IncreaseSkillLevel( + skill.Identifier, + skill.Level * SkillSettings.Current.SkillIncreasePerFabricatorRequiredSkill / Math.Max(userSkill, 1.0f), + user.WorldPosition + Vector2.UnitY * 150.0f); } } - CancelFabricating(null); -#if SERVER - item.CreateServerEvent(this); -#endif + CancelFabricating(); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs index 93c355bfa..68d569275 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs @@ -43,13 +43,14 @@ namespace Barotrauma.Items.Components private float sendUpdateTimer; private float degreeOfSuccess; - + private Vector2 optimalTemperature, allowedTemperature; private Vector2 optimalFissionRate, allowedFissionRate; private Vector2 optimalTurbineOutput, allowedTurbineOutput; private bool _powerOn; + [Serialize(defaultValue: false, isSaveable: true)] public bool PowerOn { get { return _powerOn; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs index 4d94f2ec8..830f8e5a0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs @@ -106,16 +106,18 @@ namespace Barotrauma.Items.Components get => currentMode; set { + bool changed = currentMode != value; + currentMode = value; if (value == Mode.Passive) { - currentPingIndex = -1; if (item.AiTarget != null) { item.AiTarget.SectorDegrees = 360.0f; } } #if CLIENT + if (changed) { prevPassivePingRadius = float.MaxValue; } UpdateGUIElements(); #endif } @@ -263,7 +265,7 @@ namespace Barotrauma.Items.Components character.Speak(TextManager.GetWithVariables(dialogTag, new string[2] { "[direction]", "[count]" }, new string[2] { targetGroup.Key.ToString(), targetGroup.Value.Count.ToString() }, - new bool[2] { true, false }), null, 0, "sonartarget" + targetGroup.Value[0].ID, 30); + new bool[2] { true, false }), null, 0, "sonartarget" + targetGroup.Value[0].ID, 60); //prevent the character from reporting other targets in the group for (int i = 1; i < targetGroup.Value.Count; i++) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs index 80da2e0bf..e514c6a91 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs @@ -277,21 +277,25 @@ namespace Barotrauma.Items.Components ApplyStatusEffects(ActionType.OnActive, deltaTime, null); + float userSkill = 0.0f; + if (user != null && (user.SelectedConstruction == item || item.linkedTo.Contains(user.SelectedConstruction))) + { + userSkill = user.GetSkillLevel("helm") / 100.0f; + } + if (AutoPilot) { UpdateAutoPilot(deltaTime); - float userSkill = 0.0f; - if (user != null && (user.SelectedConstruction == item || item.linkedTo.Contains(user.SelectedConstruction))) - { - userSkill = user.GetSkillLevel("helm") / 100.0f; - } targetVelocity = targetVelocity.ClampLength(MathHelper.Lerp(AutoPilotMaxSpeed, AIPilotMaxSpeed, userSkill) * 100.0f); } else { if (user != null && user.Info != null && user.SelectedConstruction == item) { - user.Info.IncreaseSkillLevel("helm", 0.005f * deltaTime, user.WorldPosition + Vector2.UnitY * 150.0f); + user.Info.IncreaseSkillLevel( + "helm", + SkillSettings.Current.SkillIncreasePerSecondWhenSteering / Math.Max(userSkill, 1.0f) * deltaTime, + user.WorldPosition + Vector2.UnitY * 150.0f); } Vector2 velocityDiff = steeringInput - targetVelocity; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs index 6f7bf3b0e..4544bd612 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs @@ -9,9 +9,6 @@ namespace Barotrauma.Items.Components { partial class Repairable : ItemComponent, IServerSerializable, IClientSerializable { - public static float SkillIncreasePerRepair = 5.0f; - public static float SkillIncreasePerSabotage = 3.0f; - private string header; private float deteriorationTimer; @@ -282,7 +279,7 @@ namespace Barotrauma.Items.Components { float characterSkillLevel = CurrentFixer.GetSkillLevel(skill.Identifier); CurrentFixer.Info.IncreaseSkillLevel(skill.Identifier, - SkillIncreasePerRepair / Math.Max(characterSkillLevel, 1.0f), + SkillSettings.Current.SkillIncreasePerRepair / Math.Max(characterSkillLevel, 1.0f), CurrentFixer.WorldPosition + Vector2.UnitY * 100.0f); } @@ -313,7 +310,7 @@ namespace Barotrauma.Items.Components { float characterSkillLevel = CurrentFixer.GetSkillLevel(skill.Identifier); CurrentFixer.Info.IncreaseSkillLevel(skill.Identifier, - SkillIncreasePerSabotage / Math.Max(characterSkillLevel, 1.0f), + SkillSettings.Current.SkillIncreasePerSabotage / Math.Max(characterSkillLevel, 1.0f), CurrentFixer.WorldPosition + Vector2.UnitY * 100.0f); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs index f78b70c90..4342bb427 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs @@ -83,8 +83,14 @@ namespace Barotrauma.Items.Components public bool CanReceive(WifiComponent sender) { if (sender == null || sender.channel != channel) { return false; } - if (sender.TeamID == Character.TeamType.Team1 && TeamID == Character.TeamType.Team2) { return false; } - if (sender.TeamID == Character.TeamType.Team2 && TeamID == Character.TeamType.Team1) { return false; } + + if (sender.TeamID != Character.TeamType.None && TeamID != Character.TeamType.None) + { + if (sender.TeamID != TeamID) + { + return false; + } + } if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) { return false; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs index cc89c64ad..efdb0d0e6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs @@ -671,21 +671,33 @@ namespace Barotrauma.Items.Components return closestIndex; } - + public override void FlipX(bool relativeToSub) - { + { + Vector2 refPos = item.Submarine == null ? + Vector2.Zero : + item.Position - item.Submarine.HiddenSubPosition; + for (int i = 0; i < nodes.Count; i++) { - nodes[i] = new Vector2(-nodes[i].X, nodes[i].Y); + nodes[i] = relativeToSub ? + new Vector2(-nodes[i].X, nodes[i].Y) : + new Vector2(refPos.X - (nodes[i].X - refPos.X), nodes[i].Y); } UpdateSections(); } public override void FlipY(bool relativeToSub) { + Vector2 refPos = item.Submarine == null ? + Vector2.Zero : + item.Position - item.Submarine.HiddenSubPosition; + for (int i = 0; i < nodes.Count; i++) { - nodes[i] = new Vector2(nodes[i].X, -nodes[i].Y); + nodes[i] = relativeToSub ? + new Vector2(nodes[i].X, -nodes[i].Y) : + new Vector2(nodes[i].X, refPos.Y - (nodes[i].Y - refPos.Y)); } UpdateSections(); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs index 998411cec..e55d25536 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs @@ -44,15 +44,9 @@ namespace Barotrauma // 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); - DropIndicator = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(870, 55, 73, 66), new Vector2(0.5f, 0.75f), 0); - DropIndicatorHighlight = new Sprite("Content/UI/inventoryAtlas.png", new Rectangle(946, 54, 73, 66), new Vector2(0.5f, 0.75f), 0); } #endif } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs index 27ca4a39a..454068b5e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs @@ -107,19 +107,16 @@ namespace Barotrauma : this (rectangle, Submarine.MainSub) { } - public Gap(Rectangle newRect, Submarine submarine) - : this(newRect, newRect.Width < newRect.Height, submarine) + public Gap(Rectangle rect, Submarine submarine) + : this(rect, rect.Width < rect.Height, submarine) { } - public Gap(Rectangle newRect, bool isHorizontal, Submarine submarine) + public Gap(Rectangle rect, bool isHorizontal, Submarine submarine) : base(MapEntityPrefab.Find(null, "gap"), submarine) { - rect = newRect; - + this.rect = rect; flowForce = Vector2.Zero; - - this.IsHorizontal = isHorizontal; - + IsHorizontal = isHorizontal; open = 1.0f; FindHulls(); @@ -131,6 +128,7 @@ namespace Barotrauma outsideCollisionBlocker.CollisionCategories = Physics.CollisionWall; outsideCollisionBlocker.CollidesWith = Physics.CollisionCharacter; outsideCollisionBlocker.Enabled = false; + Resized += newRect => IsHorizontal = newRect.Width < newRect.Height; DebugConsole.Log("Created gap (" + ID + ")"); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs index edbcea775..1f03417ba 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs @@ -36,6 +36,8 @@ namespace Barotrauma //is the mouse inside the rect private bool isHighlighted; + public event Action Resized; + public bool IsHighlighted { get { return isHighlighted || ExternalHighlight; } @@ -578,6 +580,7 @@ namespace Barotrauma if (!float.IsNaN(value)) { _spriteOverrideDepth = MathHelper.Clamp(value, 0.001f, 0.999f); + if (this is Item) { _spriteOverrideDepth = Math.Min(_spriteOverrideDepth, 0.9f); } SpriteDepthOverrideIsSet = true; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Structure.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Structure.cs index fb11526b5..a3d64c723 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Structure.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Structure.cs @@ -42,9 +42,6 @@ namespace Barotrauma public const int WallSectionSize = 96; public static List WallList = new List(); - //how much mechanic skill increases per damage removed from the wall by welding - public const float SkillIncreaseMultiplier = 0.005f; - const float LeakThreshold = 0.1f; #if CLIENT @@ -1008,7 +1005,7 @@ namespace Barotrauma if (damageDiff < 0.0f) { attacker.Info.IncreaseSkillLevel("mechanical", - -damageDiff * SkillIncreaseMultiplier / Math.Max(attacker.GetSkillLevel("mechanical"), 1.0f), + -damageDiff * SkillSettings.Current.SkillIncreasePerRepairedStructureDamage / Math.Max(attacker.GetSkillLevel("mechanical"), 1.0f), SectionPosition(sectionIndex, true)); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs index 00319e3f3..09e5fda56 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs @@ -949,6 +949,7 @@ namespace Barotrauma && !fixture.CollisionCategories.HasFlag(Physics.CollisionWall) && !fixture.CollisionCategories.HasFlag(Physics.CollisionRepair)) { return -1; } if (ignoreSubs && fixture.Body.UserData is Submarine) { return -1; } + if (fixture.Body.UserData as string == "ruinroom") { return -1; } if (fixture.Body.UserData is Structure structure) { if (structure.IsPlatform || structure.StairDirection != Direction.None) { return -1; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs index d79cf7e6e..bf838f108 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChildServerRelay.cs @@ -176,8 +176,16 @@ namespace Barotrauma.Networking byte[] lengthBytes = new byte[2]; lengthBytes[0] = (byte)(msg.Length & 0xFF); lengthBytes[1] = (byte)((msg.Length >> 8) & 0xFF); - writeStream?.Write(lengthBytes, 0, 2); - writeStream?.Write(msg, 0, msg.Length); + try + { + writeStream?.Write(lengthBytes, 0, 2); + writeStream?.Write(msg, 0, msg.Length); + } + catch (IOException e) + { + shutDown = true; + break; + } if (shutDown) { break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs index b79e5f4c4..a42d9ce20 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs @@ -74,6 +74,17 @@ namespace Barotrauma.Networking RespawnShuttle.Load(false); RespawnShuttle.PhysicsBody.FarseerBody.OnCollision += OnShuttleCollision; + //prevent wifi components from communicating between the respawn shuttle and other subs + List wifiComponents = new List(); + foreach (Item item in Item.ItemList) + { + if (item.Submarine == RespawnShuttle) { wifiComponents.AddRange(item.GetComponents()); } + } + foreach (WifiComponent wifiComponent in wifiComponents) + { + wifiComponent.TeamID = Character.TeamType.FriendlyNPC; + } + ResetShuttle(); shuttleDoors = new List(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index 35601ec5b..be0e35b25 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -148,10 +148,26 @@ namespace Barotrauma sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("LevelUpdate", sw.ElapsedTicks); - if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction)) + if (Character.Controlled != null) { - Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled, (float)deltaTime); + if (Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction)) + { + Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled, (float)deltaTime); + } + if (Character.Controlled.Inventory != null) + { + foreach (Item item in Character.Controlled.Inventory.Items) + { + if (item == null) { continue; } + if (Character.Controlled.HasEquippedItem(item)) + { + item.UpdateHUD(cam, Character.Controlled, (float)deltaTime); + } + } + } } + + sw.Restart(); Character.UpdateAll((float)deltaTime, cam); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs index 803448b5c..2526e7f8c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs @@ -520,7 +520,7 @@ namespace Barotrauma { if (parentObject is Character character && value is float) { character.LowPassMultiplier = (float)value; return true; } } break; case "SpeedMultiplier": - { if (parentObject is Character character && value is float) { character.SpeedMultiplier = (float)value; return true; } } + { if (parentObject is Character character && value is float) { character.StackSpeedMultiplier((float)value); return true; } } break; case "IsOn": { if (parentObject is LightComponent lightComponent && value is bool) { lightComponent.IsOn = (bool)value; return true; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Utils/AssemblyInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Utils/AssemblyInfo.cs index 9984506ed..4e891145a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Utils/AssemblyInfo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Utils/AssemblyInfo.cs @@ -35,6 +35,8 @@ public static class AssemblyInfo #if DEBUG retVal = "Debug" + retVal; +#elif UNSTABLE + retVal = "Unstable" + retVal; #else retVal = "Release" + retVal; #endif diff --git a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub b/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub deleted file mode 100644 index 4c8fa1c9e..000000000 Binary files a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub and /dev/null differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Muikku.sub b/Barotrauma/BarotraumaShared/Submarines/Muikku.sub deleted file mode 100644 index 386de54c9..000000000 Binary files a/Barotrauma/BarotraumaShared/Submarines/Muikku.sub and /dev/null differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Orca.sub b/Barotrauma/BarotraumaShared/Submarines/Orca.sub index 6e84aceed..4983a2c43 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Orca.sub and b/Barotrauma/BarotraumaShared/Submarines/Orca.sub differ diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 64cf3bf7b..11dff8d22 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,5 +1,35 @@ --------------------------------------------------------------------------------------------------------- -v0.9.702 (Unstable) +v0.9.703.0 (Unstable) +--------------------------------------------------------------------------------------------------------- + +- Numerous UI fixes (layout improvements, improved scaling on different resolutions, fixed item interface overlaps, text overflow fixes). +- Added Korean translation. +- Numerous fixes to random events to better pace new level dimensions. +- Fixed non-host clients crashing when disconnecting from the server. +- Made giveperm/giverank commands suck less by allowing names, endpoints and SteamIDs instead of clientlist id, and allowing users to skip question prompt by adding rank or perm as a second parameter. +- Fixes to render order oddities (structures with a depth > 0.5 always rendering behind all items, inconsistent render order between sub editor and in-game). Now structures with a depth of >= 0.9 are always behind everything (and visible through the LOS effect), and item's sprite depth is capped to 0.9. +- Fixed engines causing crashes if MinVoltage is set to 0. +- Fixed multiplayer campaign saves appearing in the single player "load game" menu if they're placed in the singleplayer save folder (leading to a crash if a player starts to load the save). +- Fixed fabricator cancellation failing to be communicated under certain circumstances. +- Fixed fabricator an deconstructor operating faster when run on overvoltage, making it possible to fabricate/deconstruct things almost instantaneously by using relays. +- Fixed campaign store filter doing nothing. +- Potentially a fixed race condition when autoupdating Workshop items during loading screen. +- Fixed subinventories not opening when trying to heal an unconscious character. +- Fixed crashing when moving the nodes of a wire that's not connected to anything in the sub editor. +- Fixed inability to drag wires out of the wiring interface (even if they're disconnected from both ends). +- Another fix to inventory items occasionally getting messed up in multiplayer. +- Removed oxygenite shards as a product of deconstructing liquid oxygenite to prevent production loops. +- Fixed sonar showing everything around the sub when sending out a directional ping and switching to passive. +- Fixed inability to drag characters from room to another in alien ruins. +- Fixed excessively large tonic liquid collider. +- Fixed reactor's on/off state not being saved. +- Fixed crashing if a modded UI style contains multiple child styles with the same name. +- Wifi components in the respawn shuttle can't communicate with components in other submarines/shuttles. +- Fixed wire nodes getting misplaced when flipping wires in the sub editor. +- Fixed groups of items that include wires sometimes not getting placed at the position of the cursor when pasting them in the sub editor. + +--------------------------------------------------------------------------------------------------------- +v0.9.702.0 (Unstable) --------------------------------------------------------------------------------------------------------- - UI overhaul @@ -25,7 +55,7 @@ v0.9.702 (Unstable) - Added combat priorities to alien weapons to allow bots to use them. --------------------------------------------------------------------------------------------------------- -v0.9.701 (Unstable) +v0.9.701.0 (Unstable) --------------------------------------------------------------------------------------------------------- - Fixed SteamP2P server hosting. @@ -45,7 +75,7 @@ v0.9.701 (Unstable) - Fixed sub editor allowing vanilla subs to be deleted. --------------------------------------------------------------------------------------------------------- -v0.9.700 (Unstable) +v0.9.700.0 (Unstable) --------------------------------------------------------------------------------------------------------- - Additional logging to diagnose event/entity ID errors: server and clients write a log file with a bunch of debug information the error happens. The files can be found in the ServerLogs folder after the error has occurred. If you get log files, please send them to us to help us diagnose these bugs! diff --git a/Libraries/Facepunch.Steamworks/Generated/Interfaces/ISteamMatchmakingServers.cs b/Libraries/Facepunch.Steamworks/Generated/Interfaces/ISteamMatchmakingServers.cs index 340189508..bc31ffc60 100644 --- a/Libraries/Facepunch.Steamworks/Generated/Interfaces/ISteamMatchmakingServers.cs +++ b/Libraries/Facepunch.Steamworks/Generated/Interfaces/ISteamMatchmakingServers.cs @@ -56,13 +56,41 @@ namespace Steamworks #region FunctionMeta [UnmanagedFunctionPointer( Platform.MemberConvention )] - private delegate HServerListRequest FRequestInternetServerList( IntPtr self, AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); + private delegate HServerListRequest FRequestInternetServerList( IntPtr self, AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); private FRequestInternetServerList _RequestInternetServerList; #endregion - internal HServerListRequest RequestInternetServerList( AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) + internal HServerListRequest RequestInternetServerList( AppId iApp, MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) { - var returnValue = _RequestInternetServerList( Self, iApp, ref ppchFilters, nFilters, pRequestServersResponse ); + int numPtrs = ppchFilters.Length; + if (numPtrs <= 0) { numPtrs = 1; } + + IntPtr[] filterPtrs = new IntPtr[numPtrs]; + GCHandle?[] filterHandles = new GCHandle?[numPtrs]; + for (int i=0;i