| @@ -0,0 +1,175 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Parallel.h" | ||
|
|
||
| #include "console/engineAPI.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Parallel node | ||
| //------------------------------------------------------------------------------ | ||
| IMPLEMENT_CONOBJECT(Parallel); | ||
|
|
||
| Parallel::Parallel() | ||
| : mReturnPolicy(REQUIRE_ALL) | ||
| { | ||
| } | ||
|
|
||
| ImplementEnumType( ParallelReturnPolicy, | ||
| "@brief The policy to use when determining the return status of a parallel node.\n\n" | ||
| "@ingroup AI\n\n") | ||
| { Parallel::REQUIRE_ALL, "REQUIRE_ALL", "Will return success if all children succeed.\n" | ||
| "Will terminate and return failure if one child fails \n"}, | ||
| { Parallel::REQUIRE_NONE, "REQUIRE_NONE", "Will return success even if all children fail.\n" }, | ||
| { Parallel::REQUIRE_ONE, "REQUIRE_ONE", "Will terminate and return success when one child succeeds.\n" }, | ||
| EndImplementEnumType; | ||
|
|
||
| void Parallel::initPersistFields() | ||
| { | ||
| addGroup( "Behavior" ); | ||
|
|
||
| addField( "returnPolicy", TYPEID< Parallel::ParallelPolicy >(), Offset(mReturnPolicy, Parallel), | ||
| "@brief The policy to use when deciding the return status for the parallel sequence."); | ||
|
|
||
| endGroup( "Behavior" ); | ||
|
|
||
| Parent::initPersistFields(); | ||
| } | ||
|
|
||
| Task *Parallel::createTask(SimObject &owner, BehaviorTreeRunner &runner) | ||
| { | ||
| return new ParallelTask(*this, owner, runner); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Parallel Task | ||
| //------------------------------------------------------------------------------ | ||
| ParallelTask::ParallelTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner), | ||
| mHasSuccess(false), | ||
| mHasFailure(false) | ||
| { | ||
| } | ||
|
|
||
| void ParallelTask::onInitialize() | ||
| { | ||
| Parent::onInitialize(); | ||
|
|
||
| mHasSuccess = mHasFailure = false; | ||
|
|
||
| if(mBranches.empty()) | ||
| { | ||
| for (VectorPtr<Task*>::iterator i = mChildren.begin(); i != mChildren.end(); ++i) | ||
| { | ||
| mBranches.push_back(BehaviorTreeBranch(*i)); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| for (Vector<BehaviorTreeBranch>::iterator it = mBranches.begin(); it != mBranches.end(); ++it) | ||
| { | ||
| it->reset(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Task* ParallelTask::update() | ||
| { | ||
| bool hasRunning = false, hasSuspended = false, hasResume = false; | ||
| for (Vector<BehaviorTreeBranch>::iterator it = mBranches.begin(); it != mBranches.end(); ++it) | ||
| { | ||
| Status s = it->getStatus(); | ||
| if(s == INVALID || s == RUNNING || s == RESUME) | ||
| { | ||
| s = it->update(); | ||
|
|
||
| switch(it->getStatus()) | ||
| { | ||
| case SUCCESS: | ||
| mHasSuccess = true; | ||
| break; | ||
| case FAILURE: | ||
| mHasFailure = true; | ||
| break; | ||
| case RUNNING: | ||
| hasRunning = true; | ||
| break; | ||
| case SUSPENDED: | ||
| hasSuspended = true; | ||
| break; | ||
| case RESUME: | ||
| hasResume = true; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| switch(static_cast<Parallel *>(mNodeRep)->getReturnPolicy()) | ||
| { | ||
| // REQUIRE_NONE | ||
| // returns SUCCESS when all children have finished irrespective of their return status. | ||
| case Parallel::REQUIRE_NONE: | ||
| mStatus = hasResume ? RESUME : ( hasRunning ? RUNNING : ( hasSuspended ? SUSPENDED : SUCCESS ) ); | ||
| break; | ||
|
|
||
| // REQUIRE_ONE | ||
| // terminates and returns SUCCESS when any of its children succeed | ||
| // returns FAILURE if no children succeed | ||
| case Parallel::REQUIRE_ONE: | ||
| mStatus = mHasSuccess ? SUCCESS : ( hasResume ? RESUME : ( hasRunning ? RUNNING : ( hasSuspended ? SUSPENDED : FAILURE ) ) ); | ||
| break; | ||
|
|
||
| // REQUIRE_ALL | ||
| // returns SUCCESS if all of its children succeed. | ||
| // terminates and returns failure if any of its children fail | ||
| case Parallel::REQUIRE_ALL: | ||
| mStatus = mHasFailure ? FAILURE : ( hasResume ? RESUME : ( hasRunning ? RUNNING : ( hasSuspended ? SUSPENDED : SUCCESS ) ) ); | ||
| break; | ||
| } | ||
|
|
||
| mIsComplete = (mStatus != RUNNING && mStatus != SUSPENDED && mStatus != RESUME); | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
|
|
||
| Status ParallelTask::getStatus() | ||
| { | ||
| if(mStatus == SUSPENDED) | ||
| { | ||
| // need to check if the parallel is still suspended. | ||
| // A parallel will only report SUSPENDED when all of its children are suspended | ||
| for(Vector<BehaviorTreeBranch>::iterator it = mBranches.begin(); it != mBranches.end(); ++it) | ||
| { | ||
| switch(it->getStatus()) | ||
| { | ||
| case RUNNING: | ||
| return RUNNING; | ||
| case RESUME: | ||
| return RESUME; | ||
| } | ||
| } | ||
| } | ||
| return mStatus; | ||
| } |
| @@ -0,0 +1,97 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_PARALLEL_H_ | ||
| #define _BB_PARALLEL_H_ | ||
|
|
||
| #ifndef _BB_CORE_H_ | ||
| #include "BadBehavior/core/Composite.h" | ||
| #endif | ||
|
|
||
| #ifndef _BB_BRANCH_H_ | ||
| #include "BadBehavior/core/Branch.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // Parallel sequence node | ||
| // Runs all of its children irrespective of their return status | ||
| // The final return status depends on the chosen policy | ||
| // (not a true parallel, as branches are actually evaluated sequentially) | ||
| //--------------------------------------------------------------------------- | ||
| class Parallel: public CompositeNode | ||
| { | ||
| typedef CompositeNode Parent; | ||
|
|
||
| public: | ||
| // parallel return policies | ||
| enum ParallelPolicy | ||
| { | ||
| REQUIRE_NONE, | ||
| REQUIRE_ONE, | ||
| REQUIRE_ALL, | ||
| }; | ||
|
|
||
| protected: | ||
| ParallelPolicy mReturnPolicy; | ||
|
|
||
| public: | ||
| Parallel(); | ||
|
|
||
| virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| static void initPersistFields(); | ||
|
|
||
| ParallelPolicy getReturnPolicy() const { return mReturnPolicy; } | ||
|
|
||
| DECLARE_CONOBJECT(Parallel); | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Parallel Task | ||
| //--------------------------------------------------------------------------- | ||
| class ParallelTask: public CompositeTask | ||
| { | ||
| typedef CompositeTask Parent; | ||
|
|
||
| protected: | ||
| Vector<BehaviorTreeBranch> mBranches; | ||
|
|
||
| bool mHasSuccess, mHasFailure; | ||
|
|
||
| virtual void onInitialize(); | ||
| virtual Task* update(); | ||
|
|
||
| public: | ||
| ParallelTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| virtual Status getStatus(); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| // make the return policy enum accessible from script | ||
| typedef BadBehavior::Parallel::ParallelPolicy ParallelReturnPolicy; | ||
| DefineEnumType( ParallelReturnPolicy ); | ||
|
|
||
| #endif |
| @@ -0,0 +1,68 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "RandomSelector.h" | ||
|
|
||
| #include "math/mMathFn.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Random selector node | ||
| //------------------------------------------------------------------------------ | ||
| IMPLEMENT_CONOBJECT(RandomSelector); | ||
|
|
||
| Task *RandomSelector::createTask(SimObject &owner, BehaviorTreeRunner &runner) | ||
| { | ||
| return new RandomSelectorTask(*this, owner, runner); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Random selector task | ||
| //------------------------------------------------------------------------------ | ||
| RandomSelectorTask::RandomSelectorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner) | ||
| { | ||
| } | ||
|
|
||
| void RandomSelectorTask::onInitialize() | ||
| { | ||
| Parent::onInitialize(); | ||
|
|
||
| // randomize the order of our child tasks | ||
| VectorPtr<Task *> randomChildren; | ||
|
|
||
| while(mChildren.size() > 0) | ||
| { | ||
| U32 index = mRandI(0, mChildren.size() - 1); | ||
| Task* child = mChildren[index]; | ||
| randomChildren.push_back(child); | ||
| mChildren.erase_fast(index); | ||
| } | ||
|
|
||
| mChildren = randomChildren; | ||
|
|
||
| // normal init | ||
| mCurrentChild = mChildren.begin(); | ||
| if(mCurrentChild != mChildren.end()) | ||
| (*mCurrentChild)->reset(); | ||
| } |
| @@ -0,0 +1,62 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_RANDOMSELECTOR_H_ | ||
| #define _BB_RANDOMSELECTOR_H_ | ||
|
|
||
| #ifndef _BB_SELECTOR_H_ | ||
| #include "Selector.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // Random selector node | ||
| // selects its children in a random order until one of them succeeds | ||
| //--------------------------------------------------------------------------- | ||
| class RandomSelector : public Selector | ||
| { | ||
| typedef Selector Parent; | ||
|
|
||
| public: | ||
| virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| DECLARE_CONOBJECT(RandomSelector); | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Random selector task | ||
| //--------------------------------------------------------------------------- | ||
| class RandomSelectorTask : public SelectorTask | ||
| { | ||
| typedef SelectorTask Parent; | ||
|
|
||
| protected: | ||
| virtual void onInitialize(); | ||
|
|
||
| public: | ||
| RandomSelectorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,54 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Selector.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Selector node | ||
| //------------------------------------------------------------------------------ | ||
| IMPLEMENT_CONOBJECT(Selector); | ||
|
|
||
| Task *Selector::createTask(SimObject &owner, BehaviorTreeRunner &runner) | ||
| { | ||
| return new SelectorTask(*this, owner, runner); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Selector task | ||
| //------------------------------------------------------------------------------ | ||
| SelectorTask::SelectorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner) | ||
| { | ||
| } | ||
|
|
||
| void SelectorTask::onChildComplete(Status s) | ||
| { | ||
| mStatus = s; | ||
|
|
||
| // if child failed, move on to the next child | ||
| if(mStatus == FAILURE) | ||
| ++mCurrentChild; | ||
| else | ||
| mIsComplete = true; | ||
| } |
| @@ -0,0 +1,60 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_SELECTOR_H_ | ||
| #define _BBSELECTOR_H_ | ||
|
|
||
| #ifndef _BB_CORE_H_ | ||
| #include "BadBehavior/core/Composite.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // Selector Node | ||
| //--------------------------------------------------------------------------- | ||
| class Selector : public CompositeNode | ||
| { | ||
| typedef CompositeNode Parent; | ||
|
|
||
| public: | ||
| virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| DECLARE_CONOBJECT(Selector); | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Selector Task | ||
| //--------------------------------------------------------------------------- | ||
| class SelectorTask : public CompositeTask | ||
| { | ||
| typedef CompositeTask Parent; | ||
|
|
||
| public: | ||
| SelectorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| virtual void onChildComplete(Status); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,55 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Sequence.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Sequence node | ||
| //------------------------------------------------------------------------------ | ||
| IMPLEMENT_CONOBJECT(Sequence); | ||
|
|
||
| Task *Sequence::createTask(SimObject &owner, BehaviorTreeRunner &runner) | ||
| { | ||
| return new SequenceTask(*this, owner, runner); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Sequence Task | ||
| //------------------------------------------------------------------------------ | ||
| SequenceTask::SequenceTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner) | ||
| { | ||
| } | ||
|
|
||
| void SequenceTask::onChildComplete(Status s) | ||
| { | ||
| mStatus = s; | ||
|
|
||
| // if child succeeded, move on to the next child | ||
| if(mStatus == SUCCESS) | ||
| ++mCurrentChild; | ||
| else | ||
| mIsComplete = true; | ||
| } | ||
|
|
| @@ -0,0 +1,60 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_SEQUENCE_H_ | ||
| #define _BB_SEQUENCE_H_ | ||
|
|
||
| #ifndef _BB_CORE_H_ | ||
| #include "BadBehavior/core/Composite.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // Sequence Node | ||
| //--------------------------------------------------------------------------- | ||
| class Sequence : public CompositeNode | ||
| { | ||
| typedef CompositeNode Parent; | ||
|
|
||
| public: | ||
| virtual Task* createTask(SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| DECLARE_CONOBJECT(Sequence); | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Sequence Task | ||
| //--------------------------------------------------------------------------- | ||
| class SequenceTask : public CompositeTask | ||
| { | ||
| typedef CompositeTask Parent; | ||
|
|
||
| public: | ||
| SequenceTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| virtual void onChildComplete(Status); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,66 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Branch.h" | ||
| #include "Stepper.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| BehaviorTreeBranch::BehaviorTreeBranch() | ||
| : mRootTask(NULL) | ||
| { | ||
| } | ||
|
|
||
| BehaviorTreeBranch::BehaviorTreeBranch(Task *root) | ||
| : mRootTask(root), | ||
| mStatus(INVALID) | ||
| { | ||
| } | ||
|
|
||
| Status BehaviorTreeBranch::getStatus() | ||
| { | ||
| if(!mTasks.empty()) | ||
| return mTasks.back()->getStatus(); | ||
|
|
||
| return mStatus; | ||
| } | ||
|
|
||
| Status BehaviorTreeBranch::update() | ||
| { | ||
| if(mRootTask) | ||
| { | ||
| if(mTasks.empty()) | ||
| { | ||
| mRootTask->setup(); | ||
| mTasks.push_back(mRootTask); | ||
| } | ||
| } | ||
| mStatus = BehaviorTreeStepper::stepThrough(mTasks); | ||
| return mStatus; | ||
| } | ||
|
|
||
| void BehaviorTreeBranch::reset() | ||
| { | ||
| mStatus = INVALID; | ||
| mRootTask->reset(); | ||
| mTasks.clear(); | ||
| } |
| @@ -0,0 +1,53 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_BRANCH_H_ | ||
| #define _BB_BRANCH_H_ | ||
|
|
||
| #ifndef _BB_CORE_H_ | ||
| #include "Core.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| // The branch class handles a single execution path in the tree | ||
| // Typically used for the tree root and for handling suspension and concurrency | ||
| class BehaviorTreeBranch | ||
| { | ||
| private: | ||
| Status mStatus; | ||
| Task *mRootTask; | ||
| VectorPtr<Task *> mTasks; | ||
|
|
||
| public: | ||
| BehaviorTreeBranch(); | ||
| BehaviorTreeBranch(Task *root); | ||
|
|
||
| Status getStatus(); | ||
| Status update(); | ||
| void reset(); | ||
| }; | ||
|
|
||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,110 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Composite.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Base composite node | ||
| // override addObject to only allow behavior tree nodes to be added | ||
| //------------------------------------------------------------------------------ | ||
| void CompositeNode::addObject(SimObject *object) | ||
| { | ||
| if(dynamic_cast<Node*>(object)) | ||
| Parent::addObject(object); | ||
| } | ||
|
|
||
| bool CompositeNode::acceptsAsChild( SimObject *object ) const | ||
| { | ||
| return (dynamic_cast<Node*>(object)); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Base composite task | ||
| //------------------------------------------------------------------------------ | ||
| CompositeTask::CompositeTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner) | ||
| { | ||
| } | ||
|
|
||
| CompositeTask::~CompositeTask() | ||
| { | ||
| while(mChildren.size()) | ||
| { | ||
| Task *child = mChildren.back(); | ||
| mChildren.pop_back(); | ||
| if(child) | ||
| delete child; | ||
| } | ||
| } | ||
|
|
||
| void CompositeTask::onInitialize() | ||
| { | ||
| if(mChildren.empty()) | ||
| { | ||
| CompositeNode *node = static_cast<CompositeNode *>(mNodeRep); | ||
| for(SimSet::iterator i = node->begin(); i != node->end(); ++i) | ||
| { | ||
| Task *task = static_cast<Node*>(*i)->createTask(*mOwner, *mRunner); | ||
| if(task) | ||
| { | ||
| task->setParent(this); | ||
| mChildren.push_back(task); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| mStatus = INVALID; | ||
| mCurrentChild = mChildren.begin(); | ||
| if(mCurrentChild != mChildren.end()) | ||
| (*mCurrentChild)->reset(); | ||
| } | ||
|
|
||
| void CompositeTask::onTerminate() | ||
| { | ||
| mStatus = INVALID; | ||
| } | ||
|
|
||
| Task* CompositeTask::update() | ||
| { | ||
| // reached the end of child list, we are complete | ||
| if (mCurrentChild == mChildren.end()) | ||
| mIsComplete = true; | ||
|
|
||
| // task has finished | ||
| if( mIsComplete ) | ||
| { | ||
| // are we latent? | ||
| if(mStatus == RUNNING || mStatus == SUSPENDED) | ||
| mIsComplete = false; | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| // reset the child ready for the next tick | ||
| if(mStatus != RUNNING && mStatus != SUSPENDED) | ||
| (*mCurrentChild)->reset(); | ||
|
|
||
| // return child | ||
| return (*mCurrentChild); | ||
| } |
| @@ -0,0 +1,70 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_COMPOSITE_H_ | ||
| #define _BB_COMPOSITE_H_ | ||
|
|
||
| #ifndef _BB_CORE_H_ | ||
| #include "Core.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // Composite node base class - for nodes with children | ||
| //--------------------------------------------------------------------------- | ||
| class CompositeNode : public Node | ||
| { | ||
| typedef Node Parent; | ||
|
|
||
| public: | ||
| // override addObject and acceptsAsChild to only allow behavior tree nodes to be added as children | ||
| virtual void addObject(SimObject *obj); | ||
| virtual bool acceptsAsChild( SimObject *object ) const; | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Composite task base class | ||
| //--------------------------------------------------------------------------- | ||
| class CompositeTask : public Task | ||
| { | ||
| typedef Task Parent; | ||
|
|
||
| protected: | ||
| // vector of pointers to child tasks | ||
| VectorPtr<Task*> mChildren; | ||
|
|
||
| // the current child task | ||
| VectorPtr<Task*>::iterator mCurrentChild; | ||
|
|
||
| virtual void onInitialize(); | ||
| virtual void onTerminate(); | ||
| virtual Task* update(); | ||
|
|
||
| public: | ||
| CompositeTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
| virtual ~CompositeTask(); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,161 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Core.h" | ||
| #include "Runner.h" | ||
|
|
||
| #include "console/engineAPI.h" | ||
| #include "platform/profiler.h" | ||
|
|
||
| bool gInBtEditor = false; | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // script enum for return type | ||
| //------------------------------------------------------------------------------ | ||
| ImplementEnumType( BehaviorReturnType, | ||
| "@brief The return status for a behavior.\n\n" | ||
| "@ingroup AI\n\n") | ||
| // not needed script side | ||
| //{ BadBehavior::INVALID, "INVALID", "The behavior could not be evaluated.\n" }, | ||
| { BadBehavior::SUCCESS, "SUCCESS", "The behavior succeeded.\n" }, | ||
| { BadBehavior::FAILURE, "FAILURE", "The behavior failed.\n" }, | ||
| { BadBehavior::RUNNING, "RUNNING", "The behavior is still running.\n" }, | ||
| // not needed script side | ||
| //{ BadBehavior::SUSPENDED, "SUSPENDED", "The behavior has been suspended.\n" }, | ||
| //{ BadBehavior::RESUME, "RESUME", "The behavior is resuming from suspended.\n" } | ||
| EndImplementEnumType; | ||
|
|
||
|
|
||
| //================================LeafNode====================================== | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // don't allow objects to be added | ||
| //------------------------------------------------------------------------------ | ||
| void LeafNode::addObject(SimObject *object) | ||
| { | ||
| } | ||
|
|
||
| bool LeafNode::acceptsAsChild( SimObject *object ) const | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
|
|
||
| //==================================Task======================================== | ||
|
|
||
| Task::Task(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : mStatus(INVALID), | ||
| mIsComplete(false), | ||
| mNodeRep(&node), | ||
| mOwner(&owner), | ||
| mRunner(&runner), | ||
| mParent(NULL) | ||
| { | ||
| } | ||
|
|
||
| Task::~Task() | ||
| { | ||
| } | ||
|
|
||
| void Task::onInitialize() | ||
| { | ||
| } | ||
|
|
||
| void Task::onTerminate() | ||
| { | ||
| } | ||
|
|
||
| Task* Task::tick() | ||
| { | ||
| PROFILE_SCOPE(Task_Tick); | ||
|
|
||
| return update(); | ||
| } | ||
|
|
||
| void Task::setup() | ||
| { | ||
| PROFILE_SCOPE(Task_setup); | ||
|
|
||
| if(mStatus != RUNNING && mStatus != SUSPENDED) | ||
| onInitialize(); | ||
|
|
||
| mIsComplete = false; | ||
| } | ||
|
|
||
| void Task::finish() | ||
| { | ||
| if(mIsComplete) | ||
| onTerminate(); | ||
| } | ||
|
|
||
| void Task::reset() | ||
| { | ||
| mStatus = INVALID; | ||
| } | ||
|
|
||
| Status Task::getStatus() | ||
| { | ||
| return mStatus; | ||
| } | ||
|
|
||
| void Task::setStatus(Status newStatus) | ||
| { | ||
| mStatus = newStatus; | ||
| } | ||
|
|
||
| void Task::setParent(Task *parent) | ||
| { | ||
| mParent = parent; | ||
| } | ||
|
|
||
| Task *Task::getParent() | ||
| { | ||
| return mParent; | ||
| } | ||
|
|
||
| void Task::onChildComplete(Status) | ||
| { | ||
| } | ||
|
|
||
| void Task::onResume() | ||
| { | ||
| if(mStatus == SUSPENDED) | ||
| mStatus = RESUME; | ||
|
|
||
| //Con::warnf("onResume %s", | ||
| // mNodeRep->getIdString()); | ||
| } | ||
|
|
||
| DefineEngineFunction(onBehaviorTreeEditorStart, void, (),, | ||
| "@brief Notify the engine that the behavior tree editor is active") | ||
| { | ||
| gInBtEditor = true; | ||
| } | ||
|
|
||
|
|
||
| DefineEngineFunction(onBehaviorTreeEditorStop, void, (),, | ||
| "@brief Notify the engine that the behavior tree editor has finished") | ||
| { | ||
| gInBtEditor = false; | ||
| } |
| @@ -0,0 +1,151 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BBCORE_H_ | ||
| #define _BBCORE_H_ | ||
|
|
||
| #ifndef _SIMSET_H_ | ||
| #include "console/simSet.h" | ||
| #endif | ||
| #ifndef _SIMOBJECT_H_ | ||
| #include "console/simObject.h" | ||
| #endif | ||
|
|
||
| extern bool gInBtEditor; | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // return status values | ||
| //--------------------------------------------------------------------------- | ||
| enum Status | ||
| { | ||
| INVALID = -1, | ||
| FAILURE, | ||
| SUCCESS, | ||
| RUNNING, | ||
| SUSPENDED, | ||
| RESUME | ||
| }; | ||
|
|
||
| class Task; | ||
| class BehaviorTreeRunner; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // node base class | ||
| // derived from SimGroup for easy editor integration | ||
| //--------------------------------------------------------------------------- | ||
| class Node : public SimGroup | ||
| { | ||
| typedef SimGroup Parent; | ||
|
|
||
| public: | ||
| // create a runtime task for this node | ||
| virtual Task* createTask(SimObject &owner, BehaviorTreeRunner &runner) = 0; | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Leaf node base class - for nodes without children | ||
| //--------------------------------------------------------------------------- | ||
| class LeafNode : public Node | ||
| { | ||
| typedef Node Parent; | ||
|
|
||
| public: | ||
| virtual void addObject(SimObject *obj); | ||
| virtual bool acceptsAsChild( SimObject *object ) const; | ||
| }; | ||
|
|
||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // base class for all behavior tree tasks | ||
| //--------------------------------------------------------------------------- | ||
| class Task | ||
| { | ||
| protected: | ||
|
|
||
| // the current status | ||
| Status mStatus; | ||
|
|
||
| // has the task finished | ||
| bool mIsComplete; | ||
|
|
||
| // the node associated with this task | ||
| Node *mNodeRep; | ||
|
|
||
| // the object that owns us | ||
| SimObjectPtr<SimObject> mOwner; | ||
|
|
||
| // the object running us | ||
| BehaviorTreeRunner *mRunner; | ||
|
|
||
| // the parent of this task | ||
| Task *mParent; | ||
|
|
||
| // update | ||
| virtual Task* update() = 0; | ||
|
|
||
| // initialize | ||
| virtual void onInitialize(); | ||
|
|
||
| // terminate | ||
| virtual void onTerminate(); | ||
|
|
||
| public: | ||
| // tasks are instantiated with a reference to their associated node | ||
| Task(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
| virtual ~Task(); | ||
|
|
||
| // status sets and gets | ||
| virtual Status getStatus(); | ||
| void setStatus(Status newStatus); | ||
|
|
||
| // parent sets and gets | ||
| void setParent(Task *parent); | ||
| Task *getParent(); | ||
|
|
||
| // run the task | ||
| Task* tick(); | ||
|
|
||
| // called when child task finishes | ||
| virtual void onChildComplete(Status); | ||
|
|
||
| // called when a suspended task becomes active | ||
| virtual void onResume(); | ||
|
|
||
| // prepare the task | ||
| void setup(); | ||
|
|
||
| // finish the task | ||
| void finish(); | ||
|
|
||
| // reset the task | ||
| void reset(); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| // make the return status enum accessible from script | ||
| typedef BadBehavior::Status BehaviorReturnType; | ||
| DefineEnumType( BehaviorReturnType ); | ||
|
|
||
| #endif |
| @@ -0,0 +1,106 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Decorator.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Base decorator node | ||
| // overrides for decorators to only allow 1 child | ||
| //------------------------------------------------------------------------------ | ||
| void DecoratorNode::addObject(SimObject *obj) | ||
| { | ||
| if(empty()) | ||
| Parent::addObject(obj); | ||
| } | ||
|
|
||
| bool DecoratorNode::acceptsAsChild( SimObject *object ) const | ||
| { | ||
| return (dynamic_cast<Node *>(object) && empty()); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Base decorator task | ||
| //------------------------------------------------------------------------------ | ||
| DecoratorTask::DecoratorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner), | ||
| mChild(NULL) | ||
| { | ||
| } | ||
|
|
||
| DecoratorTask::~DecoratorTask() | ||
| { | ||
| if(mChild) | ||
| { | ||
| delete mChild; | ||
| mChild = NULL; | ||
| } | ||
| } | ||
|
|
||
| void DecoratorTask::onInitialize() | ||
| { | ||
| if(!mChild) | ||
| { | ||
| if(mNodeRep->size() > 0) | ||
| { | ||
| Node *childNode = static_cast<Node*>(*mNodeRep->begin()); | ||
| if(childNode) | ||
| { | ||
| mChild = childNode->createTask(*mOwner, *mRunner); | ||
| if(mChild) | ||
| { | ||
| mChild->setParent(this); | ||
| mChild->reset(); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| mStatus = INVALID; | ||
| } | ||
|
|
||
| void DecoratorTask::onTerminate() | ||
| { | ||
| mStatus = INVALID; | ||
| } | ||
|
|
||
| Task* DecoratorTask::update() | ||
| { | ||
| // first time through, return child | ||
| if(!mIsComplete) | ||
| return mStatus != SUSPENDED ? mChild : NULL; | ||
|
|
||
| // child has completed, are we latent? | ||
| if(mStatus == RUNNING || mStatus == SUSPENDED) | ||
| mIsComplete = false; | ||
|
|
||
| // no more children | ||
| return NULL; | ||
| } | ||
|
|
||
| void DecoratorTask::onChildComplete(Status s) | ||
| { | ||
| // set our status to the child status and flag completed | ||
| mStatus = s; | ||
| mIsComplete = true; | ||
| } |
| @@ -0,0 +1,68 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_DECORATOR_H_ | ||
| #define _BB_DECORATOR_H_ | ||
|
|
||
| #ifndef _BB_CORE_H_ | ||
| #include "BadBehavior/core/Core.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // Decorator node base class | ||
| //--------------------------------------------------------------------------- | ||
| class DecoratorNode : public Node | ||
| { | ||
| typedef Node Parent; | ||
|
|
||
| public: | ||
| // only allow 1 child node to be added | ||
| virtual void addObject(SimObject *obj); | ||
| virtual bool acceptsAsChild( SimObject *object ) const; | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Decorator task base class | ||
| //--------------------------------------------------------------------------- | ||
| class DecoratorTask : public Task | ||
| { | ||
| typedef Task Parent; | ||
|
|
||
| protected: | ||
| Task* mChild; | ||
|
|
||
| virtual Task* update(); | ||
| virtual void onInitialize(); | ||
| virtual void onTerminate(); | ||
|
|
||
| public: | ||
| DecoratorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
| virtual ~DecoratorTask(); | ||
|
|
||
| virtual void onChildComplete(Status s); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,278 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Runner.h" | ||
|
|
||
| #include "console/engineAPI.h" | ||
| #include "platform/profiler.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| IMPLEMENT_CONOBJECT(BehaviorTreeRunner); | ||
|
|
||
| BehaviorTreeRunner::BehaviorTreeRunner() | ||
| : mOwner(NULL), | ||
| mRootNode(NULL), | ||
| mRootTask(NULL), | ||
| mIsRunning(0), | ||
| mTickEvent(0), | ||
| mTickFrequency(100) | ||
| {} | ||
|
|
||
|
|
||
| BehaviorTreeRunner::~BehaviorTreeRunner() | ||
| { | ||
| delete mRootTask; | ||
|
|
||
| if(Sim::isEventPending(mTickEvent)) | ||
| { | ||
| Sim::cancelEvent(mTickEvent); | ||
| mTickEvent = 0; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| void BehaviorTreeRunner::initPersistFields() | ||
| { | ||
| addGroup( "Behavior" ); | ||
|
|
||
| addProtectedField("rootNode", TYPEID< SimObject >(), Offset(mRootNode, BehaviorTreeRunner), | ||
| &_setRootNode, &defaultProtectedGetFn, "@brief The root node of the tree to be run."); | ||
|
|
||
| addProtectedField("ownerObject", TYPEID< SimObject >(), Offset(mOwner, BehaviorTreeRunner), | ||
| &_setOwner, &defaultProtectedGetFn, "@brief The object that owns the tree to be run."); | ||
|
|
||
| addField("frequency", TypeS32, Offset(mTickFrequency, BehaviorTreeRunner), | ||
| "@brief The frequency in ms that the tree is ticked at."); | ||
|
|
||
| endGroup( "Behavior" ); | ||
|
|
||
| Parent::initPersistFields(); | ||
| } | ||
|
|
||
| void BehaviorTreeRunner::onDeleteNotify(SimObject *object) | ||
| { | ||
| // delete ourselves nicely | ||
| // - this takes care of any events registered to this runner | ||
| if(object == mOwner.getObject()) | ||
| safeDeleteObject(); | ||
| } | ||
|
|
||
|
|
||
| // processTick is where the magic happens :) | ||
| void BehaviorTreeRunner::onTick() | ||
| { | ||
| PROFILE_SCOPE(BehaviorTreeRunner_processTick); | ||
|
|
||
| // check that we are setup to run | ||
| if(mOwner.isNull() || mRootNode.isNull()) | ||
| return; | ||
|
|
||
| if(gInBtEditor) | ||
| { | ||
| if(mRootTask) | ||
| reset(); | ||
| } | ||
| else | ||
| { | ||
| if(!mRootTask) | ||
| { | ||
| if((mRootTask = mRootNode->createTask(*mOwner, *this)) == NULL) | ||
| { | ||
| Con::errorf("BehaviorTreeTicker::processTick, no task for root node"); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| // dispatch any signals | ||
| mSignalHandler.dispatchSignals(); | ||
|
|
||
| // Evaluate the tree | ||
| mRootTask->setup(); | ||
| mRootTask->tick(); | ||
| //Con::warnf("Tree returned %s", EngineMarshallData(mRootTask->getStatus())); | ||
| mRootTask->finish(); | ||
| } | ||
|
|
||
| // schedule the next tick | ||
| if(Sim::isEventPending(mTickEvent)) | ||
| Sim::cancelEvent(mTickEvent); | ||
|
|
||
| mTickEvent = Sim::postEvent(this, new BehaviorTreeTickEvent(), Sim::getCurrentTime() + mTickFrequency); | ||
|
|
||
| mIsRunning = true; | ||
| } | ||
|
|
||
| void BehaviorTreeRunner::onReactivateEvent(Task *task) | ||
| { | ||
| if(task) | ||
| task->onResume(); | ||
| } | ||
|
|
||
| bool BehaviorTreeRunner::_setRootNode( void *object, const char *index, const char *data ) | ||
| { | ||
| BehaviorTreeRunner *runner = static_cast<BehaviorTreeRunner *>( object ); | ||
| Node* root = NULL; | ||
| Sim::findObject( data, root ); | ||
| if(root) | ||
| runner->setRootNode(root); | ||
| return false; | ||
| } | ||
|
|
||
| bool BehaviorTreeRunner::_setOwner( void *object, const char *index, const char *data ) | ||
| { | ||
| BehaviorTreeRunner *runner = static_cast<BehaviorTreeRunner *>( object ); | ||
| SimObject* owner = NULL; | ||
| Sim::findObject( data, owner ); | ||
| if(owner) | ||
| runner->setOwner(owner); | ||
| return false; | ||
| } | ||
|
|
||
| void BehaviorTreeRunner::setOwner(SimObject *owner) | ||
| { | ||
| reset(); | ||
| mOwner = owner; | ||
| deleteNotify(mOwner); | ||
| start(); | ||
| } | ||
|
|
||
|
|
||
| void BehaviorTreeRunner::setRootNode(Node *root) | ||
| { | ||
| reset(); | ||
| mRootNode = root; | ||
| start(); | ||
| } | ||
|
|
||
|
|
||
| void BehaviorTreeRunner::stop() | ||
| { | ||
| if(Sim::isEventPending(mTickEvent)) | ||
| { | ||
| Sim::cancelEvent(mTickEvent); | ||
| mTickEvent = 0; | ||
| } | ||
| mIsRunning = false; | ||
| } | ||
|
|
||
|
|
||
| void BehaviorTreeRunner::start() | ||
| { | ||
| if(Sim::isEventPending(mTickEvent)) | ||
| { | ||
| Sim::cancelEvent(mTickEvent); | ||
| mTickEvent = 0; | ||
| } | ||
|
|
||
| mIsRunning = true; | ||
| if(mRootTask) | ||
| mRootTask->reset(); | ||
|
|
||
| mTickEvent = Sim::postEvent(this, new BehaviorTreeTickEvent(), -1); | ||
| } | ||
|
|
||
|
|
||
| void BehaviorTreeRunner::reset() | ||
| { | ||
| //stop(); | ||
| if(mRootTask) | ||
| { | ||
| delete mRootTask; | ||
| mRootTask = 0; | ||
| } | ||
| mSignalHandler.reset(); | ||
| } | ||
|
|
||
|
|
||
| void BehaviorTreeRunner::clear() | ||
| { | ||
| reset(); | ||
| mRootNode = 0; | ||
| } | ||
|
|
||
|
|
||
| bool BehaviorTreeRunner::isRunning() | ||
| { | ||
| return mIsRunning; | ||
| } | ||
|
|
||
|
|
||
| void BehaviorTreeRunner::subscribeToSignal(const char *signal, SignalSubscriber *subscriber) | ||
| { | ||
| mSignalHandler.registerSubscriber(signal, subscriber); | ||
| } | ||
|
|
||
|
|
||
| void BehaviorTreeRunner::unsubscribeFromSignal(const char *signal, SignalSubscriber *subscriber) | ||
| { | ||
| mSignalHandler.unregisterSubscriber(signal, subscriber); | ||
| } | ||
|
|
||
|
|
||
| void BehaviorTreeRunner::postSignal(const char *signal) | ||
| { | ||
| mSignalHandler.postSignal(signal); | ||
| } | ||
|
|
||
|
|
||
| DefineEngineMethod( BehaviorTreeRunner, stop, void, (), , | ||
| "Halt the execution of the behavior tree.\n\n" | ||
| "@note The internal task status is retained, allowing execution to be resumed.") | ||
| { | ||
| object->stop(); | ||
| } | ||
|
|
||
|
|
||
| DefineEngineMethod( BehaviorTreeRunner, start, void, (), , | ||
| "Resume execution of the (stopped) behavior tree.") | ||
| { | ||
| object->start(); | ||
| } | ||
|
|
||
|
|
||
| DefineEngineMethod( BehaviorTreeRunner, reset, void, (), , | ||
| "Reset the behavior tree. Any internal state is lost.") | ||
| { | ||
| object->reset(); | ||
| } | ||
|
|
||
|
|
||
| DefineEngineMethod( BehaviorTreeRunner, clear, void, (), , | ||
| "Clear the behavior tree.") | ||
| { | ||
| object->clear(); | ||
| } | ||
|
|
||
|
|
||
| DefineEngineMethod( BehaviorTreeRunner, isRunning, bool, (), , | ||
| "Is the behavior tree running") | ||
| { | ||
| return object->isRunning(); | ||
| } | ||
|
|
||
|
|
||
| DefineEngineMethod(BehaviorTreeRunner, postSignal, void, (const char *signal),, | ||
| "@brief Posts a signal to the behavior tree.\n\n") | ||
| { | ||
| object->postSignal( signal ); | ||
| } |
| @@ -0,0 +1,140 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_RUNNER_H_ | ||
| #define _BB_RUNNER_H_ | ||
|
|
||
| #ifndef _BB_CORE_H_ | ||
| #include "Core.h" | ||
| #endif | ||
| #ifndef _BB_SIGNAL_H_ | ||
| #include "Signal.h" | ||
| #endif | ||
| #ifndef _SIMOBJECT_H_ | ||
| #include "console/simObject.h" | ||
| #endif | ||
| #ifndef _SIMBASE_H_ | ||
| #include "console/simBase.h" | ||
| #endif | ||
| #ifndef _TVECTOR_H_ | ||
| #include "util/tVector.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // BehaviorTreeRunner - handles the evaluation of the tree | ||
| //--------------------------------------------------------------------------- | ||
| class BehaviorTreeRunner : public SimObject | ||
| { | ||
| typedef SimObject Parent; | ||
|
|
||
| private: | ||
| // is this tree running? | ||
| bool mIsRunning; | ||
|
|
||
| // event ID of the tick event | ||
| U32 mTickEvent; | ||
|
|
||
| // frequency of ticks in ms | ||
| U32 mTickFrequency; | ||
|
|
||
| // the root node of the tree | ||
| SimObjectPtr<Node> mRootNode; | ||
|
|
||
| // the task associated with the root node | ||
| Task *mRootTask; | ||
|
|
||
| // the game object that is using this tree | ||
| SimObjectPtr<SimObject> mOwner; | ||
|
|
||
| // signal handler for throwing signals around | ||
| SignalHandler mSignalHandler; | ||
|
|
||
| // setters for the script interface | ||
| static bool _setRootNode( void *object, const char *index, const char *data ); | ||
| static bool _setOwner( void *object, const char *index, const char *data ); | ||
|
|
||
| public: | ||
| /*Ctor*/ BehaviorTreeRunner(); | ||
| /*Dtor*/ ~BehaviorTreeRunner(); | ||
|
|
||
| // public setters for the script interface | ||
| void setOwner(SimObject *owner); | ||
| void setRootNode(Node *root); | ||
|
|
||
| // notification if our owner is deleted | ||
| virtual void onDeleteNotify(SimObject *object); | ||
|
|
||
| // for script control | ||
| void stop(); | ||
| void start(); | ||
| void reset(); | ||
| void clear(); | ||
| bool isRunning(); | ||
|
|
||
| // tick | ||
| void onTick(); | ||
|
|
||
| // signal handling | ||
| void subscribeToSignal(const char *signal, SignalSubscriber *subscriber); | ||
| void unsubscribeFromSignal(const char *signal, SignalSubscriber *subscriber); | ||
| void postSignal(const char *signal); | ||
|
|
||
| // task reactivation | ||
| void onReactivateEvent(Task *task); | ||
|
|
||
| // script interface | ||
| static void initPersistFields(); | ||
|
|
||
| DECLARE_CONOBJECT(BehaviorTreeRunner); | ||
| }; | ||
|
|
||
|
|
||
| class BehaviorTreeTickEvent : public SimEvent | ||
| { | ||
| public: | ||
| void process( SimObject *object ) | ||
| { | ||
| ((BehaviorTreeRunner*)object)->onTick(); | ||
| } | ||
| }; | ||
|
|
||
| class TaskReactivateEvent : public SimEvent | ||
| { | ||
| Task *mTask; | ||
| public: | ||
| TaskReactivateEvent(Task &task) | ||
| { | ||
| mTask = &task; | ||
| } | ||
|
|
||
| void process( SimObject *object ) | ||
| { | ||
| ((BehaviorTreeRunner*)object)->onReactivateEvent(mTask); | ||
| } | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,168 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Signal.h" | ||
|
|
||
| #include "core/stringTable.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| // clean up | ||
| SignalHandler::~SignalHandler() | ||
| { | ||
| clearSignalQueue(); | ||
| clearSubscribers(); | ||
| } | ||
|
|
||
| void SignalHandler::clearSignalQueue() | ||
| { | ||
| while(!mSignalQueue.empty()) | ||
| { | ||
| Signal *sig = mSignalQueue.back(); | ||
| mSignalQueue.pop_back(); | ||
| delete sig; | ||
| sig = NULL; | ||
| } | ||
| } | ||
|
|
||
| void SignalHandler::clearSubscribers() | ||
| { | ||
| for( Vector<StringTableEntry>::const_iterator it = mSignals.begin(); it != mSignals.end(); ++it ) | ||
| { | ||
| // Delete the subscriber list. | ||
| VectorPtr<SignalSubscriber*>* subscribers = mSubscribers.remove( *it ); | ||
| if(subscribers) | ||
| delete subscribers; | ||
| } | ||
| } | ||
|
|
||
| void SignalHandler::reset() | ||
| { | ||
| // empty out the signal queue | ||
| clearSignalQueue(); | ||
|
|
||
| // clear out the subscribers table | ||
| clearSubscribers(); | ||
|
|
||
| // reset the vector of registered signals | ||
| mSignals.clear(); | ||
| } | ||
|
|
||
| // check if the specified signal is registered | ||
| bool SignalHandler::isSignalRegistered(const char *signal) | ||
| { | ||
| StringTableEntry signalName = StringTable->insert( signal ); | ||
| return mSignals.contains(signalName); | ||
| } | ||
|
|
||
| // register a signal | ||
| void SignalHandler::registerSignal(const char *signal) | ||
| { | ||
| // check signal has a name | ||
| if(!signal || !signal[0]) | ||
| return; | ||
|
|
||
| // Make sure the signal has not been registered yet. | ||
| if(!isSignalRegistered( signal ) ) | ||
| { | ||
| // Add to the signal list. | ||
| mSignals.push_back( StringTable->insert( signal ) ); | ||
|
|
||
| // Create a list of subscribers for this event. | ||
| mSubscribers.insert( new VectorPtr<SignalSubscriber*>, signal ); | ||
| } | ||
| } | ||
|
|
||
| // register a subscriber to a signal | ||
| void SignalHandler::registerSubscriber(const char *signal, SignalSubscriber *subscriber) | ||
| { | ||
| // must have a subscriber | ||
| if(!subscriber) | ||
| return; | ||
|
|
||
| // and an signal name | ||
| if(!signal || !signal[0]) | ||
| return; | ||
|
|
||
| // register a new event if this one hasn't already been registered | ||
| if(!isSignalRegistered(signal)) | ||
| registerSignal(signal); | ||
|
|
||
| // add the subscriber if it's not already registered for this signal | ||
| VectorPtr<SignalSubscriber*>* subscribers = mSubscribers.retreive( signal ); | ||
|
|
||
| if(!subscribers->contains(subscriber)) | ||
| subscribers->push_back(subscriber); | ||
| } | ||
|
|
||
| // unregister a subscriber | ||
| void SignalHandler::unregisterSubscriber(const char *signal, SignalSubscriber *subscriber) | ||
| { | ||
| // check if the subscriber exists and that the signal is actually registered | ||
| if(!subscriber || !isSignalRegistered(signal)) | ||
| return; | ||
|
|
||
| // find the subscriber and remove it | ||
| VectorPtr<SignalSubscriber*>* subscribers = mSubscribers.retreive( signal ); | ||
|
|
||
| for( VectorPtr<SignalSubscriber *>::iterator iter = subscribers->begin(); iter != subscribers->end(); ++iter ) | ||
| { | ||
| if( *iter == subscriber ) | ||
| { | ||
| subscribers->erase_fast( iter ); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // post a signal | ||
| void SignalHandler::postSignal(const char *signal) | ||
| { | ||
| // signal must be registered | ||
| if(!isSignalRegistered(signal)) | ||
| return; | ||
|
|
||
| // dispatch a signal to each of the subscribers | ||
| VectorPtr<SignalSubscriber*>* subscribers = mSubscribers.retreive( signal ); | ||
|
|
||
| for( VectorPtr<SignalSubscriber *>::iterator iter = subscribers->begin(); iter != subscribers->end(); ++iter ) | ||
| { | ||
| mSignalQueue.push_back(new Signal((*iter))); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| // dispatch queued signals | ||
| void SignalHandler::dispatchSignals() | ||
| { | ||
| if(mSignalQueue.empty()) | ||
| return; | ||
|
|
||
| while(!mSignalQueue.empty()) | ||
| { | ||
| Signal *sig = mSignalQueue.back(); | ||
| mSignalQueue.pop_back(); | ||
| sig->send(); | ||
| delete sig; | ||
| sig = NULL; | ||
| } | ||
| } |
| @@ -0,0 +1,97 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_SIGNAL_H_ | ||
| #define _BB_SIGNAL_H_ | ||
|
|
||
| #ifndef _TVECTOR_H_ | ||
| #include "core/util/tVector.h" | ||
| #endif | ||
| #ifndef _TSIMPLEHASHTABLE_H | ||
| #include "core/tSimpleHashTable.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // Signal subscriber interface | ||
| //--------------------------------------------------------------------------- | ||
| class SignalSubscriber | ||
| { | ||
| protected: | ||
| virtual void subscribe() = 0; | ||
| virtual void unsubscribe() = 0; | ||
|
|
||
| public: | ||
| virtual void onSignal() = 0; | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Signal class | ||
| //--------------------------------------------------------------------------- | ||
| class Signal | ||
| { | ||
| private: | ||
| SignalSubscriber *mSubscriber; | ||
| public: | ||
| Signal(SignalSubscriber *subscriber) : mSubscriber(subscriber) {} | ||
| void send() { if(mSubscriber) mSubscriber->onSignal(); } | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // SignalHandler | ||
| // Simple handler to pass signals to tree task listeners | ||
| //--------------------------------------------------------------------------- | ||
| class SignalHandler | ||
| { | ||
| private: | ||
| SimpleHashTable<VectorPtr<SignalSubscriber*> > mSubscribers; | ||
| Vector<StringTableEntry> mSignals; | ||
|
|
||
| VectorPtr<Signal*> mSignalQueue; | ||
|
|
||
| void registerSignal(const char *signal); | ||
| bool isSignalRegistered(const char *signal); | ||
| void clearSignalQueue(); | ||
| void clearSubscribers(); | ||
|
|
||
| public: | ||
| SignalHandler() {} | ||
| ~SignalHandler(); | ||
|
|
||
| // reset | ||
| void reset(); | ||
|
|
||
| // register a scubscriber | ||
| void registerSubscriber(const char *signal, SignalSubscriber *subscriber); | ||
|
|
||
| // unregister a subscriber | ||
| void unregisterSubscriber(const char *signal, SignalSubscriber *subscriber); | ||
|
|
||
| // post an signal | ||
| void postSignal(const char *signal); | ||
|
|
||
| // dispatch queued signals | ||
| void dispatchSignals(); | ||
| }; | ||
| } // namespace BadBehavior | ||
| #endif |
| @@ -0,0 +1,71 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Stepper.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| Status BehaviorTreeStepper::stepThrough(VectorPtr<Task *> &taskVector) | ||
| { | ||
| if(taskVector.empty()) return INVALID; | ||
|
|
||
| if(taskVector.back()->getStatus() == SUSPENDED) | ||
| return SUSPENDED; | ||
|
|
||
| Status status = INVALID; | ||
|
|
||
| // loop through the tasks in the task list | ||
| while(!taskVector.empty()) | ||
| { | ||
| // get a task | ||
| Task *currentTask = taskVector.back(); | ||
|
|
||
| // tick the task | ||
| Task *nextTask = currentTask->tick(); | ||
|
|
||
| // if task returned no children, it has completed | ||
| if(!nextTask) | ||
| { | ||
| // stop if it's RUNNING or SUSPENED | ||
| status = currentTask->getStatus(); | ||
| if(status == RUNNING || status == SUSPENDED) | ||
| break; | ||
|
|
||
| // otherwise, remove it from the list | ||
| taskVector.pop_back(); | ||
| if(!taskVector.empty()) | ||
| // and tell its parent that it completed | ||
| taskVector.back()->onChildComplete(currentTask->getStatus()); | ||
|
|
||
| // complete the task | ||
| currentTask->finish(); | ||
| } | ||
| else | ||
| { | ||
| // add the child as a task | ||
| nextTask->setup(); | ||
| taskVector.push_back(nextTask); | ||
| } | ||
| } | ||
|
|
||
| return status; | ||
| } |
| @@ -0,0 +1,43 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_STEPPER_H_ | ||
| #define _BB_STEPPER_H_ | ||
|
|
||
| #ifndef _BB_CORE_H_ | ||
| #include "Core.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // helper class for stepping through a tree | ||
| //--------------------------------------------------------------------------- | ||
| class BehaviorTreeStepper | ||
| { | ||
| public: | ||
| static Status stepThrough(VectorPtr<Task *> &taskVector); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,106 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "behavior.h" | ||
|
|
||
| #include "console/engineAPI.h" | ||
| #include "platform/profiler.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // script enum for precondition mode | ||
| //------------------------------------------------------------------------------ | ||
| ImplementEnumType( BehaviorPreconditionType, | ||
| "@brief When should the precondition function be evaluated.\n\n" | ||
| "@ingroup AI\n\n") | ||
| { ONCE, "ONCE", "The first time the node is executed.\n" }, | ||
| { TICK, "TICK", "Each time the node is executed.\n" }, | ||
| EndImplementEnumType; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Behavior node | ||
| //------------------------------------------------------------------------------ | ||
| IMPLEMENT_CONOBJECT(Behavior); | ||
|
|
||
| Behavior::Behavior() | ||
| : mPreconditionMode(ONCE) | ||
| { | ||
| } | ||
|
|
||
| void Behavior::initPersistFields() | ||
| { | ||
| addGroup( "Behavior" ); | ||
|
|
||
| addField( "preconditionMode", TYPEID< BadBehavior::PreconditionMode >(), Offset(mPreconditionMode, Behavior), | ||
| "@brief When to evaluate the precondition function."); | ||
|
|
||
| endGroup( "Behavior" ); | ||
|
|
||
| Parent::initPersistFields(); | ||
| } | ||
|
|
||
| Task *Behavior::createTask(SimObject &owner, BehaviorTreeRunner &runner) | ||
| { | ||
| return new BehaviorTask(*this, owner, runner); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // ScriptedBehavior task | ||
| //------------------------------------------------------------------------------ | ||
| BehaviorTask::BehaviorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner) | ||
| { | ||
| } | ||
|
|
||
| Task* BehaviorTask::update() | ||
| { | ||
| PROFILE_SCOPE(BehaviorTask_update); | ||
|
|
||
| Behavior *node = static_cast<Behavior*>(mNodeRep); | ||
|
|
||
| // first check preconditions are valid | ||
| bool precondition = true; | ||
| if( (node->getPreconditionMode() == ONCE && mStatus == INVALID) || (node->getPreconditionMode() == TICK) ) | ||
| precondition = node->precondition( mOwner ); | ||
|
|
||
| if(precondition) | ||
| { | ||
| // run onEnter if this is the first time the node is ticked | ||
| if(mStatus == INVALID) | ||
| node->onEnter(mOwner); | ||
|
|
||
| // execute the main behavior and get its return value | ||
| mStatus = node->behavior(mOwner); | ||
| } | ||
| else | ||
| { | ||
| mStatus = FAILURE; | ||
| } | ||
|
|
||
| mIsComplete = mStatus != RUNNING && mStatus != SUSPENDED; | ||
|
|
||
| if(mIsComplete) | ||
| node->onExit(mOwner); | ||
|
|
||
| return NULL; // leaves don't have children | ||
| } |
| @@ -0,0 +1,87 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_BEHAVIOR_H_ | ||
| #define _BB_BEHAVIOR_H_ | ||
|
|
||
| #ifndef _BB_CORE_H_ | ||
| #include "Core.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| // specify when the precondition function should be executed | ||
| enum PreconditionMode | ||
| { | ||
| ONCE, // the first time the behavior is evaluated | ||
| TICK // every tick | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Behavior - Base class for structured behavior leaf nodes | ||
| //--------------------------------------------------------------------------- | ||
| class Behavior : public LeafNode | ||
| { | ||
| typedef LeafNode Parent; | ||
|
|
||
| protected: | ||
| // how often should we valuate the precondition | ||
| PreconditionMode mPreconditionMode; | ||
|
|
||
| public: | ||
| Behavior(); | ||
|
|
||
| virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| static void initPersistFields(); | ||
|
|
||
| const PreconditionMode &getPreconditionMode() const { return mPreconditionMode; } | ||
|
|
||
| virtual bool precondition( SimObject *owner ) { return true; } | ||
| virtual void onEnter( SimObject *owner ) {} | ||
| virtual void onExit( SimObject *owner ) {} | ||
| virtual Status behavior( SimObject *owner ) { return SUCCESS; } | ||
|
|
||
| DECLARE_CONOBJECT(Behavior); | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Behavior task | ||
| //--------------------------------------------------------------------------- | ||
| class BehaviorTask : public Task | ||
| { | ||
| typedef Task Parent; | ||
|
|
||
| protected: | ||
| virtual Task* update(); | ||
|
|
||
| public: | ||
| BehaviorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| // make the return precondition mode accessible from script | ||
| typedef BadBehavior::PreconditionMode BehaviorPreconditionType; | ||
| DefineEnumType( BehaviorPreconditionType ); | ||
|
|
||
| #endif |
| @@ -0,0 +1,51 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "FailAlways.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // FailAlways decorator node | ||
| //------------------------------------------------------------------------------ | ||
| IMPLEMENT_CONOBJECT(FailAlways); | ||
|
|
||
| Task *FailAlways::createTask(SimObject &owner, BehaviorTreeRunner &runner) | ||
| { | ||
| return new FailAlwaysTask(*this, owner, runner); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // FailAlways decorator task | ||
| //------------------------------------------------------------------------------ | ||
| FailAlwaysTask::FailAlwaysTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner) | ||
| { | ||
| } | ||
|
|
||
| void FailAlwaysTask::onChildComplete(Status s) | ||
| { | ||
| Parent::onChildComplete(s); | ||
| if(mStatus == SUCCESS) | ||
| mStatus = FAILURE; | ||
| } | ||
|
|
| @@ -0,0 +1,61 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_FAILALWAYS_H_ | ||
| #define _BB_FAILALWAYS_H_ | ||
|
|
||
| #ifndef _BB_DECORATOR_H_ | ||
| #include "BadBehavior/core/Decorator.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // FailAlways decorator | ||
| // Returns FAILURE if child returns SUCCESS or FAILURE. RUNNING and INVALID are unchanged | ||
| //--------------------------------------------------------------------------- | ||
| class FailAlways : public DecoratorNode | ||
| { | ||
| typedef DecoratorNode Parent; | ||
|
|
||
| public: | ||
| virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| DECLARE_CONOBJECT(FailAlways); | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // FailAlways task | ||
| //--------------------------------------------------------------------------- | ||
| class FailAlwaysTask : public DecoratorTask | ||
| { | ||
| typedef DecoratorTask Parent; | ||
|
|
||
| public: | ||
| FailAlwaysTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| virtual void onChildComplete(Status s); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,54 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Inverter.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Inverter decorator node | ||
| //------------------------------------------------------------------------------ | ||
| IMPLEMENT_CONOBJECT(Inverter); | ||
|
|
||
| Task *Inverter::createTask(SimObject &owner, BehaviorTreeRunner &runner) | ||
| { | ||
| return new InverterTask(*this, owner, runner); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Inverter decorator task | ||
| //------------------------------------------------------------------------------ | ||
| InverterTask::InverterTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner) | ||
| { | ||
| } | ||
|
|
||
| void InverterTask::onChildComplete(Status s) | ||
| { | ||
| Parent::onChildComplete(s); | ||
|
|
||
| // invert SUCCESS or FAILURE, leave INVALID and RUNNING unchanged | ||
| if (mStatus == SUCCESS) | ||
| mStatus = FAILURE; | ||
| else if (mStatus == FAILURE) | ||
| mStatus = SUCCESS; | ||
| } |
| @@ -0,0 +1,62 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_INVERTER_H_ | ||
| #define _BB_INVERTER_H_ | ||
|
|
||
| #ifndef _BB_DECORATOR_H_ | ||
| #include "BadBehavior/core/Decorator.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // inverter decorator | ||
| // invert the return value of the child, | ||
| // SUCCESS becomes FAILURE, FAILURE becomes SUCCESS, INVALID and RUNNING are unmodified | ||
| //--------------------------------------------------------------------------- | ||
| class Inverter : public DecoratorNode | ||
| { | ||
| typedef DecoratorNode Parent; | ||
|
|
||
| public: | ||
| virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| DECLARE_CONOBJECT(Inverter); | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // inverter decorator task | ||
| //--------------------------------------------------------------------------- | ||
| class InverterTask : public DecoratorTask | ||
| { | ||
| typedef DecoratorTask Parent; | ||
|
|
||
| public: | ||
| InverterTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| virtual void onChildComplete(Status s); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| #endif |
| @@ -0,0 +1,120 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Loop.h" | ||
|
|
||
| #include "console/consoleTypes.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Loop decorator node | ||
| //------------------------------------------------------------------------------ | ||
| IMPLEMENT_CONOBJECT(Loop); | ||
|
|
||
| ImplementEnumType( LoopTerminationPolicy, | ||
| "@brief The policy to use when determining if the loop should terminate early.\n\n" | ||
| "@ingroup AI\n\n") | ||
| { Loop::ON_FAILURE, "ON_FAILURE", "Will terminate and return FAILURE if child fails.\n" }, | ||
| { Loop::ON_SUCCESS, "ON_SUCCESS", "Will terminate and return SUCCESS if child succeeds.\n" }, | ||
| EndImplementEnumType; | ||
|
|
||
| Loop::Loop() | ||
| : mNumLoops(0), | ||
| mTerminationPolicy(ON_FAILURE) | ||
| { | ||
| } | ||
|
|
||
| void Loop::initPersistFields() | ||
| { | ||
| addGroup( "Behavior" ); | ||
|
|
||
| addProtectedField( "numLoops", TypeS32, Offset(mNumLoops, Loop), &_setNumLoops, &defaultProtectedGetFn, | ||
| "The number of times to repeat the child behavior. 0 = infinite." ); | ||
|
|
||
| addField( "terminationPolicy", TYPEID< Loop::TerminationPolicy >(), Offset(mTerminationPolicy, Loop), | ||
| "@brief The policy to use when deciding if the loop should terminate before completion."); | ||
|
|
||
| endGroup( "Behavior" ); | ||
|
|
||
| Parent::initPersistFields(); | ||
| } | ||
|
|
||
| bool Loop::_setNumLoops(void *object, const char *index, const char *data) | ||
| { | ||
| Loop *node = static_cast<Loop *>( object ); | ||
| node->mNumLoops = getMax(0, dAtoi( data )); | ||
| return false; | ||
| } | ||
|
|
||
| Task *Loop::createTask(SimObject &owner, BehaviorTreeRunner &runner) | ||
| { | ||
| return new LoopTask(*this, owner, runner); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Loop decorator task | ||
| //------------------------------------------------------------------------------ | ||
| LoopTask::LoopTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner), | ||
| mCurrentLoop(0) | ||
| { | ||
| } | ||
|
|
||
| void LoopTask::onInitialize() | ||
| { | ||
| Parent::onInitialize(); | ||
| mCurrentLoop = 0; | ||
| } | ||
|
|
||
| Task* LoopTask::update() | ||
| { | ||
| if(Parent::update()) | ||
| return mChild; | ||
|
|
||
| if(mStatus == RUNNING || mStatus == SUSPENDED) | ||
| mIsComplete = false; | ||
|
|
||
| // child has terminated with SUCCESS or FAILURE | ||
| if( mIsComplete ) | ||
| { | ||
| // check if we should continue looping or reset | ||
| Loop *nodeRep = static_cast<Loop *>(mNodeRep); | ||
| Loop::TerminationPolicy policy = nodeRep->getTerminationPolicy(); | ||
| S32 numLoops = nodeRep->getNumLoops(); | ||
|
|
||
| // termination policy not met? | ||
| if( ((policy == Loop::ON_FAILURE) && (mStatus != FAILURE)) || | ||
| ((policy == Loop::ON_SUCCESS) && (mStatus != SUCCESS)) ) | ||
| { | ||
| // more looping to be done | ||
| if ( (++mCurrentLoop < numLoops) || (numLoops == 0) ) | ||
| { | ||
| mIsComplete = false; | ||
| mStatus = RUNNING; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // no children to return | ||
| return NULL; | ||
| } |
| @@ -0,0 +1,90 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _BB_LOOP_H_ | ||
| #define _BB_LOOP_H_ | ||
|
|
||
| #ifndef _BB_DECORATOR_H_ | ||
| #include "BadBehavior/core/Decorator.h" | ||
| #endif | ||
|
|
||
| namespace BadBehavior | ||
| { | ||
| //--------------------------------------------------------------------------- | ||
| // loop decorator | ||
| // repeats the child behaviour for n times, or until it fails | ||
| // returns RUNNING until it completes | ||
| //--------------------------------------------------------------------------- | ||
| class Loop : public DecoratorNode | ||
| { | ||
| typedef DecoratorNode Parent; | ||
|
|
||
| public: | ||
| // loop termination policies | ||
| enum TerminationPolicy | ||
| { | ||
| ON_FAILURE, | ||
| ON_SUCCESS, | ||
| }; | ||
|
|
||
| protected: | ||
| static bool _setNumLoops(void *object, const char *index, const char *data); | ||
| S32 mNumLoops; | ||
| TerminationPolicy mTerminationPolicy; | ||
|
|
||
| public: | ||
| Loop(); | ||
|
|
||
| virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner); | ||
|
|
||
| static void initPersistFields(); | ||
|
|
||
| S32 getNumLoops() const { return mNumLoops; } | ||
| TerminationPolicy getTerminationPolicy() const { return mTerminationPolicy; } | ||
|
|
||
| DECLARE_CONOBJECT(Loop); | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // loop task | ||
| //--------------------------------------------------------------------------- | ||
| class LoopTask : public DecoratorTask | ||
| { | ||
| typedef DecoratorTask Parent; | ||
|
|
||
| protected: | ||
| S32 mCurrentLoop; | ||
|
|
||
| virtual void onInitialize(); | ||
| virtual Task *update(); | ||
|
|
||
| public: | ||
| LoopTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner); | ||
| }; | ||
|
|
||
| } // namespace BadBehavior | ||
|
|
||
| // make the loop termination policy enum accessible from script | ||
| typedef BadBehavior::Loop::TerminationPolicy LoopTerminationPolicy; | ||
| DefineEnumType( LoopTerminationPolicy ); | ||
|
|
||
| #endif |
| @@ -0,0 +1,54 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // Copyright (c) 2014 Guy Allard | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to | ||
| // deal in the Software without restriction, including without limitation the | ||
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| // sell copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| // IN THE SOFTWARE. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #include "Monitor.h" | ||
|
|
||
| #include "console/engineAPI.h" | ||
|
|
||
| using namespace BadBehavior; | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Monitor decorator node | ||
| //------------------------------------------------------------------------------ | ||
| IMPLEMENT_CONOBJECT(Monitor); | ||
|
|
||
| Task *Monitor::createTask(SimObject &owner, BehaviorTreeRunner &runner) | ||
| { | ||
| return new MonitorTask(*this, owner, runner); | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------------ | ||
| // Logger decorator task | ||
| //------------------------------------------------------------------------------ | ||
| MonitorTask::MonitorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner) | ||
| : Parent(node, owner, runner) | ||
| { | ||
| } | ||
|
|
||
| void MonitorTask::onChildComplete(Status s) | ||
| { | ||
| Parent::onChildComplete(s); | ||
|
|
||
| Con::printf("%s (%s) child returning %s", static_cast<Monitor *>(mNodeRep)->getInternalName(), | ||
| static_cast<Monitor *>(mNodeRep)->getIdString(), | ||
| EngineMarshallData< BehaviorReturnType > (mStatus)); | ||
| } |