Table of Contents

Class SceneTypeRegistry

Namespace
PopcorningGuineaPig.Engine.Scenes
Assembly
PopcorningGuineaPig.Engine.dll

Static lookup table that maps PGPSCN scene name strings to their concrete Scene subclass Type. Exists to make scene_transition action resolution trim-safe: the DynamicallyAccessedMembersAttribute on the registration generic flows through every call site, pinning the public parameterless constructor of every registered scene class so the .NET IL Trimmer cannot strip it.

Replaces the legacy GetType(string) + assembly-walk lookup that previously lived in SceneLoader.

Contract: the engine self-registers its own built-in scenes from the Game() base constructor (runs before the subclass ctor body, so a subclass can QueueScene a transition immediately and still resolve). Games using PGPSCN with scene_transition actions must register their own Scene subclasses at startup.

public static class SceneTypeRegistry
Inheritance
SceneTypeRegistry
Inherited Members

Methods

Clear()

Removes every entry from the registry. Intended for test setup/teardown only — production code should register once at startup.

public static void Clear()

ClearProjectTypes()

Story 7.1: removes every scene type registered via RegisterProjectSceneType(string, Type). Engine self-registrations from Game()'s base ctor stay intact. Called by the build pipeline before re-registering scene types from a freshly-loaded project assembly.

public static void ClearProjectTypes()

RegisterProjectSceneType(string, Type)

Story 7.1: register a scene type that came from the user's project assembly (hot-reloadable). Tracked separately from the engine's self-registrations so ClearProjectTypes() can wipe only the project subset on rebuild. Trim contract: the sceneType parameter carries DynamicallyAccessedMembersAttribute just like RegisterSceneType(string, Type) — Story 12.1 trim safety.

public static void RegisterProjectSceneType(string name, Type sceneType)

Parameters

name string
sceneType Type

RegisterSceneType(string, Type)

Register a scene type by name. The sceneType parameter is annotated with DynamicallyAccessedMembersAttribute so that callers passing a Type must themselves flow that annotation forward — this is what makes the registry trim-safe end-to-end.

Idempotent: registering the same Type under the same name twice is a no-op. Registering a different Type under an already-used name throws ArgumentException.

public static void RegisterSceneType(string name, Type sceneType)

Parameters

name string
sceneType Type

RegisterSceneType<T>(string)

Register a scene type by name. The generic T carries a DynamicallyAccessedMembersAttribute annotation so that the trimmer preserves T's public parameterless constructor on every call site.

public static void RegisterSceneType<T>(string name) where T : Scene

Parameters

name string

Type Parameters

T

TryResolve(string, out Type?)

Pure dictionary lookup. Returns true and the registered Type when name is registered, otherwise false and null.

The out parameter carries DynamicallyAccessedMembersAttribute so that the trimmer can flow the parameterless-constructor preservation from each RegisterSceneType<T>(string) call site forward to the CreateInstance(Type) caller (SceneLoader).

[UnconditionalSuppressMessage("Trimming", "IL2067", Justification = "ConcurrentDictionary<string, Type> cannot propagate the DAM annotation through its value slot, so the trimmer cannot see that the Type stored came from an annotated RegisterSceneType call site. The class invariant is that this is the only way Types enter _types: RegisterSceneType<T>() flows PublicParameterlessConstructor on T, and RegisterSceneType(string, Type) requires the same DAM on its Type parameter. The TryResolve out annotation is therefore load-bearing and the suppression is safe so long as no future code path bypasses RegisterSceneType to write into _types.")]
public static bool TryResolve(string name, out Type? sceneType)

Parameters

name string
sceneType Type

Returns

bool