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 5bf4bf40..61f6a5ca 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 @@ -91,19 +91,16 @@ namespace e2d::touch_system_impl using world_space_collider_t = WorldSpaceCollider; using local_space_collider_t = typename WorldSpaceCollider::local_space_collider_t; - m4f inv_camera_vp{m4f::identity()}; - bool inv_camera_vp_success{false}; - - std::tie(inv_camera_vp, inv_camera_vp_success) = math::inversed(camera_vp, 0.f); + const auto [inv_camera_vp, inv_camera_vp_success] = math::inversed(camera_vp, 0.f); if ( !inv_camera_vp_success ) { return; } owner.for_joined_components([ - &mouse_p, - &camera_vp, - &inv_camera_vp, - &camera_viewport + &mouse_p = mouse_p, + &camera_vp = camera_vp, + &inv_camera_vp = inv_camera_vp, + &camera_viewport = camera_viewport ](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( 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 4951eb6c..c7f7e702 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 @@ -8,6 +8,81 @@ #include "touch_system_collector.hpp" +namespace +{ + using namespace e2d; + using namespace e2d::touch_system_impl; + + void apply_event( + gobject target, + const touchable_events::mouse_move_evt& event) + { + target.component>().ensure() + .add(event); + } + + void apply_event( + gobject target, + const touchable_events::mouse_hover_evt& event) + { + target.component>().ensure() + .add(event); + + switch ( event.type() ) { + case touchable_events::mouse_hover_evt::types::over: + target.component().ensure(); + break; + 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; + } + } + + void apply_event( + gobject target, + const touchable_events::mouse_scroll_evt& event) + { + target.component>().ensure() + .add(event); + } + + void apply_event( + gobject target, + const touchable_events::mouse_button_evt& event) + { + target.component>().ensure() + .add(event); + + if ( event.button() != mouse_button::left ) { + return; + } + + switch ( event.type() ) { + case touchable_events::mouse_button_evt::types::clicked: + target.component().ensure(); + break; + case touchable_events::mouse_button_evt::types::pressed: + target.component().ensure(); + break; + case touchable_events::mouse_button_evt::types::released: + target.component().ensure(); + break; + default: + E2D_ASSERT_MSG(false, "unexpected mouse button event type"); + break; + } + } +} + namespace { using namespace e2d; @@ -46,78 +121,20 @@ namespace return gobject(); } - template < typename E > - bool dispatch_event(gobject target, const E& event); - - void apply_event(gobject target, const touchable_events::mouse_move_evt& event) { - target.component>().ensure() - .add(event); - } - - void apply_event(gobject target, const touchable_events::mouse_hover_evt& event) { - target.component>().ensure() - .add(event); - - switch ( event.type() ) { - case touchable_events::mouse_hover_evt::types::over: - target.component().ensure(); - break; - 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 hover event type"); - break; - } - } - - void apply_event(gobject target, const touchable_events::mouse_scroll_evt& event) { - target.component>().ensure() - .add(event); - } - - void apply_event(gobject target, const touchable_events::mouse_button_evt& event) { - target.component>().ensure() - .add(event); - - if ( event.button() != mouse_button::left ) { - return; - } - - switch ( event.type() ) { - case touchable_events::mouse_button_evt::types::clicked: - target.component().ensure(); - break; - case touchable_events::mouse_button_evt::types::pressed: - target.component().ensure(); - break; - case touchable_events::mouse_button_evt::types::released: - target.component().ensure(); - break; - default: - E2D_ASSERT_MSG(false, "unexpected mouse event type"); - break; - } - } - bool capture_target(gobject target) { if ( !target ) { return false; } - const_gcomponent target_actor = target.component(); - const_gcomponent target_touchable = target.component(); + const_gcomponent target_actor{target}; + const_gcomponent target_touchable{target}; + if ( !target_actor || !target_touchable ) { return false; } - static thread_local std::vector> parents; + static thread_local std::vector< + const_gcomponent> parents; const std::size_t begin_index = parents.size(); E2D_DEFER([begin_index](){ @@ -156,8 +173,9 @@ namespace return; } - const_gcomponent target_actor = target.component(); - const_gcomponent target_touchable = target.component(); + const_gcomponent target_actor{target}; + const_gcomponent target_touchable{target}; + if ( !target_actor || !target_touchable ) { return; } @@ -166,7 +184,8 @@ namespace return; } - static thread_local std::vector> parents; + static thread_local std::vector< + const_gcomponent> parents; const std::size_t begin_index = parents.size(); E2D_DEFER([begin_index](){ @@ -215,40 +234,131 @@ namespace } } -namespace e2d::touch_system_impl +namespace { - void dispatcher::dispatch_all_events( - collector& collector, + using namespace e2d; + using namespace e2d::touch_system_impl; + + void process_event( + gobject target, + ecs::registry& owner, + const collector::mouse_move_event& event) + { + E2D_UNUSED(owner, event); + + const_gcomponent under_mouse{target}; + if ( !under_mouse ) { + return; + } + + dispatch_event( + target, + touchable_events::mouse_move_evt( + target, + under_mouse->local_point, + under_mouse->world_point)); + } + + void process_event( + gobject target, + ecs::registry& owner, + const collector::mouse_scroll_event& event) + { + E2D_UNUSED(owner); + + const_gcomponent under_mouse{target}; + if ( !under_mouse ) { + return; + } + + dispatch_event( + target, + touchable_events::mouse_scroll_evt( + target, + event.delta, + under_mouse->local_point, + under_mouse->world_point)); + } + + void process_event( + gobject target, + ecs::registry& owner, + const collector::mouse_button_event& event) + { + 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, + type, + event.button, + 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, + make_mouse_button_evt(mouse_button_evt::types::pressed)); + + if ( captured && event.button == mouse_button::left ) { + target.component().ensure(); + } + } + } + + if ( event.action == mouse_button_action::release ) { + E2D_DEFER([&owner](){ + owner.remove_all_components(); + }); + + const_gcomponent under_mouse{target}; + + if ( under_mouse ) { + using namespace touchable_events; + + const bool captured = dispatch_event( + target, + make_mouse_button_evt(mouse_button_evt::types::released)); + + if ( captured && event.button == mouse_button::left ) { + if ( target.component() ) { + dispatch_event( + target, + make_mouse_button_evt(mouse_button_evt::types::clicked)); + } + } + } + } + } +} + +namespace +{ + using namespace e2d; + using namespace e2d::touch_system_impl; + + void process_new_hover_target( + gobject target, + gobject last_target, ecs::registry& owner) { - class touchable_last_hover final {}; - class touchable_next_hover final {}; + struct touchable_last_hover final {}; + struct touchable_next_hover final {}; - E2D_DEFER([&collector, &owner](){ - collector.clear(); + E2D_DEFER([&owner](){ owner.remove_all_components(); }); - owner.remove_all_components(); - owner.remove_all_components(); - owner.remove_all_components(); - - 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); - if ( target ) { if ( auto target_n = target.component()->node() ) { nodes::for_extracted_components_from_parents(target_n, [ @@ -269,19 +379,20 @@ namespace e2d::touch_system_impl 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() ) { - const bool captured = dispatch_event( + dispatch_event( a.node()->owner(), - touchable_events::mouse_hover_evt( + mouse_hover_evt( a.node()->owner(), - touchable_events::mouse_hover_evt::types::leave)); - if ( captured ) { - e.remove_component(); - } + mouse_hover_evt::types::leave)); + + e.remove_component(); } const auto need_hover_enter = @@ -291,120 +402,84 @@ namespace e2d::touch_system_impl if ( need_hover_enter(e) && a.node() ) { const bool captured = dispatch_event( a.node()->owner(), - touchable_events::mouse_hover_evt( + mouse_hover_evt( a.node()->owner(), - touchable_events::mouse_hover_evt::types::enter)); + mouse_hover_evt::types::enter)); + if ( captured ) { e.ensure_component(); } } }); - // - // - // + if ( target != last_target ) { + using namespace touchable_events; - if ( target != last_hover_target_ ) { - if ( last_hover_target_ ) { - dispatch_event(last_hover_target_, touchable_events::mouse_hover_evt( - last_hover_target_, - touchable_events::mouse_hover_evt::types::out)); - last_hover_target_.component().remove(); - last_hover_target_.component().remove(); + 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, touchable_events::mouse_hover_evt( + const bool captured = dispatch_event(target, mouse_hover_evt( target, - touchable_events::mouse_hover_evt::types::over)); + mouse_hover_evt::types::over)); + if ( captured ) { target.component().ensure(); } } - - last_hover_target_ = target; - } - - // - // - // - - if ( target ) { - for ( const auto& event : collector ) { - std::visit(utils::overloaded { - [](std::monostate){}, - [&target](const collector::mouse_move_event&){ - const auto make_mouse_move_evt = [ - &target - ](){ - return touchable_events::mouse_move_evt( - target, - target.component()->local_point, - target.component()->world_point); - }; - dispatch_event( - target, - make_mouse_move_evt()); - }, - [&target](const collector::mouse_scroll_event& event){ - const auto make_mouse_scroll_evt = [ - &event, - &target - ](){ - return touchable_events::mouse_scroll_evt( - target, - event.delta, - target.component()->local_point, - target.component()->world_point); - }; - dispatch_event( - target, - make_mouse_scroll_evt()); - }, - [&target](const collector::mouse_button_event& event){ - const auto make_mouse_button_evt = [ - &event, - &target - ](touchable_events::mouse_button_evt::types type){ - return touchable_events::mouse_button_evt( - target, - type, - event.button, - target.component()->local_point, - target.component()->world_point); - }; - - switch ( event.action ) { - case mouse_button_action::press: { - const bool captured = dispatch_event( - target, - make_mouse_button_evt(touchable_events::mouse_button_evt::types::pressed)); - if ( captured && event.button == mouse_button::left ) { - target.component().ensure(); - } - break; - } - case mouse_button_action::release: { - const bool captured = dispatch_event( - target, - make_mouse_button_evt(touchable_events::mouse_button_evt::types::released)); - if ( captured && event.button == mouse_button::left ) { - if ( target.component() ) { - target.component().remove(); - dispatch_event( - target, - make_mouse_button_evt(touchable_events::mouse_button_evt::types::clicked)); - } - } - break; - } - default: - E2D_ASSERT_MSG(false, "unexpected mouse button event action type"); - break; - } - } - }, event); - } + } + } +} + +namespace e2d::touch_system_impl +{ + void dispatcher::dispatch_all_events( + collector& collector, + ecs::registry& owner) + { + E2D_DEFER([&collector](){ + collector.clear(); + }); + + owner.remove_all_components(); + owner.remove_all_components(); + owner.remove_all_components(); + + 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); + + if ( target != last_target_ ) { + last_target_ = target; + } + + 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); + } + }, 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 ead5ebd4..ebf06b15 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 @@ -18,6 +18,6 @@ namespace e2d::touch_system_impl collector& collector, ecs::registry& owner); private: - gobject last_hover_target_; + gobject last_target_; }; }