Пример #1
0
/**
 * menu_iterate:
 * @input                    : input sample for this frame
 * @old_input                : input sample of the previous frame
 * @trigger_input            : difference' input sample - difference
 *                             between 'input' and 'old_input'
 *
 * Runs RetroArch menu for one frame.
 *
 * Returns: 0 on success, -1 if we need to quit out of the loop. 
 **/
int generic_menu_iterate(enum menu_action action)
{
   size_t selection;
   menu_entry_t entry;
   enum action_iterate_type iterate_type;
   const char *label          = NULL;
   int ret                    = 0;
   uint32_t label_hash        = 0;
   uint32_t hash              = 0;
   menu_handle_t *menu        = menu_driver_get_ptr();
   file_list_t *menu_stack    = menu_entries_get_menu_stack_ptr();
   file_list_t *selection_buf = menu_entries_get_selection_buf_ptr();

   menu_entries_get_last_stack(NULL, &label, NULL, NULL);

   if (!menu)
      return 0;
   if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection))
      return 0;

   menu->menu_state.msg[0]   = '\0';
   hash                      = menu_hash_calculate(label);
   iterate_type              = action_iterate_type(hash);

   if (action != MENU_ACTION_NOOP || menu_entries_needs_refresh() || menu_display_ctl(MENU_DISPLAY_CTL_UPDATE_PENDING, NULL))
   {
      BIT64_SET(menu->state, MENU_STATE_RENDER_FRAMEBUFFER);
   }

   switch (iterate_type)
   {
      case ITERATE_TYPE_HELP:
         ret = action_iterate_help(menu->menu_state.msg, sizeof(menu->menu_state.msg), label);
         BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX);
         BIT64_SET(menu->state, MENU_STATE_POST_ITERATE);
         if (ret == 1 || action == MENU_ACTION_OK)
            BIT64_SET(menu->state, MENU_STATE_POP_STACK);
         break;
      case ITERATE_TYPE_BIND:
         if (menu_input_key_bind_iterate(menu->menu_state.msg, sizeof(menu->menu_state.msg)))
         {
            menu_entries_pop_stack(&selection);
            menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection);
         }
         else
            BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX);
         break;
      case ITERATE_TYPE_INFO:
         {
            menu_file_list_cbs_t *cbs = menu_entries_get_actiondata_at_offset(selection_buf, selection);
            rarch_setting_t *setting  = cbs->setting;

            if (setting)
            {
               char needle[PATH_MAX_LENGTH];
               strlcpy(needle, menu_setting_get_name(setting), sizeof(needle));
               label_hash       = menu_hash_calculate(needle);
            }

            ret = menu_hash_get_help(label_hash, menu->menu_state.msg, sizeof(menu->menu_state.msg));
         }
         BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX);
         BIT64_SET(menu->state, MENU_STATE_POST_ITERATE);
         if (action == MENU_ACTION_OK)
            BIT64_SET(menu->state, MENU_STATE_POP_STACK);
         break;
      case ITERATE_TYPE_DEFAULT:
         /* FIXME: Crappy hack, needed for mouse controls to not be completely broken
          * in case we press back.
          *
          * We need to fix this entire mess, mouse controls should not rely on a 
          * hack like this in order to work. */
         selection = max(min(selection, (menu_entries_get_size() - 1)), 0);

         menu_entry_get(&entry,    selection, NULL, false);
         ret = menu_entry_action(&entry, selection, (enum menu_action)action);

         if (ret)
            goto end;

         BIT64_SET(menu->state, MENU_STATE_POST_ITERATE);

         /* Have to defer it so we let settings refresh. */
         if (menu->push_help_screen)
         {
            menu_displaylist_info_t info = {0};

            info.list = menu_stack;
            strlcpy(info.label,
                  menu_hash_to_str(MENU_LABEL_HELP),
                  sizeof(info.label));

            menu_displaylist_push_list(&info, DISPLAYLIST_HELP);
         }
         break;
   }

   BIT64_SET(menu->state, MENU_STATE_BLIT);

   if (BIT64_GET(menu->state, MENU_STATE_POP_STACK))
   {
      size_t new_selection_ptr = selection;
      menu_entries_pop_stack(&new_selection_ptr);
      menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection);
   }
   
   if (BIT64_GET(menu->state, MENU_STATE_POST_ITERATE))
      menu_input_post_iterate(&ret, action);

