Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Widget.cs
浏览该文件的文档.
1using System.Reflection;
2using System.Xml.Linq;
3using Engine;
5using Engine.Input;
7using XmlUtilities;
8
9namespace Game {
10 public class Widget : IDisposable {
11 public class DrawContext {
12 public List<DrawItem> m_drawItems = [];
13
14 public static List<DrawItem> m_drawItemsCache = [];
15
17
19
21
26 // ReSharper disable MemberHidesStaticFromOuterClass
27 public virtual void DrawWidgetsHierarchy(Widget rootWidget)
28 // ReSharper restore MemberHidesStaticFromOuterClass
29 {
30 m_drawItems.Clear();
35 }
36
42 public virtual void CollateDrawItems(Widget widget, Rectangle scissorRectangle) {
43 if (!widget.IsVisible
44 || !widget.IsDrawEnabled) {
45 // 当 Widget 不可见或 Widget 绘制被禁用时。
46 return;
47 }
48 bool isWidgetInBound = widget.GlobalBounds.Intersection(
49 new BoundingRectangle(scissorRectangle.Left, scissorRectangle.Top, scissorRectangle.Right, scissorRectangle.Bottom)
50 );
51 Rectangle? widgetScissorRectangle = null;
52 if (widget.ClampToBounds && isWidgetInBound) {
53 // 如果 Widget 需要将自身绘制的区域限制在 Widget 的 Bounds 内,
54 // 则生成一个用于设置 ScissorRectangle 的 DrawItem
55 widgetScissorRectangle = scissorRectangle;
56 int left = (int)MathF.Floor(widget.GlobalBounds.Min.X - 0.5f);
57 int top = (int)MathF.Floor(widget.GlobalBounds.Min.Y - 0.5f);
58 int right = (int)MathF.Ceiling(widget.GlobalBounds.Max.X - 0.5f);
59 int bottom = (int)MathF.Ceiling(widget.GlobalBounds.Max.Y - 0.5f);
60 scissorRectangle = Rectangle.Intersection(new Rectangle(left, top, right - left, bottom - top), widgetScissorRectangle.Value);
61 DrawItem drawItem = GetDrawItemFromCache();
62 drawItem.ScissorRectangle = scissorRectangle;
63 m_drawItems.Add(drawItem);
64 }
65 if (widget.IsDrawRequired && isWidgetInBound) {
66 // 如果 Widget 需要绘制,则生成一个用于绘制的 DrawItem。
67 DrawItem drawItem = GetDrawItemFromCache();
68 drawItem.Widget = widget;
69 m_drawItems.Add(drawItem);
70 }
71 if (isWidgetInBound || !widget.ClampToBounds) {
72 if (widget is ContainerWidget containerWidget) {
73 // 生成子 Widget 的 DrawItem。
74 foreach (Widget child in containerWidget.Children) {
75 CollateDrawItems(child, scissorRectangle);
76 }
77 }
78 }
79 if (widget.IsOverdrawRequired && isWidgetInBound) {
80 // 如果 Widget 需要 Overdraw,则生成一个用于 Overdraw 的 DrawItem。
81 DrawItem drawItem = GetDrawItemFromCache();
82 drawItem.Widget = widget;
83 drawItem.IsOverdraw = true;
84 m_drawItems.Add(drawItem);
85 }
86 if (widgetScissorRectangle.HasValue) {
87 // 如果 Widget 需要将自身绘制区域限制在 Widget 的 Bounds 内,则生成一个用于设置 ScissorRectangle 的 DrawItem。
88 DrawItem drawItem = GetDrawItemFromCache();
89 drawItem.ScissorRectangle = widgetScissorRectangle;
90 m_drawItems.Add(drawItem);
91 }
92 widget.WidgetsHierarchyInput?.Draw(this);
93 }
94
98 public virtual void AssignDrawItemsLayers() {
99 for (int i = 0; i < m_drawItems.Count; i++) {
100 DrawItem drawItem = m_drawItems[i];
101 for (int j = i + 1; j < m_drawItems.Count; j++) {
102 DrawItem drawItem2 = m_drawItems[j];
103 if (drawItem.ScissorRectangle.HasValue
104 || drawItem2.ScissorRectangle.HasValue) {
105 drawItem2.Layer = MathUtils.Max(drawItem2.Layer, drawItem.Layer + 1);
106 }
107 else if (TestOverlap(drawItem.Widget, drawItem2.Widget)) {
108 drawItem2.Layer = MathUtils.Max(drawItem2.Layer, drawItem.Layer + 1);
109 }
110 }
111 }
112 m_drawItems.Sort();
114 "OnDrawItemAssigned",
115 loader => {
116 loader.OnDrawItemAssigned(this);
117 return false;
118 }
119 );
120 }
121
124 public virtual void RenderDrawItems() {
125 Rectangle scissorRectangle = Display.ScissorRectangle;
126 int currentLayer = 0;
127 foreach (DrawItem drawItem in m_drawItems) {
128 if (LayersLimit >= 0
129 && drawItem.Layer > LayersLimit) {
130 break;
131 }
132 if (drawItem.Layer != currentLayer) {
133 currentLayer = drawItem.Layer;
135 PrimitivesRenderer2D.Flush();
136 }
137 if (drawItem.Widget != null) {
138 Action afterWidgetDraw = null;
139 bool skip = false;
141 "BeforeWidgetDrawItemRender",
142 loader => {
143 loader.BeforeWidgetDrawItemRender(
144 drawItem,
145 out bool skipVanillaDraw,
146 out Action afterDrawAction,
147 ref scissorRectangle,
148 this
149 );
150 if (afterDrawAction != null) {
151 afterWidgetDraw += afterDrawAction;
152 }
153 skip |= skipVanillaDraw;
154 return false;
155 }
156 );
157 if (!skip) {
158 if (drawItem.IsOverdraw) {
159 drawItem.Widget.Overdraw(this);
160 }
161 else {
162 drawItem.Widget.Draw(this);
163 }
164 }
165 afterWidgetDraw?.Invoke();
166 }
167 else {
168 Display.ScissorRectangle = Rectangle.Intersection(scissorRectangle, drawItem.ScissorRectangle!.Value);
169 }
170 }
172 PrimitivesRenderer2D.Flush();
173 Display.ScissorRectangle = scissorRectangle;
175 }
176
182 if (m_drawItemsCache.Count > 0) {
183 DrawItem result = m_drawItemsCache[^1];
184 m_drawItemsCache.RemoveAt(m_drawItemsCache.Count - 1);
185 return result;
186 }
187 return new DrawItem();
188 }
189
193 public virtual void ReturnDrawItemsToCache() {
194 foreach (DrawItem drawItem in m_drawItems) {
195 drawItem.Widget = null;
196 drawItem.Layer = 0;
197 drawItem.IsOverdraw = false;
198 drawItem.ScissorRectangle = null;
199 m_drawItemsCache.Add(drawItem);
200 }
201 }
202 }
203
204 // ReSharper disable UnassignedField.Global
205 public Action<Vector2> MeasureOverride1;
206
207 public Action Update1;
208 // ReSharper restore UnassignedField.Global
209
213 public class DrawItem : IComparable<DrawItem> {
217 public int Layer;
218
223 public bool IsOverdraw;
224
229
234
235 public int CompareTo(DrawItem other) => Layer - other.Layer;
236 }
237
238 public bool m_isVisible;
239
240 public bool m_isEnabled;
241
243
245
247
249
251
252 public bool m_isLayoutTransformIdentity = true;
253
254 public bool m_isRenderTransformIdentity = true;
255
257
259
261
263
264 public float? m_globalScale;
265
267
269
271
272 public static Queue<DrawContext> m_drawContextsCache = new();
273
274 public static int LayersLimit = -1;
275
276 public static bool DrawWidgetBounds = false;
277
280 set {
281 if (value != null) {
282 if (value.m_widget != null
283 && value.m_widget != this) {
284 throw new InvalidOperationException("WidgetInput already assigned to another widget.");
285 }
286 value.m_widget = this;
288 }
289 else if (m_widgetsHierarchyInput != null) {
290 m_widgetsHierarchyInput.m_widget = null;
292 }
293 }
294 }
295
297 get {
298 Widget widget = this;
299 do {
300 if (widget.WidgetsHierarchyInput != null) {
301 return widget.WidgetsHierarchyInput;
302 }
303 widget = widget.ParentWidget;
304 }
305 while (widget != null);
306 return WidgetInput.EmptyInput;
307 }
308 }
309
311 get => m_layoutTransform;
312 set {
313 m_layoutTransform = value;
315 }
316 }
317
319 get => m_renderTransform;
320 set {
321 m_renderTransform = value;
323 }
324 }
325
327
328 public float GlobalScale {
329 get {
330 m_globalScale ??= m_globalTransform.Right.Length();
331 return m_globalScale.Value;
332 }
333 }
334
341
343
345 get => m_colorTransform;
346 set => m_colorTransform = value;
347 }
348
350
351 public virtual string Name { get; set; }
352
353 public object Tag { get; set; }
354 public object ExtraData { get; set; }
355
356 public virtual bool IsVisible {
357 get => m_isVisible;
358 set {
359 if (value != m_isVisible) {
360 m_isVisible = value;
361 if (!m_isVisible) {
362 UpdateCeases();
363 }
364 }
365 }
366 }
367
368 public virtual bool IsEnabled {
369 get => m_isEnabled;
370 set {
371 if (value != m_isEnabled) {
372 m_isEnabled = value;
373 if (!m_isEnabled) {
374 UpdateCeases();
375 }
376 }
377 }
378 }
379
380 public virtual bool IsHitTestVisible { get; set; }
381
382 public bool IsVisibleGlobal {
383 get {
384 if (IsVisible) {
385 if (ParentWidget != null) {
386 return ParentWidget.IsVisibleGlobal;
387 }
388 return true;
389 }
390 return false;
391 }
392 }
393
394 public bool IsEnabledGlobal {
395 get {
396 if (IsEnabled) {
397 if (ParentWidget != null) {
398 return ParentWidget.IsEnabledGlobal;
399 }
400 return true;
401 }
402 return false;
403 }
404 }
405
406 public bool ClampToBounds { get; set; }
407
408 public virtual Vector2 Margin {
409 [Obsolete("Use MarginLeft, MarginTop, MarginRight and MarginBottom instead.")]
410 get => new (MarginLeft, MarginTop);
411 set {
412 MarginLeft = value.X;
413 MarginRight = value.X;
414 MarginTop = value.Y;
415 MarginBottom = value.Y;
416 }
417 }
418
419 public virtual float MarginLeft { get; set; }
420
421 public virtual float MarginRight { get; set; }
422
423 public virtual float MarginTop { get; set; }
424
425 public virtual float MarginBottom { get; set; }
426
427 public virtual Vector4 Margin4 {
429 set {
430 MarginLeft = value.X;
431 MarginTop = value.Y;
432 MarginRight = value.Z;
433 MarginBottom = value.W;
434 }
435 }
436
437 public virtual float MarginHorizontalSum => MarginLeft + MarginRight;
438
439 public virtual float MarginVerticalSum => MarginTop + MarginBottom;
440
442
443 public virtual WidgetAlignment HorizontalAlignment { get; set; }
444
445 public virtual WidgetAlignment VerticalAlignment { get; set; }
446
448
450 get => m_desiredSize;
451 set => m_desiredSize = value;
452 }
453
455
456 public bool IsUpdateEnabled { get; set; } = true;
457
458 public bool IsDrawEnabled { get; set; } = true;
459
460 public bool IsDrawRequired { get; set; }
461
462 public bool IsOverdrawRequired { get; set; }
463
464 public XElement Style {
465 set => LoadContents(null, value);
466 }
467
468 public ContainerWidget ParentWidget { get; set; }
469
471 get {
472 if (ParentWidget == null) {
473 return this;
474 }
475 return ParentWidget.RootWidget;
476 }
477 }
478
479 public Widget() {
480 IsVisible = true;
481 IsHitTestVisible = true;
482 IsEnabled = true;
483 DesiredSize = new Vector2(1f / 0f);
484 }
485
486 public static Widget LoadWidget(object eventsTarget, XElement node, ContainerWidget parentWidget) {
487 if (node.Name.LocalName.Contains(".")) {
488 throw new NotImplementedException("Node property specification not implemented.");
489 }
490#pragma warning disable IL2072
491 if (Activator.CreateInstance(FindTypeFromXmlName(node.Name.LocalName, node.Name.NamespaceName)) is not Widget widget) {
492#pragma warning restore IL2072
493 throw new Exception($"Type \"{node.Name.LocalName}\" is not a Widget.");
494 }
496 "OnWidgetConstruct",
497 loader => {
498 loader.OnWidgetConstruct(ref widget);
499 return false;
500 }
501 );
502 parentWidget?.Children.Add(widget);
503 widget.LoadContents(eventsTarget, node);
504 return widget;
505 }
506
507 public virtual void LoadContents(object eventsTarget, XElement node) {
508 LoadProperties(eventsTarget, node);
509 LoadChildren(eventsTarget, node);
511 "OnWidgetContentsLoaded",
512 loader => {
513 loader.OnWidgetContentsLoaded(this);
514 return false;
515 }
516 );
517 }
518
519 public virtual void LoadProperties(object eventsTarget, XElement node) {
520#pragma warning disable IL2072
521 IEnumerable<PropertyInfo> runtimeProperties = GetType().GetRuntimeProperties().ToArray();
522#pragma warning restore IL2072
523 foreach (XAttribute attribute in node.Attributes()) {
524 if (!attribute.IsNamespaceDeclaration
525 && !attribute.Name.LocalName.StartsWith('_')) {
526 if (attribute.Name.LocalName.Contains('.')) {
527 string[] array = attribute.Name.LocalName.Split('.');
528 if (array.Length != 2) {
529 throw new InvalidOperationException(
530 $"Attached property reference must have form \"TypeName.PropertyName\", property \"{attribute.Name.LocalName}\" in widget of type \"{GetType().FullName}\"."
531 );
532 }
533 Type type = FindTypeFromXmlName(
534 array[0],
535 attribute.Name.NamespaceName != string.Empty ? attribute.Name.NamespaceName : node.Name.NamespaceName
536 );
537 string setterName = $"Set{array[1]}";
538#pragma warning disable IL2072
539 MethodInfo methodInfo = type.GetRuntimeMethods().FirstOrDefault(mi => mi.Name == setterName && mi.IsPublic && mi.IsStatic);
540#pragma warning restore IL2072
541 if (!(methodInfo != null)) {
542 throw new InvalidOperationException(
543 $"Attached property public static setter method \"{setterName}\" not found, property \"{attribute.Name.LocalName}\" in widget of type \"{GetType().FullName}\"."
544 );
545 }
546 ParameterInfo[] parameters = methodInfo.GetParameters();
547 if (parameters.Length != 2
548 || !(parameters[0].ParameterType == typeof(Widget))) {
549 throw new InvalidOperationException(
550 $"Attached property setter method must take 2 parameters and first one must be of type Widget, property \"{attribute.Name.LocalName}\" in widget of type \"{GetType().FullName}\"."
551 );
552 }
553 object obj = HumanReadableConverter.ConvertFromString(parameters[1].ParameterType, attribute.Value);
554 methodInfo.Invoke(null, [this, obj]);
555 }
556 else {
557 PropertyInfo propertyInfo = runtimeProperties.FirstOrDefault(pi => pi.Name == attribute.Name.LocalName);
558 if (!(propertyInfo != null)) {
559 throw new InvalidOperationException(
560 $"Property \"{attribute.Name.LocalName}\" not found in widget of type \"{GetType().FullName}\"."
561 );
562 }
563 if (attribute.Value.StartsWith('{')
564 && attribute.Value.EndsWith('}')) {
565 string name = attribute.Value.Substring(1, attribute.Value.Length - 2);
566 object value = ContentManager.Get(propertyInfo.PropertyType, name, null, false);
567 if (value == null) {
568 Log.Error($"Not Found Res [{name}][{propertyInfo.PropertyType.FullName}] when loading {GetType().FullName}");
569 }
570 else {
571 propertyInfo.SetValue(this, value, null);
572 }
573 }
574 else {
575 object obj2 = HumanReadableConverter.ConvertFromString(propertyInfo.PropertyType, attribute.Value);
576 if (propertyInfo.PropertyType == typeof(string)) {
577 obj2 = ((string)obj2).Replace("\\n", "\n").Replace("\\t", "\t");
578 }
579 propertyInfo.SetValue(this, obj2, null);
580 }
581 }
582 }
583 }
584 }
585
586 public virtual void LoadChildren(object eventsTarget, XElement node) {
587 if (node.HasElements) {
588 if (this is not ContainerWidget containerWidget) {
589 throw new Exception($"Type \"{node.Name.LocalName}\" is not a ContainerWidget, but it contains child widgets.");
590 }
591 foreach (XElement item in node.Elements()) {
593 Widget widget = null;
594 string attributeValue = XmlUtils.GetAttributeValue<string>(item, "Name", null);
595 if (attributeValue != null) {
596 widget = containerWidget.Children.Find(attributeValue, false);
597 }
598 if (widget != null) {
599 widget.LoadContents(eventsTarget, item);
600 }
601 else {
602 LoadWidget(eventsTarget, item, containerWidget);
603 }
604 }
605 }
606 }
607 }
608
609 public virtual bool IsChildWidgetOf(ContainerWidget containerWidget) {
610 if (containerWidget == ParentWidget) {
611 return true;
612 }
613 if (ParentWidget == null) {
614 return false;
615 }
616 return ParentWidget.IsChildWidgetOf(containerWidget);
617 }
618
619 public virtual void ChangeParent(ContainerWidget parentWidget) {
620 if (parentWidget != ParentWidget) {
621 ParentWidget = parentWidget;
622 if (parentWidget == null) {
623 UpdateCeases();
624 }
625 }
626 }
627
628 public virtual void Measure(Vector2 parentAvailableSize) {
629 if (MeasureOverride1 == null) {
630 MeasureOverride(parentAvailableSize);
631 }
632 else {
633 MeasureOverride1(parentAvailableSize);
634 return;
635 }
636 if (DesiredSize.X != 1f / 0f
637 && DesiredSize.Y != 1f / 0f) {
639 m_parentDesiredSize = boundingRectangle.Size();
640 m_parentOffset = -boundingRectangle.Min;
641 }
642 else {
645 }
646 }
647
648 public virtual void MeasureOverride(Vector2 parentAvailableSize) { }
649
650 public virtual void Arrange(Vector2 position, Vector2 parentActualSize) {
651 float num = m_layoutTransform.M11 * m_layoutTransform.M11;
652 float num2 = m_layoutTransform.M12 * m_layoutTransform.M12;
653 float num3 = m_layoutTransform.M21 * m_layoutTransform.M21;
654 float num4 = m_layoutTransform.M22 * m_layoutTransform.M22;
655 m_actualSize.X = (num * parentActualSize.X + num3 * parentActualSize.Y) / (num + num3);
656 m_actualSize.Y = (num2 * parentActualSize.X + num4 * parentActualSize.Y) / (num2 + num4);
658 m_globalColorTransform = ParentWidget != null ? ParentWidget.m_globalColorTransform * m_colorTransform : m_colorTransform;
661 }
662 else {
664 }
665 m_globalTransform.M41 += position.X + m_parentOffset.X;
666 m_globalTransform.M42 += position.Y + m_parentOffset.Y;
667 if (ParentWidget != null) {
668 m_globalTransform *= ParentWidget.GlobalTransform;
669 }
671 m_globalScale = null;
674 }
675
676 public virtual void ArrangeOverride() { }
677
678 public virtual void UpdateCeases() { }
679
680 public virtual void Update() { }
681
682 public virtual void Draw(DrawContext dc) { }
683
684 public virtual void Overdraw(DrawContext dc) { }
685
686 public virtual bool HitTest(Vector2 point) {
687 Vector2 vector = ScreenToWidget(point);
688 if (vector.X >= 0f
689 && vector.Y >= 0f
690 && vector.X <= ActualSize.X) {
691 return vector.Y <= ActualSize.Y;
692 }
693 return false;
694 }
695
696 public virtual Widget HitTestGlobal(Vector2 point, Func<Widget, bool> predicate = null) => HitTestGlobal(RootWidget, point, predicate);
697
699
701
702 public virtual void Dispose() { }
703
704 public static bool TestOverlap(Widget w1, Widget w2) {
705 if (w2.m_globalBounds.Min.X >= w1.m_globalBounds.Max.X - 0.001f) {
706 return false;
707 }
708 if (w2.m_globalBounds.Min.Y >= w1.m_globalBounds.Max.Y - 0.001f) {
709 return false;
710 }
711 if (w1.m_globalBounds.Min.X >= w2.m_globalBounds.Max.X - 0.001f) {
712 return false;
713 }
714 if (w1.m_globalBounds.Min.Y >= w2.m_globalBounds.Max.Y - 0.001f) {
715 return false;
716 }
717 return true;
718 }
719
720 public static bool IsNodeIncludedOnCurrentPlatform(XElement node) {
721 string attributeValue = XmlUtils.GetAttributeValue<string>(node, "_IncludePlatforms", null);
722 string attributeValue2 = XmlUtils.GetAttributeValue<string>(node, "_ExcludePlatforms", null);
723 if (attributeValue != null
724 && attributeValue2 == null) {
725 if (attributeValue.Split(' ').Contains(VersionsManager.PlatformString)) {
726 return true;
727 }
728 }
729 else {
730 if (attributeValue2 == null
731 || attributeValue != null) {
732 return true;
733 }
734 if (!attributeValue2.Split(' ').Contains(VersionsManager.PlatformString)) {
735 return true;
736 }
737 }
738 return false;
739 }
740
741 public static void UpdateWidgetsHierarchy(Widget rootWidget) {
742 if (rootWidget.IsUpdateEnabled) {
743 bool isMouseCursorVisible = false;
744 UpdateWidgetsHierarchy(rootWidget, ref isMouseCursorVisible);
745 Mouse.IsMouseVisible = isMouseCursorVisible;
746 }
747 }
748
749 public static void LayoutWidgetsHierarchy(Widget rootWidget, Vector2 availableSize) {
750 rootWidget.Measure(availableSize);
751 rootWidget.Arrange(Vector2.Zero, availableSize);
752 }
753
754 public static void DrawWidgetsHierarchy(Widget rootWidget) {
755 DrawContext drawContext = m_drawContextsCache.Count > 0 ? m_drawContextsCache.Dequeue() : new DrawContext();
756 try {
757 drawContext.DrawWidgetsHierarchy(rootWidget);
758 }
759 finally {
760 m_drawContextsCache.Enqueue(drawContext);
761 }
762 }
763
765 float num = m_layoutTransform.M11 * size.X;
766 float num2 = m_layoutTransform.M21 * size.Y;
767 float x = num + num2;
768 float num3 = m_layoutTransform.M12 * size.X;
769 float num4 = m_layoutTransform.M22 * size.Y;
770 float x2 = num3 + num4;
771 float x3 = MathUtils.Min(0f, num, num2, x);
772 float x4 = MathUtils.Max(0f, num, num2, x);
773 float y = MathUtils.Min(0f, num3, num4, x2);
774 float y2 = MathUtils.Max(0f, num3, num4, x2);
775 return new BoundingRectangle(x3, y, x4, y2);
776 }
777
779 float num = m_globalTransform.M11 * size.X;
780 float num2 = m_globalTransform.M21 * size.Y;
781 float x = num + num2;
782 float num3 = m_globalTransform.M12 * size.X;
783 float num4 = m_globalTransform.M22 * size.Y;
784 float x2 = num3 + num4;
785 float num5 = MathUtils.Min(0f, num, num2, x);
786 float num6 = MathUtils.Max(0f, num, num2, x);
787 float num7 = MathUtils.Min(0f, num3, num4, x2);
788 return new BoundingRectangle(
789 y2: MathUtils.Max(0f, num3, num4, x2) + m_globalTransform.M42,
790 x1: num5 + m_globalTransform.M41,
791 y1: num7 + m_globalTransform.M42,
792 x2: num6 + m_globalTransform.M41
793 );
794 }
795
796 public static Type FindTypeFromXmlName(string name, string namespaceName) {
797 if (!string.IsNullOrEmpty(namespaceName)) {
798 Uri uri = new(namespaceName);
799 if (uri.Scheme == "runtime-namespace") {
800 return TypeCache.FindType($"{uri.AbsolutePath}.{name}", false, true);
801 }
802 throw new InvalidOperationException("Unknown uri scheme when loading widget. Scheme must be runtime-namespace.");
803 }
804 throw new InvalidOperationException("Namespace must be specified when creating types in XML.");
805 }
806
807 public static Widget HitTestGlobal(Widget widget, Vector2 point, Func<Widget, bool> predicate) {
808 if (widget != null
809 && widget.IsVisible
810 && (!widget.ClampToBounds || widget.HitTest(point))) {
811 if (widget is ContainerWidget containerWidget) {
812 WidgetsList children = containerWidget.Children;
813 for (int num = children.Count - 1; num >= 0; num--) {
814 Widget widget2 = HitTestGlobal(children[num], point, predicate);
815 if (widget2 != null) {
816 return widget2;
817 }
818 }
819 }
820 if (widget.IsHitTestVisible
821 && widget.HitTest(point)
822 && (predicate == null || predicate(widget))) {
823 return widget;
824 }
825 }
826 return null;
827 }
828
829 public static void UpdateWidgetsHierarchy(Widget widget, ref bool isMouseCursorVisible) {
830 if (!widget.IsVisible
831 || !widget.IsUpdateEnabled
832 || !widget.IsEnabled) {
833 return;
834 }
835 if (widget.WidgetsHierarchyInput != null) {
837 isMouseCursorVisible |= widget.WidgetsHierarchyInput.IsMouseCursorVisible;
838 }
839 if (widget is ContainerWidget containerWidget) {
840 WidgetsList children = containerWidget.Children;
841 for (int num = children.Count - 1; num >= 0; num--) {
842 if (num < children.Count) {
843 UpdateWidgetsHierarchy(children[num], ref isMouseCursorVisible);
844 }
845 }
846 }
847 if (widget.Update1 == null) {
849 "BeforeWidgetUpdate",
850 loader => {
851 loader.BeforeWidgetUpdate(widget);
852 return false;
853 }
854 );
855 widget.Update();
857 "AfterWidgetUpdate",
858 loader => {
859 loader.AfterWidgetUpdate(widget);
860 return false;
861 }
862 );
863 }
864 else {
865 widget.Update1();
866 }
867 }
868 }
869}
Android.Net.Uri Uri
static Rectangle ScissorRectangle
static bool IsMouseVisible
static void Error(object message)
定义 Log.cs:80
static int Min(int x1, int x2)
static int Max(int x1, int x2)
static object ConvertFromString(Type type, string data)
static Type FindType(string typeName, bool skipSystemAssemblies, bool throwIfNotFound)
readonly WidgetsList Children
static object Get(Type type, string name)
virtual void ReturnDrawItemsToCache()
对 DrawItem 进行复用,并存储到缓存列表内。
virtual DrawItem GetDrawItemFromCache()
从缓存中获取一个 DrawItem 实例,用于减少实例创建次数以缓解 GC 压力。
readonly PrimitivesRenderer3D PrimitivesRenderer3D
virtual void CollateDrawItems(Widget widget, Rectangle scissorRectangle)
根据 Widget 的层级关系 以及 Widget 的各项绘制有关的属性生成 DrawItem。
readonly PrimitivesRenderer2D PrimitivesRenderer2D
virtual void RenderDrawItems()
virtual void AssignDrawItemsLayers()
指定 DrawItem 的 Layer(层级)。
static List< DrawItem > m_drawItemsCache
List< DrawItem > m_drawItems
readonly PrimitivesRenderer2D CursorPrimitivesRenderer2D
virtual void DrawWidgetsHierarchy(Widget rootWidget)
绘制 rootWidget 及其子 Widget。
绘制任务,有多种类型,绘制任务会按照 Layer 进行排序。
Widget Widget
绘制任务所属的 Widget
Rectangle? ScissorRectangle
绘制任务所绑定的 ScissorRectangle,可为空。
bool IsOverdraw
是否为 Overdraw 任务,绘制任务被定义为需要绘制 Widget 时,该值决定了 Widget.Draw 或 Widget.Overdraw 的调用 (当 IsOverdraw 为 true 时则...
int CompareTo(DrawItem other)
int Layer
绘制任务所在的层级,值越小,绘制越靠前,绘制靠前的绘制任务会被靠后的覆盖。
static void UpdateWidgetsHierarchy(Widget widget, ref bool isMouseCursorVisible)
virtual float MarginVerticalSum
virtual string Name
Vector2 ParentDesiredSize
float GlobalScale
bool m_isLayoutTransformIdentity
virtual void Arrange(Vector2 position, Vector2 parentActualSize)
Matrix m_globalTransform
bool IsUpdateEnabled
bool m_isRenderTransformIdentity
Matrix InvertedGlobalTransform
Widget RootWidget
bool IsVisibleGlobal
static Widget LoadWidget(object eventsTarget, XElement node, ContainerWidget parentWidget)
virtual Widget HitTestGlobal(Vector2 point, Func< Widget, bool > predicate=null)
virtual void MeasureOverride(Vector2 parentAvailableSize)
virtual bool IsVisible
Color m_colorTransform
virtual float MarginHorizontalSum
virtual BoundingRectangle TransformBoundsToGlobal(Vector2 size)
Matrix? m_invertedGlobalTransform
Vector2 m_parentDesiredSize
Vector2 m_actualSize
WidgetInput Input
Color GlobalColorTransform
static void DrawWidgetsHierarchy(Widget rootWidget)
ContainerWidget ParentWidget
virtual void ChangeParent(ContainerWidget parentWidget)
BoundingRectangle GlobalBounds
Vector2 DesiredSize
virtual bool HitTest(Vector2 point)
static bool TestOverlap(Widget w1, Widget w2)
virtual BoundingRectangle TransformBoundsToParent(Vector2 size)
object ExtraData
WidgetInput WidgetsHierarchyInput
virtual void ArrangeOverride()
virtual WidgetAlignment VerticalAlignment
Color ColorTransform
virtual Vector2 MarginHorizontalSumAndVerticalSum
Vector2 m_desiredSize
virtual Vector2 Margin
virtual void Update()
virtual WidgetAlignment HorizontalAlignment
Matrix RenderTransform
XElement Style
static bool DrawWidgetBounds
Matrix LayoutTransform
static Queue< DrawContext > m_drawContextsCache
virtual bool IsEnabled
static void LayoutWidgetsHierarchy(Widget rootWidget, Vector2 availableSize)
virtual Vector2 WidgetToScreen(Vector2 p)
virtual void Draw(DrawContext dc)
Color m_globalColorTransform
static void UpdateWidgetsHierarchy(Widget rootWidget)
static Type FindTypeFromXmlName(string name, string namespaceName)
bool IsDrawRequired
virtual bool IsHitTestVisible
Vector2 m_parentOffset
bool IsEnabledGlobal
float? m_globalScale
static bool IsNodeIncludedOnCurrentPlatform(XElement node)
bool IsOverdrawRequired
virtual void LoadProperties(object eventsTarget, XElement node)
Matrix m_layoutTransform
Vector2 ActualSize
virtual void LoadContents(object eventsTarget, XElement node)
virtual Vector2 ScreenToWidget(Vector2 p)
BoundingRectangle m_globalBounds
virtual Vector4 Margin4
virtual float MarginBottom
virtual float MarginRight
static int LayersLimit
Matrix m_renderTransform
Action< Vector2 > MeasureOverride1
virtual void UpdateCeases()
Matrix GlobalTransform
virtual float MarginTop
static Widget HitTestGlobal(Widget widget, Vector2 point, Func< Widget, bool > predicate)
virtual void LoadChildren(object eventsTarget, XElement node)
virtual void Measure(Vector2 parentAvailableSize)
virtual void Overdraw(DrawContext dc)
virtual bool IsChildWidgetOf(ContainerWidget containerWidget)
virtual float MarginLeft
virtual void Dispose()
WidgetInput m_widgetsHierarchyInput
virtual void Draw(Widget.DrawContext dc)
virtual void Update()
static WidgetInput EmptyInput
void Add(Widget widget)
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
static object GetAttributeValue(XElement node, string attributeName, Type type)
bool Intersection(BoundingRectangle r)
static Color White
static Matrix Invert(Matrix m)
static readonly Matrix Identity
bool Intersection(Rectangle r)
static readonly Vector2 Zero
static Vector2 Transform(Vector2 v, Matrix m)