30 KiB
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:
public struct Module {
public Action<FpsCounter, ModeEventDispatcher> Draw;
public Action<MouseButtons, Vector2D, Color> Down, Up, Move;
public Action Leave;
public Action<Vector2D> 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<byte[]>(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<BodyTemplate>() // 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
SetDefaultR()— initializes all PartGroup runtime fields to defaultsMigrateKeys()— replaces 20 Japanese keys inBodyTemplate.Difsswith English names- Type caching — iterates all
VariantGridkeys + race suffixes (人/猫/獣/鳥/蜘蛛/蜥蜴/魚/蛙/四足/水棲/半人鮫/竜/植物/巨人/妖精/兎/狐/熊/馬/鹿/狼/河馬/恐/牛/羊/鬼/亜人/機械/蛇/狗/黄金/冥府/冥界/天使/墮天使) and cachesType.GetType("BodyPartName_RaceSuffix")for each.
3.4 KeyMap (Runtime)
Defined in 2DGAMELIB/ObjExtensions.cs — 20 entries:
| Japanese | English |
|---|---|
| 咳 → Cough | 腰 → Waist |
| 頭 → Head | 後髪0 → BackHair0 |
| 脚 → Leg | 腕 → Arm |
| 下腕 → LowerArm | 上腕 → UpperArm |
| 鳥翼上腕/獣翼上腕/四足上腕 → 鳥翼UpperArm/獣翼UpperArm/四足UpperArm | |
| 鳥翼下腕/獣翼下腕/四足下腕 → 鳥翼LowerArm/獣翼LowerArm/四足LowerArm |
3.5 game_folder Runtime Assets
Copied to build output via .csproj:
<Content Include="..\game_folder\**\*" CopyToOutputDirectory="PreserveNewest" LinkBase="" />
Loaded at runtime:
- Text:
GameTextstatic ctor loadstext/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<string, VariantGrid> "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<MorphVariant> difs ← linear array [x * CountY + y]
│
└── MorphVariant [Serializable] (.Dif)
├── Tag : string
└── List<PartGroup> parss
│
└── PartGroup [Serializable] (.Pars)
├── Tag : string
├── Parent : PartGroup (runtime, non-serialized)
└── OrderedDictionary<string, object> 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<CurveOutline>
│ │ ├── ps : List<Vector2D> ← control points
│ │ ├── Tension : float ← cardinal spline
│ │ └── Outline : bool ← stroke-only?
│ ├── JP : List<JointPoint>
│ │ └── 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<PartGroup, List<Joint>>) — joints per PartGrouppr(Dictionary<PartGroup, ShapePart>) — the root ShapePart for each PartGroup's jointsJoinRoot— 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:
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():
// 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.尺度CandBelly.尺度Cusing a sine wave - Blinking: transitions
EyeL.Yv/EyeR.Yvto 1 (closed) then back - Cough: cycles
Cough.Xvthrough morph variants - Sway: oscillates body
角度B(Angle Base) - Eye tracking: sets
Head.角度Ctoward 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:
- Parse
Catalog.yaml→ discover all parts - For each part, load
part.yaml→ get morph dimensions, joints, fields, variant list - For active morph (Xv/Yv), load corresponding SVG → parse path data → extract control points
- 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:
- Cardinal spline → cubic Bezier conversion (already done in SVG export —
BuildSvgPathin Extract) - Tessellate cubic Bezier curves into triangles (or use GPU path rendering)
- Maintain the same transform chain:
localPoint → baseTransform → scale → rotate → translate → parentTransform → Unit - 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):
joints:
- position: [0.50, 0.47] # pre-computed world-space joint positions
- position: [0.48, 0.52]
Strategy:
- Define explicit parent-child joint connections in a race template YAML
- Match joint positions between adjacent parts (or name them explicitly)
JoinPA()equivalent: when parent rotates, propagate angle through the joint point offset
7.5 Morph Variant Generalization
Current: Discrete X/Y index into List<MorphVariant>. Selection via (int)(ValueX * (CountX-1)).
Target: Support both discrete selection and interpolation:
# interpolate between variant x0y0 and x0y1
morph:
x: 0.3 # selects x=0, interpolates 30% toward next X
y: 0.0
Strategy:
- Load both adjacent SVG variants
- Interpolate control point positions:
p = lerp(p_a, p_b, t) - 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 |