Client LuaCsForBarotrauma
GUIComponent.cs
1 using Microsoft.Xna.Framework;
2 using Microsoft.Xna.Framework.Graphics;
3 using System.Collections.Generic;
4 using System.Linq;
6 using System;
7 using System.Xml.Linq;
8 using Barotrauma.IO;
9 using RestSharp;
10 using System.Net;
11 using Barotrauma.Steam;
12 
13 namespace Barotrauma
14 {
15  public enum SlideDirection { Up, Down, Left, Right }
16 
17  public abstract class GUIComponent
18  {
19  #region Hierarchy
21 
23 
24  public bool AlwaysOverrideCursor = false;
25 
26  public delegate bool SecondaryButtonDownHandler(GUIComponent component, object userData);
28 
29  public IEnumerable<GUIComponent> Children => RectTransform.Children.Select(c => c.GUIComponent);
30 
31  public T GetChild<T>() where T : GUIComponent
32  {
33  return Children.FirstOrDefault(c => c is T) as T;
34  }
35 
36  public T GetAnyChild<T>() where T : GUIComponent
37  {
38  return GetAllChildren().FirstOrDefault(c => c is T) as T;
39  }
40 
41  public IEnumerable<T> GetAllChildren<T>() where T : GUIComponent
42  {
43  return GetAllChildren().OfType<T>();
44  }
45 
49  public IEnumerable<GUIComponent> GetAllChildren()
50  {
51  return RectTransform.GetAllChildren().Select(c => c.GUIComponent);
52  }
53 
54  public GUIComponent GetChild(int index)
55  {
56  if (index < 0 || index >= CountChildren) { return null; }
57  return RectTransform.GetChild(index).GUIComponent;
58  }
59 
60  public int GetChildIndex(GUIComponent child)
61  {
62  if (child == null) { return -1; }
64  }
65 
66  public GUIComponent GetChildByUserData(object obj)
67  {
68  foreach (GUIComponent child in Children)
69  {
70  if (Equals(child.UserData, obj)) { return child; }
71  }
72  return null;
73  }
74 
75  public bool IsParentOf(GUIComponent component, bool recursive = true)
76  {
77  if (component == null) { return false; }
78  return RectTransform.IsParentOf(component.RectTransform, recursive);
79  }
80 
81  public bool IsChildOf(GUIComponent component, bool recursive = true)
82  {
83  if (component == null) { return false; }
84  return RectTransform.IsChildOf(component.RectTransform, recursive);
85  }
86 
87  public virtual void RemoveChild(GUIComponent child)
88  {
89  if (child == null) { return; }
90  child.RectTransform.Parent = null;
91  }
92 
93  // TODO: refactor?
94 
95  public GUIComponent FindChild(Func<GUIComponent, bool> predicate, bool recursive = false)
96  {
97  var matchingChild = Children.FirstOrDefault(predicate);
98  if (recursive && matchingChild == null)
99  {
100  foreach (GUIComponent child in Children)
101  {
102  matchingChild = child.FindChild(predicate, recursive);
103  if (matchingChild != null) return matchingChild;
104  }
105  }
106 
107  return matchingChild;
108  }
109  public GUIComponent FindChild(object userData, bool recursive = false)
110  {
111  var matchingChild = Children.FirstOrDefault(c => Equals(c.UserData, userData));
112  if (recursive && matchingChild == null)
113  {
114  foreach (GUIComponent child in Children)
115  {
116  matchingChild = child.FindChild(userData, recursive);
117  if (matchingChild != null) return matchingChild;
118  }
119  }
120 
121  return matchingChild;
122  }
123 
124  public IEnumerable<GUIComponent> FindChildren(object userData)
125  {
126  return Children.Where(c => Equals(c.UserData, userData));
127  }
128 
129  public IEnumerable<GUIComponent> FindChildren(Func<GUIComponent, bool> predicate)
130  {
131  return Children.Where(c => predicate(c));
132  }
133 
134  public virtual void ClearChildren()
135  {
137  }
138 
139  public void SetAsFirstChild()
140  {
142  }
143 
144  public void SetAsLastChild()
145  {
147  }
148  #endregion
149 
150  public bool AutoUpdate { get; set; } = true;
151  public bool AutoDraw { get; set; } = true;
152  public int UpdateOrder { get; set; }
153 
154  public bool Bounce { get; set; }
155  private float bounceTimer;
156  private float bounceJump;
157  private bool bounceDown;
158 
159  public Action<GUIComponent> OnAddedToGUIUpdateList;
160 
162 
163  protected Alignment alignment;
164 
165  protected Identifier[] styleHierarchy;
166 
167  public bool CanBeFocused;
168 
169  protected Color color;
170  protected Color hoverColor;
171  protected Color selectedColor;
172  protected Color disabledColor;
173  protected Color pressedColor;
174 
175  public bool GlowOnSelect { get; set; }
176 
177  public Vector2 UVOffset { get; set; }
178 
179  private CoroutineHandle pulsateCoroutine;
180 
181  protected Color flashColor;
182  protected float flashDuration = 1.5f;
183  // TODO: We should use an enum for the flash modes, but it would require a bit of refactoring, because Flash method is use in so many places.
184  private bool useRectangleFlash;
185  private bool useCircularFlash;
186  public virtual float FlashTimer
187  {
188  get { return flashTimer; }
189  }
190  protected float flashTimer;
191  private Vector2 flashRectInflate;
192 
193  private bool ignoreLayoutGroups;
194  public bool IgnoreLayoutGroups
195  {
196  get { return ignoreLayoutGroups; }
197  set
198  {
199  if (ignoreLayoutGroups == value) { return; }
200  ignoreLayoutGroups = value;
201  if (Parent is GUILayoutGroup layoutGroup)
202  {
203  layoutGroup.NeedsToRecalculate = true;
204  }
205  }
206  }
207 
208  public virtual GUIFont Font
209  {
210  get;
211  set;
212  }
213 
214  private RichString toolTip;
215  public virtual RichString ToolTip
216  {
217  get
218  {
219  return toolTip;
220  }
221  set
222  {
223  toolTip = value;
224  }
225  }
226 
229 
230  public bool Visible
231  {
232  get;
233  set;
234  }
235 
236  protected bool enabled;
237  public virtual bool Enabled
238  {
239  get { return enabled; }
240  set { enabled = value; }
241  }
242 
243  private static GUITextBlock toolTipBlock;
244 
245  public Vector2 Center
246  {
247  get { return new Vector2(Rect.Center.X, Rect.Center.Y); }
248  }
249 
250  protected Rectangle ClampRect(Rectangle r)
251  {
252  if (Parent is null) { return r; }
254  if (parentRect.Width <= 0 || parentRect.Height <= 0) { return Rectangle.Empty; }
255  if (parentRect.X > r.X)
256  {
257  int diff = parentRect.X - r.X;
258  r.X = parentRect.X;
259  r.Width -= diff;
260  }
261  if (parentRect.Y > r.Y)
262  {
263  int diff = parentRect.Y - r.Y;
264  r.Y = parentRect.Y;
265  r.Height -= diff;
266  }
267  if (parentRect.X + parentRect.Width < r.X + r.Width)
268  {
269  int diff = (r.X + r.Width) - (parentRect.X + parentRect.Width);
270  r.Width -= diff;
271  }
272  if (parentRect.Y + parentRect.Height < r.Y + r.Height)
273  {
274  int diff = (r.Y + r.Height) - (parentRect.Y + parentRect.Height);
275  r.Height -= diff;
276  }
277  if (r.Width <= 0 || r.Height <= 0) { return Rectangle.Empty; }
278  return r;
279  }
280 
281  public virtual Rectangle Rect
282  {
283  get { return RectTransform.Rect; }
284  }
285 
286  public bool ClampMouseRectToParent { get; set; } = false;
287 
288  public virtual Rectangle MouseRect
289  {
290  get
291  {
292  if (!CanBeFocused) { return Rectangle.Empty; }
293 
295  }
296  }
297 
298  public Dictionary<ComponentState, List<UISprite>> sprites;
299 
301 
302  public virtual Color OutlineColor { get; set; }
303 
306  protected bool isSelected;
307  public virtual bool Selected
308  {
309  get { return isSelected; }
310  set
311  {
312  isSelected = value;
313  foreach (var child in Children)
314  {
315  child.Selected = value;
316  }
317  }
318  }
319  public virtual ComponentState State
320  {
321  get { return _state; }
322  set
323  {
324  if (_state != value)
325  {
326  spriteFadeTimer = SpriteCrossFadeTime;
327  colorFadeTimer = ColorCrossFadeTime;
329  }
330  _state = value;
331  }
332  }
333 
334  #warning TODO: this is cursed, stop using this
335  public object UserData;
336 
337  public int CountChildren
338  {
339  get { return RectTransform.CountChildren; }
340  }
341 
345  public Color DefaultColor { get; set; }
346 
347  public virtual Color Color
348  {
349  get { return color; }
350  set { color = value; }
351  }
352 
353  public virtual Color HoverColor
354  {
355  get { return hoverColor; }
356  set { hoverColor = value; }
357  }
358 
359  public virtual Color SelectedColor
360  {
361  get { return selectedColor; }
362  set { selectedColor = value; }
363  }
364  public virtual Color DisabledColor
365  {
366  get { return disabledColor; }
367  set { disabledColor = value; }
368  }
369 
370  public virtual Color PressedColor
371  {
372  get { return pressedColor; }
373  set { pressedColor = value; }
374  }
375 
376  public TransitionMode ColorTransition { get; private set; }
377  public SpriteFallBackState FallBackState { get; private set; }
378  public float SpriteCrossFadeTime { get; private set; }
379  public float ColorCrossFadeTime { get; private set; }
380 
381  private float spriteFadeTimer;
382  private float colorFadeTimer;
383 
384  public bool ExternalHighlight = false;
385 
386  public virtual bool PlaySoundOnSelect { get; set; } = false;
387 
388  private RectTransform rectTransform;
390  {
391  get { return rectTransform; }
392  private set
393  {
394  rectTransform = value;
395  // This is the only place where the element should be assigned!
396  if (rectTransform != null)
397  {
398  rectTransform.GUIComponent = this;
399  }
400  }
401  }
402 
406  protected GUIComponent(string style, RectTransform rectT)
407  {
408  RectTransform = rectT;
409 
410  Visible = true;
411  OutlineColor = Color.Transparent;
412  Font = GUIStyle.Font;
413  CanBeFocused = true;
414 
415  if (style != null) { GUIStyle.Apply(this, style); }
416  }
417 
418  protected GUIComponent(string style)
419  {
420  Visible = true;
421  OutlineColor = Color.Transparent;
422  Font = GUIStyle.Font;
423  CanBeFocused = true;
424 
425  if (style != null) { GUIStyle.Apply(this, style); }
426  }
427 
428  #region Updating
429  public virtual void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
430  {
431  if (!Visible) { return; }
432 
433  UpdateOrder = order;
434  GUI.AddToUpdateList(this);
435  if (!ignoreChildren)
436  {
437  RectTransform.AddChildrenToGUIUpdateList(ignoreChildren, order);
438  }
439  OnAddedToGUIUpdateList?.Invoke(this);
440  }
441 
442  public void RemoveFromGUIUpdateList(bool alsoChildren = true)
443  {
444  GUI.RemoveFromUpdateList(this, alsoChildren);
445  }
446 
450  public void UpdateAuto(float deltaTime)
451  {
452  if (AutoUpdate)
453  {
454  Update(deltaTime);
455  }
456  }
457 
461  public void UpdateManually(float deltaTime, bool alsoChildren = false, bool recursive = true)
462  {
463  if (!Visible) { return; }
464 
465  AutoUpdate = false;
466  Update(deltaTime);
467  if (alsoChildren)
468  {
469  UpdateChildren(deltaTime, recursive);
470  }
471  }
472 
473  protected virtual void Update(float deltaTime)
474  {
475  if (!Visible) { return; }
476 
477  if (CanBeFocused && OnSecondaryClicked != null)
478  {
479  if (GUI.IsMouseOn(this) && PlayerInput.SecondaryMouseButtonClicked())
480  {
481  OnSecondaryClicked?.Invoke(this, UserData);
482  }
483  }
484 
485  if (Bounce)
486  {
487  if (bounceTimer > 3.0f || bounceDown)
488  {
489  RectTransform.ScreenSpaceOffset = new Point(RectTransform.ScreenSpaceOffset.X, (int) -(bounceJump * 15f * GUI.Scale));
490  if (!bounceDown)
491  {
492  bounceJump += deltaTime * 4;
493  if (bounceJump > 0.5f)
494  {
495  bounceDown = true;
496  }
497  }
498  else
499  {
500  bounceJump -= deltaTime * 4;
501  if (bounceJump <= 0.0f)
502  {
503  bounceJump = 0.0f;
504  bounceTimer = 0.0f;
505  bounceDown = false;
506  Bounce = false;
507  }
508  }
509  }
510  else
511  {
512  bounceTimer += deltaTime;
513  }
514  }
515 
516  if (flashTimer > 0.0f)
517  {
518  flashTimer -= deltaTime;
519  }
520  if (spriteFadeTimer > 0)
521  {
522  spriteFadeTimer -= deltaTime;
523  }
524  if (colorFadeTimer > 0)
525  {
526  colorFadeTimer -= deltaTime;
527  }
528  }
529 
530  public virtual void ForceLayoutRecalculation()
531  {
532  //This is very ugly but it gets the job done, it
533  //would be real nice to un-jank this some day
534  ForceUpdate();
535  ForceUpdate();
536  foreach (var child in Children)
537  {
538  child.ForceLayoutRecalculation();
539  }
540  }
541 
542  public void ForceUpdate() => Update((float)Timing.Step);
543 
547  public void UpdateChildren(float deltaTime, bool recursive)
548  {
549  foreach (var child in RectTransform.Children)
550  {
551  child.GUIComponent.UpdateManually(deltaTime, recursive, recursive);
552  }
553  }
554  #endregion
555 
556  #region Drawing
560  public void DrawAuto(SpriteBatch spriteBatch)
561  {
562  if (AutoDraw)
563  {
564  Draw(spriteBatch);
565  }
566  }
567 
571  public virtual void DrawManually(SpriteBatch spriteBatch, bool alsoChildren = false, bool recursive = true)
572  {
573  if (!Visible) { return; }
574 
575  AutoDraw = false;
576  Draw(spriteBatch);
577  if (alsoChildren)
578  {
579  DrawChildren(spriteBatch, recursive);
580  }
581  }
582 
586  public virtual void DrawChildren(SpriteBatch spriteBatch, bool recursive)
587  {
588  foreach (RectTransform child in RectTransform.Children)
589  {
590  child.GUIComponent.DrawManually(spriteBatch, recursive, recursive);
591  }
592  }
593 
594  protected Color _currentColor;
595 
596  protected virtual Color GetColor(ComponentState state)
597  {
598  if (!Enabled) { return DisabledColor; }
599  if (ExternalHighlight) { return HoverColor; }
600 
601  return state switch
602  {
603  ComponentState.Hover => HoverColor,
604  ComponentState.HoverSelected => HoverColor,
605  ComponentState.Pressed => PressedColor,
606  ComponentState.Selected when !GlowOnSelect => SelectedColor,
607  _ => Color,
608  };
609  }
610 
611  protected Color GetBlendedColor(Color targetColor, ref Color blendedColor)
612  {
613  blendedColor = ColorCrossFadeTime > 0 ? Color.Lerp(blendedColor, targetColor, MathUtils.InverseLerp(ColorCrossFadeTime, 0, ToolBox.GetEasing(ColorTransition, colorFadeTimer))) : targetColor;
614  return blendedColor;
615  }
616 
617  protected virtual void Draw(SpriteBatch spriteBatch)
618  {
619  if (!Visible) { return; }
620  var rect = Rect;
621 
623 
624  if (_currentColor.A > 0.0f && (sprites == null || !sprites.Any()))
625  {
626  GUI.DrawRectangle(spriteBatch, rect, _currentColor * (_currentColor.A / 255.0f), true);
627  }
628 
629  if (sprites != null && _currentColor.A > 0)
630  {
631  if (!sprites.TryGetValue(_previousState, out List<UISprite> previousSprites) || previousSprites.None())
632  {
633  switch (FallBackState)
634  {
635  case SpriteFallBackState.Toggle:
636  sprites.TryGetValue(Selected ? ComponentState.Selected : ComponentState.None, out previousSprites);
637  break;
638  default:
639  if (Enum.TryParse(FallBackState.ToString(), ignoreCase: true, out ComponentState fallBackState))
640  {
641  sprites.TryGetValue(fallBackState, out previousSprites);
642  }
643  break;
644  }
645  }
646  // Handle fallbacks when some of the sprites are not defined
647  if (!sprites.TryGetValue(State, out List<UISprite> currentSprites) || currentSprites.None())
648  {
649  switch (FallBackState)
650  {
651  case SpriteFallBackState.Toggle:
652  sprites.TryGetValue(Selected ? ComponentState.Selected : ComponentState.None, out currentSprites);
653  break;
654  default:
655  if (Enum.TryParse(FallBackState.ToString(), ignoreCase: true, out ComponentState fallBackState))
656  {
657  sprites.TryGetValue(fallBackState, out currentSprites);
658  }
659  break;
660  }
661  }
662  if (_previousState != State && currentSprites != previousSprites)
663  {
664  if (previousSprites != null && previousSprites.Any())
665  {
666  // Draw the previous sprites(s) only while cross fading out
667  Color previousColor = GetColor(_previousState);
668  foreach (UISprite uiSprite in previousSprites)
669  {
670  float alphaMultiplier = SpriteCrossFadeTime > 0 && (uiSprite.CrossFadeOut || currentSprites != null && currentSprites.Any(s => s.CrossFadeIn))
671  ? MathUtils.InverseLerp(0, SpriteCrossFadeTime, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : 0;
672  if (alphaMultiplier > 0)
673  {
674  uiSprite.Draw(spriteBatch, rect, previousColor * alphaMultiplier, SpriteEffects, uvOffset: UVOffset);
675  }
676  }
677  }
678  }
679  if (currentSprites != null && currentSprites.Any())
680  {
681  // Draw the current sprite(s)
682  foreach (UISprite uiSprite in currentSprites)
683  {
684  float alphaMultiplier = SpriteCrossFadeTime > 0 && (uiSprite.CrossFadeIn || previousSprites != null && previousSprites.Any(s => s.CrossFadeOut))
685  ? MathUtils.InverseLerp(SpriteCrossFadeTime, 0, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : (_currentColor.A / 255.0f);
686  if (alphaMultiplier > 0)
687  {
688  // * (rect.Location.Y - PlayerInput.MousePosition.Y) / rect.Height
689  Vector2 offset = new Vector2(
690  MathUtils.PositiveModulo((int)-UVOffset.X, uiSprite.Sprite.SourceRect.Width),
691  MathUtils.PositiveModulo((int)-UVOffset.Y, uiSprite.Sprite.SourceRect.Height));
692  uiSprite.Draw(spriteBatch, rect, _currentColor * alphaMultiplier, SpriteEffects, uvOffset: offset);
693  }
694  }
695  }
696  }
697 
698  if (GlowOnSelect && State == ComponentState.Selected)
699  {
700  GUIStyle.UIGlow.Draw(spriteBatch, Rect, SelectedColor);
701  }
702 
703  if (flashTimer > 0.0f)
704  {
705  //the number of flashes depends on the duration, 1 flash per 1 full second
706  int flashCycleCount = (int)Math.Max(flashDuration, 1);
707  float flashCycleDuration = flashDuration / flashCycleCount;
708 
709  Rectangle flashRect = Rect;
710  flashRect.Inflate(flashRectInflate.X, flashRectInflate.Y);
711 
712  //MathHelper.Pi * 0.8f -> the curve goes from 144 deg to 0,
713  //i.e. quickly bumps up from almost full brightness to full and then fades out
714  if (useRectangleFlash)
715  {
716  GUI.DrawRectangle(spriteBatch, flashRect, flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), true);
717  }
718  else
719  {
720  var glow = useCircularFlash ? GUIStyle.UIGlowCircular : GUIStyle.UIGlow;
721  glow.Draw(spriteBatch,
722  flashRect,
723  flashColor * (float)Math.Sin(flashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f));
724  }
725  }
726  }
727 
731  public void DrawToolTip(SpriteBatch spriteBatch)
732  {
733  if (!Visible) { return; }
734  DrawToolTip(spriteBatch, ToolTip, Rect);
735  }
736 
737  public static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Vector2 pos, Color? textColor = null, Color? backgroundColor = null)
738  {
739  if (ObjectiveManager.ContentRunning) { return; }
740 
741  int width = (int)(400 * GUI.Scale);
742  int height = (int)(18 * GUI.Scale);
743  Point padding = new Point((int)(10 * GUI.Scale));
744 
745  if (toolTipBlock == null || (RichString)toolTipBlock.UserData != toolTip)
746  {
747  toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), toolTip, font: GUIStyle.SmallFont, wrap: true, style: "GUIToolTip");
748  if (textColor != null) { toolTipBlock.TextColor = textColor.Value; }
749  if (backgroundColor != null) { toolTipBlock.Color = backgroundColor.Value; }
750  toolTipBlock.RectTransform.NonScaledSize = new Point(
751  (int)(GUIStyle.SmallFont.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z),
752  (int)(GUIStyle.SmallFont.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W));
753  toolTipBlock.UserData = toolTip;
754  }
755 
756  toolTipBlock.RectTransform.AbsoluteOffset = pos.ToPoint();
757  toolTipBlock.SetTextPos();
758 
759  if (toolTipBlock.Rect.Right > GameMain.GraphicsWidth - 10)
760  {
761  toolTipBlock.RectTransform.AbsoluteOffset -= new Point(toolTipBlock.Rect.Width,0);
762  }
763  if (toolTipBlock.Rect.Bottom > GameMain.GraphicsHeight - 10)
764  {
765  toolTipBlock.RectTransform.AbsoluteOffset -= new Point(0, toolTipBlock.Rect.Height);
766  }
767 
768  toolTipBlock.DrawManually(spriteBatch);
769  }
770 
771  public static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Rectangle targetElement, Anchor anchor = Anchor.BottomCenter, Pivot pivot = Pivot.TopLeft)
772  {
773  if (ObjectiveManager.ContentRunning) { return; }
774 
775  int width = (int)(400 * GUI.Scale);
776  int height = (int)(18 * GUI.Scale);
777  Point padding = new Point((int)(10 * GUI.Scale));
778 
779  if (toolTipBlock == null || (RichString)toolTipBlock.UserData != toolTip)
780  {
781  toolTipBlock = new GUITextBlock(new RectTransform(new Point(width, height), null), toolTip, font: GUIStyle.SmallFont, wrap: true, style: "GUIToolTip");
782  toolTipBlock.RectTransform.NonScaledSize = new Point(
783  (int)(toolTipBlock.Font.MeasureString(toolTipBlock.WrappedText).X + padding.X + toolTipBlock.Padding.X + toolTipBlock.Padding.Z),
784  (int)(toolTipBlock.Font.MeasureString(toolTipBlock.WrappedText).Y + padding.Y + toolTipBlock.Padding.Y + toolTipBlock.Padding.W));
785  toolTipBlock.UserData = toolTip;
786  }
787 
788  CalculateOffset();
789 
790  if (toolTipBlock.Rect.Right > GameMain.GraphicsWidth - 10)
791  {
792  anchor = RectTransform.MoveAnchorLeft(anchor);
793  pivot = (Pivot)RectTransform.MoveAnchorRight((Anchor)pivot);
794  CalculateOffset();
795  }
796  if (toolTipBlock.Rect.Bottom > GameMain.GraphicsHeight - 10)
797  {
798  anchor = RectTransform.MoveAnchorTop(anchor);
799  pivot = (Pivot)RectTransform.MoveAnchorBottom((Anchor)pivot);
800  CalculateOffset();
801  }
802  toolTipBlock.SetTextPos();
803 
804  toolTipBlock.DrawManually(spriteBatch);
805 
806  void CalculateOffset()
807  {
808  toolTipBlock.RectTransform.AbsoluteOffset =
809  RectTransform.CalculateAnchorPoint(anchor, targetElement) +
811  }
812  }
813  #endregion
814 
815  protected virtual void SetAlpha(float a)
816  {
817  color = new Color(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, a);
818  hoverColor = new Color(hoverColor.R / 255.0f, hoverColor.G / 255.0f, hoverColor.B / 255.0f, a);
819  disabledColor = new Color(disabledColor.R / 255.0f, disabledColor.G / 255.0f, disabledColor.B / 255.0f, a);
820  }
821 
822  public virtual void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, bool useCircularFlash = false, Vector2? flashRectInflate = null)
823  {
825  this.flashRectInflate = flashRectInflate ?? Vector2.Zero;
826  this.useRectangleFlash = useRectangleFlash;
827  this.useCircularFlash = useCircularFlash;
828  this.flashDuration = flashDuration;
829  flashColor = (color == null) ? GUIStyle.Red : (Color)color;
830  }
831 
832  public void ImmediateFlash(Color? color = null)
833  {
834  flashTimer = MathHelper.Pi / 4.0f * 0.1f;
835  flashDuration = 1.0f *0.1f;
836  flashColor = (color == null) ? GUIStyle.Red : (Color)color;
837  }
838 
839  public void FadeOut(float duration, bool removeAfter, float wait = 0.0f, Action onRemove = null, bool alsoChildren = false)
840  {
841  CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter, wait, onRemove));
842  if (alsoChildren)
843  {
844  foreach (var child in Children)
845  {
846  child.FadeOut(duration, removeAfter, wait, onRemove, alsoChildren);
847  }
848  }
849  }
850 
851  public void FadeIn(float wait, float duration, bool alsoChildren = false)
852  {
853  SetAlpha(0.0f);
854  CoroutineManager.StartCoroutine(LerpAlpha(1.0f, duration, false, wait));
855  if (alsoChildren)
856  {
857  foreach (var child in Children)
858  {
859  child.FadeIn(wait, duration, alsoChildren);
860  }
861  }
862  }
863 
864  public void SlideIn(float wait, float duration, int amount, SlideDirection direction)
865  {
866  RectTransform.ScreenSpaceOffset = direction switch
867  {
868  SlideDirection.Up => new Point(0, amount),
869  SlideDirection.Down => new Point(0, -amount),
870  SlideDirection.Left => new Point(amount, 0),
871  SlideDirection.Right => new Point(-amount, 0),
873  };
874  CoroutineManager.StartCoroutine(SlideToPosition(duration, wait, Vector2.Zero));
875  }
876 
877  public void SlideOut(float duration, int amount, SlideDirection direction)
878  {
879  RectTransform.ScreenSpaceOffset = Point.Zero;
880 
881  Vector2 targetPos = direction switch
882  {
883  SlideDirection.Up => new Vector2(0, amount),
884  SlideDirection.Down => new Vector2(0, -amount),
885  SlideDirection.Left => new Vector2(amount, 0),
886  SlideDirection.Right => new Vector2(-amount, 0),
887  _ => Vector2.Zero
888  };
889 
890  CoroutineManager.StartCoroutine(SlideToPosition(duration, 0.0f, targetPos));
891  }
892 
893  private IEnumerable<CoroutineStatus> SlideToPosition(float duration, float wait, Vector2 target)
894  {
895  float t = 0.0f;
896  var (startX, startY) = RectTransform.ScreenSpaceOffset.ToVector2();
897  var (endX, endY) = target;
898  while (t < wait)
899  {
900  t += CoroutineManager.DeltaTime;
901  yield return CoroutineStatus.Running;
902  }
903  t = 0.0f;
904 
905  while (t < duration)
906  {
907  t += CoroutineManager.DeltaTime;
908  RectTransform.ScreenSpaceOffset = new Point((int)MathHelper.Lerp(startX, endX, t / duration), (int)MathHelper.Lerp(startY, endY, t / duration));
909  yield return CoroutineStatus.Running;
910  }
911 
912  RectTransform.ScreenSpaceOffset = new Point(0, 0);
913 
914  yield return CoroutineStatus.Success;
915  }
916 
917  private IEnumerable<CoroutineStatus> LerpAlpha(float to, float duration, bool removeAfter, float wait = 0.0f, Action onRemove = null)
918  {
919  State = ComponentState.None;
920  float t = 0.0f;
921  float startA = color.A / 255.0f;
922 
923  while (t < wait)
924  {
925  t += CoroutineManager.DeltaTime;
926  yield return CoroutineStatus.Running;
927  }
928  t = 0.0f;
929 
930  while (t < duration)
931  {
932  t += CoroutineManager.DeltaTime;
933  SetAlpha(MathHelper.Lerp(startA, to, t / duration));
934  yield return CoroutineStatus.Running;
935  }
936 
937  SetAlpha(to);
938 
939  if (removeAfter && Parent != null)
940  {
941  Parent.RemoveChild(this);
942  onRemove?.Invoke();
943  }
944 
945  yield return CoroutineStatus.Success;
946  }
947 
948  public void Pulsate(Vector2 startScale, Vector2 endScale, float duration)
949  {
950  if (CoroutineManager.IsCoroutineRunning(pulsateCoroutine))
951  {
952  return;
953  }
954  pulsateCoroutine = CoroutineManager.StartCoroutine(DoPulsate(startScale, endScale, duration), "Pulsate" + ToString());
955  }
956 
957  private IEnumerable<CoroutineStatus> DoPulsate(Vector2 startScale, Vector2 endScale, float duration)
958  {
959  float t = 0.0f;
960  while (t < duration)
961  {
962  t += CoroutineManager.DeltaTime;
963  RectTransform.LocalScale = Vector2.Lerp(startScale, endScale, (float)Math.Sin(t / duration * MathHelper.Pi));
964  yield return CoroutineStatus.Running;
965  }
966  RectTransform.LocalScale = startScale;
967  yield return CoroutineStatus.Success;
968  }
969 
970  public virtual void ApplyStyle(GUIComponentStyle style)
971  {
972  if (style == null) { return; }
973 
974  color = style.Color;
976  hoverColor = style.HoverColor;
978  pressedColor = style.PressedColor;
980  sprites = style.Sprites;
981  OutlineColor = style.OutlineColor;
986 
987  if (rectTransform != null)
988  {
989  ApplySizeRestrictions(style);
990  }
991 
993  }
994 
996  {
997  if (style.Width.HasValue)
998  {
999  RectTransform.MinSize = new Point(style.Width.Value, RectTransform.MinSize.Y);
1000  RectTransform.MaxSize = new Point(style.Width.Value, RectTransform.MaxSize.Y);
1001  if (rectTransform.IsFixedSize) { RectTransform.Resize(new Point(style.Width.Value, rectTransform.NonScaledSize.Y)); }
1002  }
1003  if (style.Height.HasValue)
1004  {
1005  RectTransform.MinSize = new Point(RectTransform.MinSize.X, style.Height.Value);
1006  RectTransform.MaxSize = new Point(RectTransform.MaxSize.X, style.Height.Value);
1007  if (rectTransform.IsFixedSize) { RectTransform.Resize(new Point(rectTransform.NonScaledSize.X, style.Height.Value)); }
1008  }
1009  }
1010 
1016  {
1018  }
1019 
1025  {
1027  }
1028 
1029  public static GUIComponent FromXML(ContentXElement element, RectTransform parent)
1030  {
1031  GUIComponent component = null;
1032 
1033  foreach (var subElement in element.Elements())
1034  {
1035  if (subElement.Name.ToString().Equals("conditional", StringComparison.OrdinalIgnoreCase) && !CheckConditional(subElement))
1036  {
1037  return null;
1038  }
1039  }
1040 
1041  switch (element.Name.ToString().ToLowerInvariant())
1042  {
1043  case "text":
1044  case "guitextblock":
1045  component = LoadGUITextBlock(element, parent);
1046  break;
1047  case "link":
1048  component = LoadLink(element, parent);
1049  break;
1050  case "frame":
1051  case "guiframe":
1052  case "spacing":
1053  component = LoadGUIFrame(element, parent);
1054  break;
1055  case "button":
1056  case "guibutton":
1057  component = LoadGUIButton(element, parent);
1058  break;
1059  case "listbox":
1060  case "guilistbox":
1061  component = LoadGUIListBox(element, parent);
1062  break;
1063  case "guilayoutgroup":
1064  case "layoutgroup":
1065  component = LoadGUILayoutGroup(element, parent);
1066  break;
1067  case "image":
1068  case "guiimage":
1069  component = LoadGUIImage(element, parent);
1070  break;
1071  case "accordion":
1072  return LoadAccordion(element, parent);
1073  case "gridtext":
1074  LoadGridText(element, parent);
1075  return null;
1076  case "conditional":
1077  break;
1078  default:
1079  throw new NotImplementedException("Loading GUI component \"" + element.Name + "\" from XML is not implemented.");
1080  }
1081 
1082  if (component != null)
1083  {
1084  foreach (var subElement in element.Elements())
1085  {
1086  if (subElement.Name.ToString().Equals("conditional", StringComparison.OrdinalIgnoreCase)) { continue; }
1087  FromXML(subElement, component is GUIListBox listBox ? listBox.Content.RectTransform : component.RectTransform);
1088  }
1089 
1090  if (element.GetAttributeBool("resizetofitchildren", false))
1091  {
1092  Vector2 relativeResizeScale = element.GetAttributeVector2("relativeresizescale", Vector2.One);
1093  if (component is GUILayoutGroup layoutGroup)
1094  {
1095  layoutGroup.RectTransform.NonScaledSize =
1096  layoutGroup.IsHorizontal ?
1097  new Point(layoutGroup.Children.Sum(c => c.Rect.Width), layoutGroup.Rect.Height) :
1098  component.RectTransform.MinSize = new Point(layoutGroup.Rect.Width, layoutGroup.Children.Sum(c => c.Rect.Height));
1099  if (layoutGroup.CountChildren > 0)
1100  {
1101  layoutGroup.RectTransform.NonScaledSize +=
1102  layoutGroup.IsHorizontal ?
1103  new Point((int)((layoutGroup.CountChildren - 1) * (layoutGroup.AbsoluteSpacing + layoutGroup.Rect.Width * layoutGroup.RelativeSpacing)), 0) :
1104  new Point(0, (int)((layoutGroup.CountChildren - 1) * (layoutGroup.AbsoluteSpacing + layoutGroup.Rect.Height * layoutGroup.RelativeSpacing)));
1105  }
1106  }
1107  else if (component is GUIListBox listBox)
1108  {
1109  listBox.RectTransform.NonScaledSize =
1110  listBox.ScrollBar.IsHorizontal ?
1111  new Point(listBox.Children.Sum(c => c.Rect.Width + listBox.Spacing), listBox.Rect.Height) :
1112  component.RectTransform.MinSize = new Point(listBox.Rect.Width, listBox.Children.Sum(c => c.Rect.Height + listBox.Spacing));
1113  }
1114  else
1115  {
1116  component.RectTransform.NonScaledSize =
1117  new Point(
1118  component.Children.Max(c => c.Rect.Right) - component.Children.Min(c => c.Rect.X),
1119  component.Children.Max(c => c.Rect.Bottom) - component.Children.Min(c => c.Rect.Y));
1120  }
1121  component.RectTransform.NonScaledSize =
1122  component.RectTransform.NonScaledSize.Multiply(relativeResizeScale);
1123  }
1124  }
1125  return component;
1126  }
1127 
1128  private static bool CheckConditional(XElement element)
1129  {
1130  foreach (XAttribute attribute in element.Attributes())
1131  {
1132  switch (attribute.Name.ToString().ToLowerInvariant())
1133  {
1134  case "language":
1135  var languages = element.GetAttributeIdentifierArray(attribute.Name.ToString(), Array.Empty<Identifier>())
1136  .Select(s => new LanguageIdentifier(s));
1137  if (!languages.Any(l => GameSettings.CurrentConfig.Language == l)) { return false; }
1138  break;
1139  case "gameversion":
1140  var version = new Version(attribute.Value);
1141  if (GameMain.Version != version) { return false; }
1142  break;
1143  case "mingameversion":
1144  var minVersion = new Version(attribute.Value);
1145  if (GameMain.Version < minVersion) { return false; }
1146  break;
1147  case "maxgameversion":
1148  var maxVersion = new Version(attribute.Value);
1149  if (GameMain.Version > maxVersion) { return false; }
1150  break;
1151  case "buildconfiguration":
1152  switch (attribute.Value.ToString().ToLowerInvariant())
1153  {
1154  case "debug":
1155 #if DEBUG
1156  return true;
1157 #else
1158  break;
1159 #endif
1160  case "unstable":
1161 #if UNSTABLE
1162  return true;
1163 #else
1164  break;
1165 #endif
1166  case "release":
1167 #if !DEBUG && !UNSTABLE
1168  return true;
1169 #else
1170  break;
1171 #endif
1172  }
1173  return false;
1174  }
1175  }
1176 
1177  return true;
1178  }
1179 
1180  private static GUITextBlock LoadGUITextBlock(XElement element, RectTransform parent, string overrideText = null, Anchor? anchor = null)
1181  {
1182  string text = overrideText ??
1183  (element.Attribute("text") == null ?
1184  element.ElementInnerText() :
1185  element.GetAttributeString("text", ""));
1186  text = text.Replace(@"\n", "\n");
1187 
1188  string style = element.GetAttributeString("style", "");
1189  if (style == "null") { style = null; }
1190  Color? color = null;
1191  if (element.Attribute("color") != null) { color = element.GetAttributeColor("color", Color.White); }
1192  float scale = element.GetAttributeFloat("scale", 1.0f);
1193  bool wrap = element.GetAttributeBool("wrap", true);
1194  Alignment alignment =
1195  element.GetAttributeEnum("alignment", text.Contains('\n') ? Alignment.Left : Alignment.Center);
1196  if (!GUIStyle.Fonts.TryGetValue(element.GetAttributeIdentifier("font", "Font"), out GUIFont font))
1197  {
1198  font = GUIStyle.Font;
1199  }
1200 
1201  var textBlock = new GUITextBlock(RectTransform.Load(element, parent),
1202  RichString.Rich(text), color, font, alignment, wrap: wrap, style: style)
1203  {
1204  TextScale = scale
1205  };
1206  if (anchor.HasValue) { textBlock.RectTransform.SetPosition(anchor.Value); }
1207  textBlock.RectTransform.IsFixedSize = true;
1208  textBlock.RectTransform.NonScaledSize = new Point(textBlock.Rect.Width, textBlock.Rect.Height);
1209  return textBlock;
1210  }
1211 
1212  private static GUIButton LoadLink(XElement element, RectTransform parent)
1213  {
1214  var button = LoadGUIButton(element, parent);
1215  string url = element.GetAttributeString("url", "");
1216  button.OnClicked = (btn, userdata) =>
1217  {
1218  try
1219  {
1220  if (SteamManager.IsInitialized)
1221  {
1222  SteamManager.OverlayCustomUrl(url);
1223  }
1224  else
1225  {
1226  ToolBox.OpenFileWithShell(url);
1227  }
1228  }
1229  catch (Exception e)
1230  {
1231  DebugConsole.ThrowError("Failed to open url \""+url+"\".", e);
1232  }
1233  return true;
1234  };
1235  return button;
1236  }
1237 
1238  private static void LoadGridText(XElement element, RectTransform parent)
1239  {
1240  string text = element.Attribute("text") == null ?
1241  element.ElementInnerText() :
1242  element.GetAttributeString("text", "");
1243  text = text.Replace(@"\n", "\n");
1244 
1245  string[] elements = text.Split(',');
1246  RectTransform lineContainer = null;
1247  for (int i = 0; i < elements.Length; i++)
1248  {
1249  switch (i % 3)
1250  {
1251  case 0:
1252  lineContainer = LoadGUITextBlock(element, parent, elements[i], Anchor.CenterLeft).RectTransform;
1253  lineContainer.Anchor = Anchor.TopCenter;
1254  lineContainer.Pivot = Pivot.TopCenter;
1255  lineContainer.NonScaledSize = new Point((int)(parent.NonScaledSize.X * 0.7f), lineContainer.NonScaledSize.Y);
1256  break;
1257  case 1:
1258  LoadGUITextBlock(element, lineContainer, elements[i], Anchor.Center).TextAlignment = Alignment.Center;
1259  break;
1260  case 2:
1261  LoadGUITextBlock(element, lineContainer, elements[i], Anchor.CenterRight).TextAlignment = Alignment.CenterRight;
1262  break;
1263  }
1264  }
1265  }
1266 
1267  private static GUIFrame LoadGUIFrame(XElement element, RectTransform parent)
1268  {
1269  string style = element.GetAttributeString("style", element.Name.ToString().Equals("spacing", StringComparison.OrdinalIgnoreCase) ? null : "");
1270  if (style == "null") { style = null; }
1271  return new GUIFrame(RectTransform.Load(element, parent), style: style);
1272  }
1273 
1274  private static GUIButton LoadGUIButton(XElement element, RectTransform parent)
1275  {
1276  string style = element.GetAttributeString("style", "");
1277  if (style == "null") { style = null; }
1278 
1279  Alignment textAlignment = Alignment.Center;
1280  Enum.TryParse(element.GetAttributeString("textalignment", "Center"), out textAlignment);
1281 
1282  string text = element.Attribute("text") == null ?
1283  element.ElementInnerText() :
1284  element.GetAttributeString("text", "");
1285  text = text.Replace(@"\n", "\n");
1286 
1287  return new GUIButton(RectTransform.Load(element, parent),
1288  text: text,
1289  textAlignment: textAlignment,
1290  style: style);
1291  }
1292 
1293  private static GUIListBox LoadGUIListBox(XElement element, RectTransform parent)
1294  {
1295  string style = element.GetAttributeString("style", "");
1296  if (style == "null") { style = null; }
1297  bool isHorizontal = element.GetAttributeBool("ishorizontal", !element.GetAttributeBool("isvertical", true));
1298  return new GUIListBox(RectTransform.Load(element, parent), isHorizontal, style: style);
1299  }
1300 
1301  private static GUILayoutGroup LoadGUILayoutGroup(XElement element, RectTransform parent)
1302  {
1303  bool isHorizontal = element.GetAttributeBool("ishorizontal", !element.GetAttributeBool("isvertical", true));
1304 
1305  Enum.TryParse(element.GetAttributeString("childanchor", "TopLeft"), out Anchor childAnchor);
1306  return new GUILayoutGroup(RectTransform.Load(element, parent), isHorizontal, childAnchor)
1307  {
1308  Stretch = element.GetAttributeBool("stretch", false),
1309  RelativeSpacing = element.GetAttributeFloat("relativespacing", 0.0f),
1310  AbsoluteSpacing = element.GetAttributeInt("absolutespacing", 0),
1311  };
1312  }
1313 
1314  private static GUIImage LoadGUIImage(ContentXElement element, RectTransform parent)
1315  {
1316  Sprite sprite;
1317  string url = element.GetAttributeString("url", "");
1318  if (!string.IsNullOrEmpty(url))
1319  {
1320  string localFileName = Path.GetFileNameWithoutExtension(url.Replace("/", "").Replace(":", "").Replace("https", "").Replace("http", ""))
1321  .Replace(".", "");
1322  localFileName += Path.GetExtension(url);
1323  string localFilePath = Path.Combine("Downloads", localFileName);
1324  if (!File.Exists(localFilePath))
1325  {
1326  Uri baseAddress = new Uri(url);
1327  Uri remoteDirectory = new Uri(baseAddress, ".");
1328  string remoteFileName = Path.GetFileName(baseAddress.LocalPath);
1329  IRestClient client = new RestClient(remoteDirectory);
1330  var response = client.Execute(new RestRequest(remoteFileName, Method.GET));
1331  if (response.ResponseStatus != ResponseStatus.Completed) { return null; }
1332  if (response.StatusCode != HttpStatusCode.OK) { return null; }
1333 
1334  if (!Directory.Exists("Downloads")) { Directory.CreateDirectory("Downloads"); }
1335  File.WriteAllBytes(localFilePath, response.RawBytes);
1336  }
1337  sprite = new Sprite(element, "Downloads", localFileName);
1338  }
1339  else
1340  {
1341  sprite = new Sprite(element);
1342  }
1343 
1344  return new GUIImage(RectTransform.Load(element, parent), sprite, scaleToFit: true);
1345  }
1346 
1347  private static GUIButton LoadAccordion(ContentXElement element, RectTransform parent)
1348  {
1349  var button = LoadGUIButton(element, parent);
1350  List<GUIComponent> content = new List<GUIComponent>();
1351  foreach (var subElement in element.Elements())
1352  {
1353  var contentElement = FromXML(subElement, parent);
1354  if (contentElement != null)
1355  {
1356  contentElement.Visible = false;
1357  contentElement.IgnoreLayoutGroups = true;
1358  content.Add(contentElement);
1359  }
1360  }
1361  button.OnClicked = (btn, userdata) =>
1362  {
1363  bool visible = content.FirstOrDefault()?.Visible ?? true;
1364  foreach (GUIComponent contentElement in content)
1365  {
1366  contentElement.Visible = !visible;
1367  contentElement.IgnoreLayoutGroups = !contentElement.Visible;
1368  }
1369  if (button.Parent is GUILayoutGroup layoutGroup)
1370  {
1371  layoutGroup.Recalculate();
1372  }
1373  return true;
1374  };
1375  return button;
1376  }
1377  }
1378 }
static CoroutineStatus Running
GUIComponent FindChild(object userData, bool recursive=false)
void ApplySizeRestrictions(GUIComponentStyle style)
void InheritTotalChildrenHeight()
Sets the minimum height of the transfrom to equal to the sum of the heights of the children (i....
GUIComponent(string style)
virtual void ForceLayoutRecalculation()
static GUIComponent FromXML(ContentXElement element, RectTransform parent)
void ImmediateFlash(Color? color=null)
IEnumerable< T > GetAllChildren< T >()
Definition: GUIComponent.cs:41
GUIComponent(string style, RectTransform rectT)
This is the new constructor.
IEnumerable< GUIComponent > FindChildren(Func< GUIComponent, bool > predicate)
void SlideIn(float wait, float duration, int amount, SlideDirection direction)
ComponentState _state
GUIComponent GetChild(int index)
Definition: GUIComponent.cs:54
void UpdateChildren(float deltaTime, bool recursive)
Updates all the children manually.
Color GetBlendedColor(Color targetColor, ref Color blendedColor)
virtual void RemoveChild(GUIComponent child)
Definition: GUIComponent.cs:87
virtual ComponentState State
SecondaryButtonDownHandler OnSecondaryClicked
Definition: GUIComponent.cs:27
virtual void Flash(Color? color=null, float flashDuration=1.5f, bool useRectangleFlash=false, bool useCircularFlash=false, Vector2? flashRectInflate=null)
static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Rectangle targetElement, Anchor anchor=Anchor.BottomCenter, Pivot pivot=Pivot.TopLeft)
void Pulsate(Vector2 startScale, Vector2 endScale, float duration)
void UpdateAuto(float deltaTime)
Only GUI should call this method. Auto updating follows the order of GUI update list....
virtual GUIFont Font
virtual Color GetColor(ComponentState state)
virtual void AddToGUIUpdateList(bool ignoreChildren=false, int order=0)
Dictionary< ComponentState, List< UISprite > > sprites
virtual Rectangle? MouseRect
void DrawAuto(SpriteBatch spriteBatch)
Only GUI should call this method. Auto drawing follows the order of GUI update list....
virtual Color OutlineColor
Rectangle ClampRect(Rectangle r)
virtual void DrawChildren(SpriteBatch spriteBatch, bool recursive)
Draws all the children manually.
void InheritTotalChildrenMinHeight()
Sets the minimum height of the transfrom to equal to the sum of the minimum heights of the children (...
virtual float FlashTimer
bool IsParentOf(GUIComponent component, bool recursive=true)
Definition: GUIComponent.cs:75
virtual bool PlaySoundOnSelect
delegate bool SecondaryButtonDownHandler(GUIComponent component, object userData)
TransitionMode ColorTransition
virtual Color DisabledColor
GUIComponent GetChildByUserData(object obj)
Definition: GUIComponent.cs:66
void SlideOut(float duration, int amount, SlideDirection direction)
Action< GUIComponent > OnAddedToGUIUpdateList
Identifier[] styleHierarchy
Color DefaultColor
Currently only used for the fade effect in GUIListBox, should be set to the same value as Color but o...
virtual void ApplyStyle(GUIComponentStyle style)
virtual void ClearChildren()
virtual void Draw(SpriteBatch spriteBatch)
GUIComponent FindChild(Func< GUIComponent, bool > predicate, bool recursive=false)
Definition: GUIComponent.cs:95
virtual RichString ToolTip
int GetChildIndex(GUIComponent child)
Definition: GUIComponent.cs:60
void UpdateManually(float deltaTime, bool alsoChildren=false, bool recursive=true)
By default, all the gui elements are updated automatically in the same order they appear on the updat...
virtual Color SelectedColor
virtual void DrawManually(SpriteBatch spriteBatch, bool alsoChildren=false, bool recursive=true)
By default, all the gui elements are drawn automatically in the same order they appear on the update ...
void RemoveFromGUIUpdateList(bool alsoChildren=true)
void FadeIn(float wait, float duration, bool alsoChildren=false)
virtual Rectangle Rect
IEnumerable< GUIComponent > GetAllChildren()
Returns all child elements in the hierarchy.
Definition: GUIComponent.cs:49
SpriteFallBackState FallBackState
bool IsChildOf(GUIComponent component, bool recursive=true)
Definition: GUIComponent.cs:81
virtual void Update(float deltaTime)
virtual Color HoverColor
GUIComponentStyle Style
virtual void SetAlpha(float a)
static void DrawToolTip(SpriteBatch spriteBatch, RichString toolTip, Vector2 pos, Color? textColor=null, Color? backgroundColor=null)
void DrawToolTip(SpriteBatch spriteBatch)
Creates and draws a tooltip.
RectTransform RectTransform
SpriteEffects SpriteEffects
IEnumerable< GUIComponent > Children
Definition: GUIComponent.cs:29
void FadeOut(float duration, bool removeAfter, float wait=0.0f, Action onRemove=null, bool alsoChildren=false)
IEnumerable< GUIComponent > FindChildren(object userData)
virtual Color PressedColor
ComponentState _previousState
readonly TransitionMode TransitionMode
readonly Dictionary< GUIComponent.ComponentState, List< UISprite > > Sprites
static Identifier[] ToHierarchy(GUIComponentStyle style)
SpriteFallBackState FallBackState
readonly float ColorCrossFadeTime
static GUIComponentStyle FromHierarchy(IReadOnlyList< Identifier > hierarchy)
readonly float SpriteCrossFadeTime
Vector2 MeasureString(LocalizedString str, bool removeExtraSpacing=false)
Definition: GUIPrefab.cs:284
GUIFrame Content
A frame that contains the contents of the listbox. The frame itself is not rendered.
Definition: GUIListBox.cs:33
override GUIFont Font
Definition: GUITextBlock.cs:66
LocalizedString WrappedText
static int GraphicsWidth
Definition: GameMain.cs:162
static int GraphicsHeight
Definition: GameMain.cs:168
bool IsParentOf(RectTransform rectT, bool recursive=true)
Point ScreenSpaceOffset
Screen space offset. From top left corner. In pixels.
static Anchor MoveAnchorTop(Anchor anchor)
Moves the anchor to the top, keeping the horizontal position unchanged (e.g. BottomCenter -> TopCente...
GUIComponent GUIComponent
Should be assigned only by GUIComponent. Note that RectTransform is created first and the GUIComponen...
IEnumerable< RectTransform > GetAllChildren()
Returns all child elements in the hierarchy.
static RectTransform Load(XElement element, RectTransform parent, Anchor defaultAnchor=Anchor.TopLeft)
void InheritTotalChildrenHeight()
Sets the minimum height of the transfrom to equal to the sum of the heights of the children (i....
Point AbsoluteOffset
Absolute in pixels but relative to the anchor point. Calculated away from the anchor point,...
void Resize(Point absoluteSize, bool resizeChildren=true)
Anchor Anchor
Does not automatically calculate children. Note also that if you change the anchor point with this pr...
void InheritTotalChildrenMinHeight()
Sets the minimum height of the transfrom to equal to the sum of the minimum heights of the children (...
RectTransform GetChild(int index)
IEnumerable< RectTransform > Children
static Anchor MoveAnchorRight(Anchor anchor)
Moves the anchor to the right, keeping the vertical position unchanged (e.g. CenterLeft -> CenterRigh...
RectTransform?? Parent
int GetChildIndex(RectTransform rectT)
static Anchor MoveAnchorBottom(Anchor anchor)
Moves the anchor to the bottom, keeping the horizontal position unchanged (e.g. TopCenter -> BottomCe...
RectTransform(Vector2 relativeSize, RectTransform parent, Anchor anchor=Anchor.TopLeft, Pivot? pivot=null, Point? minSize=null, Point? maxSize=null, ScaleBasis scaleBasis=ScaleBasis.Normal)
Point?? MinSize
Min size in pixels. Does not affect scaling.
static Point CalculatePivotOffset(Pivot anchor, Point size)
void AddChildrenToGUIUpdateList(bool ignoreChildren=false, int order=0)
bool IsChildOf(RectTransform rectT, bool recursive=true)
static Anchor MoveAnchorLeft(Anchor anchor)
Moves the anchor to the left, keeping the vertical position unchanged (e.g. CenterRight -> CenterLeft...
Point NonScaledSize
Size before scale multiplications.
Point?? MaxSize
Max size in pixels. Does not affect scaling.
bool IsFixedSize
If false, the element will resize if the parent is resized (with the children). If true,...
static Point CalculateAnchorPoint(Anchor anchor, Rectangle parent)
TransitionMode TransitionMode
Definition: UISprite.cs:56
void Draw(SpriteBatch spriteBatch, RectangleF rect, Color color, SpriteEffects spriteEffects=SpriteEffects.None, Vector2? uvOffset=null)
CursorState
Definition: GUI.cs:40
TransitionMode
Definition: Enums.cs:6