Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Keeps finger-0 position current so 2→1 transitions always start from the correct touch position, not a stale value from the last 1-finger session. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Zoom now scales proportionally to orbit distance so feel is consistent at any range. Also resets cam->up at the start of the 2-finger branch as a safety guard. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds gesture-based camera controls to the Android NativeActivity renderer by introducing a self-contained per-frame touch handler that directly updates the scene camera without modifying shared desktop camera logic.
Changes:
- Added
handle_touch()inandroid_main.cto support 1-finger orbit, 2-finger pinch zoom, and 2-finger pan. - Enabled Raylib gesture input on Android and initialized orbit state (target + previous touch tracking).
- Added design + implementation plan documents describing the touch control approach.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
android/app/src/main/cpp/android_main.c |
Implements touch-driven orbit/zoom/pan camera updates for Android. |
android/docs/superpowers/specs/2026-04-16-touch-controls-design.md |
Documents gesture behavior and architecture for Android touch controls. |
android/docs/superpowers/plans/2026-04-16-touch-controls.md |
Step-by-step implementation plan for the touch control feature. |
.claude/settings.local.json |
Expands allowed gh command permissions for tooling automation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I haven't had a chance to test it properly, but just from the video I can note a few things. It looks like mtl colors aren't being loaded on the drone obj. Do you know where and how that failed? I also see a volume bar, but this won't include audio from the log files, so that can probably be stripped. The camera movement looks intuitive, but Ramon and I just chatted the other day about a weapon wheel style selection of features like the diegetic trails, or orthographic view switching. I just want to make sure your single finger presses wouldn't conflict with a long press hold on either the left side of the screen. |
|
Hi @MikePehel nice to meet you.
Yup, it has to do with how Android handles assets. They need to be included in the APK and reading them from the JNI layer is a pain in the butt. I'll fix that in this PR.
Do you mean after pressing the volume button? That is normal system behavior but if you guys want to kill it I can intercept the event and handle it. I can also add that to this PR and we can decide if we keep the code. I would recommend we let the event go through and display the volume bar. |
|
Long press / weapon wheel: No conflict with the current implementation. The touch handler only enables |
parse_mtl_names used fopen which silently fails inside an APK — switch to LoadFileText/UnloadFileText so it routes through the existing AAssetManager callback, restoring arm material colors on Android. Wrap Raylib's onInputEvent to consume AKEYCODE_VOLUME_UP/DOWN (return 1) before they reach the OS, preventing the system volume overlay from appearing since the app has no audio. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restore android_app->onInputEvent on teardown to match the SetLoadFileTextCallback(NULL) cleanup pattern. Replace silent NULL fallback in input_handler with __android_log_print so the guard is visible in logcat if initialization order ever changes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cceeds
The real MTL loading failure was in tinyobj_parse_mtl_file (called inside
Raylib's LoadOBJ), which uses fopen directly. On Android, APK assets aren't
on the filesystem, so fopen returns NULL, tinyobj assigns material_id = -1 to
all faces, and Raylib collapses the model to a single white mesh — the
color-match in remap_materials never had anything to work with.
Fix: before vehicle_init, set the working directory to internalDataPath,
create a models/ subdirectory, and extract every model MTL from AAssetManager
to that directory. Raylib's subsequent chdir("models") then succeeds, and
tinyobj's fopen("*.mtl") finds the file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…paths tinyobj_loader_c uses fopen() to read .mtl files, which fails on Android because APK assets have no real filesystem path. An earlier approach staged .mtl files to internalDataPath and patched the mtllib directive to an absolute path, but fopen of /data/user/0/... silently fails on Pixel 10 Pro XL / Android 16 due to bind-mount CWD vs path divergence. New approach: - stage_model_assets() preloads every .mtl from the APK into an in-memory buffer via AAssetManager at startup. - -Wl,--wrap,fopen intercepts all fopen() calls within libhawkeye.so. .mtl reads return an fmemopen FILE* from the cache; everything else passes through to __real_fopen. This requires no Raylib/tinyobj source modifications and is robust across clean builds and device-specific filesystem quirks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add TOUCH_MAX_ORBIT_DIST (50.0f) to prevent pinch-out from zooming the drone to sub-pixel size. Correct stale comment referencing the removed hawkeye_mtl_fopen/tinyobj patch approach — the current MTL mechanism is __wrap_fopen + fmemopen via -Wl,--wrap,fopen in CMakeLists.txt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
⏺ Add touch camera controls to Android renderer
Adds gesture-based camera control to the Android NativeActivity renderer via a self-contained handle_touch() function in android_main.c — no changes to scene.c.
How to Test
Screen_recording_20260416_222129.mp4