Commit Graph
243 Commits
Author SHA1 Message Date
github-actions[bot] a136e1b865 release: 0.2.0 2026-08-22 12:09:26 +00:00
西风逍遥游 a6e9db4086 test(docs): expand map/rpg/building coverage matrix + accessor round-trips
Add §17b–§17d API detail tables to docs/dev/测试覆盖.md for map, rpg and
building (all rows now '已展开'), backed by a fresh audit of the existing
70+ map cases, 28 rpg cases and 15 building cases.

Fill the audit gaps with two compact accessor tests:
- map.path.accessorRoundTrips: diagonal, blockEmpty, cellCost getter,
  unblockGid/clearBlockedGids, invalidateCache, setBlocked/isWalkable.
- map.fov.accessorRoundTrips: cornerPeek, eyeOffset, cliffBlock,
  verticalRange, perceptionRadiusScale, revealerPosition3/perception,
  revealer count and unknown-id behavior.

Local win32-debug: map/map_fov/map_path bundles pass.
2026-08-22 17:13:22 +08:00
西风逍遥游 5624388f1c test(event): cover Event::wait with a pre-queued message
The blocking-wake path was already covered by event.workerPushWakesWait;
add the queued-message fast path (wait returns immediately). Update
docs/dev/测试覆盖.md §9: wait marked 已覆盖.
2026-08-22 14:05:43 +08:00
西风逍遥游 d995497842 Merge remote-tracking branch 'origin/dev' into codex/headless-tests-ci 2026-08-22 12:57:15 +08:00
西风逍遥游 ff77852fcd Merge pull request #176 from EVEngine/codex/thread-test-gaps
test(thread): close last API gaps + fix JobSystem use-after-free found by ASan
2026-08-22 12:56:46 +08:00
西风逍遥游 3e9d2814fa Merge pull request #171 from EVEngine/codex/cmdline-fixes
feat(cmdline): eve get/build 基于官方 release SDK,release CI 增加消费侧全链路验证
2026-08-22 12:38:40 +08:00
西风逍遥游 c47e061181 test(thread): cover Channel::demand and Thread::postMain
Fill the last thread-module API gaps: blocking demand() and cross-thread
postMain() into the Event queue (same-thread, empty-name throw, worker
thread). 46/46 thread bundle cases pass locally on win32-debug. Update
docs/dev/测试覆盖.md: thread row to '已展开' with a full API detail table.
2026-08-22 12:22:31 +08:00
西风逍遥游 2d079b39ef ci(linux): verify headless GPU tests run without Xvfb
Add a dedicated Linux step that runs the six headless GPU bundles
(graphics_font, TextureSampler, gpgpu, tensor, virtualgeometry_gpu,
graphics_headless) with no display server — proving the headless-vs-window
policy in docs/dev/测试覆盖.md §0. The regular xvfb run keeps covering the
full suite including windowed demo tests.
2026-08-22 11:54:15 +08:00
西风逍遥游 a7ec3938b7 test: adopt headless graphics for functional GPU tests, keep windowed demos
Introduce the headless-vs-window test policy (docs/dev/测试覆盖.md §0):
functional GPU tests run via Graphics::initHeadless + offscreen canvas
readback; visual/demo tests (ClassicScenes, RenderImageAudit, animation,
voxel, particles, UI, swapchain-readback cases) keep real windows.

Mechanics:
- Graphics::initHeadless is now re-entrant: the process-wide singleton
  updates the logical viewport on repeat calls instead of throwing, so
  multiple cases in a bundle can share one headless device.
- test/Fixtures.h adds openHeadlessGfx() and a useHeadless mode for
  GfxFixture; EVENGINE_TEST_VIEW_W/H overrides apply to both paths.

Migrated (window-free, no behavior change to assertions):
- test/graphics_font.cpp: atlas + print-to-canvas pixel readback; the
  interactive debug-preview loop is guarded by isHeadless().
- test/TextureSampler.cpp: sampler parameter round-trips.

