mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 16:09:47 +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,
|
||||
* abort. */
|
||||
desc->updated = false;
|
||||
desc->updated = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
all_buttons_pressed = true;
|
||||
desc->updated = true;
|
||||
desc->updated = 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_ABXY_AREA:
|
||||
return desc->updated;
|
||||
return (desc->updated != 0);
|
||||
|
||||
case OVERLAY_TYPE_KEYBOARD:
|
||||
if (ol_state ?
|
||||
OVERLAY_GET_KEY(ol_state, desc->retro_key_idx) :
|
||||
input_state_internal(port, RETRO_DEVICE_KEYBOARD, 0, desc->retro_key_idx))
|
||||
{
|
||||
desc->updated = true;
|
||||
desc->updated = 1;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@ -1394,16 +1394,16 @@ static bool inside_hitbox(const struct overlay_desc *desc, float x, float y)
|
||||
{
|
||||
case OVERLAY_HITBOX_RADIAL:
|
||||
{
|
||||
/* Ellipsis. */
|
||||
float x_dist = (x - desc->x_shift) / desc->range_x_mod;
|
||||
float y_dist = (y - desc->y_shift) / desc->range_y_mod;
|
||||
/* Ellipse. */
|
||||
float x_dist = (x - desc->x_hitbox) / desc->range_x_mod;
|
||||
float y_dist = (y - desc->y_hitbox) / desc->range_y_mod;
|
||||
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_shift) <= desc->range_x_mod) &&
|
||||
(fabs(y - desc->y_shift) <= desc->range_y_mod);
|
||||
(fabs(x - desc->x_hitbox) <= desc->range_x_mod) &&
|
||||
(fabs(y - desc->y_hitbox) <= desc->range_y_mod);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1411,6 +1411,7 @@ static bool inside_hitbox(const struct overlay_desc *desc, float x, float y)
|
||||
/**
|
||||
* input_overlay_poll:
|
||||
* @out : Polled output data.
|
||||
* @ptr_idx : Pointer index
|
||||
* @norm_x : Normalized X 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(
|
||||
input_overlay_t *ol,
|
||||
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,
|
||||
* like RETRO_DEVICE_POINTER. */
|
||||
@ -1443,14 +1446,34 @@ void input_overlay_poll(
|
||||
{
|
||||
float x_dist, y_dist;
|
||||
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))
|
||||
continue;
|
||||
|
||||
desc->updated = true;
|
||||
x_dist = x - desc->x_shift;
|
||||
y_dist = y - desc->y_shift;
|
||||
/* Check for exclusive hitbox, which blocks other input.
|
||||
* range_mod_exclusive has priority over exclusive. */
|
||||
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)
|
||||
{
|
||||
@ -1538,10 +1561,10 @@ void input_overlay_post_poll(
|
||||
{
|
||||
struct overlay_desc *desc = &ol->active->descs[i];
|
||||
|
||||
desc->range_x_mod = desc->range_x;
|
||||
desc->range_y_mod = desc->range_y;
|
||||
desc->range_x_mod = desc->range_x_hitbox;
|
||||
desc->range_y_mod = desc->range_y_hitbox;
|
||||
|
||||
if (desc->updated)
|
||||
if (desc->updated != 0)
|
||||
{
|
||||
/* If pressed this frame, change the hitbox. */
|
||||
desc->range_x_mod *= desc->range_mod;
|
||||
@ -1556,10 +1579,32 @@ void input_overlay_post_poll(
|
||||
}
|
||||
|
||||
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:
|
||||
* @ol : Overlay handle.
|
||||
@ -1644,6 +1689,8 @@ void input_overlay_scale(struct overlay *ol,
|
||||
desc->mod_h = 2.0f * scale_h;
|
||||
desc->mod_x = adj_center_x - scale_w;
|
||||
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];
|
||||
|
||||
desc->range_x_mod = desc->range_x;
|
||||
desc->range_y_mod = desc->range_y;
|
||||
desc->updated = false;
|
||||
desc->range_x_mod = desc->range_x_hitbox;
|
||||
desc->range_y_mod = desc->range_y_hitbox;
|
||||
desc->updated = 0;
|
||||
|
||||
desc->delta_x = 0.0f;
|
||||
desc->delta_y = 0.0f;
|
||||
@ -2078,7 +2125,7 @@ void input_poll_overlay(
|
||||
memset(&polled_data, 0, sizeof(struct input_overlay_state));
|
||||
|
||||
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
|
||||
ol->blocked = false;
|
||||
|
||||
|
@ -144,8 +144,7 @@ struct overlay_desc
|
||||
enum overlay_hitbox hitbox;
|
||||
enum overlay_type type;
|
||||
|
||||
bool updated;
|
||||
bool movable;
|
||||
uint16_t updated; /* one bit per pointer */
|
||||
|
||||
unsigned next_index;
|
||||
unsigned image_index;
|
||||
@ -167,6 +166,21 @@ struct overlay_desc
|
||||
float x_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 */
|
||||
unsigned retro_key_idx;
|
||||
|
||||
@ -332,7 +346,7 @@ void input_overlay_auto_rotate_(
|
||||
void input_overlay_poll(
|
||||
input_overlay_t *ol,
|
||||
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:
|
||||
|
@ -232,11 +232,12 @@ static bool task_overlay_load_desc(
|
||||
bool normalized, float alpha_mod, float range_mod)
|
||||
{
|
||||
float width_mod, height_mod;
|
||||
char conf_key[32];
|
||||
char conf_key[64];
|
||||
char overlay_desc_key[32];
|
||||
char overlay_desc_normalized_key[32];
|
||||
char overlay[256];
|
||||
float tmp_float = 0.0f;
|
||||
int tmp_int = 0;
|
||||
bool tmp_bool = false;
|
||||
bool ret = true;
|
||||
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_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_w = 2.0f * desc->range_x;
|
||||
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))
|
||||
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),
|
||||
"overlay%u_desc%u_movable", ol_idx, desc_idx);
|
||||
desc->movable = false;
|
||||
@ -429,9 +480,6 @@ static bool task_overlay_load_desc(
|
||||
if (config_get_bool(conf, conf_key, &tmp_bool))
|
||||
desc->movable = tmp_bool;
|
||||
|
||||
desc->range_x_mod = desc->range_x;
|
||||
desc->range_y_mod = desc->range_y;
|
||||
|
||||
input_overlay->pos ++;
|
||||
|
||||
end:
|
||||
|
Loading…
Reference in New Issue
Block a user