Add cursor support

This commit is contained in:
2023-12-07 19:24:29 +01:00
parent f27718cdbf
commit b410867902
4 changed files with 75 additions and 41 deletions

View File

@@ -17,7 +17,7 @@ typedef enum InputType {
#define MOUSE_BUTTON_COUNT (MOUSE_BUTTON_BACK + 1)
#define CLICK_LIMIT 0.2f
#define CLICK_LIMIT 0.12f
#define BUTTON_COUNT (MOUSE_BUTTON_BACK + 1)
typedef struct InputMapping {
@@ -41,6 +41,11 @@ typedef struct InputState {
Vector2 mouse;
Vector2 mouseWorld;
f32 mouseDownElapsed[BUTTON_COUNT];
enum {
CURSOR_NONE,
CURSOR_COLLECT_WOOD,
} cursor;
// INPUT_BUILDING
int building;
bool buildingCanPlace;
@@ -49,6 +54,11 @@ typedef struct InputState {
// SELECTED_UNITS
Rectangle pickArea;
// SELECTED_OBJECT
// SELECTED_BUILDING
// Other
struct {
/* Selected units
* 1: Position
@@ -58,8 +68,6 @@ typedef struct InputState {
ecs_query_t *selected;
//ecs_query_t *selectedBuilding;
} queries;
// SELECTED_OBJECT
// SELECTED_BUILDING
} InputState;
static InputMapping inputDefaultMapping() {

View File

@@ -224,7 +224,7 @@ void render(float dt, void *userData) {
bzTileMapDraw(&game->map);
drawPlayerInputUI();
drawPlayerInputUIGround();
ecs_progress(ECS, dt);
ecs_enable(ECS, renderDebugPathSystem, game->debugDraw.path);
@@ -234,6 +234,8 @@ void render(float dt, void *userData) {
if (game->debugDraw.spatialGrid)
bzSpatialGridDrawDebugGrid(game->entityGrid);
drawPlayerInputUI();
EndMode2D();
}

View File

@@ -114,7 +114,14 @@ void renderDebugPath(ecs_iter_t *it);
void updatePlayerInput();
/*
* Task:
* Task (rendering above ground):
* 0: Game (singleton)
* 0: InputState (singleton)
*/
void drawPlayerInputUIGround();
/*
* Task (rendering on top):
* 0: Game (singleton)
* 0: InputState (singleton)
*/

View File

@@ -20,6 +20,12 @@ static void iterRemovePaths(ecs_entity_t entity, Position *pos, Size *size);
void placeUnits(i32 numUnits, f32 unitSpacing, Vector2 start, Vector2 end, BzTileMap *map, Vector2 **outPlaces);
void resetInputState(InputState *input) {
input->cursor = CURSOR_NONE;
input->state = INPUT_NONE;
input->building = 0;
}
void inputPrimaryAction(Game *game, InputState *input) {
const MouseButton primaryBtn = input->mapping.primaryBtn;
if (isInputBtnDragged(input, primaryBtn)) {
@@ -40,22 +46,26 @@ void inputPrimaryAction(Game *game, InputState *input) {
}
i32 selectedCount = ecs_query_entity_count(input->queries.selected);
if (isInputBtnJustDragged(input, primaryBtn) && selectedCount > 0) {
resetInputState(input);
input->state = INPUT_SELECTED_UNITS;
} else if (isInputBtnJustUp(input, primaryBtn)) {
if (pickEntity(game->entityGrid, input->mouseDownWorld, Unit)) {
resetInputState(input);
input->state = INPUT_SELECTED_UNITS;
} else if (pickEntity(game->entityGrid, input->mouseDownWorld, Harvestable)) {
resetInputState(input);
input->state = INPUT_SELECTED_OBJECT;
} else if (pickEntity(game->entityGrid, input->mouseDownWorld, Buildable)) {
resetInputState(input);
input->state = INPUT_SELECTED_BUILDING;
}
selectedCount = ecs_query_entity_count(input->queries.selected);
}
if (selectedCount == 0)
input->state = INPUT_NONE;
resetInputState(input);
}
void inputUnitAction(Game *game, const InputState *input) {
void inputUnitAction(Game *game, InputState *input) {
ecs_query_t *query = input->queries.selected;
BzTileMap *map = &game->map;
const i32 numUnits = ecs_query_entity_count(query);
@@ -63,6 +73,14 @@ void inputUnitAction(Game *game, const InputState *input) {
const MouseButton actionBtn = input->mapping.secondaryBtn;
input->cursor = CURSOR_NONE;
if (queryEntity(game->entityGrid, input->mouseWorld, Harvestable)) {
input->cursor = CURSOR_COLLECT_WOOD;
if (isInputBtnJustUp(input, actionBtn)) {
bzLogInfo("Chop wood!");
}
}
if (isInputBtnJustDown(input, actionBtn)) {
// Note: We mustn't use ecs ecs_remove_all since this will also
// remove ongoing paths that are not part of this query.
@@ -120,8 +138,7 @@ void updatePlayerInput() {
if (IsKeyPressed(input->mapping.backBtn)) {
ecs_remove_all(ECS, Selected);
input->state = INPUT_NONE;
input->building = 0;
resetInputState(input);
return;
}
@@ -241,29 +258,21 @@ void updatePlayerInput() {
}
}
void drawPlayerInputUI() {
Game *game = ecs_singleton_get_mut(ECS, Game);
InputState *input = ecs_singleton_get_mut(ECS, InputState);
BzTileMap *map = &game->map;
void drawPlayerInputUIGround() {
const Game *game = ecs_singleton_get_mut(ECS, Game);
const InputState *input = ecs_singleton_get_mut(ECS, InputState);
const MouseButton primaryBtn = input->mapping.primaryBtn;
const MouseButton secondaryBtn = input->mapping.secondaryBtn;
i32 selectedUnitCount = ecs_count_id(ECS, Selected);
const i32 selectedUnitCount = ecs_count_id(ECS, Selected);
switch (input->state) {
case INPUT_NONE:
if (isInputBtnDragged(input, primaryBtn)) {
Rectangle area = input->pickArea;
DrawRectangleLines(area.x, area.y, area.width, area.height, RED);
}
break;
case INPUT_BUILDING: {
Color placeColor = input->buildingCanPlace ?
const Color placeColor = input->buildingCanPlace ?
(Color) {0, 255, 0, 200} :
(Color) {255, 0, 0, 200};
BzTile width = game->map.tileWidth;
BzTile height = game->map.tileHeight;
const BzTile width = game->map.tileWidth;
const BzTile height = game->map.tileHeight;
DrawRectangleLines(input->buildingPos.x * width,
input->buildingPos.y * height,
input->buildingSize.sizeX * width,
@@ -287,25 +296,9 @@ void drawPlayerInputUI() {
}
}
*/
Rectangle area = {input->mouseWorld.x, input->mouseWorld.y, 1, 1};
DrawCircle(area.x, area.y, 4.0f, BLUE);
BzSpatialGridIter it = bzSpatialGridIter(game->entityGrid, area.x, area.y, area.width, area.height);
while (bzSpatialGridQueryNext(&it)) {
ecs_entity_t entity = 0;
BzSpatialGrid *grid = game->entityGrid;
Vector2 point = input->mouseWorld;
if ((entity = queryEntity(grid, point, Harvestable))) {
DrawText("Collect resources", point.x, point.y, 10.0f, RED);
}
}
break;
}
default: break;
}
ecs_iter_t it = ecs_query_iter(ECS, input->queries.selected);
rlSetLineWidth(2.0f);
@@ -323,6 +316,30 @@ void drawPlayerInputUI() {
}
void drawPlayerInputUI() {
const Game *game = ecs_singleton_get_mut(ECS, Game);
const InputState *input = ecs_singleton_get_mut(ECS, InputState);
const MouseButton primaryBtn = input->mapping.primaryBtn;
if (isInputBtnDragged(input, primaryBtn)) {
const Rectangle area = input->pickArea;
DrawRectangleLines(area.x, area.y, area.width, area.height, RED);
}
switch (input->cursor) {
case CURSOR_COLLECT_WOOD: {
const Vector2 point = input->mouseWorld;
DrawCircle(point.x, point.y, 2.0f, RED);
DrawText("Collect wood", point.x, point.y, 10.0f, RED);
break;
}
default: break;
}
}
Rectangle calculateEntityBounds(Position pos, Size size) {
return (Rectangle) {
pos.x - size.x * 0.5f,