readme updates

This commit is contained in:
Savya Bikram Shah
2026-05-27 11:07:05 +05:45
parent f3b53be39d
commit 50ca3a0a0f

View File

@@ -1170,8 +1170,10 @@ Paths are **relative** to `persistentDataPath`. Never store absolute paths — t
## 29. Boot & Error Handling ## 29. Boot & Error Handling
> **Status: not implemented.** No `AppBoot` class exists. Today, [RootLifetimeScope.cs](Assets/Darkmatter/Code/App/LifetimeScopes/RootLifetimeScope.cs) only iterates installer MonoBehaviours and registers them — nothing runs after that. The block below is the *target* sequence when `AppBoot` is added as an `IAsyncStartable` entry point under `App/Boot/`.
``` ```
AppBoot.StartAsync() AppBoot.StartAsync() (planned — Features/Boot/AppBoot.cs, registered via builder.RegisterEntryPoint<AppBoot>())
├─ try Addressables.InitializeAsync() ├─ try Addressables.InitializeAsync()
│ fail → show "Tap to retry" splash │ fail → show "Tap to retry" splash
├─ try preload palette + UI sounds (Addressables labels) ├─ try preload palette + UI sounds (Addressables labels)
@@ -1227,6 +1229,8 @@ If a class's natural home doesn't match its asmdef, the architecture is bent —
## 32. Class Reference (Detailed) ## 32. Class Reference (Detailed)
> **Status: target spec, mostly unimplemented.** Of everything below, only the following Service classes exist on disk today: `AddressableAssetProviderService`, `AudioService` / `SfxPlayer`, `CameraService`, `SceneService`, `InputReaderSO`, `FirebaseAnalyticsSystem`. Everything else (Paper, Drawing, Coloring, History, Capture, Gallery, Progression, ColorBookFlow, ArtBook, AppBoot) is the target shape for when those classes are written. Treat this section as a contract for new code, not documentation of current state.
Canonical breakdown of every concrete class and interface. For each: **purpose**, **public surface** (signatures), **injected dependencies**, and **collaborators** (signals or interfaces it talks to). Canonical breakdown of every concrete class and interface. For each: **purpose**, **public surface** (signatures), **injected dependencies**, and **collaborators** (signals or interfaces it talks to).
> Convention used below > Convention used below
@@ -1234,6 +1238,7 @@ Canonical breakdown of every concrete class and interface. For each: **purpose**
> - `// pub:` = events / signals fired > - `// pub:` = events / signals fired
> - `// sub:` = events / signals consumed > - `// sub:` = events / signals consumed
> - All async returns are `UniTask` unless noted. > - All async returns are `UniTask` unless noted.
> - Folder labels follow the actual nesting pattern: `Core/Contracts/Features/<Name>/`, `Core/Contracts/Services/<Name>/`, `Core/Data/Dynamic/Features/<Name>/`, `Features/<Name>/<Sub>/`, `Services/<Name>/<Sub>/`.
--- ---
@@ -1241,7 +1246,7 @@ Canonical breakdown of every concrete class and interface. For each: **purpose**
Pure interfaces and DTOs. Zero logic. Pure interfaces and DTOs. Zero logic.
#### `IDrawingTemplate` *(Core/Drawing)* #### `IDrawingTemplate` *(Core/Contracts/Features/Drawing — planned)*
Immutable view of a single drawing's authored data. Immutable view of a single drawing's authored data.
```csharp ```csharp
public interface IDrawingTemplate { public interface IDrawingTemplate {
@@ -1255,7 +1260,7 @@ public interface IDrawingTemplate {
``` ```
Implemented by `DrawingTemplateSO` (ScriptableObject) loaded via Addressables. Implemented by `DrawingTemplateSO` (ScriptableObject) loaded via Addressables.
#### `IDrawingTemplateCatalog` *(Core/Drawing)* #### `IDrawingTemplateCatalog` *(Core/Contracts/Features/Drawing — planned)*
Authority on which drawings exist, completion state, and "next" selection. Authority on which drawings exist, completion state, and "next" selection.
```csharp ```csharp
public interface IDrawingTemplateCatalog { public interface IDrawingTemplateCatalog {
@@ -1268,7 +1273,7 @@ public interface IDrawingTemplateCatalog {
} }
``` ```
#### `IColorPalette` *(Core/Coloring)* #### `IColorPalette` *(Core/Contracts/Features/Coloring — planned)*
Set of colors offered to the child. Authored as `ColorPaletteSO`. Set of colors offered to the child. Authored as `ColorPaletteSO`.
```csharp ```csharp
public interface IColorPalette { public interface IColorPalette {
@@ -1277,10 +1282,10 @@ public interface IColorPalette {
} }
``` ```
#### `ICommand` & `IUndoStack` *(Core/History)* #### `ICommand` & `IUndoStack` *(Core/Contracts/Features/History — planned)*
Already shown in section 8. Each undoable user action is one `ICommand`; the stack is bounded. Already shown in section 8. Each undoable user action is one `ICommand`; the stack is bounded.
#### `IGalleryService` *(Core/Gallery)* #### `IGalleryService` *(Core/Contracts/Services/Gallery — planned)*
Persistent store of saved artwork PNGs. Persistent store of saved artwork PNGs.
```csharp ```csharp
public interface IGalleryService { public interface IGalleryService {
@@ -1292,7 +1297,7 @@ public interface IGalleryService {
} }
``` ```
#### `ICaptureService` *(Core/Capture)* #### `ICaptureService` *(Core/Contracts/Services/Capture — planned)*
Snapshots the paper RT to a PNG blob. No arguments — dimensions and content come from `IPaperRig.Surface`. Snapshots the paper RT to a PNG blob. No arguments — dimensions and content come from `IPaperRig.Surface`.
```csharp ```csharp
public interface ICaptureService { public interface ICaptureService {
@@ -1300,7 +1305,7 @@ public interface ICaptureService {
} }
``` ```
#### `IPaperRig` *(Core/Paper)* #### `IPaperRig` *(Core/Contracts/Features/Paper — planned)*
Shared art rig. The single source of truth for everything that lives in the drawing world. Shared art rig. The single source of truth for everything that lives in the drawing world.
```csharp ```csharp
public interface IPaperRig { public interface IPaperRig {
@@ -1312,7 +1317,7 @@ public interface IPaperRig {
} }
``` ```
#### `IArtInputBridge` *(Core/Paper)* #### `IArtInputBridge` *(Core/Contracts/Features/Paper — planned)*
Converts screen-space pointer coords to art-world coords inside the RT. Converts screen-space pointer coords to art-world coords inside the RT.
```csharp ```csharp
public interface IArtInputBridge { public interface IArtInputBridge {
@@ -1321,7 +1326,7 @@ public interface IArtInputBridge {
``` ```
Returns `false` when the pointer is outside the displayed RawImage rect (toddler tapped the HUD or backdrop). Every art-world raycast goes through this. Returns `false` when the pointer is outside the displayed RawImage rect (toddler tapped the HUD or backdrop). Every art-world raycast goes through this.
#### `IProgressionService` *(Core/Progression)* #### `IProgressionService` *(Core/Contracts/Features/Progression — planned)*
Tracks which templates the child has completed and what they last opened. Tracks which templates the child has completed and what they last opened.
```csharp ```csharp
public interface IProgressionService { public interface IProgressionService {
@@ -1334,7 +1339,7 @@ public interface IProgressionService {
} }
``` ```
#### `IAssetProviderService` *(Core/Assets)* #### `IAssetProviderService` *(Core/Contracts/Services/Assets — ✅ exists)*
Addressables wrapper. Hides handle bookkeeping from features. Addressables wrapper. Hides handle bookkeeping from features.
```csharp ```csharp
public interface IAssetProviderService { public interface IAssetProviderService {
@@ -1346,7 +1351,7 @@ public interface IAssetProviderService {
} }
``` ```
#### `IEventBus` *(Libs/EventBus, also referenced from Core)* #### `IEventBus` *(Libs/Observer — ✅ exists; note the folder is `Observer`, not `EventBus`)*
```csharp ```csharp
public interface IEventBus { public interface IEventBus {
void Publish<T>(T signal) where T : struct; void Publish<T>(T signal) where T : struct;
@@ -1359,15 +1364,15 @@ Signals are structs to avoid GC. Disposable subscription so presenters can unsub
### 32.2 Services Layer ### 32.2 Services Layer
Concrete infrastructure. One implementation each. All singletons in `RootLifetimeScope`. Concrete infrastructure. One implementation each. All singletons in `RootLifetimeScope`, registered via per-service `MonoBehaviour, IServiceModule` installers.
#### `AddressableAssetProviderService` *(Services/Assets)* #### `AddressableAssetProviderService` *(Services/Assets — ✅ exists)*
Implements `IAssetProviderService`. Implements `IAssetProviderService`.
- **Responsibility:** Wrap `Addressables.LoadAssetAsync<T>` and ref-count handles by address. - **Responsibility:** Wrap `Addressables.LoadAssetAsync<T>` and ref-count handles by address.
- **State:** `Dictionary<string, AsyncOperationHandle>` keyed by address. - **State:** `Dictionary<string, AsyncOperationHandle>` keyed by address.
- **Notes:** `Release(address)` decrements; `ReleaseAll()` for scene teardown. Initialization must complete before any other service may load. - **Notes:** `Release(address)` decrements; `ReleaseAll()` for scene teardown. Initialization must complete before any other service may load.
#### `FileGalleryService` *(Services/Gallery)* #### `FileGalleryService` *(Services/Gallery — planned)*
Implements `IGalleryService`. Implements `IGalleryService`.
```csharp ```csharp
// fields: // fields:
@@ -1380,13 +1385,13 @@ Implements `IGalleryService`.
- **List flow:** enumerate `*.json` in `Gallery/`, deserialize, sort by `CreatedUtc desc`. - **List flow:** enumerate `*.json` in `Gallery/`, deserialize, sort by `CreatedUtc desc`.
- **Delete flow:** delete png + thumb + json; missing files ignored (idempotent). - **Delete flow:** delete png + thumb + json; missing files ignored (idempotent).
#### `RenderTextureCaptureService` *(Services/Capture)* #### `RenderTextureCaptureService` *(Services/Capture — planned)*
Implements `ICaptureService`. Implements `ICaptureService`.
- **Steps:** allocate `RenderTexture(width, height, 0, ARGB32)` → bind to `artCamera.targetTexture``artCamera.Render()``ReadPixels` into `Texture2D` → composite `paperBackground` underneath (single shader blit) → `EncodeToPNG` → release RT + textures. - **Steps:** allocate `RenderTexture(width, height, 0, ARGB32)` → bind to `artCamera.targetTexture``artCamera.Render()``ReadPixels` into `Texture2D` → composite `paperBackground` underneath (single shader blit) → `EncodeToPNG` → release RT + textures.
- **Threading:** PNG encode happens on a `UniTask.RunOnThreadPool` to avoid hitching the main thread on tablets. - **Threading:** PNG encode happens on a `UniTask.RunOnThreadPool` to avoid hitching the main thread on tablets.
- **Sizing:** default 2048², overridable. Capped at device max texture size. - **Sizing:** default 2048², overridable. Capped at device max texture size.
#### `JsonPersistenceService` *(Services/Persistence)* #### `JsonPersistenceService` *(Services/Persistence — planned; today `Libs/PlayerPrefs` covers small-key state)*
Implements `IPersistenceService` (small JSON blob; not the gallery). Implements `IPersistenceService` (small JSON blob; not the gallery).
```csharp ```csharp
public interface IPersistenceService { public interface IPersistenceService {
@@ -1398,7 +1403,7 @@ public interface IPersistenceService {
- **Format:** single JSON object keyed by `key` so multiple services can share one file. - **Format:** single JSON object keyed by `key` so multiple services can share one file.
- **Atomicity:** write to `save.json.tmp` → rename. - **Atomicity:** write to `save.json.tmp` → rename.
#### `SceneService` *(Services/Scenes)* #### `SceneService` *(Services/Scenes — ✅ exists)*
Implements `ISceneService`. Wraps `SceneManager.LoadSceneAsync` with `UniTask` plus a fade-curtain. Implements `ISceneService`. Wraps `SceneManager.LoadSceneAsync` with `UniTask` plus a fade-curtain.
```csharp ```csharp
public interface ISceneService { public interface ISceneService {
@@ -1407,7 +1412,7 @@ public interface ISceneService {
} }
``` ```
#### `AudioService` *(Services/Audio)* #### `AudioService` *(Services/Audio — ✅ exists; see also `SfxPlayer`)*
Implements `IAudioService`. Plays SFX clips loaded by address, mixes via Unity AudioMixer groups. Implements `IAudioService`. Plays SFX clips loaded by address, mixes via Unity AudioMixer groups.
```csharp ```csharp
public interface IAudioService { public interface IAudioService {
@@ -1418,7 +1423,7 @@ public interface IAudioService {
``` ```
Holds an internal `Dictionary<string, AudioClip>` populated at preload. Holds an internal `Dictionary<string, AudioClip>` populated at preload.
#### `InputReaderSO` *(Services/Inputs)* #### `InputReaderSO` *(Services/Inputs/Readers — ✅ exists)*
ScriptableObject wrapping the new Input System; exposes events. ScriptableObject wrapping the new Input System; exposes events.
```csharp ```csharp
public interface IInputReader { public interface IInputReader {
@@ -1435,19 +1440,19 @@ public interface IInputReader {
Generic, project-agnostic utilities. Generic, project-agnostic utilities.
#### `BoundedUndoStack` *(Libs/CommandStack)* #### `BoundedUndoStack` *(Libs/CommandStack — planned)*
Implements `IUndoStack`. Source already in section 24. Implements `IUndoStack`. Source already in section 24.
- **Capacity:** default 20. - **Capacity:** default 20.
- **Invariant:** `_redo` cleared on any new `Push`. - **Invariant:** `_redo` cleared on any new `Push`.
- **Edge cases:** `Undo`/`Redo` on empty stack is a no-op (never throws). - **Edge cases:** `Undo`/`Redo` on empty stack is a no-op (never throws).
#### `EventBus` *(Libs/EventBus)* #### `EventBus` *(Libs/Observer — ✅ exists)*
Implements `IEventBus` with a `Dictionary<Type, Delegate>` of `Action<T>` per signal type. Implements `IEventBus` with a `Dictionary<Type, Delegate>` of `Action<T>` per signal type.
- **Subscribe** returns an `IDisposable` that removes the handler on `Dispose`. - **Subscribe** returns an `IDisposable` that removes the handler on `Dispose`.
- **Publish** snapshots the invocation list before iterating (so handlers may safely unsubscribe during dispatch). - **Publish** snapshots the invocation list before iterating (so handlers may safely unsubscribe during dispatch).
#### `Fsm<TState>` *(Libs/FSM)* #### `StateMachine` / `IState` / `State` *(Libs/FSM — ✅ exists)*
Generic state machine used by `ColorBookFlowController`. Generic state machine. Current shape on disk uses `IState` / `State` / `StateMachine` (see [Libs/FSM/](Assets/Darkmatter/Code/Libs/FSM/)). `ColorBookFlowController` (planned) will use this. The generic sketch below is the target shape if you decide to make it strongly-typed via an enum — verify against actual API before consuming.
```csharp ```csharp
public sealed class Fsm<TState> where TState : struct, Enum { public sealed class Fsm<TState> where TState : struct, Enum {
public TState Current { get; } public TState Current { get; }
@@ -1461,7 +1466,7 @@ public interface IFsmState { void Enter(); void Exit(); }
--- ---
### 32.4 Feature — `DrawingCatalog` ### 32.4 Feature — `DrawingCatalog` *(planned)*
#### `DrawingCatalogController` *(Systems)* #### `DrawingCatalogController` *(Systems)*
Headless logic. Owns the list of template IDs visible in the grid. Headless logic. Owns the list of template IDs visible in the grid.
@@ -1498,7 +1503,7 @@ public interface IDrawingCatalogView {
--- ---
### 32.5 Feature — `ShapeBuilder` ### 32.5 Feature — `ShapeBuilder` *(planned)*
#### `ShapeBuilderController` *(Systems)* #### `ShapeBuilderController` *(Systems)*
Spawns shape pieces for the selected template, tracks snap progress, fires `ShapeAssembledSignal` when complete. Spawns shape pieces for the selected template, tracks snap progress, fires `ShapeAssembledSignal` when complete.
@@ -1537,7 +1542,7 @@ public sealed class ShapePieceFactory {
--- ---
### 32.5b Feature — `Paper` ### 32.5b Feature — `Paper` *(planned)*
The shared art rig — RT, offscreen camera, screen↔world bridge. Every other feature in the ColorBook scene resolves `IPaperRig` and `IArtInputBridge` from DI and never touches `Screen.*` or `Camera.*` directly. The shared art rig — RT, offscreen camera, screen↔world bridge. Every other feature in the ColorBook scene resolves `IPaperRig` and `IArtInputBridge` from DI and never touches `Screen.*` or `Camera.*` directly.
@@ -1608,7 +1613,7 @@ public void Register(IContainerBuilder builder) {
--- ---
### 32.6 Feature — `Coloring` ### 32.6 Feature — `Coloring` *(planned)*
#### `ColoringStateRepository` *(Repository)* #### `ColoringStateRepository` *(Repository)*
In-memory model. Owns "currently selected color" and the palette in use. In-memory model. Owns "currently selected color" and the palette in use.
@@ -1670,7 +1675,7 @@ Mirror of `ShapePieceFactory` for regions. Pool-friendly.
--- ---
### 32.7 Feature — `History` ### 32.7 Feature — `History` *(planned)*
#### `HistoryController` *(Systems)* — `IStartable, IDisposable` #### `HistoryController` *(Systems)* — `IStartable, IDisposable`
Owns the per-session `IUndoStack` (registered scoped, so a new ColorBook scene = new stack). Owns the per-session `IUndoStack` (registered scoped, so a new ColorBook scene = new stack).
@@ -1702,7 +1707,7 @@ Wires controller `StateChanged` ↔ view enable/disable; view click events → c
--- ---
### 32.8 Feature — `Capture` ### 32.8 Feature — `Capture` *(planned)*
#### `CaptureController` *(Systems)* #### `CaptureController` *(Systems)*
The orchestrator behind the "Capture" button. Stateless other than guarding against concurrent captures. The orchestrator behind the "Capture" button. Stateless other than guarding against concurrent captures.
@@ -1723,7 +1728,7 @@ Wires button click → `CaptureController.CaptureCurrentAsync`. Disables button
--- ---
### 32.9 Feature — `Progression` ### 32.9 Feature — `Progression` *(planned)*
#### `ProgressionService` *(Systems)* — implements `IProgressionService` #### `ProgressionService` *(Systems)* — implements `IProgressionService`
The only place that knows what "completed" means. The only place that knows what "completed" means.
@@ -1736,7 +1741,7 @@ Pure in-memory holder used by the service. Separated so tests can inspect state
--- ---
### 32.10 Feature — `ColorBookFlow` ### 32.10 Feature — `ColorBookFlow` *(planned)*
#### `ColorBookFlowController` *(Systems)* — `IStartable, IDisposable` #### `ColorBookFlowController` *(Systems)* — `IStartable, IDisposable`
**The only orchestrator inside the ColorBook scene.** Drives the panel FSM: `Catalog → Building → Coloring → Done`. **The only orchestrator inside the ColorBook scene.** Drives the panel FSM: `Catalog → Building → Coloring → Done`.
@@ -1764,7 +1769,7 @@ Pure in-memory holder used by the service. Separated so tests can inspect state
--- ---
### 32.11 Feature — `ArtBook` ### 32.11 Feature — `ArtBook` *(planned)*
#### `GalleryPresenter` *(UI)* — `IAsyncStartable, IDisposable` #### `GalleryPresenter` *(UI)* — `IAsyncStartable, IDisposable`
Lists artworks, opens fullscreen view, deletes, shares. Lists artworks, opens fullscreen view, deletes, shares.
@@ -1799,7 +1804,7 @@ public interface IExternalShareService {
### 32.12 App Layer ### 32.12 App Layer
#### `AppBoot` *(App/Boot)* — `IAsyncStartable` #### `AppBoot` *(App/Boot — planned; folder doesn't exist yet)* — `IAsyncStartable`
Single entry point. Steps in section 29. Single entry point. Steps in section 29.
```csharp ```csharp
// fields: IAssetProviderService _assets, IPersistenceService _persist, IProgressionService _progress, // fields: IAssetProviderService _assets, IPersistenceService _persist, IProgressionService _progress,
@@ -1810,25 +1815,29 @@ public sealed class AppBoot : IAsyncStartable {
``` ```
#### LifetimeScopes #### LifetimeScopes
- `RootLifetimeScope`section 21. Registers all services + `IEventBus`. Persists for app lifetime. - `RootLifetimeScope`✅ exists ([source](Assets/Darkmatter/Code/App/LifetimeScopes/RootLifetimeScope.cs)). Iterates a serialized `MonoBehaviour[] serviceModules` and calls `Register` on each `IServiceModule`. Persists for app lifetime.
- `MainMenuLifetimeScope`registers `MainMenuPresenter` and view. - `MainMenuLifetimeScope`planned. Same pattern as Root (serialized installer list, no hardcoded registrations).
- `ColorBookLifetimeScope`section 21. Registers feature installers + `ColorBookFlowController` as entry point. - `ColorBookLifetimeScope`planned. Same pattern; installer list includes `PaperRigModule`, feature installers, and the flow controller installer.
- `ArtBookLifetimeScope`registers `GalleryPresenter` + view + `IExternalShareService`. - `ArtBookLifetimeScope`planned.
All scope classes are thin: serialized fields for scene refs, `Configure(IContainerBuilder)` only. All scope classes are thin: a serialized installer-MonoBehaviour list (+ optional scene refs as separate fields) and a `Configure(IContainerBuilder)` that iterates and calls `Register`.
--- ---
### 32.13 Cross-cutting types ### 32.13 Cross-cutting types
#### `ColorBookSceneRefs : MonoBehaviour` *(App)* #### `ColorBookSceneRefs : MonoBehaviour` *(App — planned)*
Aggregates all scene-bound Unity references that features need: `Camera artCamera`, `Transform catalogRoot`, `Transform builderRoot`, `Transform coloringRoot`, `RectTransform hudRoot`, `ColorPaletteView paletteView`, `HistoryButtonsView historyView`. Registered as a singleton in `ColorBookLifetimeScope` so features don't `Find` things. Aggregates scene-bound Unity references that features need: `Camera artCamera`, `Transform catalogRoot`, `Transform builderRoot`, `Transform coloringRoot`, `RectTransform hudRoot`, `ColorPaletteView paletteView`, `HistoryButtonsView historyView`. Registered in `ColorBookLifetimeScope` via `builder.RegisterInstance(_sceneRefs)` so features don't `Find` things.
#### `IInstaller` *(App)* > Most of these refs are subsumed by `IPaperRig` now (which owns `ArtCamera` and `PaperRoot`). `ColorBookSceneRefs` reduces to the HUD-side refs (palette view, history buttons, panel roots).
#### `IServiceModule` *(Libs/Installers — ✅ exists)*
```csharp ```csharp
public interface IInstaller { void Install(IContainerBuilder builder); } public interface IServiceModule {
void Register(IContainerBuilder builder);
}
``` ```
Implemented as `ScriptableObject` per feature so scopes can drag them in the inspector (section 22). Implemented as `MonoBehaviour` per feature/service so scopes can drag them in the inspector ([CameraServiceModule.cs](Assets/Darkmatter/Code/Services/Camera/Installers/CameraServiceModule.cs) shows the pattern). The method is `Register`, not `Install` — there is no `IInstaller` in this project.
--- ---
@@ -1866,3 +1875,5 @@ Implemented as `ScriptableObject` per feature so scopes can drag them in the ins
| `ProgressionService` | Service | Completion tracking | persistence | | `ProgressionService` | Service | Completion tracking | persistence |
If you add a class not in this table, add it here in the same PR. This table is the cheap mental-model index — keep it honest. If you add a class not in this table, add it here in the same PR. This table is the cheap mental-model index — keep it honest.
> Today only these rows are real on disk: `RootLifetimeScope` (App), `AddressableAssetProviderService` (Service), `AudioService` (Service), `CameraService` (Service), `SceneService` (Service), `InputReaderSO` (Service), plus the Firebase analytics class, plus the `Libs.*` entries (`EventBus`, `StateMachine`, `IServiceModule`, PlayerPrefs lib, UI toggles). Everything else is the target.