Skip to content

refactor(path-following): clean MVVM architecture, custom 3D gesture engine, and modern UI controls - #58

Merged
dkhawk merged 3 commits into
feature/new_features_with_0.2.2_sdkfrom
feat/path-following-refactor
Aug 28, 2026
Merged

refactor(path-following): clean MVVM architecture, custom 3D gesture engine, and modern UI controls#58
dkhawk merged 3 commits into
feature/new_features_with_0.2.2_sdkfrom
feat/path-following-refactor

Conversation

@dkhawk

@dkhawk dkhawk commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

PR Description: Refactor Path Following Demo Across Kotlin Views, Java Views, and Compose

Target Branch: feature/new_features_with_0.2.2_sdk
Suggested Reviewer: @LoyalAbbas


🎯 Executive Summary

This PR updates the Path Following sample across all three supported application targets (Kotlin Views, Java Views, and Jetpack Compose).

It introduces a clean, testable MVVM architecture with clear separation of concerns, replaces the generic map gesture listener with a custom touch gesture controller tailored for tracking camera manipulation, and modernizes the control panel with Material 3 components, speed preset chips, sheet swipe gestures, and idle auto-fade.


💡 The "Why" (Motivation & Design Rationale)

1. Separation of Concerns & Clean Architecture

  • The Motivation: Previously, kinematic progression math, lookahead heading trigonometry, altitude offset computations, dynamic polyline geometry generation, and Android UI lifecycle callbacks were co-located inside single Activity classes. This led to duplicated logic across Kotlin, Java, and Compose, increased potential for Binder IPC pressure, and precluded unit testing the core domain calculations without Android device dependencies.
  • The Architectural Solution:
    • Pure Kotlin Domain State Machine (PathPlaybackController): Extracted all business logic, kinematic time integration, wrapping math, and state transformations into a pure, dependency-free Kotlin class.
    • MVVM State Layer (PathFollowingViewModel): Exposes an immutable PathPlaybackState flow (and LiveData for Java), ensuring unidirectional data flow and lifecycle safety.
    • Decoupled Progress Polyline Lifecycle: Progress polylines are driven strictly by time and kinematic distance along the route. Camera adjustments and touch gestures do not trigger polyline regeneration.
    • Hardware VSYNC Ticker: Replaced timer loops with Choreographer.FrameCallback in Views and withFrameMillis in Compose for smooth 60/120fps motion.

2. Custom Touch Gesture Controller (PathTouchHandler)

  • The Motivation: The standard Google Maps gesture controller is designed for free-roaming 2D/3D map exploration. During path following, free panning detaches the camera from the vehicle tracking pose.
  • The Solution: Disabled default map gestures in favor of a custom touch gesture handler tailored for following camera controls:
    • 1-Finger Vertical Sweep: Adjusts camera pitch/tilt ($0^\circ$ top-down to $85^\circ$ horizon) relative to the vehicle while keeping the camera locked onto the path.
    • 1-Finger Horizontal Sweep: Orbits camera heading around the path.
    • 2-Finger Pinch: Adjusts camera range ($20\text{m} - 5,000\text{m}$) with $0.65\times$ exponential damping to eliminate jumpiness.
    • Tiered Long-Press Acceleration: Holding the screen accelerates playback ($2\times$ at $0.5\text{s} \rightarrow 5\times$ Warp Speed at $2.0\text{s}$), reverting upon release.
    • Double-Tap Shuttle Controls:
      • Double-tap & hold Right $\rightarrow +5\times$ Fast-Forward along route.
      • Double-tap & hold Left $\rightarrow -5\times$ Rewind backwards along route.
      • Quick double-tap $\rightarrow$ Jumps $\pm 10%$ ahead or back along the path.

3. UI/UX Modernization & Controls

  • Persistent Playback Header: Play/Pause and progress scrubbing remain permanently accessible in a slim top bar even when the settings panel is collapsed.
  • 1-Tap Speed Preset Chips: Added [ 0.5x | 1x | 2x | 3x | 5x ] Material filter chips for instant speed adjustment without opening sliders.
  • Touch Target Accessibility ($48\text{dp}$): Upgraded all buttons to standard $48\text{dp}\times 48\text{dp}$ touch targets, added a visual pill drag handle, and made the whole header clickable.
  • Sheet Swipe Gestures: Added Swipe Down to Collapse and Swipe Up to Expand gestures on the control sheet.
  • Window-Level 3.5s Idle Auto-Fade: The control panel smoothly fades down to $35%$ opacity when inactive, giving a clean full-screen view of the map, and instantly wakes to $100%$ on any touch.
  • Comprehensive In-App Help Dialog: Accessible ? button with categorized instructions explaining camera gestures, speed controls, and sheet interactions.

