# Phase 9 Prop Editor — Round 6 (Recent-on-save, Reshaped Flag, Selection Contrast) Status: **implemented** (2026-09-19; direct round — no open design choices). Source: three user feedback points against the shipped Round 5 Prop Editor. ## Feedback summary 1. Saving a file should add it to File → Recent when it isn't there yet. 2. A circle's inspector Radius field becomes meaningless once the circle's vertices are reshaped; every primitive needs a `reshaped` flag so primitive-specific inspector fields hide/disable after reshaping. 3. A white shape in front of a white shape makes the white selection outline/box invisible; the selection color should contrast with the shape's fill. ## Design decisions - **Recent-on-save:** `_save_to()` calls `_push_recent(path)` on success (dedupe + front-insert + trim, same helper as load — a save is recent activity). - **`reshaped` flag:** new boolean on every shape dict (internal + export + `.prop` schema, default `false`; additive and backward compatible — old files load as `false`). Set to `true` by: `insert_vertex`, `remove_vertex`, vertex-drag motion, `create_point_on_edge` (via insert), and **non-uniform scaling of a circle** (both the gizmo drag and `scale_selected`); cleared by `set_shape_radius` (which regenerates points from the radius). Translate/rotate/mirror/uniform-scale do **not** set it — they preserve primitive-ness. The inspector hides the Radius row and shows a muted "✏️ This shape was reshaped" note when the selected shape's flag is set (the flag exists on every primitive so future primitive-specific fields can gate on it the same way). - **Selection contrast:** new `PropCanvas.contrast_color_for(fill_hex) -> Color` — dark (`#1F1F1F`) for light fills (luminance > 0.5), white otherwise. Applied to the selection polyline and all gizmo drawing (bbox, rotation dot, scale crosses), which were previously hard white and vanished on white shapes. Vertex handles stay fill-colored (stickman-editor parity, Round 2 decision); the Create-Point flash stays yellow. ## Changes | Target | Change | | --- | --- | | `scripts/prop_editor.gd` | `_save_to` pushes the path to recents on success; `_reshaped_note` label; `_refresh_inspector_from_selection` gates `_radius_row.visible` on `not reshaped` and shows the note when reshaped. | | `scripts/prop_canvas.gd` | `"reshaped"` in `_make_shape_dict`/`_coerce_shape`/`_export_shape`; mutation sites set/clear it; `contrast_color_for` static; selection polyline + gizmos use the contrast color. | | `scripts/prop_file.gd` | `"reshaped"` serialized/parsed (default `false`). | | `tests/test_prop_editor_canvas.gd` | New `_test_reshaped_flag` (insert/remove/radius-reset/scale/mirror/translate/rotate matrix) and `_test_selection_contrast`. | | `tests/test_prop_editor_file.gd` | Round-trip `reshaped` preservation + default-false assertions. | ## Verification - `--check-only` clean; all five suites green (file 68, theme 53, canvas 100, thumb 10, round3 21). - Manual F6: save a new prop → appears in File → 🕑 Recent; reshape a circle (drag a vertex, create a point, or stretch non-uniformly) → Radius row disappears + muted note; select a white shape → dark outline/box/dot/crosses.