mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-29 16:25:42 +00:00
BadBehavior added
This commit is contained in:
parent
b16f99d51c
commit
eaa28844c9
63 changed files with 5698 additions and 0 deletions
132
Engine/source/BadBehavior/composite/ActiveSelector.cpp
Normal file
132
Engine/source/BadBehavior/composite/ActiveSelector.cpp
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "ActiveSelector.h"
|
||||||
|
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Active selector node
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(ActiveSelector);
|
||||||
|
|
||||||
|
ActiveSelector::ActiveSelector()
|
||||||
|
: mRecheckFrequency(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Task *ActiveSelector::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
return new ActiveSelectorTask(*this, owner, runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActiveSelector::initPersistFields()
|
||||||
|
{
|
||||||
|
addGroup( "Behavior" );
|
||||||
|
|
||||||
|
addField( "recheckFrequency", TypeS32, Offset(mRecheckFrequency, ActiveSelector),
|
||||||
|
"@brief The minimum time period in milliseconds to wait between re-evaluations of higher priority branches.");
|
||||||
|
|
||||||
|
endGroup( "Behavior" );
|
||||||
|
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Active selector task
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
ActiveSelectorTask::ActiveSelectorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
: Parent(node, owner, runner),
|
||||||
|
mRecheckTime(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActiveSelectorTask::onInitialize()
|
||||||
|
{
|
||||||
|
Parent::onInitialize();
|
||||||
|
|
||||||
|
if(mBranches.empty())
|
||||||
|
{
|
||||||
|
for (VectorPtr<Task*>::iterator i = mChildren.begin(); i != mChildren.end(); ++i)
|
||||||
|
{
|
||||||
|
mBranches.push_back(BehaviorTreeBranch(*i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrentBranch = mBranches.begin();
|
||||||
|
mRunningBranch = mBranches.end();
|
||||||
|
mRecheckTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Task* ActiveSelectorTask::update()
|
||||||
|
{
|
||||||
|
// empty node, bail
|
||||||
|
if(mBranches.empty())
|
||||||
|
{
|
||||||
|
mStatus = INVALID;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is it time to re-check higher priority branches?
|
||||||
|
if(Sim::getCurrentTime() >= mRecheckTime)
|
||||||
|
{
|
||||||
|
// pick highest priority branch
|
||||||
|
mCurrentBranch = mBranches.begin();
|
||||||
|
|
||||||
|
// determine the next recheck time
|
||||||
|
mRecheckTime = Sim::getCurrentTime() + static_cast<ActiveSelector *>(mNodeRep)->getRecheckFrequency();
|
||||||
|
}
|
||||||
|
|
||||||
|
// run a branch, if it fails move on to the next
|
||||||
|
for(mCurrentBranch; mCurrentBranch != mBranches.end(); ++mCurrentBranch)
|
||||||
|
{
|
||||||
|
// reset the branch if it's not the current running branch
|
||||||
|
if(mCurrentBranch != mRunningBranch)
|
||||||
|
mCurrentBranch->reset();
|
||||||
|
|
||||||
|
mStatus = mCurrentBranch->update();
|
||||||
|
|
||||||
|
if(mStatus == FAILURE) // move on to next
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(mStatus == RUNNING || mStatus == SUSPENDED) // track the current running branch
|
||||||
|
mRunningBranch = mCurrentBranch;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (mStatus != RUNNING && mStatus != SUSPENDED) || mCurrentBranch == mBranches.end() )
|
||||||
|
mIsComplete = true;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status ActiveSelectorTask::getStatus()
|
||||||
|
{
|
||||||
|
if(mStatus == SUSPENDED && mCurrentBranch != mBranches.end())
|
||||||
|
return mCurrentBranch->getStatus(); // suspended branch may have resumed
|
||||||
|
|
||||||
|
return mStatus;
|
||||||
|
}
|
||||||
92
Engine/source/BadBehavior/composite/ActiveSelector.h
Normal file
92
Engine/source/BadBehavior/composite/ActiveSelector.h
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_ACTIVESELECTOR_H_
|
||||||
|
#define _BB_ACTIVESELECTOR_H_
|
||||||
|
|
||||||
|
#ifndef _BB_CORE_H_
|
||||||
|
#include "BadBehavior/core/Composite.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _BB_BRANCH_H_
|
||||||
|
#include "BadBehavior/core/Branch.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Active Selector
|
||||||
|
// Re-evaluates its children from the beginning each tick. Lower priority
|
||||||
|
// children which previously returned RUNNING are resumed if re-selected
|
||||||
|
//
|
||||||
|
// ***** TODO - This runs OK, but may need a bit more work
|
||||||
|
// -- abort previously running branches?
|
||||||
|
//
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Active selector Node
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class ActiveSelector : public CompositeNode
|
||||||
|
{
|
||||||
|
typedef CompositeNode Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
U32 mRecheckFrequency;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ActiveSelector();
|
||||||
|
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
U32 getRecheckFrequency() const { return mRecheckFrequency; }
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(ActiveSelector);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Active selector Task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class ActiveSelectorTask : public CompositeTask
|
||||||
|
{
|
||||||
|
typedef CompositeTask Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Vector<BehaviorTreeBranch>::iterator mRunningBranch;
|
||||||
|
Vector<BehaviorTreeBranch>::iterator mCurrentBranch;
|
||||||
|
Vector<BehaviorTreeBranch> mBranches;
|
||||||
|
|
||||||
|
U32 mRecheckTime;
|
||||||
|
|
||||||
|
virtual void onInitialize();
|
||||||
|
virtual Task* update();
|
||||||
|
|
||||||
|
public:
|
||||||
|
ActiveSelectorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
Status getStatus();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
175
Engine/source/BadBehavior/composite/Parallel.cpp
Normal file
175
Engine/source/BadBehavior/composite/Parallel.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
97
Engine/source/BadBehavior/composite/Parallel.h
Normal file
97
Engine/source/BadBehavior/composite/Parallel.h
Normal file
|
|
@ -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
|
||||||
68
Engine/source/BadBehavior/composite/RandomSelector.cpp
Normal file
68
Engine/source/BadBehavior/composite/RandomSelector.cpp
Normal file
|
|
@ -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();
|
||||||
|
}
|
||||||
62
Engine/source/BadBehavior/composite/RandomSelector.h
Normal file
62
Engine/source/BadBehavior/composite/RandomSelector.h
Normal file
|
|
@ -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
|
||||||
54
Engine/source/BadBehavior/composite/Selector.cpp
Normal file
54
Engine/source/BadBehavior/composite/Selector.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
60
Engine/source/BadBehavior/composite/Selector.h
Normal file
60
Engine/source/BadBehavior/composite/Selector.h
Normal file
|
|
@ -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
|
||||||
55
Engine/source/BadBehavior/composite/Sequence.cpp
Normal file
55
Engine/source/BadBehavior/composite/Sequence.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
60
Engine/source/BadBehavior/composite/Sequence.h
Normal file
60
Engine/source/BadBehavior/composite/Sequence.h
Normal file
|
|
@ -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
|
||||||
66
Engine/source/BadBehavior/core/Branch.cpp
Normal file
66
Engine/source/BadBehavior/core/Branch.cpp
Normal file
|
|
@ -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();
|
||||||
|
}
|
||||||
53
Engine/source/BadBehavior/core/Branch.h
Normal file
53
Engine/source/BadBehavior/core/Branch.h
Normal file
|
|
@ -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
|
||||||
110
Engine/source/BadBehavior/core/Composite.cpp
Normal file
110
Engine/source/BadBehavior/core/Composite.cpp
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
70
Engine/source/BadBehavior/core/Composite.h
Normal file
70
Engine/source/BadBehavior/core/Composite.h
Normal file
|
|
@ -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
|
||||||
161
Engine/source/BadBehavior/core/Core.cpp
Normal file
161
Engine/source/BadBehavior/core/Core.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
151
Engine/source/BadBehavior/core/Core.h
Normal file
151
Engine/source/BadBehavior/core/Core.h
Normal file
|
|
@ -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
|
||||||
106
Engine/source/BadBehavior/core/Decorator.cpp
Normal file
106
Engine/source/BadBehavior/core/Decorator.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
68
Engine/source/BadBehavior/core/Decorator.h
Normal file
68
Engine/source/BadBehavior/core/Decorator.h
Normal file
|
|
@ -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
|
||||||
278
Engine/source/BadBehavior/core/Runner.cpp
Normal file
278
Engine/source/BadBehavior/core/Runner.cpp
Normal file
|
|
@ -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 );
|
||||||
|
}
|
||||||
140
Engine/source/BadBehavior/core/Runner.h
Normal file
140
Engine/source/BadBehavior/core/Runner.h
Normal file
|
|
@ -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
|
||||||
168
Engine/source/BadBehavior/core/Signal.cpp
Normal file
168
Engine/source/BadBehavior/core/Signal.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
97
Engine/source/BadBehavior/core/Signal.h
Normal file
97
Engine/source/BadBehavior/core/Signal.h
Normal file
|
|
@ -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
|
||||||
71
Engine/source/BadBehavior/core/Stepper.cpp
Normal file
71
Engine/source/BadBehavior/core/Stepper.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
43
Engine/source/BadBehavior/core/Stepper.h
Normal file
43
Engine/source/BadBehavior/core/Stepper.h
Normal file
|
|
@ -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
|
||||||
106
Engine/source/BadBehavior/core/behavior.cpp
Normal file
106
Engine/source/BadBehavior/core/behavior.cpp
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
87
Engine/source/BadBehavior/core/behavior.h
Normal file
87
Engine/source/BadBehavior/core/behavior.h
Normal file
|
|
@ -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
|
||||||
51
Engine/source/BadBehavior/decorator/FailAlways.cpp
Normal file
51
Engine/source/BadBehavior/decorator/FailAlways.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
61
Engine/source/BadBehavior/decorator/FailAlways.h
Normal file
61
Engine/source/BadBehavior/decorator/FailAlways.h
Normal file
|
|
@ -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
|
||||||
54
Engine/source/BadBehavior/decorator/Inverter.cpp
Normal file
54
Engine/source/BadBehavior/decorator/Inverter.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
62
Engine/source/BadBehavior/decorator/Inverter.h
Normal file
62
Engine/source/BadBehavior/decorator/Inverter.h
Normal file
|
|
@ -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
|
||||||
120
Engine/source/BadBehavior/decorator/Loop.cpp
Normal file
120
Engine/source/BadBehavior/decorator/Loop.cpp
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
90
Engine/source/BadBehavior/decorator/Loop.h
Normal file
90
Engine/source/BadBehavior/decorator/Loop.h
Normal file
|
|
@ -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
|
||||||
54
Engine/source/BadBehavior/decorator/Monitor.cpp
Normal file
54
Engine/source/BadBehavior/decorator/Monitor.cpp
Normal file
|
|
@ -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));
|
||||||
|
}
|
||||||
61
Engine/source/BadBehavior/decorator/Monitor.h
Normal file
61
Engine/source/BadBehavior/decorator/Monitor.h
Normal file
|
|
@ -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_MONITOR_H_
|
||||||
|
#define _BB_MONITOR_H_
|
||||||
|
|
||||||
|
#ifndef _BB_DECORATOR_H_
|
||||||
|
#include "BadBehavior/core/Decorator.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Monitor decorator
|
||||||
|
// outputs the return status to the console,
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class Monitor : public DecoratorNode
|
||||||
|
{
|
||||||
|
typedef DecoratorNode Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(Monitor);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Monitor decorator task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class MonitorTask : public DecoratorTask
|
||||||
|
{
|
||||||
|
typedef DecoratorTask Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MonitorTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
virtual void onChildComplete(Status s);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
75
Engine/source/BadBehavior/decorator/Root.cpp
Normal file
75
Engine/source/BadBehavior/decorator/Root.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "Root.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Root decorator node
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(Root);
|
||||||
|
|
||||||
|
Task *Root::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
return new RootTask(*this, owner, runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Root decorator task
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
RootTask::RootTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
: Parent(node, owner, runner),
|
||||||
|
mBranch(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RootTask::~RootTask()
|
||||||
|
{
|
||||||
|
if(mBranch)
|
||||||
|
delete mBranch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootTask::onInitialize()
|
||||||
|
{
|
||||||
|
Parent::onInitialize();
|
||||||
|
if(!mBranch)
|
||||||
|
mBranch = new BehaviorTreeBranch(mChild);
|
||||||
|
else
|
||||||
|
mBranch->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task *RootTask::update()
|
||||||
|
{
|
||||||
|
mStatus = mBranch->update();
|
||||||
|
|
||||||
|
mIsComplete = mStatus != RUNNING && mStatus != SUSPENDED;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status RootTask::getStatus()
|
||||||
|
{
|
||||||
|
if(mStatus == SUSPENDED)
|
||||||
|
return mBranch->getStatus();
|
||||||
|
|
||||||
|
return mStatus;
|
||||||
|
}
|
||||||
73
Engine/source/BadBehavior/decorator/Root.h
Normal file
73
Engine/source/BadBehavior/decorator/Root.h
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_ROOT_H_
|
||||||
|
#define _BB_ROOT_H_
|
||||||
|
|
||||||
|
#ifndef _BB_BRANCH_H_
|
||||||
|
#include "BadBehavior/core/Branch.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _BB_DECORATOR_H_
|
||||||
|
#include "BadBehavior/core/Decorator.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Root decorator
|
||||||
|
// A placeholder node to mark the start of a tree.
|
||||||
|
// Used by the editor, bypassed during tree evaluation.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class Root : public DecoratorNode
|
||||||
|
{
|
||||||
|
typedef DecoratorNode Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Task* createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(Root);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Root task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class RootTask : public DecoratorTask
|
||||||
|
{
|
||||||
|
typedef DecoratorTask Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BehaviorTreeBranch *mBranch;
|
||||||
|
|
||||||
|
virtual Task* update();
|
||||||
|
virtual void onInitialize();
|
||||||
|
//virtual void onTerminate();
|
||||||
|
|
||||||
|
public:
|
||||||
|
RootTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
virtual ~RootTask();
|
||||||
|
|
||||||
|
virtual Status getStatus();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
51
Engine/source/BadBehavior/decorator/SucceedAlways.cpp
Normal file
51
Engine/source/BadBehavior/decorator/SucceedAlways.cpp
Normal file
|
|
@ -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 "SucceedAlways.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// SucceedAlways decorator node
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(SucceedAlways);
|
||||||
|
|
||||||
|
Task *SucceedAlways::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
return new SucceedAlwaysTask(*this, owner, runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// SucceedAlways decorator task
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
SucceedAlwaysTask::SucceedAlwaysTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
: Parent(node, owner, runner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SucceedAlwaysTask::onChildComplete(Status s)
|
||||||
|
{
|
||||||
|
Parent::onChildComplete(s);
|
||||||
|
if(mStatus == FAILURE)
|
||||||
|
mStatus = SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
61
Engine/source/BadBehavior/decorator/SucceedAlways.h
Normal file
61
Engine/source/BadBehavior/decorator/SucceedAlways.h
Normal file
|
|
@ -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_SUCCEEDALWAYS_H_
|
||||||
|
#define _BB_SUCCEEDALWAYS_H_
|
||||||
|
|
||||||
|
#ifndef _BB_DECORATOR_H_
|
||||||
|
#include "BadBehavior/core/Decorator.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// SucceedAlways decorator
|
||||||
|
// Returns SUCCESS if child returns SUCCESS or FAILURE. RUNNING and INVALID are unchanged
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class SucceedAlways : public DecoratorNode
|
||||||
|
{
|
||||||
|
typedef DecoratorNode Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(SucceedAlways);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// SucceedAlways task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class SucceedAlwaysTask : public DecoratorTask
|
||||||
|
{
|
||||||
|
typedef DecoratorTask Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SucceedAlwaysTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
virtual void onChildComplete(Status s);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
136
Engine/source/BadBehavior/decorator/Ticker.cpp
Normal file
136
Engine/source/BadBehavior/decorator/Ticker.cpp
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "Ticker.h"
|
||||||
|
#include "BadBehavior/core/Runner.h"
|
||||||
|
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Ticker decorator node
|
||||||
|
// **** EXPERIMENTAL ****
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(Ticker);
|
||||||
|
|
||||||
|
Ticker::Ticker()
|
||||||
|
: mFrequencyMs(100)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ticker::initPersistFields()
|
||||||
|
{
|
||||||
|
addGroup( "Behavior" );
|
||||||
|
|
||||||
|
addProtectedField( "frequencyMs", TypeS32, Offset(mFrequencyMs, Ticker), &_setFrequency, &defaultProtectedGetFn,
|
||||||
|
"The time to wait between evaluations of this nodes child." );
|
||||||
|
|
||||||
|
endGroup( "Behavior" );
|
||||||
|
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ticker::_setFrequency(void *object, const char *index, const char *data)
|
||||||
|
{
|
||||||
|
Ticker *node = static_cast<Ticker *>( object );
|
||||||
|
node->mFrequencyMs = getMax(0, dAtoi( data ));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task *Ticker::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
return new TickerTask(*this, owner, runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Ticker decorator task
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
TickerTask::TickerTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
: Parent(node, owner, runner),
|
||||||
|
mNextTimeMs(0),
|
||||||
|
mEventId(0),
|
||||||
|
mBranch(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TickerTask::~TickerTask()
|
||||||
|
{
|
||||||
|
cancelEvent();
|
||||||
|
|
||||||
|
if(mBranch)
|
||||||
|
delete mBranch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TickerTask::cancelEvent()
|
||||||
|
{
|
||||||
|
if(Sim::isEventPending(mEventId))
|
||||||
|
{
|
||||||
|
Sim::cancelEvent(mEventId);
|
||||||
|
mEventId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TickerTask::onInitialize()
|
||||||
|
{
|
||||||
|
Parent::onInitialize();
|
||||||
|
cancelEvent();
|
||||||
|
if(!mBranch)
|
||||||
|
mBranch = new BehaviorTreeBranch(mChild);
|
||||||
|
else
|
||||||
|
mBranch->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TickerTask::onTerminate()
|
||||||
|
{
|
||||||
|
Parent::onTerminate();
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task* TickerTask::update()
|
||||||
|
{
|
||||||
|
if(Sim::getCurrentTime() < mNextTimeMs)
|
||||||
|
{
|
||||||
|
if(!Sim::isEventPending(mEventId))
|
||||||
|
mEventId = Sim::postEvent(mRunner, new TaskReactivateEvent(*this), mNextTimeMs);
|
||||||
|
|
||||||
|
mStatus = SUSPENDED;
|
||||||
|
}
|
||||||
|
else if(mStatus != SUSPENDED)
|
||||||
|
{
|
||||||
|
mNextTimeMs = Sim::getCurrentTime() + static_cast<Ticker *>(mNodeRep)->getFrequencyMs();
|
||||||
|
Status s = mBranch->update();
|
||||||
|
mStatus = s != SUSPENDED ? s : RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsComplete = mStatus != SUSPENDED && mStatus != RUNNING;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status TickerTask::getStatus()
|
||||||
|
{
|
||||||
|
if(mStatus != SUSPENDED && mStatus != RESUME)
|
||||||
|
return mBranch->getStatus();
|
||||||
|
|
||||||
|
return mStatus;
|
||||||
|
}
|
||||||
89
Engine/source/BadBehavior/decorator/Ticker.h
Normal file
89
Engine/source/BadBehavior/decorator/Ticker.h
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_TICKER_H_
|
||||||
|
#define _BB_TICKER_H_
|
||||||
|
|
||||||
|
#ifndef _BB_DECORATOR_H_
|
||||||
|
#include "BadBehavior/core/Decorator.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _BB_BRANCH_H_
|
||||||
|
#include "BadBehavior/core/Branch.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Ticker decorator
|
||||||
|
// Limits the frequency at which it's children are updated.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class Ticker : public DecoratorNode
|
||||||
|
{
|
||||||
|
typedef DecoratorNode Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static bool _setFrequency(void *object, const char *index, const char *data);
|
||||||
|
|
||||||
|
// time between ticks (in ms)
|
||||||
|
S32 mFrequencyMs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Ticker();
|
||||||
|
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
S32 getFrequencyMs() const { return mFrequencyMs; }
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(Ticker);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Ticker decorator task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class TickerTask : public DecoratorTask
|
||||||
|
{
|
||||||
|
typedef DecoratorTask Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
U32 mNextTimeMs;
|
||||||
|
U32 mEventId;
|
||||||
|
|
||||||
|
BehaviorTreeBranch *mBranch;
|
||||||
|
|
||||||
|
virtual void onInitialize();
|
||||||
|
virtual void onTerminate();
|
||||||
|
virtual Task* update();
|
||||||
|
|
||||||
|
void cancelEvent();
|
||||||
|
|
||||||
|
public:
|
||||||
|
TickerTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
virtual ~TickerTask();
|
||||||
|
|
||||||
|
virtual Status getStatus();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
125
Engine/source/BadBehavior/leaf/RandomWait.cpp
Normal file
125
Engine/source/BadBehavior/leaf/RandomWait.cpp
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "RandomWait.h"
|
||||||
|
#include "BadBehavior/core/Runner.h"
|
||||||
|
|
||||||
|
#include "math/mMathFn.h"
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// RandomWait leaf node
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(RandomWait);
|
||||||
|
|
||||||
|
RandomWait::RandomWait()
|
||||||
|
: mWaitMinMs(0),
|
||||||
|
mWaitMaxMs(99999)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomWait::initPersistFields()
|
||||||
|
{
|
||||||
|
addGroup( "Behavior" );
|
||||||
|
|
||||||
|
addProtectedField( "waitMinMs", TypeS32, Offset(mWaitMinMs, RandomWait), &_setWaitMin, &defaultProtectedGetFn,
|
||||||
|
"The minimum time period in ms to wait before completion." );
|
||||||
|
|
||||||
|
addProtectedField( "waitMaxMs", TypeS32, Offset(mWaitMaxMs, RandomWait), &_setWaitMax, &defaultProtectedGetFn,
|
||||||
|
"The maximum time period in ms to wait before completion." );
|
||||||
|
|
||||||
|
endGroup( "Behavior" );
|
||||||
|
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RandomWait::_setWaitMin(void *object, const char *index, const char *data)
|
||||||
|
{
|
||||||
|
RandomWait *node = static_cast<RandomWait *>( object );
|
||||||
|
node->mWaitMinMs = getMin(node->mWaitMaxMs, dAtoi( data ));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RandomWait::_setWaitMax(void *object, const char *index, const char *data)
|
||||||
|
{
|
||||||
|
RandomWait *node = static_cast<RandomWait *>( object );
|
||||||
|
node->mWaitMaxMs = getMax(node->mWaitMinMs, dAtoi( data ));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task *RandomWait::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
return new RandomWaitTask(*this, owner, runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// RandomWait task
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
RandomWaitTask::RandomWaitTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
: Parent(node, owner, runner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomWaitTask::~RandomWaitTask()
|
||||||
|
{
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomWaitTask::cancelEvent()
|
||||||
|
{
|
||||||
|
if(Sim::isEventPending(mEventId))
|
||||||
|
{
|
||||||
|
Sim::cancelEvent(mEventId);
|
||||||
|
mEventId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomWaitTask::onInitialize()
|
||||||
|
{
|
||||||
|
Parent::onInitialize();
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomWaitTask::onTerminate()
|
||||||
|
{
|
||||||
|
Parent::onTerminate();
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task* RandomWaitTask::update()
|
||||||
|
{
|
||||||
|
if(mStatus == RESUME)
|
||||||
|
{
|
||||||
|
mStatus = SUCCESS;
|
||||||
|
mIsComplete = true;
|
||||||
|
}
|
||||||
|
else if(mStatus == INVALID)
|
||||||
|
{
|
||||||
|
RandomWait *node = static_cast<RandomWait*>(mNodeRep);
|
||||||
|
mEventId = Sim::postEvent(mRunner, new TaskReactivateEvent(*this), Sim::getCurrentTime() + mRandI(node->getWaitMinMs(), node->getWaitMaxMs()));
|
||||||
|
mStatus = SUSPENDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
83
Engine/source/BadBehavior/leaf/RandomWait.h
Normal file
83
Engine/source/BadBehavior/leaf/RandomWait.h
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_RANDOMWAIT_H_
|
||||||
|
#define _BB_RANDOMWAIT_H_
|
||||||
|
|
||||||
|
#ifndef _BB_CORE_H_
|
||||||
|
#include "BadBehavior/core/Core.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// RandomWait leaf
|
||||||
|
// Pauses for a random period of time between delayMin and delayMax ms before completing.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class RandomWait : public LeafNode
|
||||||
|
{
|
||||||
|
typedef LeafNode Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static bool _setWaitMin(void *object, const char *index, const char *data);
|
||||||
|
static bool _setWaitMax(void *object, const char *index, const char *data);
|
||||||
|
|
||||||
|
S32 mWaitMinMs;
|
||||||
|
S32 mWaitMaxMs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RandomWait();
|
||||||
|
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
S32 getWaitMinMs() const { return mWaitMinMs; }
|
||||||
|
S32 getWaitMaxMs() const { return mWaitMaxMs; }
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(RandomWait);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// RandomWait leaf task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class RandomWaitTask : public Task
|
||||||
|
{
|
||||||
|
typedef Task Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
U32 mEventId;
|
||||||
|
|
||||||
|
virtual void onInitialize();
|
||||||
|
virtual void onTerminate();
|
||||||
|
virtual Task* update();
|
||||||
|
|
||||||
|
void cancelEvent();
|
||||||
|
|
||||||
|
public:
|
||||||
|
RandomWaitTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
virtual ~RandomWaitTask();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
94
Engine/source/BadBehavior/leaf/ScriptEval.cpp
Normal file
94
Engine/source/BadBehavior/leaf/ScriptEval.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "ScriptEval.h"
|
||||||
|
|
||||||
|
#include "console/engineAPI.h"
|
||||||
|
#include "platform/profiler.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// ScriptEval node - warning, slow!
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(ScriptEval);
|
||||||
|
|
||||||
|
ScriptEval::ScriptEval()
|
||||||
|
: mDefaultReturnStatus(SUCCESS)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptEval::initPersistFields()
|
||||||
|
{
|
||||||
|
addGroup( "Behavior" );
|
||||||
|
|
||||||
|
addField( "behaviorScript", TypeCommand, Offset(mBehaviorScript, ScriptEval),
|
||||||
|
"@brief The command to execute when the leaf is ticked. Max 255 characters." );
|
||||||
|
|
||||||
|
addField( "defaultReturnStatus", TYPEID< BadBehavior::Status >(), Offset(mDefaultReturnStatus, ScriptEval),
|
||||||
|
"@brief The default value for this node to return.");
|
||||||
|
|
||||||
|
endGroup( "Behavior" );
|
||||||
|
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task *ScriptEval::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
return new ScriptEvalTask(*this, owner, runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status ScriptEval::evaluateScript( SimObject *owner )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE(ScriptEval_evaluateScript);
|
||||||
|
|
||||||
|
if(mBehaviorScript.isEmpty())
|
||||||
|
return mDefaultReturnStatus;
|
||||||
|
|
||||||
|
// get the result
|
||||||
|
const char *result = Con::evaluatef("%%obj=%s; %s return %s;",
|
||||||
|
owner->getIdString(),
|
||||||
|
mBehaviorScript.c_str(),
|
||||||
|
EngineMarshallData< BehaviorReturnType >(mDefaultReturnStatus));
|
||||||
|
|
||||||
|
if(result[0] == '1' || result[0] == '0')
|
||||||
|
// map true or false to SUCCEED or FAILURE
|
||||||
|
return static_cast<Status>(dAtoi(result));
|
||||||
|
|
||||||
|
// convert the returned value to our internal enum type
|
||||||
|
return EngineUnmarshallData< BehaviorReturnType >()( result );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// RunScript task
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
ScriptEvalTask::ScriptEvalTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
: Parent(node, owner, runner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Task* ScriptEvalTask::update()
|
||||||
|
{
|
||||||
|
mStatus = static_cast<ScriptEval*>(mNodeRep)->evaluateScript( mOwner );
|
||||||
|
|
||||||
|
return NULL; // leaves don't have children
|
||||||
|
}
|
||||||
75
Engine/source/BadBehavior/leaf/ScriptEval.h
Normal file
75
Engine/source/BadBehavior/leaf/ScriptEval.h
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_SCRIPTEVAL_H_
|
||||||
|
#define _BB_SCRIPTEVAL_H_
|
||||||
|
|
||||||
|
#ifndef _BB_CORE_H_
|
||||||
|
#include "BadBehavior/core/Core.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// ScriptEval - evaluates a set of Torque Script commands when run
|
||||||
|
// Warning - slow, handle with care!
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class ScriptEval : public LeafNode
|
||||||
|
{
|
||||||
|
typedef LeafNode Parent;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// status to return if the command does not return a value
|
||||||
|
Status mDefaultReturnStatus;
|
||||||
|
|
||||||
|
// the torque script to evaluate
|
||||||
|
String mBehaviorScript;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScriptEval();
|
||||||
|
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
// execute the script
|
||||||
|
Status evaluateScript(SimObject *owner);
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(ScriptEval);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// ScriptEval task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class ScriptEvalTask : public Task
|
||||||
|
{
|
||||||
|
typedef Task Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual Task* update();
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScriptEvalTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
#endif
|
||||||
121
Engine/source/BadBehavior/leaf/ScriptFunc.cpp
Normal file
121
Engine/source/BadBehavior/leaf/ScriptFunc.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "ScriptFunc.h"
|
||||||
|
|
||||||
|
#include "console/engineAPI.h"
|
||||||
|
#include "platform/profiler.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// ScriptFunc node
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(ScriptFunc);
|
||||||
|
|
||||||
|
ScriptFunc::ScriptFunc()
|
||||||
|
: mDefaultReturnStatus(SUCCESS),
|
||||||
|
mScriptFunction(StringTable->insert(""))
|
||||||
|
{
|
||||||
|
for(U8 i = 0; i < MAX_COMMAND_ARGS; ++i)
|
||||||
|
mScriptArgs[i] = StringTable->insert("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ScriptFunc::initPersistFields()
|
||||||
|
{
|
||||||
|
addGroup( "Behavior" );
|
||||||
|
|
||||||
|
addField( "func", TypeCaseString, Offset(mScriptFunction, ScriptFunc),
|
||||||
|
"@brief The function to execute when the leaf is ticked." );
|
||||||
|
|
||||||
|
addField( "args", TypeCaseString, Offset(mScriptArgs, ScriptFunc), MAX_COMMAND_ARGS,
|
||||||
|
"@brief The arguments to be passed to the function to be executed." );
|
||||||
|
|
||||||
|
addField( "defaultReturnStatus", TYPEID< BadBehavior::Status >(), Offset(mDefaultReturnStatus, ScriptFunc),
|
||||||
|
"@brief The default value for this node to return.");
|
||||||
|
|
||||||
|
endGroup( "Behavior" );
|
||||||
|
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task *ScriptFunc::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
return new ScriptFuncTask(*this, owner, runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status ScriptFunc::evaluate( SimObject *owner )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE(ScriptFunc_evaluate);
|
||||||
|
|
||||||
|
if(!owner)
|
||||||
|
return INVALID;
|
||||||
|
|
||||||
|
if(!mScriptFunction || !mScriptFunction[0])
|
||||||
|
return mDefaultReturnStatus;
|
||||||
|
|
||||||
|
S32 argc = 0;
|
||||||
|
|
||||||
|
const char *args[MAX_COMMAND_ARGS + 2];
|
||||||
|
args[0] = mScriptFunction;
|
||||||
|
|
||||||
|
while(argc < MAX_COMMAND_ARGS && (mScriptArgs[argc] && mScriptArgs[argc][0]))
|
||||||
|
{
|
||||||
|
args[argc + 2] = mScriptArgs[argc];
|
||||||
|
++argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc += 2;
|
||||||
|
|
||||||
|
// get the result
|
||||||
|
const char *result = Con::execute(owner, argc, args);
|
||||||
|
|
||||||
|
// if function didn't return a result, return our default status
|
||||||
|
if(!result || !result[0])
|
||||||
|
return mDefaultReturnStatus;
|
||||||
|
|
||||||
|
// map true or false to SUCCEED or FAILURE
|
||||||
|
if(result[0] == '1' || result[0] == '0')
|
||||||
|
return static_cast<Status>(dAtoi(result));
|
||||||
|
|
||||||
|
// convert the returned value to our internal enum type
|
||||||
|
return EngineUnmarshallData< BehaviorReturnType >()( result );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// ScriptFunc task
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
ScriptFuncTask::ScriptFuncTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
: Parent(node, owner, runner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Task* ScriptFuncTask::update()
|
||||||
|
{
|
||||||
|
mStatus = static_cast<ScriptFunc*>(mNodeRep)->evaluate( mOwner );
|
||||||
|
|
||||||
|
if(mStatus != RUNNING && mStatus != SUSPENDED)
|
||||||
|
mIsComplete = true;
|
||||||
|
|
||||||
|
return NULL; // leaves don't have children
|
||||||
|
}
|
||||||
79
Engine/source/BadBehavior/leaf/ScriptFunc.h
Normal file
79
Engine/source/BadBehavior/leaf/ScriptFunc.h
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_SCRIPTFUNC_H_
|
||||||
|
#define _BB_SCRIPTFUNC_H_
|
||||||
|
|
||||||
|
#ifndef _BB_CORE_H_
|
||||||
|
#include "BadBehavior/core/Core.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
static const U8 MAX_COMMAND_ARGS = 4;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// ScriptFunc - executes a function on the owner object
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class ScriptFunc : public LeafNode
|
||||||
|
{
|
||||||
|
typedef LeafNode Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// the function to call
|
||||||
|
StringTableEntry mScriptFunction;
|
||||||
|
|
||||||
|
// the arguments for the function
|
||||||
|
StringTableEntry mScriptArgs[MAX_COMMAND_ARGS];
|
||||||
|
|
||||||
|
// status to return if the command does not return a value
|
||||||
|
Status mDefaultReturnStatus;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScriptFunc();
|
||||||
|
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
// execute the command
|
||||||
|
Status evaluate(SimObject *owner);
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(ScriptFunc);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// ScriptFunc task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class ScriptFuncTask : public Task
|
||||||
|
{
|
||||||
|
typedef Task Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual Task* update();
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScriptFuncTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
#endif
|
||||||
83
Engine/source/BadBehavior/leaf/ScriptedBehavior.cpp
Normal file
83
Engine/source/BadBehavior/leaf/ScriptedBehavior.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "ScriptedBehavior.h"
|
||||||
|
|
||||||
|
#include "console/engineAPI.h"
|
||||||
|
#include "platform/profiler.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// ScriptedBehavior node
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(ScriptedBehavior);
|
||||||
|
|
||||||
|
IMPLEMENT_CALLBACK( ScriptedBehavior, onEnter, void, ( SimObject* owner ), ( owner ),
|
||||||
|
"Called when the behavior is first run.\n"
|
||||||
|
"@param owner The object that this behavior tree belongs to." );
|
||||||
|
|
||||||
|
IMPLEMENT_CALLBACK( ScriptedBehavior, onExit, void, ( SimObject* owner ), ( owner ),
|
||||||
|
"Called when the behavior is complete.\n"
|
||||||
|
"@param owner The object that this behavior tree belongs to." );
|
||||||
|
|
||||||
|
IMPLEMENT_CALLBACK( ScriptedBehavior, precondition, bool, ( SimObject* owner ), ( owner ),
|
||||||
|
"Called prior to evaluating the behavior.\n"
|
||||||
|
"@param owner The object that this behavior tree belongs to.\n"
|
||||||
|
"A return value of false indicates that evaluation of the behavior should stop.\n"
|
||||||
|
"A return value of true indicates that evaluation of the behavior should continue.");
|
||||||
|
|
||||||
|
IMPLEMENT_CALLBACK( ScriptedBehavior, behavior, Status, ( SimObject* owner ), ( owner ),
|
||||||
|
"Evaluate the main behavior of this node.\n"
|
||||||
|
"@param owner The object that this behavior tree belongs to.\n");
|
||||||
|
|
||||||
|
ScriptedBehavior::ScriptedBehavior()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptedBehavior::precondition( SimObject *owner )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE( ScriptedBehavior_precondition);
|
||||||
|
|
||||||
|
if(isMethod("precondition"))
|
||||||
|
return precondition_callback(owner);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptedBehavior::onEnter( SimObject *owner )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE( ScriptedBehavior_onEnter );
|
||||||
|
onEnter_callback(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptedBehavior::onExit( SimObject *owner )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE( ScriptedBehavior_onExit );
|
||||||
|
onExit_callback(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status ScriptedBehavior::behavior( SimObject *owner )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE( ScriptedBehavior_behavior );
|
||||||
|
return behavior_callback( owner );
|
||||||
|
}
|
||||||
56
Engine/source/BadBehavior/leaf/ScriptedBehavior.h
Normal file
56
Engine/source/BadBehavior/leaf/ScriptedBehavior.h
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_SCRIPTEDBEHAVIOR_H_
|
||||||
|
#define _BB_SCRIPTEDBEHAVIOR_H_
|
||||||
|
|
||||||
|
#ifndef _BB_CORE_H_
|
||||||
|
#include "BadBehavior/core/behavior.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// ScriptedBehavior - A structured behavior leaf node which defines a series
|
||||||
|
// Of scripted callbacks
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class ScriptedBehavior : public Behavior
|
||||||
|
{
|
||||||
|
typedef Behavior Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScriptedBehavior();
|
||||||
|
|
||||||
|
virtual bool precondition( SimObject *owner );
|
||||||
|
virtual void onEnter( SimObject *owner );
|
||||||
|
virtual void onExit( SimObject *owner );
|
||||||
|
virtual Status behavior( SimObject *owner );
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(ScriptedBehavior);
|
||||||
|
DECLARE_CALLBACK(void, onEnter, (SimObject *owner));
|
||||||
|
DECLARE_CALLBACK(void, onExit, (SimObject *owner));
|
||||||
|
DECLARE_CALLBACK(bool, precondition, (SimObject *owner));
|
||||||
|
DECLARE_CALLBACK(Status, behavior, (SimObject *owner));
|
||||||
|
};
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
76
Engine/source/BadBehavior/leaf/SubTree.cpp
Normal file
76
Engine/source/BadBehavior/leaf/SubTree.cpp
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "SubTree.h"
|
||||||
|
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// SubTree node - links to another behavior tree
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(SubTree);
|
||||||
|
|
||||||
|
SubTree::SubTree()
|
||||||
|
: mSubTreeName(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubTree::initPersistFields()
|
||||||
|
{
|
||||||
|
addGroup( "Behavior" );
|
||||||
|
|
||||||
|
addField( "subTreeName", TypeString, Offset(mSubTreeName, SubTree),
|
||||||
|
"@brief The name of the behavior tree that this node links to. Max 255 characters." );
|
||||||
|
|
||||||
|
endGroup( "Behavior" );
|
||||||
|
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task *SubTree::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
if(!mSubTreeName || mSubTreeName[0] == 0)
|
||||||
|
{
|
||||||
|
Con::errorf("SubTree::onInitialize: no sub tree specified");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimObject *subTreeNode;
|
||||||
|
|
||||||
|
if(!Sim::findObject(mSubTreeName, subTreeNode))
|
||||||
|
{
|
||||||
|
Con::errorf("SubTree:onInitialize: the specified sub tree does not exist");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *node = dynamic_cast<Node*>(subTreeNode);
|
||||||
|
if(!node)
|
||||||
|
{
|
||||||
|
Con::errorf("SubTree::onInitialize: the specified sub tree is not a behavior tree node");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->createTask(owner, runner);
|
||||||
|
}
|
||||||
56
Engine/source/BadBehavior/leaf/SubTree.h
Normal file
56
Engine/source/BadBehavior/leaf/SubTree.h
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_SUBTREE_H_
|
||||||
|
#define _BB_SUBTREE_H_
|
||||||
|
|
||||||
|
#ifndef _BB_CORE_H_
|
||||||
|
#include "BadBehavior/core/Core.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// SubTree decorator
|
||||||
|
// Turns a named Behavior into a subtree of this node.
|
||||||
|
// Does not actually have a child, so is a subclass of leaf
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class SubTree : public LeafNode
|
||||||
|
{
|
||||||
|
typedef LeafNode Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char* mSubTreeName;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SubTree();
|
||||||
|
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(SubTree);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
115
Engine/source/BadBehavior/leaf/Wait.cpp
Normal file
115
Engine/source/BadBehavior/leaf/Wait.cpp
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "Wait.h"
|
||||||
|
#include "BadBehavior/core/Runner.h"
|
||||||
|
|
||||||
|
#include "math/mMathFn.h"
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Wait leaf node
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(Wait);
|
||||||
|
|
||||||
|
Wait::Wait()
|
||||||
|
: mWaitMs(1000)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wait::initPersistFields()
|
||||||
|
{
|
||||||
|
addGroup( "Behavior" );
|
||||||
|
|
||||||
|
addProtectedField( "waitMs", TypeS32, Offset(mWaitMs, Wait), &_setWait, &defaultProtectedGetFn,
|
||||||
|
"The time in ms that the node should wait before completion." );
|
||||||
|
|
||||||
|
endGroup( "Behavior" );
|
||||||
|
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Wait::_setWait(void *object, const char *index, const char *data)
|
||||||
|
{
|
||||||
|
Wait *node = static_cast<Wait *>( object );
|
||||||
|
node->mWaitMs = getMax(0, dAtoi( data ));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task *Wait::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
return new WaitTask(*this, owner, runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Wait task
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
WaitTask::WaitTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
: Parent(node, owner, runner),
|
||||||
|
mEventId(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitTask::~WaitTask()
|
||||||
|
{
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitTask::cancelEvent()
|
||||||
|
{
|
||||||
|
if(Sim::isEventPending(mEventId))
|
||||||
|
{
|
||||||
|
Sim::cancelEvent(mEventId);
|
||||||
|
mEventId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitTask::onInitialize()
|
||||||
|
{
|
||||||
|
Parent::onInitialize();
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitTask::onTerminate()
|
||||||
|
{
|
||||||
|
Parent::onTerminate();
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task* WaitTask::update()
|
||||||
|
{
|
||||||
|
if(mStatus == RESUME)
|
||||||
|
{
|
||||||
|
mStatus = SUCCESS;
|
||||||
|
mIsComplete = true;
|
||||||
|
}
|
||||||
|
else if(mStatus == INVALID)
|
||||||
|
{
|
||||||
|
mEventId = Sim::postEvent(mRunner, new TaskReactivateEvent(*this), Sim::getCurrentTime() + static_cast<Wait*>(mNodeRep)->getWaitMs());
|
||||||
|
mStatus = SUSPENDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
80
Engine/source/BadBehavior/leaf/Wait.h
Normal file
80
Engine/source/BadBehavior/leaf/Wait.h
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_WAIT_H_
|
||||||
|
#define _BB_WAIT_H_
|
||||||
|
|
||||||
|
#ifndef _BB_CORE_H_
|
||||||
|
#include "BadBehavior/core/Core.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Wait leaf
|
||||||
|
// Pauses for a set time period.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class Wait : public LeafNode
|
||||||
|
{
|
||||||
|
typedef LeafNode Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static bool _setWait(void *object, const char *index, const char *data);
|
||||||
|
|
||||||
|
S32 mWaitMs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Wait();
|
||||||
|
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
S32 getWaitMs() const { return mWaitMs; }
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(Wait);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Wait leaf task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class WaitTask : public Task
|
||||||
|
{
|
||||||
|
typedef Task Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
U32 mEventId;
|
||||||
|
|
||||||
|
virtual void onInitialize();
|
||||||
|
virtual void onTerminate();
|
||||||
|
virtual Task* update();
|
||||||
|
|
||||||
|
void cancelEvent();
|
||||||
|
|
||||||
|
public:
|
||||||
|
WaitTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
virtual ~WaitTask();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
145
Engine/source/BadBehavior/leaf/WaitForSignal.cpp
Normal file
145
Engine/source/BadBehavior/leaf/WaitForSignal.cpp
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "WaitForSignal.h"
|
||||||
|
#include "BadBehavior/core/Runner.h"
|
||||||
|
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// WaitForSignal leaf node
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(WaitForSignal);
|
||||||
|
|
||||||
|
WaitForSignal::WaitForSignal()
|
||||||
|
: mTimeoutMs(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForSignal::initPersistFields()
|
||||||
|
{
|
||||||
|
addGroup( "Behavior" );
|
||||||
|
|
||||||
|
addField( "signalName", TypeRealString, Offset(mSignalName, WaitForSignal),
|
||||||
|
"The time in ms that the node should wait before completion." );
|
||||||
|
|
||||||
|
addProtectedField( "timeoutMs", TypeS32, Offset(mTimeoutMs, WaitForSignal), &_setTimeout, &defaultProtectedGetFn,
|
||||||
|
"The maximum time in ms that the node should wait for the signal.\n"
|
||||||
|
"A value of 0 indicates no limit");
|
||||||
|
|
||||||
|
endGroup( "Behavior" );
|
||||||
|
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task *WaitForSignal::createTask(SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
{
|
||||||
|
return new WaitForSignalTask(*this, owner, runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WaitForSignal::_setTimeout(void *object, const char *index, const char *data)
|
||||||
|
{
|
||||||
|
WaitForSignal *node = static_cast<WaitForSignal *>( object );
|
||||||
|
node->mTimeoutMs = getMax(0, dAtoi( data ));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Wait task
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
WaitForSignalTask::WaitForSignalTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
|
||||||
|
: Parent(node, owner, runner),
|
||||||
|
mEventId(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitForSignalTask::~WaitForSignalTask()
|
||||||
|
{
|
||||||
|
unsubscribe();
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForSignalTask::subscribe()
|
||||||
|
{
|
||||||
|
mRunner->subscribeToSignal(static_cast<WaitForSignal *>(mNodeRep)->getSignalName().c_str(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForSignalTask::unsubscribe()
|
||||||
|
{
|
||||||
|
mRunner->unsubscribeFromSignal(static_cast<WaitForSignal *>(mNodeRep)->getSignalName().c_str(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForSignalTask::onSignal()
|
||||||
|
{
|
||||||
|
onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForSignalTask::onTimeout()
|
||||||
|
{
|
||||||
|
mStatus = FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForSignalTask::cancelEvent()
|
||||||
|
{
|
||||||
|
if(mEventId != 0 && Sim::isEventPending(mEventId))
|
||||||
|
{
|
||||||
|
Sim::cancelEvent(mEventId);
|
||||||
|
mEventId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForSignalTask::onInitialize()
|
||||||
|
{
|
||||||
|
Parent::onInitialize();
|
||||||
|
subscribe();
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForSignalTask::onTerminate()
|
||||||
|
{
|
||||||
|
Parent::onTerminate();
|
||||||
|
unsubscribe();
|
||||||
|
cancelEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task* WaitForSignalTask::update()
|
||||||
|
{
|
||||||
|
if(mStatus == RESUME)
|
||||||
|
{
|
||||||
|
mStatus = SUCCESS;
|
||||||
|
}
|
||||||
|
else if (mStatus == INVALID)
|
||||||
|
{
|
||||||
|
mStatus = SUSPENDED;
|
||||||
|
|
||||||
|
S32 timeout = static_cast<WaitForSignal *>(mNodeRep)->getTimeoutMs();
|
||||||
|
if(timeout > 0)
|
||||||
|
mEventId = Sim::postEvent(mRunner, new WaitForSignalTimeoutEvent(*this), Sim::getCurrentTime() + timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mStatus == SUCCESS || mStatus == FAILURE)
|
||||||
|
mIsComplete = true;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
114
Engine/source/BadBehavior/leaf/WaitForSignal.h
Normal file
114
Engine/source/BadBehavior/leaf/WaitForSignal.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_WAITFORSIGNAL_H_
|
||||||
|
#define _BB_WAITFORSIGNAL_H_
|
||||||
|
|
||||||
|
#ifndef _BB_CORE_H_
|
||||||
|
#include "BadBehavior/core/Core.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _BB_SIGNAL_H_
|
||||||
|
#include "BadBehavior/core/Signal.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _SIMEVENTS_H_
|
||||||
|
#include "console/simEvents.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// WaitForSignal leaf
|
||||||
|
// Waits until it receives the requested signal.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class WaitForSignal : public LeafNode
|
||||||
|
{
|
||||||
|
typedef LeafNode Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
String mSignalName;
|
||||||
|
S32 mTimeoutMs;
|
||||||
|
|
||||||
|
static bool _setTimeout(void *object, const char *index, const char *data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
WaitForSignal();
|
||||||
|
|
||||||
|
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
const String &getSignalName() const { return mSignalName; }
|
||||||
|
S32 getTimeoutMs() const { return mTimeoutMs; }
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(WaitForSignal);
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// WaitForSignal leaf task
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class WaitForSignalTask : public Task, public virtual SignalSubscriber
|
||||||
|
{
|
||||||
|
typedef Task Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
U32 mEventId;
|
||||||
|
|
||||||
|
virtual void onInitialize();
|
||||||
|
virtual void onTerminate();
|
||||||
|
virtual Task* update();
|
||||||
|
|
||||||
|
void cancelEvent();
|
||||||
|
|
||||||
|
// SignalSubscriber
|
||||||
|
virtual void subscribe();
|
||||||
|
virtual void unsubscribe();
|
||||||
|
|
||||||
|
public:
|
||||||
|
WaitForSignalTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
|
||||||
|
virtual ~WaitForSignalTask();
|
||||||
|
|
||||||
|
// SignalSubscriber
|
||||||
|
virtual void onSignal();
|
||||||
|
|
||||||
|
// timeout
|
||||||
|
void onTimeout();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class WaitForSignalTimeoutEvent : public SimEvent
|
||||||
|
{
|
||||||
|
WaitForSignalTask *mTask;
|
||||||
|
public:
|
||||||
|
WaitForSignalTimeoutEvent(WaitForSignalTask &task)
|
||||||
|
{
|
||||||
|
mTask = &task;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process( SimObject *object )
|
||||||
|
{
|
||||||
|
mTask->onTimeout();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
109
Engine/source/BadBehavior/leaf/compiled/followBehaviorAction.cpp
Normal file
109
Engine/source/BadBehavior/leaf/compiled/followBehaviorAction.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "followBehaviorAction.h"
|
||||||
|
|
||||||
|
#include "T3D/aiPlayer.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// FollowBehavior node
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
IMPLEMENT_CONOBJECT(FollowBehaviorAction);
|
||||||
|
|
||||||
|
FollowBehaviorAction::FollowBehaviorAction()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FollowBehaviorAction::precondition( SimObject *owner )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE( FollowBehaviorAction_precondition);
|
||||||
|
|
||||||
|
// check that our owner is an AIPlayer
|
||||||
|
AIPlayer *aiPlayer = dynamic_cast<AIPlayer *>(owner);
|
||||||
|
if(!aiPlayer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FollowBehaviorAction::onEnter( SimObject *owner )
|
||||||
|
{
|
||||||
|
//PROFILE_SCOPE( FollowBehaviorAction_onEnter );
|
||||||
|
}
|
||||||
|
|
||||||
|
void FollowBehaviorAction::onExit( SimObject *owner )
|
||||||
|
{
|
||||||
|
//PROFILE_SCOPE( FollowBehaviorAction_onExit );
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FollowBehaviorAction::behavior( SimObject *owner )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE( FollowBehaviorAction_behavior );
|
||||||
|
|
||||||
|
// get the owning AIPlayer object
|
||||||
|
AIPlayer *aiPlayer = dynamic_cast<AIPlayer *>(owner);
|
||||||
|
if(!aiPlayer)
|
||||||
|
return FAILURE;
|
||||||
|
|
||||||
|
// get the script-specified followObject
|
||||||
|
const char *followFieldName = StringTable->insert("followObject");
|
||||||
|
const char *followFieldValue = owner->getDataField(followFieldName, NULL);
|
||||||
|
if(!followFieldValue || !followFieldValue[0])
|
||||||
|
return FAILURE;
|
||||||
|
|
||||||
|
SimObject *followSimObj = Sim::findObject(dAtoi(followFieldValue));
|
||||||
|
if(!followSimObj)
|
||||||
|
return FAILURE;
|
||||||
|
|
||||||
|
// check that the follow object is a SceneObject
|
||||||
|
SceneObject *followObject = dynamic_cast<SceneObject *>(followSimObj);
|
||||||
|
if(!followObject)
|
||||||
|
return FAILURE;
|
||||||
|
|
||||||
|
// get the script-specified followDistance field
|
||||||
|
const char *distanceFieldName = StringTable->insert("followDistance");
|
||||||
|
const char *distanceFieldValue = owner->getDataField(distanceFieldName, NULL);
|
||||||
|
float followDistance = 1.f;
|
||||||
|
if(distanceFieldValue && distanceFieldValue[0])
|
||||||
|
followDistance = dAtof(distanceFieldValue);
|
||||||
|
|
||||||
|
// try and stay at followDistance from the followObject
|
||||||
|
Point3F targetPos = followObject->getPosition();
|
||||||
|
Point3F followVec = aiPlayer->getPosition() - targetPos;
|
||||||
|
|
||||||
|
// get current distance (ignore z component)
|
||||||
|
F32 curDist = Point3F(followVec.x, followVec.y, 0.f).len();
|
||||||
|
|
||||||
|
if(mFabs(curDist - followDistance) > aiPlayer->getMoveTolerance())
|
||||||
|
{
|
||||||
|
followVec.normalize();
|
||||||
|
followVec *= followDistance;
|
||||||
|
Point3F destination = targetPos + followVec;
|
||||||
|
|
||||||
|
aiPlayer->setMoveDestination(destination, true);
|
||||||
|
return RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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_FOLLOWBEHAVIORACTION_H_
|
||||||
|
#define _BB_FOLLOWBEHAVIORACTION_H_
|
||||||
|
|
||||||
|
#ifndef _BB_CORE_H_
|
||||||
|
#include "BadBehavior/core/behavior.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// FollowBehaviorAction - Make an AIPlayer follow another object
|
||||||
|
// Demonstrates how to create a compiled behavior by subclassing Behavior
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
class FollowBehaviorAction : public Behavior
|
||||||
|
{
|
||||||
|
typedef Behavior Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FollowBehaviorAction();
|
||||||
|
|
||||||
|
virtual bool precondition( SimObject *owner );
|
||||||
|
virtual void onEnter( SimObject *owner );
|
||||||
|
virtual void onExit( SimObject *owner );
|
||||||
|
virtual Status behavior( SimObject *owner );
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(FollowBehaviorAction);
|
||||||
|
};
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
135
Engine/source/BadBehavior/tools/BTUndoActions.cpp
Normal file
135
Engine/source/BadBehavior/tools/BTUndoActions.cpp
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "BTUndoActions.h"
|
||||||
|
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
#include "console/simSet.h"
|
||||||
|
|
||||||
|
S32 getNextObjectInGroup(SimObject *object, SimGroup *group)
|
||||||
|
{
|
||||||
|
group->lock();
|
||||||
|
S32 nextId = -1;
|
||||||
|
|
||||||
|
if(object != group->last() && group->find( group->begin(), group->end(), object ) != group->end())
|
||||||
|
{
|
||||||
|
for( SimSet::iterator i = group->begin(); i != group->end(); i++)
|
||||||
|
{
|
||||||
|
if( *i == object )
|
||||||
|
{
|
||||||
|
nextId = (*++i)->getId();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
group->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_CONOBJECT( BTDeleteUndoAction );
|
||||||
|
|
||||||
|
ConsoleDocClass( BTDeleteUndoAction,
|
||||||
|
"@brief Behavior Tree Editor delete undo instance\n\n"
|
||||||
|
"Not intended for game development, for editors or internal use only.\n\n "
|
||||||
|
"@internal");
|
||||||
|
|
||||||
|
BTDeleteUndoAction::BTDeleteUndoAction( const UTF8 *actionName )
|
||||||
|
: UndoAction( actionName )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BTDeleteUndoAction::~BTDeleteUndoAction()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTDeleteUndoAction::initPersistFields()
|
||||||
|
{
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTDeleteUndoAction::deleteObject( SimObject *object )
|
||||||
|
{
|
||||||
|
AssertFatal( object, "BTDeleteUndoAction::deleteObject() - Got null object!" );
|
||||||
|
AssertFatal( object->isProperlyAdded(),
|
||||||
|
"BTDeleteUndoAction::deleteObject() - Object should be registered!" );
|
||||||
|
|
||||||
|
// Capture the object id.
|
||||||
|
mObject.id = object->getId();
|
||||||
|
|
||||||
|
// Save the state.
|
||||||
|
mObject.memento.save( object );
|
||||||
|
|
||||||
|
// Store the group.
|
||||||
|
SimGroup *group = object->getGroup();
|
||||||
|
if ( group )
|
||||||
|
{
|
||||||
|
mObject.groupId = group->getId();
|
||||||
|
|
||||||
|
// and the next object in the group
|
||||||
|
mObject.nextId = getNextObjectInGroup(object, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now delete the object.
|
||||||
|
object->deleteObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleMethod( BTDeleteUndoAction, deleteObject, void, 3, 3, "( SimObject obj )")
|
||||||
|
{
|
||||||
|
SimObject *obj = NULL;
|
||||||
|
if ( Sim::findObject( argv[2], obj ) && obj )
|
||||||
|
object->deleteObject( obj );
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTDeleteUndoAction::undo()
|
||||||
|
{
|
||||||
|
// Create the object.
|
||||||
|
SimObject::setForcedId(mObject.id); // Restore the object's Id
|
||||||
|
SimObject *object = mObject.memento.restore();
|
||||||
|
if ( !object )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Now restore its group.
|
||||||
|
SimGroup *group;
|
||||||
|
if ( Sim::findObject( mObject.groupId, group ) )
|
||||||
|
{
|
||||||
|
group->addObject( object );
|
||||||
|
|
||||||
|
// restore its position in the group
|
||||||
|
SimObject *nextObj;
|
||||||
|
if ( Sim::findObject( mObject.nextId, nextObj ) )
|
||||||
|
{
|
||||||
|
group->reOrder(object, nextObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Con::executef( this, "onUndone" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void BTDeleteUndoAction::redo()
|
||||||
|
{
|
||||||
|
SimObject *object = Sim::findObject( mObject.id );
|
||||||
|
if ( object )
|
||||||
|
object->deleteObject();
|
||||||
|
|
||||||
|
Con::executef( this, "onRedone" );
|
||||||
|
}
|
||||||
77
Engine/source/BadBehavior/tools/BTUndoActions.h
Normal file
77
Engine/source/BadBehavior/tools/BTUndoActions.h
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 _BT_UNDO_ACTIONS_H_
|
||||||
|
#define _BT_UNDO_ACTIONS_H_
|
||||||
|
|
||||||
|
#ifndef _UNDO_H_
|
||||||
|
#include "util/undo.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _CONSOLE_SIMOBJECTMEMENTO_H_
|
||||||
|
#include "console/simObjectMemento.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
S32 getNextObjectInSet(SimObject *obj, SimGroup &group);
|
||||||
|
|
||||||
|
class BTDeleteUndoAction : public UndoAction
|
||||||
|
{
|
||||||
|
typedef UndoAction Parent;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
struct ObjectState
|
||||||
|
{
|
||||||
|
/// The object we deleted and will restore in undo.
|
||||||
|
SimObjectId id;
|
||||||
|
|
||||||
|
/// The captured object state.
|
||||||
|
SimObjectMemento memento;
|
||||||
|
|
||||||
|
/// Keep track of the parent group.
|
||||||
|
SimObjectId groupId;
|
||||||
|
|
||||||
|
/// Keep track of the position within the parent group
|
||||||
|
SimObjectId nextId;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The object we're deleting.
|
||||||
|
ObjectState mObject;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT( BTDeleteUndoAction );
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
BTDeleteUndoAction( const UTF8* actionName = "Delete Object" );
|
||||||
|
virtual ~BTDeleteUndoAction();
|
||||||
|
|
||||||
|
///
|
||||||
|
void deleteObject( SimObject *object );
|
||||||
|
|
||||||
|
// UndoAction
|
||||||
|
virtual void undo();
|
||||||
|
virtual void redo();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _BT_UNDO_ACTIONS_H_
|
||||||
301
Engine/source/BadBehavior/tools/guiBTViewCtrl.cpp
Normal file
301
Engine/source/BadBehavior/tools/guiBTViewCtrl.cpp
Normal file
|
|
@ -0,0 +1,301 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 "guiBTViewCtrl.h"
|
||||||
|
|
||||||
|
#include "gfx/gfxDrawUtil.h"
|
||||||
|
#include "gui/worldEditor/editorIconRegistry.h"
|
||||||
|
#include "gui/controls/guiTextEditCtrl.h"
|
||||||
|
|
||||||
|
using namespace BadBehavior;
|
||||||
|
|
||||||
|
IMPLEMENT_CONOBJECT(GuiBehaviorTreeViewCtrl);
|
||||||
|
|
||||||
|
void GuiBehaviorTreeViewCtrl::onRenderCell(Point2I offset, Point2I cell, bool, bool )
|
||||||
|
{
|
||||||
|
if( !mVisibleItems.size() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Do some sanity checking and data retrieval.
|
||||||
|
AssertFatal(cell.y < mVisibleItems.size(), "GuiTreeViewCtrl::onRenderCell: invalid cell");
|
||||||
|
Item * item = mVisibleItems[cell.y];
|
||||||
|
|
||||||
|
// If there's no object, deal with it.
|
||||||
|
if(item->isInspectorData())
|
||||||
|
if(!item->getObject())
|
||||||
|
return;
|
||||||
|
|
||||||
|
RectI drawRect( offset, mCellSize );
|
||||||
|
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||||
|
drawer->clearBitmapModulation();
|
||||||
|
|
||||||
|
FrameAllocatorMarker txtBuff;
|
||||||
|
|
||||||
|
// Ok, we have the item. There are a few possibilities at this point:
|
||||||
|
// - We need to draw inheritance lines and a treeview-chosen icon
|
||||||
|
// OR
|
||||||
|
// - We have to draw an item-dependent icon
|
||||||
|
// - If we're mouseover, we have to highlight it.
|
||||||
|
//
|
||||||
|
// - We have to draw the text for the item
|
||||||
|
// - Taking into account various mouseover states
|
||||||
|
// - Taking into account the value (set or not)
|
||||||
|
// - If it's an inspector data, we have to do some custom rendering
|
||||||
|
// - ADDED: If it is being renamed, we also have custom rendering.
|
||||||
|
|
||||||
|
// Ok, first draw the tab and icon.
|
||||||
|
|
||||||
|
// Do we draw the tree lines?
|
||||||
|
if( mFlags.test(ShowTreeLines) )
|
||||||
|
{
|
||||||
|
drawRect.point.x += ( mTabSize * item->mTabLevel );
|
||||||
|
Item* parent = item->mParent;
|
||||||
|
for ( S32 i = item->mTabLevel; ( parent && i > 0 ); i-- )
|
||||||
|
{
|
||||||
|
drawRect.point.x -= mTabSize;
|
||||||
|
if ( parent->mNext )
|
||||||
|
drawer->drawBitmapSR( mProfile->mTextureObject, drawRect.point, mProfile->mBitmapArrayRects[BmpLine] );
|
||||||
|
|
||||||
|
parent = parent->mParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, the icon...
|
||||||
|
drawRect.point.x = offset.x + mTabSize * item->mTabLevel;
|
||||||
|
|
||||||
|
// First, draw the rollover glow, if it's an inner node.
|
||||||
|
if ( item->isParent() && item->mState.test( Item::MouseOverBmp ) )
|
||||||
|
drawer->drawBitmapSR( mProfile->mTextureObject, drawRect.point, mProfile->mBitmapArrayRects[BmpGlow] );
|
||||||
|
|
||||||
|
// Now, do we draw a treeview-selected item or an item dependent one?
|
||||||
|
S32 newOffset = 0; // This is stored so we can render glow, then update render pos.
|
||||||
|
|
||||||
|
S32 bitmap = 0;
|
||||||
|
|
||||||
|
// Ok, draw the treeview lines as appropriate.
|
||||||
|
|
||||||
|
bool drawBitmap = true;
|
||||||
|
if ( !item->isParent() )
|
||||||
|
{
|
||||||
|
if( mFlags.test( ShowTreeLines ) )
|
||||||
|
{
|
||||||
|
if( ( item->mNext && item->mPrevious )
|
||||||
|
|| ( item->mNext && item->mParent && ( !_isRootLevelItem( item ) || mShowRoot ) ) )
|
||||||
|
bitmap = BmpChild;
|
||||||
|
else if( item->mNext && ( !item->mParent || !mShowRoot ) )
|
||||||
|
bitmap = BmpFirstChild;
|
||||||
|
else if( item->mPrevious || ( item->mParent && !_isRootLevelItem( item ) ) )
|
||||||
|
bitmap = BmpLastChild;
|
||||||
|
else
|
||||||
|
drawBitmap = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
drawBitmap = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitmap = item->isExpanded() ? BmpExp : BmpCon;
|
||||||
|
|
||||||
|
if( mFlags.test( ShowTreeLines ) )
|
||||||
|
{
|
||||||
|
// Shift indices to show versions with tree lines.
|
||||||
|
|
||||||
|
if ( item->mParent || item->mPrevious )
|
||||||
|
bitmap += ( item->mNext ? 3 : 2 );
|
||||||
|
else
|
||||||
|
bitmap += ( item->mNext ? 1 : 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( bitmap >= 0 ) && ( bitmap < mProfile->mBitmapArrayRects.size() ) )
|
||||||
|
{
|
||||||
|
if( drawBitmap )
|
||||||
|
drawer->drawBitmapSR( mProfile->mTextureObject, drawRect.point, mProfile->mBitmapArrayRects[bitmap] );
|
||||||
|
newOffset = mProfile->mBitmapArrayRects[bitmap].extent.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(item->isInspectorData())
|
||||||
|
{
|
||||||
|
// draw lock icon if need be
|
||||||
|
S32 icon = Lock1;
|
||||||
|
S32 icon2 = Hidden;
|
||||||
|
|
||||||
|
if (item->getObject() && item->getObject()->isLocked())
|
||||||
|
{
|
||||||
|
if (mIconTable[icon])
|
||||||
|
{
|
||||||
|
//drawRect.point.x = offset.x + mTabSize * item->mTabLevel + mIconTable[icon].getWidth();
|
||||||
|
drawRect.point.x += mIconTable[icon].getWidth();
|
||||||
|
drawer->drawBitmap( mIconTable[icon], drawRect.point );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->getObject() && item->getObject()->isHidden())
|
||||||
|
{
|
||||||
|
if (mIconTable[icon2])
|
||||||
|
{
|
||||||
|
//drawRect.point.x = offset.x + mTabSize * item->mTabLevel + mIconTable[icon].getWidth();
|
||||||
|
drawRect.point.x += mIconTable[icon2].getWidth();
|
||||||
|
drawer->drawBitmap( mIconTable[icon2], drawRect.point );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*SimObject * pObject = item->getObject();
|
||||||
|
SimGroup * pGroup = ( pObject == NULL ) ? NULL : dynamic_cast<SimGroup*>( pObject );
|
||||||
|
|
||||||
|
// If this item is a VirtualParent we can use the generic SimGroup123 icons.
|
||||||
|
// However if there is already an icon in the EditorIconRegistry for this
|
||||||
|
// exact class (not counting parent class icons) we want to use that instead.
|
||||||
|
bool hasClassIcon = gEditorIcons.hasIconNoRecurse( pObject );
|
||||||
|
|
||||||
|
// draw the icon associated with the item
|
||||||
|
if ( !hasClassIcon && item->mState.test(Item::VirtualParent))
|
||||||
|
{
|
||||||
|
if ( pGroup != NULL)
|
||||||
|
{
|
||||||
|
if (item->isExpanded())
|
||||||
|
item->mIcon = SimGroup1;
|
||||||
|
else
|
||||||
|
item->mIcon = SimGroup2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
item->mIcon = SimGroup2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !hasClassIcon && item->mState.test(Item::Marked))
|
||||||
|
{
|
||||||
|
if (item->isInspectorData())
|
||||||
|
{
|
||||||
|
if ( pGroup != NULL )
|
||||||
|
{
|
||||||
|
if (item->isExpanded())
|
||||||
|
item->mIcon = SimGroup3;
|
||||||
|
else
|
||||||
|
item->mIcon = SimGroup4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
GFXTexHandle iconHandle;
|
||||||
|
|
||||||
|
if ( ( item->mIcon != -1 ) && mIconTable[item->mIcon] )
|
||||||
|
iconHandle = mIconTable[item->mIcon];
|
||||||
|
#ifdef TORQUE_TOOLS
|
||||||
|
else
|
||||||
|
iconHandle = gEditorIcons.findIcon( item->getObject() );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( iconHandle.isValid() )
|
||||||
|
{
|
||||||
|
S32 iconHeight = (mItemHeight - iconHandle.getHeight()) / 2;
|
||||||
|
S32 oldHeight = drawRect.point.y;
|
||||||
|
if(iconHeight > 0)
|
||||||
|
drawRect.point.y += iconHeight;
|
||||||
|
drawRect.point.x += iconHandle.getWidth();
|
||||||
|
drawer->drawBitmap( iconHandle, drawRect.point );
|
||||||
|
drawRect.point.y = oldHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
S32 icon = item->isExpanded() ? item->mScriptInfo.mExpandedImage : item->mScriptInfo.mNormalImage;
|
||||||
|
if ( icon )
|
||||||
|
{
|
||||||
|
if (mIconTable[icon])
|
||||||
|
{
|
||||||
|
S32 iconHeight = (mItemHeight - mIconTable[icon].getHeight()) / 2;
|
||||||
|
S32 oldHeight = drawRect.point.y;
|
||||||
|
if(iconHeight > 0)
|
||||||
|
drawRect.point.y += iconHeight;
|
||||||
|
drawRect.point.x += mIconTable[icon].getWidth();
|
||||||
|
drawer->drawBitmap( mIconTable[icon], drawRect.point );
|
||||||
|
drawRect.point.y = oldHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok, update offset so we can render some text!
|
||||||
|
drawRect.point.x += newOffset;
|
||||||
|
|
||||||
|
// Ok, now we're off to rendering the actual data for the treeview item.
|
||||||
|
|
||||||
|
U32 bufLen = 1024; //item->mDataRenderWidth + 1;
|
||||||
|
char *displayText = (char *)txtBuff.alloc(bufLen);
|
||||||
|
displayText[bufLen-1] = 0;
|
||||||
|
item->getDisplayText(bufLen, displayText);
|
||||||
|
|
||||||
|
// Draw the rollover/selected bitmap, if one was specified.
|
||||||
|
drawRect.extent.x = mProfile->mFont->getStrWidth( displayText ) + ( 2 * mTextOffset );
|
||||||
|
if ( item->mState.test( Item::Selected ) && mTexSelected )
|
||||||
|
drawer->drawBitmapStretch( mTexSelected, drawRect );
|
||||||
|
else if ( item->mState.test( Item::MouseOverText ) && mTexRollover )
|
||||||
|
drawer->drawBitmapStretch( mTexRollover, drawRect );
|
||||||
|
|
||||||
|
// Offset a bit so as to space text properly.
|
||||||
|
drawRect.point.x += mTextOffset;
|
||||||
|
|
||||||
|
// Determine what color the font should be.
|
||||||
|
ColorI fontColor;
|
||||||
|
|
||||||
|
fontColor = item->mState.test( Item::Selected ) ? mProfile->mFontColorSEL :
|
||||||
|
( item->mState.test( Item::MouseOverText ) ? mProfile->mFontColorHL : mProfile->mFontColor );
|
||||||
|
|
||||||
|
if (item->mState.test(Item::Selected))
|
||||||
|
{
|
||||||
|
drawer->drawRectFill(drawRect, mProfile->mFillColorSEL);
|
||||||
|
}
|
||||||
|
else if (item->mState.test(Item::MouseOverText))
|
||||||
|
{
|
||||||
|
drawer->drawRectFill(drawRect, mProfile->mFillColorHL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( item->mState.test(Item::MouseOverText) )
|
||||||
|
{
|
||||||
|
fontColor = mProfile->mFontColorHL;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawer->setBitmapModulation( fontColor );
|
||||||
|
|
||||||
|
// Center the text horizontally.
|
||||||
|
S32 height = (mItemHeight - mProfile->mFont->getHeight()) / 2;
|
||||||
|
|
||||||
|
if(height > 0)
|
||||||
|
drawRect.point.y += height;
|
||||||
|
|
||||||
|
// JDD - offset by two pixels or so to keep the text from rendering RIGHT ONTOP of the outline
|
||||||
|
drawRect.point.x += 2;
|
||||||
|
|
||||||
|
drawer->drawText( mProfile->mFont, drawRect.point, displayText, mProfile->mFontColors );
|
||||||
|
|
||||||
|
if ( mRenamingItem == item && mRenameCtrl )
|
||||||
|
{
|
||||||
|
Point2I ctrPos = globalToLocalCoord( drawRect.point );
|
||||||
|
ctrPos.y -= height;
|
||||||
|
ctrPos.x -= 2;
|
||||||
|
|
||||||
|
Point2I ctrExtent( getWidth() - ctrPos.x, drawRect.extent.y );
|
||||||
|
|
||||||
|
mRenameCtrl->setPosition( ctrPos );
|
||||||
|
mRenameCtrl->setExtent( ctrExtent );
|
||||||
|
mRenameCtrl->setVisible( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
45
Engine/source/BadBehavior/tools/guiBTViewCtrl.h
Normal file
45
Engine/source/BadBehavior/tools/guiBTViewCtrl.h
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 _GUI_BTVIEWCTRL_H_
|
||||||
|
#define _GUI_BTVIEWCTRL_H_
|
||||||
|
|
||||||
|
#ifndef _GUI_TREEVIEWCTRL_H
|
||||||
|
#include "gui/controls/guiTreeViewCtrl.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace BadBehavior
|
||||||
|
{
|
||||||
|
// subclassing GuiTreeViewCtrl so that we can tweak it for the behavior tree editor
|
||||||
|
class GuiBehaviorTreeViewCtrl : public GuiTreeViewCtrl
|
||||||
|
{
|
||||||
|
typedef GuiTreeViewCtrl Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void onRenderCell(Point2I offset, Point2I cell, bool, bool);
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(GuiBehaviorTreeViewCtrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BadBehavior
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -9,4 +9,5 @@
|
||||||
// In this case all the code in the "custom" folder in your project's source directory would be added
|
// In this case all the code in the "custom" folder in your project's source directory would be added
|
||||||
// addSrcDir('../source/custom');
|
// addSrcDir('../source/custom');
|
||||||
|
|
||||||
|
includeModule("BadBehavior");
|
||||||
?>
|
?>
|
||||||
|
|
@ -9,4 +9,5 @@
|
||||||
// In this case all the code in the "custom" folder in your project's source directory would be added
|
// In this case all the code in the "custom" folder in your project's source directory would be added
|
||||||
// addSrcDir('../source/custom');
|
// addSrcDir('../source/custom');
|
||||||
|
|
||||||
|
includeModule("BadBehavior");
|
||||||
?>
|
?>
|
||||||
|
|
@ -219,6 +219,13 @@ addPath("${srcDir}/platform/input")
|
||||||
addPath("${srcDir}/platform/output")
|
addPath("${srcDir}/platform/output")
|
||||||
addPath("${srcDir}/app")
|
addPath("${srcDir}/app")
|
||||||
addPath("${srcDir}/app/net")
|
addPath("${srcDir}/app/net")
|
||||||
|
addPath("${srcDir}/BadBehavior")
|
||||||
|
addPath("${srcDir}/BadBehavior/composite")
|
||||||
|
addPath("${srcDir}/BadBehavior/core")
|
||||||
|
addPath("${srcDir}/BadBehavior/decorator")
|
||||||
|
addPath("${srcDir}/BadBehavior/leaf")
|
||||||
|
addPath("${srcDir}/BadBehavior/leaf/compiled")
|
||||||
|
addPath("${srcDir}/BadBehavior/tools")
|
||||||
addPath("${srcDir}/util/messaging")
|
addPath("${srcDir}/util/messaging")
|
||||||
addPath("${srcDir}/gfx/Null")
|
addPath("${srcDir}/gfx/Null")
|
||||||
addPath("${srcDir}/gfx/test")
|
addPath("${srcDir}/gfx/test")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue