Skip to content

Add [TypeSelector] dropdown for [SerializeReference] and type repair#49

Draft
VPDPersonal wants to merge 186 commits into
mainfrom
feature/serialize-reference-dropdown
Draft

Add [TypeSelector] dropdown for [SerializeReference] and type repair#49
VPDPersonal wants to merge 186 commits into
mainfrom
feature/serialize-reference-dropdown

Conversation

@VPDPersonal

@VPDPersonal VPDPersonal commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Summary

Extends [TypeSelector] to [SerializeReference] and adds a full authoring + integrity toolkit for managed references. Every row works in both IMGUI and UIToolkit.

Area What it does
Picker on [SerializeReference] Hierarchical type dropdown on single / array / List<T> fields. Pick → instantiate, <None> → clear, the instance's nested props draw inline. Candidates default to the declared type, narrowed by [TypeSelector(typeof(IMelee))].
Open generics Offers Modifier<T>; arguments are inferred from a closed-generic field or picked in a follow-up window honouring constraints.
Editing Matching data preserved on type switch; Copy/Paste between compatible fields; multi-object edit applies one instance per object in a single Undo group.
Picker UX [TypeSelectorItem] (display name / Category/Name / tooltip / order / icon); per-project Favorites ★ + Recent; collapsible groups with in-header search.
Missing-type repair Reads the orphaned type straight from YAML (works around UUM-129100). Inline Fix re-points the ref and keeps its data — at any nesting depth, for saved assets, Prefab Mode and saved scenes. Smart Fix ranks the likeliest replacement for a one-click apply.
Aliased refs Make Unique action + deterministic per-rid colour stripes for shared instances.
FastTools window One workbench opened from Tools → Aspid 🐍 → FastTools (entries: Welcome / Asset References / Project References / Settings, also rebindable shortcuts). Tabs: Welcome (overview + installable samples), Asset References (whole graph from YAML — MISSING / SHARED badges, orphans, inline Fix, Open Source Prefab), Project References (project sweep grouped by broken type, Fix all with YAML diff preview, per-fix receipts with Undo, deep-links into Asset References) and Settings.
Editor theming Project-level theme override (AspidThemeSettings + Project Settings page) that re-skins every Aspid FastTools editor view; a reusable AspidWindowFooter (version + GitHub link) is pinned to the bottom of the window.
Project tooling Incremental usage index → Find Usages + sr: Quick Search; delete-script guard; proactive breakage notification; build/CI gate (SerializeReferenceCiGate.RunCheck); required-field gate via [TypeSelector(Required = true)]; Project Settings page.
Authoring Drag a MonoScript onto a field; named templates; Link to Existing; picker-backed list +; Create New Script.
Sample / docs / tests SerializeReferences sample (weapons/effects, melee/ranged types, generic Modifier<T>, broken/shared demo prefabs) with a step-by-step tutorial (TypeSelectorTutorial scene + TUTORIAL.md EN/RU); README EN/RU + Documentation + CHANGELOG; first EditMode test assembly (Aspid.FastTools.Unity.Editor.Tests).

Notes for review

Linked issues

Closes #10

… drawer

Add a hierarchical type-selector dropdown for [SerializeReference] fields
(single, array and List<T>), reusing TypeSelectorWindow. Picking a concrete
type instantiates it, <None> clears the reference, the assigned instance's
nested properties are drawn inline under a foldout, and an unresolved stored
type is surfaced as a missing-type warning. Implemented for both IMGUI and
UIToolkit inspectors.

TypeSelectorWindow.Show gains an optional candidate-type filter (backward
compatible) used to exclude UnityEngine.Object, open generics, strings and
delegates.
Add a loadout-system sample exercising [SerializeReferenceSelector]: single
IWeapon field, List<IWeapon>, abstract StatusEffect base, and a nested
[SerializeReference] inside Railgun. Includes an IMGUILoadout + forcing editor
to demonstrate the IMGUI path, EN/RU README, and a package.json sample entry.
Add Loadout.prefab (UIToolkit) and IMGUILoadout.prefab (IMGUI) with pre-filled
managed references — single (Railgun + nested BurnEffect), List<IWeapon>
([Pistol, Shotgun]) and abstract-base (FreezeEffect / BurnEffect) — so the
sample can be inspected without building it by hand. Update the EN/RU sample
README "How to run" to drive the prefabs.
- Offer open generic definitions (e.g. Modifier<T>) as candidates: infer
  arguments from a closed-generic field, or resolve them in a new
  recursive, constraint-aware GenericArgumentSelectorWindow, validating
  the closed type against the field before assignment. Works in IMGUI and UIToolkit.
- Add an optional additionalTypes pass-through to TypeSelectorWindow /
  HierarchyBuilder / TypeInfo, and render generic names as Modifier<T>.
- Add a non-abstract Modifier<T> hierarchy (IModifier) with closed-generic
  subclasses, plus IModifier / Modifier<float> / List<IModifier> fields on
  Loadout and IMGUILoadout to exercise open-generic selection and the T picker.
- Document the generic flow in the sample README (EN/RU).
- Note open-generic support and the new additionalTypes parameter in the
  CHANGELOG, and add a generic bullet to the feature section of all four READMEs.
…he dropdown

- Resolve open generics inside TypeSelectorWindow as in-window argument pages (hierarchy, search, breadcrumb, live preview), removing the separate GenericArgumentSelectorWindow and its focus issues
- Extract generic resolution into GenericTypeResolver and add an argumentFilter parameter to TypeSelectorWindow.Show; the flow stays dormant unless open generics are present
- Format generic type names recursively so nested closed generics render fully (Modifier<Modifier<Int32>>)
- Resolve the generic type definition when locating a script so Open Script works for closed generics
@VPDPersonal VPDPersonal added type: feature New feature or capability status: work-in-progress Draft / not ready for review area: runtime Runtime / player code area: editor Editor-only code area: samples Sample projects labels Jun 7, 2026
VPDPersonal and others added 10 commits June 7, 2026 21:07
…eric argument selector

Open generic definitions reach the selector through the additionalTypes
path, which bypasses the name and CompilerGeneratedAttribute checks
applied to ordinary candidates. As a result anonymous types and closure
display classes (e.g. <>c__11<T>, <>f__AnonymousType0<...>) showed up as
argument candidates and bloated the unconstrained (object) list.

Exclude compiler-generated types in IsAssignableGenericDefinition so the
single gate for generic definitions filters them out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Carry the foldout caption on the toggle's aligned BaseField label so the
  type dropdown starts at the inspector value column, matching SerializableType
- Centre the header row so the open-script button lines up with the dropdown
- Split the dropdown into field/input nodes and cancel the EnumField caption's
  -2px left margin so the text indents like SerializableType
…/paste

- CreateInstancePreservingData carries matching [SerializeField] data across a
  type switch via JsonUtility ToJson/FromJsonOverwrite, instead of resetting
- SerializeReferenceClipboard backs a header right-click Copy/Paste menu scoped
  to the field (IMGUI ContextClick + UIToolkit ContextualMenuManipulator); paste
  builds an independent instance and is disabled when the type is not assignable
… references

- Add an Edit Type action to the missing-type warning: it opens an
  Assembly/Namespace/Class editor and rewrites the stored managed-reference
  type straight into the asset YAML (parser-free, no external deps), since
  Unity cannot reassign a missing reference through the serialization API.
  Applies to ScriptableObjects — the only assets where Unity preserves missing
  references (UUM-129100).
- Detect an aliased managed reference (two fields sharing one instance) and
  offer a Make Unique Reference action that clones it into an independent copy.
- Sample: add a WeaponPreset ScriptableObject with a pre-broken asset, plus
  shared-reference and missing-type demo prefabs, and document how to test both.
…YAML

- Replace the manual Edit-Type window with a Fix button that opens the existing
  hierarchical type picker; the chosen type is rewritten into the asset YAML.
