Skip to content

feat(ui): one Caramel UI, a native ImGui mod menu, and honest frame-rate modules - #183

Merged
Lynxifyy merged 7 commits into
mainfrom
feat/native-imgui-menu-present-frame-effects
Nov 14, 2026
Merged

Lynxifyy merged 7 commits into
mainfrom
feat/native-imgui-menu-present-frame-effects

Conversation

@Lynxifyy

@Lynxifyy Lynxifyy commented Nov 14, 2026 •

Copy link
Copy Markdown
Collaborator

What changed

The launcher and the in-game menu are now one product with one design language, and the two
frame-rate modules no longer claim anything they cannot measure.

One UI, from the Caramel UI pack

Both surfaces already carry the pack's tokens, and this finishes the job:

Surface Where Ported from
Launcher (Compose) ui/compose/theme/ — GlowPalette.java, GlowTheme.kt, GlowGlass.kt compose/.../Theme.kt, Glass.kt
In-game menu (Dear ImGui) sweetloader/src/pl/menu/MenuTheme.*, MenuWidgets.* imgui/src/CaramelTheme.*, CaramelWidgets.*

The in-game menu draws through the game's own GL context on the present hook
(pl/menu/MenuHost.cpp + MenuRender.cpp), not through the pack's GLFW desktop backend, and it
keeps CaramelClient's cheaper glass budget rather than the pack's whole-window blur model.

The old mod-menu surface is deleted

ui/compose/modmenu/, overlay/ModMenuOverlay.java, the radial wheel (RadialMenu*, Wheel*) and
their layouts are gone. The native menu is the only mod menu; PreloaderMenu (Java) ↔
pl/menu/MenuJni.cpp is the only bridge, and InGameMenuController builds the catalogue JSON and
forwards input. ModMenuNavLayoutTest pins that the deleted layouts stay deleted and that the
native tab bar keeps one source of truth for its labels and icons.

Follow-up cleanup: no dead UI left

A later commit on this branch removes the last leftovers of the deleted surfaces, so the docs and
the tree agree:

  • ui/compose/caramel/Caramel* was deleted — it was a second Compose token layer with zero
    importers
    ; the live Compose theme is ui/compose/theme/ with the same values. One palette, one
    place.
  • overlay/ModMenuSwitch.java (the deleted menu's pill geometry) had no references left and is gone.
  • The launch quick dock's "Radial Menu" entry and all its wiring (quickdock_wheel,
    MainActivity.openModsFromHome(), ic_wheel, RadialHeadTurn + test, the
    radial_wheel_hold_to_open pref) are removed, along with 21 strings across 10 locales and their
    translation-baseline / priority-JSON rows. The dock is now Mods + Cosmetics.
  • Docs that described the deleted surfaces as live were corrected: ui-pack-review.md no longer
    claims the pack's Desktop component files were ported, ACCESSIBILITY.md / ARCHITECTURE.md name
    the real navigation (Dear ImGui ImGuiConfigFlags_NavEnableKeyboard in pl/menu/MenuHost.cpp),
    and UI_CHECKLIST.md is renumbered with an honest skin section (the in-game Cosmetics tab says the
    preview is launcher-side).

The FPS readout is honest now

FrameRateMeter measures the launcher's own Choreographer vsync cadence — not the game's present
rate — and its doc says so. The game's rate comes from the sweetloader render hook through
FrameTickSource. FpsReadout picks between the two and labels the source, ModStatsFormatter.fps
prefixes ~ whenever the number is not the game's exact rate, and isFrameRateExact() travels the
backend chain so no surface can pass an inferred reading off as exact.

Frame generation and motion blur

Both are present-frame effects, added in core.mods.render.PresentFrameCatalog /
PresentFramePolicy and run on the engine's present / frame-boundary seam (eglSwapBuffers detour,
pl/render/PresentFrameEffect.cpp):

  • Frame generation blends the previous presented frame into the current one so motion reads
    smoother at the same render rate. It does not present an extra frame.
  • Motion blur blends by view speed, with the budget clamped so the effect cannot cost more than
    it returns.

Neither module promises a frame-rate gain, and both are badged while the present hook is absent.

Submodule

Pins app/src/main/cpp/sweetloader to the matching SweetLoader commit (native ImGui menu + present
frame effects + the vendored Dear ImGui 1.91.5 NOTICE attribution).

Verification

  • ./gradlew :app:testDebugUnitTest :app:lintDebug — BUILD SUCCESSFUL, 3516 tests, 0 failures.
  • ./gradlew :app:assembleDebug — BUILD SUCCESSFUL (compiles the NDK C++).
  • sweetloader/tests/cosmetics/run_tests.sh — all host tests pass, including the new
    PresentFrameMathTest and MenuFilterTest.
  • scripts/check_submodules.sh, scripts/validate_release_content.py,
    sweetloader/scripts/check_sources_listed.py, check_pinned_deps.py — all pass.

Device-only behaviour (the real eglSwapBuffers detour against a shipped libminecraftpe.so, and
any measured frame rate) cannot be exercised here: there is no device or emulator in the dev
container, so the present-hook path is reported as badged rather than claimed working.

…ate modules

The launcher and the in-game menu now share one design language, taken from
the CaramelClient-UI-pack: the Compose launcher uses ui.compose.caramel.*
and the in-game menu is Dear ImGui on the game's GL context, themed from the
same tokens in the sweetloader's pl/menu (pin bumped to the matching commit).

The Compose/View mod-menu surface and the radial wheel are deleted, along
with their layouts and tests: the native menu is the only mod menu now, and
ModMenuNavLayoutTest pins that the old layouts stay gone.

