# Slave Matrix Internal Architecture A detailed technical analysis of how the program works from startup to rendering a character on screen, with focus on asset loading and generalization strategy. --- ## 1. Startup Pipeline ``` Program.Main() │ ├─ [STATIC INIT] Type initializer for GlobalState (before Main) │ └─ Program static cctor (#1) │ ├─ AppContext.SetSwitch("System.Drawing.EnableUnixSupport", true) │ └─ RemappedTypeBinder.RegisterMapping for 3 game types │ "SlaveMatrix.Ele" → Element │ "SlaveMatrix.EleD" → ElementData │ "SlaveMatrix.EleI" → ElementInstance │ ├─ GlobalState static cctor (#2) │ ├─ Sets CurrentDirectory = AppContext.BaseDirectory │ ├─ Loads 13 BodyTemplate Obj resources from embedded bytes │ │ Each: byte[] → BinaryFormatter→byte[] → BinaryFormatter→BodyTemplate │ ├─ MigrateKeys() — 20-entry KeyMap renames Japanese→English keys │ ├─ Caches 843 BodyPartClass Type objects for reflection-based Element creation │ ├─ Verifies type resolution (Type.GetType) for all race-part combos │ └─ Sets imiPath, panPath for onomatopoeia/moaning text directories │ ├─ Main() │ ├─ GlobalState.LoadConfig() — reads game_folder/Config.ini │ │ Booleans: BigWindow, HighQuality, ShowFPS, etc. │ │ │ ├─ Create ModeEventDispatcher │ │ ├─ UITitle = game title string │ │ ├─ Unit = scaling factor (2203 HQ / 1101.5 LQ) │ │ ├─ Base = Rectangle(4f, 3f, percent/100f) — aspect ratio + viewport │ │ ├─ DisQuality = 1.0 │ │ └─ HitAccuracy = 0.3 │ │ │ ├─ med.InitializeModes("Start", ModuleRegistry.GetMods) │ │ └─ GetMods callback registers 25+ screen modules via RegisterModule() │ │ │ └─ med.Drawing() — creates GLFW window, enters main loop, never returns │ └─ [MAIN LOOP] med.Drawing() ├─ GlImage.BitmapSetting(Display) │ ├─ GLFW 3.3 + OpenGL 3.3 Core profile window, size = Display bitmap dims │ ├─ Compiles vertex+ fragment shader (simple textured quad) │ ├─ Creates full-screen triangle-strip VAO/VBO │ └─ Sets up callbacks: Click, Move, Leave, Scroll, Resize → Module routing │ ├─ med.Setting(GlImage) │ ├─ Creates Display Bitmap (Base.LocalWidth * Unit × Base.LocalHeight * Unit px) │ ├─ Creates Hit Bitmap (same × HitAccuracy = 0.3) │ ├─ Creates SceneFader for crossfade transitions │ └─ Calls GetMods(this) → ModuleRegistry populates all Module delegates │ └─ while(Drive) ├─ FPSF.FPSFixed(action) — fixed 60 fps timestep │ └─ action: Modes[mode].Draw(FPSF) for active screen module ├─ baseControl.PollEvents() — GLFW event pump └─ baseControl.SetBitmap(Display) ├─ glTexSubImage2D(GDI+ Bitmap → OpenGL texture) ├─ glDrawArrays(TriangleStrip, 0, 4) └─ Glfw.SwapBuffers(window) ``` ### Key files | Step | File | Lines | |------|------|-------| | Program.Main | `SlaveMatrix/GameClasses/Program.cs` | 18-43 | | GlobalState static init | `SlaveMatrix/GameClasses/GlobalState.cs` | 1087-1429 | | ModeEventDispatcher ctor | `2DGAMELIB/ModeEventDispatcher.cs` | 78-99 | | Drawing() loop | `2DGAMELIB/ModeEventDispatcher.cs` | 290-325 | | Setting() | `2DGAMELIB/ModeEventDispatcher.cs` | 101-232 | | GlImage.BitmapSetting | `2DGAMELIB/WPFImage.cs` | 146-238 | | GlImage.SetBitmap | `2DGAMELIB/WPFImage.cs` | 99-144 | | ModuleRegistry.GetMods | `SlaveMatrix/GameClasses/ModuleRegistry.cs` | 204-493 | --- ## 2. Module System (Screen Management) Each "screen" is a `Module` struct — a set of delegate callbacks: ```csharp public struct Module { public Action Draw; public Action Down, Up, Move; public Action Leave; public Action Wheel; public Action Setting; public Action Dispose; } ``` Registered via `ModeEventDispatcher.RegisterModule(string name, Module mod)`. 25 modules include: | Module Name | Purpose | |-------------|---------| | `Start` | Initial screen | | `Title` | Title screen | | `Credit` | Credits | | `メインフォーム` (MainForm) | Primary HUD/gameplay | | `対象` (Target) | Character target selection | | `Training` | Training/interaction scene | | `Blessing`, `Office` | Other gameplay scenes | | `Debt` | Debt management | | `SlaveShop`, `ToolShop` | Shop screens | | `PlayerInformation` | Player status | | `OP0`, `OP1`, `説明`, `初事務所` | Event scenes | | `RepaymentEvent1-3` | Story events | **Mode switching**: `ModeEventDispatcher.Mode = name` calls `Leave` on the old module and `Setting` on the new module. **Module draw delegates** are defined inline in `ModuleRegistry.GetMods()` — typically compositing multiple `RenderArea` layers, characters, and UI elements. --- ## 3. Asset Loading Architecture ### 3.1 The 13 Binary Resources Embedded as `byte[]` in `SlaveMatrix/Properties/Resources.resx`, accessed via `Resources.xxx`: | # | Resource Name | Contents (after MigrateKeys) | |---|---------------|------------------------------| | 1 | `Resources.胴体` | Torso, Waist, Neck, Head, Chest, BackHair0/1, SideHair, etc. | | 2 | `Resources.肩左` | Shoulder variants | | 3 | `Resources.腕左` | Arm, UpperArm, LowerArm, + wing/beast/quadruped variants | | 4 | `Resources.脚左` | Leg variants | | 5 | `Resources.尻尾` | Tail variants | | 6 | `Resources.半身` | Half-body composites | | 7 | `Resources.肢左` | Limb variants | | 8 | `Resources.肢中` | Middle limb variants | | 9 | `Resources.性器` | Genital variants | | 10 | `Resources.性器付` | Genitals with attachments | | 11 | `Resources.スタンプ` | Stamp/stencil overlays | | 12 | `Resources.カーソル` | Cursor graphics | | 13 | `Resources.その他` | Miscellaneous | | — | `Resources.タイル` | Tile/background patterns | ### 3.2 Deserialization Pipeline ``` byte[] raw = Resources.胴体 │ ├─ Serializer.Load(raw) // FIRST deserialization │ └─ new BinaryFormatter { Binder = RemappedTypeBinder } │ .Deserialize(new MemoryStream(raw)) │ └─ RemappedTypeBinder translates: │ _2DGAMELIB.Obj → BodyTemplate (outer layer is Obj wrapping a byte[]) │ └─ Result: byte[] innerData │ └─ innerData.ToDeserialObject() // SECOND deserialization └─ new BinaryFormatter { Binder = RemappedTypeBinder } .Deserialize(new MemoryStream(innerData)) └─ RemappedTypeBinder translates: _2DGAMELIB.Obj → BodyTemplate _2DGAMELIB.Difs → VariantGrid _2DGAMELIB.Dif → MorphVariant _2DGAMELIB.Pars → PartGroup _2DGAMELIB.Par → ShapePart _2DGAMELIB.ParT → ShapePartT _2DGAMELIB.Out → CurveOutline _2DGAMELIB.Joi → JointPoint └─ Result: BodyTemplate with full object graph ``` The **double-wrapping** is a legacy artifact: the `.resx` stores the data as `byte[]`, but the original source wrapped a `byte[]` containing a serialized `BodyTemplate` inside another `BinaryFormatter` envelope. ### 3.3 Post-Deserialization 1. **`SetDefaultR()`** — initializes all PartGroup runtime fields to defaults 2. **`MigrateKeys()`** — replaces 20 Japanese keys in `BodyTemplate.Difss` with English names 3. **Type caching** — iterates all `VariantGrid` keys + race suffixes (人/猫/獣/鳥/蜘蛛/蜥蜴/魚/蛙/四足/水棲/半人鮫/竜/植物/巨人/妖精/兎/狐/熊/馬/鹿/狼/河馬/恐/牛/羊/鬼/亜人/機械/蛇/狗/黄金/冥府/冥界/天使/墮天使) and caches `Type.GetType("BodyPartName_RaceSuffix")` for each. ### 3.4 KeyMap (Runtime) Defined in `2DGAMELIB/ObjExtensions.cs` — 20 entries: | Japanese | English | |----------|---------| | 咳 → Cough | 腰 → Waist | 胴 → Torso | 首 → Neck | | 頭 → Head | 後髪0 → BackHair0 | 後髪1 → BackHair1 | 横髪 → SideHair | | 脚 → Leg | 腕 → Arm | 肩 → Shoulder | 胸 → Chest | | 下腕 → LowerArm | 上腕 → UpperArm | | 鳥翼上腕/獣翼上腕/四足上腕 → 鳥翼UpperArm/獣翼UpperArm/四足UpperArm | | 鳥翼下腕/獣翼下腕/四足下腕 → 鳥翼LowerArm/獣翼LowerArm/四足LowerArm | ### 3.5 game_folder Runtime Assets Copied to build output via `.csproj`: ```xml ``` Loaded at runtime: - **Text**: `GameText` static ctor loads `text/System/Race.txt`, `Attribute.txt`, `Common.txt`, and scene-specific text - **Onomatopoeia/Moaning**: `GlobalState.Set擬音()` → `Imitation.txt`; `Set喘ぎ()` → `Pant/*.txt` - **Config**: `game_folder/Config.ini` - **BGM**: Expected in `bgm/` (currently commented out in code) - **Saves**: `save/*.sav` (BinaryFormatter) or `.json` - **Background images**: *loaded from embedded resources*, not game_folder (e.g., `Resources.dangeon01_ex2`) --- ## 4. Data Model ### 4.1 Hierarchy ``` BodyTemplate [Serializable] └── OrderedDictionary "Difss" ├── Key: "Waist", "Torso", "Neck", "Head", ... │ └── VariantGrid [Serializable] (.Difs) ├── CountX : int ← morph grid width (ValueX axis) ├── CountY : int ← morph grid height (ValueY axis) ├── ValueX : double ← current X selection (0..1 → index) ├── ValueY : double ← current Y selection (0..1 → index) ├── PositionSize : Rectangle ← inherited from parent template ├── PositionVector : Vector2D ├── AngleBase : double ├── SizeBase : double └── List difs ← linear array [x * CountY + y] │ └── MorphVariant [Serializable] (.Dif) ├── Tag : string └── List parss │ └── PartGroup [Serializable] (.Pars) ├── Tag : string ├── Parent : PartGroup (runtime, non-serialized) └── OrderedDictionary pars ├── Key: "childPartName" │ ├── ShapePart [Serializable] (.Par) │ ├── Dra : bool ← visibility │ ├── Closed : bool │ ├── PenWidth : double │ ├── BasePoint : Vector2D ← local origin │ ├── Position : Vector2D ← translation │ ├── Angle : double ← rotation │ ├── Size : double ← uniform scale │ ├── SizeX / SizeY : double ← non-uniform scale │ ├── HitColor : Color ← unique per part │ ├── OP : List │ │ ├── ps : List ← control points │ │ ├── Tension : float ← cardinal spline │ │ └── Outline : bool ← stroke-only? │ ├── JP : List │ │ └── Joint : Vector2D ← attachment point │ ├── Brush : Brush (runtime, [JsonIgnore]) │ └── Pen : Pen (runtime, [JsonIgnore]) │ ├── ShapePartT [Serializable] (.ParT) │ └── extends ShapePart │ ├── Text : string │ ├── FontSize : double │ └── Font : Font (runtime) │ └── PartGroup (recursive nesting) ``` ### 4.2 Coordinate System - **Local space**: points in `CurveOutline.ps[]` — normalized 0..1 range - **Part space**: transformed by `BasePoint`, `Position`, `Angle`, `Size/SizeX/SizeY` - **Parent space**: transformed by parent chain (PartGroup hierarchy) - **VariantGrid space**: further transformed by `VariantGrid.PositionVector`, `AngleBase`, `SizeBase` - **Screen space**: multiplied by `Unit` (2203 or 1101.5) ### 4.3 Joint System `SetJoints()` on `BodyTemplate` builds: - **`pj`** (`Dictionary>`) — joints per PartGroup - **`pr`** (`Dictionary`) — the root ShapePart for each PartGroup's joints - **`JoinRoot`** — identifies the anchor point in parent space `JoinPA()` propagates angle changes through the chain: ``` Parent.Angle → drives → Child.Position offset via joint point ``` ### 4.4 Morph Variant Selection `VariantGrid.ValueX` (0..1) → `indexX = Clamp((int)(ValueX * (CountX - 1)), 0, CountX - 1)` `VariantGrid.ValueY` (0..1) → `indexY = Clamp((int)(ValueY * (CountY - 1)), 0, CountY - 1)` Current MorphVariant: `difs[indexX * CountY + indexY]` Current PartGroup: `Current.parss[IndexY]` — then draws all children This means X axis iterates across `difs[]` while Y iterates within a `MorphVariant.parss[]`. The first entry (Y=0) of the current X gives the active PartGroup tree. --- ## 5. Rendering Pipeline (Per-Frame) ### 5.1 Compositing Layers ``` [Module.Draw(FPSF)] │ ├─ Med.HitGraphics.Clear(Color.Transparent) │ ├─ a.Draw(BasementBackground) ← background layer (embedded bitmap) │ └─ RenderArea.Draw(RenderArea other) │ └─ DisplayGraphics.DrawImage(other.DisplayLayer, ...) │ ├─ TrainingTarget.Draw(a, FPS) ← character layer │ └─ Character.Draw(Area, FpsCounter) │ ├─ bs.Draw(a) ← UI button layer ├─ dbs.Draw(a) ← bottom button layer ├─ ip.Draw(a, FPS) ← info panel layer ├─ SaveData.Draw(a) ← save data overlay │ └─ Med.Draw(a) ← composite to main display └─ RenderArea.DrawTo(Med.Display, Med.Hit) └─ DisplayGraphics.DrawImage(a.DisplayLayer, 0, 0) └─ HitGraphics.DrawImage(a.HitLayer, 0, 0) ``` ### 5.2 Character Draw ``` Character.Draw(Area, FPS) ├─ Motions.Drive(FPS) — update all animation state │ ├─ Breathing: oscillates Chest/Abdomen size │ ├─ Blinking: triggers Eye morph (Xv/Yv → closed) │ ├─ Tear/Cum/Squirt/Urination: fluid system updates │ ├─ Sway: body angle oscillation │ ├─ Eye tracking: head angle toward cursor │ ├─ Cough/Moan: variant cycling │ └─ User-defined morph motions │ └─ Body.描画(Area) ├─ 接続PA() — propagate parent angles through joint chains │ └─ For each Element: Element.Body.JoinPA() │ └─ VariantGrid.JoinPA() recurses PartGroups │ └─ ShapePart.Rotate() updates child positions │ ├─ Color updates: skin/dress/wing membrane/etc. ├─ ElementInstance updates │ └─ Draw(Area) delegate └─ Elements sorted by 描画前後 (back-to-front) ├─ Element.描画0(Are) — main body │ └─ VariantGrid.Draw(Are) │ └─ Are.Draw(Current PartGroup) │ └─ PartGroup.Draw(Unit, Graphics) │ └─ for each child in pars: │ ├─ if ShapePart + Dra: │ │ ShapePart.Draw(Unit, Graphics) │ ├─ if ShapePartT: │ │ ShapePartT.DrawString(Unit, Graphics) │ └─ if PartGroup: │ recursive PartGroup.Draw() │ ├─ Element.描画1(Are) — overlay layer 1 └─ Element.描画2(Are) — overlay layer 2 ``` ### 5.3 ShapePart.Draw() ``` ShapePart.Draw(double Unit, Graphics g) ├─ if (Edit flag) → Calculation(Unit): │ ├─ BaseTransform = -BasePoint * Size (shifts to origin) │ ├─ Position += ParentChain offset │ ├─ Angle += ParentChain angle │ ├─ Size *= ParentChain scale │ ├─ For each CurveOutline: │ │ └─ Transform points through: base → scale → rotate → translate │ ├─ Build GraphicsPath.Path via AddCurve(pointArray, tension) │ ├─ Build GraphicsPath.OutlinePath for stroke-only curves │ └─ Clear Edit flag │ ├─ Brush.Color = resolve runtime color (from Element.ColorSet) ├─ g.FillPath(Brush, Path) └─ if (Outline curves exist) → g.DrawPath(Pen, OutlinePath) ``` ### 5.4 Hit Detection Rendered on a separate lower-resolution `Hit` Bitmap. Each `ShapePart` has a unique `HitColor`. Module mouse callbacks check the pixel color under the cursor: ```csharp Color hit = Med.Hit.GetPixel((int)(pos.X * HitAccuracy), (int)(pos.Y * HitAccuracy)); // match hit to Element via HitColor → find which part was clicked ``` ### 5.5 RenderArea Hierarchy ``` RenderArea : Rectangle ├── DisplayLayer : Bitmap (full-res, visible output) ├── HitLayer : Bitmap (low-res, hit detection) ├── DisplayGraphics : Graphics (wraps DisplayLayer) ├── HitGraphics : Graphics (wraps HitLayer) ├── Draw(ShapePart) → renders to both layers ├── Draw(PartGroup) → recursive render ├── Draw(RenderArea) → composite another area onto this one └── DrawTo(display, hit) → final composite to Med.Display/Med.Hit ManagedArea : RenderArea └── Lower-resolution render target for character body (3x3 internal cells) ``` --- ## 6. Character System ### 6.1 Element Class Each `Element` wraps a single `VariantGrid` from a BodyTemplate resource. 843 Element subclasses in `BodyPartClasses/` define concrete body parts with race-specific behavior. ``` Element [Serializable] ├── 本体 : VariantGrid ← the template data ├── 位置B / 位置C : Vector2D ← position base/contract ├── 角度B / 角度C : double ← angle base/contract ├── 尺度B / 尺度C : double ← scale base/contract ├── Xv / Yv : double ← morph variant selection (drives ValueX/Y) ├── 描画前後 : int ← render order (back:0, middle:1, front:2) ├── 接続Type : int ← joint connection type ├── ColorSlot : int ← which color set to use ├── 拡張 : OrderedDictionary ← extension data │ ├── 描画0(Are) → 本体.Draw(Are) ← main render ├── 描画1(Are) → 本体.Draw(Are) ← overlay 1 └── 描画2(Are) → 本体.Draw(Are) ← overlay 2 ``` ### 6.2 Element Construction via Reflection In `Body` constructor, Elements are instantiated by `Type.GetType()`: ```csharp // Simplified: string typeName = $"_{partKey}_{raceSuffix}"; // e.g., "Head_人" Type t = GlobalState.BodyTypeCache[typeName]; Element ele = (Element)Activator.CreateInstance(t); ele.本体 = GlobalState.BodyTemplates[resourceName].Difss[partKey]; ``` 843 files mean 843 `Type` lookups. The reflection names use **original Japanese** keys (pre-MigrateKeys) for the `_人/猫/etc` suffix convention. ### 6.3 Body Class ``` Body ├── Elements : Element[] ← flat array of all parts ├── Strongly-typed fields: │ Waist, Torso, Chest, Neck, Head, │ BackHair0, BackHair1, SideHair, BaseHair, FrontHair, │ EyeL, EyeR, Nose, Mouth, EyebrowL, EyebrowR, │ BreastL, BreastR, Belly, │ Genitals, Anus, │ UpperArmL/R, LowerArmL/R, HandL/R, │ ShoulderL/R, │ UpperLegL/R, LowerLegL/R, FootL/R, │ WingL/R, Tail, │ etc. (~80 fields) │ ├── 接続PA() — joint angle propagation ├── 描画(Area) — main render entry └── Draw(Area) delegate — sorted Element rendering ``` ### 6.4 Character Class ``` Character ├── Body : Body ├── Motions : Motions ← animation controller ├── FluidSystem : CharacterFluidSystem ├── CharacterData : CharacterData ← race, colors, stats │ ├── Draw(Area, FPS) → Body.描画(Area) └── Motions.Drive(FPS) — updates all animation state ``` ### 6.5 Animation System (Motions) The `Motions` class manages a collection of `Motion` objects. Each `Motion` modifies Element properties over time: - **Breathing**: oscillates `Chest.尺度C` and `Belly.尺度C` using a sine wave - **Blinking**: transitions `EyeL.Yv` / `EyeR.Yv` to 1 (closed) then back - **Cough**: cycles `Cough.Xv` through morph variants - **Sway**: oscillates body `角度B` (Angle Base) - **Eye tracking**: sets `Head.角度C` toward cursor position - **Fluid drip**: tears, drool, cum, squirt, urination — updates fluid system - **Climax**: full-body spasm (randomized element position/angle jitter) Each `Motion` implements `Drive(FPS)` which time-samples a curve/function and applies deltas to `Element.Xv`, `Yv`, `位置B/C`, `角度B/C`, `尺度B/C`. --- ## 7. Generalization Strategy ### 7.1 Replace BinaryFormatter (Data Layer) **Current**: `byte[] → BinaryFormatter→byte[] → BinaryFormatter→BodyTemplate` **Target**: Load from structured files. Extraction is already done via `SlaveMatrix.Extract`: ``` Embedded .resx bytes ──[Extract CLI]──▶ extracted/*.json (full template data) Assets/Parts/{id}/part.yaml (per-part metadata) Assets/Parts/{id}/x{y}x{y}.svg (variant curves) Assets/Catalog.yaml (runtime index) ``` **Strategy**: 1. Parse `Catalog.yaml` → discover all parts 2. For each part, load `part.yaml` → get morph dimensions, joints, fields, variant list 3. For active morph (Xv/Yv), load corresponding SVG → parse path data → extract control points 4. Rebuild `ShapePart`-equivalent geometry from SVG path data ### 7.2 Replace GDI+ (Rendering Layer) **Current**: `System.Drawing.Graphics.FillPath/DrawPath` on GDI+ `GraphicsPath` built via `AddCurve(points, tension)`. **Target**: Vulkan/Silk.NET (or any modern GPU API). **Strategy**: 1. Cardinal spline → cubic Bezier conversion (already done in SVG export — `BuildSvgPath` in Extract) 2. Tessellate cubic Bezier curves into triangles (or use GPU path rendering) 3. Maintain the same transform chain: ``` localPoint → baseTransform → scale → rotate → translate → parentTransform → Unit ``` 4. Replace hit-testing: render with unique color IDs to offscreen buffer, sample pixel ### 7.3 Critical Data to Preserve ``` ShapePart (or equivalent): - CurveOutline[] → Points[] (local coords), Tension, Outline flag - Closed → fill vs stroke - BasePoint → local origin - Position → translation in parent space - Angle → rotation - Size, SizeX, SizeY → scale - Joints → attachment positions in local coords - Dra → visibility - HitColor → unique ID for hit testing PartGroup (or equivalent): - Tree hierarchy (ordered children) - Parent reference VariantGrid (or equivalent): - CountX, CountY → morph grid dimensions - ValueX, ValueY → current selection → (xIndex, yIndex) - PositionVector, AngleBase, SizeBase → root transform MorphVariant (or equivalent): - Per-variant PartGroup tree ``` ### 7.4 Joint System Generalization Current: `SetJoints()` builds proximity-based joint dictionaries. PartGroups have `JointPoint` lists that define connection anchors. Target: Explicit joint definitions in YAML (already in extracted `part.yaml`): ```yaml joints: - position: [0.50, 0.47] # pre-computed world-space joint positions - position: [0.48, 0.52] ``` **Strategy**: 1. Define explicit parent-child joint connections in a race template YAML 2. Match joint positions between adjacent parts (or name them explicitly) 3. `JoinPA()` equivalent: when parent rotates, propagate angle through the joint point offset ### 7.5 Morph Variant Generalization Current: Discrete X/Y index into `List`. Selection via `(int)(ValueX * (CountX-1))`. Target: Support both discrete selection and interpolation: ```yaml # interpolate between variant x0y0 and x0y1 morph: x: 0.3 # selects x=0, interpolates 30% toward next X y: 0.0 ``` **Strategy**: 1. Load both adjacent SVG variants 2. Interpolate control point positions: `p = lerp(p_a, p_b, t)` 3. Rebuild path geometry from interpolated points ### 7.6 Suggested Implementation Order ``` Phase 1: Data layer ├── JSON/YAML deserializer for extracted assets ├── BodyTemplate/VariantGrid/MorphVariant ⇒ plain C# records └── replaces BinaryFormatter dependency Phase 2: Rendering backend ├── Curve tessellator (cardinal spline → bezier → triangles) ├── Transform chain (preserve hierarchy logic) ├── Hit detection (offscreen ID buffer) └── ShapePart.Draw equivalent in new backend Phase 3: Character assembly ├── Joint system (explicit YAML connections) ├── Element system (part instance with morph state) ├── Animation (Motion/Motions port) └── Character.Draw equivalent Phase 4: Migration ├── Port BodyPartClasses → data-driven definitions ├── Port UI system → new rendering backend ├── Replace Module system → scene graph └── Wire game logic (training, shops, events) ``` --- ## Appendix: Key File Index | File | Role | |------|------| | `SlaveMatrix/GameClasses/Program.cs` | Entry point, static cctor, Main | | `SlaveMatrix/GameClasses/GlobalState.cs` | Global static state, template loading, type cache | | `SlaveMatrix/GameClasses/ModuleRegistry.cs` | Module definitions, UI, game initialization | | `SlaveMatrix/GameClasses/Character.cs` | Character class + animation | | `SlaveMatrix/GameClasses/Body.cs` | Body assembly + rendering | | `SlaveMatrix/GameClasses/Element.cs` | Element base class (VariantGrid wrapper) | | `SlaveMatrix/GameClasses/ElementInstance.cs` | Runtime Element instance | | `SlaveMatrix/GameClasses/ElementData.cs` | Serializable Element data | | `SlaveMatrix/GameClasses/GameText.cs` | Game text loader | | `SlaveMatrix/BodyPartClasses/*.cs` | 843 concrete Element subclasses | | `2DGAMELIB/ModeEventDispatcher.cs` | Main loop, mode switching, GLFW integration | | `2DGAMELIB/WPFImage.cs` | GLFW window, OpenGL texture upload (GlImage) | | `2DGAMELIB/RenderArea.cs` | Offscreen render buffer (display + hit) | | `2DGAMELIB/ManagedArea.cs` | Lower-res render area | | `2DGAMELIB/SceneFader.cs` | Crossfade transition | | `2DGAMELIB/Module.cs` | Module delegate struct | | `2DGAMELIB/BodyTemplate.cs` | Top-level template container | | `2DGAMELIB/VariantGrid.cs` | Morph variant grid | | `2DGAMELIB/MorphVariant.cs` | Morph variant (PartGroup list) | | `2DGAMELIB/PartGroup.cs` | Part group tree node | | `2DGAMELIB/ShapePart.cs` | Drawable shape (curves, joints, transforms) | | `2DGAMELIB/ShapePartT.cs` | Text-rendering shape | | `2DGAMELIB/CurveOutline.cs` | Cardinal spline curve data | | `2DGAMELIB/JointPoint.cs` | Joint anchor point | | `2DGAMELIB/Joints.cs` | Joint connection management | | `2DGAMELIB/OrderedDictionary.cs` | Serializable ordered dictionary | | `2DGAMELIB/Vector2D.cs` | 2D vector struct | | `2DGAMELIB/Serializer.cs` | BinaryFormatter + JSON serialization | | `2DGAMELIB/RemappedTypeBinder.cs` | Legacy type name remapping for BinaryFormatter | | `2DGAMELIB/ObjExtensions.cs` | KeyMap + MigrateKeys | | `2DGAMELIB/GeometryUtils.cs` | ObjLoad/ObjLoadRaw extension methods | | `2DGAMELIB/Motion.cs` | Single animation motion | | `2DGAMELIB/Motions.cs` | Motion collection controller | | `2DGAMELIB/FpsCounter.cs` | Fixed-timestep FPS lock | | `SlaveMatrix.Extract/Program.cs` | Asset extraction CLI (BinaryFormatter→JSON/SVG/YAML) | | `SlaveMatrix/Properties/Resources.resx` | Embedded resource manifest | | `SlaveMatrix/Properties/Resources.Designer.cs` | Strongly-typed resource accessors | | `SlaveMatrix/Resources/*` | Raw binary resource files | | `game_folder/` | Runtime assets (text, bgm, save, config) | | `Assets/Catalog.yaml` | Generated global catalog | | `Assets/Parts/{id}/` | Generated per-part SVG+YAML |