Node.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. //
  2. // Node C# sugar
  3. //
  4. // Authors:
  5. // Miguel de Icaza ([email protected])
  6. //
  7. // Copyrigh 2015 Xamarin INc
  8. //
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Runtime.InteropServices;
  13. using System.Reflection;
  14. namespace Urho {
  15. internal partial class NodeHelper
  16. {
  17. [DllImport (Consts.NativeImport, CallingConvention=CallingConvention.Cdecl)]
  18. internal extern static IntPtr urho_node_get_components(IntPtr node, int code, int recursive, out int count);
  19. [DllImport (Consts.NativeImport, CallingConvention=CallingConvention.Cdecl)]
  20. internal extern static IntPtr Node_GetChildrenWithTag(IntPtr node, string tag, int recursive, out int count);
  21. }
  22. public partial class Node {
  23. static Node[] ZeroArray = new Node[0];
  24. public Node[] GetChildrenWithComponent<T> (bool recursive = false) where T: Component
  25. {
  26. Runtime.ValidateRefCounted(this);
  27. var stringhash = Runtime.LookupStringHash (typeof (T));
  28. int count;
  29. var ptr = NodeHelper.urho_node_get_components (handle, stringhash.Code, recursive ? 1 : 0, out count);
  30. if (ptr == IntPtr.Zero)
  31. return ZeroArray;
  32. var res = new Node[count];
  33. for (int i = 0; i < count; i++){
  34. var node = Marshal.ReadIntPtr(ptr, i * IntPtr.Size);
  35. res [i] = Runtime.LookupObject<Node> (node);
  36. }
  37. if (Component.IsDefinedInManagedCode<T>())
  38. //is not really efficient, but underlying Urho3D knows nothing about components defined in C#
  39. return res.Where(c => c.GetComponent<T>() != null).ToArray();
  40. return res;
  41. }
  42. public Node[] GetChildrenWithTag(string tag, bool recursive = false)
  43. {
  44. Runtime.ValidateRefCounted(this);
  45. int count;
  46. var ptr = NodeHelper.Node_GetChildrenWithTag(handle, tag, recursive ? 1 : 0, out count);
  47. if (ptr == IntPtr.Zero)
  48. return ZeroArray;
  49. var res = new Node[count];
  50. for (int i = 0; i < count; i++){
  51. var node = Marshal.ReadIntPtr(ptr, i * IntPtr.Size);
  52. res [i] = Runtime.LookupObject<Node> (node);
  53. }
  54. return res;
  55. }
  56. public T CreateComponent<T> (StringHash type, CreateMode mode = CreateMode.Replicated, uint id = 0) where T:Component
  57. {
  58. Runtime.ValidateRefCounted(this);
  59. var ptr = Node_CreateComponent (handle, type.Code, mode, id);
  60. return Runtime.LookupObject<T> (ptr);
  61. }
  62. public void RemoveComponent<T> ()
  63. {
  64. Runtime.ValidateRefCounted(this);
  65. var stringHash = Runtime.LookupStringHash (typeof (T));
  66. RemoveComponent (stringHash);
  67. }
  68. public T CreateComponent<T> (CreateMode mode = CreateMode.Replicated, uint id = 0) where T:Component
  69. {
  70. Runtime.ValidateRefCounted(this);
  71. var component = Activator.CreateInstance<T>();
  72. AddComponent(component, id, mode);
  73. return component;
  74. }
  75. /// <summary>
  76. /// Add a pre-created component.
  77. /// </summary>
  78. public void AddComponent (Component component, uint id = 0)
  79. {
  80. Runtime.ValidateRefCounted(this);
  81. AddComponent (component, id, CreateMode.Replicated);
  82. }
  83. /// <summary>
  84. /// Changes Parent for the node
  85. /// </summary>
  86. public void ChangeParent(Node newParent)
  87. {
  88. AddRef();
  89. Remove(); //without AddRef "Delete" will completly delete the node and the next operation will throw AccessViolationException
  90. newParent.AddChild(this);
  91. ReleaseRef();
  92. }
  93. public T GetComponent<T> (bool recursive = false) where T : Component
  94. {
  95. Runtime.ValidateRefCounted(this);
  96. var nativeTypeHash = typeof(T).GetRuntimeProperty("TypeStatic")?.GetValue(null);
  97. if (nativeTypeHash != null)
  98. return (T)GetComponent((StringHash)nativeTypeHash, recursive);
  99. //slow search (only for components defined by user):
  100. var component = (T)Components.FirstOrDefault(c => c is T);
  101. if (component == null && recursive)
  102. return GetChildrenWithComponent<T>(true).FirstOrDefault()?.GetComponent<T>(false);
  103. return component;
  104. }
  105. public T GetOrCreateComponent<T>(bool recursive = false) where T : Component
  106. {
  107. Runtime.ValidateRefCounted(this);
  108. var component = GetComponent<T>(recursive);
  109. if (component == null)
  110. return CreateComponent<T>();
  111. return component;
  112. }
  113. public bool LoadXml(string prefab)
  114. {
  115. var file = Application.Current.ResourceCache.GetXmlFile(prefab, true);
  116. var element = file.GetRoot("node");
  117. if (element == null || element.Null)
  118. throw new Exception("'node' root element was not found");
  119. return LoadXml(element, true);
  120. }
  121. }
  122. }