Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ add_executable(Prune
src/prune/core/time.cpp
src/prune/core/input.cpp

src/prune/audio/audio_system.cpp

src/prune/editor/editor_command.cpp
src/prune/editor/editor_actions.cpp

Expand Down
77 changes: 77 additions & 0 deletions DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -892,3 +892,80 @@ Initial tool modes are deliberately limited to Select and Move. Select keeps sel

The active tool is transient editor state. It lives in the generic world scene state so viewport interaction and UI can share it, but it is not saved into scene files.


## Decision — Add basic audio hooks before final event management design

### Context

Prune needs basic sound playback now for clear runtime feedback in the existing sample scenes:

Simple Shooter firing and enemy destruction.
Platformer jumping and player hit/death feedback.
Artillery firing and explosion/player hit feedback.

The broader event/reaction system is not designed yet. Long term, events may drive multiple reaction types, including sounds, animations, sprite changes, UI effects, screen shake, object spawning, and scene-specific behaviours.

Adding a full authored event system now would be premature. The editor UI, asset model, serialisation shape, and scene semantics are not ready for that decision.

### Decision

Add a minimal audio hook path now, built on lightweight scene event ids.

Scenes may emit simple event ids such as:

player_fired
player_jumped
enemy_destroyed
player_hit
round_reset

A small audio layer maps those event ids to hard-coded sound resources and plays them when received.

Scene behaviour must not know:

- Which sound file is used.
- How sound is loaded.
- How sound is mixed.
- Whether audio is enabled.
- Which future reaction types may also respond to the same event.

The app/runtime layer is responsible for passing emitted scene events to the audio system.

- Initial constraints
- Use hard-coded event-to-sound mappings only.
- Keep sound resources small and explicit.
- Keep the audio enable/disable toggle global.
- Do not add authored event UI yet.
- Do not serialise event bindings yet.
- Do not introduce a full asset browser or asset registry for this pass.
- Do not make scene behaviour call audio playback directly.

#### Consequences

This gives Prune useful runtime feedback immediately without committing to the final event architecture.

The current audio hook path is intentionally disposable at the mapping level but not at the boundary level. The important boundary is that scenes emit events and another system consumes them.

Later, the hard-coded audio mapping can be replaced by a more general event reaction system, for example:

player_fired
- Play sound: shoot.wav
- Play animation: muzzle_flash
- Spawn object: projectile
- Trigger UI effect: screen_shake

### Rejected alternative

Direct sound calls inside scene behaviour

Rejected because it would couple scene behaviour to audio playback and make later event-driven reactions harder.

#### Bad direction:

Platformer jump code -> play jump.wav directly

#### Preferred direction:

Platformer jump code -> emit player_jumped
Audio system -> maps player_jumped to jump.wav
Future reaction system -> may also map player_jumped to animation, particles, UI effects, or scene-specific responses
246 changes: 89 additions & 157 deletions NOTES.md
Original file line number Diff line number Diff line change
@@ -1,192 +1,124 @@
# Current Phase — Immediate hardening before next tools
# Current Phase — Short-term editor/runtime hardening

## Goal

Make Prune feel like a real editor rather than a set of game type scene slices with panels attached.
Turn the current editor/runtime foundation into something that behaves more like a typical game engine/editor.

All the previous development proved that multiple scene types can share the same editor/runtime while owning their own behaviour, tools, panels, inspectors, object semantics, defaults, and save data.
The previous phase proved the important foundations: editor commands, undo/redo, multi-select, explicit tool modes, scale, and the first audio/event hook path. The next phase should now harden the everyday editor behaviour around saving, reset/reload, ordering, and scene state tracking.

During the next development phase, we should now prove that the editor can safely manipulate scene-owned objects without bypassing those scene rules.
This phase is not about adding new systems. It is about removing rough edges that will be awkward to deal with later.

## Guiding rule
Prune should know when a scene has changed, what can be saved, what can be reset, what order objects render in, and whether runtime state is being viewed or rebuilt. These behaviours should not be inferred accidentally from object shape, current UI selection, or temporary scene runtime state.

Editor tools must act through explicit editor semantics, not through incidental object shape.
## Targets

A selected object is not just a rectangle. It may be authored, runtime-created, selectable, editable, movable, persistent, solid, hazardous, scene-specific, or protected.
### 1. Dirty state tracking

## Must do first

- [x] Keep player/controller ownership scene-specific unless a genuinely shared abstraction appears.
- [x] Introduce an editor command/change model before implementing undo/redo.
- [x] Keep undo/redo editor-only at first.
- [x] Keep scene activation separate from default scene creation so loading cannot be overwritten by `on_enter()`.

## Phase targets

### 1. Editor command/change model

Create the smallest useful model for editor-authored changes.

Initial command candidates:

- [x] Move object in scene
- [x] Create object
- [x] Delete object
- [x] Rename object
- [x] Change object size
- [x] Change object rendering type (rectangle/colour)
- [x] Change object colour
- [x] Change object sprite
- [x] Viewport movement/zoom (no zoom yet)
- [x] Record state snapshots not delta changes.

Avoid runtime/gameplay commands for now. A projectile moving, an enemy spawning, or an artillery round ending should not enter editor undo history, we just care about what the user did in the editor.

### 2. Undo/redo

Build undo/redo on top of the command model, not as custom reversal logic scattered through tools and panels.
Track whether the current scene has unsaved editor-authored changes.

Initial scope:

- [x] Command history buffer panel with list of past commands
- [x] Move transform tool from scene/tools to editor/tools
- [x] Viewport object movement
- [x] Object creation
- [x] Object deletion
- [x] Simple inspector edits
* [ ] Mark scene dirty when editor commands are executed.
* [ ] Mark scene dirty when inspector edits are committed.
* [ ] Mark scene dirty when authored objects are created, deleted, duplicated, moved, scaled, or reordered.
* [ ] Clear dirty state after a successful save.
* [ ] Keep runtime-only behaviour out of dirty tracking.
* [ ] Show dirty state somewhere lightweight in the editor UI.

Out of scope for the first pass:

- Runtime object history
- Gameplay state rewind
- Save/load history restoration
- Multi-scene history

### 3. Delete and duplicate workflow

Add normal editor actions once command history exists.

Initial scope:

- [x] Delete selected authored object
- [x] Duplicate selected authored object
- [x] Select the duplicated object
- [x] Offset duplicates slightly so the result is visible

This gives undo/redo useful behaviour to prove.
* Save confirmation modal when closing Prune.
* Save confirmation modal when switching scenes.
* Per-scene dirty tracking across multiple open scenes.
* Autosave.

### 4. Multi-select
### 2. CTRL-S save shortcut

Add multi-select after the single-object command path is stable.
Add a normal editor save shortcut once dirty state exists.

Initial scope:

- [x] Selection set instead of one selected id
- [x] Shift-click to add/remove from the selection set
- [x] Clear selection on empty viewport click
- [x] Outliner multi-select support
- [x] Visible outline for every selected object
- [x] Combined selection bounds in the viewport
- [x] Multi-selection drag handle on the selection bounds
- [x] Selection count in editor UI
- [x] Move selected objects as one editor command
- [x] Delete selected deletable objects as one editor command

Multi-select now supports grouped viewport move and grouped delete. Grouped inspector/property edits remain deferred because they need more specific UX and command labels.

### 5. Tool mode state
* [ ] CTRL-S saves the current scene when a scene file path is known.
* [ ] CTRL-S uses the same save path as the existing save workflow.
* [ ] Successful save clears dirty state.
* [ ] Failed save leaves dirty state unchanged.
* [ ] Avoid triggering save repeatedly while the key is held.

Status: implemented.
Out of scope for the first pass:

Introduce an explicit editor tool mode before adding more viewport tools.
* Save As shortcut.
* Recent files.
* Save failure recovery UI beyond a simple message/log entry.

Suggested initial tools:
### 3. Runtime reset and reload

```cpp
enum class EditorTool {
Select,
Move,
Scale,
Rotate
};
```
Add explicit runtime reset/reload behaviour rather than relying only on pause/resume.

This avoids hiding editor behaviour inside whichever handle happened to be clicked.
Initial scope:

Current implementation:
* [ ] Reset runtime state for the active scene without destroying authored scene data.
* [ ] Reload the scene from saved data when a backing file exists.
* [ ] Preserve the distinction between editor-authored objects and runtime-only objects.
* [ ] Clear runtime-only objects during reset/reload.
* [ ] Re-enter scene runtime cleanly after reset/reload.
* [ ] Make behaviour consistent across Simple Shooter, Platformer, and Artillery.
* [ ] New toolbar in the editor for reset/reload/pause/resume.

- [x] Active tool state lives in generic world scene state.
- [x] A fixed viewport palette exposes Select and Move as text tool buttons.
- [x] The viewport palette also exposes scene-owned creation actions such as Wall, Platform, Hazard, and Terrain Line.
- [x] Select keeps the existing selection and move-handle behaviour.
- [x] Move allows direct body dragging for movable authored objects.
- [x] Scale and rotate remain unimplemented until their interaction rules are explicit.
Out of scope for the first pass:

### 6. Scale tool
* Save prompts before reload.
* Runtime state snapshots.
* Gameplay rewind.

Implement scale before rotate.
### 4. Z-index ordering

Scale fits the current object model because Prune already has width/height and rectangle bounds.
Add authored object ordering so render order is deliberate and editable.

Initial scope:

- [x] Single selected authored object
- [x] Corner or edge handle
- [x] Minimum size clamp
- [x] Inspector updates immediately
- [x] Undo/redo command recorded when the drag completes
* [ ] Add an authored z-index/order field to scene objects.
* [ ] Render authored objects using explicit ordering.
* [ ] Persist ordering in scene save data.
* [ ] Restore ordering on load.
* [ ] Add basic editor actions for moving selected object up/down in order.
* [ ] Keep runtime-only ordering behaviour simple and deterministic.

### 7. Basic audio and event hooks

Add audio through events.

Preferred direction:

- Scenes emit lightweight event ids such as `player_fired`, `enemy_destroyed`, `player_hit`, `round_reset`.
- A small audio layer maps event ids to sounds.
- Scene behaviour does not know how sound is played.

Initial scope:
Out of scope for the first pass:

- [ ] One or two hard-coded sound resources
- [ ] Fire event
- [ ] Hit/destroy event
- [ ] Global enable/disable toggle

## Short term, in no particular order

- Z-Index ordering
- Runtime reset and reload, not just pause/resume
- CTRL-S to save scene
- Dirty state tracking for scene

## Medium term, in no particular order

- Rotate tool
- Background image support
- Simplified asset management
- Text rendering
- Behaviour toggles for authored objects
- Polished sample scenes
- Asset browser
- Animated sprites/facing support
- Scene file versioning
- Grid snapping support on all tools and UI option, not in settings
- Object locking and protection
- More robust collision shapes and collision options
- Scene layering, rendering and collision etc.

## Long term, in no particular order

- Grouping
- Input mapping and rebinding
- Scene settings panel for background, music, and other scene-wide options
- Game UI panels
- Pathfinding support
- Full audio mixer
- Prefabs/templates
- Native playable export
- WebAssembly playable export
- Card scene
- Puzzle scene
- Many more scene tools
* Full layer system.
* Separate render/collision layers.
* Drag-and-drop ordering in the outliner.

## Follow on development targets

### Medium term, in no particular order

* Rotate tool
* Background image support
* Simplified asset management
* Text rendering
* Behaviour toggles for authored objects
* Polished sample scenes
* Event management and event-driven reactions (play audio, spawn objects, play animation, screen effects, etc.)
* Asset browser
* Animated sprites/facing support
* Scene file versioning
* Grid snapping support on all tools and UI option, not in settings
* Object locking and protection
* More robust collision shapes and collision options
* Scene layering, rendering and collision etc.

### Long term, in no particular order

* Grouping
* Input mapping and rebinding
* Scene settings panel for background, music, and other scene-wide options
* Game UI panels
* Pathfinding support
* Full audio mixer
* Prefabs/templates
* Native playable export
* WebAssembly playable export
* Card scene
* Puzzle scene
* Many more scene tools
Loading
Loading