Skip to content

feat: Add WeChat MiniGame build support and platform adapter - #1

Merged
esengine merged 3 commits into
masterfrom
feature/platform-adapter
Feb 5, 2026
Merged

feat: Add WeChat MiniGame build support and platform adapter#1
esengine merged 3 commits into
masterfrom
feature/platform-adapter

Conversation

@esengine

@esengine esengine commented Feb 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add platform adapter architecture for cross-platform support
  • Add WeChat MiniGame build target with Emscripten flags for CommonJS compatibility
  • Add initRendererWithContext() to accept externally created WebGL context (avoids document.querySelector)
  • Add npm publish workflow
  • Bump SDK version to 0.3.0

Changes

  • cmake/Emscripten.cmake - WeChat-specific build flags (-sEXPORT_ES6=0, -sDYNAMIC_EXECUTION=0)
  • scripts/build-wxgame.sh - Automated build script for WeChat engine
  • src/esengine/bindings/WebSDKEntry.cpp - Add initRendererWithContext()
  • sdk/src/app.ts - Support glContextHandle option in createWebApp()
  • editor/src/builder/WeChatBuilder.ts - Generate game.js with JS-side WebGL context creation

Test plan

  • Build WeChat MiniGame project from editor
  • Run in WeChat DevTools
  • Verify rendering works without document.querySelector errors

- Add platform adapter layer for Web and WeChat separation
- Add WeChat-specific polyfills (fetch, wasm, fs)
- Multi-entry build: index.js (Web), index.wechat.js (WeChat)
- Add GitHub Actions workflow for npm publishing
- Add esengine_wxgame CMake target with WeChat-specific Emscripten flags
  (-sEXPORT_ES6=0, -sDYNAMIC_EXECUTION=0 for CommonJS compatibility)
- Add scripts/build-wxgame.sh for automated WeChat engine builds
- Add initRendererWithContext() to accept externally created WebGL context
  (avoids document.querySelector which doesn't exist in WeChat)
- Update SDK createWebApp() to support glContextHandle option
- Add Tauri commands for wxgame engine file access
- Update WeChatBuilder to create WebGL context in JS and pass to WASM
@esengine
esengine merged commit d10b76a into master Feb 5, 2026
4 checks passed
@esengine
esengine deleted the feature/platform-adapter branch February 5, 2026 07:46
esengine added a commit that referenced this pull request Jun 23, 2026
… P1.4d #1)

SDF text was hardcoded to layer 0 → drawn under all UI quads (layer 1000+).
Fix: a Text node in a UIRect is a UI render node — a PreUpdate system ensures it
carries a UIRenderer (visualType None, not drawn) so the UI render-order pass
assigns it a uiOrder; new ui_getRenderOrder binding exposes that order to TS, and
the glyph batch uses layer = UI_BASE_LAYER + uiOrder. Pixel-verified: white text
draws on top of a blue UIRenderer panel, centered + wrapped to the panel.
esengine added a commit that referenced this pull request Jun 23, 2026
…REARCH_GUI unification S4c)