- Read the missing type straight from the asset file (stored id + RefIds type)
  instead of Unity's serialization API, which reports nothing per-property and
  drops the reference on prefabs/GameObjects (UUM-129100). Repair now works on
  prefab assets too, not just ScriptableObjects.
- Detect strictly per-field by resolving the recorded type, removing the
  single-missing fallback that falsely flagged legitimately-empty fields.
- Scan a prefab/ScriptableObject's YAML for every orphaned managed reference —
  at any nesting depth and on any child object — by walking each document's flat
  RefIds block and flagging entries whose stored type no longer resolves.
- List each with its own Fix picker that rewrites the type in the file and
  reimports, reaching references the per-field drawer cannot (nested values,
  child-object components, anything Unity dropped to <None>) without Prefab Mode.
- Open via Tools → Aspid FastTools → Repair Missing References (auto-targets the
  current selection).
… Mode repair

Replace the bulky missing-type and shared-reference help boxes with a
compact yellow inline notice: a small warning icon, terse text and an
underlined, clickable action word (Fix / Make unique) with the full
detail on hover. Covers both the IMGUI and UIToolkit drawers.

Extend missing-type repair to objects open in Prefab Mode: detection
resolves the backing document through the prefab stage (matching the
asset's file id), and the fix is applied in memory — reassigning the
reference and recovering the orphaned field data — because rewriting the
open stage's file would be discarded on save. Saved assets keep the
YAML-rewrite path.

Reselect the inspected objects after a repair so Unity's cached
object-level missing-types banner clears, and guard the UIToolkit field
against the live SerializedObject being invalidated by a reimport.
…n containers

Generalise the YAML reference resolver behind the inline missing-type Fix to
walk a property path of any shape: through managed-reference chains and through
plain [Serializable] containers (struct/class fields and List<T> of them), so a
missing type buried in a slot or list element is detected and repaired inline
like a top-level field.

When an in-memory (Prefab Mode) repair replaces a missing reference that itself
carried missing nested references, clear those now-orphaned entries too so the
object's missing-types banner clears.

Add the SlottedLoadout sample demonstrating [SerializeReferenceSelector]
references inside a container field and a List<T> of containers.
- Redesign the Repair References window in the Welcome style: boxed
  asset card with an Aspid header, centred info/success hero states,
  warning-accented results header and amber gradient rows.
- Extract the hierarchical type selector from TypeSelectorWindow into a
  reusable TypeSelectorView; the window stays a thin dropdown host with
  an unchanged public Show API.
- Expand the selector inline as an accordion under the clicked Fix row
  (dark Aspid panel, one at a time, Escape collapses) instead of the
  floating grey dropdown.
- Migrate selector USS classes to BEM under the
  aspid-fasttools-type-selector block and rename the stylesheet to
  Aspid-FastTools-TypeSelector.uss; sync the asset field when Open()
  retargets an already-open window.
- The repair window moved to Tools → Aspid 🐍 → Repair Missing
  References FastTools; mirror the new path in the CHANGELOG, both
  root/Documentation README pairs and the sample READMEs.
@VPDPersonal VPDPersonal changed the title Add [SerializeReferenceSelector] dropdown for SerializeReference fields Add [SerializeReferenceSelector] dropdown and missing-type repair Jun 10, 2026
- Remove `[SerializeReferenceSelector]`; `[TypeSelector]` now also drives `[SerializeReference]` managed-reference fields, dispatching by property type in `TypeSelectorPropertyDrawer`.
- The attribute's base types narrow the candidate list below the declared field type — applied to both concrete types and open generic definitions, in the dropdown and the missing-type Fix picker.
- Update samples, CHANGELOG and READMEs (EN/RU) to the merged attribute.
- Add the `Aspid.FastTools.Analyzers` git submodule (VPDPersonal/Aspid.FastTools.Analyzers) carrying the `AFT*` [TypeSelector] usage rules.
- Ship the prebuilt `Aspid.FastTools.Analyzers.dll` with a `RoslynAnalyzer`-labelled meta (all platforms excluded), mirroring the generator DLL.
- Document the submodule and its manual rebuild/deploy in CLAUDE.md.
- Bump the analyzer submodule: AFT0003 now also flags a sealed class paired with an interface it does not implement; redeploy the prebuilt DLL.
- Switch the submodule URL from SSH to HTTPS so public clones resolve it without keys.
- Add the rebuild-analyzers-on-change PostToolUse hook script and the build-analyzer skill mirroring the generator pipeline; document both in CLAUDE.md.
…attribute

Unify SerializeReference selector into [TypeSelector] with usage analyzer
…ector-filter

Apply TypeSelector base-type filter to paste and templates
Make List + add a single undo step without rid alias
…etach-symmetry

Re-subscribe theme updates on attach for symmetric lifecycle
Distinguish absent vs empty required field in YAML gate
…e-state

Share per-frame state between GetHeight and Draw
Preserve dominant line terminator in WritePreservingNewlines
…-cache

Cache per-asset constraint map in graph view
…property

# Conflicts:
#	Aspid.FastTools/Packages/tech.aspid.fasttools/Unity/Editor/Scripts/SerializeReferences/Drawers/SerializeReferenceIMGUIPropertyDrawer.cs
…ence-dropdown

Bring the extracted YAML engine assembly (Aspid.FastTools.Unity.Editor.Yaml) and its
test assembly onto the SerializeReference branch so SR can consume it from the new
location. This is the merge half of adopting the engine; the follow-up rewire commit
removes the now-duplicated YAML sources from SerializeReferences/Extensions and the six
engine tests from the SR test folder, and wires the asmdef references.

Conflicts: Tests.meta and Tests/Editor.meta were add/add (both branches created the
folder) — kept this branch's existing folder GUIDs.
…cates

Remove the YAML sources now provided by Aspid.FastTools.Unity.Editor.Yaml
(SerializeReferenceYaml, SerializeReferenceYamlEditor, the probe cache and its
invalidator) from SerializeReferences/Extensions, and the six engine-level tests plus
YamlFixtures from the SR test folder — they live in the Yaml and Yaml.Tests assemblies
after the merge. Keeping the duplicates would collide on type names and asset GUIDs.

Wire the references: Aspid.FastTools.Unity.Editor now references the engine assembly;
the SR editor test assembly references both the engine and Yaml.Tests so the two staying
integration tests (RequiredYaml, ManagedTypeName) still see the engine internals and the
reused fixtures.
…f-containment

Pull the engine fix that removes the inbound SerializeReferenceHelpers.IsScanCandidate
reference from SerializeReferenceYamlProbeCacheInvalidator (it now uses the engine-level
SerializeReferenceYaml.IsCandidateAssetPath). Follow-up commit routes SR's own
IsScanCandidate through the same primitive.
…rimitive

SerializeReferenceHelpers.IsScanCandidate now delegates the .prefab/.asset/.unity asset
test to SerializeReferenceYaml.IsCandidateAssetPath and only adds the settings-based
folder exclusion on top, removing the duplicated ScanExtensions list. Single source of
truth for the candidate-extension set now lives in the YAML engine.
fix(editor): restore scan results on tab switch
@VPDPersonal VPDPersonal force-pushed the feature/serialize-reference-dropdown branch from 1795454 to ec3a875 Compare June 26, 2026 13:48
@VPDPersonal VPDPersonal marked this pull request as draft June 27, 2026 19:44
@github-actions github-actions Bot added status: work-in-progress Draft / not ready for review and removed status: needs-review Ready for review labels Jun 27, 2026
VPDPersonal and others added 8 commits June 27, 2026 23:55
- Move the YAML engine asmdef back into Yaml/ as the self-contained
  ...SerializeReferences.Yaml assembly; it had wrongly been raised to the
  SerializeReferences root, capturing the whole SR folder and breaking
  compilation with a cyclic dependency on the editor assembly
- Add Yaml/AssemblyInfo.cs exposing engine internals to the editor and
  SR test assemblies
- Point the editor asmdef at the renamed Yaml assembly and drop dangling
  ...Editor.Yaml references from the empty editor test assembly
- Add runtime/source references to the SR test assembly so [TypeSelector]
  resolves
Adopt main's refactored TypeSelector engine as the canonical version.
refactor/type-selector-engine was extracted from this branch and merged
to main precisely so the SerializeReference work could rebuild on the
clean, split engine (TypeSelectorFilter API + extracted helpers).

Resolution:
- TypeSelector engine (Selectors/, Extensions/, picker USS) -> take main.
- SerializeReference + Type drawers/windows -> migrate every
  TypeSelectorWindow.Show / new TypeSelectorView call site to the new
  TypeSelectorFilter API.
- TypeSelectorAttribute -> keep the feature-only RequiredMessage member.
- Drop TypeSelectorItemAttribute for main's simplified
  TypeSelectorDisplayAttribute (Tooltip + Icon; DisplayPath/Order gone);
  update READMEs and CHANGELOG to match.
- README Show signature/param tables -> reconcile to the new API.
- Remove duplicate copies left by main's file moves (squash-merge broke
  ancestry): flat Internal/Styles/AspidTheme*.cs (main groups them under
  Theme/) and Tests/.../SerializeReferences/GenericTypeResolverTests.cs
  (main moved it under Tests/.../Types/).

