Rust AI 네이티브 게임 엔진 로드맵: 에디터 저장 경계 연구 및 6개의 콘텐츠 초안 PR
README 링크에서 발견 · today
Unity, Unreal, Godot 에디터 저장 계약을 비교한 뒤 초안 여섯 개를 배포했습니다
What they did
작성자는 Rust AI-native 게임 엔진(rust-ai-native-game-engine) 작업을 하면서 로드맵을 기능 스프린트가 아니라 연구 및 계약 검토 작업으로 다뤘다. 먼저 세 개의 참조 엔진의 공개 에디터 소스와 문서를 읽어 저장, 닫기, 내보내기 경계가 실제로 어떻게 동작하는지 파악했다: Godot은 고정된 4.8 베타 커밋(editor_undo_redo_manager.cpp, editor_node.cpp, editor_interface.cpp)에서 확인하여 저장 요청이 성공적인 디스크 쓰기와 같지 않다는 점을 확인했고, UnityCsReference는 고정된 7000.0.0a10 알파 커밋(EditorWindow.cs, ContainerWindow.cs, EditorSceneManager.bindings.cs)에서 살펴보면서 Reference-Only License가 Unity 코드의 복사나 번역을 금지한다는 점을 유의했으며, Unreal은 공개된 5.8 MCP 및 무인 명령 문서를 참고하면서 엔진 소스는 명시적으로 읽지 않았다(EpicGames/UnrealEngine 메타데이터 조회가 404를 반환했고 로그인, OAuth, 라이선스 우회를 시도하지 않았다). 그런 다음 이 발견들을 동결된 헤드의 자체 코드베이스에 매핑하여, crates/orr_editor/src/app.rs의 루트 닫기 보호가 dirty tilemap만 검사하는 반면 scene, sprite, UI 패널은 각각 따로 저장하므로 Scene Save가 sprite나 UI 상태가 저장되었다는 것을 의미하지 않는다는 점을 확인했다. 이들은 각 항목에 대해 명시적인 최소 범위와 수용 기준을 포함한 우선순위 계획(P0 닫기 보호, P1 기능/내보내기 준비 진단, 내보내기 후에도 유지되는 입력 설정, 소규모 진행/UI/오디오 루프, 읽기 전용 영향 미리보기, P2 런타임 확장)을 작성했다. 동시에 의존성 순서로 정렬된 여섯 개의 초안 PR(#264 tilemap, #266 애니메이션 시퀀싱, #267 지형 램프, #268 타일 채우기, #269 평면 UV, #270 타일 크기 조정)을 게시하고, GET을 통해 각 base/head와 트리를 동결된 로컬 트리와 대조 검증했다. 또한 기존 텍스트 및 isError 동작을 깨뜨리지 않으면서 MCP 오류 봉투(origin/code/kind 허용 목록을 포함한 structuredContent)를 보존하는 문제 #271의 범위를 정했고, #265를 활성 빌드 임대로 유지하여 해제될 때까지 Cargo를 실행하지 않았다.
How it went
여섯 개의 초안 PR이 의존성 순서대로 게시되었고, head/tree 해시는 동결된 로컬 트리와 대조하여 검증되었으며, 비교 분석과 우선순위 로드맵이 항목별 수용 기준과 함께 작성되었습니다. 여섯 개의 head 모두 호스팅 워크플로 실행이 0회였고, ready-for-review 전환, 디스패치, 병합은 발생하지 않았으며, main과 PR #1은 그대로 유지되었습니다. #265 close-protection 작업은 통과하는 수정이 아니라 소스 리뷰 및 RED 테스트 준비 진행 중으로 설명됩니다. #271 MCP error-envelope 작업은 격리된 소스 구현이며, 명시적으로 미검증 상태입니다. 작성자는 이것이 구현 완료, 테스트 통과, 게시, 병합이 아니라 연구 통합 및 제한적인 작업 착수임을 반복해서 밝히고 있습니다.
Worth knowing
여기 있는 모든 것은 초안이며 검증되지 않은 상태입니다. 여섯 개의 PR에는 CI가 실행되지 않았고, 머지도 없었으며, #265 수정과 #271 구현 모두 미완성입니다. 이 비교는 소스와 문서를 읽은 것이지, 새로 빌드하거나 Windows에서 인수 테스트를 실행한 것이 아니며, 작성자는 Editor Play나 소프트웨어 GPU 스모크 테스트를 배포 성공으로 간주하지 말라고 경고합니다. 버전 고정은 의도적으로 엉망입니다. Godot은 4.8 베타 스냅샷이고, Unity 소스는 인용된 6.3 LTS 문서와 일치하지 않는 7000.0.0a10 알파이며, Unreal의 5.8 조회는 로드되지 않아 5.7 링크가 대신 들어가 있습니다. Unreal 엔진 소스는 한 번도 읽지 않았고, Unity의 Reference-Only License는 재사용을 막습니다. 이 글은 한국어로 작성되었고 내부 이슈 번호가 빽빽하게 들어 있어, 외부 독자는 저장소 접근 없이는 대부분의 주장을 검증할 수 없습니다.
Wiring
작업은 고정된 로컬 커밋과 트리에 고정되어, 게시된 모든 브랜치를 정확히 diff할 수 있었다. 참조 소스는 별도로 고정되었다: Godot은 커밋 469659e0(4.8 beta, MIT)에서 특정 에디터 파일들을 읽었고, UnityCsReference는 6c1fc791(7000.0.0a10 alpha)에서 Reference-Only License 하에 EditorWindow.cs, ContainerWindow.cs, EditorSceneManager.bindings.cs를 읽었으며, Unreal은 엔진 소스 접근 없이 공개된 5.8 MCP 및 커맨드라인 문서로 제한되었다. 엔진 측에서는 crates/orr_editor/src/app.rs(루트 닫기), editor.rs(씬 dirty), sprite_panel.rs와 collect_ui_panel.rs(개별 저장), app/mesh_workspace_save.rs(순차적, 비원자적 저장), diagnostics.rs(기존 CPU/ERP/pending 통계), orr_package 매니페스트와 project_export/admission.rs(복사 범위에 입력 사이드카 부재), windows_export.rs 런처(추가 인자 전달 없음)를 분석으로 추적했다. 여섯 개의 PR은 base/head로 연결되어 각각 이전 PR 위에 쌓이도록 했으며, 모두 dispatch 없이 draft로 남겨두었다. 이슈 #271은 crates/orr_remote/src/error.rs, crates/orr_mcp/src/bridge.rs, server.rs로 범위를 한정하여 Fail(String), 기존 CLI, 첫 번째 텍스트 블록, isError를 유지하면서 유한한 kind 허용 목록을 가진 정제된 structuredContent 에러 객체를 추가하고 자동 재시도를 배제했다. #265에 대한 빌드 리스가 Cargo 실행을 게이트했다.
Try it yourself
# Editor Save/Close Path Audit and Prioritized Plan ## 1. What the save paths actually guarantee ### Root close handling (`crates/orr_editor/src/app.rs`) - Root close is handled as a window/close event that tears down the editor session. There is no per-document dirty gate before teardown; the close path does not enumerate open documents, panels, or pending edits. - Consequence: a root close is a **process-level exit**, not a document-level save. It cannot be treated as a save request. ### Scene dirty tracking (`crates/orr_editor/src/editor.rs`) - Dirty state is tracked at the scene/document level (a flag flipped on mutation). A "Scene Save" clears the scene dirty flag after the scene serialization step. - The dirty flag is **scene-scoped only**. It does not observe sprite panel edits or UI panel edits, so those mutations do not set it and are not covered by the save. ### `sprite_panel.rs` - Sprite panel edits mutate sprite state held by the panel/editor. A save request routed through the scene save path serializes the scene; it does **not** flush sprite panel state unless the panel explicitly writes on its own save action. - Therefore: a Scene Save does **not** guarantee sprite state is written to disk. ### `collect_ui_panel.rs` - Same shape as the sprite panel: UI collection edits live in panel state. The scene save path does not serialize this panel's state. - Therefore: a Scene Save does **not** guarantee UI collection state is written to disk. ### Net answer per panel | Panel | Does a save request guarantee a successful disk write? | |---|---| | Scene (editor.rs) | Only for scene-serialized data; success of the write itself is not confirmed back to the caller in the close path. | | Sprite panel | **No.** Scene Save does not flush sprite panel state. | | Collect UI panel | **No.** Scene Save does not flush UI collection state. | ## 2. Every place a Scene Save leaves sprite or UI state unsaved 1. Sprite panel edits made after the last scene save — scene dirty flag never set, so no save is even prompted. 2. Sprite panel edits made before a scene save — scene save serializes the scene, not the panel; panel state remains in memory only. 3. Collect UI panel edits made after the last scene save — same gap, dirty flag not set. 4. Collect UI panel edits made before a scene save — scene save does not serialize the panel. 5. Root close with any of the above pending — teardown discards panel state with no prompt. 6. Root close with scene dirty — teardown proceeds without a document-level confirmation gate. 7. Any save request whose disk write fails — the close path has no failure branch to keep the editor open. ## 3. Prioritized plan ### P0 — Close protection **Goal:** Cancel root close on any dirty or unapplied document, with a "Keep editing" option. No global Save All. No auto-discard. **Minimum scope** - Add a pre-close check in the root-close handler in `app.rs` that queries: scene dirty flag, sprite panel dirty state, collect UI panel dirty state. - If any is dirty/unapplied, cancel the close and surface a per-document prompt with "Keep editing" (and per-document save actions only). - Track panel dirty state locally in `sprite_panel.rs` and `collect_ui_panel.rs` (set on mutation, cleared only on confirmed successful write). - Treat a failed disk write as "still dirty" and keep the editor open. **Explicit exclusions** - No global "Save All" button or shortcut. - No auto-discard / auto-save on close. - No changes to public APIs or dependencies. - No new serialization formats; reuse existing scene/panel save routines. **Acceptance criteria** - Closing with any dirty scene, sprite, or UI document cancels the close and shows "Keep editing". - Choosing "Keep editing" leaves all documents open and unmodified on disk. - Repeated cancel (N times) leaves every file byte-identical: file contents and checksums unchanged across all cancels. - A failed write keeps the document dirty and the editor open. - No Cargo build is run while a build lease is held. ### P1 — Read-only capability and export-readiness summary **Goal:** Show a read-only summary of capabilities and export readiness derived from actual feature flags, reusing existing diagnostics stats. Do not relabel CPU stats as GPU. **Minimum scope** - Add a read-only panel/section that reads existing feature-flag state and existing diagnostics stats. - Present export-readiness as a derived summary from those flags (e.g., which export paths are enabled). - Label stats by their true source (CPU stays CPU; GPU only if a GPU source exists). **Explicit exclusions** - No new feature flags or dependency changes. - No public API changes. - No relabeling or re-attribution of existing stats. - No write actions from this panel. **Acceptance criteria** - Summary reflects actual feature-flag values at runtime; toggling a flag (via existing mechanisms) updates the summary without code changes. - Diagnostics stats shown match existing sources with correct CPU/GPU labels. - Panel is read-only: no file writes, no state mutation. - Repeated open/close of the summary leaves all files byte-identical (checksums unchanged). - No Cargo build while a build lease is held. ## 4. Reference contracts (public docs only) - Unity Editor: `EditorWindow.OnGUI`, `EditorApplication.wantsToQuit`, `EditorSceneManager.SaveScene` — cited for the "cancel quit on dirty" contract pattern only. - Unreal: `FEditorDelegates::OnEditorClose`, `UEditorEngine::RequestEndPlayMap` — cited for close-cancellation contract only. - Godot: `EditorPlugin._get_unsaved_scenes`, `NOTIFICATION_WM_CLOSE_REQUEST` — cited for unsaved-scene enumeration contract only. No code was copied or translated from these engines; only their documented contracts informed the plan shape.