NEON-25: follow-up from code review (missing target warn, docs, E1.M2 status)

pull/31/head
VinPropane 2026-04-07 23:54:27 -04:00
parent f4b34316a6
commit e96f70d889
4 changed files with 22 additions and 4 deletions

View File

@ -3,8 +3,9 @@ extends RefCounted
## Client-local camera snapshot for consumers (risk UX, UI, debug). Refreshed each frame by
## `isometric_follow_camera.gd`. No `class_name` — see repo Godot headless / CI notes.
## Orbit yaw (rad) around the follow target **vertical axis**, relative to [member presentation_yaw_deg]
## on the rig. Prototype UX keeps this at **0** (`allow_yaw` false). Mid-project orbit would drive this.
## Orbit yaw (rad) around the follow target **vertical axis**, **relative to** the rigs fixed
## presentation compass (`presentation_yaw_deg` on `isometric_follow_camera.gd`). This is **not** total
## camera compass—only the optional orbit delta. Prototype UX keeps this at **0** (`allow_yaw` false).
var yaw: float = 0.0
## Scene path to the follow anchor (typically `CharacterBody3D` / `Node3D`).

View File

@ -32,6 +32,7 @@ var camera_state:
var _state = null
var _smoothed_eye: Vector3 = Vector3.ZERO
var _orbit_yaw_rad: float = 0.0
var _warned_missing_follow_target: bool = false
func _ready() -> void:
@ -57,6 +58,7 @@ func _ready() -> void:
_sync_camera_state(focus0)
else:
_smoothed_eye = global_position
_warn_missing_follow_target_once()
func _process(delta: float) -> void:
@ -64,7 +66,10 @@ func _process(delta: float) -> void:
return
var target: Node3D = _resolve_target()
if target == null:
# No eye/state update until the path resolves — avoids chasing a freed or miswired node.
_warn_missing_follow_target_once()
return
_warned_missing_follow_target = false
if not allow_yaw:
_orbit_yaw_rad = 0.0
@ -91,6 +96,7 @@ func _process(delta: float) -> void:
func _sync_camera_state(focus: Vector3) -> void:
# `CameraState.yaw` stores **orbit delta** only; world-fixed diagonal framing is `presentation_yaw_deg`.
_state.follow_target_path = follow_target_path
_state.distance = follow_distance
_state.zoom_band_index = 0
@ -107,6 +113,15 @@ func _resolve_target() -> Node3D:
return null
func _warn_missing_follow_target_once() -> void:
if _warned_missing_follow_target:
return
_warned_missing_follow_target = true
push_warning(
"IsometricFollowCamera: follow_target_path is empty or does not resolve to a Node3D; camera not updating."
)
static func desired_eye_world(
focus: Vector3, distance: float, pitch_elevation_rad: float, yaw_rad: float
) -> Vector3:

View File

@ -7,7 +7,7 @@
| **Module ID** | E1.M2 |
| **Epic** | [Epic 1 — Core Player Runtime](../epics/epic_01_core_player_runtime.md) |
| **Stage target** | Prototype |
| **Status** | Planned (see [dependency register](module_dependency_register.md)) |
| **Status** | In progress — follow + `CameraState` baseline shipped ([NEON-25](https://neon-sprawl.atlassian.net/browse/NEON-25)); zoom, occlusion, hardening open ([NEON-26](https://neon-sprawl.atlassian.net/browse/NEON-26)[NEON-28](https://neon-sprawl.atlassian.net/browse/NEON-28)); see [dependency register](module_dependency_register.md) |
| **Jira** | Feature [NEON-10](https://neon-sprawl.atlassian.net/browse/NEON-10); prototype backlog stories under parent [NEON-1](https://neon-sprawl.atlassian.net/browse/NEON-1) — [Jira backlog](#jira-backlog) |
## Purpose

View File

@ -13,10 +13,12 @@ Fleshed-out scope, contracts, and integration notes live in **per-module documen
| Module ID | Module Name | Depends On | Contract Needed | Phase Required | Status |
|---|---|---|---|---|---|
| E1.M1 | InputAndMovementRuntime | None | MoveCommand, PositionState, InteractionRequest | Prototype | Ready |
| E1.M2 | IsometricCameraController | E1.M1 | CameraState, ZoomBandConfig, OcclusionPolicy | Prototype | Planned |
| E1.M2 | IsometricCameraController | E1.M1 | CameraState, ZoomBandConfig, OcclusionPolicy | Prototype | In progress |
| E1.M3 | InteractionAndTargetingLayer | E1.M1 | TargetState, InteractableDescriptor, SelectionEvent | Prototype | Planned |
| E1.M4 | AbilityInputScaffold | E1.M3, E5.M1 | AbilityCastRequest, HotbarLoadout, CooldownSnapshot | Prototype | Planned |
**E1.M2 note:** Client follow rig + per-tick `CameraState` baseline is in repo ([NEON-25](https://neon-sprawl.atlassian.net/browse/NEON-25)). Discrete zoom bands, occlusion policy, and integration hardening remain ([NEON-26](https://neon-sprawl.atlassian.net/browse/NEON-26)[NEON-28](https://neon-sprawl.atlassian.net/browse/NEON-28)).
### Epic 2 — Skills and Progression Framework
| Module ID | Module Name | Depends On | Contract Needed | Phase Required | Status |