mirror of
https://github.com/libretro/RetroArch
synced 2025-03-21 22:20:59 +00:00
Overlays: Add 'reach' and 'exclusive' for hitboxes (#14591)
Allows stretching hitboxes and handling their overlap reach_up, reach_down, reach_left, reach_right: - Stretches in one direction: reach_x, reach_y - Stretches symmetrically exclusive: - If true, blocks input from overlapped hitboxes range_mod_exclusive: - Similar, but only applies when this hitbox is extended by range_mod - After range_mod takes effect, has priority over 'exclusive' E.g. This creates a D-Pad area and extends its hitbox left & right 50%, up 15%, and down 30%. Then applies range_mod_exclusive: overlay0_desc0 = "dpad_area,0.15,0.57,rect,0.166228,0.295516" overlay0_desc0_reach_x = 1.5 overlay0_desc0_reach_up = 1.15 overlay0_desc0_reach_down = 1.3 overlay0_desc0_range_mod = 2.0 overlay0_desc0_range_mod_exclusive = true
This commit is contained in:
parent
7a6c56e947
commit
b47fb0b807
@ -1166,12 +1166,12 @@ static bool input_overlay_add_inputs_inner(overlay_desc_t *desc,
|
|||||||
{
|
{
|
||||||
/* We need ALL of the inputs to be active,
|
/* We need ALL of the inputs to be active,
|
||||||
* abort. */
|
* abort. */
|
||||||
desc->updated = false;
|
desc->updated = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
all_buttons_pressed = true;
|
all_buttons_pressed = true;
|
||||||
desc->updated = true;
|
desc->updated = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bank_mask >>= 1;
|
bank_mask >>= 1;
|
||||||
@ -1223,14 +1223,14 @@ static bool input_overlay_add_inputs_inner(overlay_desc_t *desc,
|
|||||||
|
|
||||||
case OVERLAY_TYPE_DPAD_AREA:
|
case OVERLAY_TYPE_DPAD_AREA:
|
||||||
case OVERLAY_TYPE_ABXY_AREA:
|
case OVERLAY_TYPE_ABXY_AREA:
|
||||||
return desc->updated;
|
return (desc->updated != 0);
|
||||||
|
|
||||||
case OVERLAY_TYPE_KEYBOARD:
|
case OVERLAY_TYPE_KEYBOARD:
|
||||||
if (ol_state ?
|
if (ol_state ?
|
||||||
OVERLAY_GET_KEY(ol_state, desc->retro_key_idx) :
|
OVERLAY_GET_KEY(ol_state, desc->retro_key_idx) :
|
||||||
input_state_internal(port, RETRO_DEVICE_KEYBOARD, 0, desc->retro_key_idx))
|
input_state_internal(port, RETRO_DEVICE_KEYBOARD, 0, desc->retro_key_idx))
|
||||||
{
|
{
|
||||||
desc->updated = true;
|
desc->updated = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1394,16 +1394,16 @@ static bool inside_hitbox(const struct overlay_desc *desc, float x, float y)
|
|||||||
{
|
{
|
||||||
case OVERLAY_HITBOX_RADIAL:
|
case OVERLAY_HITBOX_RADIAL:
|
||||||
{
|
{
|
||||||
/* Ellipsis. */
|
/* Ellipse. */
|
||||||
float x_dist = (x - desc->x_shift) / desc->range_x_mod;
|
float x_dist = (x - desc->x_hitbox) / desc->range_x_mod;
|
||||||
float y_dist = (y - desc->y_shift) / desc->range_y_mod;
|
float y_dist = (y - desc->y_hitbox) / desc->range_y_mod;
|
||||||
float sq_dist = x_dist * x_dist + y_dist * y_dist;
|
float sq_dist = x_dist * x_dist + y_dist * y_dist;
|
||||||
return (sq_dist <= 1.0f);
|
return (sq_dist <= 1.0f);
|
||||||
}
|
}
|
||||||
case OVERLAY_HITBOX_RECT:
|
case OVERLAY_HITBOX_RECT:
|
||||||
return
|
return
|
||||||
(fabs(x - desc->x_shift) <= desc->range_x_mod) &&
|
(fabs(x - desc->x_hitbox) <= desc->range_x_mod) &&
|
||||||
(fabs(y - desc->y_shift) <= desc->range_y_mod);
|
(fabs(y - desc->y_hitbox) <= desc->range_y_mod);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1411,6 +1411,7 @@ static bool inside_hitbox(const struct overlay_desc *desc, float x, float y)
|
|||||||
/**
|
/**
|
||||||
* input_overlay_poll:
|
* input_overlay_poll:
|
||||||
* @out : Polled output data.
|
* @out : Polled output data.
|
||||||
|
* @ptr_idx : Pointer index
|
||||||
* @norm_x : Normalized X coordinate.
|
* @norm_x : Normalized X coordinate.
|
||||||
* @norm_y : Normalized Y coordinate.
|
* @norm_y : Normalized Y coordinate.
|
||||||
*
|
*
|
||||||
@ -1422,9 +1423,11 @@ static bool inside_hitbox(const struct overlay_desc *desc, float x, float y)
|
|||||||
void input_overlay_poll(
|
void input_overlay_poll(
|
||||||
input_overlay_t *ol,
|
input_overlay_t *ol,
|
||||||
input_overlay_state_t *out,
|
input_overlay_state_t *out,
|
||||||
int16_t norm_x, int16_t norm_y, float touch_scale)
|
unsigned ptr_idx, int16_t norm_x, int16_t norm_y, float touch_scale)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i, j;
|
||||||
|
struct overlay_desc *descs = ol->active->descs;
|
||||||
|
unsigned int highest_prio = 0;
|
||||||
|
|
||||||
/* norm_x and norm_y is in [-0x7fff, 0x7fff] range,
|
/* norm_x and norm_y is in [-0x7fff, 0x7fff] range,
|
||||||
* like RETRO_DEVICE_POINTER. */
|
* like RETRO_DEVICE_POINTER. */
|
||||||
@ -1443,14 +1446,34 @@ void input_overlay_poll(
|
|||||||
{
|
{
|
||||||
float x_dist, y_dist;
|
float x_dist, y_dist;
|
||||||
unsigned int base = 0;
|
unsigned int base = 0;
|
||||||
struct overlay_desc *desc = &ol->active->descs[i];
|
unsigned int desc_prio = 0;
|
||||||
|
struct overlay_desc *desc = &descs[i];
|
||||||
|
|
||||||
if (!desc || !inside_hitbox(desc, x, y))
|
if (!desc || !inside_hitbox(desc, x, y))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
desc->updated = true;
|
/* Check for exclusive hitbox, which blocks other input.
|
||||||
x_dist = x - desc->x_shift;
|
* range_mod_exclusive has priority over exclusive. */
|
||||||
y_dist = y - desc->y_shift;
|
if (desc->range_mod_exclusive
|
||||||
|
&& desc->range_x_mod != desc->range_x_hitbox)
|
||||||
|
desc_prio = 2;
|
||||||
|
else if (desc->exclusive)
|
||||||
|
desc_prio = 1;
|
||||||
|
|
||||||
|
if (highest_prio > desc_prio)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (desc_prio > highest_prio)
|
||||||
|
{
|
||||||
|
highest_prio = desc_prio;
|
||||||
|
memset(out, 0, sizeof(*out));
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
BIT16_CLEAR(descs[j].updated, ptr_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
BIT16_SET(desc->updated, ptr_idx);
|
||||||
|
x_dist = x - desc->x_shift;
|
||||||
|
y_dist = y - desc->y_shift;
|
||||||
|
|
||||||
switch (desc->type)
|
switch (desc->type)
|
||||||
{
|
{
|
||||||
@ -1538,10 +1561,10 @@ void input_overlay_post_poll(
|
|||||||
{
|
{
|
||||||
struct overlay_desc *desc = &ol->active->descs[i];
|
struct overlay_desc *desc = &ol->active->descs[i];
|
||||||
|
|
||||||
desc->range_x_mod = desc->range_x;
|
desc->range_x_mod = desc->range_x_hitbox;
|
||||||
desc->range_y_mod = desc->range_y;
|
desc->range_y_mod = desc->range_y_hitbox;
|
||||||
|
|
||||||
if (desc->updated)
|
if (desc->updated != 0)
|
||||||
{
|
{
|
||||||
/* If pressed this frame, change the hitbox. */
|
/* If pressed this frame, change the hitbox. */
|
||||||
desc->range_x_mod *= desc->range_mod;
|
desc->range_x_mod *= desc->range_mod;
|
||||||
@ -1556,10 +1579,32 @@ void input_overlay_post_poll(
|
|||||||
}
|
}
|
||||||
|
|
||||||
input_overlay_update_desc_geom(ol, desc);
|
input_overlay_update_desc_geom(ol, desc);
|
||||||
desc->updated = false;
|
desc->updated = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void input_overlay_desc_init_hitbox(struct overlay_desc *desc)
|
||||||
|
{
|
||||||
|
desc->x_hitbox =
|
||||||
|
((desc->x_shift + desc->range_x * desc->reach_right) +
|
||||||
|
(desc->x_shift - desc->range_x * desc->reach_left)) / 2.0f;
|
||||||
|
|
||||||
|
desc->y_hitbox =
|
||||||
|
((desc->y_shift + desc->range_y * desc->reach_down) +
|
||||||
|
(desc->y_shift - desc->range_y * desc->reach_up)) / 2.0f;
|
||||||
|
|
||||||
|
desc->range_x_hitbox =
|
||||||
|
(desc->range_x * desc->reach_right +
|
||||||
|
desc->range_x * desc->reach_left) / 2.0f;
|
||||||
|
|
||||||
|
desc->range_y_hitbox =
|
||||||
|
(desc->range_y * desc->reach_down +
|
||||||
|
desc->range_y * desc->reach_up) / 2.0f;
|
||||||
|
|
||||||
|
desc->range_x_mod = desc->range_x_hitbox;
|
||||||
|
desc->range_y_mod = desc->range_y_hitbox;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* input_overlay_set_scale_factor:
|
* input_overlay_set_scale_factor:
|
||||||
* @ol : Overlay handle.
|
* @ol : Overlay handle.
|
||||||
@ -1644,6 +1689,8 @@ void input_overlay_scale(struct overlay *ol,
|
|||||||
desc->mod_h = 2.0f * scale_h;
|
desc->mod_h = 2.0f * scale_h;
|
||||||
desc->mod_x = adj_center_x - scale_w;
|
desc->mod_x = adj_center_x - scale_w;
|
||||||
desc->mod_y = adj_center_y - scale_h;
|
desc->mod_y = adj_center_y - scale_h;
|
||||||
|
|
||||||
|
input_overlay_desc_init_hitbox(desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1823,9 +1870,9 @@ void input_overlay_poll_clear(
|
|||||||
{
|
{
|
||||||
struct overlay_desc *desc = &ol->active->descs[i];
|
struct overlay_desc *desc = &ol->active->descs[i];
|
||||||
|
|
||||||
desc->range_x_mod = desc->range_x;
|
desc->range_x_mod = desc->range_x_hitbox;
|
||||||
desc->range_y_mod = desc->range_y;
|
desc->range_y_mod = desc->range_y_hitbox;
|
||||||
desc->updated = false;
|
desc->updated = 0;
|
||||||
|
|
||||||
desc->delta_x = 0.0f;
|
desc->delta_x = 0.0f;
|
||||||
desc->delta_y = 0.0f;
|
desc->delta_y = 0.0f;
|
||||||
@ -2078,7 +2125,7 @@ void input_poll_overlay(
|
|||||||
memset(&polled_data, 0, sizeof(struct input_overlay_state));
|
memset(&polled_data, 0, sizeof(struct input_overlay_state));
|
||||||
|
|
||||||
if (ol->enable)
|
if (ol->enable)
|
||||||
input_overlay_poll(ol, &polled_data, x, y, touch_scale);
|
input_overlay_poll(ol, &polled_data, i, x, y, touch_scale);
|
||||||
else
|
else
|
||||||
ol->blocked = false;
|
ol->blocked = false;
|
||||||
|
|
||||||
|
@ -144,8 +144,7 @@ struct overlay_desc
|
|||||||
enum overlay_hitbox hitbox;
|
enum overlay_hitbox hitbox;
|
||||||
enum overlay_type type;
|
enum overlay_type type;
|
||||||
|
|
||||||
bool updated;
|
uint16_t updated; /* one bit per pointer */
|
||||||
bool movable;
|
|
||||||
|
|
||||||
unsigned next_index;
|
unsigned next_index;
|
||||||
unsigned image_index;
|
unsigned image_index;
|
||||||
@ -167,6 +166,21 @@ struct overlay_desc
|
|||||||
float x_shift;
|
float x_shift;
|
||||||
float y_shift;
|
float y_shift;
|
||||||
|
|
||||||
|
/* These values are used only for hitbox
|
||||||
|
* detection. A hitbox can be stretched in
|
||||||
|
* any direction(s) by its 'reach' values */
|
||||||
|
float x_hitbox;
|
||||||
|
float y_hitbox;
|
||||||
|
float range_x_hitbox, range_y_hitbox;
|
||||||
|
float reach_right, reach_left, reach_up, reach_down;
|
||||||
|
|
||||||
|
/* If true, blocks input from overlapped hitboxes */
|
||||||
|
bool exclusive;
|
||||||
|
/* Similar, but only applies after range_mod takes affect */
|
||||||
|
bool range_mod_exclusive;
|
||||||
|
|
||||||
|
bool movable;
|
||||||
|
|
||||||
/* This is a retro_key value for keyboards */
|
/* This is a retro_key value for keyboards */
|
||||||
unsigned retro_key_idx;
|
unsigned retro_key_idx;
|
||||||
|
|
||||||
@ -332,7 +346,7 @@ void input_overlay_auto_rotate_(
|
|||||||
void input_overlay_poll(
|
void input_overlay_poll(
|
||||||
input_overlay_t *ol,
|
input_overlay_t *ol,
|
||||||
input_overlay_state_t *out,
|
input_overlay_state_t *out,
|
||||||
int16_t norm_x, int16_t norm_y, float touch_scale);
|
unsigned ptr_idx, int16_t norm_x, int16_t norm_y, float touch_scale);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* input_overlay_poll_clear:
|
* input_overlay_poll_clear:
|
||||||
|
@ -232,11 +232,12 @@ static bool task_overlay_load_desc(
|
|||||||
bool normalized, float alpha_mod, float range_mod)
|
bool normalized, float alpha_mod, float range_mod)
|
||||||
{
|
{
|
||||||
float width_mod, height_mod;
|
float width_mod, height_mod;
|
||||||
char conf_key[32];
|
char conf_key[64];
|
||||||
char overlay_desc_key[32];
|
char overlay_desc_key[32];
|
||||||
char overlay_desc_normalized_key[32];
|
char overlay_desc_normalized_key[32];
|
||||||
char overlay[256];
|
char overlay[256];
|
||||||
float tmp_float = 0.0f;
|
float tmp_float = 0.0f;
|
||||||
|
int tmp_int = 0;
|
||||||
bool tmp_bool = false;
|
bool tmp_bool = false;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
bool by_pixel = false;
|
bool by_pixel = false;
|
||||||
@ -403,6 +404,46 @@ static bool task_overlay_load_desc(
|
|||||||
desc->range_x = (float)strtod(list.elems[4].data, NULL) * width_mod;
|
desc->range_x = (float)strtod(list.elems[4].data, NULL) * width_mod;
|
||||||
desc->range_y = (float)strtod(list.elems[5].data, NULL) * height_mod;
|
desc->range_y = (float)strtod(list.elems[5].data, NULL) * height_mod;
|
||||||
|
|
||||||
|
snprintf(conf_key, sizeof(conf_key),
|
||||||
|
"overlay%u_desc%u_reach_right", ol_idx, desc_idx);
|
||||||
|
desc->reach_right = 1.0f;
|
||||||
|
if (config_get_float(conf, conf_key, &tmp_float))
|
||||||
|
desc->reach_right = tmp_float;
|
||||||
|
|
||||||
|
snprintf(conf_key, sizeof(conf_key),
|
||||||
|
"overlay%u_desc%u_reach_left", ol_idx, desc_idx);
|
||||||
|
desc->reach_left = 1.0f;
|
||||||
|
if (config_get_float(conf, conf_key, &tmp_float))
|
||||||
|
desc->reach_left = tmp_float;
|
||||||
|
|
||||||
|
snprintf(conf_key, sizeof(conf_key),
|
||||||
|
"overlay%u_desc%u_reach_up", ol_idx, desc_idx);
|
||||||
|
desc->reach_up = 1.0f;
|
||||||
|
if (config_get_float(conf, conf_key, &tmp_float))
|
||||||
|
desc->reach_up = tmp_float;
|
||||||
|
|
||||||
|
snprintf(conf_key, sizeof(conf_key),
|
||||||
|
"overlay%u_desc%u_reach_down", ol_idx, desc_idx);
|
||||||
|
desc->reach_down = 1.0f;
|
||||||
|
if (config_get_float(conf, conf_key, &tmp_float))
|
||||||
|
desc->reach_down = tmp_float;
|
||||||
|
|
||||||
|
snprintf(conf_key, sizeof(conf_key),
|
||||||
|
"overlay%u_desc%u_reach_x", ol_idx, desc_idx);
|
||||||
|
if (config_get_float(conf, conf_key, &tmp_float))
|
||||||
|
{
|
||||||
|
desc->reach_right = tmp_float;
|
||||||
|
desc->reach_left = tmp_float;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(conf_key, sizeof(conf_key),
|
||||||
|
"overlay%u_desc%u_reach_y", ol_idx, desc_idx);
|
||||||
|
if (config_get_float(conf, conf_key, &tmp_float))
|
||||||
|
{
|
||||||
|
desc->reach_up = tmp_float;
|
||||||
|
desc->reach_down = tmp_float;
|
||||||
|
}
|
||||||
|
|
||||||
desc->mod_x = desc->x - desc->range_x;
|
desc->mod_x = desc->x - desc->range_x;
|
||||||
desc->mod_w = 2.0f * desc->range_x;
|
desc->mod_w = 2.0f * desc->range_x;
|
||||||
desc->mod_y = desc->y - desc->range_y;
|
desc->mod_y = desc->y - desc->range_y;
|
||||||
@ -420,6 +461,16 @@ static bool task_overlay_load_desc(
|
|||||||
if (config_get_float(conf, conf_key, &tmp_float))
|
if (config_get_float(conf, conf_key, &tmp_float))
|
||||||
desc->range_mod = tmp_float;
|
desc->range_mod = tmp_float;
|
||||||
|
|
||||||
|
snprintf(conf_key, sizeof(conf_key),
|
||||||
|
"overlay%u_desc%u_exclusive", ol_idx, desc_idx);
|
||||||
|
desc->exclusive = false;
|
||||||
|
config_get_bool(conf, conf_key, &desc->exclusive);
|
||||||
|
|
||||||
|
snprintf(conf_key, sizeof(conf_key),
|
||||||
|
"overlay%u_desc%u_range_mod_exclusive", ol_idx, desc_idx);
|
||||||
|
desc->range_mod_exclusive = false;
|
||||||
|
config_get_bool(conf, conf_key, &desc->range_mod_exclusive);
|
||||||
|
|
||||||
snprintf(conf_key, sizeof(conf_key),
|
snprintf(conf_key, sizeof(conf_key),
|
||||||
"overlay%u_desc%u_movable", ol_idx, desc_idx);
|
"overlay%u_desc%u_movable", ol_idx, desc_idx);
|
||||||
desc->movable = false;
|
desc->movable = false;
|
||||||
@ -429,9 +480,6 @@ static bool task_overlay_load_desc(
|
|||||||
if (config_get_bool(conf, conf_key, &tmp_bool))
|
if (config_get_bool(conf, conf_key, &tmp_bool))
|
||||||
desc->movable = tmp_bool;
|
desc->movable = tmp_bool;
|
||||||
|
|
||||||
desc->range_x_mod = desc->range_x;
|
|
||||||
desc->range_y_mod = desc->range_y;
|
|
||||||
|
|
||||||
input_overlay->pos ++;
|
input_overlay->pos ++;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user