Verified: Unity compiles clean (0 errors/warnings); EditMode 110/112 pass.
The 2 failures (ManagedTypeName.FromType_Null, SettingsUI BuildControls)
are pre-existing on this branch — byte-identical to the pre-merge tip and
unrelated to the TypeSelector swap.
main's TypeSelector attribute refactor deliberately pared the attribute
down; RequiredMessage (custom required-notice text) was a branch-only
addition with no counterpart in main. Reset TypeSelectorAttribute to
main's exact version and fall the four drawers back to the fixed default
notice. The Required flag and its inline warning stay intact. Update the
CHANGELOG entry and the SerializeReferences tutorial accordingly.
- IsEmpty/DisplayName/FullName were stored fields computed in the
  constructor, so default(ManagedTypeName) (e.g. FromType(null)) reported
  a stale IsEmpty == false; make them computed so the empty default reads
  empty too.
- The breakage-detection settings toggle was missing its SyncFromSettings
  wiring, so it alone never mirrored the store live across the two
  settings surfaces; add it and cover it in the live-sync test.
Adds the project-level SerializeReferenceGateSettings asset backing the
breakage-detection gate (build severity), so the setting persists with
the project instead of being regenerated per checkout.

Co-Authored-By: Claude <noreply@anthropic.com>
…scannable

