ZMLCCParticleSystem.cpp 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498
  1. /****************************************************************************
  2. Copyright (c) 2008-2010 Ricardo Quesada
  3. Copyright (c) 2010-2012 cocos2d-x.org
  4. Copyright (c) 2011 Zynga Inc.
  5. Copyright (c) 2013-2017 Chukong Technologies Inc.
  6. http://www.cocos2d-x.org
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. ****************************************************************************/
  23. // ideas taken from:
  24. // . The ocean spray in your face [Jeff Lander]
  25. // http://www.double.co.nz/dust/col0798.pdf
  26. // . Building an Advanced Particle System [John van der Burg]
  27. // http://www.gamasutra.com/features/20000623/vanderburg_01.htm
  28. // . LOVE game engine
  29. // http://love2d.org/
  30. //
  31. //
  32. // Radius mode support, from 71 squared
  33. // http://particledesigner.71squared.com/
  34. //
  35. // IMPORTANT: Particle Designer is supported by cocos2d, but
  36. // 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guaranteed in cocos2d,
  37. // cocos2d uses a another approach, but the results are almost identical.
  38. //
  39. #include "2d/ZMLCCParticleSystem.h"
  40. #include <string>
  41. #include "2d/CCParticleBatchNode.h"
  42. #include "renderer/CCTextureAtlas.h"
  43. #include "base/base64.h"
  44. #include "base/ZipUtils.h"
  45. #include "base/CCDirector.h"
  46. #include "base/CCProfiling.h"
  47. #include "base/ccUTF8.h"
  48. #include "renderer/CCTextureCache.h"
  49. #include "platform/CCFileUtils.h"
  50. #include "common/CocosConfig.h"
  51. using namespace std;
  52. NS_CC_BEGIN
  53. // ideas taken from:
  54. // . The ocean spray in your face [Jeff Lander]
  55. // http://www.double.co.nz/dust/col0798.pdf
  56. // . Building an Advanced Particle System [John van der Burg]
  57. // http://www.gamasutra.com/features/20000623/vanderburg_01.htm
  58. // . LOVE game engine
  59. // http://love2d.org/
  60. //
  61. //
  62. // Radius mode support, from 71 squared
  63. // http://particledesigner.71squared.com/
  64. //
  65. // IMPORTANT: Particle Designer is supported by cocos2d, but
  66. // 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guaranteed in cocos2d,
  67. // cocos2d uses a another approach, but the results are almost identical.
  68. //
  69. inline void normalize_point(float x, float y, zml_particle_point* out)
  70. {
  71. float n = x * x + y * y;
  72. // Already normalized.
  73. if (n == 1.0f)
  74. return;
  75. n = sqrt(n);
  76. // Too close to zero.
  77. if (n < MATH_TOLERANCE)
  78. return;
  79. n = 1.0f / n;
  80. out->x = x * n;
  81. out->y = y * n;
  82. }
  83. /**
  84. A more effect random number getter function, get from ejoy2d.
  85. */
  86. inline static float RANDOM_M11(unsigned int *seed) {
  87. *seed = *seed * 134775813 + 1;
  88. union {
  89. uint32_t d;
  90. float f;
  91. } u;
  92. u.d = (((uint32_t)(*seed) & 0x7fff) << 8) | 0x40000000;
  93. return u.f - 3.0f;
  94. }
  95. ZMLParticleData::ZMLParticleData()
  96. {
  97. memset(this, 0, sizeof(ZMLParticleData));
  98. }
  99. bool ZMLParticleData::init(int count)
  100. {
  101. maxCount = count;
  102. posx= (float*)malloc(count * sizeof(float));
  103. posy= (float*)malloc(count * sizeof(float));
  104. startPosX= (float*)malloc(count * sizeof(float));
  105. startPosY= (float*)malloc(count * sizeof(float));
  106. colorR= (float*)malloc(count * sizeof(float));
  107. colorG= (float*)malloc(count * sizeof(float));
  108. colorB= (float*)malloc(count * sizeof(float));
  109. colorA= (float*)malloc(count * sizeof(float));
  110. deltaColorR= (float*)malloc(count * sizeof(float));
  111. deltaColorG= (float*)malloc(count * sizeof(float));
  112. deltaColorB= (float*)malloc(count * sizeof(float));
  113. deltaColorA= (float*)malloc(count * sizeof(float));
  114. size= (float*)malloc(count * sizeof(float));
  115. deltaSize= (float*)malloc(count * sizeof(float));
  116. startSize= (float*)malloc(count * sizeof(float));
  117. deltaSizeAllLife= (float*)malloc(count * sizeof(float));
  118. rotation= (float*)malloc(count * sizeof(float));
  119. deltaRotation= (float*)malloc(count * sizeof(float));
  120. timeToLive= (float*)malloc(count * sizeof(float));
  121. life= (float*)malloc(count * sizeof(float));
  122. atlasIndex= (unsigned int*)malloc(count * sizeof(unsigned int));
  123. modeA.dirX= (float*)malloc(count * sizeof(float));
  124. modeA.dirY= (float*)malloc(count * sizeof(float));
  125. modeA.radialAccel= (float*)malloc(count * sizeof(float));
  126. modeA.tangentialAccel= (float*)malloc(count * sizeof(float));
  127. modeB.angle= (float*)malloc(count * sizeof(float));
  128. modeB.degreesPerSecond= (float*)malloc(count * sizeof(float));
  129. modeB.deltaRadius= (float*)malloc(count * sizeof(float));
  130. modeB.radius= (float*)malloc(count * sizeof(float));
  131. return posx && posy && startPosY && startPosX && colorR && colorG && colorB && colorA &&
  132. deltaColorR && deltaColorG && deltaColorB && deltaColorA && size && startSize && deltaSizeAllLife && deltaSize &&
  133. rotation && deltaRotation && timeToLive &&life && atlasIndex && modeA.dirX && modeA.dirY &&
  134. modeA.radialAccel && modeA.tangentialAccel && modeB.angle && modeB.degreesPerSecond &&
  135. modeB.deltaRadius && modeB.radius;
  136. }
  137. void ZMLParticleData::release()
  138. {
  139. CC_SAFE_FREE(posx);
  140. CC_SAFE_FREE(posy);
  141. CC_SAFE_FREE(startPosX);
  142. CC_SAFE_FREE(startPosY);
  143. CC_SAFE_FREE(colorR);
  144. CC_SAFE_FREE(colorG);
  145. CC_SAFE_FREE(colorB);
  146. CC_SAFE_FREE(colorA);
  147. CC_SAFE_FREE(deltaColorR);
  148. CC_SAFE_FREE(deltaColorG);
  149. CC_SAFE_FREE(deltaColorB);
  150. CC_SAFE_FREE(deltaColorA);
  151. CC_SAFE_FREE(size);
  152. CC_SAFE_FREE(deltaSize);
  153. CC_SAFE_FREE(startSize);
  154. CC_SAFE_FREE(deltaSizeAllLife);
  155. CC_SAFE_FREE(rotation);
  156. CC_SAFE_FREE(deltaRotation);
  157. CC_SAFE_FREE(timeToLive);
  158. CC_SAFE_FREE(life);
  159. CC_SAFE_FREE(atlasIndex);
  160. CC_SAFE_FREE(modeA.dirX);
  161. CC_SAFE_FREE(modeA.dirY);
  162. CC_SAFE_FREE(modeA.radialAccel);
  163. CC_SAFE_FREE(modeA.tangentialAccel);
  164. CC_SAFE_FREE(modeB.angle);
  165. CC_SAFE_FREE(modeB.degreesPerSecond);
  166. CC_SAFE_FREE(modeB.deltaRadius);
  167. CC_SAFE_FREE(modeB.radius);
  168. }
  169. Vector<ZMLCCParticleSystem*> ZMLCCParticleSystem::__allInstances;
  170. float ZMLCCParticleSystem::__totalParticleCountFactor = 1.0f;
  171. ZMLCCParticleSystem::ZMLCCParticleSystem()
  172. : _isBlendAdditive(false)
  173. , _isAutoRemoveOnFinish(false)
  174. , _plistFile("")
  175. , _elapsed(0)
  176. , _configName("")
  177. , _emitCounter(0)
  178. , _batchNode(nullptr)
  179. , _atlasIndex(0)
  180. , _transformSystemDirty(false)
  181. , _allocatedParticles(0)
  182. , _isActive(true)
  183. , _particleCount(0)
  184. , _duration(0)
  185. , _life(0)
  186. , _lifeVar(0)
  187. , _angle(0)
  188. , _angleVar(0)
  189. , _emitterMode(Mode::GRAVITY)
  190. , _startSize(0)
  191. , _startSizeVar(0)
  192. , _endSize(0)
  193. , _endSizeVar(0)
  194. , _startSpin(0)
  195. , _startSpinVar(0)
  196. , _endSpin(0)
  197. , _endSpinVar(0)
  198. , _emissionRate(0)
  199. ,_emitFirstFrameEnabled(false)
  200. , _totalParticles(0)
  201. , _texture(nullptr)
  202. , _blendFunc(BlendFunc::ALPHA_PREMULTIPLIED)
  203. , _opacityModifyRGB(false)
  204. , _yCoordFlipped(1)
  205. , _positionType(PositionType::FREE)
  206. , _paused(false)
  207. , _sourcePositionCompatible(true) // In the furture this member's default value maybe false or be removed.
  208. ,_isInitColor(false)
  209. ,_cbOnExit(nullptr)
  210. {
  211. modeA.gravity.setZero();
  212. modeA.speed = 0;
  213. modeA.speedVar = 0;
  214. modeA.tangentialAccel = 0;
  215. modeA.tangentialAccelVar = 0;
  216. modeA.radialAccel = 0;
  217. modeA.radialAccelVar = 0;
  218. modeA.rotationIsDir = false;
  219. modeB.startRadius = 0;
  220. modeB.startRadiusVar = 0;
  221. modeB.endRadius = 0;
  222. modeB.endRadiusVar = 0;
  223. modeB.rotatePerSecond = 0;
  224. modeB.rotatePerSecondVar = 0;
  225. }
  226. // implementation ZMLCCParticleSystem
  227. ZMLCCParticleSystem * ZMLCCParticleSystem::create(const std::string& plistFile)
  228. {
  229. ZMLCCParticleSystem *ret = new (std::nothrow) ZMLCCParticleSystem();
  230. if (ret && ret->initWithFile(plistFile))
  231. {
  232. ret->autorelease();
  233. return ret;
  234. }
  235. CC_SAFE_DELETE(ret);
  236. return ret;
  237. }
  238. ZMLCCParticleSystem* ZMLCCParticleSystem::createWithTotalParticles(int numberOfParticles)
  239. {
  240. ZMLCCParticleSystem *ret = new (std::nothrow) ZMLCCParticleSystem();
  241. if (ret && ret->initWithTotalParticles(numberOfParticles))
  242. {
  243. ret->autorelease();
  244. return ret;
  245. }
  246. CC_SAFE_DELETE(ret);
  247. return ret;
  248. }
  249. // static
  250. Vector<ZMLCCParticleSystem*>& ZMLCCParticleSystem::getAllZMLCCParticleSystems()
  251. {
  252. return __allInstances;
  253. }
  254. void ZMLCCParticleSystem::setTotalParticleCountFactor(float factor)
  255. {
  256. __totalParticleCountFactor = factor;
  257. }
  258. bool ZMLCCParticleSystem::init()
  259. {
  260. return initWithTotalParticles(150);
  261. }
  262. bool ZMLCCParticleSystem::initWithFile(const std::string& plistFile)
  263. {
  264. bool ret = false;
  265. _plName = plistFile;
  266. _plistFile = FileUtils::getInstance()->fullPathForFilename(plistFile);
  267. ValueMap dict = FileUtils::getInstance()->getValueMapFromFile(_plistFile);
  268. CCASSERT( !dict.empty(), "Particles: file not found");
  269. // FIXME: compute path from a path, should define a function somewhere to do it
  270. string listFilePath = plistFile;
  271. if (listFilePath.find('/') != string::npos)
  272. {
  273. listFilePath = listFilePath.substr(0, listFilePath.rfind('/') + 1);
  274. ret = this->initWithDictionary(dict, listFilePath);
  275. }
  276. else
  277. {
  278. ret = this->initWithDictionary(dict, "");
  279. }
  280. return ret;
  281. }
  282. bool ZMLCCParticleSystem::initWithDictionary(ValueMap& dictionary)
  283. {
  284. return initWithDictionary(dictionary, "");
  285. }
  286. bool ZMLCCParticleSystem::initWithDictionary(ValueMap& dictionary, const std::string& dirname)
  287. {
  288. bool ret = false;
  289. unsigned char *buffer = nullptr;
  290. unsigned char *deflated = nullptr;
  291. Image *image = nullptr;
  292. do
  293. {
  294. int maxParticles = dictionary["maxParticles"].asInt();
  295. // self, not super
  296. if(this->initWithTotalParticles(maxParticles))
  297. {
  298. // Emitter name in particle designer 2.0
  299. _configName = dictionary["configName"].asString();
  300. // angle
  301. _angle = dictionary["angle"].asFloat();
  302. _angleVar = dictionary["angleVariance"].asFloat();
  303. // duration
  304. _duration = dictionary["duration"].asFloat();
  305. // blend function
  306. if (!_configName.empty())
  307. {
  308. _blendFunc.src = dictionary["blendFuncSource"].asFloat();
  309. }
  310. else
  311. {
  312. _blendFunc.src = dictionary["blendFuncSource"].asInt();
  313. }
  314. _blendFunc.dst = dictionary["blendFuncDestination"].asInt();
  315. // color
  316. _startColor.r = dictionary["startColorRed"].asFloat();
  317. _startColor.g = dictionary["startColorGreen"].asFloat();
  318. _startColor.b = dictionary["startColorBlue"].asFloat();
  319. _startColor.a = dictionary["startColorAlpha"].asFloat();
  320. _startColorVar.r = dictionary["startColorVarianceRed"].asFloat();
  321. _startColorVar.g = dictionary["startColorVarianceGreen"].asFloat();
  322. _startColorVar.b = dictionary["startColorVarianceBlue"].asFloat();
  323. _startColorVar.a = dictionary["startColorVarianceAlpha"].asFloat();
  324. _endColor.r = dictionary["finishColorRed"].asFloat();
  325. _endColor.g = dictionary["finishColorGreen"].asFloat();
  326. _endColor.b = dictionary["finishColorBlue"].asFloat();
  327. _endColor.a = dictionary["finishColorAlpha"].asFloat();
  328. _endColorVar.r = dictionary["finishColorVarianceRed"].asFloat();
  329. _endColorVar.g = dictionary["finishColorVarianceGreen"].asFloat();
  330. _endColorVar.b = dictionary["finishColorVarianceBlue"].asFloat();
  331. _endColorVar.a = dictionary["finishColorVarianceAlpha"].asFloat();
  332. // particle size
  333. _startSize = dictionary["startParticleSize"].asFloat();
  334. _startSizeVar = dictionary["startParticleSizeVariance"].asFloat();
  335. _endSize = dictionary["finishParticleSize"].asFloat();
  336. _endSizeVar = dictionary["finishParticleSizeVariance"].asFloat();
  337. // position
  338. float x = dictionary["sourcePositionx"].asFloat();
  339. float y = dictionary["sourcePositiony"].asFloat();
  340. if(!_sourcePositionCompatible) {
  341. this->setSourcePosition(Vec2(x, y));
  342. }
  343. else {
  344. this->setPosition(Vec2(x, y));
  345. }
  346. _posVar.x = dictionary["sourcePositionVariancex"].asFloat();
  347. _posVar.y = dictionary["sourcePositionVariancey"].asFloat();
  348. // Spinning
  349. _startSpin = dictionary["rotationStart"].asFloat();
  350. _startSpinVar = dictionary["rotationStartVariance"].asFloat();
  351. _endSpin= dictionary["rotationEnd"].asFloat();
  352. _endSpinVar= dictionary["rotationEndVariance"].asFloat();
  353. _emitterMode = (Mode) dictionary["emitterType"].asInt();
  354. // Mode A: Gravity + tangential accel + radial accel
  355. if (_emitterMode == Mode::GRAVITY)
  356. {
  357. // gravity
  358. modeA.gravity.x = dictionary["gravityx"].asFloat();
  359. modeA.gravity.y = dictionary["gravityy"].asFloat();
  360. // speed
  361. modeA.speed = dictionary["speed"].asFloat();
  362. modeA.speedVar = dictionary["speedVariance"].asFloat();
  363. // radial acceleration
  364. modeA.radialAccel = dictionary["radialAcceleration"].asFloat();
  365. modeA.radialAccelVar = dictionary["radialAccelVariance"].asFloat();
  366. // tangential acceleration
  367. modeA.tangentialAccel = dictionary["tangentialAcceleration"].asFloat();
  368. modeA.tangentialAccelVar = dictionary["tangentialAccelVariance"].asFloat();
  369. // rotation is dir
  370. modeA.rotationIsDir = dictionary["rotationIsDir"].asBool();
  371. }
  372. // or Mode B: radius movement
  373. else if (_emitterMode == Mode::RADIUS)
  374. {
  375. if (!_configName.empty())
  376. {
  377. modeB.startRadius = dictionary["maxRadius"].asInt();
  378. }
  379. else
  380. {
  381. modeB.startRadius = dictionary["maxRadius"].asFloat();
  382. }
  383. modeB.startRadiusVar = dictionary["maxRadiusVariance"].asFloat();
  384. if (!_configName.empty())
  385. {
  386. modeB.endRadius = dictionary["minRadius"].asInt();
  387. }
  388. else
  389. {
  390. modeB.endRadius = dictionary["minRadius"].asFloat();
  391. }
  392. if (dictionary.find("minRadiusVariance") != dictionary.end())
  393. {
  394. modeB.endRadiusVar = dictionary["minRadiusVariance"].asFloat();
  395. }
  396. else
  397. {
  398. modeB.endRadiusVar = 0.0f;
  399. }
  400. if (!_configName.empty())
  401. {
  402. modeB.rotatePerSecond = dictionary["rotatePerSecond"].asInt();
  403. }
  404. else
  405. {
  406. modeB.rotatePerSecond = dictionary["rotatePerSecond"].asFloat();
  407. }
  408. modeB.rotatePerSecondVar = dictionary["rotatePerSecondVariance"].asFloat();
  409. } else {
  410. CCASSERT( false, "Invalid emitterType in config file");
  411. CC_BREAK_IF(true);
  412. }
  413. // life span
  414. _life = dictionary["particleLifespan"].asFloat();
  415. _lifeVar = dictionary["particleLifespanVariance"].asFloat();
  416. // emission Rate
  417. _emissionRate = _totalParticles / _life;
  418. //don't get the internal texture if a batchNode is used
  419. if (!_batchNode)
  420. {
  421. // Set a compatible default for the alpha transfer
  422. _opacityModifyRGB = false;
  423. // texture
  424. // Try to get the texture from the cache
  425. std::string textureName = dictionary["textureFileName"].asString();
  426. size_t rPos = textureName.rfind('/');
  427. if (rPos != string::npos)
  428. {
  429. string textureDir = textureName.substr(0, rPos + 1);
  430. if (!dirname.empty() && textureDir != dirname)
  431. {
  432. textureName = textureName.substr(rPos+1);
  433. textureName = dirname + textureName;
  434. }
  435. }
  436. else if (!dirname.empty() && !textureName.empty())
  437. {
  438. textureName = dirname + textureName;
  439. }
  440. //modify by djd 粒子支持plist大纹理,优先走大纹理找不到就走小图.
  441. Texture2D *tex = nullptr;
  442. SpriteFrame *tFrame = nullptr;
  443. if (!textureName.empty())
  444. {
  445. SpriteFrameCache * frameCache = SpriteFrameCache::getInstance();
  446. tFrame = frameCache->getSpriteFrameByName(textureName.c_str());
  447. // set not pop-up message box when load image failed
  448. bool notify = FileUtils::getInstance()->isPopupNotify();
  449. FileUtils::getInstance()->setPopupNotify(false);
  450. tex = Director::getInstance()->getTextureCache()->addImage(textureName);
  451. // reset the value of UIImage notify
  452. FileUtils::getInstance()->setPopupNotify(notify);
  453. }
  454. if (tFrame){
  455. bool isrotaed = tFrame->isRotated();
  456. Vec2 offset = tFrame->getOffset();
  457. Vec2 originalSize = tFrame->getOriginalSize();
  458. auto pointRect = tFrame->getRect();
  459. setTextureWithRect(tFrame->getTexture(), pointRect,isrotaed,offset,originalSize);
  460. }else if (tex)
  461. {
  462. setTexture(tex);
  463. }
  464. else if( dictionary.find("textureImageData") != dictionary.end() )
  465. {
  466. std::string textureData = dictionary.at("textureImageData").asString();
  467. CCASSERT(!textureData.empty(), "textureData can't be empty!");
  468. auto dataLen = textureData.size();
  469. if (dataLen != 0)
  470. {
  471. // if it fails, try to get it from the base64-gzipped data
  472. int decodeLen = base64Decode((unsigned char*)textureData.c_str(), (unsigned int)dataLen, &buffer);
  473. CCASSERT( buffer != nullptr, "CCZMLCCParticleSystem: error decoding textureImageData");
  474. CC_BREAK_IF(!buffer);
  475. ssize_t deflatedLen = ZipUtils::inflateMemory(buffer, decodeLen, &deflated);
  476. CCASSERT( deflated != nullptr, "CCZMLCCParticleSystem: error ungzipping textureImageData");
  477. CC_BREAK_IF(!deflated);
  478. // For android, we should retain it in VolatileTexture::addImage which invoked in Director::getInstance()->getTextureCache()->addUIImage()
  479. image = new (std::nothrow) Image();
  480. bool isOK = image->initWithImageData(deflated, deflatedLen);
  481. CCASSERT(isOK, "CCZMLCCParticleSystem: error init image with Data");
  482. CC_BREAK_IF(!isOK);
  483. setTexture(Director::getInstance()->getTextureCache()->addImage(image, _plistFile + textureName));
  484. image->release();
  485. }
  486. }
  487. _yCoordFlipped = dictionary.find("yCoordFlipped") == dictionary.end() ? 1 : dictionary.at("yCoordFlipped").asInt();
  488. if( !this->_texture)
  489. CCLOGWARN("cocos2d: Warning: ZMLCCParticleSystemQuad system without a texture");
  490. }
  491. ret = true;
  492. }
  493. } while (0);
  494. free(buffer);
  495. free(deflated);
  496. return ret;
  497. }
  498. bool ZMLCCParticleSystem::initWithTotalParticles(int numberOfParticles)
  499. {
  500. _totalParticles = numberOfParticles;
  501. _particleData.release();
  502. if( !_particleData.init(_totalParticles) )
  503. {
  504. CCLOG("Particle system: not enough memory");
  505. this->release();
  506. return false;
  507. }
  508. _allocatedParticles = numberOfParticles;
  509. if (_batchNode)
  510. {
  511. for (int i = 0; i < _totalParticles; i++)
  512. {
  513. _particleData.atlasIndex[i] = i;
  514. }
  515. }
  516. // default, active
  517. _isActive = true;
  518. // default blend function
  519. _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
  520. // default movement type;
  521. _positionType = PositionType::FREE;
  522. // by default be in mode A:
  523. _emitterMode = Mode::GRAVITY;
  524. // default: modulate
  525. // FIXME:: not used
  526. // colorModulate = YES;
  527. _isAutoRemoveOnFinish = false;
  528. // Optimization: compile updateParticle method
  529. //updateParticleSel = @selector(updateQuadWithParticle:newPosition:);
  530. //updateParticleImp = (CC_UPDATE_PARTICLE_IMP) [self methodForSelector:updateParticleSel];
  531. //for batchNode
  532. _transformSystemDirty = false;
  533. return true;
  534. }
  535. ZMLCCParticleSystem::~ZMLCCParticleSystem()
  536. {
  537. // Since the scheduler retains the "target (in this case the ZMLCCParticleSystem)
  538. // it is not needed to call "unscheduleUpdate" here. In fact, it will be called in "cleanup"
  539. //unscheduleUpdate();
  540. _particleData.release();
  541. CC_SAFE_RELEASE(_texture);
  542. }
  543. void ZMLCCParticleSystem::addParticles(int count)
  544. {
  545. if (_paused)
  546. return;
  547. uint32_t RANDSEED = rand();
  548. int start = _particleCount;
  549. _particleCount += count;
  550. //life
  551. for (int i = start; i < _particleCount ; ++i)
  552. {
  553. float theLife = _life + _lifeVar * RANDOM_M11(&RANDSEED);
  554. _particleData.timeToLive[i] = MAX(0, theLife);
  555. _particleData.life[i] = _particleData.timeToLive[i];
  556. }
  557. //position
  558. // if (_positionType == PositionType::FREE)
  559. // {
  560. // for (int i = start; i < _particleCount; ++i)
  561. // {
  562. // float x = _sourcePosition.x + _posVar.x * RANDOM_M11(&RANDSEED);
  563. // float y = _sourcePosition.y + _posVar.y * RANDOM_M11(&RANDSEED);
  564. // Vec2 pos = this->convertToWorldSpace(Vec2(x, y));
  565. // _particleData.posx[i] = pos.x;
  566. // _particleData.posy[i] = pos.y;
  567. // }
  568. // } else {
  569. for (int i = start; i < _particleCount; ++i)
  570. {
  571. _particleData.posx[i] = _sourcePosition.x + _posVar.x * RANDOM_M11(&RANDSEED);
  572. }
  573. for (int i = start; i < _particleCount; ++i)
  574. {
  575. _particleData.posy[i] = _sourcePosition.y + _posVar.y * RANDOM_M11(&RANDSEED);
  576. }
  577. // }
  578. //color
  579. #define SET_COLOR(c, b, v)\
  580. for (int i = start; i < _particleCount; ++i)\
  581. {\
  582. c[i] = clampf( b + v * RANDOM_M11(&RANDSEED) , 0 , 1 );\
  583. }
  584. SET_COLOR(_particleData.colorR, _startColor.r, _startColorVar.r);
  585. SET_COLOR(_particleData.colorG, _startColor.g, _startColorVar.g);
  586. SET_COLOR(_particleData.colorB, _startColor.b, _startColorVar.b);
  587. SET_COLOR(_particleData.colorA, _startColor.a, _startColorVar.a);
  588. SET_COLOR(_particleData.deltaColorR, _endColor.r, _endColorVar.r);
  589. SET_COLOR(_particleData.deltaColorG, _endColor.g, _endColorVar.g);
  590. SET_COLOR(_particleData.deltaColorB, _endColor.b, _endColorVar.b);
  591. SET_COLOR(_particleData.deltaColorA, _endColor.a, _endColorVar.a);
  592. #define SET_DELTA_COLOR(c, dc)\
  593. for (int i = start; i < _particleCount; ++i)\
  594. {\
  595. dc[i] = (dc[i] - c[i]) / _particleData.timeToLive[i];\
  596. }
  597. SET_DELTA_COLOR(_particleData.colorR, _particleData.deltaColorR);
  598. SET_DELTA_COLOR(_particleData.colorG, _particleData.deltaColorG);
  599. SET_DELTA_COLOR(_particleData.colorB, _particleData.deltaColorB);
  600. SET_DELTA_COLOR(_particleData.colorA, _particleData.deltaColorA);
  601. //size
  602. for (int i = start; i < _particleCount; ++i)
  603. {
  604. _particleData.size[i] = _startSize + _startSizeVar * RANDOM_M11(&RANDSEED);
  605. _particleData.size[i] = MAX(0, _particleData.size[i]);
  606. _particleData.startSize[i] = _particleData.size[i];
  607. }
  608. if (_endSize != START_SIZE_EQUAL_TO_END_SIZE)
  609. {
  610. for (int i = start; i < _particleCount; ++i)
  611. {
  612. float endSize = _endSize + _endSizeVar * RANDOM_M11(&RANDSEED);
  613. endSize = MAX(0, endSize);
  614. _particleData.deltaSize[i] = (endSize - _particleData.size[i]) / _particleData.timeToLive[i];
  615. _particleData.deltaSizeAllLife[i] = endSize - _particleData.size[i];
  616. }
  617. }
  618. else
  619. {
  620. for (int i = start; i < _particleCount; ++i)
  621. {
  622. _particleData.deltaSize[i] = 0.0f;
  623. }
  624. }
  625. // rotation
  626. for (int i = start; i < _particleCount; ++i)
  627. {
  628. _particleData.rotation[i] = _startSpin + _startSpinVar * RANDOM_M11(&RANDSEED);
  629. }
  630. for (int i = start; i < _particleCount; ++i)
  631. {
  632. float endA = _endSpin + _endSpinVar * RANDOM_M11(&RANDSEED);
  633. _particleData.deltaRotation[i] = (endA - _particleData.rotation[i]) / _particleData.timeToLive[i];
  634. }
  635. // position
  636. Vec2 pos;
  637. if (_positionType == PositionType::FREE)
  638. {
  639. pos = this->convertToWorldSpace(Vec2::ZERO);
  640. }
  641. else if (_positionType == PositionType::RELATIVE)
  642. {
  643. pos = _position;
  644. }
  645. for (int i = start; i < _particleCount; ++i)
  646. {
  647. _particleData.startPosX[i] = pos.x;
  648. }
  649. for (int i = start; i < _particleCount; ++i)
  650. {
  651. _particleData.startPosY[i] = pos.y;
  652. }
  653. // Mode Gravity: A
  654. if (_emitterMode == Mode::GRAVITY)
  655. {
  656. // radial accel
  657. for (int i = start; i < _particleCount; ++i)
  658. {
  659. _particleData.modeA.radialAccel[i] = modeA.radialAccel + modeA.radialAccelVar * RANDOM_M11(&RANDSEED);
  660. }
  661. // tangential accel
  662. for (int i = start; i < _particleCount; ++i)
  663. {
  664. _particleData.modeA.tangentialAccel[i] = modeA.tangentialAccel + modeA.tangentialAccelVar * RANDOM_M11(&RANDSEED);
  665. }
  666. // rotation is dir
  667. if( modeA.rotationIsDir )
  668. {
  669. for (int i = start; i < _particleCount; ++i)
  670. {
  671. float a = CC_DEGREES_TO_RADIANS( _angle + _angleVar * RANDOM_M11(&RANDSEED) );
  672. Vec2 v(cosf( a ), sinf( a ));
  673. float s = modeA.speed + modeA.speedVar * RANDOM_M11(&RANDSEED);
  674. Vec2 dir = v * s;
  675. _particleData.modeA.dirX[i] = dir.x;//v * s ;
  676. _particleData.modeA.dirY[i] = dir.y;
  677. _particleData.rotation[i] = -CC_RADIANS_TO_DEGREES(dir.getAngle());
  678. }
  679. }
  680. else
  681. {
  682. for (int i = start; i < _particleCount; ++i)
  683. {
  684. float a = CC_DEGREES_TO_RADIANS( _angle + _angleVar * RANDOM_M11(&RANDSEED) );
  685. Vec2 v(cosf( a ), sinf( a ));
  686. float s = modeA.speed + modeA.speedVar * RANDOM_M11(&RANDSEED);
  687. Vec2 dir = v * s;
  688. _particleData.modeA.dirX[i] = dir.x;//v * s ;
  689. _particleData.modeA.dirY[i] = dir.y;
  690. }
  691. }
  692. }
  693. // Mode Radius: B
  694. else
  695. {
  696. //Need to check by Jacky
  697. // Set the default diameter of the particle from the source position
  698. for (int i = start; i < _particleCount; ++i)
  699. {
  700. _particleData.modeB.radius[i] = modeB.startRadius + modeB.startRadiusVar * RANDOM_M11(&RANDSEED);
  701. }
  702. for (int i = start; i < _particleCount; ++i)
  703. {
  704. _particleData.modeB.angle[i] = CC_DEGREES_TO_RADIANS( _angle + _angleVar * RANDOM_M11(&RANDSEED));
  705. }
  706. for (int i = start; i < _particleCount; ++i)
  707. {
  708. _particleData.modeB.degreesPerSecond[i] = CC_DEGREES_TO_RADIANS(modeB.rotatePerSecond + modeB.rotatePerSecondVar * RANDOM_M11(&RANDSEED));
  709. }
  710. if(modeB.endRadius == START_RADIUS_EQUAL_TO_END_RADIUS)
  711. {
  712. for (int i = start; i < _particleCount; ++i)
  713. {
  714. _particleData.modeB.deltaRadius[i] = 0.0f;
  715. }
  716. }
  717. else
  718. {
  719. for (int i = start; i < _particleCount; ++i)
  720. {
  721. float endRadius = modeB.endRadius + modeB.endRadiusVar * RANDOM_M11(&RANDSEED);
  722. _particleData.modeB.deltaRadius[i] = (endRadius - _particleData.modeB.radius[i]) / _particleData.timeToLive[i];
  723. }
  724. }
  725. }
  726. }
  727. void ZMLCCParticleSystem::onEnter()
  728. {
  729. #if CC_ENABLE_SCRIPT_BINDING
  730. if (_scriptType == kScriptTypeJavascript)
  731. {
  732. if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnEnter))
  733. return;
  734. }
  735. #endif
  736. Node::onEnter();
  737. // update after action in run!
  738. this->scheduleUpdateWithPriority(1);
  739. __allInstances.pushBack(this);
  740. }
  741. void ZMLCCParticleSystem::onExit()
  742. {
  743. #if CC_ENABLE_SCRIPT_BINDING
  744. if (_scriptType == kScriptTypeJavascript)
  745. {
  746. if (ScriptEngineManager::sendNodeEventToJSExtended(this, kNodeOnExit))
  747. return;
  748. }
  749. #endif
  750. if (_cbOnExit != nullptr && _plName.size() > 0) {
  751. _cbOnExit(_plName, this);
  752. }
  753. this->unscheduleUpdate();
  754. Node::onExit();
  755. auto iter = std::find(std::begin(__allInstances), std::end(__allInstances), this);
  756. if (iter != std::end(__allInstances))
  757. {
  758. __allInstances.erase(iter);
  759. }
  760. }
  761. void ZMLCCParticleSystem::stopSystem()
  762. {
  763. _isActive = false;
  764. _elapsed = _duration;
  765. _emitCounter = 0;
  766. }
  767. void ZMLCCParticleSystem::setVisible(bool visible)
  768. {
  769. // if (CocosConfig::getParticleVisibleReset()) {
  770. if (visible != _visible) {
  771. if (visible) this->resetSystem();
  772. else this->stopSystem();
  773. }
  774. // }
  775. Node::setVisible(visible);
  776. }
  777. void ZMLCCParticleSystem::setVisibleOnly(bool visible){
  778. Node::setVisible(visible);
  779. }
  780. //add by djd
  781. void ZMLCCParticleSystem::updateDisplayedOpacity(GLubyte opacity){
  782. Node::updateDisplayedOpacity(opacity);
  783. if (!CocosConfig::getParticleOpacity()) {
  784. return;
  785. }
  786. if (!_isInitColor) {
  787. _initStartColor = getStartColor();
  788. _initStartColorVar = getStartColorVar();
  789. _initEndColor = getEndColor();
  790. _initEndColorVar = getEndColorVar();
  791. _initBlendFunc = _blendFunc;
  792. _isInitColor = true;
  793. }
  794. if (opacity < 100) {
  795. _blendFunc = BlendFunc::ADDITIVE;
  796. }else{
  797. _blendFunc = _initBlendFunc;
  798. }
  799. setStartColor(Color4F(_initStartColor.r* opacity/255, _initStartColor.g* opacity/255, _initStartColor.b* opacity/255, _initStartColor.a ));
  800. setStartColorVar(Color4F(_initStartColorVar.r* opacity/255, _initStartColorVar.g* opacity/255, _initStartColorVar.b* opacity/255, _initStartColorVar.a));
  801. setEndColor(Color4F(_initEndColor.r* opacity/255, _initEndColor.g* opacity/255, _initEndColor.b* opacity/255, _initEndColor.a));
  802. setEndColorVar(Color4F(_initEndColorVar.r* opacity/255, _initEndColorVar.g* opacity/255, _initEndColorVar.b* opacity/255, _initEndColorVar.a));
  803. }
  804. void ZMLCCParticleSystem::resetSystem()
  805. {
  806. _isActive = true;
  807. _elapsed = 0;
  808. for (int i = 0; i < _particleCount; ++i)
  809. {
  810. _particleData.timeToLive[i] = 0.0f;
  811. }
  812. }
  813. bool ZMLCCParticleSystem::isFull()
  814. {
  815. return (_particleCount == _totalParticles);
  816. }
  817. // ZMLCCParticleSystem - MainLoop
  818. void ZMLCCParticleSystem::update(float dt)
  819. {
  820. CC_PROFILER_START_CATEGORY(kProfilerCategoryParticles , "CCZMLCCParticleSystem - update");
  821. if(CocosConfig::isParticleUpdateOptimize() == false || _visible == true){
  822. if (_isActive && _emissionRate)
  823. {
  824. float rate = 1.0f / _emissionRate;
  825. int totalParticles = static_cast<int>(_totalParticles * __totalParticleCountFactor);
  826. //issue #1201, prevent bursts of particles, due to too high emitCounter
  827. if (_particleCount < totalParticles)
  828. {
  829. _emitCounter += dt;
  830. if (_emitCounter < 0.f)
  831. _emitCounter = 0.f;
  832. }
  833. int emitCount = MIN(totalParticles - _particleCount, _emitCounter / rate);
  834. addParticles(emitCount);
  835. _emitCounter -= rate * emitCount;
  836. _elapsed += dt;
  837. if (_elapsed < 0.f)
  838. _elapsed = 0.f;
  839. if (_duration != DURATION_INFINITY && _duration < _elapsed)
  840. {
  841. this->stopSystem();
  842. }
  843. }
  844. {
  845. for (int i = 0; i < _particleCount; ++i)
  846. {
  847. _particleData.timeToLive[i] -= dt;
  848. }
  849. for (int i = 0; i < _particleCount; ++i)
  850. {
  851. if (_particleData.timeToLive[i] <= 0.0f)
  852. {
  853. int j = _particleCount - 1;
  854. while (j > 0 && _particleData.timeToLive[j] <= 0)
  855. {
  856. _particleCount--;
  857. j--;
  858. }
  859. _particleData.copyParticle(i, _particleCount - 1);
  860. if (_batchNode)
  861. {
  862. //disable the switched particle
  863. int currentIndex = _particleData.atlasIndex[i];
  864. _batchNode->disableParticle(_atlasIndex + currentIndex);
  865. //switch indexes
  866. _particleData.atlasIndex[_particleCount - 1] = currentIndex;
  867. }
  868. --_particleCount;
  869. if( _particleCount == 0 && _isAutoRemoveOnFinish )
  870. {
  871. this->unscheduleUpdate();
  872. _parent->removeChild(this, true);
  873. return;
  874. }
  875. }
  876. }
  877. if (_emitterMode == Mode::GRAVITY)
  878. {
  879. for (int i = 0 ; i < _particleCount; ++i)
  880. {
  881. zml_particle_point tmp, radial = {0.0f, 0.0f}, tangential;
  882. // radial acceleration
  883. if (_particleData.posx[i] || _particleData.posy[i])
  884. {
  885. normalize_point(_particleData.posx[i], _particleData.posy[i], &radial);
  886. }
  887. tangential = radial;
  888. radial.x *= _particleData.modeA.radialAccel[i];
  889. radial.y *= _particleData.modeA.radialAccel[i];
  890. // tangential acceleration
  891. std::swap(tangential.x, tangential.y);
  892. tangential.x *= - _particleData.modeA.tangentialAccel[i];
  893. tangential.y *= _particleData.modeA.tangentialAccel[i];
  894. // (gravity + radial + tangential) * dt
  895. tmp.x = radial.x + tangential.x + modeA.gravity.x;
  896. tmp.y = radial.y + tangential.y + modeA.gravity.y;
  897. tmp.x *= dt;
  898. tmp.y *= dt;
  899. _particleData.modeA.dirX[i] += tmp.x;
  900. _particleData.modeA.dirY[i] += tmp.y;
  901. // this is cocos2d-x v3.0
  902. // if (_configName.length()>0 && _yCoordFlipped != -1)
  903. // this is cocos2d-x v3.0
  904. tmp.x = _particleData.modeA.dirX[i] * dt * _yCoordFlipped;
  905. tmp.y = _particleData.modeA.dirY[i] * dt * _yCoordFlipped;
  906. _particleData.posx[i] += tmp.x;
  907. _particleData.posy[i] += tmp.y;
  908. }
  909. }
  910. else
  911. {
  912. //Why use so many for-loop separately instead of putting them together?
  913. //When the processor needs to read from or write to a location in memory,
  914. //it first checks whether a copy of that data is in the cache.
  915. //And every property's memory of the particle system is continuous,
  916. //for the purpose of improving cache hit rate, we should process only one property in one for-loop AFAP.
  917. //It was proved to be effective especially for low-end machine.
  918. for (int i = 0; i < _particleCount; ++i)
  919. {
  920. _particleData.modeB.angle[i] += _particleData.modeB.degreesPerSecond[i] * dt;
  921. }
  922. for (int i = 0; i < _particleCount; ++i)
  923. {
  924. _particleData.modeB.radius[i] += _particleData.modeB.deltaRadius[i] * dt;
  925. }
  926. for (int i = 0; i < _particleCount; ++i)
  927. {
  928. _particleData.posx[i] = - cosf(_particleData.modeB.angle[i]) * _particleData.modeB.radius[i];
  929. }
  930. for (int i = 0; i < _particleCount; ++i)
  931. {
  932. _particleData.posy[i] = - sinf(_particleData.modeB.angle[i]) * _particleData.modeB.radius[i] * _yCoordFlipped;
  933. }
  934. }
  935. //color r,g,b,a
  936. for (int i = 0 ; i < _particleCount; ++i)
  937. {
  938. _particleData.colorR[i] += _particleData.deltaColorR[i] * dt;
  939. }
  940. for (int i = 0 ; i < _particleCount; ++i)
  941. {
  942. _particleData.colorG[i] += _particleData.deltaColorG[i] * dt;
  943. }
  944. for (int i = 0 ; i < _particleCount; ++i)
  945. {
  946. _particleData.colorB[i] += _particleData.deltaColorB[i] * dt;
  947. }
  948. for (int i = 0 ; i < _particleCount; ++i)
  949. {
  950. _particleData.colorA[i] += _particleData.deltaColorA[i] * dt;
  951. }
  952. //size
  953. for (int i = 0 ; i < _particleCount; ++i)
  954. {
  955. _particleData.size[i] += (_particleData.deltaSize[i] * dt);
  956. _particleData.size[i] = MAX(0, _particleData.size[i]);
  957. }
  958. //angle
  959. for (int i = 0 ; i < _particleCount; ++i)
  960. {
  961. _particleData.rotation[i] += _particleData.deltaRotation[i] * dt;
  962. }
  963. updateParticleQuads();
  964. _transformSystemDirty = false;
  965. }
  966. }
  967. // only update gl buffer when visible
  968. if (_visible && ! _batchNode)
  969. {
  970. postStep();
  971. }
  972. CC_PROFILER_STOP_CATEGORY(kProfilerCategoryParticles , "CCZMLCCParticleSystem - update");
  973. }
  974. void ZMLCCParticleSystem::updateWithNoTime(void)
  975. {
  976. this->update(0.0f);
  977. }
  978. void ZMLCCParticleSystem::updateParticleQuads()
  979. {
  980. //should be overridden
  981. }
  982. void ZMLCCParticleSystem::postStep()
  983. {
  984. // should be overridden
  985. }
  986. // ZMLCCParticleSystem - Texture protocol
  987. void ZMLCCParticleSystem::setTexture(Texture2D* var)
  988. {
  989. if (_texture != var)
  990. {
  991. CC_SAFE_RETAIN(var);
  992. CC_SAFE_RELEASE(_texture);
  993. _texture = var;
  994. updateBlendFunc();
  995. }
  996. }
  997. void ZMLCCParticleSystem::setTextureWithRect(Texture2D *texture, const Rect& rect, bool isrotated, Vec2& offset, Vec2 &originalSize){
  998. setTexture(texture);
  999. }
  1000. void ZMLCCParticleSystem::updateBlendFunc()
  1001. {
  1002. CCASSERT(! _batchNode, "Can't change blending functions when the particle is being batched");
  1003. if(_texture)
  1004. {
  1005. bool premultiplied = _texture->hasPremultipliedAlpha();
  1006. _opacityModifyRGB = false;
  1007. if( _texture && ( _blendFunc.src == CC_BLEND_SRC && _blendFunc.dst == CC_BLEND_DST ) )
  1008. {
  1009. if( premultiplied )
  1010. {
  1011. _opacityModifyRGB = true;
  1012. }
  1013. else
  1014. {
  1015. _blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED;
  1016. }
  1017. }
  1018. }
  1019. }
  1020. Texture2D * ZMLCCParticleSystem::getTexture() const
  1021. {
  1022. return _texture;
  1023. }
  1024. // ZMLCCParticleSystem - Additive Blending
  1025. void ZMLCCParticleSystem::setBlendAdditive(bool additive)
  1026. {
  1027. if( additive )
  1028. {
  1029. _blendFunc = BlendFunc::ADDITIVE;
  1030. }
  1031. else
  1032. {
  1033. if( _texture && ! _texture->hasPremultipliedAlpha() )
  1034. _blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED;
  1035. else
  1036. _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
  1037. }
  1038. }
  1039. bool ZMLCCParticleSystem::isBlendAdditive() const
  1040. {
  1041. return( _blendFunc.src == GL_SRC_ALPHA && _blendFunc.dst == GL_ONE);
  1042. }
  1043. // ZMLCCParticleSystem - Properties of Gravity Mode
  1044. void ZMLCCParticleSystem::setTangentialAccel(float t)
  1045. {
  1046. CCASSERT( _emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1047. modeA.tangentialAccel = t;
  1048. }
  1049. float ZMLCCParticleSystem::getTangentialAccel() const
  1050. {
  1051. CCASSERT( _emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1052. return modeA.tangentialAccel;
  1053. }
  1054. void ZMLCCParticleSystem::setTangentialAccelVar(float t)
  1055. {
  1056. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1057. modeA.tangentialAccelVar = t;
  1058. }
  1059. float ZMLCCParticleSystem::getTangentialAccelVar() const
  1060. {
  1061. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1062. return modeA.tangentialAccelVar;
  1063. }
  1064. void ZMLCCParticleSystem::setRadialAccel(float t)
  1065. {
  1066. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1067. modeA.radialAccel = t;
  1068. }
  1069. float ZMLCCParticleSystem::getRadialAccel() const
  1070. {
  1071. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1072. return modeA.radialAccel;
  1073. }
  1074. void ZMLCCParticleSystem::setRadialAccelVar(float t)
  1075. {
  1076. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1077. modeA.radialAccelVar = t;
  1078. }
  1079. float ZMLCCParticleSystem::getRadialAccelVar() const
  1080. {
  1081. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1082. return modeA.radialAccelVar;
  1083. }
  1084. void ZMLCCParticleSystem::setRotationIsDir(bool t)
  1085. {
  1086. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1087. modeA.rotationIsDir = t;
  1088. }
  1089. bool ZMLCCParticleSystem::getRotationIsDir() const
  1090. {
  1091. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1092. return modeA.rotationIsDir;
  1093. }
  1094. void ZMLCCParticleSystem::setGravity(const Vec2& g)
  1095. {
  1096. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1097. modeA.gravity = g;
  1098. }
  1099. const Vec2& ZMLCCParticleSystem::getGravity()
  1100. {
  1101. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1102. return modeA.gravity;
  1103. }
  1104. void ZMLCCParticleSystem::setSpeed(float speed)
  1105. {
  1106. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1107. modeA.speed = speed;
  1108. }
  1109. float ZMLCCParticleSystem::getSpeed() const
  1110. {
  1111. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1112. return modeA.speed;
  1113. }
  1114. void ZMLCCParticleSystem::setSpeedVar(float speedVar)
  1115. {
  1116. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1117. modeA.speedVar = speedVar;
  1118. }
  1119. float ZMLCCParticleSystem::getSpeedVar() const
  1120. {
  1121. CCASSERT(_emitterMode == Mode::GRAVITY, "Particle Mode should be Gravity");
  1122. return modeA.speedVar;
  1123. }
  1124. // ZMLCCParticleSystem - Properties of Radius Mode
  1125. void ZMLCCParticleSystem::setStartRadius(float startRadius)
  1126. {
  1127. CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1128. modeB.startRadius = startRadius;
  1129. }
  1130. float ZMLCCParticleSystem::getStartRadius() const
  1131. {
  1132. CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1133. return modeB.startRadius;
  1134. }
  1135. void ZMLCCParticleSystem::setStartRadiusVar(float startRadiusVar)
  1136. {
  1137. CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1138. modeB.startRadiusVar = startRadiusVar;
  1139. }
  1140. float ZMLCCParticleSystem::getStartRadiusVar() const
  1141. {
  1142. CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1143. return modeB.startRadiusVar;
  1144. }
  1145. void ZMLCCParticleSystem::setEndRadius(float endRadius)
  1146. {
  1147. CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1148. modeB.endRadius = endRadius;
  1149. }
  1150. float ZMLCCParticleSystem::getEndRadius() const
  1151. {
  1152. CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1153. return modeB.endRadius;
  1154. }
  1155. void ZMLCCParticleSystem::setEndRadiusVar(float endRadiusVar)
  1156. {
  1157. CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1158. modeB.endRadiusVar = endRadiusVar;
  1159. }
  1160. float ZMLCCParticleSystem::getEndRadiusVar() const
  1161. {
  1162. CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1163. return modeB.endRadiusVar;
  1164. }
  1165. void ZMLCCParticleSystem::setRotatePerSecond(float degrees)
  1166. {
  1167. // CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1168. modeB.rotatePerSecond = degrees;
  1169. }
  1170. float ZMLCCParticleSystem::getRotatePerSecond() const
  1171. {
  1172. // CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1173. return modeB.rotatePerSecond;
  1174. }
  1175. void ZMLCCParticleSystem::setRotatePerSecondVar(float degrees)
  1176. {
  1177. // CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1178. modeB.rotatePerSecondVar = degrees;
  1179. }
  1180. float ZMLCCParticleSystem::getRotatePerSecondVar() const
  1181. {
  1182. // CCASSERT(_emitterMode == Mode::RADIUS, "Particle Mode should be Radius");
  1183. return modeB.rotatePerSecondVar;
  1184. }
  1185. void ZMLCCParticleSystem::setEmitFirstFrameEnabled(bool emitFirstFrameEnabled){
  1186. if(emitFirstFrameEnabled){
  1187. _emitCounter = _emissionRate;
  1188. }
  1189. _emitFirstFrameEnabled = emitFirstFrameEnabled;
  1190. }
  1191. bool ZMLCCParticleSystem::isActive() const
  1192. {
  1193. return _isActive;
  1194. }
  1195. int ZMLCCParticleSystem::getTotalParticles() const
  1196. {
  1197. return _totalParticles;
  1198. }
  1199. void ZMLCCParticleSystem::setTotalParticles(int var)
  1200. {
  1201. CCASSERT( var <= _allocatedParticles, "Particle: resizing particle array only supported for quads");
  1202. _totalParticles = var;
  1203. }
  1204. const BlendFunc& ZMLCCParticleSystem::getBlendFunc() const
  1205. {
  1206. return _blendFunc;
  1207. }
  1208. void ZMLCCParticleSystem::setBlendFunc(const BlendFunc &blendFunc)
  1209. {
  1210. if( _blendFunc.src != blendFunc.src || _blendFunc.dst != blendFunc.dst ) {
  1211. _blendFunc = blendFunc;
  1212. this->updateBlendFunc();
  1213. }
  1214. }
  1215. bool ZMLCCParticleSystem::isAutoRemoveOnFinish() const
  1216. {
  1217. return _isAutoRemoveOnFinish;
  1218. }
  1219. void ZMLCCParticleSystem::setAutoRemoveOnFinish(bool var)
  1220. {
  1221. _isAutoRemoveOnFinish = var;
  1222. }
  1223. // ZMLCCParticleSystem - methods for batchNode rendering
  1224. ParticleBatchNode* ZMLCCParticleSystem::getBatchNode(void) const
  1225. {
  1226. return _batchNode;
  1227. }
  1228. void ZMLCCParticleSystem::setBatchNode(ParticleBatchNode* batchNode)
  1229. {
  1230. if( _batchNode != batchNode ) {
  1231. _batchNode = batchNode; // weak reference
  1232. if( batchNode ) {
  1233. //each particle needs a unique index
  1234. for (int i = 0; i < _totalParticles; i++)
  1235. {
  1236. _particleData.atlasIndex[i] = i;
  1237. }
  1238. }
  1239. }
  1240. }
  1241. //don't use a transform matrix, this is faster
  1242. void ZMLCCParticleSystem::setScale(float s)
  1243. {
  1244. _transformSystemDirty = true;
  1245. Node::setScale(s);
  1246. }
  1247. void ZMLCCParticleSystem::setRotation(float newRotation)
  1248. {
  1249. _transformSystemDirty = true;
  1250. Node::setRotation(newRotation);
  1251. }
  1252. void ZMLCCParticleSystem::setScaleX(float newScaleX)
  1253. {
  1254. _transformSystemDirty = true;
  1255. Node::setScaleX(newScaleX);
  1256. }
  1257. void ZMLCCParticleSystem::setScaleY(float newScaleY)
  1258. {
  1259. _transformSystemDirty = true;
  1260. Node::setScaleY(newScaleY);
  1261. }
  1262. void ZMLCCParticleSystem::start()
  1263. {
  1264. resetSystem();
  1265. }
  1266. void ZMLCCParticleSystem::stop()
  1267. {
  1268. stopSystem();
  1269. }
  1270. bool ZMLCCParticleSystem::isPaused() const
  1271. {
  1272. return _paused;
  1273. }
  1274. void ZMLCCParticleSystem::pauseEmissions()
  1275. {
  1276. _paused = true;
  1277. }
  1278. void ZMLCCParticleSystem::resumeEmissions()
  1279. {
  1280. _paused = false;
  1281. }
  1282. void ZMLCCParticleSystem::setCbOnExit(std::function<void(const std::string&, ZMLCCParticleSystem*)> cb) {
  1283. _cbOnExit = cb;
  1284. }
  1285. NS_CC_END