Merge pull request #11995 from MAUSMAUSgames/v3

using Action::_tag as flag field
This commit is contained in:
子龙山人 2015-07-13 22:19:03 +08:00
commit cdc7e5205b
8 changed files with 133 additions and 0 deletions

View File

@ -40,6 +40,7 @@ Action::Action()
:_originalTarget(nullptr)
,_target(nullptr)
,_tag(Action::INVALID_TAG)
,_flags(0)
{
}

View File

@ -143,6 +143,16 @@ public:
* @param tag Used to identify the action easily.
*/
inline void setTag(int tag) { _tag = tag; }
/** Returns a flag field that is used to group the actions easily.
*
* @return A tag.
*/
inline unsigned int getFlags() const { return _flags; }
/** Changes the flag field that is used to group the actions easily.
*
* @param tag Used to identify the action easily.
*/
inline void setFlags(unsigned int flags) { _flags = flags; }
CC_CONSTRUCTOR_ACCESS:
Action();
@ -159,6 +169,8 @@ protected:
Node *_target;
/** The action tag. An identifier of the action. */
int _tag;
/** The action flag field. To categorize action into certain groups.*/
unsigned int _flags;
private:
CC_DISALLOW_COPY_AND_ASSIGN(Action);

View File

@ -315,6 +315,37 @@ void ActionManager::removeAllActionsByTag(int tag, Node *target)
}
}
void ActionManager::removeActionsByFlags(unsigned int flags, Node *target)
{
if (flags == 0)
{
return;
}
CCASSERT(target != nullptr, "");
tHashElement *element = nullptr;
HASH_FIND_PTR(_targets, &target, element);
if (element)
{
auto limit = element->actions->num;
for (int i = 0; i < limit;)
{
Action *action = (Action*)element->actions->arr[i];
if ((action->getFlags() & flags) != 0 && action->getOriginalTarget() == target)
{
removeActionAtIndex(i, element);
--limit;
}
else
{
++i;
}
}
}
}
// get
// FIXME: Passing "const O *" instead of "const O&" because HASH_FIND_IT requries the address of a pointer

View File

@ -114,6 +114,14 @@ public:
*/
void removeAllActionsByTag(int tag, Node *target);
/** Removes all actions matching at least one bit in flags and the target.
*
* @param flags The flag field to match the actions' flags based on bitwise AND.
* @param target A certain target.
* @js NA
*/
void removeActionsByFlags(unsigned int flags, Node *target);
/** Gets an action given its tag an a target.
*
* @param tag The action's tag.

View File

@ -1576,6 +1576,14 @@ void Node::stopAllActionsByTag(int tag)
_actionManager->removeAllActionsByTag(tag, this);
}
void Node::stopActionsByFlags(unsigned int flags)
{
if (flags > 0)
{
_actionManager->removeActionsByFlags(flags, this);
}
}
Action * Node::getActionByTag(int tag)
{
CCASSERT( tag != Action::INVALID_TAG, "Invalid tag");

View File

@ -1228,6 +1228,13 @@ public:
*/
void stopAllActionsByTag(int tag);
/**
* Removes all actions from the running action list by its flags.
*
* @param flags A flag field that removes actions based on bitwise AND.
*/
void stopActionsByFlags(unsigned int flags);
/**
* Gets an action from the running action list by its tag.
*

View File

@ -18,6 +18,7 @@ ActionManagerTests::ActionManagerTests()
ADD_TEST_CASE(PauseTest);
ADD_TEST_CASE(StopActionTest);
ADD_TEST_CASE(StopAllActionsTest);
ADD_TEST_CASE(StopActionsByFlagsTest);
ADD_TEST_CASE(ResumeTest);
}
@ -291,3 +292,53 @@ void ResumeTest::resumeGrossini(float time)
auto director = Director::getInstance();
director->getActionManager()->resumeTarget(pGrossini);
}
//------------------------------------------------------------------
//
// StopActionsByFlagsTest
//
//------------------------------------------------------------------
void StopActionsByFlagsTest::onEnter()
{
ActionManagerTest::onEnter();
auto l = Label::createWithTTF("Should stop scale & move after 4 seconds but keep rotate", "fonts/Thonburi.ttf", 16.0f);
addChild(l);
l->setPosition( Vec2(VisibleRect::center().x, VisibleRect::top().y - 75) );
auto pMove1 = MoveBy::create(2, Vec2(200, 0));
auto pMove2 = MoveBy::create(2, Vec2(-200, 0));
auto pSequenceMove = Sequence::createWithTwoActions(pMove1, pMove2);
auto pRepeatMove = RepeatForever::create(pSequenceMove);
pRepeatMove->setFlags(kMoveFlag | kRepeatForeverFlag);
auto pScale1 = ScaleBy::create(2, 1.5f);
auto pScale2 = ScaleBy::create(2, 1.0f/1.5f);
auto pSequenceScale = Sequence::createWithTwoActions(pScale1, pScale2);
auto pRepeatScale = RepeatForever::create(pSequenceScale);
pRepeatScale->setFlags(kScaleFlag | kRepeatForeverFlag);
auto pRotate = RotateBy::create(2, 360);
auto pRepeatRotate = RepeatForever::create(pRotate);
pRepeatRotate->setFlags(kRotateFlag | kRepeatForeverFlag);
auto pChild = Sprite::create(s_pathGrossini);
pChild->setPosition( VisibleRect::center() );
addChild(pChild, 1, kTagGrossini);
pChild->runAction(pRepeatMove);
pChild->runAction(pRepeatScale);
pChild->runAction(pRepeatRotate);
this->scheduleOnce((SEL_SCHEDULE)&StopActionsByFlagsTest::stopAction, 4);
}
void StopActionsByFlagsTest::stopAction(float time)
{
auto sprite = getChildByTag(kTagGrossini);
sprite->stopActionsByFlags(kMoveFlag | kScaleFlag);
}
std::string StopActionsByFlagsTest::subtitle() const
{
return "Stop All Actions By Flags Test";
}

View File

@ -80,4 +80,19 @@ public:
void resumeGrossini(float time);
};
class StopActionsByFlagsTest : public ActionManagerTest
{
public:
CREATE_FUNC(StopActionsByFlagsTest);
virtual std::string subtitle() const override;
virtual void onEnter() override;
void stopAction(float time);
protected:
const unsigned int kMoveFlag = 0x01;
const unsigned int kScaleFlag = 0x02;
const unsigned int kRotateFlag = 0x04;
const unsigned int kRepeatForeverFlag = 0x08; // You don't need this for the test, but it's for demonstration how to activate several flags on an action.
};
#endif