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;
}
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) {
BzArrayHead *head = ARRAY_HEAD(arr);

View File

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

View File

@@ -94,10 +94,8 @@ void igTagCheckbox(const char *label, ecs_world_t *ecs,
else
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) {
if (!ecs_has_id(ecs, entity, comp)) return;
igSeparatorText(label);
Resource *res = ecs_get_mut_id(ecs, entity, comp);
const char *resStrings[RES_COUNT];
for (i32 i = 0; i < RES_COUNT; i++) {
@@ -108,13 +106,118 @@ void igResource(const char *label, ecs_world_t *ecs,
res->type = curType;
igInputInt("Amount", &res->amount, 1, 10, 0);
}
void igVec2(const char *label, ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
if (!ecs_has_id(ecs, entity, comp)) return;
igSeparatorText(label);
Vector2 *vec = ecs_get_mut_id(ecs, entity, comp);
igPushID_Str(label);
void igTilePosition(ecs_world_t *ecs,
ecs_entity_t entity, ecs_entity_t comp) {
TilePosition *tilePos = ecs_get_mut_id(ecs, entity, comp);
igInputInt("X", &tilePos->x, 1, 4, 0);
igInputInt("Y", &tilePos->y, 1, 4, 0);
}
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("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);
typedef struct Owner {
BuildingType playerID;
int32_t playerID;
} Owner;
extern ECS_COMPONENT_DECLARE(Owner);
@@ -133,12 +133,6 @@ typedef struct Easing {
} 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
*********************************************************/
@@ -153,8 +147,6 @@ typedef struct EntityArms {
* Gameplay components
*********************************************************/
typedef Vector2 ItemOffset;
typedef struct WeaponMelee {
ecs_entity_t weapon;
f32 reach;
@@ -219,8 +211,47 @@ void initComponentIDs(ecs_world_t *ecs);
void igTagCheckbox(const char *label, ecs_world_t *ecs,
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);
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);
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

View File

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

View File

@@ -233,9 +233,10 @@ bool init(void *userData) {
loadMap(game, "assets/maps/main_menu_01.tmj");
game->debugDraw.mapColliders = true;
game->debugDraw.spatialGrid = true;
game->debugDraw.path = true;
game->debug.drawMapColliders = true;
game->debug.drawSpatialGrid = true;
game->debug.drawPath = true;
game->debug.inspecting = bzArrayCreate(ecs_entity_t, 10);
return true;
}
@@ -263,6 +264,8 @@ void deinit(void *userData) {
input = &inputCopy;
sounds = &soundsCopy;
bzArrayDestroy(game->debug.inspecting);
bzTilesetDestroy(&game->tileset);
bzStackAllocDestroy(&game->stackAlloc);
@@ -396,11 +399,11 @@ static void renderGame(Game *game, float dt) {
}
ecs_progress(ECS, dt);
ecs_enable(ECS, renderDebugPathSystem, game->debugDraw.path);
ecs_enable(ECS, renderCollidersSystem, game->debugDraw.entityColliders);
if (game->debugDraw.mapColliders)
ecs_enable(ECS, renderDebugPathSystem, game->debug.drawPath);
ecs_enable(ECS, renderCollidersSystem, game->debug.drawEntityColliders);
if (game->debug.drawMapColliders)
bzTileMapDrawCollisions(&game->map);
if (game->debugDraw.spatialGrid)
if (game->debug.drawSpatialGrid)
bzSpatialGridDrawDebugGrid(game->entityGrid);
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];
snprintf(buf, sizeof(buf), "Entity: %ld", entity);
if (igTreeNode_Str(buf)) {
igSeparatorText("Tags");
{
igTagCheckbox("GameEntity", ECS, entity, GameEntity);
if (igBegin(buf, open, 0)) {
if (igCollapsingHeader_TreeNodeFlags("Tags", 0)) {
//igTagCheckbox("GameEntity", ECS, entity, GameEntity);
igTagCheckbox("Selectable", ECS, entity, Selectable);
igTagCheckbox("Selected", ECS, entity, Selected);
igTagCheckbox("Storage", ECS, entity, Storage);
@@ -626,17 +648,30 @@ static void igEntity(ecs_entity_t entity) {
igTagCheckbox("Workable", ECS, entity, Workable);
igTagCheckbox("Attackable", ECS, entity, Attackable);
}
igResource("Resource", ECS, entity, ecs_id(Resource));
igVec2("Position", ECS, entity, ecs_id(Position));
igVec2("Size", ECS, entity, ecs_id(Size));
igVec2("Velocity", ECS, entity, ecs_id(Velocity));
igVec2("Steering", ECS, entity, ecs_id(Steering));
igVec2("TargetPosition", ECS, entity, ecs_id(TargetPosition));
igTreePop();
igInspectComp("Resource", entity, ecs_id(Resource), igResource);
igInspectComp("TilePosition", entity, ecs_id(TilePosition), igTilePosition);
igInspectComp("TileSize", entity, ecs_id(TileSize), igTileSize);
igInspectComp("Owner", entity, ecs_id(Owner), igOwner);
igInspectComp("SpatialGridID", entity, ecs_id(SpatialGridID), igSpatialGridID);
igInspectComp("Position", entity, ecs_id(Position), igVec2Comp);
igInspectComp("Size", entity, ecs_id(Size), igVec2Comp);
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) {
BZ_UNUSED(userData);
Game *game = ecs_singleton_get_mut(ECS, Game);
@@ -676,7 +711,7 @@ void imguiRender(float dt, void *userData) {
while (ecs_iter_next(&it)) {
for (i32 i = 0; i < it.count; i++) {
ecs_entity_t entity = it.entities[i];
igEntity(entity);
igText("Entity: %ld", entity);
}
}
ecs_defer_end(ECS);
@@ -705,10 +740,10 @@ void imguiRender(float dt, void *userData) {
}
if (igCollapsingHeader_TreeNodeFlags("DebugDraw", 0)) {
igCheckbox("map colliders", &game->debugDraw.mapColliders);
igCheckbox("entity colliders", &game->debugDraw.entityColliders);
igCheckbox("spatial grid", &game->debugDraw.spatialGrid);
igCheckbox("path", &game->debugDraw.path);
igCheckbox("map colliders", &game->debug.drawMapColliders);
igCheckbox("entity colliders", &game->debug.drawEntityColliders);
igCheckbox("spatial grid", &game->debug.drawSpatialGrid);
igCheckbox("path", &game->debug.drawPath);
}
if (igCollapsingHeader_TreeNodeFlags("Entities", 0)) {
@@ -718,5 +753,14 @@ void imguiRender(float dt, void *userData) {
bzGameExit();
}
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};
v = Vector2Rotate(v, orientation[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;
}
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)

View File

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