diff --git a/.codegraph/.gitignore b/.codegraph/.gitignore new file mode 100644 index 0000000..d20c0fe --- /dev/null +++ b/.codegraph/.gitignore @@ -0,0 +1,5 @@ +# CodeGraph data files — local to each machine, not for committing. +# Ignore everything in .codegraph/ except this file itself, so transient +# files (the database, daemon.pid, sockets, logs) never show up in git. +* +!.gitignore diff --git a/.vitepress/config.ts b/.vitepress/config.ts index a465018..9374ec5 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -193,11 +193,12 @@ export default defineConfig({ }, { text: 'Tilemap Editor', - collapsed: true, + collapsed: false, items: [ { text: 'Overview', link: '/tools/tilemap-editor/overview' }, { text: 'Quick start', link: '/tools/tilemap-editor/quick-start' }, { text: 'Installation', link: '/tools/tilemap-editor/installation' }, + { text: 'License & Activation', link: '/tools/tilemap-editor/license-and-activation' }, { text: 'Usage guide', link: '/tools/tilemap-editor/usage-guide' }, { text: 'Advanced guide', link: '/tools/tilemap-editor/advanced-guide' }, { text: 'Technical reference', link: '/tools/tilemap-editor/technical-reference' }, diff --git a/api/generated/audio/DefaultAudioScheduler.md b/api/generated/audio/DefaultAudioScheduler.md index bfcb940..b67cbe7 100644 --- a/api/generated/audio/DefaultAudioScheduler.md +++ b/api/generated/audio/DefaultAudioScheduler.md @@ -30,6 +30,19 @@ For platforms with a dedicated audio task (e.g., FreeRTOS on ESP32), ### `void init(AudioBackend* backend, int sampleRate, const pixelroot32::platforms::PlatformCapabilities& caps, int blockSize = 256)` +**Description:** + +Initializes the underlying ApuCore. + +**Parameters:** + +- `backend`: Unused: generation is driven by the caller of + generateSamples(), so no backend handle is needed. +- `sampleRate`: Output sample rate forwarded to ApuCore. +- `caps`: Unused: no thread/core pinning happens here. +- `blockSize`: Unused: the caller chooses the buffer length on + every generateSamples() call. + ### `void submitCommand(const AudioCommand& cmd)` **Description:** @@ -44,13 +57,13 @@ Enqueues a command to the ApuCore. @param cmd The command to submit. **Description:** -Marks scheduler as running. Starts audio generation context. +Resumes sample generation after stop(). Generation starts enabled. ### `void stop()` **Description:** -Marks scheduler as stopped. Silences all voices. +Halts generation: generateSamples() outputs silence until start(). ### `bool isIndependent() const` diff --git a/api/generated/index.md b/api/generated/index.md index a7a2e47..b901699 100644 --- a/api/generated/index.md +++ b/api/generated/index.md @@ -4,22 +4,12 @@ Auto-generated API documentation from C++ header files. ## Audio -- [ApuCore](./audio/ApuCore.md) — Shared NES-style APU core used by every AudioScheduler. - [AudioBackend](./audio/AudioBackend.md) — Abstract interface for platform-specific audio drivers. -- [AudioChannel](./audio/AudioChannel.md) — Represents the internal state of a single audio channel. -- [AudioCommand](./audio/AudioCommand.md) — Internal command to communicate between game and audio threads. -- [AudioCommandQueue](./audio/AudioCommandQueue.md) — Single-Producer Single-Consumer (SPSC) lock-free ring buffer for AudioCommands. - [AudioConfig](./audio/AudioConfig.md) — Configuration for the Audio subsystem. - [AudioEngine](./audio/AudioEngine.md) — Facade class for the NES-style audio subsystem. -- [AudioEvent](./audio/AudioEvent.md) — A fire-and-forget sound event triggered by the game. - [AudioScheduler](./audio/AudioScheduler.md) — Abstract interface for the audio execution context. - [DefaultAudioScheduler](./audio/DefaultAudioScheduler.md) — Backend-driven scheduler used on platforms without a dedicated audio task. -- [EnvelopeState](./audio/EnvelopeState.md) — Holds ADSR envelope state for a single voice. -- [InstrumentPreset](./audio/InstrumentPreset.md) — Defines instrument characteristics for playback. -- [LfoState](./audio/LfoState.md) — Holds LFO (Low-Frequency Oscillator) state for pitch or volume modulation. -- [MusicNote](./audio/MusicNote.md) — Represents a single note in a melody. - [MusicPlayer](./audio/MusicPlayer.md) — Simple sequencer to play MusicTracks using the AudioEngine. -- [SfxBreakpoint](./audio/SfxBreakpoint.md) — Timed automation point for SFX duty steps or pitch envelope. ## Core diff --git a/examples/demos.md b/examples/demos.md index d42d56a..188197c 100644 --- a/examples/demos.md +++ b/examples/demos.md @@ -26,7 +26,7 @@ The engine revision for each example is defined in `**lib_deps**` inside that ex - [flappy_bird](./flappy_bird) — [source code](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Game-Engine/tree/main/examples/flappy_bird) - [hello_world](./hello_world) — [source code](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Game-Engine/tree/main/examples/hello_world) - [metroidvania](./metroidvania) — [source code](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Game-Engine/tree/main/examples/metroidvania) -- [music_demo](./music_demo) — [source code](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Game-Engine/tree/main/examples/music_demo) +- [music-demo](./music-demo) — [source code](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Game-Engine/tree/main/examples/music-demo) - [physics](./physics) — [source code](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Game-Engine/tree/main/examples/physics) - [snake](./snake) — [source code](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Game-Engine/tree/main/examples/snake) - [space_invaders](./space_invaders) — [source code](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Game-Engine/tree/main/examples/space_invaders) diff --git a/examples/music-demo.md b/examples/music-demo.md index 427cf95..d5986e1 100644 --- a/examples/music-demo.md +++ b/examples/music-demo.md @@ -28,43 +28,43 @@ See **`platformio.ini`** for **`native`** and **`esp32dev`**. ## Melody assets (`src/assets/`) -Tracks are split per theme; shared beat constants and demo-only **`InstrumentPreset`** overrides live in **`common_melodies.h`**: +Melodies are **generated by the PixelRoot32 Tool Suite** from their **`.pr32music`** sources. Each asset is self-contained: it carries its own **`LIB_*`** `InstrumentPreset` definitions, beat constants (`S`/`E`/`Q`/`H`/`W`), and a **four-part** `MusicTrack` arrangement: -| File | Role | -|------|------| -| [`common_melodies.h`](src/assets/common_melodies.h) | Beat fractions (`S`/`E`/`Q`/…), `kDemoArcadeLeadWave` / `kDemoAdventureLeadWave`, **`DEMO_SNES_LEAD_TIGHT`** / **`DEMO_SNES_BASS_STAC`** (tighter ADSR for SNES-style arranging), **`ARP_STEP`** | -| [`classic_arcade_melody.h`](src/assets/classic_arcade_melody.h) | **Melody 1** — Classic Arcade (`sClassicArcadeTrack`) | -| [`adventure_melody.h`](src/assets/adventure_melody.h) | **Melody 2** — Adventure (`sAdventureTrack`) | -| [`action_melody.h`](src/assets/action_melody.h) | **Melody 3** — Action (`sActionTrack`) | -| [`arpeggio_melody.h`](src/assets/arpeggio_melody.h) | **Melody 4** — Em arpeggio demo (`sArpDemoTrack`) | +| File | UI button | Role | +|------|-----------|------| +| [`blaster_ridge.h`](src/assets/blaster_ridge.h) | **Blaster Ridge** | `musicdemo::blaster_ridge::kTrack` — fast action theme | +| [`coinleaf_grove.h`](src/assets/coinleaf_grove.h) | **Coinleaf Grove** | `musicdemo::coinleaf_grove::kTrack` — light adventure theme | +| [`lightworld_march.h`](src/assets/lightworld_march.h) | **Lightworld March** | `musicdemo::lightworld_march::kTrack` — heroic march | +| [`moonwell_hymn.h`](src/assets/moonwell_hymn.h) | **Moonwell Hymn** | `musicdemo::moonwell_hymn::kTrack` — dreamy hymn | -Each full arrangement uses **`MusicTrack`** layering: **main** + optional **`secondVoice`**, **`thirdVoice`**, and **`percussion`**, flattened by `MusicPlayer` into the global voice pool (**`ApuCore::MAX_VOICES`** = 8). The headers comment on keeping harmony/percussion notes relatively short so **SFX** can share the pool without constant stealing. +Each `.h` has a companion **`.h.pr32music`** sidecar (name, BPM, patterns) used to generate it. + +Each arrangement layers **main** lead + **`secondVoice`** (bass) + **`thirdVoice`** (harmony) + **`percussion`**, mapped by `MusicPlayer` to ApuCore music slots **0–3** (SFX keeps slots **4–7**). The per-track `LIB_*` presets are tuned so loops stay full after beat-accurate gates. ## Melodies (UI labels vs. engine) | UI button | BPM (see `MusicDemoScene::playMelody`) | Loop length (beats) | Layers (summary) | |-----------|----------------------------------------|---------------------|------------------| -| **Melody 1** | 140 | 32 | **SAW** lead (`kDemoArcadeLeadWave`), bass (`DEMO_SNES_BASS_STAC`), pulse harmony stabs, noise drums (two groove blocks + fill) | -| **Melody 2** | 125 | 64 | **SINE** lead (`kDemoAdventureLeadWave`), bass, harmony, drums (extended **A \| B \| A′ \| C**-style material) | -| **Melody 3** | 160 | 32 | **PULSE** lead via **`DEMO_SNES_LEAD_TIGHT`** (16th-style arpeggio macros), matching bass, sparse harmony hits, dense 16th-hat drums + break | -| **Melody 4 + ARP voice** | 145 | 32 | **SAW** lead (`kDemoArcadeLeadWave`), **`secondVoice`**: fast Em arpeggio (`INSTR_TRIANGLE_LEAD`, **`WaveType::SINE`** on the sub-track), **`thirdVoice`**: bass, **same drum grid as Melody 1** for a stable loop | +| **Blaster Ridge** | 168 | 32 | **SAW** lead (`LIB_SAW_EDGE`/`BRIGHT`/`RAZOR`), **SAW** growl bass (`LIB_SAW_GROWL_BASS`), **PULSE** harmony hits (`LIB_PULSE_HERO_BRASS`), noise drums with clap / crash / tom / zap fills | +| **Coinleaf Grove** | 152 | 32 | **PULSE** lead (`LIB_PULSE_BRIGHT`/`SPARK`/`THIN`), **TRIANGLE** thump bass (`LIB_TRIANGLE_THUMP`), pulse harmony, noise drums with clap and open-hat accents | +| **Lightworld March** | 128 | 32 | **PULSE** lead (`LIB_PULSE_BRIGHT`), **TRIANGLE** thump bass, pulse hero-brass / warm-pad harmony, noise drums with crash, tom fills and open hats | +| **Moonwell Hymn** | 104 | 32 | **SINE** flute lead (`LIB_SINE_FLUTE`, bell/glass accents), **TRIANGLE** sub bass (`LIB_TRIANGLE_SUB_BASS`), sine dream/air-pad harmony, noise drums with ride, crash, soft snare and open hats | ## Features -- **10 engine instrument presets** (one-shot tests) — Lead Square, Harmony Square, Bass Triangle, Kick, Snare, Hi-hat, Triangle Lead, Triangle Pad, Pulse Pad, Pulse Bass -- **4 multi-part demo tracks** — layered loops with distinct BPM and form (see table above) -- **Melody 4** — full **four-part** demo: lead + arpeggiated **`secondVoice`** + bass + percussion (not just lead + arp) +- **10 engine instrument presets** (one-shot tests) — Pulse Lead, Pulse Harmony, Triangle Bass, Pulse Bass, Triangle Lead, Triangle Pad, Pulse Pad, Kick, Snare, Hi-hat +- **4 four-part demo tracks** — each layers lead + bass (`secondVoice`) + harmony (`thirdVoice`) + percussion, generated from tool-suite `.pr32music` assets with distinct BPM and texture (see table above) - **Audio Lab menu** — **pulse frequency sweep** (Phase A), **SINE / SAW chord** one-shots (Phase B), and **master bitcrush** cycling via `AudioEngine::setMasterBitcrush` - **UI-based sound testing** — play individual instrument sounds on demand -- **Modular audio architecture** — demonstrates `InstrumentPreset`, per-demo preset tweaks, melody sequencing, `AudioEvent` sweep fields, and audio scheduling +- **Modular audio architecture** — demonstrates `InstrumentPreset`, per-asset `LIB_*` preset tuning, melody sequencing, `AudioEvent` sweep fields, and audio scheduling ## Documentation links -- [Audio API](/api/audio) -- [Music player guide](/guide/music-player-guide.md) -- [Input API](/api/input) -- [UI API](/api/ui) -- [Core — Scene](/api/core) +- [Audio API](../../docs/api/audio.md) +- [Music player guide](../../docs/guide/music-player-guide.md) +- [Input API](../../docs/api/input.md) +- [UI API](../../docs/api/ui.md) +- [Core — Scene](../../docs/api/core.md) ## Build diff --git a/examples/music_demo.md b/examples/music_demo.md index 3863474..d5986e1 100644 --- a/examples/music_demo.md +++ b/examples/music_demo.md @@ -28,35 +28,35 @@ See **`platformio.ini`** for **`native`** and **`esp32dev`**. ## Melody assets (`src/assets/`) -Tracks are split per theme; shared beat constants and demo-only **`InstrumentPreset`** overrides live in **`common_melodies.h`**: +Melodies are **generated by the PixelRoot32 Tool Suite** from their **`.pr32music`** sources. Each asset is self-contained: it carries its own **`LIB_*`** `InstrumentPreset` definitions, beat constants (`S`/`E`/`Q`/`H`/`W`), and a **four-part** `MusicTrack` arrangement: -| File | Role | -|------|------| -| [`common_melodies.h`](src/assets/common_melodies.h) | Beat fractions (`S`/`E`/`Q`/…), wave aliases, demo **`InstrumentPreset`** overrides (`DEMO_MELODY_LEAD`, `DEMO_HARMONY`, `DEMO_DRUM_*`, `DEMO_SNES_*`, `DEMO_ARP_VOICE`) retuned for beat-accurate gates under ApuCore 4+4 | -| [`classic_arcade_melody.h`](src/assets/classic_arcade_melody.h) | **Melody 1** — Classic Arcade (`sClassicArcadeTrack`) | -| [`adventure_melody.h`](src/assets/adventure_melody.h) | **Melody 2** — Adventure (`sAdventureTrack`) | -| [`action_melody.h`](src/assets/action_melody.h) | **Melody 3** — Action (`sActionTrack`) | -| [`arpeggio_melody.h`](src/assets/arpeggio_melody.h) | **Melody 4** — Em arpeggio demo (`sArpDemoTrack`) | +| File | UI button | Role | +|------|-----------|------| +| [`blaster_ridge.h`](src/assets/blaster_ridge.h) | **Blaster Ridge** | `musicdemo::blaster_ridge::kTrack` — fast action theme | +| [`coinleaf_grove.h`](src/assets/coinleaf_grove.h) | **Coinleaf Grove** | `musicdemo::coinleaf_grove::kTrack` — light adventure theme | +| [`lightworld_march.h`](src/assets/lightworld_march.h) | **Lightworld March** | `musicdemo::lightworld_march::kTrack` — heroic march | +| [`moonwell_hymn.h`](src/assets/moonwell_hymn.h) | **Moonwell Hymn** | `musicdemo::moonwell_hymn::kTrack` — dreamy hymn | -Each full arrangement uses **`MusicTrack`** layering: **main** + optional **`secondVoice`**, **`thirdVoice`**, and **`percussion`**, mapped by `MusicPlayer` to ApuCore music slots **0–3** (SFX keeps slots **4–7**). Demo presets in **`common_melodies.h`** add level and tail so loops stay full after beat-accurate gates. +Each `.h` has a companion **`.h.pr32music`** sidecar (name, BPM, patterns) used to generate it. + +Each arrangement layers **main** lead + **`secondVoice`** (bass) + **`thirdVoice`** (harmony) + **`percussion`**, mapped by `MusicPlayer` to ApuCore music slots **0–3** (SFX keeps slots **4–7**). The per-track `LIB_*` presets are tuned so loops stay full after beat-accurate gates. ## Melodies (UI labels vs. engine) | UI button | BPM (see `MusicDemoScene::playMelody`) | Loop length (beats) | Layers (summary) | |-----------|----------------------------------------|---------------------|------------------| -| **Melody 1** | 140 | 32 | **SAW** lead (`kDemoArcadeLeadWave`), bass (`DEMO_SNES_BASS_STAC`), pulse harmony stabs, noise drums (two groove blocks + fill) | -| **Melody 2** | 125 | 64 | **SINE** lead (`kDemoAdventureLeadWave`), bass, harmony, drums (extended **A \| B \| A′ \| C**-style material) | -| **Melody 3** | 160 | 32 | **PULSE** lead via **`DEMO_SNES_LEAD_TIGHT`** (16th-style arpeggio macros), matching bass, sparse harmony hits, dense 16th-hat drums + break | -| **Melody 4 + ARP voice** | 145 | 32 | **SAW** lead (`kDemoArcadeLeadWave`), **`secondVoice`**: fast Em arpeggio (`INSTR_TRIANGLE_LEAD`, **`WaveType::SINE`** on the sub-track), **`thirdVoice`**: bass, **same drum grid as Melody 1** for a stable loop | +| **Blaster Ridge** | 168 | 32 | **SAW** lead (`LIB_SAW_EDGE`/`BRIGHT`/`RAZOR`), **SAW** growl bass (`LIB_SAW_GROWL_BASS`), **PULSE** harmony hits (`LIB_PULSE_HERO_BRASS`), noise drums with clap / crash / tom / zap fills | +| **Coinleaf Grove** | 152 | 32 | **PULSE** lead (`LIB_PULSE_BRIGHT`/`SPARK`/`THIN`), **TRIANGLE** thump bass (`LIB_TRIANGLE_THUMP`), pulse harmony, noise drums with clap and open-hat accents | +| **Lightworld March** | 128 | 32 | **PULSE** lead (`LIB_PULSE_BRIGHT`), **TRIANGLE** thump bass, pulse hero-brass / warm-pad harmony, noise drums with crash, tom fills and open hats | +| **Moonwell Hymn** | 104 | 32 | **SINE** flute lead (`LIB_SINE_FLUTE`, bell/glass accents), **TRIANGLE** sub bass (`LIB_TRIANGLE_SUB_BASS`), sine dream/air-pad harmony, noise drums with ride, crash, soft snare and open hats | ## Features -- **10 engine instrument presets** (one-shot tests) — Lead Square, Harmony Square, Bass Triangle, Kick, Snare, Hi-hat, Triangle Lead, Triangle Pad, Pulse Pad, Pulse Bass -- **4 multi-part demo tracks** — layered loops with distinct BPM and form (see table above) -- **Melody 4** — full **four-part** demo: lead + arpeggiated **`secondVoice`** + bass + percussion (not just lead + arp) +- **10 engine instrument presets** (one-shot tests) — Pulse Lead, Pulse Harmony, Triangle Bass, Pulse Bass, Triangle Lead, Triangle Pad, Pulse Pad, Kick, Snare, Hi-hat +- **4 four-part demo tracks** — each layers lead + bass (`secondVoice`) + harmony (`thirdVoice`) + percussion, generated from tool-suite `.pr32music` assets with distinct BPM and texture (see table above) - **Audio Lab menu** — **pulse frequency sweep** (Phase A), **SINE / SAW chord** one-shots (Phase B), and **master bitcrush** cycling via `AudioEngine::setMasterBitcrush` - **UI-based sound testing** — play individual instrument sounds on demand -- **Modular audio architecture** — demonstrates `InstrumentPreset`, per-demo preset tweaks, melody sequencing, `AudioEvent` sweep fields, and audio scheduling +- **Modular audio architecture** — demonstrates `InstrumentPreset`, per-asset `LIB_*` preset tuning, melody sequencing, `AudioEvent` sweep fields, and audio scheduling ## Documentation links diff --git a/tools/index.md b/tools/index.md index de2b5fd..442d3d4 100644 --- a/tools/index.md +++ b/tools/index.md @@ -6,7 +6,12 @@ PixelRoot32 ships optional **workflow tools** alongside the open-source engine. ## Sprite Compiler (free) -Converts **PNG** images into **C headers** with sprite data (layered 1bpp, 2bpp, 4bpp, grid selection, GUI + CLI). +Converts **PNG** images into **C headers** with sprite data (layered 1bpp, 2bpp, 4bpp, grid selection). + +**Two ways to use it:** + +- **Tool Suite (recommended)**: Integrated as a native GUI module inside the Tool Suite. The actual compilation uses an external `pr32-sprite-compiler` CLI (bundled with the Tool Suite or available on `PATH`). +- **Standalone CLI**: Open-source Python repo (`python main.py …`) — ideal for CI scripts and build-automation without the full Tool Suite. - [Overview](/tools/sprite-compiler/overview) - [Installation](/tools/sprite-compiler/installation) @@ -25,7 +30,7 @@ The **Tool Suite** adds advanced editor modules. Licensing and downloads are han ### Tilemap Editor (module 1) -Coming soon - visual editor for multi-layer tilemaps, tilesets, animations, attributes, and **C++ export** aligned with the engine. +Available - visual editor for multi-layer tilemaps, tilesets, animations, attributes, and **C++ export** aligned with the engine. Ships as a native desktop app (C++17 / SDL2 / ImGui) inside the Tool Suite. - [Overview](/tools/tilemap-editor/overview) - [Quick start](/tools/tilemap-editor/quick-start) @@ -36,7 +41,11 @@ Coming soon - visual editor for multi-layer tilemaps, tilesets, animations, attr ### Music Editor (module 2) -Upcoming - tracker-style music authoring for PixelRoot32. +Upcoming - pattern-based tracker with multi-channel support for PixelRoot32 APU (planned). + +### SFX Editor (module 3) + +Upcoming - sound effect synthesis editor for the PR32 APU SFX pipeline (planned). --- @@ -45,7 +54,8 @@ Upcoming - tracker-style music authoring for PixelRoot32. | Tool | Type | Status | |------|------|--------| | Sprite Compiler | Free / standalone | Available | -| Tilemap Editor | Premium (suite) | Coming soon | +| Tilemap Editor | Premium (suite) | Available | | Music Editor | Premium (suite) | Upcoming | +| SFX Editor | Premium (suite) | Upcoming | -**Engine docs:** [Graphics Techniques](../guide/graphics-techniques.md) · [Rendering](../guide/rendering.md) · [Tile animation (architecture)](../architecture/tile-animation.md) +**Engine docs:** [Graphics Techniques](../guide/graphics-techniques) · [Rendering](../guide/rendering) · [Tile animation (architecture)](../architecture/tile-animation) diff --git a/tools/sprite-compiler/advanced-features.md b/tools/sprite-compiler/advanced-features.md index c9eadb1..3588c7e 100644 --- a/tools/sprite-compiler/advanced-features.md +++ b/tools/sprite-compiler/advanced-features.md @@ -1,6 +1,6 @@ # Sprite Compiler Advanced Features -Advanced behaviour of the PixelRoot32 Sprite Compiler: palettes, prefixes, and export modes. +Advanced behaviour of the PixelRoot32 Sprite Compiler: palettes, prefixes, and export modes. These apply to both the Tool Suite module and the standalone CLI — only the invocation differs. ## Automatic palette detection @@ -22,7 +22,7 @@ The engine exposes five built-in palette types (see [Color (API)](/api/graphics/ 2. **Match**: If every color fits a built-in palette, the tool may **omit** a custom RGB mapping array and assume you use `Color::setPalette` / engine palettes at runtime. 3. **Custom colors**: If any color is outside those sets, the header can include a `{PREFIX}_PALETTE_MAPPING[16]` (or similar) for your indices. -Exact behaviour depends on the tool version — use `python main.py --help` on your checkout. +Exact behaviour depends on the tool version — use `python main.py --help` on your checkout (standalone CLI), or check the tooltip / Log panel in the Tool Suite module. ## Naming with prefixes diff --git a/tools/sprite-compiler/installation.md b/tools/sprite-compiler/installation.md index 7487b05..4c47665 100644 --- a/tools/sprite-compiler/installation.md +++ b/tools/sprite-compiler/installation.md @@ -1,47 +1,53 @@ # Sprite Compiler Installation -This guide walks you through installing the PixelRoot32 Sprite Compiler on your system. +This guide covers all installation paths for the PixelRoot32 Sprite Compiler. -## Prerequisites +## Method 1: Install the Tool Suite (recommended) -### Required software +The Sprite Compiler is integrated as a **native GUI module** inside the **PixelRoot32 Tool Suite**. -- **Python**: Version 3.8 or higher -- **pip**: Usually included with Python +1. **Download** the Tool Suite from [pixelroot32.com](https://pixelroot32.com) +2. **Install** the platform package (Windows installer, Linux AppImage, macOS bundle) +3. **Launch** the Tool Suite and click **"Sprite Compiler"** on the launcher -### Verify prerequisites +The module discovers the `pr32-sprite-compiler` CLI automatically: +- Looked for alongside the Tool Suite executable (bundled in the installer). +- Alternatively, available on your system `PATH`. -```bash -python --version -# Should show 3.8.0 or higher -``` +If the CLI is missing, the module prints an error to the console and exports will fail. Re-run the Tool Suite installer or add `pr32-sprite-compiler` ([releases](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Sprite-Sheet-Compiler/releases)) to your `PATH`. -```bash -pip --version -``` +## Method 2: Standalone CLI (Python source) -If Python is missing, install it from [python.org](https://www.python.org/). +> For CI scripts, build automation, or development environments without the Tool Suite. -## Installation methods +Run the tool from a clone of the repository; the CLI entry point is **`python main.py`**. -### Method 1: From source +### Prerequisites -Run the tool from a clone of the repository; the CLI entry point is **`python main.py`**. +- **Python**: Version 3.8 or higher +- **pip**: Usually included with Python -#### Step 1: Clone repository +```bash +python --version # Should show 3.8.0 or higher +pip --version +``` + +### Step 1: Clone repository ```bash git clone https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Sprite-Sheet-Compiler.git -cd PixelRoot32-Sprite-Compiler +cd PixelRoot32-Sprite-Sheet-Compiler ``` -#### Step 2: Install dependencies +### Step 2: Install dependencies ```bash -pip install -r requirements.txt +pip install -e . ``` -#### Step 3: Verify installation +The project uses `pyproject.toml` (single dependency: Pillow). There is no `requirements.txt`. + +### Step 3: Verify installation ```bash python main.py --help @@ -49,7 +55,7 @@ python main.py --help Work from this directory (or call `python` with the full path to `main.py`) when building sprites. -### Method 2: Pre-built binaries (no Python) +## Method 3: Pre-built native binary The **[Releases](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Sprite-Sheet-Compiler/releases)** page may ship standalone builds so you do **not** need to install Python. Exact file names change per release; pick the asset for your OS. @@ -65,11 +71,9 @@ The **[Releases](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Sprite-S - Often a **`.dmg`** or **`.app`**. If Gatekeeper blocks the app, allow it under **System Settings → Privacy & Security**. -> **Note:** If there is no binary for your platform yet, use **Method 1**. From the Python tree, the GUI is usually started with `python main.py` (see the repository README). +> **Note:** If there is no binary for your platform yet, use **Method 2** (Python source). -## Verification - -### Test conversion +## Verification (Standalone CLI) 1. Create a small **PNG** (e.g. 8×8 or 16×16). 2. Run (adjust `--grid` / `--sprite` to match): @@ -80,8 +84,6 @@ python main.py test.png --grid 8x8 --sprite 0,0,1,1 --out test_output.h 3. Confirm `test_output.h` exists and contains data arrays. -### Help - ```bash python main.py --help ``` @@ -89,13 +91,14 @@ python main.py --help ## Updating (source install) ```bash -cd PixelRoot32-Sprite-Compiler +cd PixelRoot32-Sprite-Sheet-Compiler git pull -pip install -r requirements.txt +pip install -e . ``` ## Uninstallation +- **Tool Suite**: uninstall the Tool Suite application (platform-specific). - **Source:** delete the clone (and any venv you used). - **Pre-built:** remove the downloaded installer / AppImage / app bundle. @@ -106,18 +109,22 @@ pip install -r requirements.txt - On Windows, try `py` instead of `python`. - Ensure Python is on `PATH`; restart the terminal. -**Import errors after `pip install`** +**Import errors after install** -- Use `python -m pip install -r requirements.txt` with the same interpreter you use to run `main.py`. +- Use `pip install -e .` with the same interpreter you use to run `main.py`. **Cannot write output file** - Ensure the output directory exists and is writable. +**Tool Suite: `pr32-sprite-compiler` not found** + +- The CLI binary must be alongside the Tool Suite executable or on `PATH`. Download from the [releases](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Sprite-Sheet-Compiler/releases) page. + ### Getting help -- [Usage guide](/tools/sprite-compiler/usage-guide) — CLI patterns (`python main.py …`). -- Open an issue on the [Sprite Compiler](ttps://github.com/PixelRoot32-Game-Engine/PixelRoot32-Sprite-Sheet-Compiler/PixelRoot32-Sprite-Compiler) repository if something fails. +- [Usage guide](/tools/sprite-compiler/usage-guide) +- Open an issue on the [Sprite Compiler](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Sprite-Sheet-Compiler) repository if something fails. ## Next steps diff --git a/tools/sprite-compiler/overview.md b/tools/sprite-compiler/overview.md index c26ca75..7a06145 100644 --- a/tools/sprite-compiler/overview.md +++ b/tools/sprite-compiler/overview.md @@ -1,6 +1,13 @@ # Sprite Compiler Overview -The **Sprite Compiler** is a tool that converts PNG images into PixelRoot32 sprite data formats. It provides both a graphical interface (GUI) and a command-line interface (CLI) to automate the process of creating sprite arrays from image files. +The **Sprite Compiler** converts PNG images into PixelRoot32 sprite data arrays. It is available in two modes: + +| Mode | Interface | Best for | +|------|-----------|----------| +| **Tool Suite module** | Native ImGui GUI (3-panel: Settings / Preview / Log) | Interactive editing, project management, visual preview | +| **Standalone CLI** | `python main.py` from the open-source repo | CI scripts, batch processing, build automation | + +Both modes produce identical C header output. The Tool Suite module delegates the actual compilation to the `pr32-sprite-compiler` CLI binary (bundled with the Tool Suite installation or available on `PATH`). The standalone CLI runs directly from a Python checkout — no Tool Suite required. ## What It Does @@ -19,29 +26,33 @@ The Sprite Compiler takes bitmap images (PNG) and converts them into C header fi - **2bpp (4 colors)**: Packed format, 2 bits per pixel. - **4bpp (16 colors)**: Packed format, 4 bits per pixel. -### GUI & CLI +### Tool Suite GUI + +The Tool Suite module provides a 3-panel docked interface: + +1. **Settings** (left): Input image, Tile Size grid, Sprite Selection, Export mode/prefix/output +2. **Preview** (center): Real-time visual preview of the selected sprite +3. **Log** (bottom): Colour-coded log entries (Info / Warning / Error / Success) -- **Modern GUI**: Step-by-step card-based interface for easy configuration. -- **Powerful CLI**: Suited to build scripts and automation via `python main.py`. +The module manages `.pr32sprite` project files so you can save and resume work. Export invokes the external `pr32-sprite-compiler` CLI automatically — it must be available alongside the Tool Suite or on `PATH`. -### Sprite sheets +### Standalone CLI -Example: two cells from a sheet using `--grid` and repeated `--sprite`: +The open-source Python repo (`PixelRoot32-Sprite-Sheet-Compiler`) provides the CLI entry `python main.py`. Example: two cells from a sheet using `--grid` and repeated `--sprite`: ```bash python main.py sheet.png --grid 16x16 --sprite 0,0,1,1 --sprite 1,0,1,1 --out output.h ``` -## GUI Interface +## GUI Interface (Tool Suite) -The GUI follows a linear flow: +The Tool Suite module follows a step-by-step flow: 1. **Input Image**: Select your PNG source. 2. **Grid Settings**: Define the cell size and offsets. 3. **Sprite Selection**: Pick which cells to export. 4. **Export Settings**: Choose the mode (Layered, 2bpp, 4bpp), set a **Prefix**, and choose the output path. -5. **About**: Version info and credits (via the `?` button). -6. **Log**: Technical feedback and performance alerts. +5. **Log**: Technical feedback and status messages. ## Input Requirements @@ -54,6 +65,8 @@ The GUI follows a linear flow: ### Image constraints +> The **16-pixel width cap applies only to 1bpp** sprites — it is a 1bpp row-format constraint of the engine's `Sprite`/`MultiSprite` renderer. `Sprite2bpp`/`Sprite4bpp` use a `uint8_t` width field with no 16-pixel limit. + **For 1bpp sprites:** - Maximum width: 16 pixels @@ -62,12 +75,12 @@ The GUI follows a linear flow: **For 2bpp sprites:** -- Maximum width: 16 pixels +- Width: any (no fixed cap) - Colors: Up to 4 colors **For 4bpp sprites:** -- Maximum width: 16 pixels +- Width: any (no fixed cap) - Colors: Up to 16 colors ## Output Format @@ -90,9 +103,9 @@ static const uint16_t PLAYER_SPRITE_0_4BPP[] = { }; ``` -## Use Cases +## Use Cases (Standalone CLI) -All examples assume you are in the Sprite Compiler repository directory (or invoke `main.py` with a full path). The CLI is **`python main.py`**. +All examples below use the **standalone CLI** (`python main.py` from the open-source repo `PixelRoot32-Sprite-Sheet-Compiler`). For the Tool Suite module, open the Sprite Compiler from the Tool Suite launcher and use the 3-panel GUI instead. ### 1. Single sprite conversion @@ -135,13 +148,13 @@ for f in assets/sprites/*.png; do done ``` -## Workflow integration +## Workflow integration (Standalone CLI) ### Typical development workflow 1. **Create sprites** in your image editor (Aseprite, Piskel, GIMP, etc.) 2. **Save as PNG** with appropriate dimensions -3. **Run** `python main.py …` to generate header files +3. **Run** `python main.py …` (standalone CLI) or use the Tool Suite module GUI 4. **Include headers** in your PixelRoot32 project 5. **Use sprites** in your game code @@ -170,7 +183,7 @@ platformio run ## Limitations -- **Width limit**: 16 pixels wide for these sprite modes (engine / hardware constraint). +- **Width limit**: 16 pixels max for 1bpp sprites (row-format constraint; 2bpp/4bpp have no fixed cap). - **Color depth**: Limited by format (1bpp = 2 colors, 2bpp = 4, 4bpp = 16). - **File format**: Primarily PNG (convert other formats first). diff --git a/tools/sprite-compiler/usage-guide.md b/tools/sprite-compiler/usage-guide.md index a740316..9b823ec 100644 --- a/tools/sprite-compiler/usage-guide.md +++ b/tools/sprite-compiler/usage-guide.md @@ -1,24 +1,50 @@ # Sprite Compiler Usage Guide -Complete guide to using the PixelRoot32 Sprite Compiler for converting images to sprite data. +Complete guide to using the PixelRoot32 Sprite Compiler. The compiler is available in two modes: -> **Note:** The compiler is used as **`python main.py`** from a [source install](/tools/sprite-compiler/installation) of the repository. There is **no** official Node/npm global package; ignore any older docs that referenced `npm install -g pr32-sprite-compiler`. +- **Tool Suite module** — native ImGui GUI inside the Tool Suite application. +- **Standalone CLI** — `python main.py` from the open-source repo (see [installation](/tools/sprite-compiler/installation)). -## Basic Usage +Both produce identical C headers. The Tool Suite module delegates compilation to the `pr32-sprite-compiler` binary (bundled or on `PATH`). The standalone CLI runs directly from Python — ideal for CI and build automation. -### Launching the GUI +> **Note:** There is **no** official Node/npm global package; ignore any older docs that referenced `npm install -g pr32-sprite-compiler`. -The easiest way to use the compiler is via the Graphical User Interface (GUI). +## GUI Usage (Tool Suite) -```bash -python main.py -``` +### Opening the module + +1. Launch the **PixelRoot32 Tool Suite** +2. Click **"Sprite Compiler"** on the launcher card + +The module opens a 3-panel docked window: + +- **Settings** (left) — Input image, Tile Settings (grid W×H, offset), Sprite Selection, Export (mode, prefix, output path) +- **Preview** (center) — Real-time visual preview of the selected sprite +- **Log** (bottom) — Colour-coded output (Info / Warning / Error / Success) + +### Module workflow -This will open the application where you can interactively load images, configure the grid, and export sprites. +1. **Open or create a project** (File menu: Ctrl+N / Ctrl+O) +2. **Select an input image** — browse or type the PNG path in the Settings panel +3. **Configure grid** — set tile Width × Height, offset, and limit +4. **Select sprites** — auto-detect or manually add regions +5. **Export** — choose mode (Layered / 2bpp / 4bpp), prefix, output file, and click **"Export Sprites"** -### Command Line Interface (CLI) +Projects are saved as `.pr32sprite` files so you can resume work later. The module owns its **File** menu (a toolbar popup): New, Open, Save, Save As, Close. -For automation, you can use the CLI mode by passing arguments to the script. +### Keyboard shortcuts + +| Shortcut | Action | +|----------|--------| +| `Ctrl+N` | New project | +| `Ctrl+O` | Open project | +| `Ctrl+S` | Save project | +| `Ctrl+Shift+S` | Save project as | +| `Ctrl+W` | Close project | + +## Standalone CLI + +For automation, build scripts, and CI environments. Install via [Python source](/tools/sprite-compiler/installation#method-2-standalone-cli-python-source). ```bash python main.py [input] [options] @@ -37,7 +63,7 @@ python main.py [input] [options] - `--offset X,Y`: Initial offset in pixels (default: `0,0`) - `--mode MODE`: Export mode (`layered`, `2bpp`, `4bpp`) -## CLI Examples +## CLI Examples (Standalone) ### Simple Conversion @@ -156,11 +182,13 @@ Add `--sprite` lines for `y = 1…3` for the remaining rows (or pick cells in th ```cpp #include "characters.h" -// Sprites named CHARACTER_0, CHARACTER_1, etc. -renderer.drawSprite(CHARACTER_0, 50, 50, Color::White); -renderer.drawSprite(CHARACTER_1, 70, 50, Color::White); +// Sprites named {PREFIX}_SPRITE_{N}_LAYER_{layer}, e.g. CHARACTER_SPRITE_0_LAYER_0 +renderer.drawSprite(CHARACTER_SPRITE_0_LAYER_0, 50, 50, Color::White); +renderer.drawSprite(CHARACTER_SPRITE_1_LAYER_0, 70, 50, Color::White); ``` +> With `--mode layered`, each sprite emits one array per color layer (`..._SPRITE_N_LAYER_{i}`). Packed modes emit `..._SPRITE_N_2BPP` / `..._SPRITE_N_4BPP`. + ## Batch Processing ### Process Multiple Files @@ -220,7 +248,7 @@ python main.py --help and match your CLI to that output. Do **not** assume a globally installed `pr32-sprite-compiler` from npm. -## Integration with Build Systems +## Build-system Automation (Standalone CLI) ### PlatformIO @@ -297,35 +325,7 @@ foreach(SPRITE ${SPRITE_FILES}) endforeach() ``` -## GUI Usage (If Available) - -### Opening GUI - -From the compiler repository (see upstream README): - -```bash -python main.py -``` - -Or launch a packaged GUI executable from **Releases**, if provided for your OS. - -### GUI Workflow - -1. **Drag and drop** images into the window -2. **Preview** sprite data in real-time -3. **Adjust settings** visually (format, threshold, etc.) -4. **Export** to header files -5. **Batch process** multiple files - -### GUI Features - -- Visual preview of sprite conversion -- Real-time threshold adjustment -- Palette selection -- Batch processing interface -- Export options - -## Best Practices +## Build Integration (Standalone CLI) ### Image Preparation @@ -391,7 +391,13 @@ project/ - Check file is not corrupted - Try re-saving image in image editor -### Getting Help +**Tool Suite: Export fails silently or warns about missing CLI** + +- The `pr32-sprite-compiler` binary must be available alongside the Tool Suite executable or on `PATH`. +- Re-run the Tool Suite installer, or download the binary from the [releases](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Sprite-Sheet-Compiler/releases) page and place it next to the Tool Suite. +- Check the Log panel at the bottom of the Sprite Compiler module for the exact error message. + +### Getting Help (Standalone CLI) ```bash python main.py --help diff --git a/tools/tilemap-editor/advanced-guide.md b/tools/tilemap-editor/advanced-guide.md index 95d3a4a..26db7d4 100644 --- a/tools/tilemap-editor/advanced-guide.md +++ b/tools/tilemap-editor/advanced-guide.md @@ -1,3 +1,8 @@ +--- +title: "Advanced Guide" +description: "Tile animations, license, multi-palette export, tile attributes, flag rules, and project optimization" +--- + # Tilemap Editor - Advanced Guide **Level**: ⭐⭐ Intermediate | ⭐⭐⭐ Advanced @@ -8,7 +13,6 @@ > > - [Tile Animations](#tile-animations) > - [License System](#license-system) -> - [Memory & Lazy Loading](#memory--lazy-loading) > - [Multi-Palette Export](#multi-palette-export) > - [Tile Attributes](#tile-attributes) > - [Tile Flag Rules](#tile-flag-rules) @@ -31,7 +35,7 @@ ### ⭐⭐ Animation Panel -**Access**: **View → Animation Panel** or click animation icon +**Access**: The **Animations** panel is always docked at the bottom of the editor window (part of the default layout). No menu toggles it. **Components**: @@ -44,8 +48,8 @@ **Step 1**: New animation -1. Click **Add** in Animation Panel -2. "New Animation" appears in list +1. Click **Add** in the Animations panel +2. "Animation N" appears in the list 3. Select to configure **Step 2**: Configure properties @@ -53,9 +57,9 @@ | Property | Description | Recommended | |----------|--------------|-------------| | **Name** | Descriptive name | "Water", "Fire" | -| **Base Tile** | First tile index | - | +| **Base Tile** | First tile index (assigned via Animation tool, see Step 3) | - | | **Frame Count** | Number of frames | 2-8 | -| **Frame Duration** | Speed in engine ticks | 8-16 | +| **Frame Duration** | Speed in engine cycles | 8-16 | **Example**: Water with 4 frames @@ -67,44 +71,32 @@ Frame Duration: 8 ticks **Step 3**: Assign tiles -**Method 1** - Animation Eyedropper: - -1. Select **Animation Eyedropper** (**I**) -2. Click tiles on canvas -3. Auto-linked - -**Method 2** - Manual: - -1. Select animation -2. Enter base tile -3. Click **Apply** +Select the **Animation** tool from the toolbar, then click the tile on the canvas that should be the animation's base tile. The clicked tile becomes the base tile of the currently selected animation. ### ⭐⭐⭐ Visual Indicators -- Animated tiles show ▶ icon -- Icon color indicates status +- Animated tiles show ▶ icon on the canvas +- Indicators visible only on the active layer - Hover for details ### ⭐⭐⭐ Live Preview **Toggle**: -1. Click **Live Preview** button -2. Or press **L** -3. Animations play in real-time +1. Click the **▶ Live Preview** button in the toolbar +2. Animations play in real-time on the canvas **Features**: -- **Synchronized**: Same timer as ESP32 +- **Synchronized**: Same timer as the engine - **Optimized**: Only renders visible - **Frame Accurate**: Exact game frames - **Multi-layer**: Works across layers **Controls**: -- **Play/Pause**: Toggle playback -- **Speed Control**: 1×, 2×, 0.5× -- **Frame Step**: Debug frame by frame +- **Play / Pause / Stop**: Toggle playback +- Enabled at zoom levels above the Live Preview threshold ### ⭐⭐⭐ Validation @@ -113,46 +105,42 @@ The editor auto-validates: **Checks**: - **Tile Bounds**: base_tile + frame_count ≤ tileset -- **Overlap Detection**: No overlapping ranges -- **Memory Constraints**: ESP32 limits (64 animations, 256 frames) -- **Frame Duration**: Valid values (1-255 ticks) +- **Frame Duration**: Valid values (1-255) +- **Memory Constraints**: ESP32 limits (64 animations, 256 frames per scene) -**Error Messages**: - -- "Animation exceeds tileset bounds" -- "Animations overlap" -- "Too many animations" +> Animations are capped at 64 per scene; attempting to add more silently stops adding new ones. ### ⭐⭐⭐ Export to C++ -Animations auto-export with C++ export: +Animations auto-export with C++ export — embedded in the scene header alongside the layer definitions (no separate animation file): ```cpp -// scene_name_animations.h -extern const pixelroot32::graphics::TileAnimation scene_name_animations[]; -constexpr size_t SCENE_NAME_ANIMATION_COUNT = 2; - -// scene_name_animations.cpp -static const pixelroot32::graphics::TileAnimation scene_name_animations[] = { +// scene_name.h (excerpt) +static const pixelroot32::graphics::TileAnimation FOREGROUND_TILE_ANIMATIONS[] = { { 16, 4, 8, 0 }, // Water - { 32, 2, 12, 0 } // Fire + { 32, 2, 12, 0 }, // Fire }; +static const uint8_t FOREGROUND_TILE_ANIMATION_COUNT = 2; ``` +The initializer order is: `{ baseTile, frameCount, frameDuration, 0 }` (the trailing `0` is a reserved flag field). + **Engine Integration**: ```cpp -#include "level1_animations.h" +#include "level1.h" void game_loop() { level1::init(); while (game_running) { - level1::get_animation_manager().step(); + level1::getForegroundAnimManager().step(); render_tilemap(); } } ``` +> Each animated layer gets a `AnimManager()` accessor. A legacy alias `getAnimManager()` maps to the Details layer when present. + ### ⭐⭐⭐ ESP32 Limits | Limit | Value | @@ -166,50 +154,31 @@ void game_loop() { ## License System +> ⚠️ **Full documentation**: See **[License & Activation](/tools/tilemap-editor/license-and-activation)** for the complete licensing model (key format, fingerprint binding, storage, troubleshooting). + ### 🔒 Export License C++ export **requires a valid license**. Without: -- Export button shows 🔒 -- Upgrade dialog appears +- The **Upgrade Required** dialog appears when attempting to export ("This feature requires an active license") - Other features work normally -### ⭐⭐⭐ Verify License +### ⭐⭐ Verify License -**File → License Status** shows: +**Help → License Info** (or the launcher footer **License Info** button) shows: -- License status (active/expired) -- Expiration date -- Available features +- License status (active / not active) +- Masked key (e.g. `PR32-3X-1-****-XXXXXXXX`) +- Product version +- Activation date -### ⭐⭐⭐ Activate License +### ⭐⭐ Activate License -1. **File → Activate License** +1. **Help → License Info** or the trial dialog on first launch 2. Enter license key -3. Click **Activate** +3. Click **Activate License** ---- - -## Memory & Lazy Loading - -### 💾 Lazy Loading - -Editor implements **lazy loading**: - -- Inactive scenes stay unloaded -- Load on demand when switching -- Configurable in preferences - -### ⭐⭐⭐ Memory Optimization - -**For large projects**: - -1. **Use binary format**: `.pr32scene.bin` (up to 335× smaller) -2. **Enable History Compression**: In preferences -3. **Close unused scenes**: Free memory -4. **Limit preload**: Reduce RAM usage - -**Check**: **File → Project Statistics** shows estimated memory. +The key is validated against an Ed25519 v3 signature and bound to your machine fingerprint. See the [full license documentation](/tools/tilemap-editor/license-and-activation) for details on fingerprint tolerance and key rotation. --- @@ -291,7 +260,7 @@ Editor implements **lazy loading**: 4. Add/edit/remove 5. Click **Save** -**Visual**: Orange triangle on tiles with instance attributes. +**Visual**: Green triangle indicator on tiles with instance attributes. > ⚠️ Indicators only visible on active layer. @@ -366,12 +335,12 @@ trigger = true/false Rules resolve in order: 1. **Project rules** (`project_dir/tile_flag_rules.json`) -2. **Editor defaults** (`modules/tilemap_editor/assets/tile_flag_rules.json`) +2. **Editor defaults** (`assets/tilemap/tile_flag_rules.json`) 3. **Legacy fallback** (hardcoded) ### ⭐⭐⭐ Managing Project Rules -**Access**: **File → Project Settings** → "Tile Flag Rules" +**Access**: Click the **Settings** (gear) button in the toolbar → "Tile Flag Rules" section **Indicator**: @@ -384,19 +353,19 @@ Rules resolve in order: 1. Click **Create Project Rules** 2. Template created -3. Status: "✓ Created template rules file" +3. Status: "Created tile_flag_rules.json" **Reset**: 1. Click **Reset to Defaults** 2. Confirm -3. Status: "✓ Reset to editor defaults" +3. Status: "Reset to editor default rules" ### ⭐⭐⭐⭐ Available Flags | Flag | Function | |------|----------| -| `TILE_NONE` | No flag | +| `TILE_NONE` | Default / no flag (0) | | `TILE_SOLID` | Collision | | `TILE_SENSOR` | Trigger without blocking | | `TILE_DAMAGE` | Hurts player | @@ -435,7 +404,6 @@ if (type && strcmp(type, "door") == 0) { 1. **Binary format** (`.bin`) for >1MB projects 2. **History Compression** in preferences 3. **Close unused scenes** -4. **Limit preload** **Export size**: @@ -443,14 +411,7 @@ if (type && strcmp(type, "door") == 0) { 2. **Remove duplicate tiles** 3. **Use appropriate BPP** (1/2/4) -### ⭐⭐⭐ Statistics - -**File → Project Statistics**: - -- Unique tiles used -- Layers and scenes -- Estimated memory -- Animation limits +> There is no separate "Project Statistics" dialog. The export status output reports tile counts and estimated size. --- diff --git a/tools/tilemap-editor/installation.md b/tools/tilemap-editor/installation.md index 2608fcc..f34f029 100644 --- a/tools/tilemap-editor/installation.md +++ b/tools/tilemap-editor/installation.md @@ -1,11 +1,32 @@ # Tilemap Editor Installation -The **PixelRoot32 Tilemap Editor** can be run from **pre-built** downloads (see [Releases](https://github.com/PixelRoot32-Game-Engine/PixelRoot32-Tool-Suite-Releases/releases) on the editor repository). +The **PixelRoot32 Tilemap Editor** is distributed as a native desktop application inside the **Tool Suite**. + +## Install the Tool Suite + +1. **Download** the platform package from [pixelroot32.com](https://pixelroot32.com) +2. **Install** — Windows installer (`.exe`), Linux AppImage, or macOS bundle +3. **Launch** the Tool Suite and click **"Tilemap Editor"** on the launcher + +System requirements: any modern desktop OS (Windows 10+, Linux, macOS 11+) with an OpenGL 3.3-capable GPU. + +## File associations (Windows) + +The Windows installer optionally registers file associations so you can double-click project files to open them in the editor: + +| Extension | Opens in | +|-----------|----------| +| `.pr32scene.bin` | Tilemap Editor | +| `.pr32sprite` / `.pr32sprite.bin` | Sprite Compiler module | + +On Linux and macOS, open files via **File → Open** inside the Tool Suite or drag and drop onto the launcher window. ::: tip Premium module This editor is part of the **Tool Suite**. Use the official site for licenses and support: [pixelroot32.com](https://pixelroot32.com). +- See **[License & Activation](/tools/tilemap-editor/license-and-activation)** for details on the licensing model. + ::: ## Next steps diff --git a/tools/tilemap-editor/license-and-activation.md b/tools/tilemap-editor/license-and-activation.md new file mode 100644 index 0000000..6359161 --- /dev/null +++ b/tools/tilemap-editor/license-and-activation.md @@ -0,0 +1,192 @@ +# Tilemap Editor — License & Activation + +**Level**: ⭐⭐ Intermediate + +--- + +> **Quick Index** +> - [What the license unlocks](#what-the-license-unlocks) +> - [Activation](#activation) +> - [License key format](#license-key-format) +> - [Machine binding (fingerprint)](#machine-binding-fingerprint) +> - [License storage](#license-storage) +> - [Deactivation](#deactivation) +> - [Troubleshooting](#troubleshooting) + +--- + +## What the license unlocks + +**C++ export is the only feature gated behind a valid license.** Tilemap editing, saving, painting, and all other editor functions work without a license. + +| Feature | Without license | With license | +|---------|:---:|:---:| +| Create / edit tilemaps | ✅ | ✅ | +| Import tilesets | ✅ | ✅ | +| Save projects | ✅ | ✅ | +| Animations, attributes, layers | ✅ | ✅ | +| **C++ export** | 🔒 | ✅ | + +Attempting to export without a license shows an **"Upgrade Required"** dialog with two options: enter a license key, or continue without exporting. + +--- + +## Activation + +### Trial / activation dialog + +On first launch, the Tool Suite shows a **"License Activation"** modal: + +- **Enter a license key** and click **Activate License**. +- A **5-second countdown** gates the **Later** button — you must see the purchase link before dismissing. +- The **Activate** button is always available; only dismissal is restricted. + +You can also access activation via: + +- **License Info** button in the Tool Suite launcher footer +- The **"Enter License Key"** button on the "Upgrade Required" dialog + +> **Note:** Inside the Tilemap Editor, the module owns its own toolbar, so the global app `Help → License Info` menu item is not reachable. Use the launcher footer button instead. + +### License Info dialog + +Opened from the launcher footer: displays the current license status, masked key, product version, and activation date. A **Deactivate** button clears the license from this machine. + +--- + +## License key format + +``` +PR32-3X-{keyid}-{payload_base64url}-{signature_base64url} +``` + +| Segment | Description | +|---------|-------------| +| `PR32-3X-` | Fixed prefix — identifies v3 license keys | +| `keyid` | Integer identifying which signing key was used (currently: `1`) | +| `payload` | Base64url-encoded JSON payload (no padding) | +| `signature` | Ed25519 signature over the raw payload bytes (86 base64url chars) | + +### Validation pipeline + +1. **Format check** — regex validates the key structure +2. **Key lookup** — the keyid maps to an embedded Ed25519 public key +3. **Signature verification** — Ed25519 PureEdDSA over raw payload bytes +4. **Payload checks** — JSON payload must contain valid `v` (schema), `p` (product code `PR32TS`), and `ver` (product version) +5. **Version compatibility** — license `ver` major must match the running app version + +> **Your public key is embedded in the app.** The private key that signs licenses never ships in any binary. Extracting the public key does not allow forging licenses. + +### Masked display + +In the License Info dialog and status bar, the key is shown partially masked: + +``` +PR32-3X-1-****-XXXXXXXX +``` + +Only the last 8 characters of the signature are visible — enough to match the key against your purchase email. + +--- + +## Machine binding (fingerprint) + +Licenses are bound to your machine to prevent casual sharing (not DRM — a courtesy measure). + +### How the fingerprint is generated + +``` +SHA-256(hostname | OS | OS_major_version | architecture) +→ truncated to 16 hexadecimal characters +``` + +Example components: `DESKTOP-ABC | Windows | 10 | AMD64` → `a1b2c3d4e5f6a7b8` + +### Change tolerance + +| Rule | Behaviour | +|------|-----------| +| **Same machine** | Fingerprint matches → license valid | +| **One change** | E.g. OS upgrade, hostname rename → one-time tolerance, license stays valid for this session | +| **Two or more changes** | Crosses `MAX_CHANGES` threshold → license invalid, **re-activation required** | + +Changes that trigger a fingerprint mismatch: OS version major change, hostname change, architecture change (e.g. migration to a new CPU). + +> **Note:** The change counter is tracked in memory for the current session only — it resets every launch, and a tolerated mismatch does not rewrite the stored fingerprint. The stored fingerprint is replaced only when you re-activate the license. Re-activation does NOT consume a new license seat. + +--- + +## License storage + +### On-disk file + +``` +~/.pixelroot32/license.enc +``` + +**Format:** `ENC:` + Base64( `IV[16 bytes]` + AES-256-CBC ciphertext ) + +The ciphertext contains a JSON object with the license key, product version, activation timestamp, system fingerprint, and a SHA-256 checksum. + +### Encryption key + +Derived from machine-specific data: `SHA-256(MAC address | hostname | OS | architecture)`. This is NOT a secret — it is an anti-tamper measure, not DRM. + +On **Linux**, the key is optionally cached in the desktop Secret Service (libsecret) when available, avoiding repeated derivation. + +### Tamper detection + +The stored JSON includes a SHA-256 checksum over the license fields. Any manual modification of the file invalidates the checksum and the license is rejected. The app re-validates the file on every launch. + +--- + +## Deactivation + +1. Open **Help → License Info** (or the launcher footer **License Info** button) +2. Click **Deactivate License** +3. The `license.enc` file is removed from disk + +After deactivation, the Tool Suite returns to the trial state (only C++ export is gated). You can reactivate with the same key on the same machine, or transfer the license to a different machine. + +--- + +## Troubleshooting + +### "Invalid license key format" + +- The key must be pasted exactly as received — no extra spaces, line breaks, or quote characters. +- Verify the key starts with `PR32-3X-` and contains four segments separated by `-`. + +### "License verification failed" + +- The key may be corrupted or was edited. Request a reissue from [pixelroot32.com](https://pixelroot32.com). + +### "This license is for a different product" + +- The key was issued for a different PixelRoot32 product. Verify you purchased a **Tool Suite** license. + +### "This license is for version X, but you have version Y" + +**Major version mismatch.** You have either: + +- Upgraded the Tool Suite past the license's covered version → **renew** your license. +- Downgraded the Tool Suite to a version older than the license was issued for → **update** the Tool Suite. + +The major version is the first number: `1.0` and `1.9` are compatible (both major `1`); `1.0` and `2.0` are NOT. + +### "Unknown license key id" + +The key's signing key is not recognized. This happens if the key was issued with a newer key pair that hasn't been embedded in your Tool Suite build yet. **Update** the Tool Suite to the latest version. + +### "Hardware changed" / fingerprint mismatch + +You changed your machine significantly (OS major upgrade, new hardware). The license tolerates **one** such change. If you've already exceeded the limit, simply **reactivate with your existing key**: the old fingerprint is replaced and the counter resets. + +--- + +## See also + +- [Quick Start](/tools/tilemap-editor/quick-start) — includes export flow +- [Advanced Guide](/tools/tilemap-editor/advanced-guide) — license system in the export pipeline +- [Technical Reference](/tools/tilemap-editor/technical-reference) — C++ export format details +- [Tools overview](/tools/) diff --git a/tools/tilemap-editor/overview.md b/tools/tilemap-editor/overview.md index 710681d..41fa9da 100644 --- a/tools/tilemap-editor/overview.md +++ b/tools/tilemap-editor/overview.md @@ -18,7 +18,7 @@ The Tilemap Editor is part of the **Tool Suite**. Licensing and downloads: [pixe ## What it does - **Paint** tiles on canvas with layers -- **Manage tilesets** from PNG/JPG/BMP imports +- **Manage tilesets** from PNG imports (JPG/BMP loadable via the file picker's "All Files" filter; PNG recommended) - **Multiple scenes** in one project with shared tilesets - **Onion skinning** — overlay scenes for alignment - **Layers** — up to **8 layers** per scene, **palette slots P0-P7** for multi-palette @@ -30,7 +30,7 @@ The Tilemap Editor is part of the **Tool Suite**. Licensing and downloads: [pixe | Area | Highlights | |------|------------| -| Tools | Brush, eraser, rectangle, pipette, attribute, animation eyedropper, live preview | +| Tools | Brush, eraser, rectangle, pipette, attribute, animation, live preview | | Scenes | Multiple maps, onion skin, per-scene size | | Layers | Up to 8, visibility, reorder, palette slot per layer | | Tilesets | Multi-tileset, zoom, auto tile size | @@ -49,10 +49,11 @@ The documentation is organized in **4 guide levels**: ## Data Formats -### Project (`.pr32scene` / `.pr32scene.bin`) +### Project (`.pr32scene.bin`) -- **JSON** — human-readable, git-friendly -- **Binary** — up to 335× smaller, 10× faster +- **Single binary format** (v6) — compact and fast to load +- The **"Use Binary Format"** preference only changes the saved extension (`.pr32scene.bin` vs `.pr32scene`); the content is always binary +- No human-readable JSON project writer ### Exported C++ @@ -63,13 +64,21 @@ The documentation is organized in **4 guide levels**: ## Getting started 1. **New project** — tile size, map dimensions, target resolution -2. **Import tilesets** — use menu or drag into panel +2. **Import tilesets** — use the TILESET panel 3. **Add layers** — background, collision, detail, etc. 4. **Paint** on the canvas 5. **Export to C++** — link generated files to engine For detailed walkthrough, see the [Quick Start Guide](/tools/tilemap-editor/quick-start). +## Known limitations & Roadmap + +- **i18n**: The `language` setting in `~/.pixelroot32/settings.json` is reserved but not yet active. The UI is currently English-only. +- **Theme toggle**: Dark and Classic themes are available but switching requires editing `settings.json` directly (`"theme": "classic"` or `"dark"`). A UI toggle is planned. +- **Dock layout reset**: When a new layout schema version ships, the first launch after upgrade resets your panel arrangement silently. Make a note of repositioning in future release notes. +- **Auto-update**: The app checks for updates at startup only when a valid license is active. Manual check via **"Check for Updates"** in the launcher footer works without a license. **Skip-this-version** is not persisted between sessions. +- **Music Editor**: Planned pattern-based tracker with multi-channel support for the PixelRoot32 APU (upcoming — not yet available in the Tool Suite). + ## Next steps - [Installation](/tools/tilemap-editor/installation) diff --git a/tools/tilemap-editor/quick-start.md b/tools/tilemap-editor/quick-start.md index 98d0b55..f1ed4c4 100644 --- a/tools/tilemap-editor/quick-start.md +++ b/tools/tilemap-editor/quick-start.md @@ -1,3 +1,8 @@ +--- +title: "Quick Start" +description: "Create your first PixelRoot32 tilemap in 5 minutes - step-by-step guide" +--- + # Tilemap Editor - Quick Start Guide **Time**: 5 minutes | **Level**: ⭐ Beginner @@ -5,11 +10,11 @@ --- > **Quick Index** -> - [Step 1: Open Editor](#-step-1-open-the-editor-30-seconds) -> - [Step 2: Create Project](#-step-2-create-project-30-seconds) -> - [Step 3: Import Tileset](#-step-3-import-tileset-1-minute) -> - [Step 4: Paint](#-step-4-paint-your-first-map-2-minutes) -> - [Step 5: Save/Export](#-step-5-save-and-export-1-minute) +> - [Step 1: Open Editor](#⏱️-step-1-open-the-editor-30-seconds) +> - [Step 2: Create Project](#⏱️-step-2-create-project-30-seconds) +> - [Step 3: Import Tileset](#⏱️-step-3-import-tileset-1-minute) +> - [Step 4: Paint](#⏱️-step-4-paint-your-first-map-2-minutes) +> - [Step 5: Save/Export](#⏱️-step-5-save-and-export-1-minute) > - [Keyboard Shortcuts](#keyboard-shortcuts) --- @@ -21,26 +26,26 @@ 1. Launch **PixelRoot32 Tool Suite** from your applications menu 2. Click **Launch** on the **Tilemap Editor** card -When starting without a project, you see the **Welcome Screen** with: -- **Create New Project**: Create a new project from scratch -- **Open Existing Project**: Open `.pr32scene` or `.pr32scene.bin` +When starting without a project, you see the toolbar with: +- **File → New Project** (`Ctrl+N`): Create a new project from scratch +- **File → Open** (`Ctrl+O`): Open `.pr32scene.bin` (or legacy `.pr32scene`) --- ### ⏱️ Step 2: Create Project (30 seconds) -1. Click **Create New Project** +1. Click **File → New Project** or press **Ctrl+N** 2. Configure parameters: -| Field | Default | -|-------|--------| -| **Name** | "New Scene" | -| **Tile Size** | 8 px | -| **Map Width** | 40 tiles | -| **Map Height** | 30 tiles | -| **Orientation** | Landscape | +| Field | Default | Notes | +|-------|---------|-------| +| **Name** | "New Scene" | Sanitized to lowercase alphanumeric + `_` | +| **Tile Size** | 8 px | Validated 1-32 against engine limits | +| **Map Width** | 40 tiles | Max 255 | +| **Map Height** | 30 tiles | Max 255 | +| **Orientation** | Landscape | Portrait also available | -3. Click **Create Project** +3. Click **Create** 4. Select an empty folder 💡 **Tip**: Use **"Fit Map to Hardware Limit"** to auto-fit to ESP32 screen (320×240). @@ -49,14 +54,9 @@ When starting without a project, you see the **Welcome Screen** with: ### ⏱️ Step 3: Import Tileset (1 minute) -**Method 1** - TILESET panel: -1. In **TILESET** panel (left sidebar), click **Import tileset** -2. Select PNG, JPG, or BMP image -3. Auto-copied to `assets/tilesets/` - -**Method 2** - File menu: -1. **File → Import Tileset** -2. Select image +1. In the **TILESET** panel, click **Import tileset** +2. Select a PNG, JPG, or BMP image +3. The image is auto-copied to `assets/tilesets/` 📝 **Recommended**: PNG, multiples of tile size, up to 16 colors for 4bpp. @@ -65,7 +65,7 @@ When starting without a project, you see the **Welcome Screen** with: ### ⏱️ Step 4: Paint Your First Map (2 minutes) 1. **Select Brush** - Press **B** or click Brush tool -2. **Pick a tile** - Click any tile in TILESET panel (cyan border) +2. **Pick a tile** - Click any tile in the TILESET panel (cyan border for selected tile) 3. **Paint** - Click on canvas to place, drag to paint continuously 4. **Undo** - Use **Ctrl+Z** if you make a mistake @@ -75,45 +75,78 @@ When starting without a project, you see the **Welcome Screen** with: |-----|------|-----| | **B** | Brush | Paint tiles | | **E** | Eraser | Erase tiles | -| **R** | Rectangle | Draw rectangles | -| **P** | Pipette | Copy tile from canvas | -| **A** | Attribute | Assign attributes | +| **R** | Rectangle | Draw filled rectangles | +| **G** | Pan | Pan the canvas view | +| **I** | Pipette | Pick a tile from the canvas | +| **A** | Attribute | Open tile attribute editor | +| **Space** | Pan (hold) | Temporarily pan while held | + +🛠️ **Additional tools** (via toolbar): Animation — assign tiles to animations from the panel. --- ### ⏱️ Step 5: Save and Export (1 minute) 1. **Save project**: **Ctrl+S** or **File → Save** -2. **Export to C++**: **Ctrl+E** or **File → Export to C++** +2. **Export to C++**: Click the **Export** button in the toolbar, or **File → Export** + +⚙️ **Export options**: Namespace, color depth (auto-detected), "Store in Flash (ESP32)" for PROGMEM, and Legacy format for compatibility without Flash attributes. 🔒 **Note**: C++ export requires a valid license. Without license: - Export button shows 🔒 - Upgrade dialog appears - Other features remain available +> See **[License & Activation](/tools/tilemap-editor/license-and-activation)** for details on activating your license. + --- ## Next Steps Once you've completed your first map: -1. **Add more layers** - Click **+** in LAYERS panel -2. **Create multiple scenes** - Click **+** in SCENE panel +1. **Add more layers** - Click **+** in the LAYERS panel (max 8 per scene) +2. **Create multiple scenes** - Click **+** in the SCENE panel 3. **Explore advanced features** - See [Advanced Guide](/tools/tilemap-editor/advanced-guide) --- ## Keyboard Shortcuts +### File | Shortcut | Action | |----------|--------| -| **Ctrl+Z** | Undo | -| **Ctrl+Y** | Redo | +| **Ctrl+N** | New project | +| **Ctrl+O** | Open project | | **Ctrl+S** | Save | -| **Ctrl+E** | Export C++ | -| **Space+Drag** | Pan view | -| **Ctrl+Wheel** | Zoom | -| **L** | Toggle animation | +| **Ctrl+Shift+S** | Save As | +| **Ctrl+W** | Close project | + +### Edit +| Shortcut | Action | +|----------|--------| +| **Ctrl+Z** | Undo | +| **Ctrl+Y** / **Ctrl+Shift+Z** | Redo | + +### Tools +| Key | Tool | +|-----|------| +| **B** | Brush | +| **E** | Eraser | +| **R** | Rectangle | +| **G** | Pan | +| **I** | Pipette | +| **A** | Attribute | +| **Space** | Pan (hold while pressed) | + +### View +| Shortcut | Action | +|----------|--------| +| **Ctrl++** | Zoom in | +| **Ctrl+-** | Zoom out | +| **Ctrl+0** | Zoom reset | +| **Ctrl+F** | Fit to window | +| **F1** | Keyboard shortcuts panel | --- @@ -121,4 +154,4 @@ Once you've completed your first map: - [Usage Guide](/tools/tilemap-editor/usage-guide) - Essential features - [Advanced Guide](/tools/tilemap-editor/advanced-guide) - Advanced features -- [Technical Reference](/tools/tilemap-editor technical-reference) - Technical specs \ No newline at end of file +- [Technical Reference](/tools/tilemap-editor/technical-reference) - Technical specs diff --git a/tools/tilemap-editor/technical-reference.md b/tools/tilemap-editor/technical-reference.md index 3d9c5d7..534de5d 100644 --- a/tools/tilemap-editor/technical-reference.md +++ b/tools/tilemap-editor/technical-reference.md @@ -1,3 +1,8 @@ +--- +title: "Technical Reference" +description: "Engine limits, binary format v6, project structure, C++ export, data formats, and compatibility" +--- + # Tilemap Editor - Technical Reference **Level**: ⭐⭐⭐ Advanced @@ -8,7 +13,7 @@ > - [Engine Limits](#engine-limits) > - [File Formats](#file-formats) > - [Project Structure](#project-structure) -> - [API Services](#api-services) +> - [Application Architecture](#application-architecture) > - [C++ Export](#c-export) > - [Data Formats](#data-formats) > - [Compatibility](#compatibility) @@ -36,7 +41,7 @@ | **MIN_FRAME_DURATION** | 1 | Minimum duration (ticks) | | **MAX_FRAME_DURATION** | 255 | Maximum duration (ticks) | -> ⚠️ **Correction**: Previous docs said 4 layers. Actual limit is **8 layers**. +> **Enforcement**: Tile size, layer count, and animation limits are validated at edit time (project creation, add-layer, add-animation). At save, animations and player spawn positions are re-validated. ### Screen Resolutions @@ -52,38 +57,37 @@ ## File Formats -### Supported Formats +### Project File -| Format | Extension | Advantages | Disadvantages | -|--------|-----------|------------|-------------| -| **JSON** | `.pr32scene` | Human-readable, git-friendly | Large files | -| **Binary** | `.pr32scene.bin` | Up to 335× smaller, 10× faster | Not readable | +The editor stores projects in a **single binary format** (`.pr32scene.bin`, version **6**). There is **no human-readable JSON writer**; the JSON object used inside the serializer only carries project metadata and per-tile attributes embedded in the binary container. -### Binary Format Versions +The **"Use Binary Format"** preference in **File → Preferences** only affects the **file extension** written to disk (`.pr32scene.bin` vs `.pr32scene`). The on-disk content is the same binary v6 container either way. -| Version | Features | Compatibility | -|---------|----------|---------------| -| 1 | Basic | ✅ Compatible | -| 2 | Tile attributes | ✅ Compatible | -| 3 | Palette slots | ✅ Compatible | -| 4 | Multi-palette complete | ✅ Compatible | +| Extension | Content | +|-----------|---------| +| `.pr32scene.bin` | Binary v6 container (default) | +| `.pr32scene` | Legacy extension accepted for open; still binary v6 when saved | -> ⚠️ **Correction**: Previous docs said version 3. Actual is **version 4**. +### Binary Format -### Compression Benchmarks +The `.pr32scene.bin` format is a **big-endian** binary container (current version **6**). Layout: -| Project | JSON | Binary | Reduction | -|----------|------|--------|----------| -| Small (1 scene) | 2.6 KB | 355 bytes | **86%** | -| Medium (3 scenes) | 227 KB | 752 bytes | **99.7%** | -| Large (10 scenes) | ~1 MB | ~5 KB | **99.5%** | +| Field | Size | Notes | +|-------|------|-------| +| **MAGIC** | 4 B | `PR32` (big-endian `0x50523332`) | +| **VERSION** | u16 | Current: **6** | +| **FLAGS** | u16 | Bit 0: `COMPRESSION_ZLIB` | +| **tileSize** | u8 | Tile size in px | +| **reserved** | 3 B | Padding | +| **Metadata** | u32 len + JSON | Project metadata (JSON embedded) | +| **Tilesets** | u16 count + entries | Per-tileset data | +| **Scenes** | u16 count + entries | Per-scene data; optional zlib-compressed layers; v6+: player spawn `x/y` | -### Performance +The serializer targets byte-for-byte compatibility with the engine's binary project format (big-endian layout). Layer payloads can be zlib-compressed (flag bit 0). -| Operation | JSON | Binary | Improvement | -|-----------|------|--------|------------| -| **Save** | 20ms | 2ms | **10×** | -| **Load** | 60ms | 21ms | **3×** | +### Size & Performance + +The binary format keeps projects compact and fast to load (single-format; there is no alternative JSON serialization to compare against). --- @@ -93,8 +97,7 @@ ``` my_project/ -├── my_project.pr32scene # Main file -├── my_project.pr32scene.bin # Binary version (optional) +├── my_project.pr32scene.bin # Project file (binary v6, default) ├── tile_flag_rules.json # Custom rules (optional) └── assets/ └── tilesets/ @@ -102,76 +105,55 @@ my_project/ └── tileset2.png ``` +> The file is stored as `.pr32scene.bin` by default. With **"Use Binary Format"** disabled it is written as `.pr32scene` instead (still binary v6 content). Only the extension changes. + ### Exported Files ``` output/ -├── my_scene.h # Declarations +├── my_scene.h # Declarations + animations + palettes (multi-palette) ├── my_scene.cpp # Data (palettes, tiles, indices) -├── my_scene_animations.h # Animation declarations (if any) -├── my_scene_animations.cpp # Animation data (if any) -└── shared_palette.h # Shared palette (single palette mode) +└── {namespace}_tilemap_palette.h # Shared palette (single palette mode) ``` +> Animations are embedded in `my_scene.h` alongside their layer (`_TILE_ANIMATIONS[]`). There are no separate `*_animations.h/.cpp` files. + --- -## API Services - -### Services - -#### ProjectService - -```python -class ProjectService: - def create_project(self, name: str, tile_size: int, ...) -> ProjectModel: - """Create new project""" - - def load_project(self, path: str) -> ProjectModel: - """Load project""" - - def save_project(self, project: ProjectModel, binary: bool = False): - """Save project""" - - def export_to_cpp(self, project: ProjectModel, output_dir: str) -> Dict: - """Export to C++""" -``` +## Application Architecture -#### ExporterService +The Tilemap Editor is a **native desktop application** built with **C++17** on **SDL2 + ImGui** + **OpenGL 3.3**. There is no Python/Tkinter runtime. The editor is distributed as a compiled binary within the Tool Suite. -```python -class ExporterService: - def can_export(self) -> bool: - """Check if user can export (requires valid license)""" - - def export_project(self, project, output_dir: str) -> Dict: - """Export project to C++ files""" - # Auto-detects single/multi-palette -``` +### Core Services -#### ValidationService +The editor's logic is organized into the following internal services (C++): -```python -class ValidationService: - def validate_project(self, project: ProjectModel) -> ValidationResult: - """Validate full project""" - - def validate_animations(self, animations) -> ValidationResult: - """Validate against limits""" -``` +| Service | File (source) | Responsibility | +|---------|---------------|----------------| +| **ProjectService** | `tools/tilemap_module/project_service.{h,cpp}` | Create / load / save projects, validate project name, manage tile flag rules | +| **BinarySerializer** | `tools/tilemap_module/binary_serializer.{h,cpp}` | Read/write `.pr32scene.bin` (v6, big-endian, optional zlib compression) | +| **HistoryManager** | `tools/tilemap_module/history_manager.{h,cpp}` | Bounded (100 entries) undo/redo stack with optional compression | +| **AnimationValidator** | `tools/tilemap_module/core/animation_validator.{h,cpp}` | Validate animations against engine limits (bounds, overlap, count, duration) | +| **ExporterService** | `tools/tilemap_module/exporter_service.{h,cpp}` | Gate C++ export behind a valid license; coordinate the native export pipeline | +| **ExportOrchestrator** | `tools/tilemap_module/native_export/export_orchestrator.{h,cpp}` | Multi-palette detection, image processing, palette analysis, tile dedup, C++ code generation | +| **AutosaveService** | `tools/tilemap_module/autosave_service.{h,cpp}` | Interval-based autosave | +| **ToolManager** | `tools/tilemap_module/tool_manager.{h,cpp}` | Active tool registry (Brush, Eraser, Rectangle, Pan, Pipette, Attribute, Anim) | -#### AnimationService - -```python -class AnimationService: - def create_animation(self, name: str) -> TileAnimation: - """Create animation""" - - def link_to_tile(self, animation: TileAnimation, base_tile: int): - """Link animation to tile""" - - def export_animations(self, animations, output_dir: str): - """Export animations to C++""" -``` +> **Note:** These services are internal C++ modules compiled into the Tool Suite binary. They are **not** a public Python API and cannot be imported by external scripts. Automation should use the file formats described below or the external `pr32-sprite-compiler` CLI (Sprite Compiler module). + +### Runtime Environment + +| Item | Detail | +|------|--------| +| **Language / standard** | C++17 | +| **GUI framework** | Dear ImGui (v1.92.8) | +| **Windowing / GPU** | SDL2 + OpenGL 3.3 (single window, DockSpace layout) | +| **JSON** | nlohmann/json v3.11.3 | +| **SVG rasterization** | lunasvg v3.1.0 | +| **Native file pickers** | portable-file-dialogs | +| **Compression** | zlib (`.pr32scene.bin` layer payloads) | +| **Crypto** | OpenSSL (SHA-256 checksum + AES-256-CBC) | +| **Build system** | CMake ≥ 3.20 | --- @@ -179,9 +161,9 @@ class AnimationService: ### Requirements -⚠️ **Important**: C++ export **requires a valid license**. +⚠️ **Important**: C++ export **requires a valid license** (Ed25519 v3 key, machine-bound). See **[License & Activation](/tools/tilemap-editor/license-and-activation)** for full details. -- No license: Button shows 🔒 +- Without license, the **Upgrade Required** dialog appears when attempting to export - Other features work without license ### Export Options @@ -189,8 +171,8 @@ class AnimationService: | Option | Description | Recommended | |--------|-------------|-------------| | **C++ Namespace** | Namespace for code | Project name | -| **Color Depth** | Bit depth (auto-detect) | Auto-detect | -| **Store in Flash** | Save to PROGMEM | ✅ Always | +| **Color Depth (BPP)** | Read-only; auto-detected (1/2/4) | Auto-detect | +| **Store in Flash (ESP32)** | Save to PROGMEM | ✅ Always | | **Legacy Format** | Without Flash attributes | Compatibility only | ### Export Mode @@ -206,30 +188,22 @@ class AnimationService: ```cpp // level1.h -extern const uint16_t TILEMAP_PALETTE_DATA[]; -extern const pixelroot32::graphics::Sprite4bpp TILESET_SPRITES[]; -extern const pixelroot32::graphics::TileMap layer_foreground; +static const uint16_t TILEMAP_PALETTE_DATA[] = { /* RGB565 */ }; +extern pixelroot32::graphics::TileMap4bpp layer_foreground; // level1.cpp -static const uint16_t TILEMAP_PALETTE_DATA[] = { /* RGB565 */ }; static const pixelroot32::graphics::Sprite4bpp TILESET_SPRITES[] = { /* tiles */ }; static const uint8_t LAYER_FOREGROUND_INDICES[] = { /* indices */ }; - -void init() { - layer_foreground.palette = TILEMAP_PALETTE_DATA; - layer_foreground.tiles = TILESET_SPRITES; - layer_foreground.indices = LAYER_FOREGROUND_INDICES; -} ``` +> The palette array is declared in the header; tiles and index data live in the `.cpp`. The layer struct is `TileMap`, `TileMap2bpp`, or `TileMap4bpp` depending on the auto-detected BPP. + #### Multi-Palette ```cpp // level1.h -// setBackgroundCustomPaletteSlot(1, PLATFORMS_PALETTE); -extern const uint16_t PLATFORMS_PALETTE[]; -extern const uint16_t STAIRS_PALETTE[]; -extern const pixelroot32::graphics::Sprite4bpp PLATFORMS_TILESET_SPRITES[]; +static const uint16_t PLATFORMS_PALETTE[16] = { /* RGB565 */ }; +static const uint16_t STAIRS_PALETTE[16] = { /* RGB565 */ }; // level1.cpp void init() { @@ -245,7 +219,7 @@ void init() { #include "level1.h" level1::init(); -renderer.drawTileMap(level1::layer_background, x, y); +renderer.drawTileMap(level1::layer_foreground, x, y); ``` **Multi-Palette**: @@ -263,16 +237,18 @@ renderer.drawTileMap(level1::platforms, 0, 0); const char* type = level1::get_tile_attribute(0, x, y, "type"); // Query flags -uint8_t flags = level1::behavior_layer_background[y * width + x]; +uint8_t flags = level1::getTileFlags(0, x, y); // layer index, x, y if (flags & TILE_SOLID) { /* collision */ } ``` **Animations**: ```cpp -level1::get_animation_manager().step(); -renderer.drawTileMap(level1::layer_background, x, y); +level1::getForegroundAnimManager().step(); +renderer.drawTileMap(level1::layer_foreground, x, y); ``` +> Each animated layer exposes a `AnimManager()`. A legacy `getAnimManager()` alias maps to the Details layer when present. + --- ## Data Formats @@ -298,24 +274,28 @@ renderer.drawTileMap(level1::layer_background, x, y); ### BPP Auto-Detection -| Colors Used | BPP | Maximum | +| Real Colors (excl. transparency) | BPP | Maximum | |------------|-----|----------| -| 1-2 | 1 bpp | 2 | -| 3-4 | 2 bpp | 4 | -| 5-16 | 4 bpp | 16 | +| ≤ 1 | 1 bpp | 2 | +| 2-4 total slots (incl. optional transparency) | 2 bpp | 4 | +| otherwise | 4 bpp | 16 | + +> `totalSlots = realColors + (hasTransparency ? 1 : 0)`. 1bpp requires ≤1 real color; 2bpp when total slots ≤ 4; otherwise 4bpp. --- ## Compatibility -### Dependencies +### Runtime + +The Tilemap Editor is distributed as a **pre-built native binary** (part of the Tool Suite). No Python, Tkinter, or Pillow installation is required. -| Package | Minimum Version | -|---------|--------------| -| **Python** | 3.8+ | -| **Tkinter** | 8.6+ | -| **ttkbootstrap** | 1.0+ | -| **Pillow** | 9.0+ | +| Requirement | Detail | +|-------------|--------| +| **Operating system** | Windows, Linux, macOS (per release) | +| **GPU / Windowing** | OpenGL 3.3 capable GPU; SDL2-based window | +| **Storage** | ~tens of MB for the app + generated assets | +| **License** | A valid Tool Suite license is required for **C++ export** | ### Target Hardware diff --git a/tools/tilemap-editor/usage-guide.md b/tools/tilemap-editor/usage-guide.md index 0e32160..52448ca 100644 --- a/tools/tilemap-editor/usage-guide.md +++ b/tools/tilemap-editor/usage-guide.md @@ -1,3 +1,8 @@ +--- +title: "Usage Guide" +description: "Day-to-day PixelRoot32 Tilemap Editor reference - layers, projects, tilesets, tools, and keyboard shortcuts" +--- + # Tilemap Editor - Usage Guide **Level**: ⭐ Beginner | ⭐⭐ Intermediate @@ -26,8 +31,6 @@ - **Bottom layer**: Rendered below others - **Maximum**: **8 layers** per scene -> ⚠️ **Correction**: Previous docs said 4 layers. Actual limit is **8 layers**. - ### ⭐⭐ Managing Layers **Add layer**: @@ -48,7 +51,7 @@ - Or use ordering commands **Rename**: -1. Double-click layer name +1. Click the ✏️ rename button on the layer row 2. Type new name 3. Press Enter @@ -77,6 +80,8 @@ 3. Click **Create Project** 4. Select empty folder +> Project names are sanitized to lowercase alphanumeric + `_`. Dots `..` and `.` are rejected. See [Tile Flag Rules](/tools/tilemap-editor/advanced-guide#tile-flag-rules) for per-project rule files. + 💡 **Tip**: Use "Fit Map to Hardware Limit" to auto-fit to ESP32 (320×240). ### ⭐ Project Settings @@ -90,12 +95,24 @@ ### ⭐ Save & Load -| Format | Extension | Advantages | -|--------|----------|------------| -| **JSON** | `.pr32scene` | Human-readable, git-friendly | -| **Binary** | `.pr32scene.bin` | Up to 335× smaller, 10× faster | +| Extension | Content | +|-----------|---------| +| `.pr32scene.bin` | Binary v6 format (default) | +| `.pr32scene` | Legacy extension; still binary v6 content | + +**File → Preferences** opens a modal dialog. The **"Use Binary Format"** checkbox inside only changes the saved **extension** (`.pr32scene.bin` vs `.pr32scene`). The on-disk content is always the binary v6 container — there is no JSON project format. + +### ⭐ Toolbar Indicators + +The top toolbar shows status indicators while a project is open: -**Switch to binary**: **File → Preferences → Use Binary Format** +| Indicator | Meaning | Interactive | +|-----------|---------|:---:| +| `HIST:n` | Number of undo entries in history (max **100**) | ❌ | +| `BIN` / `JSON` | Current save format preference | ✅ Click to toggle | +| `Export` | Shortcut to export dialog | ✅ Click to open | + +> The undo history is limited to **100 operations per session**. Enabling **History Compression** in Preferences merges consecutive similar edits to stay within the cap longer. --- @@ -103,15 +120,10 @@ ### ⭐ Importing a Tileset -**Method 1** - TILESET panel: -1. Click **Import tileset** +1. In the **TILESET** panel, click **Import tileset** 2. Select PNG/JPG/BMP 3. Auto-copied to `assets/tilesets/` -**Method 2** - Menu: -1. **File → Import Tileset** -2. Select image - 📝 **Format**: PNG recommended, multiples of tile size, up to 16 colors. ### ⭐ Selecting Tiles @@ -128,7 +140,7 @@ - **Zoom In**: Mouse wheel up - **Zoom Out**: Mouse wheel down -- Increments: 0.5× (min 1×, max 10×) +- Increments: 0.25× (min 1×, max 4×) ### ⭐ Multiple Tilesets @@ -169,16 +181,16 @@ Tileset B: 8 tiles (indices 10-17) ### ⭐⭐ Managing Scenes **Rename**: -1. Right-click scene → **Rename** +1. Click the ✏️ rename button on the scene row 2. Type new name 3. Press Enter **Duplicate**: -1. Right-click scene → **Duplicate** +1. Click the 📄 duplicate button on the scene row 2. Exact copy with "(Copy)" **Delete**: -1. Right-click scene → **Delete** +1. Click 🗑️ delete button on the scene row 2. Confirm > ⚠️ Cannot delete last scene @@ -211,39 +223,32 @@ Tileset B: 8 tiles (indices 10-17) **Method 2** (universal): - Right-click with any tool -### ⭐⭐ Pipette (P) - -1. Select Pipette (**P**) -2. Click tile on canvas -3. Auto-selected in TILESET - -### ⭐⭐ Attribute Tool (A) - -1. Select Attribute (**A**) -2. Click tile to assign/edit -3. Configure properties +### ⭐⭐ Pipette (I) -> 💡 **See**: [Advanced Guide](/tools/tilemap-editor/advanced-guide) for attributes +1. Select Pipette (**I**) +2. Click tile on canvas to pick it as the active tile +3. The picked tile is auto-selected in the TILESET panel +4. To assign a tile to an animation: pick the tile with Pipette, open the **Animations** panel, select a target animation, and click **Apply** -### ⭐⭐ Animation Eyedropper (I) +> 💡 **See**: [Advanced Guide](/tools/tilemap-editor/advanced-guide) for animations and attributes -1. Select Animation Eyedropper (**I**) -2. Click tile on canvas -3. Auto-linked to current animation +### ⭐⭐ Attribute Tool (A) -> 💡 **See**: [Advanced Guide](/tools/tilemap-editor/advanced-guide) for animations +### ⭐⭐ Live Preview -### ⭐⭐ Live Preview (L) +1. Click the **▶ Live Preview** button in the toolbar +2. Animations play in real-time on the canvas +3. Uses the **Play/Pause** button, speed controls (1× / 2× / 0.5×), and frame-stepping from the toolbar -1. Click **Live Preview** button -2. Or press **L** -3. Animations play in real-time on canvas +### ⭐⭐ Pan -### ⭐ Pan (Space) +**Persistent Pan (G)**: +- Press **G** to switch to Pan tool permanently +- Use another tool key (B, E, R, I, A) to switch back -1. Hold **Space** -2. Drag to move view -3. Release to return to tool +**Temporary Pan (Space)**: +- Hold **Space** to temporarily pan +- Release to return to your previous tool ### ⭐ Zoom Controls @@ -276,7 +281,7 @@ Mouse over canvas: ### ⭐ Activating **Per scene**: -1. Click 🧅 icon next to scene +1. Check the 🧅 checkbox next to the scene 2. Scene appears translucent **Global**: @@ -285,9 +290,8 @@ Mouse over canvas: ### ⭐ Adjusting Opacity -- Use **"Opacity"** slider +- Use **"Opacity"** slider (0.0-1.0) - Recommended: 0.3-0.5 (30-50%) -- Default: 0.4 (40%) ### ⭐⭐ Example: Aligning Exit @@ -300,6 +304,27 @@ Mouse over canvas: --- +## Export + +### ⭐⭐ Export to C++ + +1. Click the **Export** button in the toolbar, or **File → Export** +2. Configure options: + +| Option | Description | +|--------|-------------| +| **C++ Namespace** | Namespace for generated code | +| **Color Depth** | Auto-detected BPP (1/2/4) | +| **Store in Flash (ESP32)** | Save tile data to PROGMEM | +| **Legacy Format** | Without Flash attributes (compatibility) | + +3. Select output directory +4. Generated files: `scene_name.h`, `scene_name.cpp`, optional `scene_name_animations.h/.cpp`, and `shared_palette.h` + +🔒 **License required**: Exporting to C++ requires a valid license. See [License & Activation](/tools/tilemap-editor/license-and-activation). + +--- + ## Preferences ### ⭐ Access @@ -307,25 +332,19 @@ Mouse over canvas: **File → Preferences** **Grid Settings**: -- **Canvas Grid Intensity**: Grid opacity (0-255) -- **Tileset Grid Intensity**: Grid opacity in tileset -- **Attribute Indicator Opacity**: Marker opacity (0.0-1.0) +- **Grid Background Color**: Color of the canvas background behind the grid +- **Canvas Grid Intensity**: Grid opacity on the canvas (0-255, default 40) +- **Tileset Grid Intensity**: Grid opacity in the tileset panel (0-255, default 120) +- **Attribute Indicator Opacity**: Marker opacity for tile attributes (0-255, default 200) +- **Animation Indicator Opacity**: Marker opacity for animated tiles (0-255, default 180) **Auto-save**: -- **Enabled**: On/off -- **Interval**: Minutes (1-60) +- **Enabled**: On/off (enabled by default) +- **Interval**: Minutes (1-30, default 5 min) **Optimization**: -- **History Compression**: Compresses consecutive operations -- **Use Binary Format**: Default .bin format - -### ⭐⭐ Memory & Lazy Loading - -Editor implements **lazy loading** for memory optimization: - -- Inactive scenes stay unloaded -- Load on demand when switching -- Configurable in preferences +- **History Compression**: Compresses consecutive undo operations +- **Use Binary Format**: Sets the saved file extension --- @@ -338,11 +357,10 @@ Editor implements **lazy loading** for memory optimization: | **B** | Brush | | **E** | Eraser | | **R** | Rectangle | -| **P** | Pipette | +| **G** | Pan (persistent) | +| **I** | Pipette | | **A** | Attribute | -| **I** | Animation Eyedropper | -| **L** | Live Preview | -| **Space** | Pan (hold) | +| **Space** | Pan (temporary hold) | ### Navigation @@ -354,15 +372,23 @@ Editor implements **lazy loading** for memory optimization: | **Ctrl+0** | Reset zoom | | **Ctrl+F** | Fit to screen | +### File + +| Shortcut | Action | +|----------|--------| +| **Ctrl+N** | New project | +| **Ctrl+O** | Open project | +| **Ctrl+S** | Save | +| **Ctrl+Shift+S** | Save As | +| **Ctrl+W** | Close project | + ### Editing | Shortcut | Action | |----------|--------| | **Ctrl+Z** | Undo | -| **Ctrl+Y** | Redo | -| **Ctrl+S** | Save | -| **Ctrl+E** | Export C++ | -| **Esc** | Close panels | +| **Ctrl+Y** / **Ctrl+Shift+Z** | Redo | +| **F1** | Keyboard shortcuts panel | ### Mouse