EditorParticleEffect.as 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733
  1. // Urho3D material editor
  2. Window@ particleEffectWindow;
  3. ParticleEffect@ editParticleEffect;
  4. XMLFile@ oldParticleEffectState;
  5. bool inParticleEffectRefresh = false;
  6. View3D@ particleEffectPreview;
  7. Camera@ particlePreviewCamera;
  8. Scene@ particlePreviewScene;
  9. Node@ particleEffectPreviewNode;
  10. Node@ particleEffectPreviewGizmoNode;
  11. Node@ particleEffectPreviewGridNode;
  12. CustomGeometry@ particleEffectPreviewGrid;
  13. Node@ particlePreviewCameraNode;
  14. Node@ particlePreviewLightNode;
  15. Light@ particlePreviewLight;
  16. ParticleEmitter@ particleEffectEmitter;
  17. float particleResetTimer;
  18. bool showParticlePreviewAxes = true;
  19. Vector3 particleViewCamDir;
  20. Vector3 particleViewCamRot;
  21. float particleViewCamDist;
  22. float gizmoOffset = 0.1f;
  23. float gizmoOffsetX;
  24. float gizmoOffsetY;
  25. void CreateParticleEffectEditor()
  26. {
  27. if (particleEffectWindow !is null)
  28. return;
  29. particleEffectWindow = LoadEditorUI("UI/EditorParticleEffectWindow.xml");
  30. ui.root.AddChild(particleEffectWindow);
  31. particleEffectWindow.opacity = uiMaxOpacity;
  32. InitParticleEffectPreview();
  33. InitParticleEffectBasicAttributes();
  34. RefreshParticleEffectEditor();
  35. int width = Min(ui.root.width - 60, 800);
  36. int height = Min(ui.root.height - 60, 600);
  37. particleEffectWindow.SetSize(width, height);
  38. CenterDialog(particleEffectWindow);
  39. HideParticleEffectEditor();
  40. SubscribeToEvent(particleEffectWindow.GetChild("NewButton", true), "Released", "NewParticleEffect");
  41. SubscribeToEvent(particleEffectWindow.GetChild("RevertButton", true), "Released", "RevertParticleEffect");
  42. SubscribeToEvent(particleEffectWindow.GetChild("SaveButton", true), "Released", "SaveParticleEffect");
  43. SubscribeToEvent(particleEffectWindow.GetChild("SaveAsButton", true), "Released", "SaveParticleEffectAs");
  44. SubscribeToEvent(particleEffectWindow.GetChild("CloseButton", true), "Released", "HideParticleEffectEditor");
  45. SubscribeToEvent(particleEffectWindow.GetChild("NewColorFrame", true), "Released", "EditParticleEffectColorFrameNew");
  46. SubscribeToEvent(particleEffectWindow.GetChild("RemoveColorFrame", true), "Released", "EditParticleEffectColorFrameRemove");
  47. SubscribeToEvent(particleEffectWindow.GetChild("ColorFrameSort", true), "Released", "EditParticleEffectColorFrameSort");
  48. SubscribeToEvent(particleEffectWindow.GetChild("NewTextureFrame", true), "Released", "EditParticleEffectTextureFrameNew");
  49. SubscribeToEvent(particleEffectWindow.GetChild("RemoveTextureFrame", true), "Released", "EditParticleEffectTextureFrameRemove");
  50. SubscribeToEvent(particleEffectWindow.GetChild("TextureFrameSort", true), "Released", "EditParticleEffectTextureFrameSort");
  51. SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceX", true), "TextChanged", "EditParticleEffectConstantForce");
  52. SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceY", true), "TextChanged", "EditParticleEffectConstantForce");
  53. SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceZ", true), "TextChanged", "EditParticleEffectConstantForce");
  54. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinX", true), "TextChanged", "EditParticleEffectDirection");
  55. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinY", true), "TextChanged", "EditParticleEffectDirection");
  56. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinZ", true), "TextChanged", "EditParticleEffectDirection");
  57. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxX", true), "TextChanged", "EditParticleEffectDirection");
  58. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxY", true), "TextChanged", "EditParticleEffectDirection");
  59. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxZ", true), "TextChanged", "EditParticleEffectDirection");
  60. SubscribeToEvent(particleEffectWindow.GetChild("DampingForce", true), "TextChanged", "EditParticleEffectDampingForce");
  61. SubscribeToEvent(particleEffectWindow.GetChild("ActiveTime", true), "TextChanged", "EditParticleEffectActiveTime");
  62. SubscribeToEvent(particleEffectWindow.GetChild("InactiveTime", true), "TextChanged", "EditParticleEffectInactiveTime");
  63. SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinX", true), "TextChanged", "EditParticleEffectParticleSize");
  64. SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinY", true), "TextChanged", "EditParticleEffectParticleSize");
  65. SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxX", true), "TextChanged", "EditParticleEffectParticleSize");
  66. SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxY", true), "TextChanged", "EditParticleEffectParticleSize");
  67. SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMin", true), "TextChanged", "EditParticleEffectTimeToLive");
  68. SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMax", true), "TextChanged", "EditParticleEffectTimeToLive");
  69. SubscribeToEvent(particleEffectWindow.GetChild("VelocityMin", true), "TextChanged", "EditParticleEffectVelocity");
  70. SubscribeToEvent(particleEffectWindow.GetChild("VelocityMax", true), "TextChanged", "EditParticleEffectVelocity");
  71. SubscribeToEvent(particleEffectWindow.GetChild("RotationMin", true), "TextChanged", "EditParticleEffectRotation");
  72. SubscribeToEvent(particleEffectWindow.GetChild("RotationMax", true), "TextChanged", "EditParticleEffectRotation");
  73. SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMin", true), "TextChanged", "EditParticleEffectRotationSpeed");
  74. SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMax", true), "TextChanged", "EditParticleEffectRotationSpeed");
  75. SubscribeToEvent(particleEffectWindow.GetChild("SizeAdd", true), "TextChanged", "EditParticleEffectSizeAdd");
  76. SubscribeToEvent(particleEffectWindow.GetChild("SizeMultiply", true), "TextChanged", "EditParticleEffectSizeMultiply");
  77. SubscribeToEvent(particleEffectWindow.GetChild("AnimationLodBias", true), "TextChanged", "EditParticleEffectAnimationLodBias");
  78. SubscribeToEvent(particleEffectWindow.GetChild("NumParticles", true), "TextChanged", "EditParticleEffectNumParticles");
  79. SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeX", true), "TextChanged", "EditParticleEffectEmitterSize");
  80. SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeY", true), "TextChanged", "EditParticleEffectEmitterSize");
  81. SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeZ", true), "TextChanged", "EditParticleEffectEmitterSize");
  82. SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMin", true), "TextChanged", "EditParticleEffectEmissionRate");
  83. SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMax", true), "TextChanged", "EditParticleEffectEmissionRate");
  84. SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceX", true), "TextFinished", "EditParticleEffectConstantForce");
  85. SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceY", true), "TextFinished", "EditParticleEffectConstantForce");
  86. SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceZ", true), "TextFinished", "EditParticleEffectConstantForce");
  87. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinX", true), "TextFinished", "EditParticleEffectDirection");
  88. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinY", true), "TextFinished", "EditParticleEffectDirection");
  89. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinZ", true), "TextFinished", "EditParticleEffectDirection");
  90. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxX", true), "TextFinished", "EditParticleEffectDirection");
  91. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxY", true), "TextFinished", "EditParticleEffectDirection");
  92. SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxZ", true), "TextFinished", "EditParticleEffectDirection");
  93. SubscribeToEvent(particleEffectWindow.GetChild("DampingForce", true), "TextFinished", "EditParticleEffectDampingForce");
  94. SubscribeToEvent(particleEffectWindow.GetChild("ActiveTime", true), "TextFinished", "EditParticleEffectActiveTime");
  95. SubscribeToEvent(particleEffectWindow.GetChild("InactiveTime", true), "TextFinished", "EditParticleEffectInactiveTime");
  96. SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinX", true), "TextFinished", "EditParticleEffectParticleSize");
  97. SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinY", true), "TextFinished", "EditParticleEffectParticleSize");
  98. SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxX", true), "TextFinished", "EditParticleEffectParticleSize");
  99. SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxY", true), "TextFinished", "EditParticleEffectParticleSize");
  100. SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMin", true), "TextFinished", "EditParticleEffectTimeToLive");
  101. SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMax", true), "TextFinished", "EditParticleEffectTimeToLive");
  102. SubscribeToEvent(particleEffectWindow.GetChild("VelocityMin", true), "TextFinished", "EditParticleEffectVelocity");
  103. SubscribeToEvent(particleEffectWindow.GetChild("VelocityMax", true), "TextFinished", "EditParticleEffectVelocity");
  104. SubscribeToEvent(particleEffectWindow.GetChild("RotationMin", true), "TextFinished", "EditParticleEffectRotation");
  105. SubscribeToEvent(particleEffectWindow.GetChild("RotationMax", true), "TextFinished", "EditParticleEffectRotation");
  106. SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMin", true), "TextFinished", "EditParticleEffectRotationSpeed");
  107. SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMax", true), "TextFinished", "EditParticleEffectRotationSpeed");
  108. SubscribeToEvent(particleEffectWindow.GetChild("SizeAdd", true), "TextFinished", "EditParticleEffectSizeAdd");
  109. SubscribeToEvent(particleEffectWindow.GetChild("SizeMultiply", true), "TextFinished", "EditParticleEffectSizeMultiply");
  110. SubscribeToEvent(particleEffectWindow.GetChild("AnimationLodBias", true), "TextFinished", "EditParticleEffectAnimationLodBias");
  111. SubscribeToEvent(particleEffectWindow.GetChild("NumParticles", true), "TextFinished", "EditParticleEffectNumParticles");
  112. SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeX", true), "TextFinished", "EditParticleEffectEmitterSize");
  113. SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeY", true), "TextFinished", "EditParticleEffectEmitterSize");
  114. SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeZ", true), "TextFinished", "EditParticleEffectEmitterSize");
  115. SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMin", true), "TextFinished", "EditParticleEffectEmissionRate");
  116. SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMax", true), "TextFinished", "EditParticleEffectEmissionRate");
  117. SubscribeToEvent(particleEffectWindow.GetChild("EmitterShape", true), "ItemSelected", "EditParticleEffectEmitterShape");
  118. SubscribeToEvent(particleEffectWindow.GetChild("Scaled", true), "Toggled", "EditParticleEffectScaled");
  119. SubscribeToEvent(particleEffectWindow.GetChild("Sorted", true), "Toggled", "EditParticleEffectSorted");
  120. SubscribeToEvent(particleEffectWindow.GetChild("Relative", true), "Toggled", "EditParticleEffectRelative");
  121. SubscribeToEvent(particleEffectWindow.GetChild("FaceCameraMode", true), "ItemSelected", "EditParticleEffectFaceCameraMode");
  122. SubscribeToEvent(particleEffectWindow.GetChild("ResetViewport", true), "Released", "ParticleEffectResetViewport");
  123. SubscribeToEvent(particleEffectWindow.GetChild("ShowGrid", true), "Toggled", "ParticleEffectShowGrid");
  124. }
  125. void SetGizmoPosition()
  126. {
  127. Vector3 screenPos = Vector3(gizmoOffsetX, gizmoOffsetY, 25.0);
  128. Vector3 newPos = particlePreviewCamera.ScreenToWorldPoint(screenPos);
  129. particleEffectPreviewGizmoNode.position = newPos;
  130. }
  131. void ResetCameraTransformation()
  132. {
  133. particlePreviewCameraNode.position = Vector3(0, 0, -5);
  134. particlePreviewCameraNode.LookAt(Vector3(0, 0, 0));
  135. particleViewCamDir = -particlePreviewCameraNode.position;
  136. // Manually set initial rotation because eulerAngle always return 0 on first frame
  137. particleViewCamRot = Vector3(0.0, 180.0, 0.0);
  138. particleViewCamDist = particleViewCamDir.length;
  139. particleViewCamDir.Normalize();
  140. }
  141. void ParticleEffectResetViewport(StringHash eventType, VariantMap& eventData)
  142. {
  143. ResetCameraTransformation();
  144. SetGizmoPosition();
  145. particleEffectPreview.QueueUpdate();
  146. }
  147. void ParticleEffectShowGrid(StringHash eventType, VariantMap& eventData)
  148. {
  149. CheckBox@ element = eventData["Element"].GetPtr();
  150. showParticlePreviewAxes = element.checked;
  151. particleEffectPreviewGridNode.enabled = showParticlePreviewAxes;
  152. particleEffectPreview.QueueUpdate();
  153. }
  154. void EditParticleEffectColorFrameNew(StringHash eventType, VariantMap& eventData)
  155. {
  156. if (inParticleEffectRefresh)
  157. return;
  158. if (editParticleEffect is null)
  159. return;
  160. BeginParticleEffectEdit();
  161. uint num = editParticleEffect.numColorFrames;
  162. editParticleEffect.numColorFrames = num + 1;
  163. RefreshParticleEffectColorFrames();
  164. EndParticleEffectEdit();
  165. }
  166. void EditParticleEffectTextureFrameNew(StringHash eventType, VariantMap& eventData)
  167. {
  168. if (inParticleEffectRefresh)
  169. return;
  170. if (editParticleEffect is null)
  171. return;
  172. BeginParticleEffectEdit();
  173. uint num = editParticleEffect.numTextureFrames;
  174. editParticleEffect.numTextureFrames = num + 1;
  175. RefreshParticleEffectTextureFrames();
  176. EndParticleEffectEdit();
  177. }
  178. void EditParticleEffectColorFrameRemove(StringHash eventType, VariantMap& eventData)
  179. {
  180. if (inParticleEffectRefresh)
  181. return;
  182. if (editParticleEffect is null)
  183. return;
  184. ListView@ lv = particleEffectWindow.GetChild("ColorFrameListView", true);
  185. if (lv !is null && lv.selection != M_MAX_UNSIGNED)
  186. {
  187. BeginParticleEffectEdit();
  188. editParticleEffect.RemoveColorFrame(lv.selection);
  189. RefreshParticleEffectColorFrames();
  190. EndParticleEffectEdit();
  191. }
  192. }
  193. void EditParticleEffectTextureFrameRemove(StringHash eventType, VariantMap& eventData)
  194. {
  195. if (inParticleEffectRefresh)
  196. return;
  197. if (editParticleEffect is null)
  198. return;
  199. ListView@ lv = particleEffectWindow.GetChild("TextureFrameListView", true);
  200. if (lv !is null && lv.selection != M_MAX_UNSIGNED)
  201. {
  202. BeginParticleEffectEdit();
  203. editParticleEffect.RemoveTextureFrame(lv.selection);
  204. RefreshParticleEffectTextureFrames();
  205. EndParticleEffectEdit();
  206. }
  207. }
  208. void EditParticleEffectColorFrameSort(StringHash eventType, VariantMap& eventData)
  209. {
  210. RefreshParticleEffectColorFrames();
  211. }
  212. void EditParticleEffectTextureFrameSort(StringHash eventType, VariantMap& eventData)
  213. {
  214. RefreshParticleEffectTextureFrames();
  215. }
  216. void InitParticleEffectBasicAttributes()
  217. {
  218. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceX", true)));
  219. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceY", true)));
  220. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceZ", true)));
  221. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinX", true)));
  222. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinY", true)));
  223. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinZ", true)));
  224. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxX", true)));
  225. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxY", true)));
  226. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxZ", true)));
  227. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("DampingForce", true)));
  228. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ActiveTime", true)));
  229. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("InactiveTime", true)));
  230. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMinX", true)));
  231. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMinY", true)));
  232. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMaxX", true)));
  233. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMaxY", true)));
  234. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("TimeToLiveMin", true)));
  235. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("TimeToLiveMax", true)));
  236. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("VelocityMin", true)));
  237. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("VelocityMax", true)));
  238. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("RotationMin", true)));
  239. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("RotationMax", true)));
  240. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("RotationSpeedMin", true)));
  241. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("RotationSpeedMax", true)));
  242. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("SizeAdd", true)));
  243. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("SizeMultiply", true)));
  244. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("AnimationLodBias", true)));
  245. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("NumParticles", true)));
  246. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeX", true)));
  247. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeY", true)));
  248. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeZ", true)));
  249. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmissionRateMin", true)));
  250. CreateDragSlider(cast<LineEdit>(particleEffectWindow.GetChild("EmissionRateMax", true)));
  251. }
  252. void EditParticleEffectConstantForce(StringHash eventType, VariantMap& eventData)
  253. {
  254. if (inParticleEffectRefresh)
  255. return;
  256. if (editParticleEffect is null)
  257. return;
  258. BeginParticleEffectEdit();
  259. LineEdit@ element = eventData["Element"].GetPtr();
  260. Vector3 v = editParticleEffect.constantForce;
  261. if (element.name == "ConstantForceX")
  262. editParticleEffect.constantForce = Vector3(element.text.ToFloat(), v.y, v.z);
  263. if (element.name == "ConstantForceY")
  264. editParticleEffect.constantForce = Vector3(v.x, element.text.ToFloat(), v.z);
  265. if (element.name == "ConstantForceZ")
  266. editParticleEffect.constantForce = Vector3(v.x, v.y, element.text.ToFloat());
  267. EndParticleEffectEdit();
  268. }
  269. void EditParticleEffectDirection(StringHash eventType, VariantMap& eventData)
  270. {
  271. if (inParticleEffectRefresh)
  272. return;
  273. if (editParticleEffect is null)
  274. return;
  275. BeginParticleEffectEdit();
  276. LineEdit@ element = eventData["Element"].GetPtr();
  277. Vector3 vMin = editParticleEffect.minDirection;
  278. Vector3 vMax = editParticleEffect.maxDirection;
  279. if (element.name == "DirectionMinX")
  280. editParticleEffect.minDirection = Vector3(element.text.ToFloat(), vMin.y, vMin.z);
  281. if (element.name == "DirectionMinY")
  282. editParticleEffect.minDirection = Vector3(vMin.x, element.text.ToFloat(), vMin.z);
  283. if (element.name == "DirectionMinZ")
  284. editParticleEffect.minDirection = Vector3(vMin.x, vMin.y, element.text.ToFloat());
  285. if (element.name == "DirectionMaxX")
  286. editParticleEffect.maxDirection = Vector3(element.text.ToFloat(), vMax.y, vMax.z);
  287. if (element.name == "DirectionMaxY")
  288. editParticleEffect.maxDirection = Vector3(vMax.x, element.text.ToFloat(), vMax.z);
  289. if (element.name == "DirectionMaxZ")
  290. editParticleEffect.maxDirection = Vector3(vMax.x, vMax.y, element.text.ToFloat());
  291. EndParticleEffectEdit();
  292. }
  293. void EditParticleEffectDampingForce(StringHash eventType, VariantMap& eventData)
  294. {
  295. if (inParticleEffectRefresh)
  296. return;
  297. if (editParticleEffect is null)
  298. return;
  299. BeginParticleEffectEdit();
  300. LineEdit@ element = eventData["Element"].GetPtr();
  301. editParticleEffect.dampingForce = element.text.ToFloat();
  302. EndParticleEffectEdit();
  303. }
  304. void EditParticleEffectActiveTime(StringHash eventType, VariantMap& eventData)
  305. {
  306. if (inParticleEffectRefresh)
  307. return;
  308. if (editParticleEffect is null)
  309. return;
  310. if (particleEffectEmitter is null)
  311. return;
  312. BeginParticleEffectEdit();
  313. LineEdit@ element = eventData["Element"].GetPtr();
  314. editParticleEffect.activeTime = element.text.ToFloat();
  315. particleEffectEmitter.Reset();
  316. EndParticleEffectEdit();
  317. }
  318. void EditParticleEffectInactiveTime(StringHash eventType, VariantMap& eventData)
  319. {
  320. if (inParticleEffectRefresh)
  321. return;
  322. if (editParticleEffect is null)
  323. return;
  324. if (particleEffectEmitter is null)
  325. return;
  326. BeginParticleEffectEdit();
  327. LineEdit@ element = eventData["Element"].GetPtr();
  328. editParticleEffect.inactiveTime = element.text.ToFloat();
  329. particleEffectEmitter.Reset();
  330. EndParticleEffectEdit();
  331. }
  332. void EditParticleEffectParticleSize(StringHash eventType, VariantMap& eventData)
  333. {
  334. if (inParticleEffectRefresh)
  335. return;
  336. if (editParticleEffect is null)
  337. return;
  338. BeginParticleEffectEdit();
  339. LineEdit@ element = eventData["Element"].GetPtr();
  340. Vector2 vMin = editParticleEffect.minParticleSize;
  341. Vector2 vMax = editParticleEffect.maxParticleSize;
  342. if (element.name == "ParticleSizeMinX")
  343. editParticleEffect.minParticleSize = Vector2(element.text.ToFloat(), vMin.y);
  344. if (element.name == "ParticleSizeMinY")
  345. editParticleEffect.minParticleSize = Vector2(vMin.x, element.text.ToFloat());
  346. if (element.name == "ParticleSizeMaxX")
  347. editParticleEffect.maxParticleSize = Vector2(element.text.ToFloat(), vMax.y);
  348. if (element.name == "ParticleSizeMaxY")
  349. editParticleEffect.maxParticleSize = Vector2(vMax.x, element.text.ToFloat());
  350. EndParticleEffectEdit();
  351. }
  352. void EditParticleEffectTimeToLive(StringHash eventType, VariantMap& eventData)
  353. {
  354. if (inParticleEffectRefresh)
  355. return;
  356. if (editParticleEffect is null)
  357. return;
  358. BeginParticleEffectEdit();
  359. LineEdit@ element = eventData["Element"].GetPtr();
  360. float vMin = editParticleEffect.minTimeToLive;
  361. float vMax = editParticleEffect.maxTimeToLive;
  362. if (element.name == "TimeToLiveMin")
  363. editParticleEffect.minTimeToLive = element.text.ToFloat();
  364. if (element.name == "TimeToLiveMax")
  365. editParticleEffect.maxTimeToLive = element.text.ToFloat();
  366. EndParticleEffectEdit();
  367. }
  368. void EditParticleEffectVelocity(StringHash eventType, VariantMap& eventData)
  369. {
  370. if (inParticleEffectRefresh)
  371. return;
  372. if (editParticleEffect is null)
  373. return;
  374. BeginParticleEffectEdit();
  375. LineEdit@ element = eventData["Element"].GetPtr();
  376. float vMin = editParticleEffect.minVelocity;
  377. float vMax = editParticleEffect.maxVelocity;
  378. if (element.name == "VelocityMin")
  379. editParticleEffect.minVelocity = element.text.ToFloat();
  380. if (element.name == "VelocityMax")
  381. editParticleEffect.maxVelocity = element.text.ToFloat();
  382. EndParticleEffectEdit();
  383. }
  384. void EditParticleEffectRotation(StringHash eventType, VariantMap& eventData)
  385. {
  386. if (inParticleEffectRefresh)
  387. return;
  388. if (editParticleEffect is null)
  389. return;
  390. BeginParticleEffectEdit();
  391. LineEdit@ element = eventData["Element"].GetPtr();
  392. float vMin = editParticleEffect.minRotation;
  393. float vMax = editParticleEffect.maxRotation;
  394. if (element.name == "RotationMin")
  395. editParticleEffect.minRotation = element.text.ToFloat();
  396. if (element.name == "RotationMax")
  397. editParticleEffect.maxRotation = element.text.ToFloat();
  398. EndParticleEffectEdit();
  399. }
  400. void EditParticleEffectRotationSpeed(StringHash eventType, VariantMap& eventData)
  401. {
  402. if (inParticleEffectRefresh)
  403. return;
  404. if (editParticleEffect is null)
  405. return;
  406. BeginParticleEffectEdit();
  407. LineEdit@ element = eventData["Element"].GetPtr();
  408. float vMin = editParticleEffect.minRotationSpeed;
  409. float vMax = editParticleEffect.maxRotationSpeed;
  410. if (element.name == "RotationSpeedMin")
  411. editParticleEffect.minRotationSpeed = element.text.ToFloat();
  412. if (element.name == "RotationSpeedMax")
  413. editParticleEffect.maxRotationSpeed = element.text.ToFloat();
  414. EndParticleEffectEdit();
  415. }
  416. void EditParticleEffectSizeAdd(StringHash eventType, VariantMap& eventData)
  417. {
  418. if (inParticleEffectRefresh)
  419. return;
  420. if (editParticleEffect is null)
  421. return;
  422. BeginParticleEffectEdit();
  423. LineEdit@ element = eventData["Element"].GetPtr();
  424. editParticleEffect.sizeAdd = element.text.ToFloat();
  425. EndParticleEffectEdit();
  426. }
  427. void EditParticleEffectSizeMultiply(StringHash eventType, VariantMap& eventData)
  428. {
  429. if (inParticleEffectRefresh)
  430. return;
  431. if (editParticleEffect is null)
  432. return;
  433. BeginParticleEffectEdit();
  434. LineEdit@ element = eventData["Element"].GetPtr();
  435. editParticleEffect.sizeMul = element.text.ToFloat();
  436. EndParticleEffectEdit();
  437. }
  438. void EditParticleEffectAnimationLodBias(StringHash eventType, VariantMap& eventData)
  439. {
  440. if (inParticleEffectRefresh)
  441. return;
  442. if (editParticleEffect is null)
  443. return;
  444. BeginParticleEffectEdit();
  445. LineEdit@ element = eventData["Element"].GetPtr();
  446. editParticleEffect.animationLodBias = element.text.ToFloat();
  447. EndParticleEffectEdit();
  448. }
  449. void EditParticleEffectNumParticles(StringHash eventType, VariantMap& eventData)
  450. {
  451. if (inParticleEffectRefresh)
  452. return;
  453. if (editParticleEffect is null)
  454. return;
  455. if (particleEffectEmitter is null)
  456. return;
  457. BeginParticleEffectEdit();
  458. LineEdit@ element = eventData["Element"].GetPtr();
  459. editParticleEffect.numParticles = element.text.ToInt();
  460. particleEffectEmitter.ApplyEffect();
  461. EndParticleEffectEdit();
  462. }
  463. void EditParticleEffectEmitterSize(StringHash eventType, VariantMap& eventData)
  464. {
  465. if (inParticleEffectRefresh)
  466. return;
  467. if (editParticleEffect is null)
  468. return;
  469. BeginParticleEffectEdit();
  470. LineEdit@ element = eventData["Element"].GetPtr();
  471. Vector3 v = editParticleEffect.emitterSize;
  472. if (element.name == "EmitterSizeX")
  473. editParticleEffect.emitterSize = Vector3(element.text.ToFloat(), v.y, v.z);
  474. if (element.name == "EmitterSizeY")
  475. editParticleEffect.emitterSize = Vector3(v.x, element.text.ToFloat(), v.z);
  476. if (element.name == "EmitterSizeZ")
  477. editParticleEffect.emitterSize = Vector3(v.x, v.y, element.text.ToFloat());
  478. EndParticleEffectEdit();
  479. }
  480. void EditParticleEffectEmissionRate(StringHash eventType, VariantMap& eventData)
  481. {
  482. if (inParticleEffectRefresh)
  483. return;
  484. if (editParticleEffect is null)
  485. return;
  486. BeginParticleEffectEdit();
  487. LineEdit@ element = eventData["Element"].GetPtr();
  488. if (element.name == "EmissionRateMin")
  489. editParticleEffect.minEmissionRate = element.text.ToFloat();
  490. if (element.name == "EmissionRateMax")
  491. editParticleEffect.maxEmissionRate = element.text.ToFloat();
  492. EndParticleEffectEdit();
  493. }
  494. void EditParticleEffectEmitterShape(StringHash eventType, VariantMap& eventData)
  495. {
  496. if (inParticleEffectRefresh)
  497. return;
  498. if (editParticleEffect is null)
  499. return;
  500. BeginParticleEffectEdit();
  501. DropDownList@ element = eventData["Element"].GetPtr();
  502. switch (element.selection)
  503. {
  504. case 0:
  505. editParticleEffect.emitterType = EMITTER_SPHERE;
  506. break;
  507. case 1:
  508. editParticleEffect.emitterType = EMITTER_BOX;
  509. break;
  510. }
  511. EndParticleEffectEdit();
  512. }
  513. void EditParticleEffectFaceCameraMode(StringHash eventType, VariantMap& eventData)
  514. {
  515. if (inParticleEffectRefresh)
  516. return;
  517. if (editParticleEffect is null)
  518. return;
  519. BeginParticleEffectEdit();
  520. DropDownList@ element = eventData["Element"].GetPtr();
  521. switch (element.selection)
  522. {
  523. case 0:
  524. editParticleEffect.faceCameraMode = FC_NONE;
  525. break;
  526. case 1:
  527. editParticleEffect.faceCameraMode = FC_ROTATE_XYZ;
  528. break;
  529. case 2:
  530. editParticleEffect.faceCameraMode = FC_ROTATE_Y;
  531. break;
  532. case 3:
  533. editParticleEffect.faceCameraMode = FC_LOOKAT_XYZ;
  534. break;
  535. case 4:
  536. editParticleEffect.faceCameraMode = FC_LOOKAT_Y;
  537. break;
  538. case 5:
  539. editParticleEffect.faceCameraMode = FC_DIRECTION;
  540. break;
  541. }
  542. particleEffectEmitter.ApplyEffect();
  543. EndParticleEffectEdit();
  544. }
  545. void EditParticleEffectMaterial(StringHash eventType, VariantMap& eventData)
  546. {
  547. if (inParticleEffectRefresh)
  548. return;
  549. if (editParticleEffect is null)
  550. return;
  551. if (particleEffectEmitter is null)
  552. return;
  553. LineEdit@ element = eventData["Element"].GetPtr();
  554. Material@ res = cache.GetResource("Material", element.text);
  555. if (res !is null)
  556. {
  557. BeginParticleEffectEdit();
  558. editParticleEffect.material = res;
  559. particleEffectEmitter.ApplyEffect();
  560. EndParticleEffectEdit();
  561. }
  562. }
  563. void PickEditParticleEffectMaterial(StringHash eventType, VariantMap& eventData)
  564. {
  565. @resourcePicker = GetResourcePicker(StringHash("Material"));
  566. if (resourcePicker is null)
  567. return;
  568. String lastPath = resourcePicker.lastPath;
  569. if (lastPath.empty)
  570. lastPath = sceneResourcePath;
  571. CreateFileSelector(localization.Get("Pick ") + resourcePicker.typeName, "OK", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter, false);
  572. SubscribeToEvent(uiFileSelector, "FileSelected", "PickEditParticleEffectMaterialDone");
  573. }
  574. void PickEditParticleEffectMaterialDone(StringHash eventType, VariantMap& eventData)
  575. {
  576. StoreResourcePickerPath();
  577. CloseFileSelector();
  578. if (!eventData["OK"].GetBool())
  579. {
  580. @resourcePicker = null;
  581. return;
  582. }
  583. String resourceName = eventData["FileName"].GetString();
  584. Resource@ res = GetPickedResource(resourceName);
  585. if (res !is null && editParticleEffect !is null && particleEffectEmitter !is null)
  586. {
  587. editParticleEffect.material = res;
  588. particleEffectEmitter.ApplyEffect();
  589. RefreshParticleEffectMaterial();
  590. }
  591. @resourcePicker = null;
  592. }
  593. void EditParticleEffectScaled(StringHash eventType, VariantMap& eventData)
  594. {
  595. if (inParticleEffectRefresh)
  596. return;
  597. if (editParticleEffect is null)
  598. return;
  599. if (particleEffectEmitter is null)
  600. return;
  601. BeginParticleEffectEdit();
  602. CheckBox@ element = eventData["Element"].GetPtr();
  603. editParticleEffect.scaled = element.checked;
  604. particleEffectEmitter.ApplyEffect();
  605. EndParticleEffectEdit();
  606. }
  607. void EditParticleEffectSorted(StringHash eventType, VariantMap& eventData)
  608. {
  609. if (inParticleEffectRefresh)
  610. return;
  611. if (editParticleEffect is null)
  612. return;
  613. if (particleEffectEmitter is null)
  614. return;
  615. BeginParticleEffectEdit();
  616. CheckBox@ element = eventData["Element"].GetPtr();
  617. editParticleEffect.sorted = element.checked;
  618. particleEffectEmitter.ApplyEffect();
  619. EndParticleEffectEdit();
  620. }
  621. void EditParticleEffectRelative(StringHash eventType, VariantMap& eventData)
  622. {
  623. if (inParticleEffectRefresh)
  624. return;
  625. if (editParticleEffect is null)
  626. return;
  627. if (particleEffectEmitter is null)
  628. return;
  629. BeginParticleEffectEdit();
  630. CheckBox@ element = eventData["Element"].GetPtr();
  631. editParticleEffect.relative = element.checked;
  632. particleEffectEmitter.ApplyEffect();
  633. EndParticleEffectEdit();
  634. }
  635. bool ToggleParticleEffectEditor()
  636. {
  637. if (particleEffectWindow.visible == false)
  638. ShowParticleEffectEditor();
  639. else
  640. HideParticleEffectEditor();
  641. return true;
  642. }
  643. void ShowParticleEffectEditor()
  644. {
  645. RefreshParticleEffectEditor();
  646. particleEffectWindow.visible = true;
  647. particleEffectWindow.BringToFront();
  648. }
  649. void HideParticleEffectEditor()
  650. {
  651. if (particleEffectWindow !is null)
  652. particleEffectWindow.visible = false;
  653. }
  654. void UpdateParticleEffectPreviewGrid()
  655. {
  656. uint gridSize = 8;
  657. uint gridSubdivisions = 3;
  658. //particleEffectPreviewGridNode.scale = Vector3(gridScale, gridScale, gridScale);
  659. uint size = uint(Floor(gridSize / 2) * 2);
  660. float halfSizeScaled = size / 2;
  661. float scale = 1.0;
  662. uint subdivisionSize = uint(Pow(2.0f, float(gridSubdivisions)));
  663. if (subdivisionSize > 0)
  664. {
  665. size *= subdivisionSize;
  666. scale /= subdivisionSize;
  667. }
  668. uint halfSize = size / 2;
  669. particleEffectPreviewGrid.BeginGeometry(0, LINE_LIST);
  670. float lineOffset = -halfSizeScaled;
  671. for (uint i = 0; i <= size; ++i)
  672. {
  673. bool lineCenter = i == halfSize;
  674. bool lineSubdiv = !Equals(Mod(i, subdivisionSize), 0.0);
  675. if (!grid2DMode)
  676. {
  677. particleEffectPreviewGrid.DefineVertex(Vector3(lineOffset, 0.0, halfSizeScaled));
  678. particleEffectPreviewGrid.DefineColor(lineCenter ? gridZColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
  679. particleEffectPreviewGrid.DefineVertex(Vector3(lineOffset, 0.0, -halfSizeScaled));
  680. particleEffectPreviewGrid.DefineColor(lineCenter ? gridZColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
  681. particleEffectPreviewGrid.DefineVertex(Vector3(-halfSizeScaled, 0.0, lineOffset));
  682. particleEffectPreviewGrid.DefineColor(lineCenter ? gridXColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
  683. particleEffectPreviewGrid.DefineVertex(Vector3(halfSizeScaled, 0.0, lineOffset));
  684. particleEffectPreviewGrid.DefineColor(lineCenter ? gridXColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
  685. }
  686. else
  687. {
  688. particleEffectPreviewGrid.DefineVertex(Vector3(lineOffset, halfSizeScaled, 0.0));
  689. particleEffectPreviewGrid.DefineColor(lineCenter ? gridYColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
  690. particleEffectPreviewGrid.DefineVertex(Vector3(lineOffset, -halfSizeScaled, 0.0));
  691. particleEffectPreviewGrid.DefineColor(lineCenter ? gridYColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
  692. particleEffectPreviewGrid.DefineVertex(Vector3(-halfSizeScaled, lineOffset, 0.0));
  693. particleEffectPreviewGrid.DefineColor(lineCenter ? gridXColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
  694. particleEffectPreviewGrid.DefineVertex(Vector3(halfSizeScaled, lineOffset, 0.0));
  695. particleEffectPreviewGrid.DefineColor(lineCenter ? gridXColor : (lineSubdiv ? gridSubdivisionColor : gridColor));
  696. }
  697. lineOffset += scale;
  698. }
  699. particleEffectPreviewGrid.Commit();
  700. }
  701. void InitParticleEffectPreview()
  702. {
  703. particlePreviewScene = Scene("particlePreviewScene");
  704. particlePreviewScene.CreateComponent("Octree");
  705. Node@ zoneNode = particlePreviewScene.CreateChild("Zone");
  706. Zone@ zone = zoneNode.CreateComponent("Zone");
  707. zone.boundingBox = BoundingBox(-1000, 1000);
  708. zone.ambientColor = Color(0.15, 0.15, 0.15);
  709. zone.fogColor = Color(0, 0, 0);
  710. zone.fogStart = 10.0;
  711. zone.fogEnd = 1000.0;
  712. particlePreviewCameraNode = particlePreviewScene.CreateChild("PreviewCamera");
  713. particlePreviewCamera = particlePreviewCameraNode.CreateComponent("Camera");
  714. particlePreviewCamera.nearClip = 0.1f;
  715. particlePreviewCamera.farClip = 1000.0f;
  716. particlePreviewCamera.fov = 45.0f;
  717. particlePreviewLightNode = particlePreviewScene.CreateChild("particlePreviewLight");
  718. particlePreviewLightNode.direction = Vector3(0.5, -0.5, 0.5);
  719. particlePreviewLight = particlePreviewLightNode.CreateComponent("Light");
  720. particlePreviewLight.lightType = LIGHT_DIRECTIONAL;
  721. particlePreviewLight.specularIntensity = 0.5;
  722. particleEffectPreviewNode = particlePreviewScene.CreateChild("PreviewEmitter");
  723. particleEffectPreviewNode.rotation = Quaternion(0, 0, 0);
  724. ResetCameraTransformation();
  725. particleEffectPreviewGizmoNode = particlePreviewScene.CreateChild("Gizmo");
  726. StaticModel@ gizmo = particleEffectPreviewGizmoNode.CreateComponent("StaticModel");
  727. gizmo.model = cache.GetResource("Model", "Models/Editor/Axes.mdl");
  728. gizmo.materials[0] = cache.GetResource("Material", "Materials/Editor/RedUnlit.xml");
  729. gizmo.materials[1] = cache.GetResource("Material", "Materials/Editor/GreenUnlit.xml");
  730. gizmo.materials[2] = cache.GetResource("Material", "Materials/Editor/BlueUnlit.xml");
  731. gizmo.occludee = false;
  732. particleEffectPreviewGridNode = particlePreviewScene.CreateChild("Grid");
  733. particleEffectPreviewGrid = particleEffectPreviewGridNode.CreateComponent("CustomGeometry");
  734. particleEffectPreviewGrid.numGeometries = 1;
  735. particleEffectPreviewGrid.material = cache.GetResource("Material", "Materials/VColUnlit.xml");
  736. particleEffectPreviewGrid.viewMask = 0x80000000; // Editor raycasts use viewmask 0x7fffffff
  737. particleEffectPreviewGrid.occludee = false;
  738. UpdateParticleEffectPreviewGrid();
  739. particleEffectEmitter = particleEffectPreviewNode.CreateComponent("ParticleEmitter");
  740. editParticleEffect = CreateNewParticleEffect();
  741. particleEffectEmitter.effect = editParticleEffect;
  742. particleEffectPreview = particleEffectWindow.GetChild("ParticleEffectPreview", true);
  743. particleEffectPreview.SetView(particlePreviewScene, particlePreviewCamera);
  744. particleEffectPreview.viewport.renderPath = renderPath;
  745. SubscribeToEvent(particleEffectPreview, "DragMove", "NavigateParticleEffectPreview");
  746. SubscribeToEvent(particleEffectPreview, "Resized", "ResizeParticleEffectPreview");
  747. }
  748. ParticleEffect@ CreateNewParticleEffect()
  749. {
  750. ParticleEffect@ effect = ParticleEffect();
  751. Material@ res = cache.GetResource("Material", "Materials/Particle.xml");
  752. if (res is null)
  753. log.Error("Could not load default material for new particle effect.");
  754. effect.material = res;
  755. effect.AddColorTime(Color(1,1,1,1), 0.0f);
  756. return effect;
  757. }
  758. void EditParticleEffect(ParticleEffect@ effect)
  759. {
  760. if (effect is null)
  761. return;
  762. if (editParticleEffect !is null)
  763. UnsubscribeFromEvent(editParticleEffect, "ReloadFinished");
  764. if (!effect.name.empty)
  765. cache.ReloadResource(effect);
  766. editParticleEffect = effect;
  767. particleEffectEmitter.effect = editParticleEffect;
  768. if (editParticleEffect !is null)
  769. SubscribeToEvent(editParticleEffect, "ReloadFinished", "RefreshParticleEffectEditor");
  770. ShowParticleEffectEditor();
  771. }
  772. void RefreshParticleEffectEditor()
  773. {
  774. inParticleEffectRefresh = true;
  775. RefreshParticleEffectPreview();
  776. RefreshParticleEffectName();
  777. RefreshParticleEffectBasicAttributes();
  778. RefreshParticleEffectMaterial();
  779. RefreshParticleEffectColorFrames();
  780. RefreshParticleEffectTextureFrames();
  781. inParticleEffectRefresh = false;
  782. }
  783. void RefreshParticleEffectColorFrames()
  784. {
  785. if (editParticleEffect is null)
  786. return;
  787. editParticleEffect.SortColorFrames();
  788. ListView@ lv = particleEffectWindow.GetChild("ColorFrameListView", true);
  789. if (lv is null)
  790. return;
  791. lv.RemoveAllItems();
  792. for (uint i = 0; i < editParticleEffect.numColorFrames; i++)
  793. {
  794. ColorFrame@ colorFrame = editParticleEffect.GetColorFrame(i);
  795. Button@ container = Button();
  796. lv.AddItem(container);
  797. container.style = "Button";
  798. container.imageRect = IntRect(18, 2, 30, 14);
  799. container.minSize = IntVector2(0, 20);
  800. container.maxSize = IntVector2(2147483647, 20);
  801. container.layoutMode = LM_HORIZONTAL;
  802. container.layoutBorder = IntRect(3,1,3,1);
  803. container.layoutSpacing = 4;
  804. UIElement@ labelContainer = UIElement();
  805. container.AddChild(labelContainer);
  806. labelContainer.style = "HorizontalPanel";
  807. labelContainer.minSize = IntVector2(0, 16);
  808. labelContainer.maxSize = IntVector2(2147483647, 16);
  809. labelContainer.verticalAlignment = VA_CENTER;
  810. {
  811. LineEdit@ le = LineEdit();
  812. labelContainer.AddChild(le);
  813. le.name = "ColorTime";
  814. le.vars["ColorFrame"] = i;
  815. le.style = "LineEdit";
  816. le.minSize = IntVector2(0, 16);
  817. le.maxSize = IntVector2(40, 16);
  818. le.text = colorFrame.time;
  819. le.cursorPosition = 0;
  820. CreateDragSlider(le);
  821. SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
  822. }
  823. UIElement@ textContainer = UIElement();
  824. labelContainer.AddChild(textContainer);
  825. textContainer.minSize = IntVector2(0, 16);
  826. textContainer.maxSize = IntVector2(2147483647, 16);
  827. textContainer.verticalAlignment = VA_CENTER;
  828. Text@ t = Text();
  829. textContainer.AddChild(t);
  830. t.style = "Text";
  831. t.text = "Color";
  832. t.autoLocalizable = true;
  833. UIElement@ editContainer = UIElement();
  834. container.AddChild(editContainer);
  835. editContainer.style = "HorizontalPanel";
  836. editContainer.minSize = IntVector2(0, 16);
  837. editContainer.maxSize = IntVector2(2147483647, 16);
  838. editContainer.verticalAlignment = VA_CENTER;
  839. {
  840. LineEdit@ le = LineEdit();
  841. editContainer.AddChild(le);
  842. le.name = "ColorR";
  843. le.vars["ColorFrame"] = i;
  844. le.style = "LineEdit";
  845. le.text = colorFrame.color.r;
  846. le.cursorPosition = 0;
  847. CreateDragSlider(le);
  848. SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
  849. }
  850. {
  851. LineEdit@ le = LineEdit();
  852. editContainer.AddChild(le);
  853. le.name = "ColorG";
  854. le.vars["ColorFrame"] = i;
  855. le.style = "LineEdit";
  856. le.text = colorFrame.color.g;
  857. le.cursorPosition = 0;
  858. CreateDragSlider(le);
  859. SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
  860. }
  861. {
  862. LineEdit@ le = LineEdit();
  863. editContainer.AddChild(le);
  864. le.name = "ColorB";
  865. le.vars["ColorFrame"] = i;
  866. le.style = "LineEdit";
  867. le.text = colorFrame.color.b;
  868. le.cursorPosition = 0;
  869. CreateDragSlider(le);
  870. SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
  871. }
  872. {
  873. LineEdit@ le = LineEdit();
  874. editContainer.AddChild(le);
  875. le.name = "ColorA";
  876. le.vars["ColorFrame"] = i;
  877. le.style = "LineEdit";
  878. le.text = colorFrame.color.a;
  879. le.cursorPosition = 0;
  880. CreateDragSlider(le);
  881. SubscribeToEvent(le, "TextChanged", "EditParticleEffectColorFrame");
  882. }
  883. }
  884. }
  885. void RefreshParticleEffectTextureFrames()
  886. {
  887. if (editParticleEffect is null)
  888. return;
  889. editParticleEffect.SortTextureFrames();
  890. ListView@ lv = particleEffectWindow.GetChild("TextureFrameListView", true);
  891. if (lv is null)
  892. return;
  893. lv.RemoveAllItems();
  894. for (uint i = 0; i < editParticleEffect.numTextureFrames; i++)
  895. {
  896. TextureFrame@ textureFrame = editParticleEffect.GetTextureFrame(i);
  897. if (textureFrame is null)
  898. continue;
  899. Button@ container = Button();
  900. lv.AddItem(container);
  901. container.style = "Button";
  902. container.imageRect = IntRect(18, 2, 30, 14);
  903. container.minSize = IntVector2(0, 20);
  904. container.maxSize = IntVector2(2147483647, 20);
  905. container.layoutMode = LM_HORIZONTAL;
  906. container.layoutBorder = IntRect(1,1,1,1);
  907. container.layoutSpacing = 4;
  908. UIElement@ labelContainer = UIElement();
  909. container.AddChild(labelContainer);
  910. labelContainer.style = "HorizontalPanel";
  911. labelContainer.minSize = IntVector2(0, 16);
  912. labelContainer.maxSize = IntVector2(2147483647, 16);
  913. labelContainer.verticalAlignment = VA_CENTER;
  914. {
  915. LineEdit@ le = LineEdit();
  916. labelContainer.AddChild(le);
  917. le.name = "TextureTime";
  918. le.vars["TextureFrame"] = i;
  919. le.style = "LineEdit";
  920. le.minSize = IntVector2(0, 16);
  921. le.maxSize = IntVector2(40, 16);
  922. le.text = textureFrame.time;
  923. le.cursorPosition = 0;
  924. CreateDragSlider(le);
  925. SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
  926. }
  927. UIElement@ textContainer = UIElement();
  928. labelContainer.AddChild(textContainer);
  929. textContainer.minSize = IntVector2(0, 16);
  930. textContainer.maxSize = IntVector2(2147483647, 16);
  931. textContainer.verticalAlignment = VA_CENTER;
  932. Text@ t = Text();
  933. textContainer.AddChild(t);
  934. t.style = "Text";
  935. t.text = "Texture";
  936. t.autoLocalizable = true;
  937. UIElement@ editContainer = UIElement();
  938. container.AddChild(editContainer);
  939. editContainer.style = "HorizontalPanel";
  940. editContainer.minSize = IntVector2(0, 16);
  941. editContainer.maxSize = IntVector2(2147483647, 16);
  942. editContainer.verticalAlignment = VA_CENTER;
  943. {
  944. LineEdit@ le = LineEdit();
  945. editContainer.AddChild(le);
  946. le.name = "TextureMinX";
  947. le.vars["TextureFrame"] = i;
  948. le.style = "LineEdit";
  949. le.text = textureFrame.uv.min.x;
  950. le.cursorPosition = 0;
  951. CreateDragSlider(le);
  952. SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
  953. }
  954. {
  955. LineEdit@ le = LineEdit();
  956. editContainer.AddChild(le);
  957. le.name = "TextureMinY";
  958. le.vars["TextureFrame"] = i;
  959. le.style = "LineEdit";
  960. le.text = textureFrame.uv.min.y;
  961. le.cursorPosition = 0;
  962. CreateDragSlider(le);
  963. SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
  964. }
  965. {
  966. LineEdit@ le = LineEdit();
  967. editContainer.AddChild(le);
  968. le.name = "TextureMaxX";
  969. le.vars["TextureFrame"] = i;
  970. le.style = "LineEdit";
  971. le.text = textureFrame.uv.max.x;
  972. le.cursorPosition = 0;
  973. CreateDragSlider(le);
  974. SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
  975. }
  976. {
  977. LineEdit@ le = LineEdit();
  978. editContainer.AddChild(le);
  979. le.name = "TextureMaxY";
  980. le.vars["TextureFrame"] = i;
  981. le.style = "LineEdit";
  982. le.text = textureFrame.uv.max.y;
  983. le.cursorPosition = 0;
  984. CreateDragSlider(le);
  985. SubscribeToEvent(le, "TextChanged", "EditParticleEffectTextureFrame");
  986. }
  987. }
  988. }
  989. void EditParticleEffectColorFrame(StringHash eventType, VariantMap& eventData)
  990. {
  991. if (inParticleEffectRefresh)
  992. return;
  993. if (editParticleEffect is null)
  994. return;
  995. if (particleEffectEmitter is null)
  996. return;
  997. BeginParticleEffectEdit();
  998. LineEdit@ element = eventData["Element"].GetPtr();
  999. uint i = element.vars["ColorFrame"].GetInt();
  1000. ColorFrame@ cf = editParticleEffect.GetColorFrame(i);
  1001. if (element.name == "ColorTime")
  1002. cf.time = element.text.ToFloat();
  1003. if (element.name == "ColorR")
  1004. cf.color = Color(element.text.ToFloat(), cf.color.g, cf.color.b, cf.color.a);
  1005. if (element.name == "ColorG")
  1006. cf.color = Color(cf.color.r, element.text.ToFloat(), cf.color.b, cf.color.a);
  1007. if (element.name == "ColorB")
  1008. cf.color = Color(cf.color.r, cf.color.g, element.text.ToFloat(), cf.color.a);
  1009. if (element.name == "ColorA")
  1010. cf.color = Color(cf.color.r, cf.color.g, cf.color.b, element.text.ToFloat());
  1011. editParticleEffect.SetColorFrame(i, cf);
  1012. particleEffectEmitter.Reset();
  1013. EndParticleEffectEdit();
  1014. }
  1015. void EditParticleEffectTextureFrame(StringHash eventType, VariantMap& eventData)
  1016. {
  1017. if (inParticleEffectRefresh)
  1018. return;
  1019. if (editParticleEffect is null)
  1020. return;
  1021. if (particleEffectEmitter is null)
  1022. return;
  1023. BeginParticleEffectEdit();
  1024. LineEdit@ element = eventData["Element"].GetPtr();
  1025. uint i = element.vars["TextureFrame"].GetInt();
  1026. TextureFrame@ tf = editParticleEffect.GetTextureFrame(i);
  1027. if (element.name == "TextureTime")
  1028. tf.time = element.text.ToFloat();
  1029. if (element.name == "TextureMinX")
  1030. tf.uv = Rect(element.text.ToFloat(), tf.uv.min.y, tf.uv.max.x, tf.uv.max.y);
  1031. if (element.name == "TextureMinY")
  1032. tf.uv = Rect(tf.uv.min.x, element.text.ToFloat(), tf.uv.max.x, tf.uv.max.y);
  1033. if (element.name == "TextureMaxX")
  1034. tf.uv = Rect(tf.uv.min.x, tf.uv.min.y, element.text.ToFloat(), tf.uv.max.y);
  1035. if (element.name == "TextureMaxY")
  1036. tf.uv = Rect(tf.uv.min.x, tf.uv.min.y, tf.uv.max.x, element.text.ToFloat());
  1037. editParticleEffect.SetTextureFrame(i, tf);
  1038. particleEffectEmitter.Reset();
  1039. EndParticleEffectEdit();
  1040. }
  1041. void RefreshParticleEffectPreview()
  1042. {
  1043. if (particleEffectEmitter is null || editParticleEffect is null)
  1044. return;
  1045. cast<CheckBox>(particleEffectWindow.GetChild("ShowGrid", true)).checked = showParticlePreviewAxes;
  1046. particleEffectEmitter.effect = editParticleEffect;
  1047. particleEffectEmitter.Reset();
  1048. particleEffectPreview.QueueUpdate();
  1049. }
  1050. void RefreshParticleEffectName()
  1051. {
  1052. UIElement@ container = particleEffectWindow.GetChild("NameContainer", true);
  1053. if (container is null)
  1054. return;
  1055. container.RemoveAllChildren();
  1056. LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, 0, 0);
  1057. if (editParticleEffect !is null)
  1058. nameEdit.text = editParticleEffect.name;
  1059. SubscribeToEvent(nameEdit, "TextFinished", "EditParticleEffectName");
  1060. Button@ pickButton = CreateResourcePickerButton(container, null, 0, 0, "smallButtonPick");
  1061. SubscribeToEvent(pickButton, "Released", "PickEditParticleEffect");
  1062. }
  1063. void RefreshParticleEffectBasicAttributes()
  1064. {
  1065. if (editParticleEffect is null)
  1066. return;
  1067. cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceX", true)).text = editParticleEffect.constantForce.x;
  1068. cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceY", true)).text = editParticleEffect.constantForce.y;
  1069. cast<LineEdit>(particleEffectWindow.GetChild("ConstantForceZ", true)).text = editParticleEffect.constantForce.z;
  1070. cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinX", true)).text = editParticleEffect.minDirection.x;
  1071. cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinY", true)).text = editParticleEffect.minDirection.y;
  1072. cast<LineEdit>(particleEffectWindow.GetChild("DirectionMinZ", true)).text = editParticleEffect.minDirection.z;
  1073. cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxX", true)).text = editParticleEffect.maxDirection.x;
  1074. cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxY", true)).text = editParticleEffect.maxDirection.y;
  1075. cast<LineEdit>(particleEffectWindow.GetChild("DirectionMaxZ", true)).text = editParticleEffect.maxDirection.z;
  1076. cast<LineEdit>(particleEffectWindow.GetChild("DampingForce", true)).text = editParticleEffect.dampingForce;
  1077. cast<LineEdit>(particleEffectWindow.GetChild("ActiveTime", true)).text = editParticleEffect.activeTime;
  1078. cast<LineEdit>(particleEffectWindow.GetChild("InactiveTime", true)).text = editParticleEffect.inactiveTime;
  1079. cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMinX", true)).text = editParticleEffect.minParticleSize.x;
  1080. cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMinY", true)).text = editParticleEffect.minParticleSize.y;
  1081. cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMaxX", true)).text = editParticleEffect.maxParticleSize.x;
  1082. cast<LineEdit>(particleEffectWindow.GetChild("ParticleSizeMaxY", true)).text = editParticleEffect.maxParticleSize.y;
  1083. cast<LineEdit>(particleEffectWindow.GetChild("TimeToLiveMin", true)).text = editParticleEffect.minTimeToLive;
  1084. cast<LineEdit>(particleEffectWindow.GetChild("TimeToLiveMax", true)).text = editParticleEffect.maxTimeToLive;
  1085. cast<LineEdit>(particleEffectWindow.GetChild("VelocityMin", true)).text = editParticleEffect.minVelocity;
  1086. cast<LineEdit>(particleEffectWindow.GetChild("VelocityMax", true)).text = editParticleEffect.maxVelocity;
  1087. cast<LineEdit>(particleEffectWindow.GetChild("RotationMin", true)).text = editParticleEffect.minRotation;
  1088. cast<LineEdit>(particleEffectWindow.GetChild("RotationMax", true)).text = editParticleEffect.maxRotation;
  1089. cast<LineEdit>(particleEffectWindow.GetChild("RotationSpeedMin", true)).text = editParticleEffect.minRotationSpeed;
  1090. cast<LineEdit>(particleEffectWindow.GetChild("RotationSpeedMax", true)).text = editParticleEffect.maxRotationSpeed;
  1091. cast<LineEdit>(particleEffectWindow.GetChild("SizeAdd", true)).text = editParticleEffect.sizeAdd;
  1092. cast<LineEdit>(particleEffectWindow.GetChild("SizeMultiply", true)).text = editParticleEffect.sizeMul;
  1093. cast<LineEdit>(particleEffectWindow.GetChild("AnimationLodBias", true)).text = editParticleEffect.animationLodBias;
  1094. cast<LineEdit>(particleEffectWindow.GetChild("NumParticles", true)).text = editParticleEffect.numParticles;
  1095. cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeX", true)).text = editParticleEffect.emitterSize.x;
  1096. cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeY", true)).text = editParticleEffect.emitterSize.y;
  1097. cast<LineEdit>(particleEffectWindow.GetChild("EmitterSizeZ", true)).text = editParticleEffect.emitterSize.z;
  1098. cast<LineEdit>(particleEffectWindow.GetChild("EmissionRateMin", true)).text = editParticleEffect.minEmissionRate;
  1099. cast<LineEdit>(particleEffectWindow.GetChild("EmissionRateMax", true)).text = editParticleEffect.maxEmissionRate;
  1100. switch (editParticleEffect.emitterType)
  1101. {
  1102. case EMITTER_SPHERE:
  1103. cast<DropDownList>(particleEffectWindow.GetChild("EmitterShape", true)).selection = 0;
  1104. break;
  1105. case EMITTER_BOX:
  1106. cast<DropDownList>(particleEffectWindow.GetChild("EmitterShape", true)).selection = 1;
  1107. break;
  1108. }
  1109. switch (editParticleEffect.faceCameraMode)
  1110. {
  1111. case FC_NONE:
  1112. cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 0;
  1113. break;
  1114. case FC_ROTATE_XYZ:
  1115. cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 1;
  1116. break;
  1117. case FC_ROTATE_Y:
  1118. cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 2;
  1119. break;
  1120. case FC_LOOKAT_XYZ:
  1121. cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 3;
  1122. break;
  1123. case FC_LOOKAT_Y:
  1124. cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 4;
  1125. break;
  1126. case FC_DIRECTION:
  1127. cast<DropDownList>(particleEffectWindow.GetChild("FaceCameraMode", true)).selection = 5;
  1128. break;
  1129. }
  1130. cast<CheckBox>(particleEffectWindow.GetChild("Scaled", true)).checked = editParticleEffect.scaled;
  1131. cast<CheckBox>(particleEffectWindow.GetChild("Sorted", true)).checked = editParticleEffect.sorted;
  1132. cast<CheckBox>(particleEffectWindow.GetChild("Relative", true)).checked = editParticleEffect.relative;
  1133. }
  1134. void RefreshParticleEffectMaterial()
  1135. {
  1136. UIElement@ container = particleEffectWindow.GetChild("ParticleMaterialContainer", true);
  1137. if (container is null)
  1138. return;
  1139. container.RemoveAllChildren();
  1140. LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, 0, 0);
  1141. if (editParticleEffect !is null)
  1142. {
  1143. if (editParticleEffect.material !is null)
  1144. nameEdit.text = editParticleEffect.material.name;
  1145. else
  1146. {
  1147. nameEdit.text = "Materials/Particle.xml";
  1148. Material@ res = cache.GetResource("Material", "Materials/Particle.xml");
  1149. if (res !is null)
  1150. editParticleEffect.material = res;
  1151. }
  1152. }
  1153. SubscribeToEvent(nameEdit, "TextFinished", "EditParticleEffectMaterial");
  1154. Button@ pickButton = CreateResourcePickerButton(container, null, 0, 0, "smallButtonPick");
  1155. SubscribeToEvent(pickButton, "Released", "PickEditParticleEffectMaterial");
  1156. }
  1157. void NavigateParticleEffectPreview(StringHash eventType, VariantMap& eventData)
  1158. {
  1159. int dx = eventData["DX"].GetInt();
  1160. int dy = eventData["DY"].GetInt();
  1161. if (particleEffectPreview.height > 0 && particleEffectPreview.width > 0)
  1162. {
  1163. if (!input.keyDown[KEY_LSHIFT])
  1164. {
  1165. particleViewCamRot.x -= dy * 20 * time.timeStep;
  1166. particleViewCamRot.y += dx * 20 * time.timeStep;
  1167. particleViewCamRot.x = Clamp(particleViewCamRot.x, -89.5, 89.5);
  1168. }
  1169. else
  1170. {
  1171. particleViewCamDist += dy * 1.5 * time.timeStep;
  1172. particleViewCamDist -= dx * 1.5 * time.timeStep;
  1173. particleViewCamDist = Max(particleViewCamDist, 0.2);
  1174. }
  1175. particlePreviewCameraNode.position = particleEffectPreviewNode.position +
  1176. Quaternion(particleViewCamRot.x, particleViewCamRot.y, 0) * particleViewCamDir * particleViewCamDist;
  1177. particlePreviewCameraNode.LookAt(particleEffectPreviewNode.position);
  1178. SetGizmoPosition();
  1179. particleEffectPreview.QueueUpdate();
  1180. }
  1181. }
  1182. void ResizeParticleEffectPreview(StringHash eventType, VariantMap& eventData)
  1183. {
  1184. float width = float(particleEffectPreview.width);
  1185. float height = float(particleEffectPreview.height);
  1186. // Manually set aspect ratio because first frame is always returning aspect ratio of 1
  1187. float aspectRatio = width / height;
  1188. particlePreviewCamera.aspectRatio = aspectRatio;
  1189. gizmoOffsetX = gizmoOffset;
  1190. gizmoOffsetY = 1.0f - gizmoOffset * aspectRatio;
  1191. if(width > height)
  1192. {
  1193. aspectRatio = height / width;
  1194. gizmoOffsetY = 1.0f - gizmoOffset;
  1195. gizmoOffsetX = gizmoOffset * aspectRatio;
  1196. }
  1197. SetGizmoPosition();
  1198. particleEffectPreview.QueueUpdate();
  1199. }
  1200. void EditParticleEffectName(StringHash eventType, VariantMap& eventData)
  1201. {
  1202. LineEdit@ nameEdit = eventData["Element"].GetPtr();
  1203. String newParticleEffectName = nameEdit.text.Trimmed();
  1204. if (!newParticleEffectName.empty && !(editParticleEffect !is null && newParticleEffectName == editParticleEffect.name))
  1205. {
  1206. ParticleEffect@ newParticleEffect = cache.GetResource("ParticleEffect", newParticleEffectName);
  1207. if (newParticleEffect !is null)
  1208. EditParticleEffect(newParticleEffect);
  1209. }
  1210. }
  1211. void PickEditParticleEffect()
  1212. {
  1213. @resourcePicker = GetResourcePicker(StringHash("ParticleEffect"));
  1214. if (resourcePicker is null)
  1215. return;
  1216. String lastPath = resourcePicker.lastPath;
  1217. if (lastPath.empty)
  1218. lastPath = sceneResourcePath;
  1219. CreateFileSelector(localization.Get("Pick ") + resourcePicker.typeName, "OK", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter, false);
  1220. SubscribeToEvent(uiFileSelector, "FileSelected", "PickEditParticleEffectDone");
  1221. }
  1222. void PickEditParticleEffectDone(StringHash eventType, VariantMap& eventData)
  1223. {
  1224. StoreResourcePickerPath();
  1225. CloseFileSelector();
  1226. if (!eventData["OK"].GetBool())
  1227. {
  1228. @resourcePicker = null;
  1229. return;
  1230. }
  1231. String resourceName = eventData["FileName"].GetString();
  1232. Resource@ res = GetPickedResource(resourceName);
  1233. if (res !is null)
  1234. EditParticleEffect(cast<ParticleEffect>(res));
  1235. @resourcePicker = null;
  1236. }
  1237. void NewParticleEffect()
  1238. {
  1239. BeginParticleEffectEdit();
  1240. EditParticleEffect(CreateNewParticleEffect());
  1241. EndParticleEffectEdit();
  1242. }
  1243. void RevertParticleEffect()
  1244. {
  1245. if (inParticleEffectRefresh)
  1246. return;
  1247. if (editParticleEffect is null)
  1248. return;
  1249. if (editParticleEffect.name.empty)
  1250. {
  1251. NewParticleEffect();
  1252. return;
  1253. }
  1254. BeginParticleEffectEdit();
  1255. cache.ReloadResource(editParticleEffect);
  1256. EndParticleEffectEdit();
  1257. RefreshParticleEffectEditor();
  1258. }
  1259. void SaveParticleEffect()
  1260. {
  1261. if (editParticleEffect is null || editParticleEffect.name.empty)
  1262. return;
  1263. String fullName = cache.GetResourceFileName(editParticleEffect.name);
  1264. if (fullName.empty)
  1265. return;
  1266. File saveFile(fullName, FILE_WRITE);
  1267. editParticleEffect.Save(saveFile);
  1268. }
  1269. void SaveParticleEffectAs()
  1270. {
  1271. if (editParticleEffect is null)
  1272. return;
  1273. @resourcePicker = GetResourcePicker(StringHash("ParticleEffect"));
  1274. if (resourcePicker is null)
  1275. return;
  1276. String lastPath = resourcePicker.lastPath;
  1277. if (lastPath.empty)
  1278. lastPath = sceneResourcePath;
  1279. CreateFileSelector("Save particle effect as", "Save", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter);
  1280. SubscribeToEvent(uiFileSelector, "FileSelected", "SaveParticleEffectAsDone");
  1281. }
  1282. void SaveParticleEffectAsDone(StringHash eventType, VariantMap& eventData)
  1283. {
  1284. StoreResourcePickerPath();
  1285. CloseFileSelector();
  1286. @resourcePicker = null;
  1287. if (editParticleEffect is null)
  1288. return;
  1289. if (!eventData["OK"].GetBool())
  1290. {
  1291. @resourcePicker = null;
  1292. return;
  1293. }
  1294. String fullName = eventData["FileName"].GetString();
  1295. // Add default extension for saving if not specified
  1296. String filter = eventData["Filter"].GetString();
  1297. if (GetExtension(fullName).empty && filter != "*.*")
  1298. fullName = fullName + filter.Substring(1);
  1299. File saveFile(fullName, FILE_WRITE);
  1300. if (editParticleEffect.Save(saveFile))
  1301. {
  1302. saveFile.Close();
  1303. // Load the new resource to update the name in the editor
  1304. ParticleEffect@ newEffect = cache.GetResource("ParticleEffect", GetResourceNameFromFullName(fullName));
  1305. if (newEffect !is null)
  1306. EditParticleEffect(newEffect);
  1307. }
  1308. }
  1309. void BeginParticleEffectEdit()
  1310. {
  1311. if (editParticleEffect is null)
  1312. return;
  1313. inParticleEffectRefresh = true;
  1314. oldParticleEffectState = XMLFile();
  1315. XMLElement particleElem = oldParticleEffectState.CreateRoot("particleeffect");
  1316. editParticleEffect.Save(particleElem);
  1317. }
  1318. void EndParticleEffectEdit()
  1319. {
  1320. if (editParticleEffect is null)
  1321. return;
  1322. if (!dragEditAttribute)
  1323. {
  1324. EditParticleEffectAction@ action = EditParticleEffectAction();
  1325. action.Define(particleEffectEmitter, editParticleEffect, oldParticleEffectState);
  1326. SaveEditAction(action);
  1327. }
  1328. inParticleEffectRefresh = false;
  1329. particleEffectPreview.QueueUpdate();
  1330. }