graphics_headless.cpp now asserts the re-entrant resize semantics.
2026-08-22 11:12:43 +08:00
西风逍遥游 80aca00f67 Merge remote-tracking branch 'origin/dev' into codex/cmdline-fixes
# Conflicts:
#	src/engine/cmdline/Doc.cpp
2026-08-22 10:45:21 +08:00
西风逍遥游 55184c7e4a docs(release): document the consumer-side validation gates in the release flow 2026-08-22 10:38:12 +08:00
西风逍遥游 432c0722fb docs: list literal API names in new chapters so check_bindings passes
avatar/database/dialogue/sceneloader/stylize/virtualgeometry now list
getName(); camera spells getTargetX/Y/Z out in full. These chapters are
gated by scripts/check_bindings.py --strict in CI.
2026-08-22 08:36:13 +08:00
西风逍遥游 18205aabb9 docs: add 10 module chapters, voxel example, gallery links; fill script binding gaps
- New user docs: avatar, buildingfx, camera, database, dialogue, grid,
  housegen, sceneloader, stylize, virtualgeometry (all written against the
  actual addFunc surfaces; API quick-refs included). Wire them into MODULES.md.
- examples/voxel: streaming terrain + place/break demo (procedural atlas,
  setTerrain + streamAround, DDA raycast picking, orbit camera). Script logic
  verified locally (no script errors; 16 chunks / 3117 rects selected).
- README gallery links in both Readme.md and Readme.en.md.
- Script binding fixes discovered while writing the docs/examples:
  * Graphics.setCanvas accepts null (and Canvas instances) so canvas sessions
    can be ended from scripts; begin3DFrame/setMesh3DViewProj/setMesh3DView/
    setMesh3DCameraPos now exposed for script-driven 3D (voxel etc.).
  * SceneLoader.load/host exposed (previously only reload/status were bound).
2026-08-22 08:27:43 +08:00
西风逍遥游 7437224c90 api(graphics): align C++/script names, validate sampler strings, document error contracts
- Add RGBA-float drawSolidRect/drawTexturedRect overloads so the C++ names
  match the script-facing API (script already bound those names).
- Add string-based setTextureSampler(Texture*, filter, mipmap, aniso, lodBias)
  overload with strict magic-string validation (unknown filter/mipmap now
  throws instead of silently falling back to linear); keep
  setTextureSamplerParams as a deprecated alias. Script binding now targets
  the overload with an explicit cast.
- Document error contracts: DataModule encode/decode (new[] ownership +
  throws), Filesystem setSource/mount/unmount (false on recoverable failure,
  no throw), ModelData getMesh vs numeric getters (nullptr vs throw), plus a
  two-state error-semantics section in API-CONVENTIONS.md.
- Tests: TextureSampler string validation (valid + deprecated alias + typo
  throws), headless test now exercises the RGBA-float overloads.
2026-08-22 02:30:12 +08:00
西风逍遥游 87b2731fb6 Merge remote-tracking branch 'origin/dev' into codex/examples-devx-ai-native
# Conflicts:
#	Makefile
2026-08-22 00:50:23 +08:00
西风逍遥游 70a0841c16 Merge pull request #164 from EVEngine/codex/example-render-gallery
docs: 新增示例渲染画廊(真实引擎帧截图)
2026-08-22 00:03:51 +08:00
西风逍遥游 9b5d6f654d feat(common): expose Runtime reflection API to scripts as eve.reflect
Runtime::initialize() now adds an eve.reflect sub-table binding the reflection layer (classes/classInfo/scan/scripts, createInstance, inspect/read/write/readObject, array*/table* editing) so Squirrel tools and editors can introspect and edit script classes and instances with the same semantics as the C++ Runtime API.

Scalar reads/writes keep the slot's own type; container/instance slots are read as live script objects; mutators return false instead of throwing on missing or method members. Adds test/ReflectScript.cpp covering the full surface.
2026-08-21 23:26:47 +08:00
西风逍遥游 8af30cb1d3 docs: resolve merge with dev, keep gallery link in user guide 2026-08-21 22:50:38 +08:00
西风逍遥游 e3ad78d30c docs: add example render gallery with real engine captures
Render 14 examples with the prebuilt eve host and capture the actual
swapchain frame via gfx.saveFramePng (capture_root.nut wrapper), then
publish the PNGs under docs/images/examples with a gallery README and a
link from the user guide.

