Beginning input refactor

This commit is contained in:
2025-09-03 11:57:48 -05:00
parent 059ccf41b6
commit 3f37b7cdb5
19 changed files with 320 additions and 137 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

1
assets/init.cfg Normal file
View File

@@ -0,0 +1 @@
bind w up;

View File

@@ -24,7 +24,6 @@ errorret_t assetAlphaImageLoad(asset_t *asset) {
errorThrow("Invalid alpha image height.");
}
printf("Alpha image dimensions: %ux%u\n", raw.width, raw.height);
zip_int64_t expecting = (
sizeof(raw.width) +
sizeof(raw.height) +

View File

@@ -29,7 +29,6 @@ errorret_t assetPaletteImageLoad(asset_t *asset) {
errorThrow("Invalid palette index.");
}
printf("Palette image dimensions: %ux%u\n", raw.width, raw.height);
zip_int64_t expecting = (
sizeof(raw.width) +
sizeof(raw.height) +

View File

@@ -13,6 +13,7 @@
#include "console/cmd/cmdecho.h"
#include "console/cmd/cmdset.h"
#include "console/cmd/cmdget.h"
#include "input/input.h"
console_t CONSOLE;
@@ -310,6 +311,12 @@ void consoleUpdate() {
threadMutexLock(&CONSOLE.execMutex);
#endif
// Toggle console
if(inputPressed(INPUT_BIND_CONSOLE)) {
CONSOLE.visible = !CONSOLE.visible;
}
// Exec pending buffer.
for(uint32_t i = 0; i < CONSOLE.execBufferCount; i++) {
consolecmdexec_t *exec = &CONSOLE.execBuffer[i];
assertNotNull(exec->cmd, "Command execution has no command.");
@@ -382,5 +389,4 @@ void consoleDispose(void) {
pfd.revents = 0;
}
}
#endif

View File

@@ -17,7 +17,11 @@ display_t DISPLAY;
errorret_t displayInit(void) {
#if DISPLAY_SDL2
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) != 0) {
uint32_t flags = SDL_INIT_VIDEO;
#if INPUT_SUPPORT_GAMEPAD
flags |= SDL_INIT_GAMECONTROLLER;
#endif
if(SDL_Init(flags) != 0) {
errorThrow("SDL Failed to Initialize: %s", SDL_GetError());
}

View File

@@ -12,7 +12,6 @@
#include "display/scene/scenemanager.h"
#include "display/mesh/quad.h"
#include "asset/assetmanager.h"
#include "display/ui/rendertext.h"
camera_t SCENE_OVERWORLD_CAMERA;
asset_t *testAsset;

View File

@@ -6,6 +6,7 @@
# Sources
target_sources(${DUSK_TARGET_NAME}
PRIVATE
rendertext.c
uitext.c
ui.c
uiconsole.c
)

View File

@@ -6,44 +6,56 @@
*/
#include "ui.h"
#include "rendertext.h"
#include "uitext.h"
#include "display/framebuffer/framebuffer.h"
#include "display/spritebatch/spritebatch.h"
#include "uiconsole.h"
#include "util/memory.h"
camera_t UI_CAMERA;
ui_t UI;
errorret_t uiInit(void) {
errorChain(renderTextInit());
memoryZero(&UI, sizeof(ui_t));
errorChain(uiTextInit());
cameraInit(&UI_CAMERA);
UI_CAMERA.projType = CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC;
cameraInit(&UI.camera);
UI.camera.projType = CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC;
UI_CAMERA.orthographic.left = 0.0f;
UI_CAMERA.orthographic.top = 0.0f;
UI_CAMERA.orthographic.right = frameBufferGetWidth(&FRAMEBUFFER_BACKBUFFER);
UI_CAMERA.orthographic.bottom = frameBufferGetHeight(&FRAMEBUFFER_BACKBUFFER);
UI_CAMERA.nearClip = -1.0f;
UI_CAMERA.farClip = 1.0f;
UI.camera.orthographic.left = 0.0f;
UI.camera.orthographic.top = 0.0f;
UI.camera.orthographic.right = frameBufferGetWidth(&FRAMEBUFFER_BACKBUFFER);
UI.camera.orthographic.bottom = frameBufferGetHeight(&FRAMEBUFFER_BACKBUFFER);
UI.camera.nearClip = -1.0f;
UI.camera.farClip = 1.0f;
UI_CAMERA.viewType = CAMERA_VIEW_TYPE_MATRIX;
glm_mat4_identity(UI_CAMERA.view);
UI.camera.viewType = CAMERA_VIEW_TYPE_MATRIX;
glm_mat4_identity(UI.camera.view);
UI.scale = 2.0f;
errorOk();
}
void uiUpdate(void) {
}
void uiRender(void) {
UI_CAMERA.orthographic.right = frameBufferGetWidth(FRAMEBUFFER_BOUND);
UI_CAMERA.orthographic.bottom = frameBufferGetHeight(FRAMEBUFFER_BOUND);
UI.camera.orthographic.right = (
frameBufferGetWidth(FRAMEBUFFER_BOUND) / UI.scale
);
UI.camera.orthographic.bottom = (
frameBufferGetHeight(FRAMEBUFFER_BOUND) / UI.scale
);
cameraPushMatrix(&UI_CAMERA);
cameraPushMatrix(&UI.camera);
renderTextDraw(10.0f, 10.0f, "Dusk Engine UI", 0xFF, 0xFF, 0xFF);
uiConsoleRender();
spriteBatchFlush();
cameraPopMatrix();
}
void uiDispose(void) {
renderTextDispose();
uiTextDispose();
}

View File

@@ -9,9 +9,31 @@
#include "error/error.h"
#include "display/camera.h"
extern camera_t UI_CAMERA;
typedef struct {
camera_t camera;
float_t scale;
} ui_t;
extern ui_t UI;
/**
* Initializes the UI system.
*
* @return An errorret_t indicating success or failure.
*/
errorret_t uiInit(void);
/**
* Updates the UI system. Will not render anything.
*/
void uiUpdate(void);
/**
* Renders the UI system.
*/
void uiRender(void);
/**
* Disposes of the UI system.
*/
void uiDispose(void);

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "uiconsole.h"
#include "uitext.h"
#include "console/console.h"
void uiConsoleRender(void) {
if(!CONSOLE.visible) return;
int32_t i = 0;
char_t *line;
do {
line = CONSOLE.line[i];
if(line[0] == '\0') {
i++;
continue;
}
uiTextDraw(
0, i * UI_TEXT_TILE_HEIGHT, line,
0xFF, 0xFF, 0xFF
);
i++;
} while(i < CONSOLE_HISTORY_MAX);
}

View File

@@ -0,0 +1,11 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dusk.h"
void uiConsoleRender(void);

View File

@@ -5,32 +5,30 @@
// * https://opensource.org/licenses/MIT
// */
#include "rendertext.h"
#include "uitext.h"
#include "asset/assetmanager.h"
#include "assert/assert.h"
#include "util/memory.h"
#include "display/spritebatch/spritebatch.h"
// #include "display/display.h"
// #include "util/math.h"
rendertext_t RENDER_TEXT;
uitext_t UI_TEXT;
errorret_t renderTextInit(void) {
memoryZero(&RENDER_TEXT, sizeof(rendertext_t));
errorret_t uiTextInit(void) {
memoryZero(&UI_TEXT, sizeof(uitext_t));
errorChain(assetManagerLoadAsset(
"font_minogram.dai", &RENDER_TEXT.asset, &RENDER_TEXT.assetRef
"font_minogram.dai", &UI_TEXT.asset, &UI_TEXT.assetRef
));
errorOk();
}
void renderTextDispose(void) {
if(RENDER_TEXT.asset) {
assetUnlock(RENDER_TEXT.asset, RENDER_TEXT.assetRef);
void uiTextDispose(void) {
if(UI_TEXT.asset) {
assetUnlock(UI_TEXT.asset, UI_TEXT.assetRef);
}
}
void renderTextDrawChar(
void uiTextDrawChar(
const float_t x,
const float_t y,
const char_t c,
@@ -38,30 +36,34 @@ void renderTextDrawChar(
const uint8_t g,
const uint8_t b
) {
int32_t tileIndex = (int32_t)(c) - RENDER_TEXT_CHAR_START;
int32_t tileIndex = (int32_t)(c) - UI_TEXT_CHAR_START;
if(tileIndex < 0 || tileIndex >= UI_TEXT_TILE_COUNT) {
tileIndex = ((int32_t)'@') - UI_TEXT_CHAR_START;
}
assertTrue(
tileIndex >= 0 && tileIndex <= RENDER_TEXT_TILE_COUNT,
tileIndex >= 0 && tileIndex <= UI_TEXT_TILE_COUNT,
"Character is out of bounds for font tiles"
);
const float_t w = (float)RENDER_TEXT.asset->alphaImage.texture.width;
const float_t h = (float)RENDER_TEXT.asset->alphaImage.texture.height;
const int32_t tileX = (tileIndex % RENDER_TEXT_COLUMN_COUNT);
const int32_t tileY = (tileIndex / RENDER_TEXT_COLUMN_COUNT);
const float_t w = (float)UI_TEXT.asset->alphaImage.texture.width;
const float_t h = (float)UI_TEXT.asset->alphaImage.texture.height;
const int32_t tileX = (tileIndex % UI_TEXT_COLUMN_COUNT);
const int32_t tileY = (tileIndex / UI_TEXT_COLUMN_COUNT);
spriteBatchPush(
&RENDER_TEXT.asset->alphaImage.texture,
&UI_TEXT.asset->alphaImage.texture,
x, y,
x + RENDER_TEXT_TILE_WIDTH, y + RENDER_TEXT_TILE_HEIGHT,
x + UI_TEXT_TILE_WIDTH, y + UI_TEXT_TILE_HEIGHT,
r, g, b, 0xFF,
(tileX * RENDER_TEXT_TILE_WIDTH) / w,
(tileY * RENDER_TEXT_TILE_HEIGHT) / h,
((tileX + 1) * RENDER_TEXT_TILE_WIDTH) / w,
((tileY + 1) * RENDER_TEXT_TILE_HEIGHT) / h
(tileX * UI_TEXT_TILE_WIDTH) / w,
(tileY * UI_TEXT_TILE_HEIGHT) / h,
((tileX + 1) * UI_TEXT_TILE_WIDTH) / w,
((tileY + 1) * UI_TEXT_TILE_HEIGHT) / h
);
}
void renderTextDraw(
void uiTextDraw(
const float_t x,
const float_t y,
const char_t *text,
@@ -79,21 +81,21 @@ void renderTextDraw(
while((c = text[i++]) != '\0') {
if(c == '\n') {
posX = x;
posY += RENDER_TEXT_TILE_HEIGHT;
posY += UI_TEXT_TILE_HEIGHT;
continue;
}
if(c == ' ') {
posX += RENDER_TEXT_TILE_WIDTH;
posX += UI_TEXT_TILE_WIDTH;
continue;
}
renderTextDrawChar(posX, posY, c, r, g, b);
posX += RENDER_TEXT_TILE_WIDTH;
uiTextDrawChar(posX, posY, c, r, g, b);
posX += UI_TEXT_TILE_WIDTH;
}
}
void renderTextMeasure(
void uiTextMeasure(
const char_t *text,
int32_t *outWidth,
int32_t *outHeight
@@ -103,7 +105,7 @@ void renderTextMeasure(
assertNotNull(outHeight, "Output height pointer cannot be NULL");
int32_t width = 0;
int32_t height = RENDER_TEXT_TILE_HEIGHT;
int32_t height = UI_TEXT_TILE_HEIGHT;
int32_t lineWidth = 0;
char_t c;
@@ -114,11 +116,11 @@ void renderTextMeasure(
width = lineWidth;
}
lineWidth = 0;
height += RENDER_TEXT_TILE_HEIGHT;
height += UI_TEXT_TILE_HEIGHT;
continue;
}
lineWidth += RENDER_TEXT_TILE_WIDTH;
lineWidth += UI_TEXT_TILE_WIDTH;
}
if(lineWidth > width) {

View File

@@ -8,26 +8,26 @@
#pragma once
#include "asset/assetmanager.h"
#define RENDER_TEXT_CHAR_START '@'
#define UI_TEXT_CHAR_START '!'
#define RENDER_TEXT_COLUMN_COUNT 16
#define RENDER_TEXT_ROW_COUNT 6
#define RENDER_TEXT_TILE_COUNT (RENDER_TEXT_COLUMN_COUNT*RENDER_TEXT_ROW_COUNT)
#define UI_TEXT_COLUMN_COUNT 16
#define UI_TEXT_ROW_COUNT 6
#define UI_TEXT_TILE_COUNT (UI_TEXT_COLUMN_COUNT*UI_TEXT_ROW_COUNT)
#define RENDER_TEXT_TILE_WIDTH 6.0f
#define RENDER_TEXT_TILE_HEIGHT 10.0f
#define UI_TEXT_TILE_WIDTH 6.0f
#define UI_TEXT_TILE_HEIGHT 10.0f
typedef struct {
ref_t assetRef;
asset_t *asset;
} rendertext_t;
} uitext_t;
extern rendertext_t RENDER_TEXT;
extern uitext_t UI_TEXT;
/**
* Initializes the text rendering system.
*/
errorret_t renderTextInit(void);
errorret_t uiTextInit(void);
/**
* Draws a single character at the specified position.
@@ -39,7 +39,7 @@ errorret_t renderTextInit(void);
* @param g The green component of the color (0-255).
* @param b The blue component of the color (0-255).
*/
void renderTextDrawChar(
void uiTextDrawChar(
const float_t x,
const float_t y,
const char_t c,
@@ -58,7 +58,7 @@ void renderTextDrawChar(
* @param g The green component of the color (0-255).
* @param b The blue component of the color (0-255).
*/
void renderTextDraw(
void uiTextDraw(
const float_t x,
const float_t y,
const char_t *text,
@@ -74,7 +74,7 @@ void renderTextDraw(
* @param outWidth Pointer to store the measured width in pixels.
* @param outHeight Pointer to store the measured height in pixels.
*/
void renderTextMeasure(
void uiTextMeasure(
const char_t *text,
int32_t *outWidth,
int32_t *outHeight
@@ -83,4 +83,4 @@ void renderTextMeasure(
/**
* Disposes of the text rendering system, freeing any allocated resources.
*/
void renderTextDispose(void);
void uiTextDispose(void);

View File

@@ -8,6 +8,7 @@
#include "engine.h"
#include "util/memory.h"
#include "time/time.h"
#include "input/input.h"
#include "console/console.h"
#include "display/display.h"
#include "asset/assetmanager.h"
@@ -22,6 +23,7 @@ errorret_t engineInit(void) {
// Init systems. Order is important.
timeInit();
inputInit();
consoleInit();
errorChain(assetManagerInit());
errorChain(displayInit());
@@ -32,6 +34,7 @@ errorret_t engineInit(void) {
errorret_t engineUpdate(void) {
timeUpdate();
inputUpdate();
consoleUpdate();
assetManagerUpdate();
errorChain(displayUpdate());

View File

@@ -8,3 +8,19 @@ target_sources(${DUSK_TARGET_NAME}
PRIVATE
input.c
)
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
target_compile_definitions(${DUSK_TARGET_NAME}
PRIVATE
INPUT_SDL2=1
INPUT_KEYBOARD=1
INPUT_MOUSE=1
INPUT_GAMEPAD=1
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
target_compile_definitions(${DUSK_TARGET_NAME}
PRIVATE
INPUT_SDL=1
INPUT_GAMEPAD=1
)
endif()

View File

@@ -13,25 +13,57 @@ input_t INPUT;
void inputInit(void) {
memoryZero(&INPUT, sizeof(input_t));
INPUT.binds[INPUT_BIND_UP].keyboard[0] = SDL_SCANCODE_W;
INPUT.binds[INPUT_BIND_UP].keyboard[1] = SDL_SCANCODE_UP;
INPUT.binds[INPUT_BIND_CONSOLE].keyboard[0] = SDL_SCANCODE_GRAVE;
}
void inputUpdate(void) {
INPUT.previous = INPUT.current;
INPUT.current = inputStateGet();
#if INPUT_SDL2 == 1
const uint8_t *keyboardState = SDL_GetKeyboardState(NULL);
#endif
// For each input bind...
inputbinddata_t *data = INPUT.binds;
do {
data->lastValue = data->currentValue;
data->currentValue = 0.0f;
// Handle keyboard
#if INPUT_KEYBOARD == 1
for(uint32_t i = 0; i < INPUT_BIND_KEYBOARD_BUTTONS_MAX; i++) {
if(data->keyboard[i] == 0) break;
#if INPUT_SDL2 == 1
if(keyboardState[data->keyboard[i]]) {
data->currentValue = 1.0f;
break;
}
#endif
}
#endif
data++;
} while(data < INPUT.binds + INPUT_BIND_COUNT);
}
inputstate_t inputStateGet(void) {
return 0;
float_t inputGetCurrentValue(const inputbind_t bind) {
assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds");
return INPUT.binds[bind].currentValue;
}
float_t inputGetLast(const inputbind_t bind) {
assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds");
return INPUT.binds[bind].lastValue;
}
bool_t inputIsDown(const inputbind_t bind) {
assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds");
return (INPUT.current & bind) != 0;
return inputGetCurrentValue(bind) > 0.0f;
}
bool_t inputWasDown(const inputbind_t bind) {
assertTrue(bind < INPUT_BIND_COUNT, "Input bind out of bounds");
return (INPUT.previous & bind) != 0;
return inputGetLast(bind) > 0.0f;
}
bool_t inputPressed(const inputbind_t bind) {

View File

@@ -8,23 +8,60 @@
#pragma once
#include "dusk.h"
typedef uint8_t inputbind_t;
typedef inputbind_t inputstate_t;
#if INPUT_SDL2 == 1
#include <SDL2/SDL.h>
#else
#error "No input backend defined"
#endif
#define INPUT_BIND_UP (1 << 0)
#define INPUT_BIND_DOWN (1 << 1)
#define INPUT_BIND_LEFT (1 << 2)
#define INPUT_BIND_RIGHT (1 << 3)
#define INPUT_BIND_ACTION (1 << 4)
#define INPUT_BIND_CANCEL (1 << 5)
#define INPUT_BIND_CONSOLE (1 << 6)
#define INPUT_BIND_QUIT (1 << 7)
// Keyboard defs
#if INPUT_KEYBOARD == 1
#define INPUT_BIND_KEYBOARD_BUTTONS_MAX 32
#define INPUT_BIND_COUNT (INPUT_BIND_QUIT + 1)
#if INPUT_SDL2 == 1
typedef SDL_Scancode inputscancode_t;
#endif
#endif
// Gamepad defs
#if INPUT_GAMEPAD == 1
#define INPUT_GAMEPAD_BUTTON_NAME_MAX 8
#define INPUT_BIND_GAMEPAD_BUTTONS_MAX 8
#if INPUT_SDL2 == 1
typedef SDL_GameControllerButton inputgamepadbutton_t;
#endif
#endif
typedef enum {
INPUT_BIND_UP,
INPUT_BIND_DOWN,
INPUT_BIND_LEFT,
INPUT_BIND_RIGHT,
INPUT_BIND_ACCEPT,
INPUT_BIND_CANCEL,
INPUT_BIND_CONSOLE,
INPUT_BIND_COUNT
} inputbind_t;
typedef struct {
uint8_t current;
uint8_t previous;
inputbind_t bind;
float_t lastValue;
float_t currentValue;
#if INPUT_GAMEPAD == 1
inputgamepadbutton_t gamepad[INPUT_BIND_GAMEPAD_BUTTONS_MAX];
uint8_t gamepadButtonCount;
#endif
#if INPUT_KEYBOARD == 1
inputscancode_t keyboard[INPUT_BIND_KEYBOARD_BUTTONS_MAX];
#endif
} inputbinddata_t;
typedef struct {
inputbinddata_t binds[INPUT_BIND_COUNT];
} input_t;
extern input_t INPUT;
@@ -40,11 +77,20 @@ void inputInit(void);
void inputUpdate(void);
/**
* Gets the current input state as a bitmask.
* Gets the current value of a specific input bind.
*
* @return The current input state as a bitmask.
* @param bind The input bind to get the value for.
* @return The current value of the bind (0.0f to 1.0f).
*/
inputstate_t inputStateGet(void);
float_t inputGetCurrentValue(const inputbind_t bind);
/**
* Gets the last value of a specific input bind.
*
* @param bind The input bind to get the value for.
* @return The last value of the bind (0.0f to 1.0f).
*/
float_t inputGetLast(const inputbind_t bind);
/**
* Checks if a specific input bind is currently pressed.

View File

@@ -36,51 +36,52 @@ void playerEntityUpdate(entity_t *entity) {
// if(UI_TEXTBOX.visible) return;
if(entityIsMoving(entity)) return;
const uint8_t moveSpeed = inputIsDown(INPUT_BIND_CANCEL) ? PLAYER_SPEED_RUN : PLAYER_SPEED_WALK;
// const uint8_t moveSpeed = inputIsDown(INPUT_BIND_CANCEL) ? PLAYER_SPEED_RUN : PLAYER_SPEED_WALK;
const uint8_t moveSpeed = PLAYER_SPEED_WALK;
if(inputIsDown(INPUT_BIND_UP)) {
if(entity->dir != DIRECTION_NORTH) {
entityTurn(entity, DIRECTION_NORTH);
return;
}
entityMove(entity, moveSpeed);
return;
// if(inputIsDown(INPUT_BIND_UP)) {
// if(entity->dir != DIRECTION_NORTH) {
// entityTurn(entity, DIRECTION_NORTH);
// return;
// }
// entityMove(entity, moveSpeed);
// return;
} else if(inputIsDown(INPUT_BIND_DOWN)) {
if(entity->dir != DIRECTION_SOUTH) {
entityTurn(entity, DIRECTION_SOUTH);
return;
}
// } else if(inputIsDown(INPUT_BIND_DOWN)) {
// if(entity->dir != DIRECTION_SOUTH) {
// entityTurn(entity, DIRECTION_SOUTH);
// return;
// }
entityMove(entity, moveSpeed);
return;
} else if(inputIsDown(INPUT_BIND_LEFT)) {
if(entity->dir != DIRECTION_WEST) {
entityTurn(entity, DIRECTION_WEST);
return;
}
entityMove(entity, moveSpeed);
return;
// entityMove(entity, moveSpeed);
// return;
// } else if(inputIsDown(INPUT_BIND_LEFT)) {
// if(entity->dir != DIRECTION_WEST) {
// entityTurn(entity, DIRECTION_WEST);
// return;
// }
// entityMove(entity, moveSpeed);
// return;
} else if(inputIsDown(INPUT_BIND_RIGHT)) {
if(entity->dir != DIRECTION_EAST) {
entityTurn(entity, DIRECTION_EAST);
return;
}
// } else if(inputIsDown(INPUT_BIND_RIGHT)) {
// if(entity->dir != DIRECTION_EAST) {
// entityTurn(entity, DIRECTION_EAST);
// return;
// }
entityMove(entity, moveSpeed);
return;
}
// entityMove(entity, moveSpeed);
// return;
// }
// Interact
if(inputPressed(INPUT_BIND_ACTION)) {
int8_t x, y;
directionGetCoordinates(entity->dir, &x, &y);
entity_t *ent = entityGetAt(entity->x + x, entity->y + y);
// if(inputPressed(INPUT_BIND_ACTION)) {
// int8_t x, y;
// directionGetCoordinates(entity->dir, &x, &y);
// entity_t *ent = entityGetAt(entity->x + x, entity->y + y);
// if(ent != NULL && ENTITY_CALLBACKS[ent->type].interact != NULL) {
// assertTrue(ent->type < ENTITY_TYPE_COUNT, "Entity type out of bounds");
// ENTITY_CALLBACKS[ent->type].interact(entity, ent);
// }
}
// // if(ent != NULL && ENTITY_CALLBACKS[ent->type].interact != NULL) {
// // assertTrue(ent->type < ENTITY_TYPE_COUNT, "Entity type out of bounds");
// // ENTITY_CALLBACKS[ent->type].interact(entity, ent);
// // }
// }
}