diff --git a/src/console/console.c b/src/console/console.c index 949463cb2..b225a0ac3 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -359,6 +359,7 @@ void console_tick(game_state *gs) { con->y_pos = 0; } } + console_release_keypress(); } void console_add_cmd(const char *name, command_func func, const char *doc) { @@ -372,6 +373,20 @@ void console_remove_cmd(const char *name) { hashmap_del_str(&con->cmds, name); } +void console_release_keypress(void) { + if(con->keypress_time > 0) { + con->keypress_time--; + return; + } + if(con->keypress_scancode != SDL_SCANCODE_UNKNOWN) { + Uint8 *state = (Uint8 *)SDL_GetKeyboardState(NULL); + state[con->keypress_scancode] = 0; + + con->keypress_time = 0; + con->keypress_scancode = SDL_SCANCODE_UNKNOWN; + } +} + bool console_window_is_open(void) { return con->is_open; } diff --git a/src/console/console.h b/src/console/console.h index aab40c397..1acabcc4b 100644 --- a/src/console/console.h +++ b/src/console/console.h @@ -16,6 +16,9 @@ void console_tick(game_state *gs); void console_add_cmd(const char *name, command_func func, const char *doc); void console_remove_cmd(const char *name); +// Potentially release a key that has been pressed by the keypress command. +void console_release_keypress(void); + void console_output_add(const char *text); void console_output_addline(const char *text); diff --git a/src/console/console_cmd.c b/src/console/console_cmd.c index bb17b0285..55235f040 100644 --- a/src/console/console_cmd.c +++ b/src/console/console_cmd.c @@ -3,6 +3,8 @@ #include "console/console_type.h" #include "formats/error.h" #include "formats/rec_assertion.h" +#include "game/gui/component.h" +#include "game/gui/sizer.h" #include "game/scenes/arena.h" #include "game/scenes/mechlab.h" #include "resources/ids.h" @@ -273,6 +275,41 @@ int console_cmd_god(game_state *gs, int argc, char **argv) { return 0; } +int console_find_by_text(game_state *gs, int argc, char **argv) { + scene *sc = game_state_get_scene(gs); + if(sc->id != SCENE_MECHLAB) { + log_debug("Wrong scene for find_by_text"); + return 1; + } + gui_frame *frame = mechlab_get_frame(game_state_get_scene(gs)); + // component *c = component_find_text(gui_frame_get_root(frame), "NEW"); + component *c = gui_frame_find_text(frame, "NEW"); + if(c == NULL) { + log_debug("Could not find the component"); + return 1; + } + component_action(c, ACT_PUNCH); + + return 0; +} + +int console_keypress(game_state *gs, int argc, char **argv) { + SDL_Event sdlevent; + memset(&sdlevent, 0, sizeof(sdlevent)); + sdlevent.type = SDL_KEYDOWN; + sdlevent.key.keysym.sym = SDLK_DOWN; + sdlevent.key.keysym.scancode = SDL_SCANCODE_DOWN; + SDL_PushEvent(&sdlevent); + + Uint8 *state = (Uint8 *)SDL_GetKeyboardState(NULL); + state[SDL_SCANCODE_DOWN] = 1; + + con->keypress_time = 20; + con->keypress_scancode = SDL_SCANCODE_DOWN; + + return 0; +} + int console_kreissack(game_state *gs, int argc, char **argv) { game_player *p1 = game_state_get_player(gs, 0); p1->sp_wins = (2046 ^ (2 << p1->pilot->pilot_id)); @@ -472,6 +509,8 @@ void console_init_cmd(void) { console_add_cmd("stun", &console_cmd_stun, "Stun the other player"); console_add_cmd("rein", &console_cmd_rein, "R-E-I-N!"); console_add_cmd("god", &console_cmd_god, "Enable god mode"); + console_add_cmd("keypress", &console_keypress, "Push a keypress into the input queue"); + console_add_cmd("find_by_text", &console_find_by_text, "Move the hand to this button"); console_add_cmd("kreissack", &console_kreissack, "Fight Kreissack"); console_add_cmd("ez-destruct", &console_cmd_ez_destruct, "Punch = destruction, kick = scrap"); console_add_cmd("warp", &console_toggle_warp, "Toggle warp speed"); diff --git a/src/console/console_type.h b/src/console/console_type.h index 38c814756..ff0e9872c 100644 --- a/src/console/console_type.h +++ b/src/console/console_type.h @@ -24,6 +24,8 @@ typedef struct console { int y_pos; hashmap cmds; // string -> command text *text; + int keypress_time; + int keypress_scancode; } console; typedef struct command { diff --git a/src/game/gui/component.c b/src/game/gui/component.c index 25f7e0549..f26bec51d 100644 --- a/src/game/gui/component.c +++ b/src/game/gui/component.c @@ -116,6 +116,16 @@ component *component_find(component *c, int id) { return c->find(c, id); } +component *component_find_text(component *c, const char *text) { + log_debug("component_find_text"); + if(c->find_text != NULL) { + log_debug("component_find_text: callback found"); + return c->find_text(c, text); + } + log_debug("component_find_text: NULL"); + return NULL; +} + void component_set_obj(component *c, void *obj) { c->obj = obj; } @@ -162,6 +172,10 @@ void component_set_find_cb(component *c, component_find_cb cb) { c->find = cb; } +void component_set_find_text_cb(component *c, component_find_text_cb cb) { + c->find_text = cb; +} + void component_set_init_cb(component *c, component_init_cb cb) { c->init = cb; } diff --git a/src/game/gui/component.h b/src/game/gui/component.h index a8924db9a..0d6c99ab2 100644 --- a/src/game/gui/component.h +++ b/src/game/gui/component.h @@ -25,6 +25,7 @@ typedef void (*component_tick_cb)(component *c); typedef void (*component_free_cb)(component *c); typedef void (*component_init_cb)(component *c, const gui_theme *theme); typedef component *(*component_find_cb)(component *c, int id); +typedef component *(*component_find_text_cb)(component *c, const char *text); /*! \brief Basic GUI object * @@ -70,8 +71,9 @@ struct component { component_tick_cb tick; ///< Tick function callback. This is called periodically. component_free_cb free; ///< Free function callback. Any component callbacks should be done here. component_find_cb find; ///< Should only be set by widget and sizer. Used to look up widgets by ID. - component_init_cb init; ///< Initialization function callback. This is called right before layout function. This - ///< should be used to prerender elements, decide size hints, etc. + component_find_text_cb find_text; ///< ... + component_init_cb init; ///< Initialization function callback. This is called right before layout function. This + ///< should be used to prerender elements, decide size hints, etc. component *parent; ///< Parent component. For widgets, usually a sizer. NULL for root component. }; @@ -106,8 +108,9 @@ void component_set_help_text(component *c, const char *text); void component_set_theme(component *c, const gui_theme *theme); const gui_theme *component_get_theme(component *c); -// ID lookup stuff +// lookup stuff component *component_find(component *c, int id); +component *component_find_text(component *c, const char *text); // Basic component callbacks void component_set_obj(component *c, void *obj); @@ -121,5 +124,6 @@ void component_set_init_cb(component *c, component_init_cb cb); void component_set_tick_cb(component *c, component_tick_cb cb); void component_set_free_cb(component *c, component_free_cb cb); void component_set_find_cb(component *c, component_find_cb cb); +void component_set_find_text_cb(component *c, component_find_text_cb cb); #endif // COMPONENT_H diff --git a/src/game/gui/gui_frame.c b/src/game/gui/gui_frame.c index 1f725f8f3..aa05b2982 100644 --- a/src/game/gui/gui_frame.c +++ b/src/game/gui/gui_frame.c @@ -1,5 +1,6 @@ #include "game/gui/gui_frame.h" #include "utils/allocator.h" +#include "utils/log.h" typedef struct gui_frame { int x; @@ -47,6 +48,14 @@ component *gui_frame_find(gui_frame *frame, int id) { return NULL; } +component *gui_frame_find_text(gui_frame *frame, const char *text) { + log_debug("gui_frame_find_text"); + if(frame->root_node) { + return component_find_text(frame->root_node, text); + } + return NULL; +} + component *gui_frame_get_root(const gui_frame *frame) { return frame->root_node; } diff --git a/src/game/gui/gui_frame.h b/src/game/gui/gui_frame.h index d75352054..b09a14253 100644 --- a/src/game/gui/gui_frame.h +++ b/src/game/gui/gui_frame.h @@ -12,6 +12,7 @@ component *gui_frame_get_root(const gui_frame *frame); void gui_frame_free(gui_frame *frame); component *gui_frame_find(gui_frame *frame, int id); +component *gui_frame_find_text(gui_frame *frame, const char *text); void gui_frame_get_measurements(const gui_frame *frame, int *x, int *y, int *w, int *h); diff --git a/src/game/gui/menu.c b/src/game/gui/menu.c index a13206537..76152a399 100644 --- a/src/game/gui/menu.c +++ b/src/game/gui/menu.c @@ -430,6 +430,17 @@ static component *menu_find(component *c, int id) { return NULL; } +static component *menu_find_text(component *c, const char *text) { + log_debug("menu_find_text"); + menu *m = sizer_get_obj(c); + if(m->submenu) { + log_debug("menu_find_text: calling for submenu"); + return component_find_text(m->submenu, text); + } + log_debug("menu_find_text: returning NULL"); + return NULL; +} + void menu_set_margin_top(component *c, int margin) { menu *m = sizer_get_obj(c); m->margin_top = margin; @@ -467,6 +478,7 @@ component *menu_create(void) { sizer_set_layout_cb(c, menu_layout); sizer_set_free_cb(c, menu_free); sizer_set_find_cb(c, menu_find); + sizer_set_find_text_cb(c, menu_find_text); return c; } diff --git a/src/game/gui/sizer.c b/src/game/gui/sizer.c index 0fa0a680a..c584744d9 100644 --- a/src/game/gui/sizer.c +++ b/src/game/gui/sizer.c @@ -17,6 +17,7 @@ typedef struct sizer { sizer_tick_cb tick; sizer_free_cb free; sizer_find_cb find; + sizer_find_text_cb find_text; sizer_init_cb init; } sizer; @@ -109,6 +110,12 @@ void sizer_set_find_cb(component *c, sizer_find_cb cb) { local->find = cb; } +void sizer_set_find_text_cb(component *c, sizer_find_text_cb cb) { + assert(c->header == SIZER_MAGIC); + sizer *local = component_get_obj(c); + local->find_text = cb; +} + void sizer_set_init_cb(component *c, sizer_init_cb cb) { assert(c->header == SIZER_MAGIC); sizer *local = component_get_obj(c); @@ -243,6 +250,31 @@ static component *sizer_find(component *c, int id) { return NULL; } +static component *sizer_find_text(component *c, const char *text) { + assert(c->header == SIZER_MAGIC); + sizer *local = component_get_obj(c); + + iterator it; + component **tmp; + vector_iter_begin(&local->objs, &it); + foreach(it, tmp) { + // Find out if the component is what we're looking for. + // If it is, return pointer. + component *out = component_find_text(*tmp, text); + if(out != NULL) { + return out; + } + } + + // If find callback is set, try to use it. + if(local->find_text) { + return local->find_text(c, text); + } + + // If requested ID was not found in any of the internal components/widgets, return NULL. + return NULL; +} + component *sizer_create(void) { component *c = component_create(SIZER_MAGIC); @@ -257,6 +289,7 @@ component *sizer_create(void) { component_set_layout_cb(c, sizer_layout); component_set_free_cb(c, sizer_free); component_set_find_cb(c, sizer_find); + component_set_find_text_cb(c, sizer_find_text); component_set_init_cb(c, sizer_init); return c; diff --git a/src/game/gui/sizer.h b/src/game/gui/sizer.h index 5f45e65d6..6cdcf10fe 100644 --- a/src/game/gui/sizer.h +++ b/src/game/gui/sizer.h @@ -12,6 +12,7 @@ typedef void (*sizer_tick_cb)(component *c); typedef void (*sizer_init_cb)(component *c, const gui_theme *theme); typedef void (*sizer_free_cb)(component *c); typedef component *(*sizer_find_cb)(component *c, int id); +typedef component *(*sizer_find_text_cb)(component *c, const char *text); typedef struct sizer sizer; @@ -36,6 +37,7 @@ void sizer_set_tick_cb(component *c, sizer_tick_cb cb); void sizer_set_free_cb(component *c, sizer_free_cb cb); void sizer_set_init_cb(component *c, sizer_init_cb cb); void sizer_set_find_cb(component *c, sizer_find_cb cb); +void sizer_set_find_text_cb(component *c, sizer_find_text_cb cb); void sizer_attach(component *c, component *nc); diff --git a/src/game/gui/spritebutton.c b/src/game/gui/spritebutton.c index d1252d1ef..c1c05cffe 100644 --- a/src/game/gui/spritebutton.c +++ b/src/game/gui/spritebutton.c @@ -25,6 +25,7 @@ typedef struct spritebutton { spritebutton_click_cb click_cb; spritebutton_tick_cb tick_cb; spritebutton_focus_cb focus_cb; + spritebutton_find_text_cb find_text_cb; bool free_userdata; void *userdata; } spritebutton; @@ -71,6 +72,15 @@ static void spritebutton_tick(component *c) { } } +static component *spritebutton_find_text(component *c, const char *text) { + log_debug("spritebutton_find_text"); + spritebutton *b = widget_get_obj(c); + if(strcmp(text_c(b->text), text) == 0) { + return c; + } + return NULL; +} + static void spritebutton_focus(component *c, bool focused) { spritebutton *b = widget_get_obj(c); if(b->focus_cb) { @@ -139,6 +149,8 @@ component *spritebutton_create(const char *text, const surface *img, bool disabl widget_set_tick_cb(c, spritebutton_tick); widget_set_free_cb(c, spritebutton_free); widget_set_layout_cb(c, spritebutton_layout); + log_debug("widget_set_find_text_cb(c, spritebutton_find_text): %s", text_c(b->text)); + widget_set_find_text_cb(c, spritebutton_find_text); return c; } diff --git a/src/game/gui/spritebutton.h b/src/game/gui/spritebutton.h index 96093db73..d00d55f8e 100644 --- a/src/game/gui/spritebutton.h +++ b/src/game/gui/spritebutton.h @@ -8,6 +8,7 @@ typedef void (*spritebutton_click_cb)(component *c, void *userdata); typedef void (*spritebutton_tick_cb)(component *c, void *userdata); typedef void (*spritebutton_focus_cb)(component *c, bool focused, void *userdata); +typedef component *(*spritebutton_find_text_cb)(component *c, const char *text); component *spritebutton_create(const char *text, const surface *img, bool disabled, spritebutton_click_cb cb, void *userdata); diff --git a/src/game/gui/trn_menu.c b/src/game/gui/trn_menu.c index 40767ffdc..a77a6a711 100644 --- a/src/game/gui/trn_menu.c +++ b/src/game/gui/trn_menu.c @@ -1,5 +1,6 @@ #include "game/gui/trn_menu.h" #include "game/gui/sizer.h" +#include "game/gui/widget.h" #include "utils/allocator.h" #include "utils/log.h" #include "utils/vector.h" @@ -420,6 +421,46 @@ int trnmenu_is_finished(const component *c) { return m->finished; } +static component *trnmenu_find_text(component *c, const char *text) { + log_debug("trnmenu_find_text"); + + iterator it; + component **tmp; + sizer_begin_iterator(c, &it); + + foreach(it, tmp) { + component *t = *tmp; + // log_debug("trnmenu_find_text: iterating %p", t); + + // if(!component_is_selectable(t)) { + // continue; + //} + // widget *w = component_get_obj(t); + // component_get_obj(t); + + component *found = widget_find_text(t, text); + if(found != NULL) { + log_debug("trnmenu_find_text: found %p", t); + return found; + } else { + log_debug("trnmenu_find_text: found was NULL on %p", t); + } + } + log_debug("trnmenu_find_text: checking submenu"); + + trnmenu *m = sizer_get_obj(c); + if(m->submenu != NULL) { + log_debug("trnmenu_find_text: submenu is non-NULL"); + component *found = component_find_text(m->submenu, text); + if(found != NULL) { + return found; + } + } else { + log_debug("trnmenu_find_text: submenu is NULL"); + } + return NULL; +} + void trnmenu_set_submenu(component *c, component *submenu) { trnmenu *m = sizer_get_obj(c); if(m->submenu) { @@ -480,6 +521,7 @@ component *trnmenu_create(surface *button_sheet, int sheet_x, int sheet_y, bool sizer_set_event_cb(c, trnmenu_event); sizer_set_tick_cb(c, trnmenu_tick); sizer_set_free_cb(c, trnmenu_free); + sizer_set_find_text_cb(c, trnmenu_find_text); return c; } diff --git a/src/game/gui/trn_menu.h b/src/game/gui/trn_menu.h index 5ff0767ad..fd3dbaa86 100644 --- a/src/game/gui/trn_menu.h +++ b/src/game/gui/trn_menu.h @@ -11,6 +11,7 @@ typedef void (*trnmenu_tick_cb)(component *c); typedef void (*trnmenu_free_cb)(component *c); typedef void (*trnmenu_submenu_init_cb)(component *menu, component *submenu); typedef void (*trnmenu_submenu_done_cb)(component *menu, component *submenu); +typedef component *(*trnmenu_find_text_cb)(component *menu, const char *text); component *trnmenu_create(surface *button_sheet, int sheet_x, int sheet_y, bool return_hand); void trnmenu_attach(component *menu, component *c); diff --git a/src/game/gui/widget.c b/src/game/gui/widget.c index 319b7be9e..4c01d3521 100644 --- a/src/game/gui/widget.c +++ b/src/game/gui/widget.c @@ -12,6 +12,7 @@ typedef struct widget { widget_event_cb event; widget_action_cb action; widget_focus_cb focus; + widget_find_text_cb find_text; widget_layout_cb layout; widget_tick_cb tick; widget_init_cb init; @@ -66,6 +67,13 @@ void widget_set_focus_cb(component *c, widget_focus_cb cb) { local->focus = cb; } +void widget_set_find_text_cb(component *c, widget_find_text_cb cb) { + log_debug("widget_set_find_text_cb %p", c); + assert(c->header == WIDGET_MAGIC); + widget *local = component_get_obj(c); + local->find_text = cb; +} + void widget_set_layout_cb(component *c, widget_layout_cb cb) { assert(c->header == WIDGET_MAGIC); widget *local = component_get_obj(c); @@ -165,6 +173,16 @@ static component *widget_find(component *c, int id) { return NULL; } +component *widget_find_text(component *c, const char *text) { + widget *w = component_get_obj(c); + log_debug("widget_find_text(%p): %p", c, w); + component *ret = NULL; + if(w->find_text != NULL) { + ret = w->find_text(c, text); + } + return ret; +} + component *widget_create(void) { component *c = component_create(WIDGET_MAGIC); c->supports_disable = 1; diff --git a/src/game/gui/widget.h b/src/game/gui/widget.h index d745aa2fe..5ab896aed 100644 --- a/src/game/gui/widget.h +++ b/src/game/gui/widget.h @@ -6,6 +6,7 @@ typedef void (*widget_render_cb)(component *c); typedef int (*widget_event_cb)(component *c, SDL_Event *event); typedef int (*widget_action_cb)(component *c, int action); +typedef component *(*widget_find_text_cb)(component *c, const char *text); typedef void (*widget_focus_cb)(component *c, bool focused); typedef void (*widget_layout_cb)(component *c, int x, int y, int w, int h); typedef void (*widget_tick_cb)(component *c); @@ -20,9 +21,12 @@ void *widget_get_obj(const component *c); void widget_set_id(component *c, int id); int widget_get_id(const component *c); +component *widget_find_text(component *c, const char *text); + void widget_set_render_cb(component *c, widget_render_cb cb); void widget_set_event_cb(component *c, widget_event_cb cb); void widget_set_action_cb(component *c, widget_action_cb cb); +void widget_set_find_text_cb(component *c, widget_find_text_cb cb); void widget_set_focus_cb(component *c, widget_focus_cb cb); void widget_set_layout_cb(component *c, widget_layout_cb cb); void widget_set_tick_cb(component *c, widget_tick_cb cb); diff --git a/src/game/scenes/mechlab.c b/src/game/scenes/mechlab.c index 477a5bba3..9a9cd09e4 100644 --- a/src/game/scenes/mechlab.c +++ b/src/game/scenes/mechlab.c @@ -587,6 +587,11 @@ void mechlab_input_tick(scene *scene) { controller_free_chain(p1); } +gui_frame *mechlab_get_frame(scene *scene) { + mechlab_local *local = scene_get_userdata(scene); + return local->frame; +} + // Init mechlab int mechlab_create(scene *scene) { // Alloc diff --git a/src/game/scenes/mechlab.h b/src/game/scenes/mechlab.h index a54022814..c38144e26 100644 --- a/src/game/scenes/mechlab.h +++ b/src/game/scenes/mechlab.h @@ -3,6 +3,7 @@ #include "formats/chr.h" #include "game/gui/component.h" +#include "game/gui/gui_frame.h" #include "game/protos/scene.h" #define MECHLAB_DARK_GREEN 165 @@ -41,4 +42,6 @@ void mechlab_spin_har(scene *scene, bool to_spin_or_not_to_spin); sd_chr_enemy *mechlab_next_opponent(scene *scene); +gui_frame *mechlab_get_frame(scene *scene); + #endif // MECHLAB_H diff --git a/src/game/scenes/mechlab/button_details.c b/src/game/scenes/mechlab/button_details.c index e4c92ee70..1a288fe6b 100644 --- a/src/game/scenes/mechlab/button_details.c +++ b/src/game/scenes/mechlab/button_details.c @@ -1,9 +1,13 @@ #include "game/scenes/mechlab/button_details.h" +#include "utils/log.h" component *sprite_button_from_details(const button_details *details, const char *text, const surface *img, void *userdata) { - component *b = - spritebutton_create(text != NULL ? text : details->text, img, details->disabled, details->cb, userdata); + text = text != NULL ? text : details->text; + + log_debug("sprite_button_from_details(%s)", text); + + component *b = spritebutton_create(text, img, details->disabled, details->cb, userdata); spritebutton_set_vertical_align(b, details->valign); spritebutton_set_horizontal_align(b, details->halign); spritebutton_set_text_direction(b, details->dir); diff --git a/src/game/scenes/mechlab/lab_menu_main.c b/src/game/scenes/mechlab/lab_menu_main.c index df763341e..52757fe30 100644 --- a/src/game/scenes/mechlab/lab_menu_main.c +++ b/src/game/scenes/mechlab/lab_menu_main.c @@ -5,6 +5,7 @@ #include "game/gui/sizer.h" #include "game/gui/spritebutton.h" #include "game/gui/trn_menu.h" +#include "game/gui/widget.h" #include "game/scenes/mechlab.h" #include "game/scenes/mechlab/button_details.h" #include "game/scenes/mechlab/lab_menu_customize.h"