Adds scripts/capture_example.ps1 + scripts/capture_root.nut for
regenerating the captures on any example.
2026-08-21 22:48:40 +08:00
西风逍遥游 ef83a2eb89 Merge remote-tracking branch 'origin/dev' into codex/examples-devx-ai-native 2026-08-21 22:28:12 +08:00
西风逍遥游 4fc5277ff1 Merge pull request #161 from EVEngine/codex/gpu-driven-rendering
GPU-driven rendering: bindless + indirect draw + GPU cull + visibility buffer/resolve + VirtualGeometry integration
2026-08-21 21:40:20 +08:00
西风逍遥游 453d33387f Merge remote-tracking branch 'origin/dev' into codex/gpu-driven-rendering
# Conflicts:
#	AGENTS.md
#	external/VKBuilder
#	src/modules/graphics/Graphics.h
#	src/modules/graphics/RenderControl.cpp
#	src/modules/graphics/RenderSystem3D.cpp
#	src/modules/graphics/vulkan/Graphics.cpp
#	src/modules/graphics/vulkan/Graphics.h
2026-08-21 20:45:42 +08:00
西风逍遥游 4c6f27d0f5 Merge pull request #158 from EVEngine/codex/runtime-inspector-mvvm
feat(ui): reflection-driven property inspector (MVVM DevTools)
2026-08-21 20:19:48 +08:00
西风逍遥游 11c6444853 Merge pull request #160 from EVEngine/codex/state-hot-reload
feat: state hot reload for scripts and state machines
2026-08-21 20:19:38 +08:00
西风逍遥游 4dc084c673 Merge remote-tracking branch 'origin/dev' into codex/examples-devx-ai-native
# Conflicts:
#	Readme.en.md
#	Readme.md
#	docs/usr/README.md
2026-08-21 19:49:06 +08:00
西风逍遥游 54dea0d561 feat: state hot reload for scripts and state machines
Adds a capture -> reload -> restore pipeline so code/asset changes can be hot-applied without resetting running state:

- common: StateValue (JSON-compatible state tree) + IStateProvider capability interface.
- devtools: Snapshot v2 (script roots + native provider section, v1 compatible, strict rejection of non-data roots), ReloadSession (begin/commit/abort), eve.dev script API (stateRoots / beginStateReload / commitStateReload / abortStateReload).
- load.nut: three-phase soft reload (capture -> dofile -> restore) with migrate_instance / remap_instances helpers and eve_before_reload / eve_after_reload hooks.
- dialogue + AnimStateMachine: IStateProvider for phase/vars/rng and params/current state.
- animation: AnimClip::adopt + AnimClipRegistry + 'animclip' IAssetReloader so .eva content reloads keep clip identity.
- rpg + card: IStateProvider for casting/cooldowns and card phases.
- Tests: stateValue, snapshot v2/strict, reload script protocol, dialogue, animation state machine + reload, rpg/card state roundtrips.
2026-08-21 19:46:25 +08:00
西风逍遥游 f7962f43fe feat(examples): developer-experience and AI-native showcase examples
- devlab: flagship --debug example (console/snapshot/AI panel/pause/hot
  reload/error slice), make devlab target with RUN_ARGS support
- ai-game: agent-drivable live game + agent_demo.py (pause/read/mutate/
  verify/snapshot/restore/screenshot loop)
- ai-editor: headless eve mcp editor host demo (JSON View + ViewModel MVVM)
- examples: fill all missing READMEs + config.nut, add examples/ index
- load.nut: add key_just_pressed/clampf/persist helpers; dedupe 19 examples
- rpg/cardgame: move JSON definitions to data files
- fix eve mcp crash: ModuleManager::requireAll() instantiates modules in
  the headless host (IEditorHost etc. were null)
- graphics: actionable screenshot error when readback was just enabled
- CI: smoke all examples (devlab with --debug) + DevLab hot-reload test

Fixes surfaced by the new CI smoke (examples had never been smoke-tested):
- scene_director kit: camera slot doubled as function + instance and was
  nulled by reset(); move the live Camera3D into cameraObj
- readTextFile used non-existent readn()/len(); use file.read()
  (rpg/cardgame/hex-levels)
