Add better click through semantics

This commit is contained in:
2026-05-21 08:55:27 +01:00
parent 2bff3eb93f
commit 72304ee925
6 changed files with 180 additions and 57 deletions
+10 -5
View File
@@ -10,6 +10,10 @@ enum Type { IMAGE,
TEXT,
RECT };
enum ClickMode { PASS,
BLOCK,
IGNORE };
namespace app {
struct Element {
Type type;
@@ -19,7 +23,7 @@ struct Element {
Vec2<float> scale = {1, 1};
float alpha = 1.0f;
float z = 0;
bool click_through = false;
ClickMode click_mode = ClickMode::BLOCK;
Ruby::Block on_click;
Element(Type type) : type(type) {}
@@ -191,11 +195,12 @@ struct Scene {
Vec2<float> size = e->size();
Rect rect = Rect::from(size);
if (rect.contains(world_to_local(position, e))) {
result.push_back(*it);
if (e->click_through)
continue;
else
if (e->click_mode == ClickMode::PASS) {
result.push_back(*it);
} else if (e->click_mode == ClickMode::BLOCK) {
result.push_back(*it);
break;
}
}
}
+132 -33
View File
@@ -320,7 +320,7 @@ static mrb_value ElementText_init(mrb_state *mrb, mrb_value self) {
float x = 0, y = 0, z = 0, rotation = 0;
float scale_x = 1, scale_y = 1, alpha = 1;
float pivot_x = 0.5, pivot_y = 0.5;
bool click_through = false;
mrb_sym click_mode_sym = sym_block;
if (!mrb_nil_p(kwargs)) {
mrb_value pos_hash = HASH_GET(kwargs, position);
if (!mrb_nil_p(pos_hash)) {
@@ -343,7 +343,10 @@ static mrb_value ElementText_init(mrb_state *mrb, mrb_value self) {
HASH_FLOAT(kwargs, z, z);
HASH_FLOAT(kwargs, rotation, rotation);
HASH_FLOAT(kwargs, alpha, alpha);
HASH_BOOL(kwargs, click_through, click_through);
mrb_value v = HASH_GET(kwargs, click_mode);
if (!mrb_nil_p(v)) {
click_mode_sym = mrb_symbol(v);
}
}
uint64_t id = get_id_Font(mrb, font_val);
@@ -362,7 +365,15 @@ static mrb_value ElementText_init(mrb_state *mrb, mrb_value self) {
element->pivot = {pivot_x, pivot_y};
element->alpha = alpha;
element->z = z;
element->click_through = click_through;
std::string click_mode = mrb_sym2name(mrb, click_mode_sym);
if (click_mode == "pass")
element->click_mode = ClickMode::PASS;
else if (click_mode == "block")
element->click_mode = ClickMode::BLOCK;
else if (click_mode == "ignore")
element->click_mode = ClickMode::IGNORE;
s->id = app::element_pool.acquire(element);
app::element_pool.use(s->id);
@@ -620,19 +631,41 @@ static mrb_value element_text_z_set(mrb_state *mrb, mrb_value self) {
return mrb_nil_value();
}
static mrb_value element_text_click_through_get(mrb_state *mrb, mrb_value self) {
static mrb_value element_text_click_mode_get(mrb_state *mrb, mrb_value self) {
uint64_t id = get_id_ElementText(mrb, self);
app::EText *element = (app::EText *)app::element_pool[id];
return mrb_bool_value(element->click_through);
std::string click_mode_str;
switch (element->click_mode) {
case ClickMode::PASS:
click_mode_str = "pass";
break;
case ClickMode::BLOCK:
click_mode_str = "block";
break;
case ClickMode::IGNORE:
click_mode_str = "ignore";
break;
}
return mrb_symbol_value(mrb_intern_cstr(mrb, click_mode_str.c_str()));
}
static mrb_value element_text_click_through_set(mrb_state *mrb, mrb_value self) {
mrb_bool click_through;
mrb_get_args(mrb, "b", &click_through);
static mrb_value element_text_click_mode_set(mrb_state *mrb, mrb_value self) {
mrb_sym click_mode_sym;
mrb_get_args(mrb, "n", &click_mode_sym);
uint64_t id = get_id_ElementText(mrb, self);
app::EText *element = (app::EText *)app::element_pool[id];
element->click_through = click_through;
std::string click_mode_str = mrb_sym2name(mrb, click_mode_sym);
if (click_mode_str == "pass")
element->click_mode = ClickMode::PASS;
else if (click_mode_str == "block")
element->click_mode = ClickMode::BLOCK;
else if (click_mode_str == "ignore")
element->click_mode = ClickMode::IGNORE;
return mrb_nil_value();
}
@@ -676,7 +709,7 @@ static mrb_value ElementRect_init(mrb_state *mrb, mrb_value self) {
float x = 0, y = 0, z = 0, rotation = 0;
float scale_x = 1, scale_y = 1, alpha = 1, pivot_x = 0.5, pivot_y = 0.5;
bool click_through = false;
mrb_sym click_mode_sym = sym_block;
if (!mrb_nil_p(kwargs)) {
mrb_value pos_hash = HASH_GET(kwargs, position);
if (!mrb_nil_p(pos_hash)) {
@@ -699,7 +732,10 @@ static mrb_value ElementRect_init(mrb_state *mrb, mrb_value self) {
HASH_FLOAT(kwargs, z, z);
HASH_FLOAT(kwargs, rotation, rotation);
HASH_FLOAT(kwargs, alpha, alpha);
HASH_BOOL(kwargs, click_through, click_through);
mrb_value v = HASH_GET(kwargs, click_mode);
if (!mrb_nil_p(v)) {
click_mode_sym = mrb_symbol(v);
}
}
Vec2<float> shape = {(float)w, (float)h};
@@ -720,7 +756,15 @@ static mrb_value ElementRect_init(mrb_state *mrb, mrb_value self) {
element->pivot = {pivot_x, pivot_y};
element->alpha = alpha;
element->z = z;
element->click_through = click_through;
std::string click_mode = mrb_sym2name(mrb, click_mode_sym);
if (click_mode == "pass")
element->click_mode = ClickMode::PASS;
else if (click_mode == "block")
element->click_mode = ClickMode::BLOCK;
else if (click_mode == "ignore")
element->click_mode = ClickMode::IGNORE;
s->id = app::element_pool.acquire(element);
app::element_pool.use(s->id);
@@ -946,19 +990,41 @@ static mrb_value element_rect_z_set(mrb_state *mrb, mrb_value self) {
return mrb_nil_value();
}
static mrb_value element_rect_click_through_get(mrb_state *mrb, mrb_value self) {
static mrb_value element_rect_click_mode_get(mrb_state *mrb, mrb_value self) {
uint64_t id = get_id_ElementRect(mrb, self);
app::ERect *element = (app::ERect *)app::element_pool[id];
return mrb_bool_value(element->click_through);
std::string click_mode_str;
switch (element->click_mode) {
case ClickMode::PASS:
click_mode_str = "pass";
break;
case ClickMode::BLOCK:
click_mode_str = "block";
break;
case ClickMode::IGNORE:
click_mode_str = "ignore";
break;
}
return mrb_symbol_value(mrb_intern_cstr(mrb, click_mode_str.c_str()));
}
static mrb_value element_rect_click_through_set(mrb_state *mrb, mrb_value self) {
mrb_bool click_through;
mrb_get_args(mrb, "b", &click_through);
static mrb_value element_rect_click_mode_set(mrb_state *mrb, mrb_value self) {
mrb_sym click_mode_sym;
mrb_get_args(mrb, "n", &click_mode_sym);
uint64_t id = get_id_ElementRect(mrb, self);
app::ERect *element = (app::ERect *)app::element_pool[id];
element->click_through = click_through;
std::string click_mode = mrb_sym2name(mrb, click_mode_sym);
if (click_mode == "pass")
element->click_mode = ClickMode::PASS;
else if (click_mode == "block")
element->click_mode = ClickMode::BLOCK;
else if (click_mode == "ignore")
element->click_mode = ClickMode::IGNORE;
return mrb_nil_value();
}
@@ -1001,7 +1067,7 @@ static mrb_value ElementImage_init(mrb_state *mrb, mrb_value self) {
float x = 0, y = 0, z = 0, rotation = 0;
float scale_x = 1, scale_y = 1, alpha = 1, pivot_x = 0.5, pivot_y = 0.5;
bool click_through = false;
mrb_sym click_mode_sym = sym_block;
if (!mrb_nil_p(kwargs)) {
mrb_value pos_hash = HASH_GET(kwargs, position);
if (!mrb_nil_p(pos_hash)) {
@@ -1024,7 +1090,10 @@ static mrb_value ElementImage_init(mrb_state *mrb, mrb_value self) {
HASH_FLOAT(kwargs, z, z);
HASH_FLOAT(kwargs, rotation, rotation);
HASH_FLOAT(kwargs, alpha, alpha);
HASH_BOOL(kwargs, click_through, click_through);
mrb_value v = HASH_GET(kwargs, click_mode);
if (!mrb_nil_p(v)) {
click_mode_sym = mrb_symbol(v);
}
}
uint64_t id = get_id_Animation(mrb, animation_val);
@@ -1036,7 +1105,15 @@ static mrb_value ElementImage_init(mrb_state *mrb, mrb_value self) {
element->pivot = {pivot_x, pivot_y};
element->alpha = alpha;
element->z = z;
element->click_through = click_through;
std::string click_mode = mrb_sym2name(mrb, click_mode_sym);
if (click_mode == "pass")
element->click_mode = ClickMode::PASS;
else if (click_mode == "block")
element->click_mode = ClickMode::BLOCK;
else if (click_mode == "ignore")
element->click_mode = ClickMode::IGNORE;
s->id = app::element_pool.acquire(element);
app::element_pool.use(s->id);
@@ -1245,19 +1322,41 @@ static mrb_value element_image_z_set(mrb_state *mrb, mrb_value self) {
return mrb_nil_value();
}
static mrb_value element_image_click_through_get(mrb_state *mrb, mrb_value self) {
static mrb_value element_image_click_mode_get(mrb_state *mrb, mrb_value self) {
uint64_t id = get_id_ElementImage(mrb, self);
app::EImage *element = (app::EImage *)app::element_pool[id];
return mrb_bool_value(element->click_through);
std::string click_mode_str;
switch (element->click_mode) {
case ClickMode::PASS:
click_mode_str = "pass";
break;
case ClickMode::BLOCK:
click_mode_str = "block";
break;
case ClickMode::IGNORE:
click_mode_str = "ignore";
break;
}
return mrb_symbol_value(mrb_intern_cstr(mrb, click_mode_str.c_str()));
}
static mrb_value element_image_click_through_set(mrb_state *mrb, mrb_value self) {
mrb_bool click_through;
mrb_get_args(mrb, "b", &click_through);
static mrb_value element_image_click_mode_set(mrb_state *mrb, mrb_value self) {
mrb_sym click_mode_sym;
mrb_get_args(mrb, "n", &click_mode_sym);
uint64_t id = get_id_ElementImage(mrb, self);
app::EImage *element = (app::EImage *)app::element_pool[id];
element->click_through = click_through;
std::string click_mode = mrb_sym2name(mrb, click_mode_sym);
if (click_mode == "pass")
element->click_mode = ClickMode::PASS;
else if (click_mode == "block")
element->click_mode = ClickMode::BLOCK;
else if (click_mode == "ignore")
element->click_mode = ClickMode::IGNORE;
return mrb_nil_value();
}
@@ -1697,8 +1796,8 @@ inline void setup() {
ADD_METHOD(ElementText, "alpha", element_text_alpha_get, MRB_ARGS_NONE());
ADD_METHOD(ElementText, "z=", element_text_z_set, MRB_ARGS_REQ(1));
ADD_METHOD(ElementText, "z", element_text_z_get, MRB_ARGS_NONE());
ADD_METHOD(ElementText, "click_through=", element_text_click_through_set, MRB_ARGS_REQ(1));
ADD_METHOD(ElementText, "click_through", element_text_click_through_get, MRB_ARGS_NONE());
ADD_METHOD(ElementText, "click_mode=", element_text_click_mode_set, MRB_ARGS_REQ(1));
ADD_METHOD(ElementText, "click_mode", element_text_click_mode_get, MRB_ARGS_NONE());
ADD_METHOD(ElementText, "width", element_text_width, MRB_ARGS_NONE());
ADD_METHOD(ElementText, "height", element_text_height, MRB_ARGS_NONE());
@@ -1727,8 +1826,8 @@ inline void setup() {
ADD_METHOD(ElementRect, "alpha", element_rect_alpha_get, MRB_ARGS_NONE());
ADD_METHOD(ElementRect, "z=", element_rect_z_set, MRB_ARGS_REQ(1));
ADD_METHOD(ElementRect, "z", element_rect_z_get, MRB_ARGS_NONE());
ADD_METHOD(ElementRect, "click_through=", element_rect_click_through_set, MRB_ARGS_REQ(1));
ADD_METHOD(ElementRect, "click_through", element_rect_click_through_get, MRB_ARGS_NONE());
ADD_METHOD(ElementRect, "click_mode=", element_rect_click_mode_set, MRB_ARGS_REQ(1));
ADD_METHOD(ElementRect, "click_mode", element_rect_click_mode_get, MRB_ARGS_NONE());
DEF_CLASS(ElementImage, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
ADD_METHOD(ElementImage, "on_click", element_image_on_click, MRB_ARGS_BLOCK());
@@ -1751,8 +1850,8 @@ inline void setup() {
ADD_METHOD(ElementImage, "alpha", element_image_alpha_get, MRB_ARGS_NONE());
ADD_METHOD(ElementImage, "z=", element_image_z_set, MRB_ARGS_REQ(1));
ADD_METHOD(ElementImage, "z", element_image_z_get, MRB_ARGS_NONE());
ADD_METHOD(ElementImage, "click_through=", element_image_click_through_set, MRB_ARGS_REQ(1));
ADD_METHOD(ElementImage, "click_through", element_image_click_through_get, MRB_ARGS_NONE());
ADD_METHOD(ElementImage, "click_mode=", element_image_click_mode_set, MRB_ARGS_REQ(1));
ADD_METHOD(ElementImage, "click_mode", element_image_click_mode_get, MRB_ARGS_NONE());
DEF_CLASS(Scene, MRB_ARGS_NONE());
ADD_METHOD(Scene, "==", scene_equal, MRB_ARGS_REQ(1));
+4 -1
View File
@@ -107,7 +107,10 @@ DEF_SYM(pivot)
DEF_SYM(scale)
DEF_SYM(alpha)
DEF_SYM(fps)
DEF_SYM(click_through)
DEF_SYM(click_mode)
DEF_SYM(pass)
DEF_SYM(block)
DEF_SYM(ignore)
DEF_SYM(call)
DEF_SYM(x)
DEF_SYM(y)