ParticlesGame.cpp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  1. #include "ParticlesGame.h"
  2. // Declare our game instance.
  3. ParticlesGame game;
  4. #define DEFAULT_PARTICLE_EMITTER "res/fire.particle"
  5. const float INPUT_SENSITIVITY = 0.05f;
  6. const float PANNING_SENSITIVITY = 0.01f;
  7. const float ROTATE_SENSITIVITY = 0.25f;
  8. const Vector4 BACKGROUND_COLOR = Vector4::zero();
  9. const float INITIAL_ZOOM = 6.0f;
  10. ParticlesGame::ParticlesGame() : _scene(NULL), _panning(false), _rotating(false), _zooming(false)
  11. {
  12. }
  13. void addGrid(unsigned int lineCount)
  14. {
  15. float z = -1;
  16. // There needs to be an odd number of lines
  17. lineCount |= 1;
  18. const unsigned int pointCount = lineCount * 4;
  19. const unsigned int verticesSize = pointCount * (3 + 3); // (3 (position(xyz) + 3 color(rgb))
  20. std::vector<float> vertices;
  21. vertices.resize(verticesSize);
  22. const float gridLength = (float)(lineCount / 2);
  23. float value = -gridLength;
  24. for (unsigned int i = 0; i < verticesSize; ++i)
  25. {
  26. // Default line color is dark grey
  27. Vector4 color(0.3f, 0.3f, 0.3f, 1.0f);
  28. // Every 10th line is brighter grey
  29. if (((int)value) % 10 == 0)
  30. {
  31. color.set(0.45f, 0.45f, 0.45f, 1.0f);
  32. }
  33. // The Z axis is blue
  34. if (value == 0.0f)
  35. {
  36. color.set(0.15f, 0.15f, 0.7f, 1.0f);
  37. }
  38. // Build the lines
  39. vertices[i] = value;
  40. vertices[++i] = -gridLength;
  41. vertices[++i] = z;
  42. vertices[++i] = color.x;
  43. vertices[++i] = color.y;
  44. vertices[++i] = color.z;
  45. vertices[++i] = value;
  46. vertices[++i] = gridLength;
  47. vertices[++i] = z;
  48. vertices[++i] = color.x;
  49. vertices[++i] = color.y;
  50. vertices[++i] = color.z;
  51. // The X axis is red
  52. if (value == 0.0f)
  53. {
  54. color.set(0.7f, 0.15f, 0.15f, 1.0f);
  55. }
  56. vertices[++i] = -gridLength;
  57. vertices[++i] = value;
  58. vertices[++i] = z;
  59. vertices[++i] = color.x;
  60. vertices[++i] = color.y;
  61. vertices[++i] = color.z;
  62. vertices[++i] = gridLength;
  63. vertices[++i] = value;
  64. vertices[++i] = z;
  65. vertices[++i] = color.x;
  66. vertices[++i] = color.y;
  67. vertices[++i] = color.z;
  68. value += 1.0f;
  69. }
  70. VertexFormat::Element elements[] =
  71. {
  72. VertexFormat::Element(VertexFormat::POSITION, 3),
  73. VertexFormat::Element(VertexFormat::COLOR, 3)
  74. };
  75. Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 2), pointCount, false);
  76. if (mesh == NULL)
  77. return;
  78. mesh->setPrimitiveType(Mesh::LINES);
  79. mesh->setVertexData(&vertices[0], 0, pointCount);
  80. Model* model = Model::create(mesh);
  81. model->setMaterial("res/grid.material");
  82. SAFE_RELEASE(mesh);
  83. Scene::getScene()->addNode("grid")->setModel(model);
  84. model->release();
  85. }
  86. void ParticlesGame::initialize()
  87. {
  88. // Display the gameplay splash screen
  89. displayScreen(this, &ParticlesGame::drawSplash, NULL, 250L);
  90. setMultiTouch(true);
  91. // Set keyboard state.
  92. _wDown = _aDown = _sDown = _dDown = false;
  93. _touched = false;
  94. _prevX = _prevY = 0;
  95. // Create a scene with a camera node.
  96. // The camera node is a child of a node at the same location as the particle emitter.
  97. // The camera node is offset from its parent, looking straight at it.
  98. // That way, when we rotate the parent node, the camera stays aimed at the particle emitter.
  99. _scene = Scene::create();
  100. Node* cameraNode = _scene->addNode("Camera");
  101. _cameraParent = _scene->addNode("CameraParent");
  102. _cameraParent->addChild(cameraNode);
  103. Camera* camera = Camera::createPerspective(45.0f, (float)getWidth() / (float)getHeight(), 0.25f, 1000.0f);
  104. cameraNode->setCamera(camera);
  105. cameraNode->setTranslation(0.0f, 0.0f, INITIAL_ZOOM);
  106. _scene->setActiveCamera(camera);
  107. SAFE_RELEASE(camera);
  108. addGrid(61);
  109. // Create a font for drawing the framerate.
  110. _font = Font::create("res/arial.gpb");
  111. // Load the form for editing ParticleEmitters.
  112. _form = Form::create("res/editor.form");
  113. _form->setConsumeInputEvents(false);
  114. //_form->setState(Control::FOCUS);
  115. // Store pointers to UI controls we care about.
  116. _startRed = (Slider*)_form->getControl("startRed");
  117. _startGreen = (Slider*)_form->getControl("startGreen");
  118. _startBlue = (Slider*)_form->getControl("startBlue");
  119. _startAlpha = (Slider*)_form->getControl("startAlpha");
  120. _endRed = (Slider*)_form->getControl("endRed");
  121. _endGreen = (Slider*)_form->getControl("endGreen");
  122. _endBlue = (Slider*)_form->getControl("endBlue");
  123. _endAlpha = (Slider*)_form->getControl("endAlpha");
  124. _particleProperties = (Container*)_form->getControl("particleProperties");
  125. _startMin = (Slider*)_form->getControl("startMin");
  126. _startMax = (Slider*)_form->getControl("startMax");
  127. _endMin = (Slider*)_form->getControl("endMin");
  128. _endMax = (Slider*)_form->getControl("endMax");
  129. _energyMin = (Slider*)_form->getControl("energyMin");
  130. _energyMax = (Slider*)_form->getControl("energyMax");
  131. _emissionRate = (Slider*)_form->getControl("emissionRate");
  132. _started = (CheckBox*)_form->getControl("started");
  133. _reset = (Button*)_form->getControl("reset");
  134. _emit = (Button*)_form->getControl("emit");
  135. _zoomIn = (Button*)_form->getControl("zoomIn");
  136. _zoomOut = (Button*)_form->getControl("zoomOut");
  137. _save = (Button*)_form->getControl("save");
  138. _load = (Button*)_form->getControl("load");
  139. _burstSize = (Slider*)_form->getControl("burstSize");
  140. _posVarX = (Slider*)_form->getControl("posVarX");
  141. _posVarY = (Slider*)_form->getControl("posVarY");
  142. _posVarZ = (Slider*)_form->getControl("posVarZ");
  143. _velX = (Slider*)_form->getControl("velocityX");
  144. _velY = (Slider*)_form->getControl("velocityY");
  145. _velZ = (Slider*)_form->getControl("velocityZ");
  146. _velVarX = (Slider*)_form->getControl("velocityVarX");
  147. _velVarY = (Slider*)_form->getControl("velocityVarY");
  148. _velVarZ = (Slider*)_form->getControl("velocityVarZ");
  149. _accelX = (Slider*)_form->getControl("accelX");
  150. _accelY = (Slider*)_form->getControl("accelY");
  151. _accelZ = (Slider*)_form->getControl("accelZ");
  152. _accelVarX = (Slider*)_form->getControl("accelVarX");
  153. _accelVarY = (Slider*)_form->getControl("accelVarY");
  154. _accelVarZ = (Slider*)_form->getControl("accelVarZ");
  155. _spinSpeedMin = (Slider*)_form->getControl("spinSpeedMin");
  156. _spinSpeedMax = (Slider*)_form->getControl("spinSpeedMax");
  157. _axisX = (Slider*)_form->getControl("axisX");
  158. _axisY = (Slider*)_form->getControl("axisY");
  159. _axisZ = (Slider*)_form->getControl("axisZ");
  160. _axisVarX = (Slider*)_form->getControl("axisVarX");
  161. _axisVarY = (Slider*)_form->getControl("axisVarY");
  162. _axisVarZ = (Slider*)_form->getControl("axisVarZ");
  163. _rotationSpeedMin = (Slider*)_form->getControl("rotationSpeedMin");
  164. _rotationSpeedMax = (Slider*)_form->getControl("rotationSpeedMax");
  165. _vsync = (CheckBox*)_form->getControl("vsync");
  166. // Listen for UI events.
  167. _startRed->addListener(this, Listener::VALUE_CHANGED);
  168. _startGreen->addListener(this, Listener::VALUE_CHANGED);
  169. _startBlue->addListener(this, Listener::VALUE_CHANGED);
  170. _startAlpha->addListener(this, Listener::VALUE_CHANGED);
  171. _endRed->addListener(this, Listener::VALUE_CHANGED);
  172. _endGreen->addListener(this, Listener::VALUE_CHANGED);
  173. _endBlue->addListener(this, Listener::VALUE_CHANGED);
  174. _endAlpha->addListener(this, Listener::VALUE_CHANGED);
  175. _startMin->addListener(this, Listener::VALUE_CHANGED);
  176. _startMax->addListener(this, Listener::VALUE_CHANGED);
  177. _endMin->addListener(this, Listener::VALUE_CHANGED);
  178. _endMax->addListener(this, Listener::VALUE_CHANGED);
  179. _energyMin->addListener(this, Listener::VALUE_CHANGED);
  180. _energyMax->addListener(this, Listener::VALUE_CHANGED);
  181. _emissionRate->addListener(this, Listener::VALUE_CHANGED);
  182. _started->addListener(this, Listener::VALUE_CHANGED);
  183. _reset->addListener(this, Listener::CLICK);
  184. _emit->addListener(this, Listener::CLICK);
  185. _zoomIn->addListener(this, Listener::PRESS);
  186. _zoomIn->addListener(this, Listener::RELEASE);
  187. _zoomOut->addListener(this, Listener::PRESS);
  188. _zoomOut->addListener(this, Listener::RELEASE);
  189. _save->addListener(this, Listener::RELEASE);
  190. _load->addListener(this, Listener::RELEASE);
  191. _burstSize->addListener(this, Listener::VALUE_CHANGED);
  192. _form->getControl("posX")->addListener(this, Listener::VALUE_CHANGED);
  193. _form->getControl("posY")->addListener(this, Listener::VALUE_CHANGED);
  194. _form->getControl("posZ")->addListener(this, Listener::VALUE_CHANGED);
  195. _posVarX->addListener(this, Listener::VALUE_CHANGED);
  196. _posVarY->addListener(this, Listener::VALUE_CHANGED);
  197. _posVarZ->addListener(this, Listener::VALUE_CHANGED);
  198. _velX->addListener(this, Listener::VALUE_CHANGED);
  199. _velY->addListener(this, Listener::VALUE_CHANGED);
  200. _velZ->addListener(this, Listener::VALUE_CHANGED);
  201. _velVarX->addListener(this, Listener::VALUE_CHANGED);
  202. _velVarY->addListener(this, Listener::VALUE_CHANGED);
  203. _velVarZ->addListener(this, Listener::VALUE_CHANGED);
  204. _accelX->addListener(this, Listener::VALUE_CHANGED);
  205. _accelY->addListener(this, Listener::VALUE_CHANGED);
  206. _accelZ->addListener(this, Listener::VALUE_CHANGED);
  207. _accelVarX->addListener(this, Listener::VALUE_CHANGED);
  208. _accelVarY->addListener(this, Listener::VALUE_CHANGED);
  209. _accelVarZ->addListener(this, Listener::VALUE_CHANGED);
  210. _spinSpeedMin->addListener(this, Listener::VALUE_CHANGED);
  211. _spinSpeedMax->addListener(this, Listener::VALUE_CHANGED);
  212. _axisX->addListener(this, Listener::VALUE_CHANGED);
  213. _axisY->addListener(this, Listener::VALUE_CHANGED);
  214. _axisZ->addListener(this, Listener::VALUE_CHANGED);
  215. _axisVarX->addListener(this, Listener::VALUE_CHANGED);
  216. _axisVarY->addListener(this, Listener::VALUE_CHANGED);
  217. _axisVarZ->addListener(this, Listener::VALUE_CHANGED);
  218. _rotationSpeedMin->addListener(this, Listener::VALUE_CHANGED);
  219. _rotationSpeedMax->addListener(this, Listener::VALUE_CHANGED);
  220. _vsync->addListener(this, Listener::VALUE_CHANGED);
  221. _form->getControl("sprite")->addListener(this, Listener::CLICK);
  222. _form->getControl("additive")->addListener(this, Listener::VALUE_CHANGED);
  223. _form->getControl("transparent")->addListener(this, Listener::VALUE_CHANGED);
  224. _form->getControl("multiply")->addListener(this, Listener::VALUE_CHANGED);
  225. _form->getControl("opaque")->addListener(this, Listener::VALUE_CHANGED);
  226. _form->getControl("updateFrames")->addListener(this, Listener::CLICK);
  227. // Hide save/load buttons for non-windows platforms until we implement picking dialogs for others
  228. #ifdef WIN32
  229. _form->getControl("zoomIn")->setVisible(false);
  230. _form->getControl("zoomOut")->setVisible(false);
  231. #else
  232. _form->getControl("saveLoad")->setVisible(false);
  233. _form->getControl("image")->setVisible(false);
  234. #endif
  235. // Load preset emitters.
  236. loadEmitters();
  237. updateImageControl();
  238. }
  239. #ifdef WIN32
  240. #include <Windows.h>
  241. #include <Commdlg.h>
  242. #endif
  243. std::string ParticlesGame::openFile(const char* title, const char* filterDescription, const char* filterExtension)
  244. {
  245. #ifdef WIN32
  246. OPENFILENAMEA ofn;
  247. memset(&ofn, 0, sizeof(ofn));
  248. std::string desc = filterDescription;
  249. desc += " (*.";
  250. desc += filterExtension;
  251. desc += ")";
  252. std::string ext = "*.";
  253. ext += filterExtension;
  254. char filter[1024];
  255. memset(filter, 0, 1024);
  256. strcpy(filter, desc.c_str());
  257. strcpy(filter + desc.length() + 1, ext.c_str());
  258. char szCurrentDir[256];
  259. GetCurrentDirectoryA(256, szCurrentDir);
  260. std::string initialDir = szCurrentDir;
  261. initialDir += "\\res";
  262. char szFileName[256] = "";
  263. ofn.lStructSize = sizeof(ofn); // SEE NOTE BELOW
  264. ofn.hwndOwner = GetForegroundWindow();
  265. ofn.lpstrTitle = title;
  266. ofn.lpstrFilter = filter;//"Particle Files (*.particle)\0*.particle\0";
  267. ofn.lpstrFile = szFileName;
  268. ofn.lpstrInitialDir = initialDir.c_str();
  269. ofn.nMaxFile = 256;
  270. ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  271. ofn.lpstrDefExt = "filterExtension";
  272. GetOpenFileNameA(&ofn);
  273. // Restore current dir
  274. SetCurrentDirectoryA(szCurrentDir);
  275. return szFileName;
  276. #endif
  277. return "";
  278. }
  279. std::string toString(ParticleEmitter::TextureBlending blending)
  280. {
  281. switch (blending)
  282. {
  283. case ParticleEmitter::BLEND_OPAQUE:
  284. return "OPAQUE";
  285. case ParticleEmitter::BLEND_TRANSPARENT:
  286. return "TRANSPARENT";
  287. case ParticleEmitter::BLEND_ADDITIVE:
  288. return "ADDITIVE";
  289. case ParticleEmitter::BLEND_MULTIPLIED:
  290. return "MULTIPLIED";
  291. default:
  292. return "TRANSPARENT";
  293. }
  294. }
  295. std::string toString(const Vector4& v)
  296. {
  297. std::ostringstream s;
  298. s << v.x << ", " << v.y << ", " << v.z << ", " << v.w;
  299. return s.str();
  300. }
  301. std::string toString(const Vector3& v)
  302. {
  303. std::ostringstream s;
  304. s << v.x << ", " << v.y << ", " << v.z;
  305. return s.str();
  306. }
  307. std::string toString(const Quaternion& q)
  308. {
  309. std::ostringstream s;
  310. s << q.x << ", " << q.y << ", " << q.z << ", " << q.w;
  311. return s.str();
  312. }
  313. std::string toString(bool b)
  314. {
  315. return b ? "true" : "false";
  316. }
  317. std::string toString(int i)
  318. {
  319. char buf[1024];
  320. sprintf(buf, "%d", i);
  321. return buf;
  322. }
  323. std::string toString(unsigned int i)
  324. {
  325. char buf[1024];
  326. sprintf(buf, "%d", i);
  327. return buf;
  328. }
  329. void ParticlesGame::saveFile()
  330. {
  331. std::string filename;
  332. #ifdef WIN32
  333. OPENFILENAMEA ofn;
  334. memset(&ofn, 0, sizeof(ofn));
  335. char szCurrentDir[256];
  336. GetCurrentDirectoryA(256, szCurrentDir);
  337. std::string initialDir = szCurrentDir;
  338. initialDir += "\\res";
  339. char szFileName[256] = "";
  340. ofn.lStructSize = sizeof(ofn); // SEE NOTE BELOW
  341. ofn.hwndOwner = GetForegroundWindow();
  342. ofn.lpstrFilter = "Particle Files (*.particle)\0*.particle\0";
  343. ofn.lpstrFile = szFileName;
  344. ofn.lpstrInitialDir = initialDir.c_str();
  345. ofn.nMaxFile = 256;
  346. ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
  347. ofn.lpstrDefExt = "particle";
  348. GetSaveFileNameA(&ofn);
  349. filename = szFileName;
  350. // Restore current dir
  351. SetCurrentDirectoryA(szCurrentDir);
  352. #endif
  353. if (filename.length() == 0)
  354. return;
  355. ParticleEmitter* e = _particleEmitter;
  356. // Extract just the particle name from the filename
  357. std::string dir = FileSystem::getDirectoryName(filename.c_str());
  358. std::string ext = FileSystem::getExtension(filename.c_str());
  359. std::string name = filename.substr(dir.length(), filename.length() - dir.length() - ext.length());
  360. Texture* texture = e->getTexture();
  361. std::string texturePath = texture->getPath();
  362. std::string textureDir = FileSystem::getDirectoryName(texturePath.c_str());
  363. texturePath = texturePath.substr(textureDir.length());
  364. // Get camera rotation as axis-angle
  365. Vector3 cameraAxis;
  366. float cameraAngle = MATH_RAD_TO_DEG(_cameraParent->getRotation().toAxisAngle(&cameraAxis));
  367. // Write out a properties file
  368. std::ostringstream s;
  369. s <<
  370. "particle " << name << "\n" <<
  371. "{\n" <<
  372. " sprite\n" <<
  373. " {\n" <<
  374. " path = " << texturePath << "\n" <<
  375. " width = " << e->getSpriteWidth() << "\n" <<
  376. " height = " << e->getSpriteHeight() << "\n" <<
  377. " blending = " << toString(e->getTextureBlending()) << "\n" <<
  378. " animated = " << toString(e->isSpriteAnimated()) << "\n" <<
  379. " looped = " << toString(e->isSpriteLooped()) << "\n" <<
  380. " frameCount = " << e->getSpriteFrameCount() << "\n" <<
  381. " frameRandomOffset = " << e->getSpriteFrameRandomOffset() << "\n" <<
  382. " frameDuration = " << e->getSpriteFrameDuration() << "\n" <<
  383. " }\n" <<
  384. "\n" <<
  385. " particleCountMax = " << e->getParticleCountMax() << "\n" <<
  386. " emissionRate = " << e->getEmissionRate() << "\n" <<
  387. " ellipsoid = " << toString(e->isEllipsoid()) << "\n" <<
  388. " orbitPosition = " << toString(e->getOrbitPosition()) << "\n" <<
  389. " orbitVelocity = " << toString(e->getOrbitVelocity()) << "\n" <<
  390. " orbitAcceleration = " << toString(e->getOrbitAcceleration()) << "\n" <<
  391. " sizeStartMin = " << e->getSizeStartMin() << "\n" <<
  392. " sizeStartMax = " << e->getSizeStartMax() << "\n" <<
  393. " sizeEndMin = " << e->getSizeEndMin() << "\n" <<
  394. " sizeEndMax = " << e->getSizeEndMax() << "\n" <<
  395. " energyMin = " << e->getEnergyMin() << "\n" <<
  396. " energyMax = " << e->getEnergyMax() << "\n" <<
  397. " colorStart = " << toString(e->getColorStart()) << "\n" <<
  398. " colorStartVar = " << toString(e->getColorStartVariance()) << "\n" <<
  399. " colorEnd = " << toString(e->getColorEnd()) << "\n" <<
  400. " colorEndVar = " << toString(e->getColorEndVariance()) << "\n" <<
  401. " position = " << toString(e->getPosition()) << "\n" <<
  402. " positionVar = " << toString(e->getPositionVariance()) << "\n" <<
  403. " velocity = " << toString(e->getVelocity()) << "\n" <<
  404. " velocityVar = " << toString(e->getVelocityVariance()) << "\n" <<
  405. " acceleration = " << toString(e->getAcceleration()) << "\n" <<
  406. " accelerationVar = " << toString(e->getAccelerationVariance()) << "\n" <<
  407. " rotationPerParticleSpeedMin = " << e->getRotationPerParticleSpeedMin() << "\n" <<
  408. " rotationPerParticleSpeedMax = " << e->getRotationPerParticleSpeedMax() << "\n" <<
  409. "\n" <<
  410. " editor\n" <<
  411. " {\n" <<
  412. " cameraTranslation = " << toString(_cameraParent->getTranslation()) << "\n" <<
  413. " cameraZoom = " << toString(_scene->getActiveCamera()->getNode()->getTranslation()) << "\n" <<
  414. " cameraRotation = " << toString(cameraAxis) << ", " << cameraAngle << "\n" <<
  415. " sizeMax = " << _startMax->getMax() << "\n" <<
  416. " energyMax = " << _energyMax->getMax() << "\n" <<
  417. " }\n"
  418. "}\n";
  419. std::string text = s.str();
  420. Stream* stream = FileSystem::open(filename.c_str(), FileSystem::WRITE);
  421. stream->write(text.c_str(), 1, text.length());
  422. stream->close();
  423. SAFE_DELETE(stream);
  424. }
  425. void ParticlesGame::controlEvent(Control* control, EventType evt)
  426. {
  427. std::string id = control->getId();
  428. // Handle UI events.
  429. ParticleEmitter* emitter = _particleEmitterNode->getParticleEmitter();
  430. switch(evt)
  431. {
  432. case Listener::VALUE_CHANGED:
  433. if (control == _startRed)
  434. {
  435. Vector4 startColor = emitter->getColorStart();
  436. startColor.x = _startRed->getValue();
  437. emitter->setColor(startColor, emitter->getColorStartVariance(), emitter->getColorEnd(), emitter->getColorEndVariance());
  438. }
  439. else if (control == _startGreen)
  440. {
  441. Vector4 startColor = emitter->getColorStart();
  442. startColor.y = _startGreen->getValue();
  443. emitter->setColor(startColor, emitter->getColorStartVariance(), emitter->getColorEnd(), emitter->getColorEndVariance());
  444. }
  445. else if (control == _startBlue)
  446. {
  447. Vector4 startColor = emitter->getColorStart();
  448. startColor.z = _startBlue->getValue();
  449. emitter->setColor(startColor, emitter->getColorStartVariance(), emitter->getColorEnd(), emitter->getColorEndVariance());
  450. }
  451. else if (control == _startAlpha)
  452. {
  453. Vector4 startColor = emitter->getColorStart();
  454. startColor.w = _startAlpha->getValue();
  455. emitter->setColor(startColor, emitter->getColorStartVariance(), emitter->getColorEnd(), emitter->getColorEndVariance());
  456. }
  457. else if (control == _endRed)
  458. {
  459. Vector4 endColor = emitter->getColorEnd();
  460. endColor.x = _endRed->getValue();
  461. emitter->setColor(emitter->getColorStart(), emitter->getColorStartVariance(), endColor, emitter->getColorEndVariance());
  462. }
  463. else if (control == _endGreen)
  464. {
  465. Vector4 endColor = emitter->getColorEnd();
  466. endColor.y = _endGreen->getValue();
  467. emitter->setColor(emitter->getColorStart(), emitter->getColorStartVariance(), endColor, emitter->getColorEndVariance());
  468. }
  469. else if (control == _endBlue)
  470. {
  471. Vector4 endColor = emitter->getColorEnd();
  472. endColor.z = _endBlue->getValue();
  473. emitter->setColor(emitter->getColorStart(), emitter->getColorStartVariance(), endColor, emitter->getColorEndVariance());
  474. }
  475. else if (control == _endAlpha)
  476. {
  477. Vector4 endColor = emitter->getColorEnd();
  478. endColor.w = _endAlpha->getValue();
  479. emitter->setColor(emitter->getColorStart(), emitter->getColorStartVariance(), endColor, emitter->getColorEndVariance());
  480. }
  481. else if (control == _startMin)
  482. {
  483. emitter->setSize(_startMin->getValue(), emitter->getSizeStartMax(), emitter->getSizeEndMin(), emitter->getSizeEndMax());
  484. }
  485. else if (control == _startMax)
  486. {
  487. emitter->setSize(emitter->getSizeStartMin(), _startMax->getValue(), emitter->getSizeEndMin(), emitter->getSizeEndMax());
  488. }
  489. else if (control == _endMin)
  490. {
  491. emitter->setSize(emitter->getSizeStartMin(), emitter->getSizeStartMax(), _endMin->getValue(), emitter->getSizeEndMax());
  492. }
  493. else if (control == _endMax)
  494. {
  495. emitter->setSize(emitter->getSizeStartMin(), emitter->getSizeStartMax(), emitter->getSizeEndMin(), _endMax->getValue());
  496. }
  497. else if (control == _energyMin)
  498. {
  499. emitter->setEnergy(_energyMin->getValue(), emitter->getEnergyMax());
  500. }
  501. else if (control == _energyMax)
  502. {
  503. emitter->setEnergy(emitter->getEnergyMin(), _energyMax->getValue());
  504. }
  505. else if (control == _emissionRate)
  506. {
  507. emitter->setEmissionRate(_emissionRate->getValue());
  508. }
  509. else if (id == "posX")
  510. {
  511. Vector3 pos(emitter->getPosition());
  512. pos.x = ((Slider*)control)->getValue();
  513. emitter->setPosition(pos, emitter->getPositionVariance());
  514. }
  515. else if (id == "posY")
  516. {
  517. Vector3 pos(emitter->getPosition());
  518. pos.y = ((Slider*)control)->getValue();
  519. emitter->setPosition(pos, emitter->getPositionVariance());
  520. }
  521. else if (id == "posZ")
  522. {
  523. Vector3 pos(emitter->getPosition());
  524. pos.z = ((Slider*)control)->getValue();
  525. emitter->setPosition(pos, emitter->getPositionVariance());
  526. }
  527. else if (control == _posVarX)
  528. {
  529. Vector3 posVar = emitter->getPositionVariance();
  530. posVar.x = _posVarX->getValue();
  531. emitter->setPosition(emitter->getPosition(), posVar);
  532. }
  533. else if (control == _posVarY)
  534. {
  535. Vector3 posVar = emitter->getPositionVariance();
  536. posVar.y = _posVarY->getValue();
  537. emitter->setPosition(emitter->getPosition(), posVar);
  538. }
  539. else if (control == _posVarZ)
  540. {
  541. Vector3 posVar = emitter->getPositionVariance();
  542. posVar.z = _posVarZ->getValue();
  543. emitter->setPosition(emitter->getPosition(), posVar);
  544. }
  545. else if (control == _velX)
  546. {
  547. Vector3 vel = emitter->getVelocity();
  548. vel.x = _velX->getValue();
  549. emitter->setVelocity(vel, emitter->getVelocityVariance());
  550. }
  551. else if (control == _velY)
  552. {
  553. Vector3 vel = emitter->getVelocity();
  554. vel.y = _velY->getValue();
  555. emitter->setVelocity(vel, emitter->getVelocityVariance());
  556. }
  557. else if (control == _velZ)
  558. {
  559. Vector3 vel = emitter->getVelocity();
  560. vel.z = _velZ->getValue();
  561. emitter->setVelocity(vel, emitter->getVelocityVariance());
  562. }
  563. else if (control == _velVarX)
  564. {
  565. Vector3 velVar = emitter->getVelocityVariance();
  566. velVar.x = _velVarX->getValue();
  567. emitter->setVelocity(emitter->getVelocity(), velVar);
  568. }
  569. else if (control == _velVarY)
  570. {
  571. Vector3 velVar = emitter->getVelocityVariance();
  572. velVar.y = _velVarY->getValue();
  573. emitter->setVelocity(emitter->getVelocity(), velVar);
  574. }
  575. else if (control == _velVarZ)
  576. {
  577. Vector3 velVar = emitter->getVelocityVariance();
  578. velVar.z = _velVarZ->getValue();
  579. emitter->setVelocity(emitter->getVelocity(), velVar);
  580. }
  581. else if (control == _accelX)
  582. {
  583. Vector3 accel = emitter->getAcceleration();
  584. accel.x = _accelX->getValue();
  585. emitter->setAcceleration(accel, emitter->getAccelerationVariance());
  586. }
  587. else if (control == _accelY)
  588. {
  589. Vector3 accel = emitter->getAcceleration();
  590. accel.y = _accelY->getValue();
  591. emitter->setAcceleration(accel, emitter->getAccelerationVariance());
  592. }
  593. else if (control == _accelZ)
  594. {
  595. Vector3 accel = emitter->getAcceleration();
  596. accel.z = _accelZ->getValue();
  597. emitter->setAcceleration(accel, emitter->getAccelerationVariance());
  598. }
  599. else if (control == _accelVarX)
  600. {
  601. Vector3 accelVar = emitter->getAccelerationVariance();
  602. accelVar.x = _accelVarX->getValue();
  603. emitter->setAcceleration(emitter->getAcceleration(), accelVar);
  604. }
  605. else if (control == _accelVarY)
  606. {
  607. Vector3 accelVar = emitter->getAccelerationVariance();
  608. accelVar.y = _accelVarY->getValue();
  609. emitter->setAcceleration(emitter->getAcceleration(), accelVar);
  610. }
  611. else if (control == _accelVarZ)
  612. {
  613. Vector3 accelVar = emitter->getAccelerationVariance();
  614. accelVar.z = _accelVarZ->getValue();
  615. emitter->setAcceleration(emitter->getAcceleration(), accelVar);
  616. }
  617. else if (control == _spinSpeedMin)
  618. {
  619. emitter->setRotationPerParticle(_spinSpeedMin->getValue(), emitter->getRotationPerParticleSpeedMax());
  620. }
  621. else if (control == _spinSpeedMax)
  622. {
  623. emitter->setRotationPerParticle(emitter->getRotationPerParticleSpeedMin(), _spinSpeedMax->getValue());
  624. }
  625. else if (control == _axisX)
  626. {
  627. Vector3 axis = emitter->getRotationAxis();
  628. axis.x = _axisX->getValue();
  629. emitter->setRotation(emitter->getRotationSpeedMin(), emitter->getRotationSpeedMax(), axis, emitter->getRotationAxisVariance());
  630. }
  631. else if (control == _axisY)
  632. {
  633. Vector3 axis = emitter->getRotationAxis();
  634. axis.y = _axisY->getValue();
  635. emitter->setRotation(emitter->getRotationSpeedMin(), emitter->getRotationSpeedMax(), axis, emitter->getRotationAxisVariance());
  636. }
  637. else if (control == _axisZ)
  638. {
  639. Vector3 axis = emitter->getRotationAxis();
  640. axis.z = _axisZ->getValue();
  641. emitter->setRotation(emitter->getRotationSpeedMin(), emitter->getRotationSpeedMax(), axis, emitter->getRotationAxisVariance());
  642. }
  643. else if (control == _axisVarX)
  644. {
  645. Vector3 axisVar = emitter->getRotationAxisVariance();
  646. axisVar.x = _axisVarX->getValue();
  647. emitter->setRotation(emitter->getRotationSpeedMin(), emitter->getRotationSpeedMax(), emitter->getRotationAxis(), axisVar);
  648. }
  649. else if (control == _axisVarY)
  650. {
  651. Vector3 axisVar = emitter->getRotationAxisVariance();
  652. axisVar.y = _axisVarY->getValue();
  653. emitter->setRotation(emitter->getRotationSpeedMin(), emitter->getRotationSpeedMax(), emitter->getRotationAxis(), axisVar);
  654. }
  655. else if (control == _axisVarZ)
  656. {
  657. Vector3 axisVar = emitter->getRotationAxisVariance();
  658. axisVar.z = _axisVarZ->getValue();
  659. emitter->setRotation(emitter->getRotationSpeedMin(), emitter->getRotationSpeedMax(), emitter->getRotationAxis(), axisVar);
  660. }
  661. else if (control == _rotationSpeedMin)
  662. {
  663. emitter->setRotation(_rotationSpeedMin->getValue(), emitter->getRotationSpeedMax(), emitter->getRotationAxis(), emitter->getRotationAxisVariance());
  664. }
  665. else if (control == _rotationSpeedMax)
  666. {
  667. emitter->setRotation(emitter->getRotationSpeedMin(), _rotationSpeedMax->getValue(), emitter->getRotationAxis(), emitter->getRotationAxisVariance());
  668. }
  669. else if (control == _burstSize)
  670. {
  671. char txt[25];
  672. sprintf(txt, "Burst Size\n\n%.0f", _burstSize->getValue());
  673. _burstSize->setText(txt);
  674. }
  675. else if (control == _started)
  676. {
  677. if (_started->isChecked())
  678. {
  679. emitter->start();
  680. }
  681. else
  682. {
  683. emitter->stop();
  684. }
  685. }
  686. else if (control == _vsync)
  687. {
  688. Game::getInstance()->setVsync(_vsync->isChecked());
  689. }
  690. else if (id == "additive")
  691. {
  692. if (((RadioButton*)control)->isSelected())
  693. emitter->setTextureBlending(ParticleEmitter::BLEND_ADDITIVE);
  694. }
  695. else if (id == "transparent")
  696. {
  697. if (((RadioButton*)control)->isSelected())
  698. emitter->setTextureBlending(ParticleEmitter::BLEND_TRANSPARENT);
  699. }
  700. else if (id == "multiply")
  701. {
  702. if (((RadioButton*)control)->isSelected())
  703. emitter->setTextureBlending(ParticleEmitter::BLEND_MULTIPLIED);
  704. }
  705. else if (id == "opaque")
  706. {
  707. if (((RadioButton*)control)->isSelected())
  708. emitter->setTextureBlending(ParticleEmitter::BLEND_OPAQUE);
  709. }
  710. break;
  711. case Listener::CLICK:
  712. if (control == _reset)
  713. {
  714. // Re-load the current emitter and reset the view
  715. _particleEmitter = ParticleEmitter::create(_url.c_str());
  716. emitterChanged();
  717. }
  718. else if (control == _emit)
  719. {
  720. // Emit a burst of particles.
  721. unsigned int burstSize = (unsigned int)_burstSize->getValue();
  722. emitter->emitOnce(burstSize);
  723. }
  724. else if (id == "sprite")
  725. {
  726. updateTexture();
  727. }
  728. else if (id == "updateFrames")
  729. {
  730. updateFrames();
  731. }
  732. break;
  733. case Listener::PRESS:
  734. if (control == _zoomIn)
  735. {
  736. _wDown = true;
  737. }
  738. else if (control == _zoomOut)
  739. {
  740. _sDown = true;
  741. }
  742. break;
  743. case Listener::RELEASE:
  744. if (control == _zoomIn)
  745. {
  746. _wDown = false;
  747. }
  748. else if (control == _zoomOut)
  749. {
  750. _sDown = false;
  751. }
  752. else if (control == _save)
  753. {
  754. Game::getInstance()->pause();
  755. saveFile();
  756. Game::getInstance()->resume();
  757. }
  758. else if (control == _load)
  759. {
  760. Game::getInstance()->pause();
  761. std::string filename = openFile("Select Particle File", "Particle Files", "particle");
  762. if (filename.length() > 0)
  763. {
  764. _url = filename;
  765. _particleEmitter = ParticleEmitter::create(_url.c_str());
  766. emitterChanged();
  767. }
  768. Game::getInstance()->resume();
  769. }
  770. break;
  771. }
  772. }
  773. void ParticlesGame::updateFrames()
  774. {
  775. Texture* texture = _particleEmitter->getTexture();
  776. TextBox* cBox = (TextBox*)_form->getControl("frameCount");
  777. TextBox* wBox = (TextBox*)_form->getControl("frameWidth");
  778. TextBox* hBox = (TextBox*)_form->getControl("frameHeight");
  779. unsigned int fc = (unsigned int)atoi(cBox->getText());
  780. unsigned int w = (unsigned int)atoi(wBox->getText());
  781. unsigned int h = (unsigned int)atoi(hBox->getText());
  782. if (fc > 0 && fc < 256 && fc < 1000 && w > 0 && h > 0 && w < 4096 && h < 4096)
  783. {
  784. if (w > _particleEmitter->getTexture()->getWidth())
  785. {
  786. wBox->setText(toString(texture->getWidth()).c_str());
  787. }
  788. if (h > texture->getHeight())
  789. {
  790. hBox->setText(toString(texture->getHeight()).c_str());
  791. }
  792. _particleEmitter->setSpriteFrameCoords(fc, w, h);
  793. }
  794. }
  795. void ParticlesGame::finalize()
  796. {
  797. SAFE_RELEASE(_scene);
  798. SAFE_RELEASE(_form);
  799. SAFE_RELEASE(_font);
  800. SAFE_RELEASE(_particleEmitter);
  801. }
  802. void ParticlesGame::update(float elapsedTime)
  803. {
  804. // Update camera movement
  805. if (_wDown)
  806. {
  807. Vector3 v = _scene->getActiveCamera()->getNode()->getForwardVector();
  808. v.normalize();
  809. v.scale(INPUT_SENSITIVITY * elapsedTime);
  810. _scene->getActiveCamera()->getNode()->translate(v);
  811. }
  812. if (_aDown)
  813. {
  814. Vector3 v = _scene->getActiveCamera()->getNode()->getLeftVector();
  815. v.normalize();
  816. v.scale(INPUT_SENSITIVITY * elapsedTime);
  817. _scene->getActiveCamera()->getNode()->translate(v);
  818. }
  819. if (_sDown)
  820. {
  821. Vector3 v = _scene->getActiveCamera()->getNode()->getBackVector();
  822. v.normalize();
  823. v.scale(INPUT_SENSITIVITY * elapsedTime);
  824. _scene->getActiveCamera()->getNode()->translate(v);
  825. }
  826. if (_dDown)
  827. {
  828. Vector3 v = _scene->getActiveCamera()->getNode()->getRightVector();
  829. v.normalize();
  830. v.scale(INPUT_SENSITIVITY * elapsedTime);
  831. _scene->getActiveCamera()->getNode()->translate(v);
  832. }
  833. // Update particles.
  834. _particleEmitterNode->getParticleEmitter()->update(elapsedTime);
  835. }
  836. void ParticlesGame::render(float elapsedTime)
  837. {
  838. // Clear the color and depth buffers.
  839. clear(CLEAR_COLOR_DEPTH, BACKGROUND_COLOR, 1.0f, 0);
  840. // Visit all the nodes in the scene for drawing.
  841. _scene->visit(this, &ParticlesGame::drawScene, (void*)0);
  842. // Draw the UI.
  843. _form->draw();
  844. // Draw the framerate and number of live particles.
  845. drawFrameRate(_font, Vector4(1, 1, 1, 1), 170, 40, getFrameRate());
  846. }
  847. bool ParticlesGame::drawScene(Node* node, void* cookie)
  848. {
  849. if (node->getModel())
  850. node->getModel()->draw();
  851. if (node->getParticleEmitter())
  852. node->getParticleEmitter()->draw();
  853. return true;
  854. }
  855. bool ParticlesGame::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
  856. {
  857. switch (evt)
  858. {
  859. case Mouse::MOUSE_PRESS_MIDDLE_BUTTON:
  860. Game::getInstance()->setMouseCaptured(true);
  861. _panning = true;
  862. return true;
  863. case Mouse::MOUSE_RELEASE_MIDDLE_BUTTON:
  864. Game::getInstance()->setMouseCaptured(false);
  865. _panning = false;
  866. return true;
  867. case Mouse::MOUSE_PRESS_LEFT_BUTTON:
  868. Game::getInstance()->setMouseCaptured(true);
  869. _rotating = true;
  870. return true;
  871. case Mouse::MOUSE_RELEASE_LEFT_BUTTON:
  872. Game::getInstance()->setMouseCaptured(false);
  873. _rotating = false;
  874. return true;
  875. case Mouse::MOUSE_PRESS_RIGHT_BUTTON:
  876. Game::getInstance()->setMouseCaptured(true);
  877. _zooming = true;
  878. return true;
  879. case Mouse::MOUSE_RELEASE_RIGHT_BUTTON:
  880. Game::getInstance()->setMouseCaptured(false);
  881. _zooming = false;
  882. return true;
  883. case Mouse::MOUSE_MOVE:
  884. if (_panning)
  885. {
  886. Vector3 n(-(float)x * PANNING_SENSITIVITY, (float)y * PANNING_SENSITIVITY, 0);
  887. _cameraParent->getMatrix().transformVector(&n);
  888. _cameraParent->translate(n);
  889. return true;
  890. }
  891. else if (_rotating)
  892. {
  893. _cameraParent->rotateY(-MATH_DEG_TO_RAD((float)x * ROTATE_SENSITIVITY));
  894. _cameraParent->rotateX(-MATH_DEG_TO_RAD((float)y * ROTATE_SENSITIVITY));
  895. return true;
  896. }
  897. else if (_zooming)
  898. {
  899. Vector3 v = _scene->getActiveCamera()->getNode()->getForwardVector();
  900. v.normalize();
  901. v.scale((float)(x-y) * INPUT_SENSITIVITY);
  902. _scene->getActiveCamera()->getNode()->translate(v);
  903. return true;
  904. }
  905. break;
  906. }
  907. return true;
  908. }
  909. void ParticlesGame::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  910. {
  911. // Touch events that don't hit the UI
  912. // allow the camera to rotate around the particle emitter.
  913. switch (evt)
  914. {
  915. case Touch::TOUCH_PRESS:
  916. _touched = true;
  917. _prevX = x;
  918. _prevY = y;
  919. break;
  920. case Touch::TOUCH_RELEASE:
  921. _touched = false;
  922. break;
  923. case Touch::TOUCH_MOVE:
  924. {
  925. if (_touched)
  926. {
  927. int deltaX = x - _prevX;
  928. int deltaY = y - _prevY;
  929. _prevX = x;
  930. _prevY = y;
  931. _cameraParent->rotateY(MATH_DEG_TO_RAD(deltaX * -0.5f));
  932. _cameraParent->rotateX(MATH_DEG_TO_RAD(deltaY * -0.5f));
  933. }
  934. }
  935. break;
  936. default:
  937. break;
  938. };
  939. }
  940. void ParticlesGame::keyEvent(Keyboard::KeyEvent evt, int key)
  941. {
  942. switch(evt)
  943. {
  944. case Keyboard::KEY_PRESS:
  945. switch (key)
  946. {
  947. case Keyboard::KEY_ESCAPE:
  948. exit();
  949. break;
  950. case Keyboard::KEY_B:
  951. // Disable blending.
  952. _particleEmitterNode->getParticleEmitter()->setTextureBlending(ParticleEmitter::BLEND_OPAQUE);
  953. break;
  954. case Keyboard::KEY_W:
  955. _wDown = true;
  956. break;
  957. case Keyboard::KEY_A:
  958. _aDown = true;
  959. break;
  960. case Keyboard::KEY_S:
  961. _sDown = true;
  962. break;
  963. case Keyboard::KEY_D:
  964. _dDown = true;
  965. break;
  966. }
  967. break;
  968. case Keyboard::KEY_RELEASE:
  969. switch (key)
  970. {
  971. case Keyboard::KEY_W:
  972. _wDown = false;
  973. break;
  974. case Keyboard::KEY_A:
  975. _aDown = false;
  976. break;
  977. case Keyboard::KEY_S:
  978. _sDown = false;
  979. break;
  980. case Keyboard::KEY_D:
  981. _dDown = false;
  982. break;
  983. }
  984. break;
  985. }
  986. }
  987. void ParticlesGame::loadEmitters()
  988. {
  989. // Load the default particle emitter
  990. _url = DEFAULT_PARTICLE_EMITTER;
  991. _particleEmitter = ParticleEmitter::create(_url.c_str());
  992. _particleEmitterNode = _scene->addNode("Particle Emitter");
  993. _particleEmitterNode->setTranslation(0.0f, 0.0f, 0.0f);
  994. emitterChanged();
  995. }
  996. void ParticlesGame::emitterChanged()
  997. {
  998. ParticleEmitter* emitter = _particleEmitter;
  999. // Set the new emitter on the node.
  1000. _particleEmitterNode->setParticleEmitter(_particleEmitter);
  1001. _particleEmitter->release();
  1002. // Reset camera view and zoom.
  1003. _scene->getActiveCamera()->getNode()->setTranslation(0.0f, 0.0f, 40.0f);
  1004. _cameraParent->setIdentity();
  1005. _particleEmitterNode->setIdentity();
  1006. // Set the values of UI controls to display the new emitter's settings.
  1007. _startRed->setValue(emitter->getColorStart().x);
  1008. _startGreen->setValue(emitter->getColorStart().y);
  1009. _startBlue->setValue(emitter->getColorStart().z);
  1010. _startAlpha->setValue(emitter->getColorStart().w);
  1011. _endRed->setValue(emitter->getColorEnd().x);
  1012. _endGreen->setValue(emitter->getColorEnd().y);
  1013. _endBlue->setValue(emitter->getColorEnd().z);
  1014. _endAlpha->setValue(emitter->getColorEnd().w);
  1015. _startMin->setValue(emitter->getSizeStartMin());
  1016. _startMax->setValue(emitter->getSizeStartMax());
  1017. _endMin->setValue(emitter->getSizeEndMin());
  1018. _endMax->setValue(emitter->getSizeEndMax());
  1019. _energyMin->setValue(emitter->getEnergyMin());
  1020. _energyMax->setValue(emitter->getEnergyMax());
  1021. _emissionRate->setValue(emitter->getEmissionRate());
  1022. char txt[25];
  1023. sprintf(txt, "Burst Size\n\n%.0f", _burstSize->getValue());
  1024. _burstSize->setText(txt);
  1025. const Vector3& posVar = emitter->getPositionVariance();
  1026. _posVarX->setValue(posVar.x);
  1027. _posVarY->setValue(posVar.y);
  1028. _posVarZ->setValue(posVar.z);
  1029. const Vector3& vel = emitter->getVelocity();
  1030. _velX->setValue(vel.x);
  1031. _velY->setValue(vel.y);
  1032. _velZ->setValue(vel.z);
  1033. const Vector3& velVar = emitter->getVelocityVariance();
  1034. _velVarX->setValue(velVar.x);
  1035. _velVarY->setValue(velVar.y);
  1036. _velVarZ->setValue(velVar.z);
  1037. const Vector3& accel = emitter->getAcceleration();
  1038. _accelX->setValue(accel.x);
  1039. _accelY->setValue(accel.y);
  1040. _accelZ->setValue(accel.z);
  1041. const Vector3& accelVar = emitter->getAccelerationVariance();
  1042. _accelVarX->setValue(accelVar.x);
  1043. _accelVarY->setValue(accelVar.y);
  1044. _accelVarZ->setValue(accelVar.z);
  1045. _spinSpeedMin->setValue(emitter->getRotationPerParticleSpeedMin());
  1046. _spinSpeedMax->setValue(emitter->getRotationPerParticleSpeedMax());
  1047. const Vector3& axis = emitter->getRotationAxis();
  1048. _axisX->setValue(axis.x);
  1049. _axisY->setValue(axis.y);
  1050. _axisZ->setValue(axis.z);
  1051. const Vector3& axisVar = emitter->getRotationAxisVariance();
  1052. _axisVarX->setValue(axisVar.x);
  1053. _axisVarY->setValue(axisVar.y);
  1054. _axisVarZ->setValue(axisVar.z);
  1055. _rotationSpeedMin->setValue(emitter->getRotationSpeedMin());
  1056. _rotationSpeedMax->setValue(emitter->getRotationSpeedMax());
  1057. // Update our image control
  1058. updateImageControl();
  1059. // Parse editor section of particle properties
  1060. Properties* p = Properties::create(_url.c_str());
  1061. Properties* ns = p->getNamespace("editor", true);
  1062. if (ns)
  1063. {
  1064. Vector3 v3;
  1065. if (ns->getVector3("cameraTranslation", &v3))
  1066. {
  1067. _cameraParent->setTranslation(v3);
  1068. }
  1069. if (ns->getVector3("cameraZoom", &v3))
  1070. {
  1071. _scene->getActiveCamera()->getNode()->setTranslation(v3);
  1072. }
  1073. Quaternion q;
  1074. if (ns->getQuaternionFromAxisAngle("cameraRotation", &q))
  1075. {
  1076. _cameraParent->setRotation(q);
  1077. }
  1078. float f;
  1079. if ((f = ns->getFloat("sizeMax")) != 0.0f)
  1080. {
  1081. _startMin->setMax(f);
  1082. _startMax->setMax(f);
  1083. _endMin->setMax(f);
  1084. _endMax->setMax(f);
  1085. }
  1086. if ((f = ns->getFloat("energyMax")) != 0.0f)
  1087. {
  1088. _energyMin->setMax(f);
  1089. _energyMax->setMax(f);
  1090. }
  1091. }
  1092. SAFE_DELETE(p);
  1093. // Start the emitter
  1094. emitter->start();
  1095. }
  1096. void ParticlesGame::drawSplash(void* param)
  1097. {
  1098. clear(CLEAR_COLOR_DEPTH, Vector4(0, 0, 0, 1), 1.0f, 0);
  1099. SpriteBatch* batch = SpriteBatch::create("res/logo_powered_white.png");
  1100. batch->start();
  1101. batch->draw(this->getWidth() * 0.5f, this->getHeight() * 0.5f, 0.0f, 512.0f, 512.0f, 0.0f, 1.0f, 1.0f, 0.0f, Vector4::one(), true);
  1102. batch->finish();
  1103. SAFE_DELETE(batch);
  1104. }
  1105. void ParticlesGame::drawFrameRate(Font* font, const Vector4& color, unsigned int x, unsigned int y, unsigned int fps)
  1106. {
  1107. char buffer[30];
  1108. sprintf(buffer, "FPS: %u\nParticles: %u", fps, _particleEmitterNode->getParticleEmitter()->getParticlesCount());
  1109. font->start();
  1110. font->drawText(buffer, x, y, color, 22);
  1111. font->finish();
  1112. }
  1113. void ParticlesGame::resizeEvent(unsigned int width, unsigned int height)
  1114. {
  1115. setViewport(gameplay::Rectangle(width, height));
  1116. _form->setSize(width, height);
  1117. _scene->getActiveCamera()->setAspectRatio((float)getWidth() / (float)getHeight());
  1118. }
  1119. void ParticlesGame::updateTexture()
  1120. {
  1121. std::string file = openFile("Select Texture", "PNG Files", "png");
  1122. if (file.length() > 0)
  1123. {
  1124. // Set new sprite on our emitter
  1125. _particleEmitter->setTexture(file.c_str(), _particleEmitter->getTextureBlending());
  1126. // Update the UI to display the new sprite
  1127. updateImageControl();
  1128. }
  1129. }
  1130. void ParticlesGame::updateImageControl()
  1131. {
  1132. ((ImageControl*)_form->getControl("sprite"))->setImage(_particleEmitter->getTexture()->getPath());
  1133. // Resize the image control so keep it to scale
  1134. int w = _particleEmitter->getTexture()->getWidth();
  1135. int h = _particleEmitter->getTexture()->getHeight();
  1136. int max = w > h ? w : h;
  1137. if (max > 140)
  1138. {
  1139. float ratio = 140.0f / max;
  1140. w *= ratio;
  1141. h *= ratio;
  1142. }
  1143. ((ImageControl*)_form->getControl("sprite"))->setSize(w, h);
  1144. _form->getControl("image")->setHeight(h + _form->getControl("imageSettings")->getHeight() + 50);
  1145. ((TextBox*)_form->getControl("frameCount"))->setText(toString(_particleEmitter->getSpriteFrameCount()).c_str());
  1146. ((TextBox*)_form->getControl("frameWidth"))->setText(toString(_particleEmitter->getSpriteWidth()).c_str());
  1147. ((TextBox*)_form->getControl("frameHeight"))->setText(toString(_particleEmitter->getSpriteHeight()).c_str());
  1148. switch (_particleEmitter->getTextureBlending())
  1149. {
  1150. case ParticleEmitter::BLEND_ADDITIVE:
  1151. ((RadioButton*)_form->getControl("additive"))->setSelected(true);
  1152. break;
  1153. case ParticleEmitter::BLEND_MULTIPLIED:
  1154. ((RadioButton*)_form->getControl("multiply"))->setSelected(true);
  1155. break;
  1156. case ParticleEmitter::BLEND_OPAQUE:
  1157. ((RadioButton*)_form->getControl("opaque"))->setSelected(true);
  1158. break;
  1159. case ParticleEmitter::BLEND_TRANSPARENT:
  1160. ((RadioButton*)_form->getControl("transparent"))->setSelected(true);
  1161. break;
  1162. }
  1163. }