diff --git a/headers/enduro2d/high/components/touchable.hpp b/headers/enduro2d/high/components/touchable.hpp index a8aea924..2782a440 100644 --- a/headers/enduro2d/high/components/touchable.hpp +++ b/headers/enduro2d/high/components/touchable.hpp @@ -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 final : public empty_factory_loader {}; - template <> - class factory_loader final - : public empty_factory_loader {}; - - template <> - class factory_loader final - : public empty_factory_loader {}; - template <> class factory_loader> final : public empty_factory_loader> {}; @@ -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_; } diff --git a/samples/bin/library/scripts/emmy/components/touchable.lua b/samples/bin/library/scripts/emmy/components/touchable.lua index e890a369..bfdf12d6 100644 --- a/samples/bin/library/scripts/emmy/components/touchable.lua +++ b/samples/bin/library/scripts/emmy/components/touchable.lua @@ -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, diff --git a/samples/bin/library/scripts/sample_10/sample_10.lua b/samples/bin/library/scripts/sample_10/sample_10.lua index b8d55566..8f489a1c 100644 --- a/samples/bin/library/scripts/sample_10/sample_10.lua +++ b/samples/bin/library/scripts/sample_10/sample_10.lua @@ -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, diff --git a/sources/enduro2d/high/bindings/high_binds/components/touchable_binds.cpp b/sources/enduro2d/high/bindings/high_binds/components/touchable_binds.cpp index c5e61aca..de5c10ee 100644 --- a/sources/enduro2d/high/bindings/high_binds/components/touchable_binds.cpp +++ b/sources/enduro2d/high/bindings/high_binds/components/touchable_binds.cpp @@ -154,32 +154,6 @@ namespace e2d::bindings::high } ), - "hover_enter", sol::property( - [](const gcomponent& c) -> bool { - return c.component().exists(); - }, - [](gcomponent& c, bool yesno){ - if ( yesno ) { - c.component().ensure(); - } else { - c.component().remove(); - } - } - ), - - "hover_leave", sol::property( - [](const gcomponent& c) -> bool { - return c.component().exists(); - }, - [](gcomponent& c, bool yesno){ - if ( yesno ) { - c.component().ensure(); - } else { - c.component().remove(); - } - } - ), - "bubbling", sol::property( [](const gcomponent& c) -> bool { return c->bubbling(); diff --git a/sources/enduro2d/high/components/touchable.cpp b/sources/enduro2d/high/components/touchable.cpp index 0c764727..72556023 100644 --- a/sources/enduro2d/high/components/touchable.cpp +++ b/sources/enduro2d/high/components/touchable.cpp @@ -166,34 +166,6 @@ namespace e2d ImGui::Separator(); - // - // hover_enter/hover_leave - // - - if ( bool hover_enter = c.component().exists(); - ImGui::Checkbox("hover_enter", &hover_enter) ) - { - if ( hover_enter ) { - c.component().ensure(); - } else { - c.component().remove(); - } - } - - ImGui::SameLine(); - - if ( bool hover_leave = c.component().exists(); - ImGui::Checkbox("hover_leave", &hover_leave) ) - { - if ( hover_leave ) { - c.component().ensure(); - } else { - c.component().remove(); - } - } - - ImGui::Separator(); - // // bubbling/capturing // diff --git a/sources/enduro2d/high/starter.cpp b/sources/enduro2d/high/starter.cpp index d7a1a21e..f8cfef38 100644 --- a/sources/enduro2d/high/starter.cpp +++ b/sources/enduro2d/high/starter.cpp @@ -241,8 +241,6 @@ namespace e2d .register_component("touchable.released") .register_component("touchable.hover_over") .register_component("touchable.hover_out") - .register_component("touchable.hover_enter") - .register_component("touchable.hover_leave") .register_component>("touchable.events") .register_component("widget") .register_component("widget.dirty") @@ -287,8 +285,6 @@ namespace e2d //.register_component("touchable.released") //.register_component("touchable.hover_over") //.register_component("touchable.hover_out") - //.register_component("touchable.hover_enter") - //.register_component("touchable.hover_leave") //.register_component>("touchable.events") .register_component("widget") //.register_component("widget.dirty") diff --git a/sources/enduro2d/high/systems/touch_system.cpp b/sources/enduro2d/high/systems/touch_system.cpp index 7673b928..e893ccd0 100644 --- a/sources/enduro2d/high/systems/touch_system.cpp +++ b/sources/enduro2d/high/systems/touch_system.cpp @@ -28,7 +28,7 @@ namespace e2d internal_state(input& i, window& w) : input_(i) , window_(w) - , collector_(window_.register_event_listener(i)) {} + , collector_(window_.register_event_listener(i, w)) {} ~internal_state() noexcept { window_.unregister_event_listener(collector_); diff --git a/sources/enduro2d/high/systems/touch_system_impl/touch_system_base.hpp b/sources/enduro2d/high/systems/touch_system_impl/touch_system_base.hpp index 7b844050..97f734fe 100644 --- a/sources/enduro2d/high/systems/touch_system_impl/touch_system_base.hpp +++ b/sources/enduro2d/high/systems/touch_system_impl/touch_system_base.hpp @@ -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 { diff --git a/sources/enduro2d/high/systems/touch_system_impl/touch_system_collector.cpp b/sources/enduro2d/high/systems/touch_system_impl/touch_system_collector.cpp index 3fbfaf4d..fe2977b9 100644 --- a/sources/enduro2d/high/systems/touch_system_impl/touch_system_collector.cpp +++ b/sources/enduro2d/high/systems/touch_system_impl/touch_system_collector.cpp @@ -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)); diff --git a/sources/enduro2d/high/systems/touch_system_impl/touch_system_collector.hpp b/sources/enduro2d/high/systems/touch_system_impl/touch_system_collector.hpp index a7700af8..684ac92f 100644 --- a/sources/enduro2d/high/systems/touch_system_impl/touch_system_collector.hpp +++ b/sources/enduro2d/high/systems/touch_system_impl/touch_system_collector.hpp @@ -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; 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 events_; }; } diff --git a/sources/enduro2d/high/systems/touch_system_impl/touch_system_colliders.cpp b/sources/enduro2d/high/systems/touch_system_impl/touch_system_colliders.cpp index da268a99..37fb3b4c 100644 --- a/sources/enduro2d/high/systems/touch_system_impl/touch_system_colliders.cpp +++ b/sources/enduro2d/high/systems/touch_system_impl/touch_system_colliders.cpp @@ -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(); - owner.for_joined_components([&input, &window, &owner]( + + const auto camera_comp = [](const auto& l, const auto& r) noexcept { + return std::get(l).depth() >= std::get(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()), + b2f(window.framebuffer_size().cast_to()), math::point_to_normalized( b2f(window.real_size().cast_to()), 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(), - camera.viewport().size * target_size.cast_to()); + camera.viewport().position * window.framebuffer_size().cast_to(), + camera.viewport().size * window.framebuffer_size().cast_to()); if ( !math::inside(camera_viewport, mouse_p) ) { return; } - impl::update_world_space_colliders_under_mouse( - 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() ) { + return; + } + e.ensure_component( + camera_go, + local_point, + world_point); + }; - impl::update_world_space_colliders_under_mouse( + impl::for_world_space_colliders_under_mouse( owner, mouse_p, camera_vp, - camera_viewport); + camera_viewport, + under_mouse_func); - impl::update_world_space_colliders_under_mouse( + impl::for_world_space_colliders_under_mouse( owner, mouse_p, camera_vp, - camera_viewport); - }, !ecs::exists_any< - disabled, - disabled>()); + camera_viewport, + under_mouse_func); + + impl::for_world_space_colliders_under_mouse( + owner, + mouse_p, + camera_vp, + camera_viewport, + under_mouse_func); + }; + + ecsex::for_extracted_sorted_components( + owner, + camera_comp, + camera_func, + !ecs::exists_any< + disabled, + disabled>()); } } diff --git a/sources/enduro2d/high/systems/touch_system_impl/touch_system_colliders.hpp b/sources/enduro2d/high/systems/touch_system_impl/touch_system_colliders.hpp index 61f6a5ca..62925c1a 100644 --- a/sources/enduro2d/high/systems/touch_system_impl/touch_system_colliders.hpp +++ b/sources/enduro2d/high/systems/touch_system_impl/touch_system_colliders.hpp @@ -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(); + 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, diff --git a/sources/enduro2d/high/systems/touch_system_impl/touch_system_dispatcher.cpp b/sources/enduro2d/high/systems/touch_system_impl/touch_system_dispatcher.cpp index c7f7e702..7f5f3f93 100644 --- a/sources/enduro2d/high/systems/touch_system_impl/touch_system_dispatcher.cpp +++ b/sources/enduro2d/high/systems/touch_system_impl/touch_system_dispatcher.cpp @@ -13,6 +13,56 @@ namespace using namespace e2d; using namespace e2d::touch_system_impl; + std::pair screen_to_world_point( + const gobject& input_camera, + const collector::mouse_event& event) + { + if ( !input_camera || !input_camera.component() ) { + return {v2f::zero(), false}; + } + + const camera& cam = *input_camera.component(); + + const v2f& mouse_p = math::normalized_to_point( + b2f(event.event_window.framebuffer_size().cast_to()), + math::point_to_normalized( + b2f(event.event_window.real_size().cast_to()), + 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(), + cam.viewport().size * event.event_window.framebuffer_size().cast_to()); + + 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>().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().ensure(); break; - case touchable_events::mouse_hover_evt::types::enter: - target.component().ensure(); - break; - case touchable_events::mouse_hover_evt::types::leave: - target.component().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 vectortarget : 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().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().ensure(); + } + } + } + + const_gcomponent current_target_under_mouse{current_target}; + return current_target_under_mouse && current_target_under_mouse->input_camera + ? std::make_optional( + 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 under_mouse = hovering + ? hovering->target + : const_gcomponent(); - const_gcomponent 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 under_mouse = hovering + ? hovering->target + : const_gcomponent(); - const_gcomponent 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 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(); - - return touchable_events::mouse_button_evt( - target, + &under_mouse, + ¤t_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 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().ensure(); + current_target.component().ensure(); } } } @@ -321,19 +420,15 @@ namespace owner.remove_all_components(); }); - const_gcomponent 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() ) { + if ( current_target.component() ) { 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(); - }); + if ( !dragging || !dragging->target || !dragging->camera ) { + return std::nullopt; + } - if ( target ) { - if ( auto target_n = target.component()->node() ) { - nodes::for_extracted_components_from_parents(target_n, [ - ](const const_gcomponent& parent){ - const bool parent_disabled = ecs::exists_any< - disabled, - disabled - >()(parent.owner().raw_entity()); + const auto& [world_point, world_point_success] = screen_to_world_point( + dragging->camera, + event); - if ( !parent_disabled ) { - parent.owner().component().ensure(); + if ( !world_point_success ) { + return std::nullopt; + } + + const_gcomponent 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 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().ensure(); + dragging = std::make_optional( + current_target, + under_mouse->input_camera); + } + } + } + + if ( event.action == mouse_button_action::release ) { + E2D_DEFER([&owner, &dragging](){ + dragging.reset(); + owner.remove_all_components(); + }); + + 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 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([ - ](ecs::entity e, const touchable&, const actor& a){ - using namespace touchable_events; - - const auto need_hover_leave = - ecs::exists() && - !ecs::exists(); - - 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(); - } - - const auto need_hover_enter = - !ecs::exists() && - ecs::exists(); - - 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(); - } - } - }); - - 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().remove(); - } - - if ( target ) { - const bool captured = dispatch_event(target, mouse_hover_evt( - target, - mouse_hover_evt::types::over)); - - if ( captured ) { - target.component().ensure(); } } } + + return dragging; } } @@ -452,32 +565,34 @@ namespace e2d::touch_system_impl owner.remove_all_components(); owner.remove_all_components(); - owner.remove_all_components(); - owner.remove_all_components(); owner.for_each_component>([ ](const ecs::const_entity&, events& 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); } diff --git a/sources/enduro2d/high/systems/touch_system_impl/touch_system_dispatcher.hpp b/sources/enduro2d/high/systems/touch_system_impl/touch_system_dispatcher.hpp index ebf06b15..6f67070b 100644 --- a/sources/enduro2d/high/systems/touch_system_impl/touch_system_dispatcher.hpp +++ b/sources/enduro2d/high/systems/touch_system_impl/touch_system_dispatcher.hpp @@ -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; + using dragging_info_opt = std::optional; + 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_; }; }