Add cleanup for compsites in BT + refactor
This commit is contained in:
@@ -345,7 +345,8 @@ static BzBTNodeState *getNodeState(const BzBTNode *node, BzBTExecState *state) {
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
static BzBTNodeState *ensureValidNodeState(const BzBTNode *node, BzObjectPool *pool, BzBTNodeState *existing) {
|
||||
static BzBTNodeState *ensureValidNodeState(const BzBTNode *node, BzBTNodeState *existing,
|
||||
BzObjectPool *pool) {
|
||||
if (existing)
|
||||
return existing;
|
||||
|
||||
@@ -356,12 +357,24 @@ static BzBTNodeState *ensureValidNodeState(const BzBTNode *node, BzObjectPool *p
|
||||
bzMemSet(&existing->as, 0, sizeof(existing->as));
|
||||
return existing;
|
||||
}
|
||||
static void releaseNodeState(BzObjectPool *pool, BzBTNodeState *nodeState) {
|
||||
static void releaseNodeState(BzBTNodeState *nodeState, BzObjectPool *pool) {
|
||||
bzObjectPoolRelease(pool, nodeState);
|
||||
}
|
||||
|
||||
static inline void bzBTClearNodeState(const BzBTNode *node, BzBTExecState *state,
|
||||
BzObjectPool *pool) {
|
||||
BzBTNodeState *nodeState = getNodeState(node, state);
|
||||
if (nodeState == NULL) return;
|
||||
releaseNodeState(nodeState, pool);
|
||||
|
||||
const BzBTNode *first = node->first;
|
||||
while (first) {
|
||||
bzBTClearNodeState(first, state, pool);
|
||||
first = first->next;
|
||||
}
|
||||
}
|
||||
static inline BzBTExecReturn bzBTExecuteNode(const BzBTNode *node, f32 dt,
|
||||
BzBTExecState *nodeState, BzObjectPool *statePool);
|
||||
BzBTExecState *state, BzObjectPool *statePool);
|
||||
static inline BzBTExecReturn bzBTExecuteComposite(const BzBTNode *node, f32 dt,
|
||||
BzBTExecState *state, BzObjectPool *statePool) {
|
||||
BzBTNodeState *nodeState = getNodeState(node, state);
|
||||
@@ -445,14 +458,22 @@ static inline BzBTExecReturn bzBTExecuteComposite(const BzBTNode *node, f32 dt,
|
||||
|
||||
bool finished = execReturn.status == BZ_BT_SUCCESS ||
|
||||
execReturn.status == BZ_BT_FAIL;
|
||||
|
||||
// Clean up, if exited prematurely
|
||||
const BzBTNode *pChild = child;
|
||||
while (finished && pChild) {
|
||||
bzBTClearNodeState(pChild, state, statePool);
|
||||
pChild = pChild->next;
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
BZ_ASSERT(execReturn.state.first == NULL);
|
||||
if (nodeState) releaseNodeState(statePool, nodeState);
|
||||
if (nodeState) releaseNodeState(nodeState, statePool);
|
||||
return execReturn;
|
||||
}
|
||||
BZ_ASSERT(execReturn.status == BZ_BT_RUNNING);
|
||||
// Parallels don't utilize state but still require it for correct tree traversal.
|
||||
nodeState = ensureValidNodeState(node, statePool, nodeState);
|
||||
nodeState = ensureValidNodeState(node, nodeState, statePool);
|
||||
nodeState->as.composite.running = child;
|
||||
execStatePushFront(&execReturn.state, nodeState);
|
||||
|
||||
@@ -469,11 +490,11 @@ static inline BzBTExecReturn bzBTExecuteDecorator(const BzBTNode *node, f32 dt,
|
||||
|
||||
switch (node->type) {
|
||||
case BZ_BT_DECOR_REPEAT:
|
||||
nodeState = ensureValidNodeState(node, statePool, nodeState);
|
||||
nodeState = ensureValidNodeState(node, nodeState, statePool);
|
||||
execStatePushBack(&execReturn.state, nodeState);
|
||||
break;
|
||||
case BZ_BT_DECOR_DELAY:
|
||||
nodeState = ensureValidNodeState(node, statePool, nodeState);
|
||||
nodeState = ensureValidNodeState(node, nodeState, statePool);
|
||||
nodeState->as.delay.elapsed += dt;
|
||||
execStatePushBack(&execReturn.state, nodeState);
|
||||
if (nodeState->as.delay.elapsed < node->as.delay.ms) {
|
||||
@@ -481,7 +502,7 @@ static inline BzBTExecReturn bzBTExecuteDecorator(const BzBTNode *node, f32 dt,
|
||||
return execReturn;
|
||||
}
|
||||
BZ_ASSERT(nodeState == execStatePopFront(&execReturn.state));
|
||||
releaseNodeState(statePool, nodeState);
|
||||
releaseNodeState(nodeState, statePool);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -542,7 +563,7 @@ static inline BzBTExecReturn bzBTExecuteDecorator(const BzBTNode *node, f32 dt,
|
||||
nodeState->as.repeat.iter++;
|
||||
if (nodeState->as.repeat.iter >= node->as.repeat.n) {
|
||||
BZ_ASSERT(nodeState == execStatePopFront(&execReturn.state));
|
||||
releaseNodeState(statePool, nodeState);
|
||||
releaseNodeState(nodeState, statePool);
|
||||
execReturn.status = childReturn.status;
|
||||
break;
|
||||
}
|
||||
@@ -554,14 +575,14 @@ static inline BzBTExecReturn bzBTExecuteDecorator(const BzBTNode *node, f32 dt,
|
||||
return execReturn;
|
||||
}
|
||||
static inline BzBTExecReturn bzBTExecuteNode(const BzBTNode *node, f32 dt,
|
||||
BzBTExecState *nodeState, BzObjectPool *statePool) {
|
||||
BzBTExecState *state, BzObjectPool *statePool) {
|
||||
BzBTExecReturn execReturn = { .status = BZ_BT_ERROR };
|
||||
switch (node->type) {
|
||||
case BZ_BT_COMP_SELECTOR:
|
||||
case BZ_BT_COMP_SEQUENCE:
|
||||
case BZ_BT_COMP_P_SELECTOR:
|
||||
case BZ_BT_COMP_P_SEQUENCE:
|
||||
execReturn = bzBTExecuteComposite(node, dt, nodeState, statePool);
|
||||
execReturn = bzBTExecuteComposite(node, dt, state, statePool);
|
||||
break;
|
||||
case BZ_BT_DECOR_DUMMY:
|
||||
case BZ_BT_DECOR_SUCCESS:
|
||||
@@ -571,11 +592,11 @@ static inline BzBTExecReturn bzBTExecuteNode(const BzBTNode *node, f32 dt,
|
||||
case BZ_BT_DECOR_UNTIL_FAIL:
|
||||
case BZ_BT_DECOR_REPEAT:
|
||||
case BZ_BT_DECOR_DELAY:
|
||||
execReturn = bzBTExecuteDecorator(node, dt, nodeState, statePool);
|
||||
execReturn = bzBTExecuteDecorator(node, dt, state, statePool);
|
||||
break;
|
||||
case BZ_BT_ACTION:
|
||||
BZ_ASSERT(node->as.action.fn);
|
||||
execReturn.status = node->as.action.fn(nodeState->userData, dt);
|
||||
execReturn.status = node->as.action.fn(state->userData, dt);
|
||||
break;
|
||||
}
|
||||
return execReturn;
|
||||
|
||||
@@ -26,7 +26,7 @@ bool init(int *game) {
|
||||
// delay 1s
|
||||
// print "Hello, world!"
|
||||
printBT = bzBTMakeRoot(nodePool);
|
||||
BzBTNode *pseq = bzBTCompSequence(nodePool, printBT, true);
|
||||
BzBTNode *pseq = bzBTCompSelector(nodePool, printBT, true);
|
||||
bzBTDecorDelay(nodePool, pseq, 2.0f);
|
||||
|
||||
BzBTNode *node = bzBTDecorRepeat(nodePool, pseq, 5);
|
||||
|
||||
Reference in New Issue
Block a user