Two defects made packaged macOS games fail at window creation:
1. The bundled MoltenVK_icd.json used a relative library_path; the Khronos
loader resolves it with dlopen() against the process cwd / system dirs,
never the manifest directory, so MoltenVK was silently ignored and the
surface extensions were missing. bootstrapBundledVulkan() now rewrites the
manifest with the absolute dylib path before setting VK_ICD_FILENAMES.
2. vk-bootstrap dlopens its own libvulkan (vulkan.hpp DynamicLoader, which
even throws 'Failed to load vulkan library!' on machines without a system
Vulkan), so the VkInstance was created by a DIFFERENT loader than the one
SDL cached; SDL_Vulkan_CreateSurface then could not resolve the surface
functions. createInstanceAndDevice now seeds the Vulkan-Hpp default
dispatcher from SDL_Vulkan_GetVkGetInstanceProcAddr() and marks
vkb::InstanceBuilder loaded, so the instance is built through the same
bundled loader SDL uses.
The SDK eve carries INSTALL_RPATH @loader_path/../lib for the bin/+lib/
SDK layout, but 'eve package' places the copied lib/ tree at <out>/lib
next to the eve binary, so dyld failed with '@rpath/libz.1.dylib' not
loaded. Add @loader_path/lib to the RPATH and make bootstrapBundledVulkan
check exeDir/lib (package layout) in addition to ../lib (SDK) and
../Frameworks (.app bundle).
Gradle lintVitalRelease (consumer android build) rejects
PendingIntent.getBroadcast with flags=0 on modern Android
(UnspecifiedImmutableFlag). minSdk is 24, so FLAG_IMMUTABLE (API 23+)
is safe unconditionally.
The APK template declared EVTestActivity (the zeroerr test host) as the
MAIN/LAUNCHER activity, so a game packaged with ve build android opened the
test host (which unpacks assets/test, absent from a game APK) instead of the
game. Point the launcher at EVEngineActivity (unpacks assets/game and runs
ve run <game>); the test suite already starts EVTestActivity explicitly via
am start. test-sdk.sh now fails the android SDK smoke if the launcher regresses.
Frame readback (saveFramePng/getPixel) previously crashed the WASM runtime
when called from the playground bridge: emscripten_sleep inside a deep
JS->Squirrel->Graphics call chain breaks ASYNCIFY (rewind hits 'unreachable').
- add async two-phase readback to the webgpu backend (beginFrameReadback /
frameReadbackStatus, pumped from present() so the map callback is delivered
on the browser event loop without sleeping)
- bridge: eve_playground_capture / eve_playground_readback_status /
eve_playground_read_bytes (binary-safe VFS read)
- playground: 截图 button captures the current frame and previews the PNG
- bump ASYNCIFY_STACK_SIZE and TOTAL_STACK (1 MiB) for deep native chains
- export HEAPU8 for binary reads from the page
Adds a self-contained browser playground (editor + canvas + console + REPL)
around the Emscripten WebGPU build, plus the engine fixes required to render:
- JS<->Squirrel bridge (apply/eval/read/pause) and Emscripten 6 exports
- soft hot-reload via load.nut handle_change with __pg state preservation
- fix Uint16 index buffer byte sizes in SetIndexBuffer calls
- fix dangling GbufferSlot/SceneColorSlot gpuHandle pointers (std::move bug)
- fallback shadow depth texture when no shadow map is configured
- fix WGSL syntax (mod/ivec2) and default shadow sampler maxAnisotropy
- serve_webgpu.py COOP/COEP server and playground docs/demos/assets
SDL_Vulkan_CreateSurface fails with "Installed Vulkan does not implement
the VK_KHR_surface extension" on player machines when only libvulkan is
shipped: on macOS that extension comes from MoltenVK, which the old
packaging never bundled.
- cmake/macosx_bundle_vulkan.cmake: install-time step that copies
libvulkan.1.dylib + libMoltenVK.dylib + MoltenVK_icd.json into
<prefix>/lib, rewrites the manifest library_path to the relative
libMoltenVK.dylib, rebases eve loader reference to
@rpath/libvulkan.1.dylib, sets @rpath ids on the dylibs and re-signs
ad-hoc (install_name_tool invalidates the original signature).
- install_sdk.cmake: run the bundling step for macosx (third-party dylib
copy unchanged).
- platform/macosx: bootstrapBundledVulkan() locates ../lib or
../Frameworks next to the executable and points VK_ICD_FILENAMES at the
bundled manifest (respecting an explicit user override).
- window/sdl: load the bundled loader via SDL_Vulkan_LoadLibrary before
creating the SDL window so SDL does not rely on system search paths.
- docs: publishing flow now ships lib/; players no longer need the SDK.
* chore(ci): add clang-format gate, CODEOWNERS and agent collaboration rules
* refactor(modules): clear remaining back-edges and split the largest TUs
Three known dependency back-edges are gone (module_depgraph.py KNOWN_BACK_EDGES
is now empty; --check passes with 0 violations, 0 cycles):
- window -> graphics: window queries the new IWindowSurfaceHost capability
(common/WindowSurfaceHost.h) instead of holding a Graphics pointer;
Window::setGraphics was removed and all call sites updated.
- window -> image: Window::setIcon was replaced by setIconRGBA(const uint8_t*,
w, h); the window no longer decodes ImageData.
- scene -> graphics: pickScreenAt / collectFrustumIdsAt implementations moved
to graphics/ScenePicking.cpp (graphics -> scene is a legal downward edge);
scene now depends only on spatial.
TU splits (pure moves, verified identical method sets and brace balance):
- vulkan/Graphics.cpp (5118 lines) -> Graphics.cpp (lifecycle), GraphicsPipeline,
Graphics2D, Graphics3D, GraphicsMesh + shared GraphicsInternal.h.
- scene/Scene.cpp -> Scene.cpp (script layer / host lifecycle / serialization)
+ SceneNodes.cpp + shared SceneInternal.h.
Verified with a real build (MSVC 19.51, prebuilt third-party): full build green;
window.* and Scene.* suites pass, including scene picking/culling and GPU cases.
* refactor(graphics): narrow Graphics interfaces and clear public-header leaks
Step 4 — interface segregation:
- New lean interfaces: IGraphics2D, IGraphics3D, IResourceFactory, IPostFX
(pure virtuals, forward-declared types only; graphics/Color.h extracted from
Canvas.h so modules that only need the color type stop pulling Canvas.h).
- Graphics now implements all four facets; consumers can depend on the narrow
interface they use instead of the 129-method god class.
- Migrated voxel (VoxelWorld::drawVisible -> IGraphics3D*) and model3d
(ModelRenderer::buildRenderable(s) -> IResourceFactory&).
- Graphics.h slims from 24 sub-header includes to a handful of small type
headers + forward declarations; the destructor moved out-of-line so
unique_ptr effect members are destroyed where types are complete.
Step 5 — header leaks (module_depgraph.py '*' marks: 14 -> 7):
- map/TileLayer.h, particles/ParticleEmitter.h, avatar/AvatarInstance.h,
animation/SpineAnim.h, map/TileSystem.h, model3d/ModelData.h,
model3d/ModelRenderer.h, audio/Audio.h + Source.h, image/ImageData.h +
Image.h, dialogue/Dialogue.h, procgen Palette/OutputSpec/TextureRecipe/
PbrMaterial -> forward declarations, includes moved to .cpp.
- voxel/VoxelWorld.h: terrain sampler Pimpl'd (unique_ptr + out-of-line
destructor), removing the procgen header dependency.
- gpgpu/vulkan backend headers stop pulling graphics/vulkan/Graphics.h.
- Remaining '*' marks are deliberate: tiny POD/enum headers (GridConfig,
MapObject, BlendMode, Color), an internal backend header
(GraphicsInternal.h -> filesystem), and lean interface references.
Verified with a full clean build (MSVC) and tests: window/Scene/voxel/
RenderSystem/Quad/shader/TextureSampler/resourceLifetime pass; broad suite
only shows the pre-existing PHYSFS-init filesystem-environment failures.
* feat(resources): revive ResourceManager as unified IAssetReloader-backed cache
* fix(resources): leak ResourceManager singleton to avoid exit-time teardown crashes
Cached CPU resources may own third-party handles (FreeType faces, Assimp
scenes, image decode handlers) whose libraries are torn down at process
exit in an unspecified TU order; destroying cached entries from the
singleton destructor can segfault at exit (seen on CI Windows in
model3d.materialApi.objMtl). Keep the singleton alive until OS reclaim;
explicit unload()/clear() still release entries during the run.
* refactor(devtools): consume business modules through capability interfaces
DevTools / cmdline no longer include business-module headers, so trimming
scene / physics / procgen / particles / audio / ui / graphics no longer
requires disabling devtools, and devtools can be switched off with
-DEVENGINE_MODULE_DEVTOOLS=OFF.
New capability interfaces in common/:
- ISceneQuery (scene) - host/node inspection + mutation + transform sync
- IRenderCapture (graphics) - render status, PNG capture, camera control,
visible-entity snapshot, entity-ID mask, G-buffer PNGs
- IPhysicsQuery (physics) - 2D world lifecycle + ray casts
- IProcgenQuery (procgen) - recipe listing, map/mesh generation
- IParticlesQuery (particles) - emitter status + one-shot emit
- IAudioQuery (audio) - volume / stop-all
- IEditorHost (ui) - declarative editor host (used by cmdline too)
Providers register in their module constructors. DevTools rewires McpServer
(render/scene/procgen/physics/particles/audio/host tools), SceneInspect
(now delegates to ISceneQuery + IRenderCapture) and RenderVision (uses
IRenderCapture::capturePngDataUrl); cmdline/Mcp.cpp uses IEditorHost.
manifest: devtools DEPS graphics scene physics procgen particles audio ui
image event filesystem -> event; cmdline DEPS filesystem ui -> filesystem.
Verified: full build green; devtools.mcp.* tests pass; broad suite shows
only the pre-existing PHYSFS-init filesystem-environment failures.
* style: apply clang-format to changed lines after dev merge
* fix(webgpu): include RenderControl/TextureSampler explicitly after Graphics.h slimming
* fix(webgpu): provide newFont/print stubs to satisfy IGraphics2D/IResourceFactory vtables
* fix(common): make ProcgenQuery.h self-sufficient (cstdint/utility for GCC)
- release.py: use explicit refs/heads + refs/tags refspecs everywhere (short
refspecs are ambiguous when the release branch and tag share a name, and git
refuses to push them); rebase dev onto the branch's -dev write-back instead
of the official tag; add a real-git integration test suite.
- version single-sourcing: fix config.h.in PATCH macro bug and include -dev;
derive Android versionCode; sync required version touchpoints in start and
enforce them via check-versions in CI.
- SDK: exact version assertions in test-sdk.sh, publish-time VERSION cross-check.
- workflows: converge toolchain versions to repo vars, SHA-pin actions, add
Dependabot config.
Add a development-server based remote hot reload so script/resource changes
made on the host are synced and reloaded live on devices whose game bundle is
read-only (iOS app bundle, Android APK).
- Implement the previously stubbed `eve dev` command as a small HTTP file
server (GET /manifest, /raw/<path>, /ping) serving a game directory.
- Extend HotReload with a background remote-sync client: poll the server
manifest, compare mtime/size, download changed files into a writable overlay
directory mounted at "/" via the new Filesystem::mountRealDirectory, and
queue changed virtual paths for the script layer to dofile/reload.
- Wire it into load.nut: config.devServer/devSyncMs, shared handle_change(),
poll_remote_reload(), and a `eve run --dev-server <url>` CLI override.
- Add iOS/Android hot-reload dir helpers and cleartext-HTTP platform config
(iOS ATS + NSLocalNetworkUsageDescription, Android usesCleartextTraffic).
- Add test/remotesync.cpp covering overlay shadowing, end-to-end sync, and
unreachable-recovery; update docs.
Replace the bouncing-squares demo with a 48x24 lit sphere that rotates around Y, exercising the offscreen scene-color pass, mesh3D shader, and swapchain compositing path that was just fixed.
- Link eve to eve.html via --shell-file so the shell template is actually applied and regenerated on every build; track the shell as a link dependency.
- Keep C++ exception catching enabled under ASYNCIFY so expose() failures abort cleanly instead of asserting on __cxa_throw.
- ModuleManager::exposeVM no longer find()+catch for the eve table: Runtime::initialize() guarantees expose() runs once, and ASYNCIFY-wrapped frames can drop the catch and leak NotFoundException.
- Expose window.hideEVELoading and call it on the first presented frame so the shell's loading overlay is dismissed.
- FileWatch.h includes common/config.h so EVENGINE_WEBGPU is defined before the Poco guard.
- Added support for the WebGPU backend in the CMake configuration, enabling builds for Emscripten and native Dawn.
- Implemented conditional compilation for WebGPU-specific features, including shader management and file system handling.
- Updated the build process to exclude unnecessary modules and dependencies for WebGPU, optimizing the engine for browser environments.
- Enhanced the installation script to include WebGPU-related files and directories in the output.
- Refactored existing modules to accommodate WebGPU, ensuring compatibility and performance improvements across the engine.
- Introduced new compile options and configurations tailored for WebGPU builds, including handling of third-party libraries and assets.
Adds EVENGINE_ANDROID_TEST_APP build mode: the unit_test sources are
compiled into libmain.so (SDL entry) and packaged by the existing Gradle
APK along with the test assets, so the full zeroerr suite can run on a
device via adb logcat.
- test/main.cpp: Android runner with LogcatBuf (cout/cerr -> logcat),
chdir to <files>/evengine_test, SDL_Init; keeps SDL_main symbol unmangled.
- test/PathBesideSource.h: shared pathBesideThisSource helper that maps
__FILE__ to the on-device unpacked tree on Android.
- EVTestActivity: unpacks assets/test + assets/examples to internal
storage and passes an optional --testcase filter from an intent extra.
- test/CMakeLists.txt: builds `main` instead of unit_test on Android,
excludes desktop-only devtools tests, links Android system libs.
- Makefile: build/android-debug-test, sync/android-test-assets,
run/android-test-debug, log/android-test targets.
- Gradle wrapper bumped to 8.5 for Java 21 compatibility.
- Added setIcon and getIcon methods to the Window interface for managing application icons.
- Implemented setIcon in the SDL window class, ensuring compatibility with RGBA8 image formats.
- Introduced a new test case to validate icon setting and retrieval functionality.
- Updated documentation to reflect the new icon management features.
- Removed UWP platform from the available build options in CMake.
- Deleted the UWP-specific CMakeLists.txt file.
- Added comprehensive tests for various map projection methods, including isometric and staggered projections, to ensure accurate tile-to-world and world-to-tile conversions.
These changes streamline the build configuration and improve the testing coverage for map projections.
- Updated .gitignore to include new build and output directories for SDK packaging.
- Modified CMakeLists.txt to include installation script for SDK.
- Enhanced Makefile to support new SDK targets for various platforms.
- Improved documentation to reflect new shader capabilities and 3D model support.
- Added new shader functions and updated rendering systems to utilize custom shaders.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Added support for selecting between demo and example game assets in the Makefile and CMakeLists.txt.
- Updated the build process to handle different game directories based on the selected game type.
- Improved the run commands for various platforms to utilize the specified game directory.
- Refactored comments for clarity regarding the game asset bundling process in iOS.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced a new optional demo module that includes procedural sound effects and planet texture generation.
- Updated the build system to support the demo module with the `EVENGINE_BUILD_DEMO` option.
- Enhanced the Makefile to synchronize game assets into the APK during the build process.
- Modified the AndroidManifest to set the screen orientation to portrait for better compatibility.
- Improved documentation to reflect the new demo features and asset synchronization process.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Removed obsolete game configuration and main script files from the assets directory.
- Introduced new configuration file for the APK shell, allowing for dynamic width and height settings based on device display size.
- Added a root script for initializing the game engine with version information.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add UIKit path/audio/safe-area helpers, Info.plist for device family 1+2, and LaunchScreen for the arm64 app shell.
Co-authored-by: Cursor <cursoragent@cursor.com>
Unpack APK game assets into internal storage, route SDL_main into the engine cmdline entry, and keep Android filesystem paths aligned with the runtime root.
Co-authored-by: Cursor <cursoragent@cursor.com>
Package an arm64 SDLActivity app shell that loads libmain and ships the example game assets, with Android 14 receiver export compatibility for HID.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced platform-specific CMake configurations for macOS, including the addition of the EVPlatformMacOSX library.
- Enhanced Vulkan integration on macOS by requiring the LunarG Vulkan SDK and ensuring proper setup instructions in the documentation.
- Updated the Makefile to support macOS build targets alongside Windows and Linux.
- Improved CMakeLists and source files to handle platform-specific libraries and dependencies more effectively.
- Added detailed instructions for macOS setup in the README, including environment configuration for Vulkan SDK.
- Refactored existing code to ensure compatibility with macOS, including adjustments in event handling and graphics functionality.