- daynight used non-existent keyboard.wasPressed() -> key_just_pressed
- outline passed ints to float-only drawSolidRect; linear-structures
  slider passed an int value
- scene-ecs beginNode() requires (id, name); ai-stage guarded compilestring
- smoke_examples.sh: timeout -k 3 so SIGTERM-ignoring hosts cannot hang CI
2026-08-21 19:18:52 +08:00
西风逍遥游 4f527476fa Merge pull request #157 from EVEngine/codex/docs-user-docs-and-doxygen-sidebar
docs: rework user docs and rebuild the Doxygen sidebar
2026-08-21 18:47:15 +08:00
西风逍遥游 96dae32c38 feat(ui): DevTools panel suite - database grid, nested editing, scene tree, editor shell 2026-08-21 18:15:59 +08:00
西风逍遥游 c79f5e8042 docs: make light/dark switching robust in embedded browsers
- Harden the doxygen-awesome dark-mode toggle against blocked localStorage
  (sandboxed webviews / file://): storage failures no longer break theme
  initialization or the toggle click.
- Add a CSS-only prefers-color-scheme fallback so dark mode still follows the
  OS/app scheme when scripting is unavailable.
2026-08-21 17:43:48 +08:00
西风逍遥游 06061d9d99 feat(ui): reflection-driven property inspector (MVVM DevTools) 2026-08-21 17:34:26 +08:00
西风逍遥游 d86f9eceec docs: rework user docs and rebuild the Doxygen sidebar
- Readme (zh/en): make "download prebuilt SDK, no build" the primary path for
  game developers; move build-from-source content under an engine-developers
  section.
- Rewrite docs/usr/README.md: download/run, capabilities, debugging,
  packaging, and a "things to keep in mind" section.
- Unify wording in MODULES/TRIMMING/dev docs and the SDK README.
- Replace the JS treeview with a plain-HTML static sidebar (home, user guide,
  module handbook grouped into 5 categories, API indexes) so docs navigate
  without JavaScript.
- Add a Doxygen landing page and page-hierarchy wrappers generated by
  docs/CMakeLists.txt; tune Doxyfile for the static layout.
2026-08-21 17:05:51 +08:00
西风逍遥游 5065d0a91b merge: integrate origin/dev (PR #134 JobSystem, #151-#154) into codex/framegraph-mt-render
dev is the repo's feature branch (main is release-gated to promote/docs PRs).
Resolved JobSystemThreadPool.cpp to our completeJob ordering (decrement
outstanding counters after fireCompletion/releaseDependents) — dev's merged
PR #134 version kept the pre-fix order that can reset the frame arena under a
still-running worker.
2026-08-21 12:57:16 +08:00
西风逍遥游 95b869cbbd merge: integrate origin/main (TU split, #129 perf, module decoupling) into codex/framegraph-mt-render
Port the deferred FrameGraph integration onto main's split Vulkan backend:
- Graphics3D.cpp owns buildDeferredFrameGraphs / recordDeferredFrameGraph /
  recordShadowCascadePass / recordGBufferPassDraws (parallel JobSystem
  recording, one command pool per frame-slot per pass).
- begin3DFrame / beginSwapchainRenderPass / flushToSwapchain 2D-only path
  call recordDeferredFrameGraph() instead of the serial pending passes.
- Drop the superseded serial recordPendingShadowPasses/GBufferPass and the
  duplicate culling implementation (main's RenderSystem3D already carries
  the per-camera / per-cascade frustum culling).
- VKBuilder submodule -> 51514d9 (master; our spec-safe pool/lifecycle PR
  was merged upstream as sunxfancy/VKBuilder#2).
2026-08-21 12:48:49 +08:00
西风逍遥游 0ca17b9a57 feat(render): enforce spec-safe parallel recording via per-pass command pools and RecordCycle lifecycle 2026-08-21 09:35:25 +08:00
西风逍遥游 d786e18fa9 feat(animation): add 3D lattice scale-deformer (AnimLattice)
CPU trilinear lattice deformation for procedural 3D scale/squash-stretch
animation: per-control-point scale + offset, model/array binding, deformed
position/normal cache, script API (anim.newLattice + AnimLattice class) and
gfx.newMeshFromArrays / gfx.updateMeshVertices script wrappers so scripts can
upload deformed meshes per frame. Includes unit tests and the
examples/lattice-deform demo.
2026-08-21 01:08:35 +08:00
西风逍遥游 d4936d12dc docs(framegraph): record parallel-recording verdict (driver-level AMDVLK crash)
TSan (WSL) proves the JobSystem + executor + framegraph planning are
data-race-free; on Windows the parallel record path AVs inside
amdvlk64.dll from vkb::FrameGraph::record's recordOne on two workers, and
still crashes after device->waitIdle() — an AMDVLK concurrent-recording
defect, not a pending-CB reuse issue. Engine keeps serial recording; the
executor stays available for drivers/CI builds that support it.
2026-08-21 00:35:47 +08:00
西风逍遥游 b684bf713d feat(render): move the 3 CSM shadow cascades into the deferred FrameGraph
Stage D (shadow part): each in-flight slot's FrameGraph now owns both the
shadow and G-buffer passes as declarative, dependency-free passes in one
layer. The CSM array is imported per cascade via its layer view with
arrayLayers=3 so barriers cover the whole array; every cascade ends in
DepthStencilReadOnlyOptimal for the engine-side forward pass to sample.

- recordPendingShadowPasses / recordPendingGBufferPass are gone, merged
  into recordDeferredFrameGraph(): graph record + submit before the
  swapchain pass, with a once-per-slot-per-frame guard so repeated
  render3D() calls in one script frame never re-record the same command
  buffers (resetting in-flight CBs hung the driver).
- buildDeferredFrameGraphs() rebuilds one graph per slot from the current
  shadow array + G-buffer targets; shadows can be enabled without a
  G-buffer pass and vice versa (graphs are built on demand).
- JobSystem fix (PR #134 scheduler bug): completeJob now decrements
  outstanding/outstandingFrame only after fireCompletion +
  releaseDependents have finished using the job. Previously a waiter
  (beginFrame/endFrame) could observe outstandingFrame == 0 and reset the
  per-frame arena while a worker still touched the job (use-after-free:
  lost forked job -> hang, or crash). Two stress tests
  (render_graph.jobSystemGroupStress, render_graph.jobSystemEngineFramePattern)
  cover the engine's exact beginFrame/parallel_for/task-group frame
  pattern.
- Recording stays serial (graph->record()) for now: the JobSystem
  help-execution path still has a residual timing-sensitive race that can
  leave a worker stuck in a pass callback. The parallel executor
  (jobSystemPassExecutor) is ready and CPU-tested; enable it once that
  race is root-caused upstream (documented in FrameGraphJobs.h).

Verified locally (win32-debug, full clean rebuild): render_graph.*,
thread.*, Shadow3D.*, RenderSystem3D.*, Lighting3D.*, Mesh.* and
AO/AA/Outline/GI — 77 cases pass.
2026-08-20 23:11:38 +08:00
西风逍遥游 674643c2da feat(graphics): GPU-driven phase 0 - bindless set, GPU tables, per-frame arena
- GpuDrivenCaps: probe + enable Vulkan 1.2 core features (drawIndirectCount,
  descriptor indexing, non-uniform indexing, update-after-bind) at device
  creation; the toolchain's Vulkan headers omit the core drawIndirect bit so
  it is assumed supported and left untouched.
- Bindless Set1: sampler2D array (4096) + samplerCube array (64) + SSBO table
  array (64) with PARTIALLY_BOUND | UPDATE_AFTER_BIND; textures register on
  creation, placeholder-filled with the 1x1 white texture/cubemap.
- GPU tables: GpuMeshRecord (bounds + index/vertex ranges) filled at mesh
  upload and GpuMaterialRecord built from Material params, uploaded to
  host-visible SSBOs with fixed capacity.
- FrameArena: per-frame-slot host-visible ring allocator, reset each
  begin3DFrame; unused until phase 1 (indirect draw).
- Tests: GpuDriven.capsAvailable / bindlessTextureRegistration /
  meshTableRegistration (GPU runtime verification pending driver recovery).

Rendering is unchanged: nothing consumes the new infrastructure yet.
2026-08-20 21:17:17 +08:00
西风逍遥游 ab1c398b6f feat(render): record the G-buffer pass through vkb::FrameGraph
Stage B of the FrameGraph migration: the G-buffer fill is now a
declarative FrameGraph pass recorded with the JobSystem executor and
submitted before the swapchain pass, replacing the hand-rolled
render-pass + manual begin/end layout tracking in recordPendingGBufferPass.

Design:
- One vkb::FrameGraph per in-flight present slot (framesInFlight=1),
  importing the engine-owned ColorTarget images via importTexture. The
  engine keeps image ownership, so renderEntityIdMask /
  readGBufferToImageData and the AO/outline/AA descriptor wrappers work
  unchanged.
- Each graph declares addPass("gbuffer") with 3 color attachments + 1
  depth attachment (clear ops matching the old path). compilePlan derives
  the dependency/barrier/layout plan; attachment->sampled transitions
  fold into render-pass initial/final layouts (ShaderReadOnly /
  DepthStencilReadOnly after the pass).
- recordPendingGBufferPass now runs recordFrameGraphWithJobSystem() +
  graph->submit() inside a JobSystem frame bracket; the graph's command
  buffer is recorded (serial for one pass today; parallel once shadow
  cascades join in Stage D) and submitted on the graphics queue before
  the swapchain pass. The graph's RP is render-pass compatible with the
  engine's gbuffer pipelines (same formats/samples/subpass layouts).
- Command-buffer safety without a swapchain-driven FrameGraph: each
  graph's CB is only reused two frames later, by which time the present
  slot fence (waited in Present::begin) guarantees the previous graph
  submit completed (same queue, submitted before the present CB).
  An upstream VKBuilder patch (swapchain-less frame advancement + fences)
  would let this collapse back to one graph.

Verified locally (win32-debug, full clean rebuild): render_graph.*,
thread.*, Shadow3D.*, RenderSystem3D.*, Lighting3D.*, Mesh.* and
AO/AA/Outline/GI (75 cases) all pass. Also fixed the test build's
stale-obj layout mismatch that made the new member corrupt ownedTextures
until the graphics module was rebuilt from scratch.
2026-08-20 20:46:16 +08:00
西风逍遥游 5c8046e85f feat(render): FrameGraph parallel-recording foundation on top of JobSystem
PR #134's secondary-command-buffer recording violated the Vulkan state
machine (secondaries began their own render pass instances without
pInheritanceInfo; the spec-compliant fix 1291df8 was reverted). Replace
that path with the groundwork for the vkb::FrameGraph migration:

- Drop the illegal secondary-CB deferred recording and restore the
  branch base's legal inline recording for shadow/GBuffer passes.
- Fix frame-prep culling regressions from PR #134:
  * per-item camera frustum culling (item.culled) instead of always
    testing against the main camera;
  * default-camera culling for the G-buffer pass (item.culledMain);
  * restore per-cascade CSM caster masks (item.cascadeMask).
  Camera view-proj matrices are snapshotted on the main thread before
  the parallel job forks; workers only read immutable data. The light
  job's CSM output is joined before the entity job forks so cascade
  culling never races with the shadow-upload write.
- Add FrameGraphJobs.h: vkb::PassRecordExecutor backed by the JobSystem
  (layer-internal fork/join via frame task groups, layers sequential),
  the exact executor the render backend will hand to FrameGraph::record().
- Add device-free tests (test/render_graph.cpp): the engine's target
  pass topology (3 CSM cascades + GBuffer in one parallel layer ->
  forward -> present) plans with attachment->sampled barrier folding
  (zero explicit barriers on forward/present), and the JobSystem
  executor records every pass exactly once, in parallel per layer.

Verified locally (win32-debug): render_graph.*, thread.*, Shadow3D.*,
RenderSystem3D.*, Lighting3D.* and Mesh.* all pass (58/58). Bundle-mode
SEGFAULTs are the known pre-existing zeroerr single-process issue, not
this change. See docs/dev/superpowers/specs/2026-08-20-framegraph-mt-render.md
for the staged migration plan (GBuffer into the graph next, then the
dedicated render thread).
2026-08-20 19:39:10 +08:00
西风逍遥游 e5b1f455a2 docs: link to the GitHub Pages docs site from the user guide 2026-08-20 16:16:39 +08:00
西风逍遥游 2ab09dcf68 feat(script): bind Image decode, Joystick Pad axes/buttons, Mouse relative mode
- Image: expose newImageData(newImageDataFromFile)/newEmptyImageData/isCompressed and a
  full ImageData script class (getWidth/Height/Format/Size, pixel get/set, paste, clone,
  rotate). ImageData is now registered once by the Image module; drop the duplicate
  minimal registrations in Font and Model3D that could overwrite each other.
- Joystick: expose getJoystick/getJoystickFromID/getIndex/addJoystick/removeJoystick and a
  Pad class with raw axes/buttons/hats, GameController axis/button names, device info,
  and vibration. Pads stay owned by the module (non-owning script handles).
- Mouse: expose setRelativeMode/getRelativeMode plus setVisible/setPosition/setX/setY/
  setGrabbed/isGrabbed (SDL backend already implemented them).
- Tests: add image.nut/image_script.cpp and joystick.nut/joystick_script.cpp script tests,
  extend mouse.nut with relative-mode/visibility checks, wire into test CMake and the nut
  embed template.
- Docs: update image/joystick/mouse user chapters, MODULES.md and the REVIEW log.
2026-08-20 12:31:11 +08:00
西风逍遥游 34d1fdb63b refactor(modules): clear remaining back-edges and split the largest TUs (#127)
* 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)
2026-08-20 05:53:33 +08:00
西风逍遥游 a195d4781f Merge branch 'dev' into codex/release-flow-sdk 2026-08-19 23:40:12 +08:00
西风逍遥游 da3e103ba9 Merge pull request #124 from EVEngine/feat/card-ecs
refactor(card): 用 ECS 持有卡牌运行时对象
2026-08-19 23:38:05 +08:00
西风逍遥游 38b70171fb fix(release): make sync-docs PR-based and release-aware
- compute main's changes since the merge-base with dev instead of per-commit
  cherry-picks, so merge/squash/rebase doc merges all work and dev-only work
  is never touched;
- allow release version touchpoints (RELEASE_PATHS) in the non-doc gate, fixing
  the spurious failure every sync-docs run after a non-ff release merge;
- sync by copying doc paths from main onto sync-docs/from-main and opening a
  PR to dev (no direct push), matching the PR-only branch model;
- docs updated in 发布流程.md and the release-branch-model spec.
2026-08-19 22:07:42 +08:00
西风逍遥游 b08657ab67 feat(sdk): package licenses, auto-export module headers, add plugin/APK smoke tests, checksums and branch cleanup
- install_sdk.cmake: export headers for exactly the modules the build enabled
  (EVE_ENABLED_MODULES from cmake/module_manifest.cmake) instead of a stale
  whitelist; package engine + vendored third-party licenses under
  share/eve/licenses/.
- test-sdk.sh: hard-gate native C++ plugin compile (find_package(EVEngine) +
  add_eve_plugin) on win32/linux/macosx; android now assembles an APK from the
  SDK template (gradlew assembleDebug) instead of skipping.
- sdk-release.yml: run the android APK smoke; publish generates SHA256SUMS,
  verifies every zip's share/eve/VERSION against the tag, uploads SHA256SUMS
  with the SDKs, and (best-effort) attests build provenance.
- release.py: new cleanup-branches subcommand deletes merged vX.Y.Z /
  promote/* / rebase/* branches (tags and main/dev are never touched);
  new cleanup-branches.yml runs it weekly + on demand.
- docs: SDK packaging and branch cleanup sections in 发布流程.md and the
  release-branch-model spec.
2026-08-19 21:57:52 +08:00
西风逍遥游 703f1fb7a5 ci(release): fix ambiguous refspecs, add version consistency and SDK hardening
- 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.
2026-08-19 21:50:02 +08:00
西风逍遥游 138072f513 feat(release): open PRs instead of pushing main and dest
finish no longer updates main or force-pushes dest. It opens promote/vX.X.X to main and rebase/vX.X.X to dest for a human merge, and posts the main-gate check so GITHUB_TOKEN PRs stay mergeable.
2026-08-19 20:53:05 +08:00