Skip to content

"Integrations" (simple) API layer#1701

Draft
ryantrem wants to merge 62 commits into
BabylonJS:masterfrom
ryantrem:integrations
Draft

"Integrations" (simple) API layer#1701
ryantrem wants to merge 62 commits into
BabylonJS:masterfrom
ryantrem:integrations

Conversation

@ryantrem
Copy link
Copy Markdown
Member

@ryantrem ryantrem commented May 16, 2026

Summary

Introduces a new Babylon::Integrations layer that gives host apps a small, opinionated Runtime + View API for embedding Babylon Native, and migrates every Playground host (Android, iOS, visionOS, macOS, UWP, Win32, X11) onto it. The goal is to make platform integration a job that takes tens — not hundreds — of lines of code, and to do that without leaking AppRuntime, Graphics::Device, plugin headers, polyfill plumbing, or threading rules into the host.

Two layers ship together:

  1. Core C++ API (Integrations/Include/Shared/Babylon/Integrations/{Runtime,View,RuntimeOptions,LogLevel}.h) — cross-platform, single source of truth for the lifecycle, threading, suspend/resume, input forwarding, and XR window management.
  2. Per-platform language facades that wrap the core API in idiomatic types for the host language:
    • Android: BabylonNative.java + JNI (BabylonNativeIntegrations.cpp)
    • Apple: BNRuntime / BNView Obj‑C classes (Swift-friendly via the bridging header)

What's new

Integrations core (Integrations/Source, Integrations/Include/Shared)

Two value types with explicit ownership and a documented contract:

Babylon::Integrations::RuntimeOptions options{};
options.enableDebugger = true;
options.log = [](LogLevel level, std::string_view msg) { /**/ };

Babylon::Integrations::Runtime runtime{options};

runtime.LoadScript("app:///Scripts/babylon.max.js");
runtime.LoadScript("app:///Scripts/scene.js");

Babylon::Integrations::View view{runtime, nativeWindowHandle};
view.Resize(width, height, CoordinateUnits::Physical);

// driven from the host's draw callback:
view.RenderFrame();

What the layer takes care of for you:

  • Runtime construction: spins up AppRuntime, JsRuntime, polyfills (Console, Window, XMLHttpRequest, WebSocket, URL, Canvas, TextDecoder, Performance, Scheduling), and non‑GPU plugins.
  • GPU deferral: Graphics::Device, NativeEngine, NativeInput, NativeCanvas, TestUtils, and (optionally) NativeXr / ShaderCache are constructed lazily on the first View::Resize. Subsequent View attaches just rebind the Device.
  • Script queuing: LoadScript / Eval / RunOnJsThread are safe to call before the first View attach; queued and flushed when the engine comes up.
  • Suspend / Resume: reference-counted, closes the in-flight frame, pauses JS timers, optionally persists the shader cache.
  • Input: OnPointer* / OnMouse* accept either Physical or Logical pixel units; the View handles DPR conversion.
  • XR window: Runtime::SetXrWindow hands off a secondary surface for NativeXr.
  • Logging: single RuntimeOptions::log sink for console.{log,warn,error}, Babylon::DebugTrace, and uncaught JS exceptions.

Android facade

Integrations/Android/BabylonNative/ (replaces the old BabylonNativeJNI.cpp + Wrapper.java).

  • com.babylonjs.integrations.BabylonNative — Java mirror of the C++ API: loadScript, eval, runOnJsThread, suspend, resume, attachView, setXrWindow. Includes a Runtime.Builder, a LogListener interface, and a SurfaceView attach overload that wires SurfaceHolder.Callback for you.

Apple facade

Integrations/Apple/ — Obj‑C wrappers (BNRuntime, BNView, BNViewDelegate) usable from Obj‑C and from Swift via the bridging header. Used by Playground iOS, macOS, and visionOS. BNRuntimeNative.h exposes the underlying Babylon::Integrations::Runtime& for callers that need the C++ API.

Host app migrations

Every Playground host now runs on top of the Integrations layer:

Host Before After
Android BabylonNativeJNI.cpp (~196 lines bespoke JNI) + Wrapper.java BabylonNative Java class
iOS LibNativeBridge.{h,mm} + ad-hoc Swift glue BNRuntime / BNView, ~75-line ViewController.swift
macOS 222-line ViewController.mm doing its own AppContext plumbing Same BNRuntime / BNView types as iOS
visionOS LibNativeBridge.{h,mm} + custom App.swift threading BNRuntime / BNView + bridging header
Win32 AppContext + manual UpdateSize / mouse plumbing Runtime + View with WM_POINTERView::On*
UWP C++/WinRT AppContext + manual swap-chain plumbing Runtime + View from IInspectable
X11 AppContext + xcb event handlers Runtime + View with View::OnMouse*

Lifecycle contract

  • First View attach is the heavy step. Hosts MUST call Resize at least once with the surface's pixel dimensions before the first RenderFrame — the Device is built on the first Resize.
  • One View per Runtime at a time. View constructor throws std::runtime_error on double-attach.
  • Destroy Views before their Runtime. ~Runtime is noexcept(false) and throws if a View is still attached. ~View clears the back-reference, so LIFO destruction works.
  • Frame thread: RenderFrame, Resize, Suspend, Resume, LoadScript, Eval, RunOnJsThread, View construction/destruction.
  • Any thread: OnPointer* / OnMouse* / IsSuspended / IsXrActive / SetXrWindow.

File scope

Integrations/                                ~2,800 lines added
  Include/Shared/Babylon/Integrations/{Runtime,View,RuntimeOptions,LogLevel}.h
  Source/{Runtime,View}.cpp + RuntimeImpl.h
  Android/ — JNI + Java facade
  Apple/   — BNRuntime / BNView / BNViewDelegate

Apps/Playground/
  Win32/ UWP/ X11/ macOS/ iOS/ visionOS/ Android/   (all migrated)

Closed open items

  • AI-generated comment cleanup
  • Naming ("Integrations")
  • All Playground hosts migrated (Android, iOS, visionOS, macOS, UWP, Win32, X11)
  • RunOnJsThread now has an afterScriptLoad parameter
  • Runtime / View are regular movable value types
  • Removed the planning .md from the repo root
  • Real fix for DeviceImpl.cpp issue

Copy link
Copy Markdown
Contributor

@bghgary bghgary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Reviewed by Copilot on behalf of @bghgary]

Concerns inline.

Comment thread Integrations/Apple/Source/BNView.mm
Comment thread Integrations/Source/Runtime.cpp Outdated
Comment thread Integrations/Include/Shared/Babylon/Integrations/Runtime.h
Comment on lines +217 to +219
// TODO: Should be able to clear the Dirty flag, but bgfx::init is not doing everything that UpdateBgfxState is doing (at least on Apple platforms).
// See https://github.com/BabylonJS/ThePirateCove/issues/1657
// m_state.Bgfx.Dirty = false;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably need to sort this out before merging.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Integrations" may not be the right name for this.

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.

2 participants