Skip to content

Fix character creation on empty accounts, correct the preview placement, and add Visual Studio 2026 support - #2

Open
DaviRJ wants to merge 2 commits into
VDraven:mainfrom
DaviRJ:character-creation-fix
Open

DaviRJ wants to merge 2 commits into
VDraven:mainfrom
DaviRJ:character-creation-fix

Conversation

@DaviRJ

@DaviRJ DaviRJ commented Oct 26, 2026

Copy link
Copy Markdown

Summary

This PR fixes two bugs in the character creation screen and adds build support for Visual Studio 2026.

The critical bug: on accounts with no characters yet, the creation screen was visible and accepted keyboard input, but every click was dead — class buttons, OK and Cancel did nothing, and the Menu/Create buttons in the corner of the screen were unresponsive too, leaving the player stuck with no option other than closing the process. Accounts that already had a character worked fine. That asymmetry was the giveaway.

The second bug was purely visual: the 3D character preview was rendered near the bottom of the screen instead of in its top-left slot.

Root cause

1. Dead clicks (empty accounts only)

CUIMng::CreateCharacterScene() published the character selection window last:

m_CharMakeWin->Create();
m_WinList.AddHead(m_CharMakeWin.get());

m_CharSelMainWin->UpdateDisplay();   // auto-shows m_CharMakeWin when the account has no characters
m_CharInfoBalloonMng->UpdateDisplay();

ShowWin(m_CharSelMainWin.get());      // <- moved the selection bar back to the top / active

CCharSelMainWin::UpdateDisplay() intentionally auto-shows the creation window when the account has no live character. The following ShowWin(m_CharSelMainWin) then called SetActiveWin(), pushing the selection bar to the head of the window list and marking it active — so the creation window ended up visible but inactive.

CWin::Update() only invokes UpdateWhileActive() for the active window, and that is the only place where the Rml creation panel consumes its pending changes:

const auto changes = panel_.TakeChanges();
if (changes.ok)     RequestCreateCharacter();
else if (changes.cancel) HideWin(this);

The RmlUi panel did register the click (changes_.ok = ok_.IsClick() || changes_.ok), but nobody ever read it.

A click could not "wake up" the window either: while the Rml panel is visible, RmlCharacterCreatePanel::Impl::Input() returns true for every pointer event, so the legacy path is skipped in ApplicationLoopFrame — MouseLButtonPush never updates, and the CUIMng::Update() loop that would call SetActiveWin() never fires. Fully circular.

The corner Create/Menu buttons were dead for the same reason (CCharSelMainWin::UpdateWhileActive() reads the same frozen input), and ESC could not open the system menu because CUIMng::Update() bails out while the creation window is shown, while the panel's own ESC handling lived in the inactive window.

Why it worked with an existing character: the creation window started hidden, so ProcessModernUiInput() returned false and legacy clicks flowed normally. The Create button then called ShowWin(m_CharMakeWin) as the last action, leaving the window active — everything worked from there.

2. Preview in the wrong place

PreviewBounds() derives the preview rectangle from the Rml layout using Panel-Reference (640x480), so it is top-left origin:

bounds_ = { offset.x * reference[0] / viewport.width,
            offset.y * reference[1] / viewport.height, ... };

CCharMakeWin::RenderCreateCharacter() passed it straight to BeginOpengl(), but the render tape viewport is bottom-left origin — MapGpuRect() in the GPU backend converts with surfaceHeight - rect.y - rect.height. With top: 0, the preview landed at the bottom of the screen and was clipped by the edge.

Changes

UI fixes

  • src/client/ui/session/UiSessionLogic.cpp — CUIMng::CreateCharacterScene() now shows m_CharSelMainWin before calling UpdateDisplay(), so the auto-shown creation window ends up on top of the list and active. UpdateWhileActive() runs again, and OK/Cancel/class buttons/Enter/Esc all respond. Existing-character flow is untouched because UpdateDisplay() shows nothing in that case.
    This also fixes window resizing, since RepositionSceneUI() recreates the scene through the same path.

  • src/client/ui/features/Shell/ShellRender.cpp — RenderCreateCharacter() flips the Y coordinate at the BeginOpengl() call:

    BeginOpengl(viewport.x, REFERENCE_HEIGHT - viewport.y - viewport.height,
                viewport.width, viewport.height);

    This matches the convention already used by SetupMainSceneViewport(). PreviewBounds() keeps its Rml-native top-left semantics.

Visual Studio 2026 build support

  • CMakePresets.json
    • New hidden base preset windows-vs2026-base using the Visual Studio 18 2026 generator, restricted to CMAKE_CONFIGURATION_TYPES=Debug;Release and Windows hosts.
    • New configure presets vs2026-x64 and vs2026-x86, mirroring the vs2022 ones (toolset host=x64, same toolchain files with architecture x64/Win32 so the active config is not overridden), outputting to bin/x64 and bin/x86.
    • New build presets vs2026-x64-debug, vs2026-x64-release, vs2026-x86-debug, vs2026-x86-release.
    • The VS2022 presets are unchanged and remain the fallback.
  • Build.ps1 — new Get-VisualStudioPresetPrefix helper. It locates vswhere.exe, checks for the C++ workload (Microsoft.VisualStudio.Component.VC.Tools.x86.x64) in the [18.0,19.0) version range, and returns vs2026 when found, otherwise vs2022. ./Build.ps1 therefore picks the newest installed Visual Studio automatically; the -Generator Ninja path is unaffected.
  • README.md — requirements updated to "Visual Studio 2022 or 2026", preset list extended, and the example now uses vs2026-x64.

How to test

Character creation:

  1. Log in with an account that has zero characters. The creation panel should open automatically.
  2. Click each of the three class buttons — stats and the preview model should change.
  3. Type a name, click OK — the character must be created.
  4. Press Cancel or ESC — the panel closes and Create/Menu/Connect respond again.
  5. Verify the preview sits in the top-left slot of the panel, with the character fully framed.
  6. Resize the window, and repeat at 1024x768 and 1600x900.
  7. Log in with an account that already has a character — the previous flow (Create -> OK) must be unchanged.

Build:

cmake --preset vs2026-x64
cmake --build --preset vs2026-x64-release

or simply ./Build.ps1, which auto-detects VS2022/VS2026. Verified locally: configure and full build succeed, producing bin/x64/Release/Main.exe and bin/x64/Release/MuLauncher.exe with assets copied by the CopyAssets target.

Notes

  • The creation panel is modal and still consumes all pointer input; corner buttons only respond after Cancel/ESC. That is the intended behaviour for the panel and was left as is.
  • If the preview is correctly positioned but tightly framed after this fix, the remaining issue would be camera framing, not placement — Preview-Camera uses a narrow FOV (10) and Preview-Models scales the Dark Knight at 5.9. Not addressed here.
  • Generated network sources (src/client/network/generated/, src/client-library/) may appear modified after a build due to CRLF rewriting; they are content-identical and were not included in this PR.

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