# Sprint 5c — Editor Screenshot + Camera Control

## Objective

Give the AI agent **eyes** in the editor. Two capabilities:

1. **Editor screenshot** — Capture the 3D viewport of the editor WITHOUT running the game. The agent can "see" the scene as the developer sees it.
2. **Camera control** — Move the editor's 3D camera to look at specific nodes or positions. Combined with screenshot for visual debugging.

After this sprint: **30 MCP tools** (29 + camera. Screenshot is an upgrade to existing tool).

---

## CRITICAL RESEARCH FINDINGS

### Editor Screenshot: CONFIRMED WORKING

API is simple and tested by multiple plugin developers:
```gdscript
var viewport := EditorInterface.get_editor_viewport_3d(0)
var img := viewport.get_texture().get_image()
# img is now an Image — resize, encode to base64, done
```

This captures the 3D viewport including editor gizmos. Works in `@tool` plugins.
Source: Godot PR #68696, confirmed in forum posts.

### Camera Control: IMPORTANT LIMITATION

**The editor camera is NOT directly controllable in a persistent way.**

The 3D editor viewport uses an internal `cursor` struct (private in `Node3DEditorViewport`) that stores the "target" position/rotation. The visible camera INTERPOLATES toward this cursor every frame. This means:

- Setting `camera.global_position` directly → works for ONE frame, then interpolation resets it
- Middle-clicking or any user interaction → full reset to cursor position
- **There is NO public API to set the cursor** — Godot proposal #12112 (March 2025) requests this, NOT yet implemented

**What DOES work reliably:**
1. **Reading** camera position/rotation → always accurate
2. **`EditorInterface.edit_node(node)`** → selects a node and the editor's "F" focus shortcut works on it. But this doesn't auto-move the camera.
3. **Temporary positioning + immediate screenshot** → set camera position, wait 1 frame for render, capture screenshot. The image will show the correct view even if the camera interpolates back afterward.

### Our Architecture Decision

**Two tools, not one:**

**`godotiq_screenshot` upgrade** — add `viewport: "editor" | "game"` parameter:
- `"game"` (default) → existing behavior via EngineDebugger
- `"editor"` → capture editor 3D viewport directly from godotiq_server.gd
- Optional: `camera_position` and `camera_target` parameters. If provided:
  1. Save current camera transform
  2. Move camera to requested position + look_at target
  3. Wait 2 frames for rendering
  4. Capture screenshot
  5. Restore original camera transform
  This is ATOMIC — one tool call = move + capture + restore. No interpolation race.

**`godotiq_camera` NEW tool** — editor camera queries and best-effort positioning:
- `action: "get_position"` → read current camera position/rotation (always works)
- `action: "look_at"` → set camera position + target (temporary, will drift back on interaction)
- `action: "focus_node"` → select node in editor. Agent can then use keyboard "F" via input, or accept that selection alone is useful context.

---

## CRITICAL LESSONS (still apply from Phase 2)

1. **NO Python ternaries** in GDScript
2. **`snapped()` NOT `snapf()`**
3. **NO f-strings** in GDScript
4. **Await pattern for frames**: use `await RenderingServer.frame_post_draw` to wait for a render frame, NOT `await get_tree().process_frame` (which may not trigger a viewport redraw)
5. **Editor API available**: `godotiq_server.gd` is a child of the EditorPlugin → `EditorInterface` is directly accessible as a global static

---

## DO NOT TOUCH:
- `src/godotiq/parsers/`, `tools/code/`, `tools/spatial/`, `tools/animation/`, `tools/assets/`, `tools/memory/`
- `src/godotiq/resolvers/`, `src/godotiq/session.py`
- `godot-addon/addons/godotiq/godotiq_plugin.gd`
- `godot-addon/addons/godotiq/godotiq_runtime.gd` — game screenshot stays as-is
- `godot-addon/addons/godotiq/godotiq_debugger.gd`
- Existing test files

## Files to MODIFY:
- `godot-addon/addons/godotiq/godotiq_server.gd` — add `_handle_editor_screenshot()`, `_handle_camera()`, update dispatch
- `src/godotiq/tools/bridge/screenshot.py` (or wherever the screenshot tool is) — add `viewport` parameter routing
- `src/godotiq/__main__.py` (or registration) — register `godotiq_camera`

## Files to CREATE:
- `src/godotiq/tools/bridge/camera.py` — new MCP tool
- `tests/test_bridge/test_camera.py` — tests
- `tests/test_bridge/test_editor_screenshot.py` — tests for editor viewport capture

---

## TOOL 1: `godotiq_screenshot` upgrade — `viewport` parameter

### Current behavior (KEEP UNCHANGED):
- Default sends to game via EngineDebugger → game screenshot

### New behavior:
- `viewport="editor"` → captures editor 3D viewport directly from server
- Optional camera override: `camera_position=[x,y,z]` + `camera_target=[x,y,z]`

### Python: Modify screenshot tool

Add parameters to the existing screenshot tool function:

```python
async def screenshot(
    scale: float = 0.5,
    format: str = "webp",
    viewport: str = "game",
    camera_position: list[float] | None = None,
    camera_target: list[float] | None = None,
) -> dict:
```

### GDScript: Add to `godotiq_server.gd`

Add to dispatch:
```gdscript
"editor_screenshot":
    _handle_editor_screenshot(peer_id, id, params)
```

Implementation uses `EditorInterface.get_editor_viewport_3d(0)`, optional camera repositioning with `await RenderingServer.frame_post_draw` (2 frames), capture, restore.

---

## TOOL 2: `godotiq_camera` — Editor Camera Control

### GDScript: Add to `godotiq_server.gd`

Add to dispatch:
```gdscript
"camera":
    _handle_camera(peer_id, id, params)
```

Actions: get_position, look_at, focus_node.

### Python: Create `src/godotiq/tools/bridge/camera.py`

Camera tool with action parameter routing to bridge.

---

## Summary of deliverables

### Files to CREATE:
| # | Path | Purpose |
|---|------|---------|
| 1 | `src/godotiq/tools/bridge/camera.py` | MCP tool |
| 2 | `tests/test_bridge/test_camera.py` | Tests |
| 3 | `tests/test_bridge/test_editor_screenshot.py` | Tests |

### Files to MODIFY:
| Path | Change |
|------|--------|
| `godot-addon/addons/godotiq/godotiq_server.gd` | Add `editor_screenshot` + `camera` dispatch, handlers with await frame pattern |
| `src/godotiq/tools/bridge/screenshot.py` (or registration) | Add `viewport`, `camera_position`, `camera_target` params |
| `src/godotiq/__main__.py` (or registration) | Register `godotiq_camera` |
| `src/godotiq/prompts/godot_development.md` | Add editor screenshot + camera docs |
