Files
2025-06-17 16:38:11 +03:00

370 lines
11 KiB
C#

using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
{
public class GUIButton : GUIComponent
{
protected GUITextBlock textBlock;
public GUITextBlock TextBlock { get { return textBlock; } }
protected GUIFrame frame;
public GUIFrame Frame { get { return frame; } }
public delegate bool OnClickedHandler(GUIButton button, object obj);
public OnClickedHandler OnClicked;
public delegate bool OnPressedHandler();
public OnPressedHandler OnPressed;
public delegate bool OnButtonDownHandler();
public OnButtonDownHandler OnButtonDown;
public bool CanBeSelected = true;
public override bool Enabled
{
get
{
return enabled;
}
set
{
if (value == enabled) { return; }
enabled = frame.Enabled = textBlock.Enabled = value;
}
}
public override Color Color
{
get { return base.Color; }
set
{
base.Color = value;
frame.Color = value;
}
}
public override Color HoverColor
{
get { return base.HoverColor; }
set
{
base.HoverColor = value;
frame.HoverColor = value;
}
}
public override Color SelectedColor
{
get
{
return base.SelectedColor;
}
set
{
base.SelectedColor = value;
frame.SelectedColor = value;
}
}
public override Color PressedColor
{
get
{
return base.PressedColor;
}
set
{
base.PressedColor = value;
frame.PressedColor = value;
}
}
public override Color OutlineColor
{
get { return base.OutlineColor; }
set
{
base.OutlineColor = value;
if (frame != null) frame.OutlineColor = value;
}
}
public Color TextColor
{
get { return textBlock.TextColor; }
set { textBlock.TextColor = value; }
}
public Color HoverTextColor
{
get { return textBlock.HoverTextColor; }
set { textBlock.HoverTextColor = value; }
}
public Color SelectedTextColor
{
get { return textBlock.SelectedTextColor; }
set { textBlock.SelectedTextColor = value; }
}
public Color DisabledTextColor
{
get { return textBlock.DisabledTextColor; }
}
public override float FlashTimer
{
get { return Frame.FlashTimer; }
}
public override GUIFont Font
{
get
{
return (textBlock == null) ? GUIStyle.Font : textBlock.Font;
}
set
{
base.Font = value;
if (textBlock != null) { textBlock.Font = value; }
}
}
public LocalizedString Text
{
get { return textBlock.Text; }
set { textBlock.Text = value; }
}
public ForceUpperCase ForceUpperCase
{
get { return textBlock.ForceUpperCase; }
set { textBlock.ForceUpperCase = value; }
}
public override RichString ToolTip
{
get
{
return base.ToolTip;
}
set
{
base.ToolTip = value;
textBlock.ToolTip = value;
}
}
private GUIComponent holdOverlay;
private bool requireHold;
public bool RequireHold
{
get => requireHold;
set
{
requireHold = value;
if (value)
{
holdOverlay ??= new GUIFrame(new RectTransform(new Vector2(0.5f, 1f), Frame.RectTransform, Anchor.CenterLeft), style: null)
{
Color = GUIStyle.Yellow * 0.33f,
CanBeFocused = false,
IgnoreLayoutGroups = true,
Visible = true
};
}
else if (holdOverlay != null)
{
holdOverlay.Visible = false;
}
}
}
public float HoldDurationSeconds { get; set; } = 5f;
private float holdTimer;
public bool Pulse { get; set; }
private float pulseTimer;
private float pulseExpand;
private bool flashed;
public GUISoundType ClickSound { get; set; } = GUISoundType.Select;
public override bool PlaySoundOnSelect { get; set; } = true;
public GUIButton(RectTransform rectT, Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : this(rectT, LocalizedString.EmptyString, textAlignment, style, color) { }
public GUIButton(RectTransform rectT, LocalizedString text, Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : base(style, rectT)
{
CanBeFocused = true;
HoverCursor = CursorState.Hand;
frame = new GUIFrame(new RectTransform(Vector2.One, rectT), style) { CanBeFocused = false };
if (style != null) { GUIStyle.Apply(frame, style == "" ? "GUIButton" : style); }
if (color.HasValue)
{
this.color = frame.Color = color.Value;
}
var selfStyle = Style;
textBlock = new GUITextBlock(new RectTransform(Vector2.One, rectT, Anchor.Center), RichString.Rich(text), textAlignment: textAlignment, style: null)
{
TextColor = selfStyle?.TextColor ?? Color.Black,
HoverTextColor = selfStyle?.HoverTextColor ?? Color.Black,
SelectedTextColor = selfStyle?.SelectedTextColor ?? Color.Black,
CanBeFocused = false
};
if (rectT.Rect.Height == 0 && !text.IsNullOrEmpty())
{
RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(textBlock.Text).Y));
RectTransform.MinSize = textBlock.RectTransform.MinSize = new Point(0, System.Math.Max(rectT.MinSize.Y, Rect.Height));
TextBlock.SetTextPos();
}
GUIStyle.Apply(textBlock, "", this);
Enabled = true;
}
public override void ApplyStyle(GUIComponentStyle style)
{
base.ApplyStyle(style);
frame?.ApplyStyle(style);
}
public override void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, bool useCircularFlash = false, Vector2? flashRectInflate = null)
{
Frame.Flash(color, flashDuration, useRectangleFlash, useCircularFlash, flashRectInflate);
}
protected override void Draw(SpriteBatch spriteBatch)
{
if (Pulse && pulseTimer > 1.0f)
{
Rectangle expandRect = Rect;
float expand = (pulseExpand * 20.0f) * GUI.Scale;
expandRect.Inflate(expand, expand);
GUIStyle.EndRoundButtonPulse.Draw(spriteBatch, expandRect, ToolBox.GradientLerp(pulseExpand, Color.White, Color.White, Color.Transparent));
}
}
protected override void Update(float deltaTime)
{
if (!Visible) return;
base.Update(deltaTime);
if (Rect.Contains(PlayerInput.MousePosition) && CanBeSelected && CanBeFocused && Enabled && GUI.IsMouseOn(this))
{
State = Selected ?
ComponentState.HoverSelected :
ComponentState.Hover;
if (PlayerInput.PrimaryMouseButtonDown())
{
OnButtonDown?.Invoke();
}
if (PlayerInput.PrimaryMouseButtonHeld())
{
if (RequireHold)
{
holdTimer += deltaTime;
}
if (OnPressed != null)
{
if (OnPressed())
{
State = ComponentState.Pressed;
}
}
else
{
State = ComponentState.Pressed;
}
}
else if (PlayerInput.PrimaryMouseButtonClicked())
{
if (!RequireHold || holdTimer > HoldDurationSeconds)
{
if (PlaySoundOnSelect)
{
SoundPlayer.PlayUISound(ClickSound);
}
if (OnClicked != null)
{
if (OnClicked(this, UserData))
{
State = ComponentState.Selected;
}
}
else
{
Selected = !Selected;
}
}
}
else
{
holdTimer = 0.0f;
}
}
else
{
holdTimer = 0.0f;
if (!ExternalHighlight)
{
State = Selected ? ComponentState.Selected : ComponentState.None;
}
else
{
State = ComponentState.Hover;
}
}
if (RequireHold)
{
float width = MathHelper.Clamp(holdTimer / HoldDurationSeconds, 0f, 1f);
if (!MathUtils.NearlyEqual(width, holdOverlay.RectTransform.RelativeSize.X))
{
holdOverlay.RectTransform.RelativeSize = new Vector2(width, 1f);
}
holdOverlay.Color =
holdTimer >= HoldDurationSeconds
? Color.Green * 0.33f
: Color.Red * 0.33f;
}
foreach (GUIComponent child in Children)
{
child.State = State;
}
if (Pulse)
{
pulseTimer += deltaTime;
if (pulseTimer > 1.0f)
{
if (!flashed)
{
flashed = true;
Frame.Flash(Color.White * 0.2f, 0.8f, true);
}
pulseExpand += deltaTime;
if (pulseExpand > 1.0f)
{
pulseTimer = 0.0f;
pulseExpand = 0.0f;
flashed = false;
}
}
}
}
}
}