Replace the 16 dense paragraph bullets with a lead intro, an upfront usage
example, and compact capability/repair tables; add a pointer to the
SerializeReferences sample and its TUTORIAL. Keep all four README copies
(root EN/RU + Documentation EN/RU) in sync.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEM7bUksXammDxDqNn1iHb
- Replace the three checkboxes with AspidSwitch, an iOS-style toggle
  ported from Aspid.MVVM's AspidToggle: an outlined track, a translucent
  accent on-fill and a handle that slides on an ease-out-cubic curve.
- Swap the multiline excluded-folders TextField for an add/remove list
  backed by a folder picker, mirrored live with the Project Settings page.
- Theme the Build/CI gate EnumField dark so it no longer clashes with the
  window's canvas, scoped to the in-window tab so Project Settings keeps
  its native look.
- Brand the Build / CI gate EnumField: translucent dark fill, 8px radius,
  a dimmed chevron and the signature green on hover / open, split evenly
  50/50 with its caption instead of stretching the whole row.
- Make the excluded-folders control a compact translucent panel — folder
  rows over a single add row whose "+" sits at the right edge, rounded to
  match the window's cards.
- Drop the in-content "Settings" heading; the active gear tab already
  names the mode, so it only read as a foreign block.
- Show the Aspid brand icon beside the window title.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: editor Editor-only code area: runtime Runtime / player code area: samples Sample projects status: work-in-progress Draft / not ready for review type: feature New feature or capability

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

SerializeReferenceSelector

1 participant