The FPS readout no longer passes one measurement off as another. FrameRateMeter
measures the launcher's own Choreographer cadence and says so; the game's rate
comes from the sweetloader render hook, and FpsReadout/ModStatsFormatter mark
any value that is not the game's exact rate with a ~ and name its source.

Frame generation and motion blur are added as present-frame effects: both
blend the previous presented frame into the new one on the present boundary,
neither presents an extra frame, and both are badged while the present hook
is absent. Neither claims a frame-rate gain.
…product

Follow-up cleanup to the one-UI change (PR #183). Everything here is either dead
code that still referenced the deleted menu, or documentation that described the
deleted surface as if it were live.

Dead code removed:
- `ui/compose/caramel/Caramel*` — a second Compose token layer that nothing
  imported; the live Compose theme is `ui/compose/theme/` (GlowPalette +
  GlowTheme + GlowGlass) with the same values. Two copies of one palette is how
  a "one design system" claim quietly stops being true.
- `overlay/ModMenuSwitch.java` — the deleted menu's pill-switch geometry, with
  zero references left.
- The launch quick dock's "Radial Menu" entry and its wiring (`quickdock_wheel`,
  `MainActivity.openModsFromHome()`), its drawable, `RadialHeadTurn` + its test,
  and `InbuiltModManager`'s `radial_wheel_hold_to_open` pref — all leftovers of
  the removed wheel. The dock is now Mods + Cosmetics.

Strings and baselines:
- Dropped the 21 wheel/dock keys from every locale, `translation-baseline.json`,
  `scripts/hygiene/translation-baseline.txt` and `translations_priority.json`
  (180 priority entries).

Docs corrected to the shipped product:
- `ui-pack-review.md` and the one-UI note no longer claim the pack's Desktop
  component files were ported; they name the two live token sources and record
  that the duplicate `Caramel*` layer was dead code.
- `ACCESSIBILITY.md` / `ARCHITECTURE.md` replace the `ModMenuSwitch` claim with
  the real navigation (Dear ImGui `NavEnableKeyboard` in `pl/menu/MenuHost.cpp`).
- `UI_CHECKLIST.md`: renumbered sections, and the skin section no longer claims
  an in-game cosmetics preview — the in-game Cosmetics tab says the preview is
  launcher-side and offers to open it.

Verified: `check_ui_hygiene.py` clean, 3516 unit tests green, `lintDebug` and
`assembleDebug` green.
The previous cleanup commit claimed the dead UI was gone; it was not. `ic_wheel.xml`,
`RadialHeadTurn` and a larger cluster the mod-menu removal had orphaned were still in the
tree and still compiled. This removes the real cluster and makes the docs, the hygiene
baselines and the lint baseline match the shipped product.

Deleted (each verified to have no remaining reference from code, layouts or the manifest):

- Retired View/Compose mod-menu + VIP leftovers: `ControllerProfileEditor`, `PackChangerPanel`,
  `HudSafeAreaView`, `RenderDebugOverlay`, `MenuBindRelay`, `VipKeyLayout`, `VipTheme`,
  `ModCategory`, `KeyboardIllustrationView`, `ModToggleAnim`, `RadialHeadTurn`,
  `RadialHeadTurnTest`, `ModCategoryTest`.
- The old 3D splash scene, replaced by a key-art backdrop and a single-arc spinner:
  `SplashSceneView`, `SplashIsland`, `SplashWorld`, `SplashParticles`, `WordmarkShatter`,
  `ShatterPlan`, `OreBlockLoaderView`, `OreLoaderLayout`, `OreCrackSprites` (its only caller,
  `SplashTimeline.crackStage`, was itself uncalled) and their tests.
- Other unreachable screens/adapters: `CompatibilityProbe`, `QuickActionsAdapter`,
  `SettingsAdapter`, `GlideImageGetter`, `GameVersionSelectDialog` + the `gameversionselect`
  package, and the seven layouts they were the last users of (`item_version*`,
  `dialog_game_version_select`, `dialog_rename_entry`, `item_quick_action`,
  `item_settings_container`).

Kept, because they are still live: `CaramelBadge`, `ModIconHelper`, `OverlayResizeHandles`,
the `bg_vip_*` drawables (the pause menu borrows two of them), and the `ModMenu*` palette /
settings / metrics classes (still read by `ModMenuTheme` and `InbuiltModManager`).

Docs: `splash-screen.md` and `one-mod-menu-...-were-merged.md` rewritten to describe what
ships; `in-game-pack-changer.md` title no longer names a deleted panel; `FileSizeBudgetTest`'s
doc comment no longer names a deleted overlay. Baselines: retired the dead
`findViewById`/layout entries and the nine stale lint-baseline issues.

Verified: :app:compileDebugJavaWithJavac, :app:testDebugUnitTest (3460 tests, 0 failures),
:app:lintDebug, check_ui_hygiene.py, validate_release_content.py and verify_berryapi_abi.py all
pass.
…rd the palette

The launch tab is now the pack's own Compose screen (ui/compose/caramel/launch),
rendered by one ComposeView in MainActivity. It reads the pack component port
(ui/compose/caramel: CaramelTheme/Controls/Labels/Glass), which is the pack's
theme/Theme.kt and components/* value for value, including the caramel amber nav
indicator and the green Play face the shared scale never carried.

CaramelPaletteParityTest pins the three palette carriers together: the overlap
(navy, blue, text, the three status colours) must equal UiTokens/GlowPalette, and
the in-game ImGui twin (MenuTheme.hpp) must equal the Compose port token for
token. The docs and memory that called the caramel layer dead code now describe
the two-layer architecture.
@Lynxifyy
Lynxifyy merged commit 6b83ec5 into main Nov 14, 2026
5 checks passed
@Lynxifyy
Lynxifyy deleted the feat/native-imgui-menu-present-frame-effects branch November 14, 2026 19:26
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.

1 participant