📦 File Manifest (The "What")

Maps3DSamples/
├── ApiDemos/
│   ├── common/
│   │   ├── src/main/java/com/example/maps3d/common/
│   │   │   ├── PathData.kt                     # Shared Urban (SF) & Rural (Marin) GPS datasets
│   │   │   ├── PathEngine.kt                   # Mathematical utilities for distance & slicing
│   │   │   ├── PathPlaybackController.kt       # Pure domain state machine (kinematics, gestures, speeds)
│   │   │   ├── PathFollowingViewModel.kt       # MVVM ViewModel exposing immutable PathPlaybackState
│   │   │   └── PathTouchHandler.kt             # Custom Views touch gesture listener (tilt, orbit, zoom, shuttle)
│   │   ├── src/main/res/
│   │   │   ├── drawable/drag_handle_bar.xml    # Pill drag handle affordance
│   │   │   ├── drawable/help_outline_24px.xml  # Material help outline icon
│   │   │   ├── layout/activity_path_following.xml # Modernized layout with persistent bar & speed chips
│   │   │   └── values/strings.xml              # Help dialog strings and localized formats
│   │   └── src/test/java/com/example/maps3d/common/
│   │       └── PathPlaybackControllerTest.kt   # JVM unit tests (kinematics, rewind, skip, gestures)
│   ├── kotlin-app/
│   │   └── src/main/java/com/example/maps3dkotlin/pathfollowing/
│   │       └── PathFollowingActivity.kt        # Kotlin Views implementation with MVVM & PathTouchHandler
│   └── java-app/
│       └── src/main/java/com/example/maps3djava/pathfollowing/
│           └── PathFollowingActivity.java      # Java Views implementation with LiveData & PathTouchHandler
└── ComposeDemos/
    └── app/
        ├── build.gradle.kts                    # Desugaring & common dependency
        └── src/main/java/com/example/composedemos/pathfollowing/
            └── PathFollowingActivity.kt        # Jetpack Compose implementation with custom pointerInput gestures

🧪 Verification Matrix

  • JVM Unit Tests: ./gradlew :Maps3DSamples:ApiDemos:common:testDebugUnitTest passes 100%.
  • Spotless Formatting: Verified clean with ./gradlew spotlessApply.
  • Live Device Testing: Verified and synchronized across Kotlin Views, Java Views, and Jetpack Compose on Pixel 6.

@dkhawk
dkhawk requested a review from LoyalAbbas August 28, 2026 02:54

