Adding a start screen led to cleaning up some initialisation processes. Dengine now formally initialises subsystems from the respective .h files instead of ad-hoc from the main game file.
299 lines
8.4 KiB
C
299 lines
8.4 KiB
C
#include "Dengine/Debug.h"
|
|
#include "Dengine/AssetManager.h"
|
|
#include "Dengine/MemoryArena.h"
|
|
#include "Dengine/Platform.h"
|
|
#include "Dengine/Renderer.h"
|
|
#include "Dengine/Asteroid.h"
|
|
|
|
typedef struct DebugState
|
|
{
|
|
b32 init;
|
|
Font font;
|
|
i32 *callCount;
|
|
f32 stringLineGap;
|
|
|
|
/* Debug strings rendered in top left corner */
|
|
char debugStrings[64][128];
|
|
i32 numDebugStrings;
|
|
f32 stringUpdateTimer;
|
|
f32 stringUpdateRate;
|
|
v2 initialStringP;
|
|
v2 currStringP;
|
|
|
|
/* Debug gui console log */
|
|
char console[20][128];
|
|
i32 consoleIndex;
|
|
v2 initialConsoleP;
|
|
} DebugState;
|
|
|
|
GLOBAL_VAR DebugState GLOBAL_debug;
|
|
|
|
void debug_init(MemoryArena_ *arena, v2 windowSize, Font font)
|
|
{
|
|
GLOBAL_debug.font = font;
|
|
GLOBAL_debug.callCount =
|
|
memory_pushBytes(arena, debugcount_num * sizeof(i32));
|
|
GLOBAL_debug.stringLineGap = CAST(f32) font.verticalSpacing;
|
|
|
|
/* Init debug string stack */
|
|
GLOBAL_debug.numDebugStrings = 0;
|
|
GLOBAL_debug.stringUpdateTimer = 0.0f;
|
|
GLOBAL_debug.stringUpdateRate = 0.15f;
|
|
|
|
GLOBAL_debug.initialStringP =
|
|
V2(0.0f, (windowSize.h - 1.8f * GLOBAL_debug.stringLineGap));
|
|
GLOBAL_debug.currStringP = GLOBAL_debug.initialStringP;
|
|
|
|
/* Init gui console */
|
|
i32 maxConsoleStrLen = ARRAY_COUNT(GLOBAL_debug.console[0]);
|
|
GLOBAL_debug.consoleIndex = 0;
|
|
|
|
// TODO(doyle): Font max size not entirely correct? using 1 * font.maxSize.w
|
|
// reveals around 4 characters ..
|
|
f32 consoleXPos = font.maxSize.w * 20;
|
|
f32 consoleYPos = windowSize.h - 1.8f * GLOBAL_debug.stringLineGap;
|
|
GLOBAL_debug.initialConsoleP = V2(consoleXPos, consoleYPos);
|
|
|
|
GLOBAL_debug.init = TRUE;
|
|
}
|
|
|
|
void debug_recursivePrintXmlTree(XmlNode *root, i32 levelsDeep)
|
|
{
|
|
if (!root)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
for (i32 i = 0; i < levelsDeep; i++)
|
|
{
|
|
printf("-");
|
|
}
|
|
|
|
printf("%s ", root->name);
|
|
|
|
XmlAttribute *attribute = &root->attribute;
|
|
printf("| %s = %s", attribute->name, attribute->value);
|
|
|
|
while (attribute->next)
|
|
{
|
|
attribute = attribute->next;
|
|
printf("| %s = %04s", attribute->name, attribute->value);
|
|
}
|
|
printf("\n");
|
|
|
|
debug_recursivePrintXmlTree(root->child, levelsDeep+1);
|
|
debug_recursivePrintXmlTree(root->next, levelsDeep);
|
|
}
|
|
}
|
|
|
|
void debug_countIncrement(i32 id)
|
|
{
|
|
if (GLOBAL_debug.init == FALSE) return;
|
|
|
|
ASSERT(id < debugcount_num);
|
|
GLOBAL_debug.callCount[id]++;
|
|
}
|
|
|
|
|
|
void debug_consoleLog(char *string, char *file, int lineNum)
|
|
{
|
|
|
|
i32 maxConsoleStrLen = ARRAY_COUNT(GLOBAL_debug.console[0]);
|
|
|
|
/* Completely clear out current console line */
|
|
for (i32 i = 0; i < maxConsoleStrLen; i++)
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][i] = 0;
|
|
|
|
i32 strIndex = 0;
|
|
i32 fileStrLen = common_strlen(file);
|
|
for (i32 count = 0; strIndex < maxConsoleStrLen; strIndex++, count++)
|
|
{
|
|
if (fileStrLen <= count) break;
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex] = file[count];
|
|
}
|
|
|
|
if (strIndex < maxConsoleStrLen)
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex++] = ':';
|
|
|
|
char line[12] = {0};
|
|
common_itoa(lineNum, line, ARRAY_COUNT(line));
|
|
i32 lineStrLen = common_strlen(line);
|
|
for (i32 count = 0; strIndex < maxConsoleStrLen; strIndex++, count++)
|
|
{
|
|
if (lineStrLen <= count) break;
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex] = line[count];
|
|
}
|
|
|
|
if (strIndex < maxConsoleStrLen)
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex++] = ':';
|
|
|
|
i32 stringStrLen = common_strlen(string);
|
|
for (i32 count = 0; strIndex < maxConsoleStrLen; strIndex++, count++)
|
|
{
|
|
if (stringStrLen <= count) break;
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex] = string[count];
|
|
}
|
|
|
|
if (strIndex >= maxConsoleStrLen)
|
|
{
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][maxConsoleStrLen-4] = '.';
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][maxConsoleStrLen-3] = '.';
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][maxConsoleStrLen-2] = '.';
|
|
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][maxConsoleStrLen-1] = 0;
|
|
}
|
|
|
|
i32 maxConsoleLines = ARRAY_COUNT(GLOBAL_debug.console);
|
|
GLOBAL_debug.consoleIndex++;
|
|
|
|
if (GLOBAL_debug.consoleIndex >= maxConsoleLines)
|
|
GLOBAL_debug.consoleIndex = 0;
|
|
}
|
|
|
|
void debug_pushString(char *formatString, void *data, char *dataType)
|
|
{
|
|
if (GLOBAL_debug.numDebugStrings >=
|
|
ARRAY_COUNT(GLOBAL_debug.debugStrings))
|
|
{
|
|
DEBUG_LOG("Debug string stack is full, DEBUG_PUSH() failed");
|
|
return;
|
|
}
|
|
|
|
if (GLOBAL_debug.stringUpdateTimer <= 0)
|
|
{
|
|
i32 numDebugStrings = GLOBAL_debug.numDebugStrings;
|
|
if (common_strcmp(dataType, "v2") == 0)
|
|
{
|
|
v2 val = *(CAST(v2 *) data);
|
|
snprintf(GLOBAL_debug.debugStrings[numDebugStrings],
|
|
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]),
|
|
formatString, val.x, val.y);
|
|
}
|
|
else if (common_strcmp(dataType, "v3") == 0)
|
|
{
|
|
v3 val = *(CAST(v3 *) data);
|
|
snprintf(GLOBAL_debug.debugStrings[numDebugStrings],
|
|
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]),
|
|
formatString, val.x, val.y, val.z);
|
|
}
|
|
else if (common_strcmp(dataType, "i32") == 0)
|
|
{
|
|
i32 val = *(CAST(i32 *) data);
|
|
snprintf(GLOBAL_debug.debugStrings[numDebugStrings],
|
|
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]),
|
|
formatString, val);
|
|
}
|
|
else if (common_strcmp(dataType, "f32") == 0)
|
|
{
|
|
f32 val = *(CAST(f32 *) data);
|
|
snprintf(GLOBAL_debug.debugStrings[numDebugStrings],
|
|
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]),
|
|
formatString, val);
|
|
}
|
|
else if (common_strcmp(dataType, "char") == 0)
|
|
{
|
|
if (data)
|
|
{
|
|
char *val = CAST(char *) data;
|
|
|
|
snprintf(GLOBAL_debug.debugStrings[numDebugStrings],
|
|
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]),
|
|
formatString, val);
|
|
}
|
|
else
|
|
{
|
|
snprintf(GLOBAL_debug.debugStrings[numDebugStrings],
|
|
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]),
|
|
formatString);
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
ASSERT(INVALID_CODE_PATH);
|
|
}
|
|
GLOBAL_debug.numDebugStrings++;
|
|
}
|
|
}
|
|
|
|
INTERNAL void updateAndRenderDebugStack(Renderer *renderer, MemoryArena_ *arena,
|
|
f32 dt)
|
|
{
|
|
for (i32 i = 0; i < GLOBAL_debug.numDebugStrings; i++)
|
|
{
|
|
f32 rotate = 0;
|
|
v4 color = V4(1, 1, 1, 1);
|
|
renderer_staticString(
|
|
renderer, arena, &GLOBAL_debug.font, GLOBAL_debug.debugStrings[i],
|
|
GLOBAL_debug.currStringP, V2(0, 0), rotate, color, 0);
|
|
GLOBAL_debug.currStringP.y -= (0.9f * GLOBAL_debug.stringLineGap);
|
|
}
|
|
|
|
if (GLOBAL_debug.stringUpdateTimer <= 0)
|
|
{
|
|
GLOBAL_debug.stringUpdateTimer =
|
|
GLOBAL_debug.stringUpdateRate;
|
|
}
|
|
else
|
|
{
|
|
GLOBAL_debug.stringUpdateTimer -= dt;
|
|
if (GLOBAL_debug.stringUpdateTimer <= 0)
|
|
{
|
|
GLOBAL_debug.numDebugStrings = 0;
|
|
}
|
|
}
|
|
|
|
GLOBAL_debug.currStringP = GLOBAL_debug.initialStringP;
|
|
|
|
}
|
|
|
|
INTERNAL void renderConsole(Renderer *renderer, MemoryArena_ *arena)
|
|
{
|
|
i32 maxConsoleLines = ARRAY_COUNT(GLOBAL_debug.console);
|
|
v2 consoleStrP = GLOBAL_debug.initialConsoleP;
|
|
for (i32 i = 0; i < maxConsoleLines; i++)
|
|
{
|
|
f32 rotate = 0;
|
|
v4 color = V4(1.0f, 1.0f, 1.0f, 1.0f);
|
|
renderer_staticString(renderer, arena, &GLOBAL_debug.font,
|
|
GLOBAL_debug.console[i], consoleStrP,
|
|
V2(0, 0), rotate, color, 0);
|
|
consoleStrP.y -= (0.9f * GLOBAL_debug.stringLineGap);
|
|
}
|
|
}
|
|
|
|
void debug_drawUi(GameState *state, f32 dt)
|
|
{
|
|
{ // Print Memory Arena Info
|
|
DEBUG_PUSH_STRING("== MEMORY ARENAS ==");
|
|
MemoryArena_ *transient = &state->transientArena;
|
|
i32 transientSizeInKbs = transient->size / 1024;
|
|
i32 transientUsedInKbs = transient->used / 1024;
|
|
v2 transientUsage = V2i(transientUsedInKbs, transientSizeInKbs);
|
|
DEBUG_PUSH_VAR("Transient Usage: %.0f/%.0f", transientUsage, "v2");
|
|
|
|
MemoryArena_ *persistent = &state->persistentArena;
|
|
i32 persistentSizeInKbs = persistent->size / 1024;
|
|
i32 persistentUsedInKbs = persistent->used / 1024;
|
|
v2 persistentUsage = V2i(persistentUsedInKbs, persistentSizeInKbs);
|
|
DEBUG_PUSH_VAR("Permanent Usage: %.0f/%.0f", persistentUsage, "v2");
|
|
|
|
MemoryArena_ *entityArena = &state->world.entityArena;
|
|
i32 entitySizeInKbs = entityArena->size / 1024;
|
|
i32 entityUsedInKbs = entityArena->used / 1024;
|
|
v2 entityUsage = V2i(entityUsedInKbs, entitySizeInKbs);
|
|
DEBUG_PUSH_VAR("Entity Usage: %.0f/%.0f", entityUsage, "v2");
|
|
DEBUG_PUSH_STRING("== ==");
|
|
}
|
|
|
|
DEBUG_PUSH_VAR("Num Vertex: %d",
|
|
GLOBAL_debug.callCount[debugcount_numVertex], "i32");
|
|
|
|
updateAndRenderDebugStack(&state->renderer, &state->transientArena, dt);
|
|
renderConsole(&state->renderer, &state->transientArena);
|
|
|
|
{ // Clear debug call counters
|
|
for (i32 i = 0; i < debugcount_num; i++) GLOBAL_debug.callCount[i] = 0;
|
|
}
|
|
}
|