mirror of https://github.com/axmolengine/axmol.git
Add sprite frame and animation descriptors support
This commit is contained in:
parent
49763c5f17
commit
0a8035c12c
|
@ -1,3 +1,4 @@
|
||||||
|
#include "CCParticleSystem.h"
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Copyright (c) 2008-2010 Ricardo Quesada
|
Copyright (c) 2008-2010 Ricardo Quesada
|
||||||
Copyright (c) 2010-2012 cocos2d-x.org
|
Copyright (c) 2010-2012 cocos2d-x.org
|
||||||
|
@ -98,7 +99,7 @@ inline void normalize_point(float x, float y, particle_point* out)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A more effect random number getter function, get from ejoy2d.
|
A more effective random number generator function, made by ejoy2d.
|
||||||
*/
|
*/
|
||||||
inline static float RANDOM_M11(unsigned int* seed)
|
inline static float RANDOM_M11(unsigned int* seed)
|
||||||
{
|
{
|
||||||
|
@ -121,24 +122,30 @@ bool ParticleData::init(int count)
|
||||||
{
|
{
|
||||||
maxCount = count;
|
maxCount = count;
|
||||||
|
|
||||||
posx = (float*)malloc(count * sizeof(float));
|
posx = (float*)malloc(count * sizeof(float));
|
||||||
posy = (float*)malloc(count * sizeof(float));
|
posy = (float*)malloc(count * sizeof(float));
|
||||||
startPosX = (float*)malloc(count * sizeof(float));
|
startPosX = (float*)malloc(count * sizeof(float));
|
||||||
startPosY = (float*)malloc(count * sizeof(float));
|
startPosY = (float*)malloc(count * sizeof(float));
|
||||||
colorR = (float*)malloc(count * sizeof(float));
|
colorR = (float*)malloc(count * sizeof(float));
|
||||||
colorG = (float*)malloc(count * sizeof(float));
|
colorG = (float*)malloc(count * sizeof(float));
|
||||||
colorB = (float*)malloc(count * sizeof(float));
|
colorB = (float*)malloc(count * sizeof(float));
|
||||||
colorA = (float*)malloc(count * sizeof(float));
|
colorA = (float*)malloc(count * sizeof(float));
|
||||||
deltaColorR = (float*)malloc(count * sizeof(float));
|
deltaColorR = (float*)malloc(count * sizeof(float));
|
||||||
deltaColorG = (float*)malloc(count * sizeof(float));
|
deltaColorG = (float*)malloc(count * sizeof(float));
|
||||||
deltaColorB = (float*)malloc(count * sizeof(float));
|
deltaColorB = (float*)malloc(count * sizeof(float));
|
||||||
deltaColorA = (float*)malloc(count * sizeof(float));
|
deltaColorA = (float*)malloc(count * sizeof(float));
|
||||||
size = (float*)malloc(count * sizeof(float));
|
size = (float*)malloc(count * sizeof(float));
|
||||||
deltaSize = (float*)malloc(count * sizeof(float));
|
deltaSize = (float*)malloc(count * sizeof(float));
|
||||||
rotation = (float*)malloc(count * sizeof(float));
|
rotation = (float*)malloc(count * sizeof(float));
|
||||||
deltaRotation = (float*)malloc(count * sizeof(float));
|
staticRotation = (float*)malloc(count * sizeof(float));
|
||||||
timeToLive = (float*)malloc(count * sizeof(float));
|
deltaRotation = (float*)malloc(count * sizeof(float));
|
||||||
atlasIndex = (unsigned int*)malloc(count * sizeof(unsigned int));
|
totalTimeToLive = (float*)malloc(count * sizeof(float));
|
||||||
|
timeToLive = (float*)malloc(count * sizeof(float));
|
||||||
|
animTimeDelta = (float*)malloc(count * sizeof(float));
|
||||||
|
animTimeLength = (float*)malloc(count * sizeof(float));
|
||||||
|
animIndex = (unsigned short*)malloc(count * sizeof(unsigned short));
|
||||||
|
animCellIndex = (unsigned short*)malloc(count * sizeof(unsigned short));
|
||||||
|
atlasIndex = (unsigned int*)malloc(count * sizeof(unsigned int));
|
||||||
|
|
||||||
modeA.dirX = (float*)malloc(count * sizeof(float));
|
modeA.dirX = (float*)malloc(count * sizeof(float));
|
||||||
modeA.dirY = (float*)malloc(count * sizeof(float));
|
modeA.dirY = (float*)malloc(count * sizeof(float));
|
||||||
|
@ -151,9 +158,9 @@ bool ParticleData::init(int count)
|
||||||
modeB.radius = (float*)malloc(count * sizeof(float));
|
modeB.radius = (float*)malloc(count * sizeof(float));
|
||||||
|
|
||||||
return posx && posy && startPosY && startPosX && colorR && colorG && colorB && colorA && deltaColorR &&
|
return posx && posy && startPosY && startPosX && colorR && colorG && colorB && colorA && deltaColorR &&
|
||||||
deltaColorG && deltaColorB && deltaColorA && size && deltaSize && rotation && deltaRotation && timeToLive &&
|
deltaColorG && deltaColorB && deltaColorA && size && deltaSize && rotation && deltaRotation && totalTimeToLive &&
|
||||||
atlasIndex && modeA.dirX && modeA.dirY && modeA.radialAccel && modeA.tangentialAccel && modeB.angle &&
|
timeToLive && atlasIndex && modeA.dirX && modeA.dirY && modeA.radialAccel && modeA.tangentialAccel &&
|
||||||
modeB.degreesPerSecond && modeB.deltaRadius && modeB.radius;
|
modeB.angle && modeB.degreesPerSecond && modeB.deltaRadius && modeB.radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleData::release()
|
void ParticleData::release()
|
||||||
|
@ -173,8 +180,14 @@ void ParticleData::release()
|
||||||
CC_SAFE_FREE(size);
|
CC_SAFE_FREE(size);
|
||||||
CC_SAFE_FREE(deltaSize);
|
CC_SAFE_FREE(deltaSize);
|
||||||
CC_SAFE_FREE(rotation);
|
CC_SAFE_FREE(rotation);
|
||||||
|
CC_SAFE_FREE(staticRotation);
|
||||||
CC_SAFE_FREE(deltaRotation);
|
CC_SAFE_FREE(deltaRotation);
|
||||||
|
CC_SAFE_FREE(totalTimeToLive);
|
||||||
CC_SAFE_FREE(timeToLive);
|
CC_SAFE_FREE(timeToLive);
|
||||||
|
CC_SAFE_FREE(animTimeDelta);
|
||||||
|
CC_SAFE_FREE(animTimeLength);
|
||||||
|
CC_SAFE_FREE(animIndex);
|
||||||
|
CC_SAFE_FREE(animCellIndex);
|
||||||
CC_SAFE_FREE(atlasIndex);
|
CC_SAFE_FREE(atlasIndex);
|
||||||
|
|
||||||
CC_SAFE_FREE(modeA.dirX);
|
CC_SAFE_FREE(modeA.dirX);
|
||||||
|
@ -223,6 +236,15 @@ ParticleSystem::ParticleSystem()
|
||||||
, _texture(nullptr)
|
, _texture(nullptr)
|
||||||
, _blendFunc(BlendFunc::ALPHA_PREMULTIPLIED)
|
, _blendFunc(BlendFunc::ALPHA_PREMULTIPLIED)
|
||||||
, _opacityModifyRGB(false)
|
, _opacityModifyRGB(false)
|
||||||
|
, _isLifeAnimated(false)
|
||||||
|
, _isEmitterAnimated(false)
|
||||||
|
, _isLoopAnimated(false)
|
||||||
|
, _isAnimationAtlas(false)
|
||||||
|
, _animDir(TexAnimDir::VERTICAL)
|
||||||
|
, _animUnifiedSize(1)
|
||||||
|
, _animIndexCount(0)
|
||||||
|
, _isLifeAnimationReversed(false)
|
||||||
|
, _isAnimationMulti(false)
|
||||||
, _yCoordFlipped(1)
|
, _yCoordFlipped(1)
|
||||||
, _positionType(PositionType::FREE)
|
, _positionType(PositionType::FREE)
|
||||||
, _paused(false)
|
, _paused(false)
|
||||||
|
@ -604,23 +626,31 @@ ParticleSystem::~ParticleSystem()
|
||||||
// it is not needed to call "unscheduleUpdate" here. In fact, it will be called in "cleanup"
|
// it is not needed to call "unscheduleUpdate" here. In fact, it will be called in "cleanup"
|
||||||
// unscheduleUpdate();
|
// unscheduleUpdate();
|
||||||
_particleData.release();
|
_particleData.release();
|
||||||
|
_animations.clear();
|
||||||
CC_SAFE_RELEASE(_texture);
|
CC_SAFE_RELEASE(_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleSystem::addParticles(int count)
|
void ParticleSystem::addParticles(int count, int animationCellIndex, int animationIndex)
|
||||||
{
|
{
|
||||||
if (_paused)
|
if (_paused)
|
||||||
return;
|
return;
|
||||||
uint32_t RANDSEED = rand();
|
uint32_t RANDSEED = rand();
|
||||||
|
|
||||||
|
if (_isAnimationAtlas)
|
||||||
|
{
|
||||||
|
animationCellIndex = MIN(animationCellIndex, getTotalAnimationCells() - 1);
|
||||||
|
animationIndex = MIN(animationIndex, _animIndexCount - 1);
|
||||||
|
}
|
||||||
|
|
||||||
int start = _particleCount;
|
int start = _particleCount;
|
||||||
_particleCount += count;
|
_particleCount += count;
|
||||||
|
|
||||||
// life
|
// life
|
||||||
for (int i = start; i < _particleCount; ++i)
|
for (int i = start; i < _particleCount; ++i)
|
||||||
{
|
{
|
||||||
float theLife = _life + _lifeVar * RANDOM_M11(&RANDSEED);
|
float particleLife = _life + _lifeVar * RANDOM_M11(&RANDSEED);
|
||||||
_particleData.timeToLive[i] = MAX(0, theLife);
|
_particleData.totalTimeToLive[i] = MAX(0, particleLife);
|
||||||
|
_particleData.timeToLive[i] = MAX(0, particleLife);
|
||||||
}
|
}
|
||||||
|
|
||||||
// position
|
// position
|
||||||
|
@ -634,6 +664,63 @@ void ParticleSystem::addParticles(int count)
|
||||||
_particleData.posy[i] = _sourcePosition.y + _posVar.y * RANDOM_M11(&RANDSEED);
|
_particleData.posy[i] = _sourcePosition.y + _posVar.y * RANDOM_M11(&RANDSEED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (animationCellIndex == -1 && _isEmitterAnimated)
|
||||||
|
{
|
||||||
|
for (int i = start; i < _particleCount; ++i)
|
||||||
|
{
|
||||||
|
_particleData.animCellIndex[i] = (int)abs(RANDOM_M11(&RANDSEED) * getTotalAnimationCells());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animationCellIndex != -1)
|
||||||
|
{
|
||||||
|
for (int i = start; i < _particleCount; ++i)
|
||||||
|
{
|
||||||
|
_particleData.animCellIndex[i] = animationCellIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animationIndex == -1 && !_isAnimationMulti && _isLoopAnimated)
|
||||||
|
{
|
||||||
|
for (int i = start; i < _particleCount; ++i)
|
||||||
|
{
|
||||||
|
_particleData.animIndex[i] = 0;
|
||||||
|
auto descriptor = _animations.at(_particleData.animIndex[i]);
|
||||||
|
_particleData.animTimeLength[i] =
|
||||||
|
descriptor.animationSpeed + descriptor.animationSpeedVariance * RANDOM_M11(&RANDSEED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animationIndex == -1 && _isAnimationMulti && _isLoopAnimated)
|
||||||
|
{
|
||||||
|
for (int i = start; i < _particleCount; ++i)
|
||||||
|
{
|
||||||
|
_particleData.animIndex[i] = _randomAnimations[abs(RANDOM_M11(&RANDSEED) * _randomAnimations.size())];
|
||||||
|
auto descriptor = _animations.at(_particleData.animIndex[i]);
|
||||||
|
_particleData.animTimeLength[i] =
|
||||||
|
descriptor.animationSpeed + descriptor.animationSpeedVariance * RANDOM_M11(&RANDSEED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isLoopAnimated)
|
||||||
|
{
|
||||||
|
for (int i = start; i < _particleCount; ++i)
|
||||||
|
{
|
||||||
|
_particleData.animTimeDelta[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animationIndex != -1)
|
||||||
|
{
|
||||||
|
for (int i = start; i < _particleCount; ++i)
|
||||||
|
{
|
||||||
|
_particleData.animIndex[i] = animationIndex;
|
||||||
|
auto descriptor = _animations.at(_particleData.animIndex[i]);
|
||||||
|
_particleData.animTimeLength[i] =
|
||||||
|
descriptor.animationSpeed + descriptor.animationSpeedVariance * RANDOM_M11(&RANDSEED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// color
|
// color
|
||||||
#define SET_COLOR(c, b, v) \
|
#define SET_COLOR(c, b, v) \
|
||||||
for (int i = start; i < _particleCount; ++i) \
|
for (int i = start; i < _particleCount; ++i) \
|
||||||
|
@ -697,6 +784,12 @@ void ParticleSystem::addParticles(int count)
|
||||||
_particleData.deltaRotation[i] = (endA - _particleData.rotation[i]) / _particleData.timeToLive[i];
|
_particleData.deltaRotation[i] = (endA - _particleData.rotation[i]) / _particleData.timeToLive[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static rotation
|
||||||
|
for (int i = start; i < _particleCount; ++i)
|
||||||
|
{
|
||||||
|
_particleData.staticRotation[i] = _staticRotation + _staticRotationVar * RANDOM_M11(&RANDSEED);
|
||||||
|
}
|
||||||
|
|
||||||
// position
|
// position
|
||||||
Vec2 pos;
|
Vec2 pos;
|
||||||
if (_positionType == PositionType::FREE)
|
if (_positionType == PositionType::FREE)
|
||||||
|
@ -801,6 +894,84 @@ void ParticleSystem::addParticles(int count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::setAnimationDescriptor(unsigned short indexOfDescriptor,
|
||||||
|
float time,
|
||||||
|
float timeVariance,
|
||||||
|
std::vector<unsigned short> indices,
|
||||||
|
bool reverse)
|
||||||
|
{
|
||||||
|
ParticleAnimationDescriptor desc{};
|
||||||
|
|
||||||
|
desc.animationSpeed = time;
|
||||||
|
desc.animationSpeedVariance = timeVariance;
|
||||||
|
desc.animationIndices = indices;
|
||||||
|
desc.reverseIndices = reverse;
|
||||||
|
|
||||||
|
if (_animations.find(indexOfDescriptor) == _animations.end())
|
||||||
|
_animations.insert({indexOfDescriptor, desc});
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_animations.erase(indexOfDescriptor);
|
||||||
|
_animations.insert({indexOfDescriptor, desc});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::resetAnimationIndices()
|
||||||
|
{
|
||||||
|
_animIndexCount = 0;
|
||||||
|
_animationIndices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::resetAnimationDescriptors()
|
||||||
|
{
|
||||||
|
_animations.clear();
|
||||||
|
_randomAnimations.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::setMultiAnimationRandom()
|
||||||
|
{
|
||||||
|
_randomAnimations.clear();
|
||||||
|
for (auto& a : _animations)
|
||||||
|
_randomAnimations.push_back(a.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::addAnimationIndex(std::string_view frameName)
|
||||||
|
{
|
||||||
|
addAnimationIndex(_animIndexCount++, frameName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::addAnimationIndex(unsigned short index, std::string_view frameName)
|
||||||
|
{
|
||||||
|
auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(frameName);
|
||||||
|
|
||||||
|
if (frame)
|
||||||
|
addAnimationIndex(index, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::addAnimationIndex(cocos2d::SpriteFrame* frame)
|
||||||
|
{
|
||||||
|
addAnimationIndex(_animIndexCount++, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::addAnimationIndex(unsigned short index, cocos2d::SpriteFrame* frame)
|
||||||
|
{
|
||||||
|
//Not sure how to check texture equality truly but it won't hurt to skip it
|
||||||
|
//CCASSERT(frame->getTexture() == _texture, "Sprite frame texture and particle system texture should match!");
|
||||||
|
|
||||||
|
ParticleFrameDescriptor desc{};
|
||||||
|
|
||||||
|
desc.rect = frame->getRect();
|
||||||
|
desc.isRotated = frame->isRotated();
|
||||||
|
|
||||||
|
if (_animationIndices.find(index) == _animationIndices.end())
|
||||||
|
_animationIndices.insert({index, desc});
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_animationIndices.erase(index);
|
||||||
|
_animationIndices.insert({index, desc});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ParticleSystem::onEnter()
|
void ParticleSystem::onEnter()
|
||||||
{
|
{
|
||||||
Node::onEnter();
|
Node::onEnter();
|
||||||
|
@ -880,6 +1051,37 @@ void ParticleSystem::update(float dt)
|
||||||
for (int i = 0; i < _particleCount; ++i)
|
for (int i = 0; i < _particleCount; ++i)
|
||||||
{
|
{
|
||||||
_particleData.timeToLive[i] -= dt;
|
_particleData.timeToLive[i] -= dt;
|
||||||
|
if (_isLifeAnimated && _animations.empty())
|
||||||
|
{
|
||||||
|
float percent = (_particleData.totalTimeToLive[i] - _particleData.timeToLive[i]) / _particleData.totalTimeToLive[i];
|
||||||
|
percent = _isLifeAnimationReversed ? 1.0F - percent : percent;
|
||||||
|
_particleData.animCellIndex[i] = (unsigned int)MIN((percent * getTotalAnimationCells()), getTotalAnimationCells() - 1);
|
||||||
|
}
|
||||||
|
if (_isLifeAnimated && !_animations.empty())
|
||||||
|
{
|
||||||
|
auto& anim = _animations.begin()->second;
|
||||||
|
|
||||||
|
float percent =
|
||||||
|
(_particleData.totalTimeToLive[i] - _particleData.timeToLive[i]) / _particleData.totalTimeToLive[i];
|
||||||
|
|
||||||
|
percent = (!!_isLifeAnimationReversed != !!anim.reverseIndices) ? 1.0F - percent : percent;
|
||||||
|
_particleData.animCellIndex[i] = anim.animationIndices[MIN(abs(percent * anim.animationIndices.size()),
|
||||||
|
anim.animationIndices.size() - 1)];
|
||||||
|
}
|
||||||
|
if (_isLoopAnimated)
|
||||||
|
{
|
||||||
|
auto& anim = _animations.at(_particleData.animIndex[i]);
|
||||||
|
|
||||||
|
_particleData.animTimeDelta[i] += dt;
|
||||||
|
if (_particleData.animTimeDelta[i] >= _particleData.animTimeLength[i])
|
||||||
|
_particleData.animTimeDelta[i] = 0;
|
||||||
|
|
||||||
|
float percent = _particleData.animTimeDelta[i] / _particleData.animTimeLength[i];
|
||||||
|
|
||||||
|
percent = anim.reverseIndices ? 1.0F - percent : percent;
|
||||||
|
_particleData.animCellIndex[i] = anim.animationIndices[MIN(abs(percent * anim.animationIndices.size()),
|
||||||
|
anim.animationIndices.size() - 1)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _particleCount; ++i)
|
for (int i = 0; i < _particleCount; ++i)
|
||||||
|
|
|
@ -52,6 +52,20 @@ struct particle_point
|
||||||
float y;
|
float y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ParticleAnimationDescriptor
|
||||||
|
{
|
||||||
|
float animationSpeed;
|
||||||
|
float animationSpeedVariance;
|
||||||
|
std::vector<unsigned short> animationIndices;
|
||||||
|
bool reverseIndices;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParticleFrameDescriptor
|
||||||
|
{
|
||||||
|
cocos2d::Rect rect;
|
||||||
|
bool isRotated;
|
||||||
|
};
|
||||||
|
|
||||||
class CC_DLL ParticleData
|
class CC_DLL ParticleData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -73,8 +87,14 @@ public:
|
||||||
float* size;
|
float* size;
|
||||||
float* deltaSize;
|
float* deltaSize;
|
||||||
float* rotation;
|
float* rotation;
|
||||||
|
float* staticRotation;
|
||||||
float* deltaRotation;
|
float* deltaRotation;
|
||||||
|
float* totalTimeToLive;
|
||||||
float* timeToLive;
|
float* timeToLive;
|
||||||
|
float* animTimeDelta;
|
||||||
|
float* animTimeLength;
|
||||||
|
unsigned short* animIndex;
|
||||||
|
unsigned short* animCellIndex;
|
||||||
unsigned int* atlasIndex;
|
unsigned int* atlasIndex;
|
||||||
|
|
||||||
//! Mode A: gravity, direction, radial accel, tangential accel
|
//! Mode A: gravity, direction, radial accel, tangential accel
|
||||||
|
@ -124,8 +144,10 @@ public:
|
||||||
rotation[p1] = rotation[p2];
|
rotation[p1] = rotation[p2];
|
||||||
deltaRotation[p1] = deltaRotation[p2];
|
deltaRotation[p1] = deltaRotation[p2];
|
||||||
|
|
||||||
|
totalTimeToLive[p1] = totalTimeToLive[p2];
|
||||||
timeToLive[p1] = timeToLive[p2];
|
timeToLive[p1] = timeToLive[p2];
|
||||||
|
|
||||||
|
animCellIndex[p1] = animCellIndex[p2];
|
||||||
atlasIndex[p1] = atlasIndex[p2];
|
atlasIndex[p1] = atlasIndex[p2];
|
||||||
|
|
||||||
modeA.dirX[p1] = modeA.dirX[p2];
|
modeA.dirX[p1] = modeA.dirX[p2];
|
||||||
|
@ -202,7 +224,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/** PositionType
|
/** PositionType
|
||||||
Possible types of particle positions.
|
Types of particle positioning.
|
||||||
* @js cc.ParticleSystem.TYPE_FREE
|
* @js cc.ParticleSystem.TYPE_FREE
|
||||||
*/
|
*/
|
||||||
enum class PositionType
|
enum class PositionType
|
||||||
|
@ -216,6 +238,17 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** TexAnimDir
|
||||||
|
Texture animation direction for the particles.
|
||||||
|
*/
|
||||||
|
enum class TexAnimDir
|
||||||
|
{
|
||||||
|
VERTICAL, /** texture coordinates are read top to bottom within the texture */
|
||||||
|
|
||||||
|
HORIZONTAL, /** texture coordinates are read left to right within the texture */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
//* @enum
|
//* @enum
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -252,7 +285,7 @@ public:
|
||||||
static Vector<ParticleSystem*>& getAllParticleSystems();
|
static Vector<ParticleSystem*>& getAllParticleSystems();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void addParticles(int count);
|
void addParticles(int count, int animationCellIndex = -1, int animationIndex = -1);
|
||||||
|
|
||||||
void stopSystem();
|
void stopSystem();
|
||||||
/** Kill all living particles.
|
/** Kill all living particles.
|
||||||
|
@ -702,6 +735,17 @@ public:
|
||||||
*/
|
*/
|
||||||
void setEndSpinVar(float endSpinVar) { _endSpinVar = endSpinVar; }
|
void setEndSpinVar(float endSpinVar) { _endSpinVar = endSpinVar; }
|
||||||
|
|
||||||
|
/** Sets the static rotation of each particle
|
||||||
|
*
|
||||||
|
* @param angle The angle in degrees that the particle will exist with
|
||||||
|
*/
|
||||||
|
virtual void setStaticRotation(float angle) { _staticRotation = angle; };
|
||||||
|
/** Sets the static rotation variance of each particle.
|
||||||
|
*
|
||||||
|
* @param angle The angle in degrees variance
|
||||||
|
*/
|
||||||
|
virtual void setStaticRotationVar(float angle) { _staticRotationVar = angle; };
|
||||||
|
|
||||||
/** Gets the emission rate of the particles.
|
/** Gets the emission rate of the particles.
|
||||||
*
|
*
|
||||||
* @return The emission rate of the particles.
|
* @return The emission rate of the particles.
|
||||||
|
@ -728,6 +772,141 @@ public:
|
||||||
void setOpacityModifyRGB(bool opacityModifyRGB) override { _opacityModifyRGB = opacityModifyRGB; }
|
void setOpacityModifyRGB(bool opacityModifyRGB) override { _opacityModifyRGB = opacityModifyRGB; }
|
||||||
bool isOpacityModifyRGB() const override { return _opacityModifyRGB; }
|
bool isOpacityModifyRGB() const override { return _opacityModifyRGB; }
|
||||||
|
|
||||||
|
/** Enables or disables tex coord animations that are set based on particle life. */
|
||||||
|
void setLifeAnimation(bool enabled)
|
||||||
|
{
|
||||||
|
_isLifeAnimated = enabled;
|
||||||
|
_isEmitterAnimated = false;
|
||||||
|
_isLoopAnimated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enables or disables tex coord animations that are set by the emitter randomly when a particle is emitted.
|
||||||
|
* WARNING: this won't matter if particle life animation is enabled ie. setLifeAnimation(true) */
|
||||||
|
void setEmitterAnimation(bool enabled)
|
||||||
|
{
|
||||||
|
_isEmitterAnimated = enabled;
|
||||||
|
_isLifeAnimated = false;
|
||||||
|
_isLoopAnimated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enables or disables tex coord animations that are used to make particles play a sequence forever until they die
|
||||||
|
* This interduces a new concept of animation where you specify the indices and then specify animations descriptors that tell how these indices are used and what speed they're played at.
|
||||||
|
* Functions that effect this are: setMultiAnimationParticles(), resetAnimationDescriptors(), resetAnimationIndices(), addAnimationIndex(), setAnimationDescriptor(), setMultiAnimationRandom(), setMultiAnimationRandomSpecific(),
|
||||||
|
*/
|
||||||
|
void setLoopAnimation(bool enabled)
|
||||||
|
{
|
||||||
|
_isLoopAnimated = enabled;
|
||||||
|
_isEmitterAnimated = false;
|
||||||
|
_isLifeAnimated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLifeAnimated() { return _isLifeAnimated; }
|
||||||
|
bool isEmitterAnimated() { return _isEmitterAnimated; }
|
||||||
|
|
||||||
|
/** Sets texture animation direction for the particles */
|
||||||
|
void setAnimationTexDir(TexAnimDir dir = TexAnimDir::VERTICAL) { _animDir = dir; }
|
||||||
|
|
||||||
|
/** Gets texture animation direction for the particles */
|
||||||
|
TexAnimDir getAnimationTexDir() { return _animDir; }
|
||||||
|
|
||||||
|
/** Sets the width and height of a single animated cell *unified*
|
||||||
|
* Example: if a cell's size in the texture is 32 pixels wide and 32 pixel high then the unified size is 32 */
|
||||||
|
void setAnimationCellUnifiedSize(int unifiedSizeInPixels) { _animUnifiedSize = unifiedSizeInPixels; }
|
||||||
|
|
||||||
|
/** Gets the width and height of a single animated cell *unified*
|
||||||
|
* Example: if a cell's size in the texture is 32 pixels wide and 32 pixel high then the unified size is 32 */
|
||||||
|
int getAnimationCellUnifiedSize() { return _animUnifiedSize; }
|
||||||
|
|
||||||
|
/** Gets the total pixels in a texture based on the direction set */
|
||||||
|
int getAnimationPixels()
|
||||||
|
{
|
||||||
|
switch (_animDir)
|
||||||
|
{
|
||||||
|
case TexAnimDir::VERTICAL:
|
||||||
|
return _texture->getPixelsHigh();
|
||||||
|
case TexAnimDir::HORIZONTAL:
|
||||||
|
return _texture->getPixelsWide();
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the total cells viewable in a texture by dividing texture height or width into animation cell size
|
||||||
|
* animation cell size can be changed using setAnimationCellUnifiedSize(int)
|
||||||
|
* incase atlas animation is set off it will return the indices added through addAnimationIndex() */
|
||||||
|
int getTotalAnimationCells() { return _isAnimationAtlas ? getAnimationPixels() / _animUnifiedSize : _animIndexCount; }
|
||||||
|
|
||||||
|
/** Sets wether to start from first cell and go forward (normal)
|
||||||
|
* or last cell and go backward (reversed) when using life animation */
|
||||||
|
void setLifeAnimationReverse(bool reverse) { _isLifeAnimationReversed = reverse; }
|
||||||
|
bool isAnimationLifeReversed() { return _isLifeAnimationReversed; }
|
||||||
|
|
||||||
|
/** Sets wether to use atlas rendering or sprite frame rendering */
|
||||||
|
void setAnimationAtlas(bool atlas) { _isAnimationAtlas = atlas; }
|
||||||
|
bool isAnimationAtlas() { return _isAnimationAtlas; }
|
||||||
|
|
||||||
|
/** Sets wether to use multiable different index animations that can be randomly choosen for particles */
|
||||||
|
void setMultiAnimationParticles(bool multi) { _isAnimationMulti = multi; }
|
||||||
|
bool isMultiAnimationParticles() { return _isAnimationMulti; }
|
||||||
|
|
||||||
|
/** Resets the count of indices to 0 and empties the index array */
|
||||||
|
void resetAnimationIndices();
|
||||||
|
|
||||||
|
/** Resets the container of animation descriptors empties the random array */
|
||||||
|
void resetAnimationDescriptors();
|
||||||
|
|
||||||
|
/** Choose what animation descriptors are to be selected at random for particles
|
||||||
|
* This function should be called after you've inserted/overwritten any animation descriptors.
|
||||||
|
*
|
||||||
|
* @param animations Array of specific animations to play at random
|
||||||
|
*/
|
||||||
|
void setMultiAnimationRandomSpecific(std::vector<unsigned short> animations) { _randomAnimations = animations; };
|
||||||
|
|
||||||
|
/** Choose ALL animation descriptors to be selected at random for particles.
|
||||||
|
* This function should be called after you've inserted/overwritten any animation descriptors.
|
||||||
|
*/
|
||||||
|
void setMultiAnimationRandom();
|
||||||
|
|
||||||
|
/** Add a particle animation index based on tex coords spicified using a sprite frame if atlas mode is off.
|
||||||
|
* The index is automatically incremented on each addition.
|
||||||
|
*
|
||||||
|
* @param frameName SpriteFrame name to search for
|
||||||
|
*/
|
||||||
|
void addAnimationIndex(std::string_view frameName);
|
||||||
|
|
||||||
|
/** Add a particle animation index based on tex coords spicified using a sprite frame if atlas mode is off.
|
||||||
|
*
|
||||||
|
* @param frameName SpriteFrame name to search for
|
||||||
|
*/
|
||||||
|
void addAnimationIndex(unsigned short index, std::string_view frameName);
|
||||||
|
|
||||||
|
/** Add a particle animation index based on tex coords spicified using a sprite frame if atlas mode is off.
|
||||||
|
* The index is automatically incremented on each addition.
|
||||||
|
*
|
||||||
|
* @param frame SpriteFrame containting data about tex coords
|
||||||
|
*/
|
||||||
|
void addAnimationIndex(cocos2d::SpriteFrame* frame);
|
||||||
|
|
||||||
|
/** Add a particle animation index based on tex coords spicified using a sprite frame if atlas mode is off.
|
||||||
|
* you can specify which index you want to override in this function
|
||||||
|
* @param index Index id to override the index with
|
||||||
|
* @param frame SpriteFrame containting data about tex coords
|
||||||
|
*/
|
||||||
|
void addAnimationIndex(unsigned short index, cocos2d::SpriteFrame* frame);
|
||||||
|
|
||||||
|
/** Add a particle animation descriptor with an index.
|
||||||
|
*
|
||||||
|
* @param indexOfDescriptor Index of the animation to be added, adding to the same index will just override the pervious animation descriptor
|
||||||
|
* @param time length of the animation in seconds
|
||||||
|
* @param timeVariance Time randomly selected for each different particle added on the animation length
|
||||||
|
* @param indices An array of the indicies
|
||||||
|
* @param reverse Should the animation indicies be played backwards? (default: false)
|
||||||
|
*/
|
||||||
|
void setAnimationDescriptor(unsigned short indexOfDescriptor,
|
||||||
|
float time,
|
||||||
|
float timeVariance,
|
||||||
|
std::vector<unsigned short> indices,
|
||||||
|
bool reverse = false);
|
||||||
|
|
||||||
/** Gets the particles movement type: Free or Grouped.
|
/** Gets the particles movement type: Free or Grouped.
|
||||||
@since v0.8
|
@since v0.8
|
||||||
*
|
*
|
||||||
|
@ -965,6 +1144,10 @@ protected:
|
||||||
float _endSpin;
|
float _endSpin;
|
||||||
//* initial angle of each particle
|
//* initial angle of each particle
|
||||||
float _endSpinVar;
|
float _endSpinVar;
|
||||||
|
//* initial rotation of each particle
|
||||||
|
float _staticRotation;
|
||||||
|
//* initial rotation of each particle
|
||||||
|
float _staticRotationVar;
|
||||||
/** emission rate of the particles */
|
/** emission rate of the particles */
|
||||||
float _emissionRate;
|
float _emissionRate;
|
||||||
/** maximum particles of the system */
|
/** maximum particles of the system */
|
||||||
|
@ -975,6 +1158,31 @@ protected:
|
||||||
BlendFunc _blendFunc;
|
BlendFunc _blendFunc;
|
||||||
/** does the alpha value modify color */
|
/** does the alpha value modify color */
|
||||||
bool _opacityModifyRGB;
|
bool _opacityModifyRGB;
|
||||||
|
/** is the particle system animated */
|
||||||
|
bool _isLifeAnimated;
|
||||||
|
/** is the emitter particle system animated */
|
||||||
|
bool _isEmitterAnimated;
|
||||||
|
/** is the emitter particle system animated */
|
||||||
|
bool _isLoopAnimated;
|
||||||
|
/** True if you want to use an atlas with a fixed cell size
|
||||||
|
* False if you want to use SpriteFrames as your indexes using the function addAnimationIndex() */
|
||||||
|
bool _isAnimationAtlas;
|
||||||
|
/** tex coord animation direction for the system */
|
||||||
|
TexAnimDir _animDir;
|
||||||
|
/** the width and height of an animated cell unified */
|
||||||
|
int _animUnifiedSize;
|
||||||
|
/** variable keeping count of sprite frames added for atlas mode off */
|
||||||
|
int _animIndexCount;
|
||||||
|
/** wether to start from first or last when using life animation */
|
||||||
|
bool _isLifeAnimationReversed;
|
||||||
|
/** A map that stores particle animation index coords */
|
||||||
|
std::unordered_map<unsigned short, ParticleFrameDescriptor> _animationIndices;
|
||||||
|
/** wether to start from first or last when using life animation */
|
||||||
|
int _isAnimationMulti;
|
||||||
|
/** A map that stores particle animation descriptors */
|
||||||
|
std::unordered_map<unsigned short, ParticleAnimationDescriptor> _animations;
|
||||||
|
/** A vector that stores ids of animation descriptors that are choosen at random */
|
||||||
|
std::vector<unsigned short> _randomAnimations;
|
||||||
/** does FlippedY variance of each particle */
|
/** does FlippedY variance of each particle */
|
||||||
int _yCoordFlipped;
|
int _yCoordFlipped;
|
||||||
|
|
||||||
|
|
|
@ -273,7 +273,11 @@ void ParticleSystemQuad::initIndices()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void updatePosWithParticle(V3F_C4B_T2F_Quad* quad, const Vec2& newPosition, float size, float rotation)
|
inline void updatePosWithParticle(V3F_C4B_T2F_Quad* quad,
|
||||||
|
const Vec2& newPosition,
|
||||||
|
float size,
|
||||||
|
float rotation,
|
||||||
|
float staticRotation)
|
||||||
{
|
{
|
||||||
// vertices
|
// vertices
|
||||||
float size_2 = size / 2;
|
float size_2 = size / 2;
|
||||||
|
@ -285,7 +289,7 @@ inline void updatePosWithParticle(V3F_C4B_T2F_Quad* quad, const Vec2& newPositio
|
||||||
float x = newPosition.x;
|
float x = newPosition.x;
|
||||||
float y = newPosition.y;
|
float y = newPosition.y;
|
||||||
|
|
||||||
float r = (float)-CC_DEGREES_TO_RADIANS(rotation);
|
float r = (float)-CC_DEGREES_TO_RADIANS(rotation + staticRotation);
|
||||||
float cr = cosf(r);
|
float cr = cosf(r);
|
||||||
float sr = sinf(r);
|
float sr = sinf(r);
|
||||||
float ax = x1 * cr - y1 * sr + x;
|
float ax = x1 * cr - y1 * sr + x;
|
||||||
|
@ -351,14 +355,15 @@ void ParticleSystemQuad::updateParticleQuads()
|
||||||
worldToNodeTM.transformPoint(&p1);
|
worldToNodeTM.transformPoint(&p1);
|
||||||
Vec3 p2;
|
Vec3 p2;
|
||||||
Vec2 newPos;
|
Vec2 newPos;
|
||||||
float* startX = _particleData.startPosX;
|
float* startX = _particleData.startPosX;
|
||||||
float* startY = _particleData.startPosY;
|
float* startY = _particleData.startPosY;
|
||||||
float* x = _particleData.posx;
|
float* x = _particleData.posx;
|
||||||
float* y = _particleData.posy;
|
float* y = _particleData.posy;
|
||||||
float* s = _particleData.size;
|
float* s = _particleData.size;
|
||||||
float* r = _particleData.rotation;
|
float* r = _particleData.rotation;
|
||||||
|
float* sr = _particleData.staticRotation;
|
||||||
V3F_C4B_T2F_Quad* quadStart = startQuad;
|
V3F_C4B_T2F_Quad* quadStart = startQuad;
|
||||||
for (int i = 0; i < _particleCount; ++i, ++startX, ++startY, ++x, ++y, ++quadStart, ++s, ++r)
|
for (int i = 0; i < _particleCount; ++i, ++startX, ++startY, ++x, ++y, ++quadStart, ++s, ++r, ++sr)
|
||||||
{
|
{
|
||||||
p2.set(*startX, *startY, 0);
|
p2.set(*startX, *startY, 0);
|
||||||
worldToNodeTM.transformPoint(&p2);
|
worldToNodeTM.transformPoint(&p2);
|
||||||
|
@ -366,7 +371,7 @@ void ParticleSystemQuad::updateParticleQuads()
|
||||||
p2 = p1 - p2;
|
p2 = p1 - p2;
|
||||||
newPos.x -= p2.x - pos.x;
|
newPos.x -= p2.x - pos.x;
|
||||||
newPos.y -= p2.y - pos.y;
|
newPos.y -= p2.y - pos.y;
|
||||||
updatePosWithParticle(quadStart, newPos, *s, *r);
|
updatePosWithParticle(quadStart, newPos, *s, *r, *sr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_positionType == PositionType::RELATIVE)
|
else if (_positionType == PositionType::RELATIVE)
|
||||||
|
@ -378,14 +383,15 @@ void ParticleSystemQuad::updateParticleQuads()
|
||||||
float* y = _particleData.posy;
|
float* y = _particleData.posy;
|
||||||
float* s = _particleData.size;
|
float* s = _particleData.size;
|
||||||
float* r = _particleData.rotation;
|
float* r = _particleData.rotation;
|
||||||
|
float* sr = _particleData.staticRotation;
|
||||||
V3F_C4B_T2F_Quad* quadStart = startQuad;
|
V3F_C4B_T2F_Quad* quadStart = startQuad;
|
||||||
for (int i = 0; i < _particleCount; ++i, ++startX, ++startY, ++x, ++y, ++quadStart, ++s, ++r)
|
for (int i = 0; i < _particleCount; ++i, ++startX, ++startY, ++x, ++y, ++quadStart, ++s, ++r, ++sr)
|
||||||
{
|
{
|
||||||
newPos.set(*x, *y);
|
newPos.set(*x, *y);
|
||||||
newPos.x = *x - (currentPosition.x - *startX);
|
newPos.x = *x - (currentPosition.x - *startX);
|
||||||
newPos.y = *y - (currentPosition.y - *startY);
|
newPos.y = *y - (currentPosition.y - *startY);
|
||||||
newPos += pos;
|
newPos += pos;
|
||||||
updatePosWithParticle(quadStart, newPos, *s, *r);
|
updatePosWithParticle(quadStart, newPos, *s, *r, *sr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -397,24 +403,75 @@ void ParticleSystemQuad::updateParticleQuads()
|
||||||
float* y = _particleData.posy;
|
float* y = _particleData.posy;
|
||||||
float* s = _particleData.size;
|
float* s = _particleData.size;
|
||||||
float* r = _particleData.rotation;
|
float* r = _particleData.rotation;
|
||||||
|
float* sr = _particleData.staticRotation;
|
||||||
V3F_C4B_T2F_Quad* quadStart = startQuad;
|
V3F_C4B_T2F_Quad* quadStart = startQuad;
|
||||||
for (int i = 0; i < _particleCount; ++i, ++startX, ++startY, ++x, ++y, ++quadStart, ++s, ++r)
|
for (int i = 0; i < _particleCount; ++i, ++startX, ++startY, ++x, ++y, ++quadStart, ++s, ++r, ++sr)
|
||||||
{
|
{
|
||||||
newPos.set(*x + pos.x, *y + pos.y);
|
newPos.set(*x + pos.x, *y + pos.y);
|
||||||
updatePosWithParticle(quadStart, newPos, *s, *r);
|
updatePosWithParticle(quadStart, newPos, *s, *r, *sr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto setTexCoords = [this](V3F_C4B_T2F_Quad* quad, unsigned short* cellIndex) {
|
||||||
|
|
||||||
|
float left = 0.0F, bottom = 0.0F, top = 1.0F, right = 1.0F;
|
||||||
|
|
||||||
|
if (_isAnimationAtlas)
|
||||||
|
{
|
||||||
|
float texPixels = getAnimationPixels();
|
||||||
|
float cellPixels = getAnimationCellUnifiedSize();
|
||||||
|
|
||||||
|
left = 0.0F;
|
||||||
|
right = 1.0F;
|
||||||
|
top = *cellIndex * cellPixels / texPixels;
|
||||||
|
bottom = (*cellIndex * cellPixels + cellPixels) / texPixels;
|
||||||
|
|
||||||
|
// Flip texture coords if direction of texture is horizontal
|
||||||
|
if (_animDir == TexAnimDir::HORIZONTAL)
|
||||||
|
{
|
||||||
|
std::swap(top, right);
|
||||||
|
std::swap(left, bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto& index = _animationIndices.at(*cellIndex);
|
||||||
|
|
||||||
|
auto texWidth = _texture->getPixelsWide();
|
||||||
|
auto texHeight = _texture->getPixelsHigh();
|
||||||
|
|
||||||
|
left = index.rect.origin.x / texWidth;
|
||||||
|
right = (index.rect.origin.x + index.rect.size.x) / texWidth;
|
||||||
|
|
||||||
|
top = index.rect.origin.y / texHeight;
|
||||||
|
bottom = (index.rect.origin.y + index.rect.size.y) / texHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
quad->bl.texCoords.u = left;
|
||||||
|
quad->bl.texCoords.v = bottom;
|
||||||
|
|
||||||
|
quad->br.texCoords.u = right;
|
||||||
|
quad->br.texCoords.v = bottom;
|
||||||
|
|
||||||
|
quad->tl.texCoords.u = left;
|
||||||
|
quad->tl.texCoords.v = top;
|
||||||
|
|
||||||
|
quad->tr.texCoords.u = right;
|
||||||
|
quad->tr.texCoords.v = top;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// set color
|
// set color
|
||||||
if (_opacityModifyRGB)
|
if (_opacityModifyRGB)
|
||||||
{
|
{
|
||||||
V3F_C4B_T2F_Quad* quad = startQuad;
|
V3F_C4B_T2F_Quad* quad = startQuad;
|
||||||
float* r = _particleData.colorR;
|
float* r = _particleData.colorR;
|
||||||
float* g = _particleData.colorG;
|
float* g = _particleData.colorG;
|
||||||
float* b = _particleData.colorB;
|
float* b = _particleData.colorB;
|
||||||
float* a = _particleData.colorA;
|
float* a = _particleData.colorA;
|
||||||
|
unsigned short* cellIndex = _particleData.animCellIndex;
|
||||||
|
|
||||||
for (int i = 0; i < _particleCount; ++i, ++quad, ++r, ++g, ++b, ++a)
|
for (int i = 0; i < _particleCount; ++i, ++quad, ++r, ++g, ++b, ++a, ++cellIndex)
|
||||||
{
|
{
|
||||||
uint8_t colorR = *r * *a * 255;
|
uint8_t colorR = *r * *a * 255;
|
||||||
uint8_t colorG = *g * *a * 255;
|
uint8_t colorG = *g * *a * 255;
|
||||||
|
@ -424,17 +481,21 @@ void ParticleSystemQuad::updateParticleQuads()
|
||||||
quad->br.colors.set(colorR, colorG, colorB, colorA);
|
quad->br.colors.set(colorR, colorG, colorB, colorA);
|
||||||
quad->tl.colors.set(colorR, colorG, colorB, colorA);
|
quad->tl.colors.set(colorR, colorG, colorB, colorA);
|
||||||
quad->tr.colors.set(colorR, colorG, colorB, colorA);
|
quad->tr.colors.set(colorR, colorG, colorB, colorA);
|
||||||
|
|
||||||
|
if (_isLifeAnimated || _isEmitterAnimated || _isLoopAnimated)
|
||||||
|
setTexCoords(quad, cellIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
V3F_C4B_T2F_Quad* quad = startQuad;
|
V3F_C4B_T2F_Quad* quad = startQuad;
|
||||||
float* r = _particleData.colorR;
|
float* r = _particleData.colorR;
|
||||||
float* g = _particleData.colorG;
|
float* g = _particleData.colorG;
|
||||||
float* b = _particleData.colorB;
|
float* b = _particleData.colorB;
|
||||||
float* a = _particleData.colorA;
|
float* a = _particleData.colorA;
|
||||||
|
unsigned short* cellIndex = _particleData.animCellIndex;
|
||||||
|
|
||||||
for (int i = 0; i < _particleCount; ++i, ++quad, ++r, ++g, ++b, ++a)
|
for (int i = 0; i < _particleCount; ++i, ++quad, ++r, ++g, ++b, ++a, ++cellIndex)
|
||||||
{
|
{
|
||||||
uint8_t colorR = *r * 255;
|
uint8_t colorR = *r * 255;
|
||||||
uint8_t colorG = *g * 255;
|
uint8_t colorG = *g * 255;
|
||||||
|
@ -444,6 +505,9 @@ void ParticleSystemQuad::updateParticleQuads()
|
||||||
quad->br.colors.set(colorR, colorG, colorB, colorA);
|
quad->br.colors.set(colorR, colorG, colorB, colorA);
|
||||||
quad->tl.colors.set(colorR, colorG, colorB, colorA);
|
quad->tl.colors.set(colorR, colorG, colorB, colorA);
|
||||||
quad->tr.colors.set(colorR, colorG, colorB, colorA);
|
quad->tr.colors.set(colorR, colorG, colorB, colorA);
|
||||||
|
|
||||||
|
if (_isLifeAnimated || _isEmitterAnimated || _isLoopAnimated)
|
||||||
|
setTexCoords(quad, cellIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,6 +310,7 @@ bool AudioEngineImpl::init()
|
||||||
|
|
||||||
if (s_ALDevice)
|
if (s_ALDevice)
|
||||||
{
|
{
|
||||||
|
alGetError();
|
||||||
s_ALContext = alcCreateContext(s_ALDevice, nullptr);
|
s_ALContext = alcCreateContext(s_ALDevice, nullptr);
|
||||||
alcMakeContextCurrent(s_ALContext);
|
alcMakeContextCurrent(s_ALContext);
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ NS_CC_BEGIN
|
||||||
namespace network
|
namespace network
|
||||||
{
|
{
|
||||||
|
|
||||||
Uri::Uri() : _isValid(false), _isSecure(false), _hasAuthority(false), _isCustomPort(false), _port(0) {}
|
Uri::Uri() : _isValid(false), _isSecure(false), _hasAuthority(false), _port(0) {}
|
||||||
|
|
||||||
Uri::Uri(const Uri& o)
|
Uri::Uri(const Uri& o)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +95,6 @@ Uri& Uri::operator=(const Uri& o)
|
||||||
_host = o._host;
|
_host = o._host;
|
||||||
_hostName = o._hostName;
|
_hostName = o._hostName;
|
||||||
_hasAuthority = o._hasAuthority;
|
_hasAuthority = o._hasAuthority;
|
||||||
_isCustomPort = o._isCustomPort;
|
|
||||||
_port = o._port;
|
_port = o._port;
|
||||||
_authority = o._authority;
|
_authority = o._authority;
|
||||||
_pathEtc = o._pathEtc;
|
_pathEtc = o._pathEtc;
|
||||||
|
@ -122,9 +121,7 @@ Uri& Uri::operator=(Uri&& o)
|
||||||
_host = std::move(o._host);
|
_host = std::move(o._host);
|
||||||
_hostName = std::move(o._hostName);
|
_hostName = std::move(o._hostName);
|
||||||
_hasAuthority = o._hasAuthority;
|
_hasAuthority = o._hasAuthority;
|
||||||
_isCustomPort = o._isCustomPort;
|
|
||||||
o._hasAuthority = false;
|
o._hasAuthority = false;
|
||||||
o._isCustomPort = false;
|
|
||||||
_port = o._port;
|
_port = o._port;
|
||||||
o._port = 0;
|
o._port = 0;
|
||||||
_authority = std::move(o._authority);
|
_authority = std::move(o._authority);
|
||||||
|
@ -293,26 +290,18 @@ bool Uri::doParse(std::string_view str)
|
||||||
_isSecure = true;
|
_isSecure = true;
|
||||||
if (_port == 0)
|
if (_port == 0)
|
||||||
_port = 443;
|
_port = 443;
|
||||||
|
|
||||||
_isCustomPort = _port != 443;
|
|
||||||
}
|
}
|
||||||
else if (_scheme == "http" || _scheme == "ws")
|
else if (_scheme == "http" || _scheme == "ws")
|
||||||
{
|
{
|
||||||
if (_port == 0)
|
if (_port == 0)
|
||||||
_port = 80;
|
_port = 80;
|
||||||
|
|
||||||
_isCustomPort = _port != 80;
|
|
||||||
}
|
}
|
||||||
else if (_scheme == "ftp")
|
else if (_scheme == "ftp")
|
||||||
{
|
{
|
||||||
if (_port == 0)
|
if (_port == 0)
|
||||||
_port = 21;
|
_port = 21;
|
||||||
|
|
||||||
_isCustomPort = _port != 21;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
_isCustomPort = _port != 0;
|
|
||||||
|
|
||||||
if (_path.empty())
|
if (_path.empty())
|
||||||
_path.push_back('/');
|
_path.push_back('/');
|
||||||
|
@ -330,7 +319,6 @@ void Uri::clear()
|
||||||
_host.clear();
|
_host.clear();
|
||||||
_hostName.clear();
|
_hostName.clear();
|
||||||
_hasAuthority = false;
|
_hasAuthority = false;
|
||||||
_isCustomPort = false;
|
|
||||||
_port = 0;
|
_port = 0;
|
||||||
_authority.clear();
|
_authority.clear();
|
||||||
_pathEtc.clear();
|
_pathEtc.clear();
|
||||||
|
@ -383,7 +371,7 @@ std::string Uri::toString() const
|
||||||
ss << _username << "@";
|
ss << _username << "@";
|
||||||
}
|
}
|
||||||
ss << _host;
|
ss << _host;
|
||||||
if (_isCustomPort)
|
if (_port != 0)
|
||||||
{
|
{
|
||||||
ss << ":" << _port;
|
ss << ":" << _port;
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,8 +130,6 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string_view getAuthority() const { return _authority; }
|
std::string_view getAuthority() const { return _authority; }
|
||||||
|
|
||||||
bool isCustomPort() const { return _isCustomPort; }
|
|
||||||
|
|
||||||
/** Gets a string representation of the URI. */
|
/** Gets a string representation of the URI. */
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
|
@ -165,14 +163,13 @@ private:
|
||||||
|
|
||||||
bool _isValid;
|
bool _isValid;
|
||||||
bool _isSecure;
|
bool _isSecure;
|
||||||
bool _hasAuthority;
|
|
||||||
bool _isCustomPort;
|
|
||||||
uint16_t _port;
|
|
||||||
std::string _scheme;
|
std::string _scheme;
|
||||||
std::string _username;
|
std::string _username;
|
||||||
std::string _password;
|
std::string _password;
|
||||||
std::string _host;
|
std::string _host;
|
||||||
std::string _hostName;
|
std::string _hostName;
|
||||||
|
bool _hasAuthority;
|
||||||
|
uint16_t _port;
|
||||||
std::string _authority;
|
std::string _authority;
|
||||||
std::string _pathEtc;
|
std::string _pathEtc;
|
||||||
std::string _path;
|
std::string _path;
|
||||||
|
|
|
@ -625,7 +625,7 @@ void AssetsManagerEx::downloadVersion()
|
||||||
{
|
{
|
||||||
_updateState = State::DOWNLOADING_VERSION;
|
_updateState = State::DOWNLOADING_VERSION;
|
||||||
// Download version file asynchronously
|
// Download version file asynchronously
|
||||||
_downloader->createDownloadFileTask(versionUrl, _tempVersionPath, VERSION_ID);
|
_downloader->createDownloadFileTask(versionUrl, _tempVersionPath, "", VERSION_ID);
|
||||||
}
|
}
|
||||||
// No version file found
|
// No version file found
|
||||||
else
|
else
|
||||||
|
@ -696,7 +696,7 @@ void AssetsManagerEx::downloadManifest()
|
||||||
{
|
{
|
||||||
_updateState = State::DOWNLOADING_MANIFEST;
|
_updateState = State::DOWNLOADING_MANIFEST;
|
||||||
// Download version file asynchronously
|
// Download version file asynchronously
|
||||||
_downloader->createDownloadFileTask(manifestUrl, _tempManifestPath, MANIFEST_ID);
|
_downloader->createDownloadFileTask(manifestUrl, _tempManifestPath, "", MANIFEST_ID);
|
||||||
}
|
}
|
||||||
// No manifest file found
|
// No manifest file found
|
||||||
else
|
else
|
||||||
|
@ -1258,7 +1258,7 @@ void AssetsManagerEx::queueDowload()
|
||||||
_currConcurrentTask++;
|
_currConcurrentTask++;
|
||||||
DownloadUnit& unit = _downloadUnits[key];
|
DownloadUnit& unit = _downloadUnits[key];
|
||||||
_fileUtils->createDirectory(basename(unit.storagePath));
|
_fileUtils->createDirectory(basename(unit.storagePath));
|
||||||
_downloader->createDownloadFileTask(unit.srcUrl, unit.storagePath, unit.customId);
|
_downloader->createDownloadFileTask(unit.srcUrl, unit.storagePath, "", unit.customId);
|
||||||
|
|
||||||
_tempManifest->setAssetDownloadState(key, Manifest::DownloadState::DOWNLOADING);
|
_tempManifest->setAssetDownloadState(key, Manifest::DownloadState::DOWNLOADING);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1204,7 +1204,7 @@ void ParseUriTest::onEnter()
|
||||||
EXPECT_EQ("ws", v.getScheme());
|
EXPECT_EQ("ws", v.getScheme());
|
||||||
EXPECT_EQ("localhost", v.getHost());
|
EXPECT_EQ("localhost", v.getHost());
|
||||||
EXPECT_EQ("localhost", v.getHostName());
|
EXPECT_EQ("localhost", v.getHostName());
|
||||||
EXPECT_EQ("/", v.getPath());
|
EXPECT_EQ("", v.getPath());
|
||||||
EXPECT_EQ(90, v.getPort());
|
EXPECT_EQ(90, v.getPort());
|
||||||
EXPECT_EQ("", v.getFragment());
|
EXPECT_EQ("", v.getFragment());
|
||||||
EXPECT_EQ("key1=foo=bar&key2=foobar&", v.getQuery());
|
EXPECT_EQ("key1=foo=bar&key2=foobar&", v.getQuery());
|
||||||
|
@ -1219,7 +1219,7 @@ void ParseUriTest::onEnter()
|
||||||
EXPECT_EQ("ws", v.getScheme());
|
EXPECT_EQ("ws", v.getScheme());
|
||||||
EXPECT_EQ("localhost", v.getHost());
|
EXPECT_EQ("localhost", v.getHost());
|
||||||
EXPECT_EQ("localhost", v.getHostName());
|
EXPECT_EQ("localhost", v.getHostName());
|
||||||
EXPECT_EQ("/", v.getPath());
|
EXPECT_EQ("", v.getPath());
|
||||||
EXPECT_EQ(90, v.getPort());
|
EXPECT_EQ(90, v.getPort());
|
||||||
EXPECT_EQ("", v.getFragment());
|
EXPECT_EQ("", v.getFragment());
|
||||||
EXPECT_EQ("key1=foo=bar&key2=foobar&", v.getQuery());
|
EXPECT_EQ("key1=foo=bar&key2=foobar&", v.getQuery());
|
||||||
|
@ -1246,7 +1246,7 @@ void ParseUriTest::onEnter()
|
||||||
EXPECT_EQ("ws", v.getScheme());
|
EXPECT_EQ("ws", v.getScheme());
|
||||||
EXPECT_EQ("localhost", v.getHost());
|
EXPECT_EQ("localhost", v.getHost());
|
||||||
EXPECT_EQ("localhost", v.getHostName());
|
EXPECT_EQ("localhost", v.getHostName());
|
||||||
EXPECT_EQ("/", v.getPath());
|
EXPECT_EQ("", v.getPath());
|
||||||
EXPECT_EQ(90, v.getPort());
|
EXPECT_EQ(90, v.getPort());
|
||||||
EXPECT_EQ("", v.getFragment());
|
EXPECT_EQ("", v.getFragment());
|
||||||
EXPECT_EQ("key1=foo=bar&key2=foobar&", v.getQuery());
|
EXPECT_EQ("key1=foo=bar&key2=foobar&", v.getQuery());
|
||||||
|
@ -1262,7 +1262,7 @@ void ParseUriTest::onEnter()
|
||||||
EXPECT_EQ("ws", v.getScheme());
|
EXPECT_EQ("ws", v.getScheme());
|
||||||
EXPECT_EQ("localhost", v.getHost());
|
EXPECT_EQ("localhost", v.getHost());
|
||||||
EXPECT_EQ("localhost", v.getHostName());
|
EXPECT_EQ("localhost", v.getHostName());
|
||||||
EXPECT_EQ("/", v.getPath());
|
EXPECT_EQ("", v.getPath());
|
||||||
EXPECT_EQ(90, v.getPort());
|
EXPECT_EQ(90, v.getPort());
|
||||||
EXPECT_EQ("", v.getFragment());
|
EXPECT_EQ("", v.getFragment());
|
||||||
EXPECT_EQ("key1=foo=bar&key2=foobar&", v.getQuery());
|
EXPECT_EQ("key1=foo=bar&key2=foobar&", v.getQuery());
|
||||||
|
@ -1386,20 +1386,20 @@ void ParseUriTest::onEnter()
|
||||||
EXPECT_EQ(u4.getScheme(), "");
|
EXPECT_EQ(u4.getScheme(), "");
|
||||||
EXPECT_EQ(u4.getHost(), "localhost");
|
EXPECT_EQ(u4.getHost(), "localhost");
|
||||||
EXPECT_EQ(u4.getPort(), 8080);
|
EXPECT_EQ(u4.getPort(), 8080);
|
||||||
EXPECT_EQ(u4.getPath(), "/");
|
EXPECT_EQ(u4.getPath(), "");
|
||||||
EXPECT_EQ(u4.getPathEtc(), "");
|
EXPECT_EQ(u4.getPathEtc(), "");
|
||||||
|
|
||||||
EXPECT_EQ(u5.getScheme(), "bb");
|
EXPECT_EQ(u5.getScheme(), "bb");
|
||||||
EXPECT_EQ(u5.getHost(), "localhost");
|
EXPECT_EQ(u5.getHost(), "localhost");
|
||||||
EXPECT_EQ(u5.getPort(), 0);
|
EXPECT_EQ(u5.getPort(), 0);
|
||||||
EXPECT_EQ(u5.getPath(), "/");
|
EXPECT_EQ(u5.getPath(), "");
|
||||||
EXPECT_EQ(u5.getPathEtc(), "?&foo=12:4&ccc=13");
|
EXPECT_EQ(u5.getPathEtc(), "?&foo=12:4&ccc=13");
|
||||||
EXPECT_EQ(u5.getQuery(), "&foo=12:4&ccc=13");
|
EXPECT_EQ(u5.getQuery(), "&foo=12:4&ccc=13");
|
||||||
|
|
||||||
EXPECT_EQ(u6.getScheme(), "cc");
|
EXPECT_EQ(u6.getScheme(), "cc");
|
||||||
EXPECT_EQ(u6.getHost(), "localhost");
|
EXPECT_EQ(u6.getHost(), "localhost");
|
||||||
EXPECT_EQ(u6.getPort(), 91);
|
EXPECT_EQ(u6.getPort(), 91);
|
||||||
EXPECT_EQ(u6.getPath(), "/");
|
EXPECT_EQ(u6.getPath(), "");
|
||||||
EXPECT_EQ(u6.getPathEtc(), "?&foo=321&bbb=1");
|
EXPECT_EQ(u6.getPathEtc(), "?&foo=321&bbb=1");
|
||||||
EXPECT_EQ(u6.getQuery(), "&foo=321&bbb=1");
|
EXPECT_EQ(u6.getQuery(), "&foo=321&bbb=1");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue