fix(ui): take the splash font from memory, and <cstring> for ocean_fft - #60
Merged
Merged
Conversation
Two portability fixes that have nothing to do with each other beyond both being one-liners in the same tree. The splash wrote Roboto to a temp file and handed ultragui the path, because FT_New_Face was the only way into its text engine. The file needed a name no concurrent process would also pick, so it carried ::getpid() -- and that single call dragged <unistd.h> into the module, which MSVC does not have. A windows build of anything linking rx::ui fails on the include. libultragui grew LoadFontMemory (Force67/libultragui#5), so the bytes from rx_fonts.rxp go straight in. The temp path, the pid, the write, the unlink in Shutdown and font_cache_path_ all go with it; a splash that fails to find its font still falls back to a system one. ocean_fft.cc calls std::memcpy and never included <cstring>; it arrived transitively through equilibrium's headers until equilibrium removed the STL from base's production surface. Include it where it is used.
Force67
added a commit
to Force67/recreation
that referenced
this pull request
Sep 16, 2026
Retarget the build onto rx main (2198552), which moved its ultragui integration out of apps/editor into an rx::ui module and put an engine splash on it. rx::app links that module, so the plate needs nothing from the game -- but libultragui stops being optional, and the engine now owns three files and six shaders recreation carried its own copies of. libultragui is configured ahead of rx: rx::ui adds the checkout itself when no ultragui target exists yet, and that copy would carry ultragui's Lua scripting instead of recreation's C# host (adding the same source directory twice is a hard error anyway). The platform and RHI shims now come from the engine, as do the ugui pipeline shaders -- both repos embedded those six blobs to the same generated header path, which ninja refuses outright. RX_LIBULTRAGUI_DIR is forwarded for the builds that compile no HUD of their own; android checks the library out for that. The HUD's own Vulkan backend stays, renamed HudRenderBackend so it no longer collides with rx::ui::GuiRenderBackend. It keeps the growing descriptor pool chain a vanilla Scaleform screen's art needs, which the engine's single fixed block does not hold; it can go when that lands in rx::ui. The flake stops reading the siblings out of one developer's home directory. All six (rx, zetanet, nanobuf, libultragui, kinema, equilibrium) are fetched from github at the revisions build.yml pins, with submodules wherever CI checks them out recursively, so the sandbox and CI compile the same engine on any machine. What git does not carry does not arrive: rx's FidelityFX/DLSS/NRD/Jolt SDKs are downloads, so that build configures with those features off and a working copy stays the way to build with them. equilibrium stops being welded to the submodule. It is where base:: comes from, and it was reachable one way only: third_party/equilibrium, checked out recursively, which drags in its own eight submodules (googletest, musl, mbedtls, tracy and the rest) that sit behind EQ_BUILD_TESTS and never compile here. Every CI job cloned all of them, and `src = self` carries no submodules at all, so the nix build could not see equilibrium in the first place. RECREATION_EQUILIBRIUM_DIR now names the checkout, the submodule stays the default, the sandbox gets a tarball input at the revision the submodule records, and the checkouts that only need equilibrium itself ask for one level instead of eight. With that and slangc (rx compiles .slang shaders now), `nix build` produces recreation, recreation-server and esminfo for the first time. The sibling pins move together, because the retarget needed fixes in three of them. zetanet spells out the <string.h> its bare mem* calls always needed (Force67/zetanet#2). libultragui can load a font from memory instead of only from a path (Force67/libultragui#5). rx uses that for the splash wordmark, which deletes the temp file it used to write, the pid in its name and the <unistd.h> that came with it -- the include MSVC does not have, and the reason a windows build of anything linking rx::ui failed (Force67/rx#60). Verified against rx 2198552: full build, 107/107 tests, and a windowed run that shows the plate and hands the frame back to the game's own UI when it expires. RECREATION_NET=OFF, the no-SDL3 path and an out-of-tree equilibrium all configure. `nix build .#default` completes.
Force67
added a commit
to Force67/recreation
that referenced
this pull request
Sep 16, 2026
Retarget the build onto rx main (2198552), which moved its ultragui integration out of apps/editor into an rx::ui module and put an engine splash on it. rx::app links that module, so the plate needs nothing from the game -- but libultragui stops being optional, and the engine now owns three files and six shaders recreation carried its own copies of. libultragui is configured ahead of rx: rx::ui adds the checkout itself when no ultragui target exists yet, and that copy would carry ultragui's Lua scripting instead of recreation's C# host (adding the same source directory twice is a hard error anyway). The platform and RHI shims now come from the engine, as do the ugui pipeline shaders -- both repos embedded those six blobs to the same generated header path, which ninja refuses outright. RX_LIBULTRAGUI_DIR is forwarded for the builds that compile no HUD of their own; android checks the library out for that. The HUD's own Vulkan backend stays, renamed HudRenderBackend so it no longer collides with rx::ui::GuiRenderBackend. It keeps the growing descriptor pool chain a vanilla Scaleform screen's art needs, which the engine's single fixed block does not hold; it can go when that lands in rx::ui. The flake stops reading the siblings out of one developer's home directory. All six (rx, zetanet, nanobuf, libultragui, kinema, equilibrium) are fetched from github at the revisions build.yml pins, with submodules wherever CI checks them out recursively, so the sandbox and CI compile the same engine on any machine. What git does not carry does not arrive: rx's FidelityFX/DLSS/NRD/Jolt SDKs are downloads, so that build configures with those features off and a working copy stays the way to build with them. equilibrium moves to the head of devel5, the branch .gitmodules names and the pin had drifted off: a commit on no branch at all, five behind devel5 and one ahead, reachable by sha alone. devel5 brings the STL out of base's production surface, the security pass behind it, and a string option that owns its value instead of pointing at the buffer it was parsed from (Force67/equilibrium#15) -- the bug that had RX_UI_SHOT writing captures to a filename made of freed memory. equilibrium also stops being welded to the submodule. It is where base:: comes from, and it was reachable one way only: third_party/equilibrium, checked out recursively, which drags in its own eight submodules (googletest, musl, mbedtls, tracy and the rest) that sit behind EQ_BUILD_TESTS and never compile here. Every CI job cloned all of them, and `src = self` carries no submodules at all, so the nix build could not see equilibrium in the first place. RECREATION_EQUILIBRIUM_DIR now names the checkout, the submodule stays the default, the sandbox gets a tarball input at the revision the submodule records, and the checkouts that only need equilibrium itself ask for one level instead of eight. With that and slangc (rx compiles .slang shaders now), `nix build` produces recreation, recreation-server and esminfo for the first time. The sibling pins move together, because the retarget needed fixes in three of them. zetanet spells out the <string.h> its bare mem* calls always needed (Force67/zetanet#2). libultragui can load a font from memory instead of only from a path (Force67/libultragui#5). rx uses that for the splash wordmark, which deletes the temp file it used to write, the pid in its name and the <unistd.h> that came with it -- the include MSVC does not have, and the reason a windows build of anything linking rx::ui failed (Force67/rx#60). Verified against rx 2198552: full build, 107/107 tests, and a windowed run that shows the plate and hands the frame back to the game's own UI when it expires. RECREATION_NET=OFF, the no-SDL3 path and an out-of-tree equilibrium all configure. `nix build .#default` completes.
Force67
added a commit
to Force67/recreation
that referenced
this pull request
Sep 16, 2026
Retarget the build onto rx main (2198552), which moved its ultragui integration out of apps/editor into an rx::ui module and put an engine splash on it. rx::app links that module, so the plate needs nothing from the game -- but libultragui stops being optional, and the engine now owns three files and six shaders recreation carried its own copies of. libultragui is configured ahead of rx: rx::ui adds the checkout itself when no ultragui target exists yet, and that copy would carry ultragui's Lua scripting instead of recreation's C# host (adding the same source directory twice is a hard error anyway). The platform and RHI shims now come from the engine, as do the ugui pipeline shaders -- both repos embedded those six blobs to the same generated header path, which ninja refuses outright. RX_LIBULTRAGUI_DIR is forwarded for the builds that compile no HUD of their own; android checks the library out for that. The HUD's own Vulkan backend stays, renamed HudRenderBackend so it no longer collides with rx::ui::GuiRenderBackend. It keeps the growing descriptor pool chain a vanilla Scaleform screen's art needs, which the engine's single fixed block does not hold; it can go when that lands in rx::ui. The flake stops reading the siblings out of one developer's home directory. All six (rx, zetanet, nanobuf, libultragui, kinema, equilibrium) are fetched from github at the revisions build.yml pins, with submodules wherever CI checks them out recursively, so the sandbox and CI compile the same engine on any machine. What git does not carry does not arrive: rx's FidelityFX/DLSS/NRD/Jolt SDKs are downloads, so that build configures with those features off and a working copy stays the way to build with them. equilibrium moves to the head of devel5, the branch .gitmodules names and the pin had drifted off: a commit on no branch at all, five behind devel5 and one ahead, reachable by sha alone. devel5 brings the STL out of base's production surface, the security pass behind it, and a string option that owns its value instead of pointing at the buffer it was parsed from (Force67/equilibrium#15) -- the bug that had RX_UI_SHOT writing captures to a filename made of freed memory. equilibrium also stops being welded to the submodule. It is where base:: comes from, and it was reachable one way only: third_party/equilibrium, checked out recursively, which drags in its own eight submodules (googletest, musl, mbedtls, tracy and the rest) that sit behind EQ_BUILD_TESTS and never compile here. Every CI job cloned all of them, and `src = self` carries no submodules at all, so the nix build could not see equilibrium in the first place. RECREATION_EQUILIBRIUM_DIR now names the checkout, the submodule stays the default, the sandbox gets a tarball input at the revision the submodule records, and the checkouts that only need equilibrium itself ask for one level instead of eight. With that and slangc (rx compiles .slang shaders now), `nix build` produces recreation, recreation-server and esminfo for the first time. The sibling pins move together, because the retarget needed fixes in three of them. zetanet spells out the <string.h> its bare mem* calls always needed (Force67/zetanet#2). libultragui can load a font from memory instead of only from a path (Force67/libultragui#5). rx uses that for the splash wordmark, which deletes the temp file it used to write, the pid in its name and the <unistd.h> that came with it -- the include MSVC does not have, and the reason a windows build of anything linking rx::ui failed (Force67/rx#60). Verified against rx 2198552: full build, 107/107 tests, and a windowed run that shows the plate and hands the frame back to the game's own UI when it expires. RECREATION_NET=OFF, the no-SDL3 path and an out-of-tree equilibrium all configure. `nix build .#default` completes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two portability fixes, both one-liners in effect, unrelated to each other beyond
living in this tree.
The splash no longer writes a font to disk
Splash::LoadFontmirrored Roboto out ofrx_fonts.rxpinto a temp file andhanded ultragui the path, because
FT_New_Facewas the only way into its textengine. The file needed a name no concurrent process would also pick — the
editor and a game starting together would otherwise delete each other's copy
mid-face — so it carried
::getpid(). That one call is the only reason<unistd.h>was in the module, and MSVC has no such header: any Windows buildthat links
rx::uifails on the include, which isrx::app, which is every rxapplication.
libultragui grew a memory loader for exactly this (Force67/libultragui#5), so
the archive's bytes go straight in:
The temp path, the pid, the write, the
Shutdown()unlink andfont_cache_path_all go with it — 30 lines out, 8 in. ultragui copies thebytes, so the
Vectorcan die at the end of the scope as it already did. Thesystem-font fallback is untouched: a tree whose
rx_fonts.rxpwas never packedstill gets its line of text.
Depends on Force67/libultragui#5. Merge that first, or this does not compile.
<cstring>in ocean_fft.ccOceanFftcallsstd::memcpyand never included<cstring>; it arrivedtransitively through equilibrium's headers. equilibrium removed the STL from
base's production surface (Force67/equilibrium#14, now on
devel5), so theinclude has to be where the call is. This is the entire fallout of that change
in rx — one file.
Verification
Built through a consumer (recreation) against libultragui#5 and equilibrium
devel5: engine, game and tools compile and link. Running the plate:and no
rx-splash-*.ttfis left anywhere under the temp dir, where the old pathwrote one per process.