end:
   if (ret)
      return -1;
   return 0;
}
Пример #2
0
bool menu_input_ctl(enum menu_input_ctl_state state, void *data)
{
   static char menu_input_keyboard_label_setting[256];
   static const char **menu_input_keyboard_buffer;
   static const char *menu_input_keyboard_label = NULL;
   static bool pointer_dragging                 = false;
   menu_input_t *menu_input                     = menu_input_get_ptr();

   if (!menu_input)
      return false;

   switch (state)
   {
      case MENU_INPUT_CTL_BIND_SET_MIN_MAX:
         {
            menu_input_ctx_bind_limits_t *lim = 
               (menu_input_ctx_bind_limits_t*)data;
            if (!lim || !menu_input)
               return false;

            menu_input->binds.begin = lim->min;
            menu_input->binds.last  = lim->max;
         }
         break;
      case MENU_INPUT_CTL_CHECK_INSIDE_HITBOX:
         {
            menu_input_ctx_hitbox_t *hitbox = (menu_input_ctx_hitbox_t*)data;
            int16_t  mouse_x       = menu_input_mouse_state(MENU_MOUSE_X_AXIS);
            int16_t  mouse_y       = menu_input_mouse_state(MENU_MOUSE_Y_AXIS);
            bool     inside_hitbox = 
                  (mouse_x    >= hitbox->x1) 
                  && (mouse_x <= hitbox->x2) 
                  && (mouse_y >= hitbox->y1) 
                  && (mouse_y <= hitbox->y2)
                  ;

            if (!inside_hitbox)
               return false;
         }
         break;
      case MENU_INPUT_CTL_DEINIT:
         memset(menu_input, 0, sizeof(menu_input_t));
         pointer_dragging      = false;
         break;
      case MENU_INPUT_CTL_SEARCH_START:
         {
            menu_handle_t      *menu = NULL;
            if (!menu_driver_ctl(
                     RARCH_MENU_CTL_DRIVER_DATA_GET, &menu))
               return false;

            menu_input->keyboard.display = true;
            menu_input_keyboard_label    = menu_hash_to_str(MENU_VALUE_SEARCH);
            menu_input_keyboard_buffer   =
               input_keyboard_start_line(menu, menu_input_search_cb);
         }
         break;
      case MENU_INPUT_CTL_MOUSE_PTR:
         {
            unsigned *ptr = (unsigned*)data;
            menu_input->mouse.ptr = *ptr;
         }
         break;
      case MENU_INPUT_CTL_POINTER_PTR:
         {
            unsigned *ptr = (unsigned*)data;
            menu_input->pointer.ptr = *ptr;
         }
         break;
      case MENU_INPUT_CTL_POINTER_ACCEL_READ:
         {
            float *ptr = (float*)data;
            *ptr = menu_input->pointer.accel;
         }
         break;
      case MENU_INPUT_CTL_POINTER_ACCEL_WRITE:
         {
            float *ptr = (float*)data;
            menu_input->pointer.accel = *ptr;
         }
         break;
      case MENU_INPUT_CTL_IS_POINTER_DRAGGED:
         return pointer_dragging;
      case MENU_INPUT_CTL_SET_POINTER_DRAGGED:
         pointer_dragging = true;
         break;
      case MENU_INPUT_CTL_UNSET_POINTER_DRAGGED:
         pointer_dragging = false;
         break;
      case MENU_INPUT_CTL_KEYBOARD_DISPLAY:
         {
            bool *ptr = (bool*)data;
            *ptr = menu_input->keyboard.display;
         }
         break;
      case MENU_INPUT_CTL_SET_KEYBOARD_DISPLAY:
         {
            bool *ptr = (bool*)data;
            menu_input->keyboard.display = *ptr;
         }
         break;
      case MENU_INPUT_CTL_KEYBOARD_BUFF_PTR:
         {
            const char **ptr = (const char**)data;
            *ptr = *menu_input_keyboard_buffer;
         }
         break;
      case MENU_INPUT_CTL_KEYBOARD_LABEL:
         {
            const char **ptr = (const char**)data;
            *ptr = menu_input_keyboard_label;
         }
         break;
      case MENU_INPUT_CTL_SET_KEYBOARD_LABEL:
         {
            char **ptr = (char**)data;
            menu_input_keyboard_label = *ptr;
         }
         break;
      case MENU_INPUT_CTL_UNSET_KEYBOARD_LABEL:
         menu_input_keyboard_label = NULL;
         break;
      case MENU_INPUT_CTL_KEYBOARD_LABEL_SETTING:
         {
            const char **ptr = (const char**)data;
            *ptr = menu_input_keyboard_label_setting;
         }
         break;
      case MENU_INPUT_CTL_SET_KEYBOARD_LABEL_SETTING:
         {
            char **ptr = (char**)data;
            strlcpy(menu_input_keyboard_label_setting,
            *ptr, sizeof(menu_input_keyboard_label_setting));
         }
         break;
      case MENU_INPUT_CTL_UNSET_KEYBOARD_LABEL_SETTING:
         menu_input_keyboard_label_setting[0] = '\0';
         break;
      case MENU_INPUT_CTL_BIND_NONE:
      case MENU_INPUT_CTL_BIND_SINGLE:
      case MENU_INPUT_CTL_BIND_ALL:
         return menu_input_key_bind_set_mode(state, data);
      case MENU_INPUT_CTL_BIND_ITERATE:
         {
            menu_input_ctx_bind_t *bind = (menu_input_ctx_bind_t*)data;
            if (!bind)
               return false;
            return menu_input_key_bind_iterate(bind->s, bind->len);
         }
      case MENU_INPUT_CTL_START_LINE:
         {
            bool keyboard_display       = true;
            menu_handle_t    *menu      = NULL;
            menu_input_ctx_line_t *line = (menu_input_ctx_line_t*)data;
            if (!menu_input || !line)
               return false;
            if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu))
               return false;

            menu_input_ctl(MENU_INPUT_CTL_SET_KEYBOARD_DISPLAY,
                  &keyboard_display);
            menu_input_ctl(MENU_INPUT_CTL_SET_KEYBOARD_LABEL,
                  &line->label);
            menu_input_ctl(MENU_INPUT_CTL_SET_KEYBOARD_LABEL_SETTING,
                  &line->label_setting);

            menu_input->keyboard.type   = line->type;
            menu_input->keyboard.idx    = line->idx;
            menu_input_keyboard_buffer  = 
               input_keyboard_start_line(menu, line->cb);
         }
         break;
      default:
      case MENU_INPUT_CTL_NONE:
         break;
   }

   return true;
}
Пример #3
0
/**
 * menu_iterate:
 * @input                    : input sample for this frame
 * @old_input                : input sample of the previous frame
 * @trigger_input            : difference' input sample - difference
 *                             between 'input' and 'old_input'
 *
 * Runs RetroArch menu for one frame.
 *
 * Returns: 0 on success, -1 if we need to quit out of the loop.
 **/
