EditorViewDebugIcons.as 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. // Editor debug icons
  2. // to add new std debug icons just add IconType, IconsTypesMaterials and ComponentTypes items
  3. enum IconsTypes
  4. {
  5. ICON_POINT_LIGHT = 0,
  6. ICON_SPOT_LIGHT,
  7. ICON_DIRECTIONAL_LIGHT,
  8. ICON_CAMERA,
  9. ICON_SOUND_SOURCE,
  10. ICON_SOUND_SOURCE_3D,
  11. ICON_SOUND_LISTENERS,
  12. ICON_ZONE,
  13. ICON_SPLINE_PATH,
  14. ICON_TRIGGER,
  15. ICON_CUSTOM_GEOMETRY,
  16. ICON_PARTICLE_EMITTER,
  17. ICON_COUNT
  18. }
  19. enum IconsColorType
  20. {
  21. ICON_COLOR_DEFAULT = 0,
  22. ICON_COLOR_SPLINE_PATH_BEGIN,
  23. ICON_COLOR_SPLINE_PATH_END
  24. }
  25. Array<Color> debugIconsColors = { Color(1,1,1) , Color(1,1,0), Color(0,1,0) };
  26. Array<String> IconsTypesMaterials = {"DebugIconPointLight.xml",
  27. "DebugIconSpotLight.xml",
  28. "DebugIconLight.xml",
  29. "DebugIconCamera.xml",
  30. "DebugIconSoundSource.xml",
  31. "DebugIconSoundSource.xml",
  32. "DebugIconSoundListener.xml",
  33. "DebugIconZone.xml",
  34. "DebugIconSplinePathPoint.xml",
  35. "DebugIconCollisionTrigger.xml",
  36. "DebugIconCustomGeometry.xml",
  37. "DebugIconParticleEmitter.xml"};
  38. Array<String> ComponentTypes = {"Light",
  39. "Light",
  40. "Light",
  41. "Camera",
  42. "SoundSource",
  43. "SoundSource3D",
  44. "SoundListener",
  45. "Zone",
  46. "SplinePath",
  47. "RigidBody",
  48. "CustomGeometry",
  49. "ParticleEmitter"};
  50. Array<BillboardSet@> debugIconsSet(ICON_COUNT);
  51. Node@ debugIconsNode = null;
  52. int stepDebugIconsUpdate = 100; //ms
  53. uint timeToNextDebugIconsUpdate = 0;
  54. int stepDebugIconsUpdateSplinePath = 1000; //ms
  55. uint timeToNextDebugIconsUpdateSplinePath = 0;
  56. const int splinePathResolution = 16;
  57. const float splineStep = 1.0f / splinePathResolution;
  58. bool debugIconsShow = true;
  59. Vector2 debugIconsSize = Vector2(64, 64);
  60. Vector2 debugIconsSizeSmall = debugIconsSize / 1.5;
  61. VariantMap debugIconsPlacement;
  62. const int debugIconsPlacementIndent = 1.0;
  63. const float debugIconsOrthoDistance = 15.0;
  64. const float debugIconAlphaThreshold = 0.1;
  65. const float maxDistance = 50.0;
  66. void CreateDebugIcons(Node@ tempNode)
  67. {
  68. if (editorScene is null) return;
  69. debugIconsSet.Resize(ICON_COUNT);
  70. for (int i = 0; i < ICON_COUNT; ++i)
  71. {
  72. debugIconsSet[i] = tempNode.CreateComponent("BillboardSet");
  73. debugIconsSet[i].material = cache.GetResource("Material", "Materials/Editor/" + IconsTypesMaterials[i]);
  74. debugIconsSet[i].sorted = true;
  75. debugIconsSet[i].temporary = true;
  76. debugIconsSet[i].fixedScreenSize = true;
  77. debugIconsSet[i].viewMask = 0x80000000;
  78. }
  79. }
  80. void UpdateViewDebugIcons()
  81. {
  82. if (editorScene is null || timeToNextDebugIconsUpdate > time.systemTime) return;
  83. debugIconsNode = editorScene.GetChild("DebugIconsContainer", true);
  84. if (debugIconsNode is null)
  85. {
  86. debugIconsNode = editorScene.CreateChild("DebugIconsContainer", LOCAL);
  87. debugIconsNode.temporary = true;
  88. }
  89. // Checkout if debugIconsNode do not have any BBS component, add all at once
  90. BillboardSet@ isBSExist = debugIconsNode.GetComponent("BillboardSet");
  91. if (isBSExist is null)
  92. CreateDebugIcons(debugIconsNode);
  93. if (debugIconsSet[ICON_POINT_LIGHT] !is null)
  94. {
  95. for (int i = 0; i < ICON_COUNT; ++i)
  96. debugIconsSet[i].enabled = debugIconsShow;
  97. }
  98. if (debugIconsShow == false) return;
  99. Vector3 camPos = activeViewport.cameraNode.worldPosition;
  100. bool isOrthographic = activeViewport.camera.orthographic;
  101. debugIconsPlacement.Clear();
  102. for (int iconType = 0; iconType < ICON_COUNT; ++iconType)
  103. {
  104. if (debugIconsSet[iconType] !is null)
  105. {
  106. // SplinePath update resolution
  107. if (iconType == ICON_SPLINE_PATH && timeToNextDebugIconsUpdateSplinePath > time.systemTime)
  108. continue;
  109. Array<Node@> nodes = editorScene.GetChildrenWithComponent(ComponentTypes[iconType], true);
  110. // Clear old data
  111. if (iconType == ICON_SPLINE_PATH)
  112. ClearCommit(ICON_SPLINE_PATH, ICON_SPLINE_PATH + 1, nodes.length * splinePathResolution);
  113. else if (iconType == ICON_POINT_LIGHT || iconType == ICON_SPOT_LIGHT || iconType == ICON_DIRECTIONAL_LIGHT)
  114. ClearCommit(ICON_POINT_LIGHT, ICON_DIRECTIONAL_LIGHT + 1, nodes.length);
  115. else if (iconType == ICON_SOUND_SOURCE || iconType == ICON_SOUND_SOURCE_3D)
  116. ClearCommit(ICON_SOUND_SOURCE, ICON_SOUND_SOURCE_3D + 1, nodes.length);
  117. else
  118. ClearCommit(iconType, iconType + 1, nodes.length);
  119. if (nodes.length > 0)
  120. {
  121. // Fill with new data
  122. for (uint i = 0; i < nodes.length; ++i)
  123. {
  124. Component@ component = nodes[i].GetComponent(ComponentTypes[iconType]);
  125. if (component is null) continue;
  126. Color finalIconColor = debugIconsColors[ICON_COLOR_DEFAULT];
  127. float distance = (camPos - nodes[i].worldPosition).length;
  128. if (isOrthographic)
  129. distance = debugIconsOrthoDistance;
  130. int iconsOffset = debugIconsPlacement[StringHash(nodes[i].id)].GetInt();
  131. float iconsYPos = 0;
  132. if (iconType == ICON_SPLINE_PATH)
  133. {
  134. SplinePath@ sp = cast<SplinePath>(component);
  135. if (sp !is null)
  136. {
  137. if (sp.length > 0.01f)
  138. {
  139. for (int step = 0; step < splinePathResolution; step++)
  140. {
  141. int index = (i * splinePathResolution) + step;
  142. Vector3 splinePoint = sp.GetPoint(splineStep * step);
  143. Billboard@ bb = debugIconsSet[ICON_SPLINE_PATH].billboards[index];
  144. float stepDistance = (camPos - splinePoint).length;
  145. if (isOrthographic)
  146. stepDistance = debugIconsOrthoDistance;
  147. if (step == 0) // SplinePath start
  148. {
  149. bb.color = debugIconsColors[ICON_COLOR_SPLINE_PATH_BEGIN];
  150. bb.size = debugIconsSize;
  151. bb.position = splinePoint;
  152. }
  153. else if ((step+1) >= (splinePathResolution - splineStep)) // SplinePath end
  154. {
  155. bb.color = debugIconsColors[ICON_COLOR_SPLINE_PATH_END];
  156. bb.size = debugIconsSize;
  157. bb.position = splinePoint;
  158. }
  159. else // SplinePath middle points
  160. {
  161. bb.color = finalIconColor;
  162. bb.size = debugIconsSizeSmall;
  163. bb.position = splinePoint;
  164. }
  165. bb.enabled = sp.enabled;
  166. // Blend Icon relatively by distance to it
  167. bb.color = Color(bb.color.r, bb.color.g, bb.color.b, 1.2f - 1.0f / (maxDistance / stepDistance));
  168. if (bb.color.a < debugIconAlphaThreshold)
  169. bb.enabled = false;
  170. }
  171. }
  172. }
  173. }
  174. else
  175. {
  176. Billboard@ bb = debugIconsSet[iconType].billboards[i];
  177. bb.size = debugIconsSize;
  178. if (iconType == ICON_TRIGGER)
  179. {
  180. RigidBody@ rigidbody = cast<RigidBody>(component);
  181. if (rigidbody !is null)
  182. {
  183. if (rigidbody.trigger == false)
  184. continue;
  185. }
  186. }
  187. else if (iconType == ICON_POINT_LIGHT || iconType == ICON_SPOT_LIGHT || iconType == ICON_DIRECTIONAL_LIGHT)
  188. {
  189. Light@ light = cast<Light>(component);
  190. if (light !is null)
  191. {
  192. if (light.lightType == LIGHT_POINT)
  193. bb = debugIconsSet[ICON_POINT_LIGHT].billboards[i];
  194. else if (light.lightType == LIGHT_DIRECTIONAL)
  195. bb = debugIconsSet[ICON_DIRECTIONAL_LIGHT].billboards[i];
  196. else if (light.lightType == LIGHT_SPOT)
  197. bb = debugIconsSet[ICON_SPOT_LIGHT].billboards[i];
  198. finalIconColor = light.effectiveColor;
  199. }
  200. }
  201. bb.position = nodes[i].worldPosition;
  202. // Blend Icon relatively by distance to it
  203. bb.color = Color(finalIconColor.r, finalIconColor.g, finalIconColor.b, 1.2f - 1.0f / (maxDistance / distance));
  204. bb.enabled = component.enabled;
  205. // Discard billboard if it almost transparent
  206. if (bb.color.a < debugIconAlphaThreshold)
  207. bb.enabled = false;
  208. IncrementIconPlacement(bb.enabled, nodes[i], 1);
  209. }
  210. }
  211. Commit(iconType, iconType+1);
  212. // SplinePath update resolution
  213. if (iconType == ICON_SPLINE_PATH)
  214. timeToNextDebugIconsUpdateSplinePath = time.systemTime + stepDebugIconsUpdateSplinePath;
  215. }
  216. }
  217. }
  218. timeToNextDebugIconsUpdate = time.systemTime + stepDebugIconsUpdate;
  219. }
  220. void ClearCommit(int begin, int end, int newLength)
  221. {
  222. for (int i = begin; i < end; ++i)
  223. {
  224. BillboardSet@ iconSet = debugIconsSet[i];
  225. iconSet.numBillboards = newLength;
  226. for (int j = 0; j < newLength; ++j)
  227. {
  228. Billboard@ bb = iconSet.billboards[j];
  229. bb.enabled = false;
  230. }
  231. iconSet.Commit();
  232. }
  233. }
  234. void Commit(int begin, int end)
  235. {
  236. for (int i = begin; i < end; ++i)
  237. {
  238. debugIconsSet[i].Commit();
  239. }
  240. }
  241. void IncrementIconPlacement(bool componentEnabled, Node@ node, int offset)
  242. {
  243. if (componentEnabled == true)
  244. {
  245. int oldPlacement = debugIconsPlacement[StringHash(node.id)].GetInt();
  246. debugIconsPlacement[StringHash(node.id)] = Variant(oldPlacement + offset);
  247. }
  248. }