Refactor behaviour_tree (more consistent naming), fix BT visualization
This commit is contained in:
@@ -26,7 +26,10 @@ bool init(int *game) {
|
||||
// delay 1s
|
||||
// print "Hello, world!"
|
||||
printBT = bzBTMakeRoot(nodePool);
|
||||
BzBTNode *node = bzBTDecorRepeat(nodePool, printBT, 5);
|
||||
BzBTNode *pseq = bzBTCompSequence(nodePool, printBT, true);
|
||||
bzBTDecorDelay(nodePool, pseq, 2.0f);
|
||||
|
||||
BzBTNode *node = bzBTDecorRepeat(nodePool, pseq, 5);
|
||||
|
||||
BzBTNode *seq = bzBTCompSequence(nodePool, node, false);
|
||||
|
||||
@@ -48,78 +51,14 @@ void deinit(int *game) {
|
||||
bzObjectPoolDestroy(nodeStatePool);
|
||||
}
|
||||
|
||||
void igVisualizeBTState(const BzBTNode *node, const BzBTNodeState *state, bool sameLine, i32 depth) {
|
||||
const BzBTNode *child = bzBTNodeChild(node);
|
||||
BzBTNodeType type = bzBTGetNodeType(node);
|
||||
char extraInfo[128];
|
||||
extraInfo[0] = '\0';
|
||||
|
||||
bool hasState = bzBTNodeMatchesState(node, state);
|
||||
|
||||
switch (type) {
|
||||
case BZ_BT_DECOR_REPEAT:
|
||||
if (hasState) {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%d < %d)",
|
||||
bzBTRepeatStateGetIter(state),
|
||||
bzBTDecorGetRepeat(node));
|
||||
} else {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%d)", bzBTDecorGetRepeat(node));
|
||||
}
|
||||
break;
|
||||
case BZ_BT_DECOR_DELAY:
|
||||
if (hasState) {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%.2f < %.2fms)",
|
||||
bzBTDelayStateGetElapsed(state),
|
||||
bzBTDecorGetDelay(node));
|
||||
} else {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%.2fms)", bzBTDecorGetDelay(node));
|
||||
}
|
||||
break;
|
||||
case BZ_BT_ACTION:
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%s:%p)",
|
||||
bzBTNodeGetName(node) ? bzBTNodeGetName(node) : "?",
|
||||
bzBTActionGetFn(node));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (hasState)
|
||||
state = bzBTNodeStateNext(state);
|
||||
|
||||
ImVec4 color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
if (hasState)
|
||||
color = (ImVec4) {1.0f, 1.0f, 0.5f, 1.0f};
|
||||
|
||||
bool hasSingleChild = false;
|
||||
if (child && bzBTNodeNext(child) == NULL) hasSingleChild = true;
|
||||
|
||||
const char *suffix = hasSingleChild ? " > " : ": ";
|
||||
|
||||
if (sameLine) {
|
||||
igTextColored(color, "%s%s%s", bzBTNodeTypeToStr(type),
|
||||
extraInfo, suffix);
|
||||
} else {
|
||||
igTextColored(color, "%*s%s %s",
|
||||
depth * 2, "",
|
||||
bzBTNodeTypeToStr(type), extraInfo, suffix);
|
||||
depth++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
while (child) {
|
||||
if (hasSingleChild) igSameLine(0, 0);
|
||||
igVisualizeBTState(child, state, hasSingleChild, depth);
|
||||
child = bzBTNodeNext(child);
|
||||
}
|
||||
}
|
||||
|
||||
void igVisualizeBTState(const BzBTNode *node, const BzBTNodeState *state,
|
||||
bool isActive, bool sameLine, i32 depth);
|
||||
void igRenderBT(BzBTState *state) {
|
||||
const BzBTNode *root = state->root;
|
||||
if (igBegin("BehaviourTree", NULL, 0)) {
|
||||
igText("NodeState pool: %d", bzObjectPoolGetNumFree(nodeStatePool));
|
||||
igSeparatorText("");
|
||||
igVisualizeBTState(root, state->_first, false, 0);
|
||||
igVisualizeBTState(root, state->_first, true, false, 0);
|
||||
}
|
||||
igEnd();
|
||||
}
|
||||
@@ -143,3 +82,89 @@ bool bzMain(BzAppDesc *appDesc, int argc, const char **argv) {
|
||||
|
||||
return true;
|
||||
}
|
||||
static const BzBTNodeState *findNodeState(const BzBTNode *node, const BzBTNodeState *state) {
|
||||
const BzBTNodeState *pState = state;
|
||||
|
||||
// Although it's painfully slow, it serves as a debug tool,
|
||||
// so speed is not a critical concern.
|
||||
while (pState) {
|
||||
const BzBTNodeState *next = bzBTNodeStateNext(pState);
|
||||
if (bzBTNodeMatchesState(node, pState))
|
||||
return pState;
|
||||
pState = next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void igVisualizeBTState(const BzBTNode *node, const BzBTNodeState *state,
|
||||
bool isActive, bool sameLine, i32 depth) {
|
||||
const BzBTNode *child = bzBTNodeChild(node);
|
||||
BzBTNodeType type = bzBTGetNodeType(node);
|
||||
char extraInfo[128];
|
||||
extraInfo[0] = '\0';
|
||||
|
||||
const BzBTNodeState *nodeState = findNodeState(node, state);
|
||||
bool hasState = nodeState != NULL;
|
||||
isActive |= hasState;
|
||||
|
||||
switch (type) {
|
||||
case BZ_BT_DECOR_REPEAT:
|
||||
if (hasState) {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%d < %d)",
|
||||
bzBTRepeatStateGetIter(nodeState),
|
||||
bzBTDecorGetRepeat(node));
|
||||
} else {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%d)", bzBTDecorGetRepeat(node));
|
||||
}
|
||||
break;
|
||||
case BZ_BT_DECOR_DELAY:
|
||||
if (hasState) {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%.2f < %.2fms)",
|
||||
bzBTDelayStateGetElapsed(nodeState),
|
||||
bzBTDecorGetDelay(node));
|
||||
} else {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%.2fms)", bzBTDecorGetDelay(node));
|
||||
}
|
||||
break;
|
||||
case BZ_BT_ACTION:
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%s:%p)",
|
||||
bzBTNodeGetName(node) ? bzBTNodeGetName(node) : "?",
|
||||
bzBTActionGetFn(node));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
ImVec4 color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
if (isActive)
|
||||
color = (ImVec4) {1.0f, 1.0f, 0.5f, 1.0f};
|
||||
|
||||
bool hasSingleChild = true;
|
||||
if (child && bzBTNodeNext(child)) hasSingleChild = false;
|
||||
|
||||
const char *suffix = hasSingleChild ? " > " : ": ";
|
||||
|
||||
if (sameLine) {
|
||||
igTextColored(color, "%s%s%s", bzBTNodeTypeToStr(type),
|
||||
extraInfo, suffix);
|
||||
} else {
|
||||
igTextColored(color, "%*s%s %s",
|
||||
depth * 2, "",
|
||||
bzBTNodeTypeToStr(type), extraInfo, suffix);
|
||||
depth++;
|
||||
}
|
||||
|
||||
bool isComposite = type == BZ_BT_COMP_SELECTOR ||
|
||||
type == BZ_BT_COMP_P_SELECTOR ||
|
||||
type == BZ_BT_COMP_SEQUENCE ||
|
||||
type == BZ_BT_COMP_P_SEQUENCE;
|
||||
|
||||
while (child) {
|
||||
if (hasSingleChild) igSameLine(0, 0);
|
||||
bool childActive = isActive && hasSingleChild;
|
||||
if (hasState && isComposite && !childActive)
|
||||
childActive = bzBTCompStateGetRunningChild(state) == child;
|
||||
igVisualizeBTState(child, state, childActive, hasSingleChild, depth);
|
||||
child = bzBTNodeNext(child);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user