From 3c796ea873fe4b3efe6ddd2b94fa8aee7a900a27 Mon Sep 17 00:00:00 2001 From: liu weikai Date: Fri, 12 Jun 2026 16:01:11 +0800 Subject: [PATCH] Restore smooth touch map dragging --- .../include/ui/widgets/map/map_viewport.h | 2 + .../src/ui/screens/gps/gps_page_runtime.cpp | 45 ++++++++++++++++++- .../src/ui/widgets/map/map_viewport.cpp | 44 ++++++++++++++++-- 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/modules/ui_shared/include/ui/widgets/map/map_viewport.h b/modules/ui_shared/include/ui/widgets/map/map_viewport.h index a451b9c2..4c2d6e92 100644 --- a/modules/ui_shared/include/ui/widgets/map/map_viewport.h +++ b/modules/ui_shared/include/ui/widgets/map/map_viewport.h @@ -117,6 +117,7 @@ class Runtime friend const Widgets& widgets(const Runtime& runtime); friend void set_size(Runtime& runtime, lv_coord_t width, lv_coord_t height); friend void apply_model(Runtime& runtime, const Model& model); + friend void apply_model_lightweight(Runtime& runtime, const Model& model); friend void apply_overlay(Runtime& runtime, const ui::map::MapOverlaySnapshot& overlay); friend void clear(Runtime& runtime); friend bool project_point(const Runtime& runtime, const GeoPoint& point, lv_point_t& out_screen_point); @@ -132,6 +133,7 @@ void destroy(Runtime& runtime); const Widgets& widgets(const Runtime& runtime); void set_size(Runtime& runtime, lv_coord_t width, lv_coord_t height); void apply_model(Runtime& runtime, const Model& model); +void apply_model_lightweight(Runtime& runtime, const Model& model); void apply_overlay(Runtime& runtime, const ui::map::MapOverlaySnapshot& overlay); void clear(Runtime& runtime); bool project_point(const Runtime& runtime, const GeoPoint& point, lv_point_t& out_screen_point); diff --git a/modules/ui_shared/src/ui/screens/gps/gps_page_runtime.cpp b/modules/ui_shared/src/ui/screens/gps/gps_page_runtime.cpp index cdf4b3e2..aaa3da1f 100644 --- a/modules/ui_shared/src/ui/screens/gps/gps_page_runtime.cpp +++ b/modules/ui_shared/src/ui/screens/gps/gps_page_runtime.cpp @@ -85,6 +85,7 @@ constexpr std::uint32_t kLvglFunctionKeyF1 = 0x110001U; constexpr std::uint32_t kInvalidMemberId = 0xFFFFFFFFU; constexpr std::size_t kMaxTrackOverlayPoints = 48; constexpr int kDefaultTrackerZoom = 16; +constexpr std::uint32_t kMapDragPreviewIntervalMs = 16; struct TrackOverlayPoint { @@ -146,6 +147,7 @@ char s_map_notice_text[64]{}; uint32_t s_map_notice_until_ms = 0; int s_map_drag_start_pan_x = 0; int s_map_drag_start_pan_y = 0; +std::uint32_t s_map_drag_last_preview_ms = 0; std::vector s_track_points; std::vector s_track_modal_names; std::string s_track_file; @@ -166,6 +168,7 @@ void request_refresh_view(); void consume_key_event(lv_event_t* e); bool load_map_track_file_impl(const char* path, bool show_fail_toast); ::ui::presentation_sources::TeamMapOverlaySource& team_map_overlay_source(); +void apply_map_drag_preview(); lv_obj_t* create_map_control_button(lv_obj_t* parent, lv_coord_t width, const char* text, @@ -412,6 +415,7 @@ void clear_map_controls() s_member_button_ids.clear(); s_member_list_hash = 0; s_member_panel_last_ms = 0; + s_map_drag_last_preview_ms = 0; } void set_hidden(lv_obj_t* obj, bool hidden) @@ -1237,6 +1241,7 @@ void map_gesture_callback(const ::ui::widgets::map::GestureEvent& event, void*) case ::ui::widgets::map::GesturePhase::Pressed: s_map_drag_start_pan_x = s_map_pan_x; s_map_drag_start_pan_y = s_map_pan_y; + s_map_drag_last_preview_ms = 0; s_map_drag_active = false; break; case ::ui::widgets::map::GesturePhase::DragBegin: @@ -1246,7 +1251,7 @@ void map_gesture_callback(const ::ui::widgets::map::GestureEvent& event, void*) s_map_drag_active = true; s_map_pan_x = s_map_drag_start_pan_x + event.total_dx; s_map_pan_y = s_map_drag_start_pan_y + event.total_dy; - request_refresh_view(); + apply_map_drag_preview(); break; case ::ui::widgets::map::GesturePhase::DragEnd: case ::ui::widgets::map::GesturePhase::Cancel: @@ -1256,6 +1261,7 @@ void map_gesture_callback(const ::ui::widgets::map::GestureEvent& event, void*) s_map_pan_x = 0; s_map_pan_y = 0; sync_workspace_viewport_from_renderer(); + s_map_drag_last_preview_ms = 0; request_refresh_view(); } s_map_drag_active = false; @@ -1263,6 +1269,32 @@ void map_gesture_callback(const ::ui::widgets::map::GestureEvent& event, void*) } } +void apply_map_drag_preview() +{ + if (!s_root) + { + return; + } + + const std::uint32_t now_ms = sys::millis_now(); + if (s_map_drag_last_preview_ms != 0 && + now_ms - s_map_drag_last_preview_ms < kMapDragPreviewIntervalMs) + { + return; + } + s_map_drag_last_preview_ms = now_ms; + + const auto snapshot = map_workspace_model().snapshot(); + if (!snapshot.header.valid) + { + return; + } + + ::ui::widgets::map::apply_model_lightweight( + s_map_runtime, + build_map_model(snapshot)); +} + void refresh_view() { if (!s_root) @@ -1280,7 +1312,16 @@ void refresh_view() if (snapshot.header.valid) { - ::ui::widgets::map::apply_model(s_map_runtime, build_map_model(snapshot)); + if (s_map_drag_active) + { + ::ui::widgets::map::apply_model_lightweight( + s_map_runtime, + build_map_model(snapshot)); + } + else + { + ::ui::widgets::map::apply_model(s_map_runtime, build_map_model(snapshot)); + } if (!s_map_drag_active && commit_pending_map_pan_from_screen()) { snapshot = map_workspace_model().snapshot(); diff --git a/modules/ui_shared/src/ui/widgets/map/map_viewport.cpp b/modules/ui_shared/src/ui/widgets/map/map_viewport.cpp index eb16ebe6..fb0163c8 100644 --- a/modules/ui_shared/src/ui/widgets/map/map_viewport.cpp +++ b/modules/ui_shared/src/ui/widgets/map/map_viewport.cpp @@ -46,7 +46,18 @@ struct RuntimeImpl namespace { +#ifndef MAP_VIEWPORT_DEBUG +#define MAP_VIEWPORT_DEBUG 0 +#endif + +#if MAP_VIEWPORT_DEBUG #define MAP_VIEWPORT_LOG(...) std::printf("[MapViewport] " __VA_ARGS__) +#else +#define MAP_VIEWPORT_LOG(...) \ + do \ + { \ + } while (0) +#endif constexpr double kCoordPi = 3.14159265358979323846; constexpr double kCoordA = 6378245.0; @@ -343,7 +354,7 @@ GeoPoint transformed_focus(const Model& model) return out; } -void refresh_tiles(RuntimeImpl& impl, const char* reason) +void refresh_tiles(RuntimeImpl& impl, const char* reason, bool prime_visible) { if (!is_runtime_alive(impl)) { @@ -383,7 +394,10 @@ void refresh_tiles(RuntimeImpl& impl, const char* reason) impl.model.pan_x, impl.model.pan_y, true); - prime_visible_tiles(impl, reason); + if (prime_visible) + { + prime_visible_tiles(impl, reason); + } MAP_VIEWPORT_LOG("refresh_tiles reason=%s zoom=%d pan=%d,%d src=%u contour=%d anchor=%d size=%dx%d map_data=%d visible_map=%d\n", reason ? reason : "", impl.model.zoom, @@ -718,7 +732,31 @@ void apply_model(Runtime& runtime, const Model& model) static_cast(impl->model.map_source), impl->model.contour_enabled ? 1 : 0, static_cast(impl->model.coord_system)); - refresh_tiles(*impl, "apply_model"); + refresh_tiles(*impl, "apply_model", true); + render_overlay(*impl); +} + +void apply_model_lightweight(Runtime& runtime, const Model& model) +{ + if (!runtime.impl_) + { + runtime.impl_ = new RuntimeImpl(); + runtime.impl_->tiles.reserve(TILE_RECORD_LIMIT); + } + RuntimeImpl* impl = runtime.impl_; + impl->model = model; + impl->model.map_source = sanitize_map_source(impl->model.map_source); + MAP_VIEWPORT_LOG("apply_model_lightweight focus_valid=%d lat=%.7f lon=%.7f zoom=%d pan=%d,%d src=%u contour=%d coord=%u\n", + impl->model.focus_point.valid ? 1 : 0, + impl->model.focus_point.lat, + impl->model.focus_point.lon, + impl->model.zoom, + impl->model.pan_x, + impl->model.pan_y, + static_cast(impl->model.map_source), + impl->model.contour_enabled ? 1 : 0, + static_cast(impl->model.coord_system)); + refresh_tiles(*impl, "apply_model_lightweight", false); render_overlay(*impl); }