PageRenderTime 71ms CodeModel.GetById 41ms RepoModel.GetById 1ms app.codeStats 0ms

/Script/AtomicNET/AtomicNET/Scene/Scene.cs

https://gitlab.com/Teo-Mirror/AtomicGameEngine
C# | 397 lines | 264 code | 109 blank | 24 comment | 49 complexity | 966a3065a97b138b6c08c8730162a656 MD5 | raw file
  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using System.Runtime.InteropServices;
  5. using static System.Reflection.IntrospectionExtensions;
  6. namespace AtomicEngine
  7. {
  8. public partial class Scene : Node
  9. {
  10. /// <summary>
  11. /// Explicitly destroys scene and disposes of children and components
  12. /// </summary>
  13. public override void Destroy()
  14. {
  15. if (Destroyed)
  16. return;
  17. cscomponents.Clear();
  18. cscomponentStart.Clear();
  19. base.Destroy();
  20. }
  21. internal override void PostNativeUpdate()
  22. {
  23. SubscribeToEvent<NodeAddedEvent>(this, e =>
  24. {
  25. //Log.Info($"Node ADDED: {e.Node.Name}");
  26. // The NodeAdded event is generated when adding a node as a child
  27. e.Node.GetComponents<CSComponent>(csComponentVector);
  28. for (uint i = 0; i < csComponentVector.Size; i++)
  29. {
  30. AddCSComponent(csComponentVector[i]);
  31. }
  32. csComponentVector.Clear();
  33. });
  34. SubscribeToEvent<NodeRemovedEvent>(this, e =>
  35. {
  36. //Log.Info($"Node REMOVED: {e.Node.Name}");
  37. // The NodeRemoved event is generated when explicitly removing nodes from a scene
  38. // For general cleanup, it will not be generated
  39. e.Node.GetComponents<CSComponent>(csComponentVector);
  40. for (uint i = 0; i < csComponentVector.Size; i++)
  41. {
  42. HandleComponentRemoved(csComponentVector[i]);
  43. }
  44. csComponentVector.Clear();
  45. });
  46. SubscribeToEvent<CSComponentLoadEvent>(this, HandleCSComponentLoad);
  47. SubscribeToEvent<ComponentAddedEvent>(this, e =>
  48. {
  49. Component component = null;
  50. try
  51. {
  52. // will throw if component isn't a known native
  53. component = e.Component;
  54. }
  55. catch
  56. {
  57. return;
  58. }
  59. HandleComponentAdded(component);
  60. });
  61. SubscribeToEvent<ComponentRemovedEvent>(this, e =>
  62. {
  63. Component component = null;
  64. try
  65. {
  66. // will throw if component isn't a known native
  67. component = e.Component;
  68. }
  69. catch
  70. {
  71. return;
  72. }
  73. HandleComponentRemoved(component);
  74. });
  75. // Update variable timestep logic
  76. SubscribeToEvent<SceneUpdateEvent>(this, HandleSceneUpdate);
  77. // Update scene subsystems. If a physics world is present, it will be updated, triggering fixed timestep logic updates
  78. SubscribeToEvent<SceneSubsystemUpdateEvent>(this, HandleSceneSubsystemUpdate);
  79. // Update transform smoothing
  80. SubscribeToEvent<UpdateSmoothingEvent>(this, HandleUpdateSmoothing);
  81. // Post-update variable timestep logic
  82. SubscribeToEvent<ScenePostUpdateEvent>(this, HandleScenePostUpdate);
  83. }
  84. // Update variable timestep logic
  85. void HandleSceneUpdate(SceneUpdateEvent e)
  86. {
  87. // Handle Start
  88. if (cscomponentStart.Count > 0)
  89. {
  90. var started = new List<CSComponent>();
  91. foreach (var csc in cscomponentStart.ToList())
  92. {
  93. if (!csc.IsEnabled())
  94. {
  95. continue;
  96. }
  97. // mark as started whether or not a Start method exists
  98. csc.started = true;
  99. started.Add(csc);
  100. CSComponentInfo info;
  101. if (CSComponentCore.csinfoLookup.TryGetValue(csc.GetType(), out info))
  102. {
  103. if (info.StartMethod != null)
  104. {
  105. info.StartMethod.Invoke(csc, null);
  106. }
  107. }
  108. }
  109. foreach (var csc in started)
  110. {
  111. cscomponentStart.Remove(csc);
  112. }
  113. }
  114. // Handle Scene Update
  115. Object[] args = new Object[1] { e.TimeStep };
  116. foreach (var item in cscomponents.ToList())
  117. {
  118. var info = item.Key;
  119. var UpdateMethod = info.UpdateMethod;
  120. if (UpdateMethod == null)
  121. continue;
  122. foreach (var csc in item.Value.ToList())
  123. {
  124. if (!csc.Started || !csc.IsEnabled())
  125. continue;
  126. UpdateMethod.Invoke(csc, args);
  127. }
  128. }
  129. }
  130. // Update scene subsystems. If a physics world is present, it will be updated, triggering fixed timestep logic updates
  131. void HandleSceneSubsystemUpdate(SceneSubsystemUpdateEvent e)
  132. {
  133. }
  134. // Update transform smoothing
  135. void HandleUpdateSmoothing(UpdateSmoothingEvent e)
  136. {
  137. }
  138. // Post-update variable timestep logic
  139. void HandleScenePostUpdate(ScenePostUpdateEvent e)
  140. {
  141. Object[] args = new Object[1] { e.TimeStep };
  142. foreach (var item in cscomponents)
  143. {
  144. var info = item.Key;
  145. var PostUpdateMethod = info.PostUpdateMethod;
  146. if (PostUpdateMethod == null)
  147. continue;
  148. foreach (var csc in item.Value)
  149. {
  150. if (!csc.Started || !csc.IsEnabled())
  151. continue;
  152. PostUpdateMethod.Invoke(csc, args);
  153. }
  154. }
  155. }
  156. void HandlePhysicsPreStep(PhysicsPreStepEvent e)
  157. {
  158. Object[] args = new Object[1] { e.TimeStep };
  159. foreach (var item in cscomponents)
  160. {
  161. var info = item.Key;
  162. var PhysicsPreStepMethod = info.PhysicsPreStepMethod;
  163. if (PhysicsPreStepMethod == null)
  164. continue;
  165. foreach (var csc in item.Value)
  166. {
  167. if (!csc.Started || !csc.IsEnabled())
  168. continue;
  169. PhysicsPreStepMethod.Invoke(csc, args);
  170. }
  171. }
  172. }
  173. void HandlePhysicsPostStep(PhysicsPostStepEvent e)
  174. {
  175. Object[] args = new Object[1] { e.TimeStep };
  176. foreach (var item in cscomponents)
  177. {
  178. var info = item.Key;
  179. var PhysicsPostStepMethod = info.PhysicsPostStepMethod;
  180. if (PhysicsPostStepMethod == null)
  181. continue;
  182. foreach (var csc in item.Value)
  183. {
  184. if (!csc.Started || !csc.IsEnabled())
  185. continue;
  186. PhysicsPostStepMethod.Invoke(csc, args);
  187. }
  188. }
  189. }
  190. void HandleCSComponentLoad(CSComponentLoadEvent e)
  191. {
  192. var scriptMap = e.scriptMap;
  193. // Get the NativeInstance as an IntPtr, otherwise we would be wrapping as a CSComponent
  194. IntPtr csnative = scriptMap.GetVoidPtr("NativeInstance");
  195. IntPtr fieldValues = IntPtr.Zero;
  196. if (scriptMap.Contains("FieldValues"))
  197. fieldValues = scriptMap.GetVoidPtr("FieldValues");
  198. CSComponentInfo csinfo;
  199. if (!CSComponentCore.componentCache.TryGetValue(e.ClassName, out csinfo))
  200. {
  201. Log.Error("Scene.HandleCSComponentLoad - unable to find CSComponent in cache for classname: " + e.ClassName );
  202. return;
  203. }
  204. var component = CSComponent.LoadCreateInstance(csinfo.Type, csnative);
  205. if (component == null)
  206. {
  207. Log.Error("Scene.HandleCSComponentLoad - unable to create CSComponent for classname: " + e.ClassName);
  208. return;
  209. }
  210. if (fieldValues != IntPtr.Zero)
  211. csinfo.ApplyFieldValues(component, fieldValues);
  212. AddCSComponent(component);
  213. }
  214. void AddCSComponent(CSComponent csc)
  215. {
  216. CSComponentInfo info;
  217. if (!CSComponentCore.csinfoLookup.TryGetValue(csc.GetType(), out info))
  218. {
  219. Log.Error("Scene.HandleComponentAdded - unable to get CSComponentInfo");
  220. return;
  221. }
  222. List<CSComponent> cslist;
  223. if (!cscomponents.TryGetValue(info, out cslist))
  224. {
  225. cslist = cscomponents[info] = new List<CSComponent>();
  226. }
  227. if (cslist.Contains(csc))
  228. {
  229. throw new InvalidOperationException("Scene.HandleComponentAdded - CSComponent already added to component list");
  230. }
  231. cslist.Add(csc);
  232. if (!csc.started)
  233. {
  234. if (cscomponentStart.Contains(csc))
  235. {
  236. throw new InvalidOperationException("Scene.HandleComponentAdded CSComponent already added to start list");
  237. }
  238. cscomponentStart.Add(csc);
  239. }
  240. }
  241. void HandleComponentAdded(Component component)
  242. {
  243. // Check null (CSComponent) or other abstract component
  244. if (component == null)
  245. {
  246. return;
  247. }
  248. if (component.GetType() == typeof(PhysicsWorld) || component.GetType() == typeof(PhysicsWorld2D))
  249. {
  250. SubscribeToEvent<PhysicsPreStepEvent>(component, HandlePhysicsPreStep);
  251. SubscribeToEvent<PhysicsPostStepEvent>(component, HandlePhysicsPostStep);
  252. }
  253. // CSComponent
  254. if (component.GetType().GetTypeInfo().IsSubclassOf(typeof(CSComponent)))
  255. {
  256. var csc = (CSComponent)component;
  257. AddCSComponent(csc);
  258. }
  259. }
  260. void HandleComponentRemoved(Component component)
  261. {
  262. if (component.GetType() == typeof(PhysicsWorld) || component.GetType() == typeof(PhysicsWorld2D))
  263. {
  264. UnsubscribeFromEvent<PhysicsPreStepEvent>();
  265. UnsubscribeFromEvent<PhysicsPostStepEvent>();
  266. }
  267. if (component.GetType().GetTypeInfo().IsSubclassOf(typeof(CSComponent)))
  268. {
  269. var csc = (CSComponent)component;
  270. CSComponentInfo info;
  271. if (!CSComponentCore.csinfoLookup.TryGetValue(csc.GetType(), out info))
  272. {
  273. return;
  274. }
  275. cscomponentStart.Remove(csc);
  276. List<CSComponent> cslist;
  277. if (!cscomponents.TryGetValue(info, out cslist))
  278. {
  279. return;
  280. }
  281. cslist.Remove(csc);
  282. }
  283. }
  284. Vector<CSComponent> csComponentVector = new Vector<CSComponent>();
  285. Dictionary<CSComponentInfo, List<CSComponent>> cscomponents = new Dictionary<CSComponentInfo, List<CSComponent>>();
  286. List<CSComponent> cscomponentStart = new List<CSComponent>();
  287. }
  288. }