int generic_menu_iterate(void *data, void *userdata, enum menu_action action)
{
   menu_entry_t entry;
   enum action_iterate_type iterate_type;
   size_t selection               = 0;
   unsigned file_type             = 0;
   int ret                        = 0;
   uint32_t hash                  = 0;
   enum msg_hash_enums enum_idx   = MSG_UNKNOWN;
   const char *label              = NULL;
   menu_handle_t *menu            = (menu_handle_t*)data;

   menu_entries_get_last_stack(NULL, &label, &file_type, &enum_idx, NULL);

   if (!menu)
      return 0;
   if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection))
      return 0;

   menu->menu_state.msg[0]   = '\0';
   hash                      = msg_hash_calculate(label);
   iterate_type              = action_iterate_type(hash);

   menu_driver_set_binding_state(iterate_type == ITERATE_TYPE_BIND);

   if (     action != MENU_ACTION_NOOP
         || menu_entries_ctl(MENU_ENTRIES_CTL_NEEDS_REFRESH, NULL)
         || menu_display_get_update_pending())
   {
      BIT64_SET(menu->state, MENU_STATE_RENDER_FRAMEBUFFER);
   }

   switch (iterate_type)
   {
      case ITERATE_TYPE_HELP:
         ret = menu_dialog_iterate(
               menu->menu_state.msg, sizeof(menu->menu_state.msg), label);
         BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX);
         BIT64_SET(menu->state, MENU_STATE_POST_ITERATE);
         if (ret == 1 || action == MENU_ACTION_OK)
         {
            BIT64_SET(menu->state, MENU_STATE_POP_STACK);
            menu_dialog_set_active(false);
         }

         if (action == MENU_ACTION_CANCEL)
         {
            BIT64_SET(menu->state, MENU_STATE_POP_STACK);
            menu_dialog_set_active(false);
         }
         break;
      case ITERATE_TYPE_BIND:
         {
            menu_input_ctx_bind_t bind;

            bind.s   = menu->menu_state.msg;
            bind.len = sizeof(menu->menu_state.msg);

            if (menu_input_key_bind_iterate(&bind))
            {
               menu_entries_pop_stack(&selection, 0, 0);
               menu_navigation_ctl(
                     MENU_NAVIGATION_CTL_SET_SELECTION, &selection);
            }
            else
               BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX);
         }
         break;
      case ITERATE_TYPE_INFO:
         {
            file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
            menu_file_list_cbs_t *cbs  =
               menu_entries_get_actiondata_at_offset(selection_buf, selection);

            if (cbs->enum_idx != MSG_UNKNOWN)
            {
               ret = menu_hash_get_help_enum(cbs->enum_idx,
                     menu->menu_state.msg, sizeof(menu->menu_state.msg));
            }
            else
            {
               unsigned type = 0;
               enum msg_hash_enums enum_idx = MSG_UNKNOWN;
               menu_entries_get_at_offset(selection_buf, selection,
                     NULL, NULL, &type, NULL, NULL);

               switch (type)
               {
                  case FILE_TYPE_FONT:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_FONT;
                     break;
                  case FILE_TYPE_RDB:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_RDB;
                     break;
                  case FILE_TYPE_OVERLAY:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_OVERLAY;
                     break;
                  case FILE_TYPE_CHEAT:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_CHEAT;
                     break;
                  case FILE_TYPE_SHADER_PRESET:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_SHADER_PRESET;
                     break;
                  case FILE_TYPE_SHADER:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_SHADER;
                     break;
                  case FILE_TYPE_REMAP:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_REMAP;
                     break;
                  case FILE_TYPE_RECORD_CONFIG:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_RECORD_CONFIG;
                     break;
                  case FILE_TYPE_CURSOR:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_CURSOR;
                     break;
                  case FILE_TYPE_CONFIG:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_CONFIG;
                     break;
                  case FILE_TYPE_CARCHIVE:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_COMPRESSED_ARCHIVE;
                     break;
                  case FILE_TYPE_DIRECTORY:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_DIRECTORY;
                     break;
                  case FILE_TYPE_VIDEOFILTER:            /* TODO/FIXME */
                  case FILE_TYPE_AUDIOFILTER:            /* TODO/FIXME */
                  case FILE_TYPE_SHADER_SLANG:           /* TODO/FIXME */
                  case FILE_TYPE_SHADER_GLSL:            /* TODO/FIXME */
                  case FILE_TYPE_SHADER_HLSL:            /* TODO/FIXME */
                  case FILE_TYPE_SHADER_CG:              /* TODO/FIXME */
                  case FILE_TYPE_SHADER_PRESET_GLSLP:    /* TODO/FIXME */
                  case FILE_TYPE_SHADER_PRESET_HLSLP:    /* TODO/FIXME */
                  case FILE_TYPE_SHADER_PRESET_CGP:      /* TODO/FIXME */
                  case FILE_TYPE_SHADER_PRESET_SLANGP:   /* TODO/FIXME */
                  case FILE_TYPE_PLAIN:
                     enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_PLAIN_FILE;
                     break;
                  default:
                     break;
               }

               if (enum_idx != MSG_UNKNOWN)
                  ret = menu_hash_get_help_enum(enum_idx,
                        menu->menu_state.msg, sizeof(menu->menu_state.msg));

            }
         }
         BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX);
         BIT64_SET(menu->state, MENU_STATE_POST_ITERATE);
         if (action == MENU_ACTION_OK || action == MENU_ACTION_CANCEL)
         {
            BIT64_SET(menu->state, MENU_STATE_POP_STACK);
         }
         menu_dialog_set_active(false);
         break;
      case ITERATE_TYPE_DEFAULT:
         /* FIXME: Crappy hack, needed for mouse controls
          * to not be completely broken in case we press back.
          *
          * We need to fix this entire mess, mouse controls
          * should not rely on a hack like this in order to work. */
         selection = MAX(MIN(selection, (menu_entries_get_size() - 1)), 0);

         menu_entry_get(&entry, 0, selection, NULL, false);
         ret = menu_entry_action(&entry, selection, (enum menu_action)action);

         if (ret)
            goto end;

         BIT64_SET(menu->state, MENU_STATE_POST_ITERATE);

         /* Have to defer it so we let settings refresh. */
         menu_dialog_push();
         break;
   }

   BIT64_SET(menu->state, MENU_STATE_BLIT);

   if (BIT64_GET(menu->state, MENU_STATE_POP_STACK))
   {
      size_t new_selection_ptr = selection;
      menu_entries_pop_stack(&new_selection_ptr, 0, 0);
      menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection);
   }

   if (BIT64_GET(menu->state, MENU_STATE_POST_ITERATE))
      menu_input_post_iterate(&ret, action);

end:
   if (ret)
      return -1;
   return 0;
}