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
> **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()
│ fail → show "Tap to retry" splash
├─ 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)
> **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).
> Convention used below
@@ -1234,6 +1238,7 @@ Canonical breakdown of every concrete class and interface. For each: **purpose**
> - `// pub:` = events / signals fired
> - `// sub:` = events / signals consumed
> - 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.
#### `IDrawingTemplate` *(Core/Drawing)*
#### `IDrawingTemplate` *(Core/Contracts/Features/Drawing — planned)*
Immutable view of a single drawing's authored data.
```csharp
public interface IDrawingTemplate {
@@ -1255,7 +1260,7 @@ public interface IDrawingTemplate {
```
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.
```csharp
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`.
```csharp
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.
#### `IGalleryService` *(Core/Gallery)*
#### `IGalleryService` *(Core/Contracts/Services/Gallery — planned)*
Persistent store of saved artwork PNGs.
```csharp
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`.
```csharp
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.
```csharp
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.
```csharp
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.
#### `IProgressionService` *(Core/Progression)*
#### `IProgressionService` *(Core/Contracts/Features/Progression — planned)*
Tracks which templates the child has completed and what they last opened.
```csharp
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.
```csharp
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
public interface IEventBus {
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
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`.
- **Responsibility:** Wrap `Addressables.LoadAssetAsync<T>` and ref-count handles 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.
#### `FileGalleryService` *(Services/Gallery)*
#### `FileGalleryService` *(Services/Gallery — planned)*
Implements `IGalleryService`.
```csharp
// fields:
@@ -1380,13 +1385,13 @@ Implements `IGalleryService`.
- **List flow:** enumerate `*.json` in `Gallery/`, deserialize, sort by `CreatedUtc desc`.
- **Delete flow:** delete png + thumb + json; missing files ignored (idempotent).
#### `RenderTextureCaptureService` *(Services/Capture)*
#### `RenderTextureCaptureService` *(Services/Capture — planned)*
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.
- **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.
#### `JsonPersistenceService` *(Services/Persistence)*
#### `JsonPersistenceService` *(Services/Persistence — planned; today `Libs/PlayerPrefs` covers small-key state)*
Implements `IPersistenceService` (small JSON blob; not the gallery).
```csharp
public interface IPersistenceService {
@@ -1398,7 +1403,7 @@ public interface IPersistenceService {
- **Format:** single JSON object keyed by `key` so multiple services can share one file.
- **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.
```csharp
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.
```csharp
public interface IAudioService {
@@ -1418,7 +1423,7 @@ public interface IAudioService {
```
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.
```csharp
public interface IInputReader {
@@ -1435,19 +1440,19 @@ public interface IInputReader {
Generic, project-agnostic utilities.
#### `BoundedUndoStack` *(Libs/CommandStack)*
#### `BoundedUndoStack` *(Libs/CommandStack — planned)*
Implements `IUndoStack`. Source already in section 24.
- **Capacity:** default 20.
- **Invariant:** `_redo` cleared on any new `Push`.
- **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.
- **Subscribe** returns an `IDisposable` that removes the handler on `Dispose`.
- **Publish** snapshots the invocation list before iterating (so handlers may safely unsubscribe during dispatch).
#### `Fsm<TState>` *(Libs/FSM)*
Generic state machine used by `ColorBookFlowController`.
#### `StateMachine` / `IState` / `State` *(Libs/FSM — ✅ exists)*
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
public sealed class Fsm<TState> where TState : struct, Enum {
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)*
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)*
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.
@@ -1608,7 +1613,7 @@ public void Register(IContainerBuilder builder) {
---
### 32.6 Feature — `Coloring`
### 32.6 Feature — `Coloring` *(planned)*
#### `ColoringStateRepository` *(Repository)*
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`
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)*
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`
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`
**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`
Lists artworks, opens fullscreen view, deletes, shares.
@@ -1799,7 +1804,7 @@ public interface IExternalShareService {
### 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.
```csharp
// fields: IAssetProviderService _assets, IPersistenceService _persist, IProgressionService _progress,
@@ -1810,25 +1815,29 @@ public sealed class AppBoot : IAsyncStartable {
```
#### LifetimeScopes
- `RootLifetimeScope`section 21. Registers all services + `IEventBus`. Persists for app lifetime.
- `MainMenuLifetimeScope`registers `MainMenuPresenter` and view.
- `ColorBookLifetimeScope`section 21. Registers feature installers + `ColorBookFlowController` as entry point.
- `ArtBookLifetimeScope`registers `GalleryPresenter` + view + `IExternalShareService`.
- `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`planned. Same pattern as Root (serialized installer list, no hardcoded registrations).
- `ColorBookLifetimeScope`planned. Same pattern; installer list includes `PaperRigModule`, feature installers, and the flow controller installer.
- `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
#### `ColorBookSceneRefs : MonoBehaviour` *(App)*
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.
#### `ColorBookSceneRefs : MonoBehaviour` *(App — planned)*
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
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 |
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.