From 023443e1aa960e57c1c5e466301fb25ecc16f36b Mon Sep 17 00:00:00 2001 From: Themaister Date: Sat, 22 Dec 2012 13:27:00 +0100 Subject: [PATCH] Initial overlay config work. --- input/input_common.c | 71 +++++++++ input/input_common.h | 2 + input/overlay.c | 264 ++++++++++++++++++++++++++----- media/overlays/basic_overlay.cfg | 19 +++ 4 files changed, 317 insertions(+), 39 deletions(-) create mode 100644 media/overlays/basic_overlay.cfg diff --git a/input/input_common.c b/input/input_common.c index 9aab2731df..ece76fd3ec 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -481,3 +481,74 @@ unsigned input_translate_rk_to_keysym(enum retro_key key) return rarch_keysym_lut[key]; } +struct str_to_bind_map +{ + const char *str; + unsigned bind; +}; + +static const struct str_to_bind_map str_to_bind[] = { + { "b", RETRO_DEVICE_ID_JOYPAD_B }, + { "y", RETRO_DEVICE_ID_JOYPAD_Y }, + { "select", RETRO_DEVICE_ID_JOYPAD_SELECT }, + { "start", RETRO_DEVICE_ID_JOYPAD_START }, + { "up", RETRO_DEVICE_ID_JOYPAD_UP }, + { "down", RETRO_DEVICE_ID_JOYPAD_DOWN }, + { "left", RETRO_DEVICE_ID_JOYPAD_LEFT }, + { "right", RETRO_DEVICE_ID_JOYPAD_RIGHT }, + { "a", RETRO_DEVICE_ID_JOYPAD_A }, + { "x", RETRO_DEVICE_ID_JOYPAD_X }, + { "l", RETRO_DEVICE_ID_JOYPAD_L }, + { "r", RETRO_DEVICE_ID_JOYPAD_R }, + { "l2", RETRO_DEVICE_ID_JOYPAD_L2 }, + { "r2", RETRO_DEVICE_ID_JOYPAD_R2 }, + { "l3", RETRO_DEVICE_ID_JOYPAD_L3 }, + { "r3", RETRO_DEVICE_ID_JOYPAD_R3 }, + { "turbo", RARCH_TURBO_ENABLE }, + { "l_x_plus", RARCH_ANALOG_LEFT_X_PLUS }, + { "l_x_minus", RARCH_ANALOG_LEFT_X_MINUS }, + { "l_y_plus", RARCH_ANALOG_LEFT_Y_PLUS }, + { "l_y_minus", RARCH_ANALOG_LEFT_Y_MINUS }, + { "r_x_plus", RARCH_ANALOG_RIGHT_X_PLUS }, + { "r_x_minus", RARCH_ANALOG_RIGHT_X_MINUS }, + { "r_y_plus", RARCH_ANALOG_RIGHT_Y_PLUS }, + { "r_y_minus", RARCH_ANALOG_RIGHT_Y_MINUS }, + { "toggle_fast_forward", RARCH_FAST_FORWARD_KEY }, + { "hold_fast_forward", RARCH_FAST_FORWARD_HOLD_KEY }, + { "load_state", RARCH_LOAD_STATE_KEY }, + { "save_state", RARCH_SAVE_STATE_KEY }, + { "toggle_fullscreen", RARCH_FULLSCREEN_TOGGLE_KEY }, + { "exit_emulator", RARCH_QUIT_KEY }, + { "state_slot_increase", RARCH_STATE_SLOT_PLUS }, + { "state_slot_decrease", RARCH_STATE_SLOT_MINUS }, + { "rewind", RARCH_REWIND }, + { "movie_record_toggle", RARCH_MOVIE_RECORD_TOGGLE }, + { "pause_toggle", RARCH_PAUSE_TOGGLE }, + { "frame_advance", RARCH_FRAMEADVANCE }, + { "reset", RARCH_RESET }, + { "shader_next", RARCH_SHADER_NEXT }, + { "shader_prev", RARCH_SHADER_PREV }, + { "cheat_index_plus", RARCH_CHEAT_INDEX_PLUS }, + { "cheat_index_minus", RARCH_CHEAT_INDEX_MINUS }, + { "cheat_toggle", RARCH_CHEAT_TOGGLE }, + { "screenshot", RARCH_SCREENSHOT }, + { "dsp_config", RARCH_DSP_CONFIG }, + { "audio_mute", RARCH_MUTE }, + { "netplay_flip_players", RARCH_NETPLAY_FLIP }, + { "slowmotion", RARCH_SLOWMOTION }, + { "enable_hotkey", RARCH_ENABLE_HOTKEY }, + { "volume_up", RARCH_VOLUME_UP }, + { "volume_down", RARCH_VOLUME_DOWN }, +}; + +unsigned input_str_to_bind(const char *str) +{ + for (unsigned i = 0; i < ARRAY_SIZE(str_to_bind); i++) + { + if (!strcmp(str_to_bind[i].str, str)) + return str_to_bind[i].bind; + } + + return RARCH_BIND_LIST_END; +} + diff --git a/input/input_common.h b/input/input_common.h index fbef9fbb80..6c41005938 100644 --- a/input/input_common.h +++ b/input/input_common.h @@ -97,5 +97,7 @@ void input_init_keyboard_lut(const struct rarch_key_map *map); enum retro_key input_translate_keysym_to_rk(unsigned sym); unsigned input_translate_rk_to_keysym(enum retro_key key); +unsigned input_str_to_bind(const char *str); + #endif diff --git a/input/overlay.c b/input/overlay.c index 1bcd999ac3..71c0ef48fb 100644 --- a/input/overlay.c +++ b/input/overlay.c @@ -18,14 +18,208 @@ #include "../driver.h" #include "../libretro.h" #include "../gfx/image.h" +#include "../conf/config_file.h" +#include "input_common.h" +#include "../file.h" +#include +#include + +enum overlay_hitbox +{ + OVERLAY_HITBOX_RADIAL = 0, + OVERLAY_HITBOX_RECT +}; + +struct overlay_desc +{ + float x; + float y; + + enum overlay_hitbox hitbox; + float range_x, range_y; + + unsigned key; +}; + +struct overlay +{ + struct overlay_desc *descs; + size_t size; + + uint32_t *image; + unsigned width; + unsigned height; +}; struct input_overlay { void *iface_data; const video_overlay_interface_t *iface; bool enable; + + struct overlay *overlays; + const struct overlay *active; + size_t index; + size_t size; }; +static void input_overlay_free_overlay(struct overlay *overlay) +{ + free(overlay->descs); + free(overlay->image); +} + +static void input_overlay_free_overlays(input_overlay_t *ol) +{ + for (size_t i = 0; i < ol->size; i++) + input_overlay_free_overlay(&ol->overlays[i]); + free(ol->overlays); +} + +static bool input_overlay_load_desc(config_file_t *conf, struct overlay_desc *desc, + unsigned ol_index, unsigned desc_index, + unsigned width, unsigned height) +{ + bool ret = true; + char overlay_desc_key[64]; + snprintf(overlay_desc_key, sizeof(overlay_desc_key), "overlay%u_desc%u", ol_index, desc_index); + + char overlay[256]; + if (!config_get_array(conf, overlay_desc_key, overlay, sizeof(overlay))) + return false; + + struct string_list *list = string_split(overlay, ", "); + if (!list) + return false; + + if (list->size < 6) + { + string_list_free(list); + return false; + } + + const char *key = list->elems[0].data; + const char *x = list->elems[1].data; + const char *y = list->elems[2].data; + const char *box = list->elems[3].data; + + desc->key = input_str_to_bind(key); + desc->x = strtod(x, NULL) / width; + desc->y = strtod(y, NULL) / height; + + if (!strcmp(box, "radial")) + desc->hitbox = OVERLAY_HITBOX_RADIAL; + else if (!strcmp(box, "rect")) + desc->hitbox = OVERLAY_HITBOX_RECT; + else + { + ret = false; + goto end; + } + + desc->range_x = strtod(list->elems[4].data, NULL) / width; + desc->range_y = strtod(list->elems[5].data, NULL) / height; + +end: + if (list) + string_list_free(list); + return ret; +} + +static bool input_overlay_load_overlay(config_file_t *conf, const char *config_path, + struct overlay *overlay, unsigned index) +{ + char overlay_path_key[64]; + char overlay_path[PATH_MAX]; + char overlay_resolved_path[PATH_MAX]; + + snprintf(overlay_path_key, sizeof(overlay_path_key), "overlay%u_overlay", index); + if (!config_get_path(conf, overlay_path_key, overlay_path, sizeof(overlay_path))) + return false; + + fill_pathname_resolve_relative(overlay_resolved_path, config_path, + overlay_path, sizeof(overlay_resolved_path)); + + struct texture_image img = {0}; + if (!texture_image_load(overlay_resolved_path, &img)) + { + RARCH_ERR("Failed to load image: %s.\n", overlay_path); + return false; + } + + overlay->image = img.pixels; + overlay->width = img.width; + overlay->height = img.height; + + char overlay_descs_key[64]; + snprintf(overlay_descs_key, sizeof(overlay_descs_key), "overlay%u_descs", index); + + unsigned descs = 0; + if (!config_get_uint(conf, overlay_descs_key, &descs)) + return false; + + overlay->descs = (struct overlay_desc*)calloc(descs, sizeof(*overlay->descs)); + if (!overlay->descs) + return false; + + overlay->size = descs; + + for (size_t i = 0; i < overlay->size; i++) + { + if (!input_overlay_load_desc(conf, &overlay->descs[i], index, i, img.width, img.height)) + return false; + } + + return true; +} + +static bool input_overlay_load_overlays(input_overlay_t *ol, const char *path) +{ + bool ret = true; + config_file_t *conf = config_file_new(path); + if (!conf) + { + RARCH_ERR("Failed to load config file: %s.\n", path); + return false; + } + + unsigned overlays = 0; + if (!config_get_uint(conf, "overlays", &overlays)) + { + RARCH_ERR("overlays variable not defined in config.\n"); + ret = false; + goto end; + } + + if (!overlays) + { + ret = false; + goto end; + } + + ol->overlays = (struct overlay*)calloc(overlays, sizeof(*ol->overlays)); + if (!ol->overlays) + { + ret = false; + goto end; + } + + ol->size = overlays; + + for (size_t i = 0; i < ol->size; i++) + { + if (!input_overlay_load_overlay(conf, path, &ol->overlays[i], i)) + { + ret = false; + goto end; + } + } + +end: + config_file_free(conf); + return ret; +} + input_overlay_t *input_overlay_new(const char *overlay) { input_overlay_t *ol = (input_overlay_t*)calloc(1, sizeof(*ol)); @@ -45,15 +239,11 @@ input_overlay_t *input_overlay_new(const char *overlay) if (!ol->iface) goto error; - struct texture_image img = {0}; - if (!texture_image_load(overlay, &img)) - { - RARCH_ERR("Failed to load overlay image.\n"); + if (!input_overlay_load_overlays(ol, overlay)) goto error; - } - ol->iface->load(ol->iface_data, img.pixels, img.width, img.height); - free(img.pixels); + ol->active = &ol->overlays[0]; + ol->iface->load(ol->iface_data, ol->active->image, ol->active->width, ol->active->height); ol->iface->enable(ol->iface_data, true); ol->enable = true; @@ -71,34 +261,27 @@ void input_overlay_enable(input_overlay_t *ol, bool enable) ol->iface->enable(ol->iface_data, enable); } -struct overlay_desc +static bool inside_hitbox(const struct overlay_desc *desc, float x, float y) { - float x; - float y; - float rad; - unsigned key; -}; + switch (desc->hitbox) + { + case OVERLAY_HITBOX_RADIAL: + { + // Ellipsis. + float x_dist = (x - desc->x) / desc->range_x; + float y_dist = (y - desc->y) / desc->range_y; + float sq_dist = x_dist * x_dist + y_dist * y_dist; + return sq_dist <= 1.0f; + } + + case OVERLAY_HITBOX_RECT: + return (fabs(x - desc->x) <= desc->range_x) && + (fabs(y - desc->y) <= desc->range_y); -// TODO: This will be part of a config of some sort, all customizable and nice. -// -// basic_overlay.png -static const struct overlay_desc descs[] = { - { 15.0 / 256.0, 210.0 / 256.0, 10.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_LEFT }, - { 60.0 / 256.0, 210.0 / 256.0, 10.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_RIGHT }, - { 37.5 / 256.0, 188.0 / 256.0, 10.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_UP }, - { 37.5 / 256.0, 231.0 / 256.0, 10.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_DOWN }, - { 7.5 / 256.0, 113.0 / 256.0, 20.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_L }, - { 7.5 / 256.0, 59.0 / 256.0, 20.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_L2 }, - { 246.0 / 256.0, 113.0 / 256.0, 20.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_R }, - { 246.0 / 256.0, 59.0 / 256.0, 20.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_R2 }, - { 91.0 / 256.0, 168.0 / 256.0, 10.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_SELECT }, - { 134.0 / 256.0, 168.0 / 256.0, 10.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_START }, - - { 200.0 / 256.0, 237.0 / 256.0, 15.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_B }, - { 234.0 / 256.0, 210.0 / 256.0, 15.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_A }, - { 200.0 / 256.0, 180.0 / 256.0, 15.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_X }, - { 163.0 / 256.0, 210.0 / 256.0, 15.0 / 256.0, RETRO_DEVICE_ID_JOYPAD_Y }, -}; + default: + return false; + } +} uint64_t input_overlay_poll(input_overlay_t *ol, int16_t norm_x, int16_t norm_y) { @@ -110,11 +293,10 @@ uint64_t input_overlay_poll(input_overlay_t *ol, int16_t norm_x, int16_t norm_y) float y = (float)(norm_y + 0x7fff) / 0xffff; uint64_t state = 0; - for (unsigned i = 0; i < ARRAY_SIZE(descs); i++) + for (size_t i = 0; i < ol->active->size; i++) { - float sq_dist = (x - descs[i].x) * (x - descs[i].x) + (y - descs[i].y) * (y - descs[i].y); - if (sq_dist <= descs[i].rad * descs[i].rad) - state |= UINT64_C(1) << descs[i].key; + if (inside_hitbox(&ol->active->descs[i], x, y)) + state |= UINT64_C(1) << ol->active->descs[i].key; } return state; @@ -122,8 +304,10 @@ uint64_t input_overlay_poll(input_overlay_t *ol, int16_t norm_x, int16_t norm_y) void input_overlay_next(input_overlay_t *ol) { - // Dummy. Useful when we have configs and multiple overlays. - (void)ol; + ol->index = (ol->index + 1) % ol->size; + ol->active = &ol->overlays[ol->index]; + + ol->iface->load(ol->iface_data, ol->active->image, ol->active->width, ol->active->height); } void input_overlay_free(input_overlay_t *ol) @@ -131,6 +315,8 @@ void input_overlay_free(input_overlay_t *ol) if (!ol) return; + input_overlay_free_overlays(ol); + if (ol->iface) ol->iface->enable(ol->iface_data, false); diff --git a/media/overlays/basic_overlay.cfg b/media/overlays/basic_overlay.cfg new file mode 100644 index 0000000000..22a4844c7e --- /dev/null +++ b/media/overlays/basic_overlay.cfg @@ -0,0 +1,19 @@ +overlays = 1 + +overlay0_overlay = basic_overlay.png + +overlay0_descs = 14 +overlay0_desc0 = "left,15,210,radial,10,10" +overlay0_desc1 = "right,60,210,radial,10,10" +overlay0_desc2 = "up,38,188,radial,10,10" +overlay0_desc3 = "down,38,231,radial,10,10" +overlay0_desc4 = "l,8,113,radial,20,20" +overlay0_desc5 = "l2,8,59,radial,20,20" +overlay0_desc6 = "r,246,113,radial,20,20" +overlay0_desc7 = "r2,246,59,radial,20,20" +overlay0_desc8 = "select,91,168,radial,10,10" +overlay0_desc9 = "start,134,168,radial,10,10" +overlay0_desc10 = "b,200,237,radial,15,15" +overlay0_desc11 = "a,234,210,radial,15,15" +overlay0_desc12 = "x,200,180,radial,15,15" +overlay0_desc13 = "y,163,210,radial,15,15"