impl simple drag events

This commit is contained in:
BlackMATov
2020-05-13 07:19:39 +07:00
parent cd7c2c6260
commit 2622900dde
14 changed files with 369 additions and 252 deletions
+2 -14
View File
@@ -38,8 +38,6 @@ namespace e2d
class hover_over final {};
class hover_out final {};
class hover_enter final {};
class hover_leave final {};
public:
touchable() = default;
@@ -108,14 +106,6 @@ namespace e2d
class factory_loader<touchable::hover_out> final
: public empty_factory_loader<touchable::hover_out> {};
template <>
class factory_loader<touchable::hover_enter> final
: public empty_factory_loader<touchable::hover_enter> {};
template <>
class factory_loader<touchable::hover_leave> final
: public empty_factory_loader<touchable::hover_leave> {};
template <>
class factory_loader<events<touchable_events::event>> final
: public empty_factory_loader<events<touchable_events::event>> {};
@@ -223,14 +213,12 @@ namespace e2d::touchable_events
public:
ENUM_HPP_CLASS_DECL(types, u8,
(over)
(out)
(enter)
(leave))
(out))
public:
mouse_hover_evt(
gobject target,
types type)
: base_evt(target, type == types::over || type == types::out)
: base_evt(target, true)
, type_(type) {}
[[nodiscard]] types type() const noexcept { return type_; }
@@ -30,12 +30,6 @@ local touchable = {
---@type boolean
hover_out = false,
---@type boolean
hover_enter = false,
---@type boolean
hover_leave = false,
---@type boolean
bubbling = true,
@@ -13,6 +13,13 @@ end
---@param type string
---@param event touchable_event
function M:on_event(go, type, event)
if type == "touchable.mouse_hover_evt" then
the_debug:trace(string.format("event: %q\n-->type: %q\n-->target: %q",
type,
event.type,
event.target.named and event.target.named.name or "[unnamed]"))
end
if type == "touchable.mouse_drag_evt" then
the_debug:trace(string.format("event: %q\n-->type: %q\n-->target: %q\n-->local_point: %s\n-->world_point: %s",
type,
@@ -154,32 +154,6 @@ namespace e2d::bindings::high
}
),
"hover_enter", sol::property(
[](const gcomponent<touchable>& c) -> bool {
return c.component<touchable::hover_enter>().exists();
},
[](gcomponent<touchable>& c, bool yesno){
if ( yesno ) {
c.component<touchable::hover_enter>().ensure();
} else {
c.component<touchable::hover_enter>().remove();
}
}
),
"hover_leave", sol::property(
[](const gcomponent<touchable>& c) -> bool {
return c.component<touchable::hover_leave>().exists();
},
[](gcomponent<touchable>& c, bool yesno){
if ( yesno ) {
c.component<touchable::hover_leave>().ensure();
} else {
c.component<touchable::hover_leave>().remove();
}
}
),
"bubbling", sol::property(
[](const gcomponent<touchable>& c) -> bool {
return c->bubbling();
@@ -166,34 +166,6 @@ namespace e2d
ImGui::Separator();
//
// hover_enter/hover_leave
//
if ( bool hover_enter = c.component<touchable::hover_enter>().exists();
ImGui::Checkbox("hover_enter", &hover_enter) )
{
if ( hover_enter ) {
c.component<touchable::hover_enter>().ensure();
} else {
c.component<touchable::hover_enter>().remove();
}
}
ImGui::SameLine();
if ( bool hover_leave = c.component<touchable::hover_leave>().exists();
ImGui::Checkbox("hover_leave", &hover_leave) )
{
if ( hover_leave ) {
c.component<touchable::hover_leave>().ensure();
} else {
c.component<touchable::hover_leave>().remove();
}
}
ImGui::Separator();
//
// bubbling/capturing
//
-4
View File
@@ -241,8 +241,6 @@ namespace e2d
.register_component<touchable::released>("touchable.released")
.register_component<touchable::hover_over>("touchable.hover_over")
.register_component<touchable::hover_out>("touchable.hover_out")
.register_component<touchable::hover_enter>("touchable.hover_enter")
.register_component<touchable::hover_leave>("touchable.hover_leave")
.register_component<events<touchable_events::event>>("touchable.events")
.register_component<widget>("widget")
.register_component<widget::dirty>("widget.dirty")
@@ -287,8 +285,6 @@ namespace e2d
//.register_component<touchable::released>("touchable.released")
//.register_component<touchable::hover_over>("touchable.hover_over")
//.register_component<touchable::hover_out>("touchable.hover_out")
//.register_component<touchable::hover_enter>("touchable.hover_enter")
//.register_component<touchable::hover_leave>("touchable.hover_leave")
//.register_component<events<touchable_events::event>>("touchable.events")
.register_component<widget>("widget")
//.register_component<widget::dirty>("widget.dirty")
@@ -28,7 +28,7 @@ namespace e2d
internal_state(input& i, window& w)
: input_(i)
, window_(w)
, collector_(window_.register_event_listener<collector>(i)) {}
, collector_(window_.register_event_listener<collector>(i, w)) {}
~internal_state() noexcept {
window_.unregister_event_listener(collector_);
@@ -25,8 +25,16 @@ namespace e2d::touch_system_impl
namespace e2d::touch_system_impl
{
struct touchable_under_mouse final {
gobject input_camera;
v2f local_point{v2f::zero()};
v2f world_point{v2f::zero()};
touchable_under_mouse(
gobject input_camera,
const v2f& local_point,
const v2f& world_point)
: input_camera(input_camera)
, local_point(local_point)
, world_point(world_point) {}
};
struct world_space_collider_base {
@@ -8,8 +8,9 @@
namespace e2d::touch_system_impl
{
collector::collector(input& i)
: input_(i) {}
collector::collector(input& i,window& w)
: input_(i)
, window_(w) {}
void collector::clear() noexcept {
events_.clear();
@@ -42,12 +43,14 @@ namespace e2d::touch_system_impl
void collector::on_move_cursor(const v2f& pos) noexcept {
E2D_UNUSED(pos);
events_.push_back(mouse_move_event(
window_,
input_.mouse().cursor_pos()));
}
void collector::on_mouse_scroll(const v2f& delta) noexcept {
E2D_UNUSED(delta);
events_.push_back(mouse_scroll_event(
window_,
input_.mouse().cursor_pos(),
input_.mouse().scroll_delta()));
}
@@ -62,6 +65,7 @@ namespace e2d::touch_system_impl
}
events_.push_back(mouse_button_event(
window_,
input_.mouse().cursor_pos(),
button,
action));
@@ -13,24 +13,29 @@ namespace e2d::touch_system_impl
class collector final : public window::event_listener {
public:
struct mouse_event {
window& event_window;
v2f screen_point{v2f::zero()};
mouse_event(
window& w,
const v2f& screen_point)
: screen_point(screen_point) {}
: event_window(w)
, screen_point(screen_point) {}
};
struct mouse_move_event : mouse_event {
mouse_move_event(
window& w,
const v2f& screen_point)
: mouse_event(screen_point) {}
: mouse_event(w, screen_point) {}
};
struct mouse_scroll_event : mouse_event {
v2f delta{v2f::zero()};
mouse_scroll_event(
window& w,
const v2f& screen_point,
const v2f& delta)
: mouse_event(screen_point)
: mouse_event(w, screen_point)
, delta(delta) {}
};
@@ -38,10 +43,11 @@ namespace e2d::touch_system_impl
mouse_button button{mouse_button::unknown};
mouse_button_action action{mouse_button_action::unknown};
mouse_button_event(
window& w,
const v2f& screen_point,
mouse_button button,
mouse_button_action action)
: mouse_event(screen_point)
: mouse_event(w, screen_point)
, button(button)
, action(action) {}
};
@@ -52,7 +58,7 @@ namespace e2d::touch_system_impl
mouse_button_event>;
using events = vector<event>;
public:
collector(input& i);
collector(input& i, window& w);
void clear() noexcept;
@@ -75,6 +81,7 @@ namespace e2d::touch_system_impl
mouse_button_action action) noexcept final;
private:
input& input_;
window& window_;
vector<event> events_;
};
}
@@ -174,17 +174,28 @@ namespace e2d::touch_system_impl
void update_world_space_colliders_under_mouse(input& input, window& window, ecs::registry& owner) {
owner.remove_all_components<touchable_under_mouse>();
owner.for_joined_components<camera::input, camera>([&input, &window, &owner](
const auto camera_comp = [](const auto& l, const auto& r) noexcept {
return std::get<camera>(l).depth() >= std::get<camera>(r).depth();
};
const auto camera_func = [&input, &window, &owner](
const ecs::const_entity&,
const camera::input&,
const camera& camera)
const camera& camera,
const actor& camera_a)
{
const v2u& target_size = camera.target()
? camera.target()->size()
: window.framebuffer_size();
if ( camera.target() ) {
return;
}
const gobject camera_go = camera_a.node() ? camera_a.node()->owner() : gobject();
if ( !camera_go ) {
return;
}
const v2f& mouse_p = math::normalized_to_point(
b2f(target_size.cast_to<f32>()),
b2f(window.framebuffer_size().cast_to<f32>()),
math::point_to_normalized(
b2f(window.real_size().cast_to<f32>()),
input.mouse().cursor_pos()));
@@ -193,32 +204,53 @@ namespace e2d::touch_system_impl
camera.view() * camera.projection();
const b2f& camera_viewport = b2f(
camera.viewport().position * target_size.cast_to<f32>(),
camera.viewport().size * target_size.cast_to<f32>());
camera.viewport().position * window.framebuffer_size().cast_to<f32>(),
camera.viewport().size * window.framebuffer_size().cast_to<f32>());
if ( !math::inside(camera_viewport, mouse_p) ) {
return;
}
impl::update_world_space_colliders_under_mouse<world_space_rect_collider>(
owner,
mouse_p,
camera_vp,
camera_viewport);
const auto under_mouse_func = [
&camera_go
](ecs::entity e, const v2f& local_point, const v2f& world_point){
if ( e.exists_component<touchable_under_mouse>() ) {
return;
}
e.ensure_component<touchable_under_mouse>(
camera_go,
local_point,
world_point);
};
impl::update_world_space_colliders_under_mouse<world_space_circle_collider>(
impl::for_world_space_colliders_under_mouse<world_space_rect_collider>(
owner,
mouse_p,
camera_vp,
camera_viewport);
camera_viewport,
under_mouse_func);
impl::update_world_space_colliders_under_mouse<world_space_polygon_collider>(
impl::for_world_space_colliders_under_mouse<world_space_circle_collider>(
owner,
mouse_p,
camera_vp,
camera_viewport);
}, !ecs::exists_any<
disabled<actor>,
disabled<camera>>());
camera_viewport,
under_mouse_func);
impl::for_world_space_colliders_under_mouse<world_space_polygon_collider>(
owner,
mouse_p,
camera_vp,
camera_viewport,
under_mouse_func);
};
ecsex::for_extracted_sorted_components<camera::input, camera, actor>(
owner,
camera_comp,
camera_func,
!ecs::exists_any<
disabled<actor>,
disabled<camera>>());
}
}
@@ -81,12 +81,13 @@ namespace e2d::touch_system_impl
const m4f& camera_vp,
const b2f& camera_viewport);
template < typename WorldSpaceCollider >
void update_world_space_colliders_under_mouse(
template < typename WorldSpaceCollider, typename F >
void for_world_space_colliders_under_mouse(
ecs::registry& owner,
const v2f& mouse_p,
const m4f& camera_vp,
const b2f& camera_viewport)
const b2f& camera_viewport,
F&& f)
{
using world_space_collider_t = WorldSpaceCollider;
using local_space_collider_t = typename WorldSpaceCollider::local_space_collider_t;
@@ -100,7 +101,8 @@ namespace e2d::touch_system_impl
&mouse_p = mouse_p,
&camera_vp = camera_vp,
&inv_camera_vp = inv_camera_vp,
&camera_viewport = camera_viewport
&camera_viewport = camera_viewport,
&f = f
](ecs::entity e, const touchable&, const world_space_collider_t& c){
if ( is_world_space_collider_under_mouse(c, mouse_p, camera_vp, camera_viewport) ) {
const auto& [world_point, world_point_success] = math::unproject(
@@ -119,11 +121,9 @@ namespace e2d::touch_system_impl
return;
}
touchable_under_mouse& under_mouse_c
= e.ensure_component<touchable_under_mouse>();
const v2f& local_point = v2f(v4f(world_point, 1.f) * world_to_local);
under_mouse_c.world_point = v2f(world_point);
under_mouse_c.local_point = v2f(v4f(world_point, 1.f) * world_to_local);
std::invoke(f, e, v2f(local_point), v2f(world_point));
}
}, !ecs::exists_any<
disabled<touchable>,
@@ -13,6 +13,56 @@ namespace
using namespace e2d;
using namespace e2d::touch_system_impl;
std::pair<v2f, bool> screen_to_world_point(
const gobject& input_camera,
const collector::mouse_event& event)
{
if ( !input_camera || !input_camera.component<camera>() ) {
return {v2f::zero(), false};
}
const camera& cam = *input_camera.component<camera>();
const v2f& mouse_p = math::normalized_to_point(
b2f(event.event_window.framebuffer_size().cast_to<f32>()),
math::point_to_normalized(
b2f(event.event_window.real_size().cast_to<f32>()),
event.screen_point));
const m4f& cam_vp =
cam.view() * cam.projection();
const b2f& cam_viewport = b2f(
cam.viewport().position * event.event_window.framebuffer_size().cast_to<f32>(),
cam.viewport().size * event.event_window.framebuffer_size().cast_to<f32>());
const auto [inv_cam_vp, inv_cam_vp_success] = math::inversed(cam_vp, 0.f);
if ( !inv_cam_vp_success ) {
return {v2f::zero(), false};
}
const auto& [world_point, world_point_success] = math::unproject(
v3f(mouse_p, 0.f),
inv_cam_vp,
cam_viewport);
return std::make_pair(v2f(world_point), world_point_success);
}
}
namespace
{
using namespace e2d;
using namespace e2d::touch_system_impl;
void apply_event(
gobject target,
const touchable_events::mouse_drag_evt& event)
{
target.component<events<touchable_events::event>>().ensure()
.add(event);
}
void apply_event(
gobject target,
const touchable_events::mouse_move_evt& event)
@@ -35,12 +85,6 @@ namespace
case touchable_events::mouse_hover_evt::types::out:
target.component<touchable::hover_out>().ensure();
break;
case touchable_events::mouse_hover_evt::types::enter:
target.component<touchable::hover_enter>().ensure();
break;
case touchable_events::mouse_hover_evt::types::leave:
target.component<touchable::hover_leave>().ensure();
break;
default:
E2D_ASSERT_MSG(false, "unexpected mouse hover event type");
break;
@@ -88,7 +132,7 @@ namespace
using namespace e2d;
using namespace e2d::touch_system_impl;
gobject find_event_target(const ecs::registry& owner) {
gobject find_current_target(const ecs::registry& owner) {
static thread_local vector<std::tuple<
ecs::const_entity,
scene,
@@ -239,79 +283,134 @@ namespace
using namespace e2d;
using namespace e2d::touch_system_impl;
void process_event(
gobject target,
hovering_info_opt process_hover_target(
ecs::registry& owner,
gobject current_target,
hovering_info_opt hovering,
dragging_info_opt dragging)
{
E2D_UNUSED(owner, dragging);
using namespace touchable_events;
if ( gobject last_target = hovering ? hovering->target : gobject();
last_target != current_target )
{
if ( last_target ) {
dispatch_event(last_target, mouse_hover_evt(
last_target,
mouse_hover_evt::types::out));
last_target.component<touchable::hovering>().remove();
}
if ( current_target ) {
const bool captured = dispatch_event(current_target, mouse_hover_evt(
current_target,
mouse_hover_evt::types::over));
if ( captured ) {
current_target.component<touchable::hovering>().ensure();
}
}
}
const_gcomponent<touchable_under_mouse> current_target_under_mouse{current_target};
return current_target_under_mouse && current_target_under_mouse->input_camera
? std::make_optional<hovering_info>(
current_target,
current_target_under_mouse->input_camera)
: std::nullopt;
}
}
namespace
{
using namespace e2d;
using namespace e2d::touch_system_impl;
void process_hovering_target_event(
ecs::registry& owner,
const hovering_info_opt& hovering,
const dragging_info_opt& dragging,
const collector::mouse_move_event& event)
{
E2D_UNUSED(owner, event);
E2D_UNUSED(owner, dragging, event);
const_gcomponent<touchable_under_mouse> under_mouse = hovering
? hovering->target
: const_gcomponent<touchable_under_mouse>();
const_gcomponent<touchable_under_mouse> under_mouse{target};
if ( !under_mouse ) {
return;
}
dispatch_event(
target,
hovering->target,
touchable_events::mouse_move_evt(
target,
hovering->target,
under_mouse->local_point,
under_mouse->world_point));
}
void process_event(
gobject target,
void process_hovering_target_event(
ecs::registry& owner,
const hovering_info_opt& hovering,
const dragging_info_opt& dragging,
const collector::mouse_scroll_event& event)
{
E2D_UNUSED(owner);
E2D_UNUSED(owner, dragging);
using namespace touchable_events;
const_gcomponent<touchable_under_mouse> under_mouse = hovering
? hovering->target
: const_gcomponent<touchable_under_mouse>();
const_gcomponent<touchable_under_mouse> under_mouse{target};
if ( !under_mouse ) {
return;
}
dispatch_event(
target,
touchable_events::mouse_scroll_evt(
target,
hovering->target,
mouse_scroll_evt(
hovering->target,
event.delta,
under_mouse->local_point,
under_mouse->world_point));
}
void process_event(
gobject target,
void process_hovering_target_event(
ecs::registry& owner,
const hovering_info_opt& hovering,
const dragging_info_opt& dragging,
const collector::mouse_button_event& event)
{
E2D_UNUSED(owner, dragging);
using namespace touchable_events;
gobject current_target = hovering ? hovering->target : gobject();
const_gcomponent<touchable_under_mouse> under_mouse{current_target};
const auto make_mouse_button_evt = [
&event,
&target
](touchable_events::mouse_button_evt::types type){
touchable_under_mouse& under_mouse =
*target.component<touchable_under_mouse>();
return touchable_events::mouse_button_evt(
target,
&under_mouse,
&current_target
](mouse_button_evt::types type){
return mouse_button_evt(
current_target,
type,
event.button,
under_mouse.local_point,
under_mouse.world_point);
under_mouse->local_point,
under_mouse->world_point);
};
if ( event.action == mouse_button_action::press ) {
const_gcomponent<touchable_under_mouse> under_mouse{target};
if ( under_mouse ) {
using namespace touchable_events;
const bool captured = dispatch_event(
target,
current_target,
make_mouse_button_evt(mouse_button_evt::types::pressed));
if ( captured && event.button == mouse_button::left ) {
target.component<touchable::pushing>().ensure();
current_target.component<touchable::pushing>().ensure();
}
}
}
@@ -321,19 +420,15 @@ namespace
owner.remove_all_components<touchable::pushing>();
});
const_gcomponent<touchable_under_mouse> under_mouse{target};
if ( under_mouse ) {
using namespace touchable_events;
const bool captured = dispatch_event(
target,
current_target,
make_mouse_button_evt(mouse_button_evt::types::released));
if ( captured && event.button == mouse_button::left ) {
if ( target.component<touchable::pushing>() ) {
if ( current_target.component<touchable::pushing>() ) {
dispatch_event(
target,
current_target,
make_mouse_button_evt(mouse_button_evt::types::clicked));
}
}
@@ -347,92 +442,110 @@ namespace
using namespace e2d;
using namespace e2d::touch_system_impl;
void process_new_hover_target(
gobject target,
gobject last_target,
ecs::registry& owner)
dragging_info_opt process_dragging_target_event(
ecs::registry& owner,
hovering_info_opt hovering,
dragging_info_opt dragging,
const collector::mouse_move_event& event)
{
struct touchable_last_hover final {};
struct touchable_next_hover final {};
E2D_UNUSED(owner, hovering);
using namespace touchable_events;
E2D_DEFER([&owner](){
owner.remove_all_components<touchable_next_hover>();
});
if ( !dragging || !dragging->target || !dragging->camera ) {
return std::nullopt;
}
if ( target ) {
if ( auto target_n = target.component<actor>()->node() ) {
nodes::for_extracted_components_from_parents<touchable>(target_n, [
](const const_gcomponent<touchable>& parent){
const bool parent_disabled = ecs::exists_any<
disabled<actor>,
disabled<touchable>
>()(parent.owner().raw_entity());
const auto& [world_point, world_point_success] = screen_to_world_point(
dragging->camera,
event);
if ( !parent_disabled ) {
parent.owner().component<touchable_next_hover>().ensure();
if ( !world_point_success ) {
return std::nullopt;
}
const_gcomponent<actor> dragging_target_a{dragging->target};
if ( !dragging_target_a || !dragging_target_a->node() ) {
return std::nullopt;
}
v2f local_point = v2f(dragging_target_a->node()->world_to_local(
v4f(world_point, 0.f, 1.f)));
dispatch_event(dragging->target, mouse_drag_evt(
dragging->target,
mouse_drag_evt::types::move,
local_point,
world_point));
return dragging;
}
dragging_info_opt process_dragging_target_event(
ecs::registry& owner,
hovering_info_opt hovering,
dragging_info_opt dragging,
const collector::mouse_scroll_event& event)
{
E2D_UNUSED(owner, hovering, dragging, event);
return dragging;
}
dragging_info_opt process_dragging_target_event(
ecs::registry& owner,
hovering_info_opt hovering,
dragging_info_opt dragging,
const collector::mouse_button_event& event)
{
E2D_UNUSED(hovering);
using namespace touchable_events;
if ( event.action == mouse_button_action::press ) {
gobject current_target = hovering ? hovering->target : gobject();
const_gcomponent<touchable_under_mouse> under_mouse{current_target};
if ( under_mouse ) {
const bool captured = dispatch_event(current_target, mouse_drag_evt(
current_target,
mouse_drag_evt::types::start,
under_mouse->local_point,
under_mouse->world_point));
if ( captured && event.button == mouse_button::left ) {
current_target.component<touchable::dragging>().ensure();
dragging = std::make_optional<dragging_info>(
current_target,
under_mouse->input_camera);
}
}
}
if ( event.action == mouse_button_action::release ) {
E2D_DEFER([&owner, &dragging](){
dragging.reset();
owner.remove_all_components<touchable::dragging>();
});
if ( dragging && dragging->target && dragging->camera ) {
const auto& [world_point, world_point_success] = screen_to_world_point(
dragging->camera,
event);
if ( world_point_success ) {
const_gcomponent<actor> dragging_target_a{dragging->target};
if ( dragging_target_a && dragging_target_a->node() ) {
v2f local_point = v2f(dragging_target_a->node()->world_to_local(
v4f(world_point, 0.f, 1.f)));
dispatch_event(dragging->target, mouse_drag_evt(
dragging->target,
mouse_drag_evt::types::end,
local_point,
world_point));
}
}, nodes::options()
.recursive(true)
.include_root(true));
}
}
owner.for_joined_components<touchable, actor>([
](ecs::entity e, const touchable&, const actor& a){
using namespace touchable_events;
const auto need_hover_leave =
ecs::exists<touchable_last_hover>() &&
!ecs::exists<touchable_next_hover>();
if ( need_hover_leave(e) && a.node() ) {
dispatch_event(
a.node()->owner(),
mouse_hover_evt(
a.node()->owner(),
mouse_hover_evt::types::leave));
e.remove_component<touchable_last_hover>();
}
const auto need_hover_enter =
!ecs::exists<touchable_last_hover>() &&
ecs::exists<touchable_next_hover>();
if ( need_hover_enter(e) && a.node() ) {
const bool captured = dispatch_event(
a.node()->owner(),
mouse_hover_evt(
a.node()->owner(),
mouse_hover_evt::types::enter));
if ( captured ) {
e.ensure_component<touchable_last_hover>();
}
}
});
if ( target != last_target ) {
using namespace touchable_events;
if ( last_target ) {
dispatch_event(last_target, mouse_hover_evt(
last_target,
mouse_hover_evt::types::out));
last_target.component<touchable::hovering>().remove();
}
if ( target ) {
const bool captured = dispatch_event(target, mouse_hover_evt(
target,
mouse_hover_evt::types::over));
if ( captured ) {
target.component<touchable::hovering>().ensure();
}
}
}
return dragging;
}
}
@@ -452,32 +565,34 @@ namespace e2d::touch_system_impl
owner.remove_all_components<touchable::hover_over>();
owner.remove_all_components<touchable::hover_out>();
owner.remove_all_components<touchable::hover_enter>();
owner.remove_all_components<touchable::hover_leave>();
owner.for_each_component<events<touchable_events::event>>([
](const ecs::const_entity&, events<touchable_events::event>& es) {
es.clear();
});
gobject target = find_event_target(owner);
process_new_hover_target(target, last_target_, owner);
gobject target = find_current_target(owner);
if ( target != last_target_ ) {
last_target_ = target;
}
hovering_ = process_hover_target(
owner,
target,
hovering_,
dragging_);
for ( const auto& event : collector ) {
std::visit(utils::overloaded {
[](std::monostate){},
[&owner, &target](const collector::mouse_move_event& event){
process_event(target, owner, event);
},
[&owner, &target](const collector::mouse_scroll_event& event){
process_event(target, owner, event);
},
[&owner, &target](const collector::mouse_button_event& event){
process_event(target, owner, event);
[this, &owner](const auto& event){
process_hovering_target_event(
owner,
hovering_,
dragging_,
event);
dragging_ = process_dragging_target_event(
owner,
hovering_,
dragging_,
event);
}
}, event);
}
@@ -10,6 +10,25 @@
namespace e2d::touch_system_impl
{
struct hovering_info {
gobject target;
gobject camera;
hovering_info(gobject target, gobject camera)
: target(std::move(target))
, camera(std::move(camera)) {}
};
struct dragging_info {
gobject target;
gobject camera;
dragging_info(gobject target, gobject camera)
: target(std::move(target))
, camera(std::move(camera)) {}
};
using hovering_info_opt = std::optional<hovering_info>;
using dragging_info_opt = std::optional<dragging_info>;
class dispatcher final {
public:
dispatcher() = default;
@@ -18,6 +37,7 @@ namespace e2d::touch_system_impl
collector& collector,
ecs::registry& owner);
private:
gobject last_target_;
hovering_info_opt hovering_;
dragging_info_opt dragging_;
};
}