Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
739a72e
test: add core/tests/filePath — path edge cases across OSes
tettou771 Jul 3, 2026
57f0af2
doc: fs::path path-handling docs (reference prose + FOR_AI corpus)
tettou771 Jul 3, 2026
e9dcb95
feat: carry file paths as fs::path end to end (UTF-8 safe on Windows)
tettou771 Jul 3, 2026
efbc740
Merge remote-tracking branch 'origin/dev' into refactor/fs-path-unify
tettou771 Jul 3, 2026
2001400
ci: fail the build on deprecated TrussC API use in the repo's own sou…
tettou771 Jul 3, 2026
97b8f9f
refactor: gather per-window state into internal::WindowContext (multi…
tettou771 Jul 4, 2026
1add9f3
feat: per-window swapchain + dimension seams in the window context
tettou771 Jul 4, 2026
47f93c1
feat: secondary windows on macOS (createWindow, per-display tick)
tettou771 Jul 4, 2026
b5a5b76
add: multiWindowExample (second window, own mouse, shared FBO)
tettou771 Jul 4, 2026
178cae1
doc: reference prose for Window / createWindow (glue helpers hidden)
tettou771 Jul 4, 2026
89ad7bc
fix: secondary window tracks hover without key focus
tettou771 Jul 4, 2026
81a1c71
feat: sync a RectNode root to the secondary window's logical size
tettou771 Jul 5, 2026
e338d85
feat: Window::setApp — an App drives each window (setRoot removed)
tettou771 Jul 5, 2026
dd498b0
fix: per-window delta time — getDeltaTime/getFrameRate resolve throug…
tettou771 Jul 7, 2026
f5101e6
doc: sokol_app_tc.h design + sapp_* usage inventory
tettou771 Jul 7, 2026
6d73d9a
feat: sokol_app_tc.h — secondary windows behind a standalone C API (P0a)
tettou771 Jul 7, 2026
6686f27
feat: sokol_app_tc.h implements the sapp_* API on macOS (P0b: main wi…
tettou771 Jul 7, 2026
d09dafc
doc: win32/D3D11 implementation contract + multi-window-win branch au…
tettou771 Jul 9, 2026
30da93d
feat: sokol_app_tc.h implements the sapp_* API on Windows (P1: win32/…
tettou771 Jul 9, 2026
317696b
fix: qualify X11 Window type as ::Window in tcPlatform_linux.cpp
tettou771 Jul 9, 2026
0ea8753
fix: exclude archive member header metadata from hot-reload .def export
tettou771 Jul 9, 2026
11b984f
fix: silence -Wpass-failed on the snappy dependency under Emscripten
tettou771 Jul 9, 2026
82703e8
fix: capture and echo test binary output in build_all.py
tettou771 Jul 9, 2026
a9cd45a
fix: open text file utilities in binary mode (byte-faithful on Windows)
tettou771 Jul 9, 2026
ab084bd
doc: record P1 full-CI-green status in the design doc
tettou771 Jul 9, 2026
5f1c2f1
feat!: make VecN single-value (splat) constructors explicit + Vec4 co…
tettou771 Jul 13, 2026
a9f100b
doc: fix FOR_AI corpus — plain RectNode does not auto-enable events (…
tettou771 Jul 13, 2026
c1628ff
doc: roadmap — plan mouse press/release/drag bubbling for v0.7.0 (uni…
tettou771 Jul 13, 2026
f8f8105
add: emit-sketch-reference.js (Lua-flavored reference data) + implici…
tettou771 Jul 13, 2026
2cd7ecb
fix: mark trusssketch-ref.js as lang:'lua' (renderer picks '.' scope …
tettou771 Jul 13, 2026
1c82710
fix(tcxLua): enable Type(...) constructor call form via sol::call_con…
tettou771 Jul 13, 2026
cb28ad5
fix(sokol_app_tc): stop the render loop stalling after the first fram…
tettou771 Jul 13, 2026
d62ce33
fix(docs): sketch emitters derive hand-written types from the ACTUAL …
tettou771 Jul 13, 2026
f1be754
doc: record the waitable single-consumer contract + Win11 runtime ver…
tettou771 Jul 13, 2026
9a5f9ae
fix: restore the real screen camera after FullscreenShader::draw
tettou771 Jul 13, 2026
dc5c035
doc: x11/GLX implementation contract + corrected P2 tick model (P2 ki…
tettou771 Jul 13, 2026
5c5881e
doc: roadmap — retire implemented entries (audio, font wrap), add fea…
tettou771 Jul 13, 2026
dd874ff
feat: implement Linux X11/GLX driver in sokol_app_tc.h (P2)
tettou771 Jul 13, 2026
7a3e152
doc: update multiWindowExample platform note (macOS/Windows/Linux)
tettou771 Jul 13, 2026
d6c3d0c
fix: define GL_GLEXT_PROTOTYPES before the first GL include on Linux
tettou771 Jul 13, 2026
5956ddf
doc: record P2 Linux driver as-built (self-healing swap pacing, EMA r…
tettou771 Jul 13, 2026
b768b53
doc: record P2 Linux runtime verification (real hardware, all checks …
tettou771 Jul 13, 2026
2bfaf1a
feat: implement web (emscripten) driver in sokol_app_tc.h (P3)
tettou771 Jul 13, 2026
9c5fb9a
doc: roadmap — kiosk sink/thumbnail/MCP-passthrough design + fleet da…
tettou771 Jul 13, 2026
7a46507
doc: record P3 web driver CI green (run 29259516968)
tettou771 Jul 13, 2026
5e63ff5
fix: force GROWABLE_ARRAYBUFFERS=0 on emscripten 6.x web builds
tettou771 Jul 14, 2026
528bdea
fix: put TC_PLATFORMS annotation before GNU unavailable attribute
tettou771 Jul 14, 2026
f3ac1c8
feat: add iOS driver to sokol_app_tc.h (P4)
tettou771 Jul 14, 2026
dde4d72
add: metal_sim shader variant for iOS simulator support
tettou771 Jul 14, 2026
ccfd8e5
doc: roadmap — kiosk/fleet settled design (auth model, notifications …
tettou771 Jul 14, 2026
5b96f8c
feat: get_health MCP tool + TRUSSC_LOG_FILE env (kiosk groundwork)
tettou771 Jul 14, 2026
181b271
feat: get_thumbnail MCP tool — encode runs on the HTTP worker, not th…
tettou771 Jul 14, 2026
5e2cfc9
Merge origin/dev into feat/sokol-app-tc
tettou771 Jul 14, 2026
4923012
doc: P4 iOS driver device pass complete (full checklist on iPhone 16)
tettou771 Jul 14, 2026
9722aa6
doc: roadmap — ops tool named gusset (one binary: serve/agent), separ…
tettou771 Jul 14, 2026
9c57bab
doc: supervisor references — trusscli kiosk -> gusset agent
tettou771 Jul 14, 2026
0295b8e
feat: add Android driver to sokol_app_tc.h (P5)
tettou771 Jul 14, 2026
565c9e9
doc: P5 CI green (run 29306102924)
tettou771 Jul 14, 2026
d1127cc
fix: route sokol_app_tc.h Android logs to logcat
tettou771 Jul 14, 2026
ac0cbe7
doc: P5 Android driver device pass complete (Pixel 8a, full checklist)
tettou771 Jul 14, 2026
77bffd2
doc: roadmap — rename the ops tool gusset -> anchorbolt
tettou771 Jul 14, 2026
356605b
doc: supervisor references — gusset -> anchorbolt
tettou771 Jul 14, 2026
94b1bec
doc: roadmap — anchorbolt agent -> anchorbolt start (kiosk mode)
tettou771 Jul 14, 2026
25fb4a9
doc: supervisor references — anchorbolt agent -> anchorbolt start
tettou771 Jul 14, 2026
c958864
doc: roadmap — Android soft keyboard + file dialog via core-shipped J…
tettou771 Jul 14, 2026
4595b40
feat: add GLES3/EGL Linux driver to sokol_app_tc.h (P5.5, Raspberry Pi)
tettou771 Jul 14, 2026
4f10707
feat: app-published ops status (mcp::status/graph/statusImage + ancho…
tettou771 Jul 14, 2026
35f793d
refactor: mcp::graph -> mcp::statusGraph; warn on MCP tool re-registr…
tettou771 Jul 14, 2026
77faf44
refactor!: namespace all standard MCP tools as tc_* / tcx_imgui_*
tettou771 Jul 14, 2026
1b97d34
feat: merge tc_get_thumbnail into tc_get_screenshot(format, width, qu…
tettou771 Jul 14, 2026
90b7a2d
doc: roadmap — shard luagen output to fix tcxLua build OOM on low-mem…
tettou771 Jul 14, 2026
ddb1e1d
feat: pid + rssBytes in tc_get_health
tettou771 Jul 14, 2026
febd1ee
fix: accurate createWindow() platform-gap message + iOS gets the Wind…
tettou771 Jul 14, 2026
e222cdd
doc: P5.5 RasPi device pass complete; P6 scope note (self-contained h…
tettou771 Jul 14, 2026
7a1347e
feat: sokol_app.h deleted -- sokol_app_tc.h is self-contained (P6)
tettou771 Jul 14, 2026
6b1f44b
feat!: image tools return MCP-standard image content blocks
tettou771 Jul 16, 2026
6cf10f0
refactor!: complete the fs::path unification (v0.7 breaking set)
tettou771 Jul 16, 2026
ffd93c3
feat!: unified LoadResult API for resource loading (v0.7 breaking set)
tettou771 Jul 16, 2026
ee855bc
fix: one more toWide(fs::path) call site in the Windows save dialog
tettou771 Jul 16, 2026
d388a9e
fix: trusscli GUI dialog call sites for fs::path FileDialogResult
tettou771 Jul 16, 2026
0bd195c
Merge origin/dev into feat/sokol-app-tc (roadmap doc commits) before …
tettou771 Jul 16, 2026
f826bd5
Merge remote-tracking branch 'origin/dev' into feat/kiosk
tettou771 Jul 16, 2026
b98774c
fix: Windows build — 'small' is a macro in Windows headers
tettou771 Jul 16, 2026
6ee6a8d
feat: MCP window targeting -- list_windows tool + window arg on scree…
tettou771 Jul 16, 2026
25551f9
Merge remote-tracking branch 'origin/dev' into feat/explicit-vec-splat
tettou771 Jul 16, 2026
fa538e3
feat(tcxLua): shard the generated usertype bindings across 16 TUs
tettou771 Jul 16, 2026
829c9f7
Merge branch 'dev' of github.com:TrussC-org/TrussC into dev
tettou771 Jul 16, 2026
2b767bb
refactor(luagen-types): fixed 16-shard output, no flags
tettou771 Jul 16, 2026
bde8850
fix: TcpServer::stop() logs 'stopped' only if the server was running
tettou771 Jul 16, 2026
e69319e
feat: tcxImGui multi-window -- one ImGui context per window
tettou771 Jul 16, 2026
6a94c57
feat: EasyCam multi-window contract doc + easyCamWindowExample
tettou771 Jul 16, 2026
53e7fdf
Merge branch 'dev' into feat/explicit-vec-splat
tettou771 Jul 16, 2026
bca96f0
chore(tcxLua): regenerate bindings for explicit-splat + Vec4 componen…
tettou771 Jul 16, 2026
42c8287
Merge feat/explicit-vec-splat into dev (0.7.0: explicit VecN splat ct…
tettou771 Jul 16, 2026
c394263
Merge origin/dev into feat/multiwindow-phase4 (tc_* MCP rename + luag…
tettou771 Jul 16, 2026
fe53846
Merge origin/dev (explicit VecN splat + Vec4 ops); regenerate Lua bin…
tettou771 Jul 16, 2026
2dc9347
feat: mcp::alert() + tc_get_alerts — operator alerts from the app
tettou771 Jul 16, 2026
20c203d
Merge branch 'dev' of github.com:TrussC-org/TrussC into dev
tettou771 Jul 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
# Uses of [[deprecated]] TrussC API in the repo's own sources
# (core/examples/tests, all jobs incl. web/android) fail the build
# (GCC/Clang only; see core/CMakeLists.txt + trussc_app.cmake).
# User projects never set this.
TC_DEPRECATED_ERRORS: 1

jobs:
# Path-based change detector. Emits docs_only=true when EVERY file in the diff
# is documentation (any *.md, or anything under docs/ — prose + doc tooling).
Expand Down
5 changes: 2 additions & 3 deletions addons/tcxBox2d/example-collision/src/tcApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,14 @@ void tcApp::addBall(float x, float y) {
// Add collision callback to ball
auto* collider = ball->getCollider();
if (collider) {
ballListeners.emplace_back();
collider->onCollisionEnter.listen(ballListeners.back(), [this](box2d::CollisionEvent& e) {
ballListeners.push_back(collider->onCollisionEnter.listen([this](box2d::CollisionEvent& e) {
enterCount++;
collisionMarkers.push_back({
e.contactPoint,
0.3f,
Color(0.2f, 0.8f, 1.0f) // cyan for ball collisions
});
});
}));
}

addChild(ball);
Expand Down
2 changes: 1 addition & 1 deletion addons/tcxCurl/src/tcxCurl_android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

#include <jni.h>
#include <android/native_activity.h>
#include "sokol_app.h"
#include "sokol_app_tc.h"

#include <cstring>

Expand Down
4 changes: 2 additions & 2 deletions addons/tcxDepthRecord/src/tcxDepthPlayback.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ class PlaybackDepthCamera : public DepthCamera {

protected:
bool openDevice() override {
std::filesystem::path p(path_);
std::string resolved = p.is_relative() ? getDataPath(path_) : path_;
// getDataPath passes absolute paths through unchanged
std::filesystem::path resolved = getDataPath(path_);
file_.open(resolved, std::ios::binary);
if (!file_) {
logError("tcxDepthRecord") << "PlaybackDepthCamera: cannot open " << resolved;
Expand Down
7 changes: 3 additions & 4 deletions addons/tcxDepthRecord/src/tcxDepthRecorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,15 @@ class DepthRecorder {
std::uint32_t streams = REC_ALL,
DepthCodecId depthCodec = DepthCodecId::HiloLZ4,
ColorCodecId colorCodec = ColorCodecId::LZ4) {
std::filesystem::path p(path);
std::string resolved = p.is_relative() ? getDataPath(path) : path;
std::filesystem::path rp(resolved);
// getDataPath passes absolute paths through unchanged
std::filesystem::path rp = getDataPath(path);
if (rp.has_parent_path()) {
std::error_code ec;
std::filesystem::create_directories(rp.parent_path(), ec);
}
file_.open(rp, std::ios::binary | std::ios::trunc);
if (!file_) {
logError("tcxDepthRecord") << "DepthRecorder: cannot open " << resolved;
logError("tcxDepthRecord") << "DepthRecorder: cannot open " << rp;
return false;
}
streams_ = streams;
Expand Down
2 changes: 1 addition & 1 deletion addons/tcxGltf/src/tcxGltf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ bool GltfModel::load(const string& path) {
textures_.clear();
loaded_ = false;

string resolved = getDataPath(path);
string resolved = getDataPath(path).string();

// Parse with cgltf
cgltf_options options = {};
Expand Down
7 changes: 7 additions & 0 deletions addons/tcxHap/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ set(SNAPPY_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(SNAPPY_BUILD_BENCHMARKS OFF CACHE BOOL "" FORCE)
set(SNAPPY_INSTALL OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(snappy)
if(EMSCRIPTEN)
# snappy compiles itself with -Werror on Clang; its '#pragma clang loop'
# vectorization hints cannot be honored under wasm, and the resulting
# -Wpass-failed diagnostic would fail the build. Silence it on the
# dependency target only.
target_compile_options(snappy PRIVATE -Wno-pass-failed)
endif()

# Snappy adds -Werror for Clang builds; its `#pragma clang loop` hints can fail
# on backends that can't vectorize them (e.g. wasm/em++), turning the
Expand Down
2 changes: 1 addition & 1 deletion addons/tcxHap/example-hap/src/tcApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void tcApp::setup() {
.bind([this](const json& args) -> json {
string path = args.at("path").get<string>();
logNotice("tcApp") << "MCP: Loading " << path;
bool success = player_.load(path);
bool success = player_.load(path).ok();
if (success) {
player_.play();
statusText_ = "Loaded: " + path;
Expand Down
26 changes: 19 additions & 7 deletions addons/tcxHap/src/tcxHapPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,23 @@ class HapPlayer : public tc::VideoPlayerBase {
// Load / Close
// =========================================================================

bool load(const std::string& path) override {
tc::LoadResult load(const tc::fs::path& path) override {
if (initialized_) {
close();
}
resetStats();

std::error_code ec;
if (!tc::fs::exists(path, ec)) {
return tc::LoadResult::fail(tc::LoadError::FileNotFound,
"file not found: " + tc::internal::pathToUtf8(path));
}

// Parse MOV file
if (!movParser_.open(path)) {
tc::logError("HapPlayer") << "Failed to open: " << path;
return false;
return tc::LoadResult::fail(tc::LoadError::DecodeFailed,
"failed to parse MOV: " + tc::internal::pathToUtf8(path));
}

const auto& info = movParser_.getInfo();
Expand All @@ -92,14 +99,17 @@ class HapPlayer : public tc::VideoPlayerBase {
if (!videoTrack) {
tc::logError("HapPlayer") << "No video track found";
movParser_.close();
return false;
return tc::LoadResult::fail(tc::LoadError::DecodeFailed,
"no video track found");
}

if (!videoTrack->isHap()) {
tc::logError("HapPlayer") << "Not a HAP codec (FourCC: "
<< MovParser::fourccToString(videoTrack->codecFourCC) << ")";
movParser_.close();
return false;
return tc::LoadResult::fail(tc::LoadError::UnsupportedFormat,
"not a HAP codec (FourCC: " +
MovParser::fourccToString(videoTrack->codecFourCC) + ")");
}

// Store video info
Expand All @@ -120,7 +130,8 @@ class HapPlayer : public tc::VideoPlayerBase {
if (hapFormat_ == HapFormat::Unknown) {
tc::logError("HapPlayer") << "Could not determine HAP format";
movParser_.close();
return false;
return tc::LoadResult::fail(tc::LoadError::DecodeFailed,
"could not determine HAP format");
}

// Allocate frame buffer for decoded DXT data
Expand All @@ -131,7 +142,8 @@ class HapPlayer : public tc::VideoPlayerBase {
if (!createCompressedTexture()) {
tc::logError("HapPlayer") << "Failed to create compressed texture";
movParser_.close();
return false;
return tc::LoadResult::fail(tc::LoadError::Unknown,
"failed to create compressed texture");
}

// Load audio track if available
Expand All @@ -147,7 +159,7 @@ class HapPlayer : public tc::VideoPlayerBase {

initialized_ = true;
currentFrame_ = 0;
return true;
return tc::LoadResult::success();
}

void close() override {
Expand Down
2 changes: 1 addition & 1 deletion addons/tcxHap/src/tcxMovParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ class MovParser {
return *this;
}

bool open(const std::string& path) {
bool open(const tc::fs::path& path) {
close();

// Create a completely fresh fstream object (not reusing old one)
Expand Down
8 changes: 4 additions & 4 deletions addons/tcxImGui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ void tcApp::setup() {

| Tool | Arguments | Description |
|------|-----------|-------------|
| `imgui_get_widgets` | `window` (optional) | List all widgets with labels, types, and positions |
| `imgui_click` | `label`, `window` (optional) | Click a widget by label |
| `imgui_input` | `label`, `text`, `window` (optional) | Set a widget's value: replaces text in input widgets, and enters numeric values directly into slider/drag widgets (Ctrl+Click temp input) |
| `imgui_checkbox` | `label`, `value` (optional), `window` (optional) | Toggle or set a checkbox |
| `tcx_imgui_get_widgets` | `window` (optional) | List all widgets with labels, types, and positions |
| `tcx_imgui_click` | `label`, `window` (optional) | Click a widget by label |
| `tcx_imgui_input` | `label`, `text`, `window` (optional) | Set a widget's value: replaces text in input widgets, and enters numeric values directly into slider/drag widgets (Ctrl+Click temp input) |
| `tcx_imgui_checkbox` | `label`, `value` (optional), `window` (optional) | Toggle or set a checkbox |

These tools use ImGui's Test Engine hooks to collect widget info each frame.

Expand Down
2 changes: 1 addition & 1 deletion addons/tcxImGui/src/platform/imgui_impl_android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#ifdef __ANDROID__

// sokol headers (must come before sokol_imgui.h)
#include "sokol/sokol_app.h"
#include "sokol/sokol_app_tc.h"
#include "sokol/sokol_gfx.h"
#include "sokol/sokol_log.h"

Expand Down
2 changes: 1 addition & 1 deletion addons/tcxImGui/src/platform/imgui_impl_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// =============================================================================

// sokol headers (required before sokol_imgui.h)
#include "sokol/sokol_app.h"
#include "sokol/sokol_app_tc.h"
#include "sokol/sokol_gfx.h"
#include "sokol/sokol_log.h"

Expand Down
2 changes: 1 addition & 1 deletion addons/tcxImGui/src/platform/imgui_impl_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// =============================================================================

// sokol ヘッダー(sokol_imgui.h より先に必要)
#include "sokol/sokol_app.h"
#include "sokol/sokol_app_tc.h"
#include "sokol/sokol_gfx.h"
#include "sokol/sokol_log.h"

Expand Down
2 changes: 1 addition & 1 deletion addons/tcxImGui/src/platform/imgui_impl_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// =============================================================================

// sokol ヘッダー(sokol_imgui.h より先に必要)
#include "sokol/sokol_app.h"
#include "sokol/sokol_app_tc.h"
#include "sokol/sokol_gfx.h"
#include "sokol/sokol_log.h"

Expand Down
2 changes: 1 addition & 1 deletion addons/tcxImGui/src/platform/imgui_impl_web.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// =============================================================================

// sokol ヘッダー(sokol_imgui.h より先に必要)
#include "sokol/sokol_app.h"
#include "sokol/sokol_app_tc.h"
#include "sokol/sokol_gfx.h"
#include "sokol/sokol_log.h"

Expand Down
2 changes: 1 addition & 1 deletion addons/tcxImGui/src/platform/imgui_impl_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// =============================================================================

// sokol ヘッダー(sokol_imgui.h より先に必要)
#include "sokol/sokol_app.h"
#include "sokol/sokol_app_tc.h"
#include "sokol/sokol_gfx.h"
#include "sokol/sokol_log.h"

Expand Down
103 changes: 100 additions & 3 deletions addons/tcxImGui/src/sokol_imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,18 @@ SOKOL_IMGUI_API_DECL void simgui_shutdown(void);
inline void simgui_setup(const simgui_desc_t& desc) { return simgui_setup(&desc); }
inline void simgui_new_frame(const simgui_frame_desc_t& desc) { return simgui_new_frame(&desc); }

/* [TrussC] multi-context API (multi-window support). Each context is a full,
independent sokol_imgui instance (own ImGui context, font atlas, buffers,
pipeline). simgui_tc_set_context() selects which instance the classic
simgui_* calls (and ImGui::GetCurrentContext) operate on. The context
handle from simgui_tc_get_context() before any make/set is the default
instance (what plain simgui_setup initialized). */
typedef struct simgui_tc_context { void* ptr; } simgui_tc_context;
SOKOL_IMGUI_API_DECL simgui_tc_context simgui_tc_make_context(const simgui_desc_t* desc);
SOKOL_IMGUI_API_DECL void simgui_tc_set_context(simgui_tc_context ctx);
SOKOL_IMGUI_API_DECL simgui_tc_context simgui_tc_get_context(void);
SOKOL_IMGUI_API_DECL void simgui_tc_destroy_context(simgui_tc_context ctx);

#endif
#endif /* SOKOL_IMGUI_INCLUDED */

Expand Down Expand Up @@ -646,8 +658,17 @@ typedef struct {
sg_range vertices;
sg_range indices;
bool is_osx;
void* imgui_ctx; // [TrussC] the ImGuiContext* owned by this instance
} _simgui_state_t;
static _simgui_state_t _simgui;

// [TrussC] Multi-context support (multi-window): _simgui becomes a reference
// to the ACTIVE instance so the whole implementation below compiles
// unchanged. simgui_setup()/simgui_* operate on the instance selected via
// simgui_tc_set_context(); the default instance preserves classic
// single-window behavior.
static _simgui_state_t _simgui_default_instance;
static _simgui_state_t* _simgui_cur = &_simgui_default_instance;
#define _simgui (*_simgui_cur)

//>#shdgen
#if defined(SOKOL_GLCORE)
Expand Down Expand Up @@ -2127,10 +2148,19 @@ static void _simgui_imgui_newframe(void) {
}

static void _simgui_imgui_create_context(void) {
// [TrussC] Since Dear ImGui 1.90, CreateContext() RESTORES the previously
// current context before returning (it is deliberately not
// context-switching). Capture the RETURN VALUE and make the new context
// current explicitly -- the rest of simgui_setup() configures "the
// current context" and must target the newly created one.
#if defined(__cplusplus)
ImGui::CreateContext();
ImGuiContext* ctx = ImGui::CreateContext();
ImGui::SetCurrentContext(ctx);
_simgui.imgui_ctx = (void*)ctx;
#else
_SIMGUI_CFUNC(CreateContext)(0);
ImGuiContext* ctx = _SIMGUI_CFUNC(CreateContext)(0);
_SIMGUI_CFUNC(SetCurrentContext)(ctx);
_simgui.imgui_ctx = (void*)ctx;
#endif
}

Expand Down Expand Up @@ -3170,4 +3200,71 @@ SOKOL_API_IMPL bool simgui_handle_event(const sapp_event* ev) {
}
#endif // SOKOL_IMGUI_NO_SOKOL_APP

/* [TrussC] multi-context API implementation */
SOKOL_API_IMPL simgui_tc_context simgui_tc_get_context(void) {
simgui_tc_context c; c.ptr = (void*)_simgui_cur; return c;
}

SOKOL_API_IMPL void simgui_tc_set_context(simgui_tc_context ctx) {
SOKOL_ASSERT(ctx.ptr);
_simgui_cur = (_simgui_state_t*)ctx.ptr;
if (_simgui.imgui_ctx) {
#if defined(__cplusplus)
ImGui::SetCurrentContext((ImGuiContext*)_simgui.imgui_ctx);
#else
_SIMGUI_CFUNC(SetCurrentContext)((ImGuiContext*)_simgui.imgui_ctx);
#endif
}
}

SOKOL_API_IMPL simgui_tc_context simgui_tc_make_context(const simgui_desc_t* desc) {
SOKOL_ASSERT(desc);
/* plain malloc: instance lifetime is independent of any per-instance
custom allocator (custom allocators across tc contexts unsupported) */
_simgui_state_t* inst = (_simgui_state_t*)malloc(sizeof(_simgui_state_t));
SOKOL_ASSERT(inst);
memset(inst, 0, sizeof(_simgui_state_t));
_simgui_state_t* prev = _simgui_cur;
#if defined(__cplusplus)
ImGuiContext* prev_im = ImGui::GetCurrentContext();
#else
ImGuiContext* prev_im = _SIMGUI_CFUNC(GetCurrentContext)();
#endif
_simgui_cur = inst;
simgui_setup(desc); /* fills the new instance, creates its ImGui context */
_simgui_cur = prev;
#if defined(__cplusplus)
ImGui::SetCurrentContext(prev_im);
#else
_SIMGUI_CFUNC(SetCurrentContext)(prev_im);
#endif
simgui_tc_context c; c.ptr = (void*)inst; return c;
}

SOKOL_API_IMPL void simgui_tc_destroy_context(simgui_tc_context ctx) {
if (!ctx.ptr || ctx.ptr == (void*)&_simgui_default_instance) {
return; /* the default instance is torn down by plain simgui_shutdown() */
}
_simgui_state_t* inst = (_simgui_state_t*)ctx.ptr;
_simgui_state_t* prev = _simgui_cur;
#if defined(__cplusplus)
ImGuiContext* prev_im = ImGui::GetCurrentContext();
#else
ImGuiContext* prev_im = _SIMGUI_CFUNC(GetCurrentContext)();
#endif
if (prev == inst) { prev = &_simgui_default_instance; prev_im = 0; }
simgui_tc_context sel; sel.ptr = (void*)inst;
simgui_tc_set_context(sel);
simgui_shutdown();
_simgui_cur = prev;
if (prev_im) {
#if defined(__cplusplus)
ImGui::SetCurrentContext(prev_im);
#else
_SIMGUI_CFUNC(SetCurrentContext)(prev_im);
#endif
}
free(inst);
}

#endif // SOKOL_IMPL
Loading
Loading