The legacy Transform-based ScrollView was a dual implementation (the rearch's
#1 smell); the modern collection/ScrollContainer + ListView is the single
scroll path. Per the clean-break directive: delete it outright (no migration) —
ScrollViewPlugin.ts, ScrollView.ts, scrollview.test.ts, and all its plugin/
label/export references. One of the last two UIRect holders is gone.
sdk tsc clean; 2297 tests green.
esengine added a commit that referenced this pull request Jun 23, 2026
…r<struct> (REARCH_GUI F5)

Kills the audit's #1 worst component smell: StateVisuals' 8 hardcoded slotN*
field quartets (32 flat fields) read by stringly-keyed reflection
(record[`slot${i}Sprite`]). It's now a single variable-length
`std::vector<VisualState>` looked up by name.

EHT codegen — generalize to std::vector<CustomStruct>:
- type_system: VisualState added to CUSTOM_STRUCTS (string+primitive members,
  vector-only so it skips the pointer cursor); is_struct_vector/vector_elem
  helpers; struct-vector forces a JS wrapper and marshals as emscripten::val.
- embind: the wrapper field is an emscripten::val; from/toJS convert array↔vector
  element-by-element via the VisualState value_object (embind won't auto-convert a
  JS array to a registered std::vector, so a register_vector binding is not used).
- field_utils: struct-vector defaults to [] and is editor-skip.

Component + consumers:
- C++ VisualState POD (flat r/g/b/a so it round-trips through the vector path);
  StateVisuals.states replaces the 32 slot fields.
- TS state-visuals: states[] + a visualState(name, color, {sprite,scale}) builder;
  the apply system (behavior/systems) iterates states[] — no reflection.
- button/dropdown build states[]; STATE_VISUALS_SLOT_COUNT removed.

Verified: clean build -t web (ABI hash changed, expected), sdk tsc clean, full
suite 2267 green incl. a new real-WASM embind round-trip test proving a
vector<VisualState> (string + color + sprite + scale) survives the boundary;
ui-node-flex pixel-verified (no render regression).
esengine added a commit that referenced this pull request Jun 29, 2026
…st (B4a)

RC6 Batch B4 (compressed-texture producer — the #1 RC6 payoff: VRAM). The asset
cook needs a build-time PNG/JPG -> KTX2 encoder; this lands the encoder + a tested
API, decoupled from cook (no pipeline change yet, zero regression risk).

- build-tools/basis/: the vendored prebuilt Basis Universal *encoder* wasm
  (basis_encoder.cjs + .wasm), built from the in-tree third_party/basis_universal
  via its reference emscripten project (non-threads wasm32 — Node-capable). Copied
  with a .cjs extension so Node loads it as CommonJS under this type:module repo,
  and committed (gitignore exception) so cooking needs no emsdk. README documents
  provenance + the rebuild command.
- encoder.mjs: a small Promise API — encodePngToKtx2 / encodeToKtx2 (UASTC or
  ETC1S) / transcodeKtx2ToRgba. UASTC is emitted WITHOUT zstd supercompression to
  match the runtime transcoder (BASISD_SUPPORT_KTX2_ZSTD=0); same vendored library
  as the runtime transcoder, so encode and decode agree by construction.
- ktx2-encode.test.ts: RGBA gradient -> KTX2 -> transcode round-trips at >40 dB
  PSNR (near-lossless UASTC); a real PNG encodes with matching dimensions; and the
  encoder is deterministic (identical bytes -> identical KTX2) — the prerequisite
  for content-addressing the .ktx2 in B3.

Verified: 3 tests pass (desktop vitest). encode-time only; the runtime side
(Batch C wiring) and cook integration (B4c) follow.
esengine added a commit that referenced this pull request Jun 29, 2026
…st (B4a)

RC6 Batch B4 (compressed-texture producer — the #1 RC6 payoff: VRAM). The asset
cook needs a build-time PNG/JPG -> KTX2 encoder; this lands the encoder + a tested
API, decoupled from cook (no pipeline change yet, zero regression risk).

- build-tools/basis/: the vendored prebuilt Basis Universal *encoder* wasm
  (basis_encoder.cjs + .wasm), built from the in-tree third_party/basis_universal
  via its reference emscripten project (non-threads wasm32 — Node-capable). Copied
  with a .cjs extension so Node loads it as CommonJS under this type:module repo,
  and committed (gitignore exception) so cooking needs no emsdk. README documents
  provenance + the rebuild command.
- encoder.mjs: a small Promise API — encodePngToKtx2 / encodeToKtx2 (UASTC or
  ETC1S) / transcodeKtx2ToRgba. UASTC is emitted WITHOUT zstd supercompression to
  match the runtime transcoder (BASISD_SUPPORT_KTX2_ZSTD=0); same vendored library
  as the runtime transcoder, so encode and decode agree by construction.
- ktx2-encode.test.ts: RGBA gradient -> KTX2 -> transcode round-trips at >40 dB
  PSNR (near-lossless UASTC); a real PNG encodes with matching dimensions; and the
  encoder is deterministic (identical bytes -> identical KTX2) — the prerequisite
  for content-addressing the .ktx2 in B3.

Verified: 3 tests pass (desktop vitest). encode-time only; the runtime side
(Batch C wiring) and cook integration (B4c) follow.
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