Partial entity inspector

This commit is contained in:
2024-01-07 13:49:13 +01:00
parent 5dbc5ba15e
commit 9c745d2857
9 changed files with 276 additions and 56 deletions

View File

@@ -66,6 +66,19 @@ void _bzArrayDelN(void *arr, i32 idx, i32 n) {
head->size -= n; head->size -= n;
} }
void _bzArrayDelSwap(void *arr, i32 idx) {
BzArrayHead *head = ARRAY_HEAD(arr);
BZ_ASSERT(idx >= 0 && idx < head->size);
i32 lastIdx = head->size - 1;
if (idx != lastIdx) {
bzMemMove((u8 *) arr + idx * head->stride,
(u8 *) arr + (lastIdx) * head->stride,
head->stride);
}
head->size--;
}
i32 _bzArrayPush(void *arr) { i32 _bzArrayPush(void *arr) {
BzArrayHead *head = ARRAY_HEAD(arr); BzArrayHead *head = ARRAY_HEAD(arr);

View File

@@ -15,6 +15,7 @@ void *_bzArrayEnsureCapacity(void **arr, i32 capacity);
i32 _bzArrayGet(void *arr, i32 idx); i32 _bzArrayGet(void *arr, i32 idx);
void _bzArrayDelN(void *arr, i32 idx, i32 n); void _bzArrayDelN(void *arr, i32 idx, i32 n);
void _bzArrayDelSwap(void *arr, i32 idx);
i32 _bzArrayPush(void *arr); i32 _bzArrayPush(void *arr);
i32 _bzArrayIns(void *arr, i32 idx); i32 _bzArrayIns(void *arr, i32 idx);
@@ -37,6 +38,7 @@ i32 _bzArrayPop(void *arr);
#define bzArrayGet(arr, idx) (arr)[_bzArrayGet(arr, idx)] #define bzArrayGet(arr, idx) (arr)[_bzArrayGet(arr, idx)]
#define bzArrayDel(arr, idx) _bzArrayDelN(arr, idx, 1) #define bzArrayDel(arr, idx) _bzArrayDelN(arr, idx, 1)
#define bzArrayDelN(arr, idx, n) _bzArrayDelN(arr, idx, n) #define bzArrayDelN(arr, idx, n) _bzArrayDelN(arr, idx, n)
#define bzArrayDelSwap(arr, idx) _bzArrayDelSwap(arr, idx)
#define bzArrayPush(arr, ...) \ #define bzArrayPush(arr, ...) \
do { \ do { \

View File

@@ -94,10 +94,8 @@ void igTagCheckbox(const char *label, ecs_world_t *ecs,
else else
ecs_remove_id(ecs, entity, tag); ecs_remove_id(ecs, entity, tag);
} }
void igResource(const char *label, ecs_world_t *ecs, void igResource(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) { ecs_entity_t entity, ecs_entity_t comp) {
if (!ecs_has_id(ecs, entity, comp)) return;
igSeparatorText(label);
Resource *res = ecs_get_mut_id(ecs, entity, comp); Resource *res = ecs_get_mut_id(ecs, entity, comp);
const char *resStrings[RES_COUNT]; const char *resStrings[RES_COUNT];
for (i32 i = 0; i < RES_COUNT; i++) { for (i32 i = 0; i < RES_COUNT; i++) {
@@ -108,13 +106,118 @@ void igResource(const char *label, ecs_world_t *ecs,
res->type = curType; res->type = curType;
igInputInt("Amount", &res->amount, 1, 10, 0); igInputInt("Amount", &res->amount, 1, 10, 0);
} }
void igVec2(const char *label, ecs_world_t *ecs, void igTilePosition(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) { ecs_entity_t entity, ecs_entity_t comp) {
if (!ecs_has_id(ecs, entity, comp)) return; TilePosition *tilePos = ecs_get_mut_id(ecs, entity, comp);
igSeparatorText(label); igInputInt("X", &tilePos->x, 1, 4, 0);
Vector2 *vec = ecs_get_mut_id(ecs, entity, comp); igInputInt("Y", &tilePos->y, 1, 4, 0);
igPushID_Str(label); }
void igTileSize(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
TileSize *tileSize = ecs_get_mut_id(ecs, entity, comp);
igInputInt("X", &tileSize->sizeX, 1, 1, 0);
igInputInt("Y", &tileSize->sizeY, 1, 1, 0);
}
void igOwner(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
Owner *owner = ecs_get_mut_id(ecs, entity, comp);
igInputInt("PlayerID", &owner->playerID, 0, 0, 0);
}
void igSpatialGridID(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
SpatialGridID *id = ecs_get_mut_id(ecs, entity, comp);
igText("SpatialID", *id);
}
void igVec2(Vector2 *vec) {
igInputFloat("X", &vec->x, 1.0f, 10.0f, "%.2f", 0); igInputFloat("X", &vec->x, 1.0f, 10.0f, "%.2f", 0);
igInputFloat("Y", &vec->y, 1.0f, 10.0f, "%.2f", 0); igInputFloat("Y", &vec->y, 1.0f, 10.0f, "%.2f", 0);
igPopID(); }
void igVec2Comp(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
Vector2 *vec = ecs_get_mut_id(ecs, entity, comp);
igVec2(vec);
}
void igFloat(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
f32 *f = ecs_get_mut_id(ecs, entity, comp);
igInputFloat("", f, 0.1f, 1.0f, "%.2f", 0);
}
void igPath(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
Path path = *(Path *) ecs_get_mut_id(ecs, entity, comp);
i32 idx = 0;
while (path.paths) {
for (int32_t i = path.curWaypoint; i < path.paths->numWaypoints; i++) {
igPushID_Int(idx);
igText("Waypoint %d:", idx);
igInputFloat("X", &path.paths->waypoints[i].x, 1, 16, "%.2f", 0);
igInputFloat("Y", &path.paths->waypoints[i].y, 1, 16, "%.2f", 0);
igPopID();
idx++;
}
path.paths = path.paths->next;
path.curWaypoint = 0;
}
}
void igRect(Rectangle *rect) {
igInputFloat("X", &rect->x, 1, 16, "%.2f", 0);
igInputFloat("Y", &rect->y, 1, 16, "%.2f", 0);
igInputFloat("Width", &rect->width, 1, 16, "%.2f", 0);
igInputFloat("Height", &rect->height, 1, 16, "%.2f", 0);
}
void igTextureRegion(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
TextureRegion *tex = ecs_get_mut_id(ecs, entity, comp);
igText("Texture: %d", tex->texture.id);
igRect(&tex->rec);
bool flipX = tex->flipX;
bool flipY = tex->flipY;
igCheckbox("flipX", &flipX);
igCheckbox("flipY", &flipY);
tex->flipX = flipX;
tex->flipY = flipY;
}
void igAnimation(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
//Animation *anim = ecs_get_mut_id(ecs, entity, comp);
}
void igEasing(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
Easing *easing = ecs_get_mut_id(ecs, entity, comp);
igText("Component: %d, offset: %d", easing->compID, easing->offset);
igText("x = %.2f + %.2f * (%.2f + (%.2f * %.2f) + %.2f) + %.2f",
easing->start, easing->target, easing->easeStart, easing->easeTarget,
easing->x, easing->easeOffset, easing->offset);
}
void igArms(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
}
void igArm(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
}
void igUnitAction(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
}
void igUnitAI(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
}
void igWorker(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
}
void igUnit(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
} }

View File

@@ -46,7 +46,7 @@ typedef struct TileSize {
extern ECS_COMPONENT_DECLARE(TileSize); extern ECS_COMPONENT_DECLARE(TileSize);
typedef struct Owner { typedef struct Owner {
BuildingType playerID; int32_t playerID;
} Owner; } Owner;
extern ECS_COMPONENT_DECLARE(Owner); extern ECS_COMPONENT_DECLARE(Owner);
@@ -133,12 +133,6 @@ typedef struct Easing {
} Easing; } Easing;
extern ECS_COMPONENT_DECLARE(Easing); extern ECS_COMPONENT_DECLARE(Easing);
typedef struct EntityArms {
ecs_entity_t left;
ecs_entity_t right;
} EntityArms;
//extern ECS_COMPONENT_DECLARE(EntityArms);
/********************************************************** /**********************************************************
* Event components * Event components
*********************************************************/ *********************************************************/
@@ -153,8 +147,6 @@ typedef struct EntityArms {
* Gameplay components * Gameplay components
*********************************************************/ *********************************************************/
typedef Vector2 ItemOffset;
typedef struct WeaponMelee { typedef struct WeaponMelee {
ecs_entity_t weapon; ecs_entity_t weapon;
f32 reach; f32 reach;
@@ -219,8 +211,47 @@ void initComponentIDs(ecs_world_t *ecs);
void igTagCheckbox(const char *label, ecs_world_t *ecs, void igTagCheckbox(const char *label, ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t tag); ecs_entity_t entity, ecs_entity_t tag);
void igResource(const char *label, ecs_world_t *ecs,
typedef void(*ImGuiCompFn)(ecs_world_t *ecs, ecs_entity_t entity, ecs_entity_t comp);
void igResource(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp); ecs_entity_t entity, ecs_entity_t comp);
void igVec2(const char *label, ecs_world_t *ecs, void igTilePosition(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igTileSize(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igOwner(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igSpatialGridID(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igVec2Comp(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igFloat(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp); ecs_entity_t entity, ecs_entity_t comp);
void igPath(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igTextureRegion(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igAnimation(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igEasing(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igArms(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igArm(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igUnitAction(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igUnitAI(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igWorker(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
void igUnit(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp);
#endif //PIXELDEFENSE_COMPONENTS_H #endif //PIXELDEFENSE_COMPONENTS_H

View File

@@ -42,11 +42,12 @@ typedef struct Game {
BzObjectPool *actions; BzObjectPool *actions;
} pools; } pools;
struct { struct {
bool path; bool drawPath;
bool entityColliders; bool drawEntityColliders;
bool mapColliders; bool drawMapColliders;
bool spatialGrid; bool drawSpatialGrid;
} debugDraw; ecs_entity_t *inspecting;
} debug;
f32 elapsed; f32 elapsed;
ecs_query_t *drawQuery; ecs_query_t *drawQuery;

View File

@@ -233,9 +233,10 @@ bool init(void *userData) {
loadMap(game, "assets/maps/main_menu_01.tmj"); loadMap(game, "assets/maps/main_menu_01.tmj");
game->debugDraw.mapColliders = true; game->debug.drawMapColliders = true;
game->debugDraw.spatialGrid = true; game->debug.drawSpatialGrid = true;
game->debugDraw.path = true; game->debug.drawPath = true;
game->debug.inspecting = bzArrayCreate(ecs_entity_t, 10);
return true; return true;
} }
@@ -263,6 +264,8 @@ void deinit(void *userData) {
input = &inputCopy; input = &inputCopy;
sounds = &soundsCopy; sounds = &soundsCopy;
bzArrayDestroy(game->debug.inspecting);
bzTilesetDestroy(&game->tileset); bzTilesetDestroy(&game->tileset);
bzStackAllocDestroy(&game->stackAlloc); bzStackAllocDestroy(&game->stackAlloc);
@@ -396,11 +399,11 @@ static void renderGame(Game *game, float dt) {
} }
ecs_progress(ECS, dt); ecs_progress(ECS, dt);
ecs_enable(ECS, renderDebugPathSystem, game->debugDraw.path); ecs_enable(ECS, renderDebugPathSystem, game->debug.drawPath);
ecs_enable(ECS, renderCollidersSystem, game->debugDraw.entityColliders); ecs_enable(ECS, renderCollidersSystem, game->debug.drawEntityColliders);
if (game->debugDraw.mapColliders) if (game->debug.drawMapColliders)
bzTileMapDrawCollisions(&game->map); bzTileMapDrawCollisions(&game->map);
if (game->debugDraw.spatialGrid) if (game->debug.drawSpatialGrid)
bzSpatialGridDrawDebugGrid(game->entityGrid); bzSpatialGridDrawDebugGrid(game->entityGrid);
drawPlayerInputUI(); drawPlayerInputUI();
@@ -612,13 +615,32 @@ void render(float dt, void *userData) {
} }
static void igEntity(ecs_entity_t entity) { void igInspectComp(const char *label, ecs_entity_t entity, ecs_entity_t comp, ImGuiCompFn fn) {
igPushID_Int(comp);
igSeparatorText(label);
bool isAttached = ecs_has_id(ECS, entity, comp);
igCheckbox("Attached", &isAttached);
if (isAttached)
fn(ECS, entity, comp);
if (isAttached != ecs_has_id(ECS, entity, comp)) {
if (!isAttached) {
ecs_remove_id(ECS, entity, comp);
} else {
ecs_set_id(ECS, entity, comp, 0, NULL);
}
}
igPopID();
}
void igInspectWindow(ecs_entity_t entity, bool *open) {
igSetNextWindowSize((ImVec2) {300, 440}, ImGuiCond_FirstUseEver);
char buf[64]; char buf[64];
snprintf(buf, sizeof(buf), "Entity: %ld", entity); snprintf(buf, sizeof(buf), "Entity: %ld", entity);
if (igTreeNode_Str(buf)) { if (igBegin(buf, open, 0)) {
igSeparatorText("Tags"); if (igCollapsingHeader_TreeNodeFlags("Tags", 0)) {
{ //igTagCheckbox("GameEntity", ECS, entity, GameEntity);
igTagCheckbox("GameEntity", ECS, entity, GameEntity);
igTagCheckbox("Selectable", ECS, entity, Selectable); igTagCheckbox("Selectable", ECS, entity, Selectable);
igTagCheckbox("Selected", ECS, entity, Selected); igTagCheckbox("Selected", ECS, entity, Selected);
igTagCheckbox("Storage", ECS, entity, Storage); igTagCheckbox("Storage", ECS, entity, Storage);
@@ -626,17 +648,30 @@ static void igEntity(ecs_entity_t entity) {
igTagCheckbox("Workable", ECS, entity, Workable); igTagCheckbox("Workable", ECS, entity, Workable);
igTagCheckbox("Attackable", ECS, entity, Attackable); igTagCheckbox("Attackable", ECS, entity, Attackable);
} }
igResource("Resource", ECS, entity, ecs_id(Resource)); igInspectComp("Resource", entity, ecs_id(Resource), igResource);
igVec2("Position", ECS, entity, ecs_id(Position)); igInspectComp("TilePosition", entity, ecs_id(TilePosition), igTilePosition);
igVec2("Size", ECS, entity, ecs_id(Size)); igInspectComp("TileSize", entity, ecs_id(TileSize), igTileSize);
igVec2("Velocity", ECS, entity, ecs_id(Velocity)); igInspectComp("Owner", entity, ecs_id(Owner), igOwner);
igVec2("Steering", ECS, entity, ecs_id(Steering)); igInspectComp("SpatialGridID", entity, ecs_id(SpatialGridID), igSpatialGridID);
igVec2("TargetPosition", ECS, entity, ecs_id(TargetPosition)); igInspectComp("Position", entity, ecs_id(Position), igVec2Comp);
igInspectComp("Size", entity, ecs_id(Size), igVec2Comp);
igTreePop(); igInspectComp("Velocity", entity, ecs_id(Velocity), igVec2Comp);
igInspectComp("TargetPosition", entity, ecs_id(TargetPosition), igVec2Comp);
igInspectComp("Steering", entity, ecs_id(Steering), igVec2Comp);
igInspectComp("Rotation", entity, ecs_id(Rotation), igFloat);
igInspectComp("Path", entity, ecs_id(Path), igPath);
igInspectComp("TextureRegion", entity, ecs_id(TextureRegion), igTextureRegion);
igInspectComp("Animation", entity, ecs_id(Animation), igAnimation);
igInspectComp("Easing", entity, ecs_id(Easing), igEasing);
igInspectComp("Arms", entity, ecs_id(Arms), igArms);
igInspectComp("Arm", entity, ecs_id(Arm), igArm);
igInspectComp("UnitAction", entity, ecs_id(UnitAction), igUnitAction);
igInspectComp("UnitAI", entity, ecs_id(UnitAI), igUnitAI);
igInspectComp("Worker", entity, ecs_id(Worker), igWorker);
igInspectComp("Unit", entity, ecs_id(Unit), igUnit);
} }
igEnd();
} }
void imguiRender(float dt, void *userData) { void imguiRender(float dt, void *userData) {
BZ_UNUSED(userData); BZ_UNUSED(userData);
Game *game = ecs_singleton_get_mut(ECS, Game); Game *game = ecs_singleton_get_mut(ECS, Game);
@@ -676,7 +711,7 @@ void imguiRender(float dt, void *userData) {
while (ecs_iter_next(&it)) { while (ecs_iter_next(&it)) {
for (i32 i = 0; i < it.count; i++) { for (i32 i = 0; i < it.count; i++) {
ecs_entity_t entity = it.entities[i]; ecs_entity_t entity = it.entities[i];
igEntity(entity); igText("Entity: %ld", entity);
} }
} }
ecs_defer_end(ECS); ecs_defer_end(ECS);
@@ -705,10 +740,10 @@ void imguiRender(float dt, void *userData) {
} }
if (igCollapsingHeader_TreeNodeFlags("DebugDraw", 0)) { if (igCollapsingHeader_TreeNodeFlags("DebugDraw", 0)) {
igCheckbox("map colliders", &game->debugDraw.mapColliders); igCheckbox("map colliders", &game->debug.drawMapColliders);
igCheckbox("entity colliders", &game->debugDraw.entityColliders); igCheckbox("entity colliders", &game->debug.drawEntityColliders);
igCheckbox("spatial grid", &game->debugDraw.spatialGrid); igCheckbox("spatial grid", &game->debug.drawSpatialGrid);
igCheckbox("path", &game->debugDraw.path); igCheckbox("path", &game->debug.drawPath);
} }
if (igCollapsingHeader_TreeNodeFlags("Entities", 0)) { if (igCollapsingHeader_TreeNodeFlags("Entities", 0)) {
@@ -718,5 +753,14 @@ void imguiRender(float dt, void *userData) {
bzGameExit(); bzGameExit();
} }
igEnd(); igEnd();
i32 inspectLen = bzArraySize(game->debug.inspecting);
for (i32 i = inspectLen - 1; i >= 0; i--) {
bool open = true;
igInspectWindow(game->debug.inspecting[i], &open);
if (!open) {
bzArrayDelSwap(game->debug.inspecting, i);
}
}
} }

View File

@@ -189,7 +189,7 @@ void renderOrientationDirection(ecs_iter_t *it) {
Vector2 v = {6.0f, 0.0f}; Vector2 v = {6.0f, 0.0f};
v = Vector2Rotate(v, orientation[i]); v = Vector2Rotate(v, orientation[i]);
v = Vector2Add(v, pos[i]); v = Vector2Add(v, pos[i]);
DrawLine(pos->x, pos->y, v.x, v.y, RED); DrawLine(pos[i].x, pos[i].y, v.x, v.y, RED);
} }
} }

View File

@@ -64,6 +64,24 @@ void inputPrimaryAction(Game *game, InputState *input) {
input->state = INPUT_SELECTED_BUILDING; input->state = INPUT_SELECTED_BUILDING;
} }
selectedCount = ecs_query_entity_count(input->queries.selected); selectedCount = ecs_query_entity_count(input->queries.selected);
if (IsKeyDown(KEY_LEFT_ALT) && IsKeyDown(KEY_LEFT_SHIFT)) {
ecs_iter_t it = ecs_query_iter(ECS, input->queries.selected);
while (ecs_iter_next(&it)) {
for (i32 i = 0; i < it.count; i++) {
ecs_entity_t entity = it.entities[i];
bool alreadyInspecting = false;
for (i32 j = 0; j < bzArraySize(game->debug.inspecting); j++) {
if (game->debug.inspecting[j] == entity) {
alreadyInspecting = true;
break;
}
}
if (!alreadyInspecting)
bzArrayPush(game->debug.inspecting, entity);
}
}
}
} }
if (selectedCount == 0) if (selectedCount == 0)

View File

@@ -29,10 +29,17 @@ ECS_MOVE(Path, dst, src, {
}) })
ECS_DTOR(Arms, arms, { ECS_DTOR(Arms, arms, {
if (arms->primary) if (arms->primary) {
ecs_delete(ECS, arms->primary); ecs_delete(ECS, arms->primary);
if (arms->secondary) arms->primary = 0;
}
if (arms->secondary) {
ecs_delete(ECS, arms->secondary); ecs_delete(ECS, arms->secondary);
arms->secondary = 0;
}
})
ECS_MOVE(Arms, dst, src, {
*dst = *src;
}); });
void setupSystems() { void setupSystems() {
@@ -45,7 +52,8 @@ void setupSystems() {
.move_dtor = ecs_move(Path) .move_dtor = ecs_move(Path)
}); });
ecs_set_hooks(ECS, Arms, { ecs_set_hooks(ECS, Arms, {
.dtor = ecs_dtor(Arms) .dtor = ecs_dtor(Arms),
.move_dtor = ecs_move(Arms)
}); });
ECS_OBSERVER(ECS, entityPathRemove, EcsOnRemove, Path); ECS_OBSERVER(ECS, entityPathRemove, EcsOnRemove, Path);