@LoyalAbbas LoyalAbbas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dkhawk
dkhawk merged commit 4fa3cfc into feature/new_features_with_0.2.2_sdk Aug 28, 2026
4 checks passed
@dkhawk
dkhawk deleted the feat/path-following-refactor branch August 28, 2026 15:34
dkhawk added a commit that referenced this pull request Aug 28, 2026
…llowing, Data Viz, Roadmap Mode, FOV) (#50)

* Add sample demos for Cloud Styling, Roadmap Mode, Data Visualization, Field of View, Path Following, and Advanced Camera Animation

* feat(samples): polish 0.2.2 showcase features and apply spotless formatting

- Add showcase demos for Advanced Camera Animation, Path Following, Data Visualization, Roadmap Mode, and Field of View
- Synchronize hardware frame loops to VSYNC and improve touch-fade UX
- Format codebase using spotless to adhere to 4-space ktlint rules

* test(visual): optimize visual test synchronization using MapSteady listener

* fix(compose): preserve Cloud Styling skeleton placeholder to match main baseline

* feat(compose): implement Data Visualization (Flood Fill) demo in ComposeDemos

* refactor(samples): polish 0.2.2 showcase samples with collapsible UI, auto-fade, and literate docs (#54)

* Enhance Advanced Camera Animation and Path Following samples

- Advanced Camera Animation:
  - Add modular step animation pipeline (FlyToStep, OrbitStep, DwellStep, FlyAroundStep, KeyframeStep).
  - Add high-altitude San Francisco starting camera view.
  - Implement full reset and continuous orbit support.
  - Sync Java, Kotlin, and Jetpack Compose implementations.

- Path Following:
  - Implement two-polyline progress tracking with wide blue base route (lower z-index) and narrow purple progress route (higher z-index).
  - Use in-place fixed polyline IDs to eliminate rendering flickering.
  - Default altitude mode to 'Clamp to Ground' with support for Relative to Ground, Relative to Mesh, and Absolute.
  - Add dynamic path height slider to avoid z-fighting with terrain.
  - Add collapsible control panel with explicit collapse/expand button, auto-slide dismissal, and subtle idle opacity.
  - Extract all hardcoded strings into strings.xml resources.
  - Align Java and Kotlin implementations.

* feat(fieldofview,datavisualization): polish FOV and Data Visualization with collapsible cards and literate docs

* feat(roadmapmode): polish Roadmap Mode with collapsible header and literate docs

* feat(routes): polish Routes API sample with collapsible control panel, auto-fade, and literate docs

* docs(samples): augment literate comments explaining 3D coordinates, extrusion, and smoothing

* build: untrack and gitignore gradle-daemon-jvm.properties

* docs: update copyright headers to 2026 for camera animation step classes

* fix(samples): address PR review feedback on animation timing, tour resume, onPause, and TransitionManager collapse

* fix(lint): resolve github-advanced-security warnings for text size, layout hierarchy, and KTX color parsing (#55)

* refactor(path-following): clean MVVM architecture, custom 3D gesture engine, and modern UI controls (#58)

* refactor(path-following): clean MVVM architecture, custom 3D gesture engine, and modern UI controls

* test(path-following): add unit test suites for PathEngine and PathFollowingViewModel

* refactor(path-following): clean PathPlaybackState data class and remove unused strings

* refactor(camera): declarative keyframe tour, reverse-trig stationary tracking & 3-way framework parity (#59)

* feat(camera): implement declarative keyframe tour with reverse-trig stationary tracking

- Implement StationaryCameraTracker math controller with ENU inverse spherical trigonometry for fixed-vantage camera tracking
- Add 5-step keyframe queue tour (high-altitude swoop, dwell pause, 360 orbit, stationary vantage tracking flight, and native flyTo transition to Coit Tower)
- Modernize UI controls with Material 3 dropdown menu button and structured HTML help dialog across Kotlin Views, Java Views, and Jetpack Compose
- Ensure consistent glTF model coordinate alignment, midpoint jump teleportation, and post-flight destination persistence
- Add comprehensive unit test coverage with Google Truth assertions across domain controllers

* fix(camera): synchronize UI state across frameworks and add framework subtitles

- Add framework indicator subtitles (Kotlin Views, Java Views, Jetpack Compose) to control panel headers and top toolbars
- Fix LiveData approach button label and sub-options observation in Java Views Activity
- Correct chase camera heading for High-Rate Frame Dispatcher to follow flight path bearing (106.2°)
- Add delayed onMap3DViewReady initialization workaround to ensure reliable initial camera and entity setup

* docs(camera): document onMap3DViewReady initialization delay workaround

* docs(camera): clean KDoc math formatting for Android Studio and Dokka compatibility

---------

Co-authored-by: Dale Hawkins <107309+dkhawk@users.noreply.github.com>

* fix(lint): resolve StringFormatInvalid and SuspiciousIndentation warnings

* fix(lint): resolve version catalog, hardcoded text, and accessibility warnings

* feat(branding): add framework-specific Google Maps 3D launcher icons for Kotlin, Java, and Compose

---------

Co-authored-by: Dale Hawkins <107309+dkhawk@users.noreply.github.com>
googlemaps-bot pushed a commit that referenced this pull request Aug 28, 2026
# [1.10.0](v1.9.0...v1.10.0) (2026-08-28)

### Features

* **samples:** add 0.2.2 showcase features (Camera Animation, Path Following, Data Viz, Roadmap Mode, FOV) ([#50](#50)) ([b87b16c](b87b16c)), closes [#54](#54) [#55](#55) [#58](#58) [#59](#59)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants