CultLib/src/GameCult.Unity/Assets/Caching/README.md

200 lines
9.5 KiB
Markdown
Raw Normal View History

2026-05-24 19:30:46 +01:00
# GameCult CultCache Unity Tools
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
`org.gamecult.caching.unity` is the Unity editor surface over CultCache: open a
store, browse its documents, edit them, save.
2026-05-24 19:30:46 +01:00
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
CultCache owns document identity, schema descriptors, persistence, dirty state
2026-09-14 13:43:45 +02:00
and flush. `CultInspectorModel` (in `GameCult.Caching`) owns what an inspector
shows and which edits it may make. The Studio window owns selection, the
toolbar and IMGUI widgets. It references `GameCult.Caching` and
`GameCult.Caching.MessagePack` at compile time through the
`org.gamecult.cultlib` package (assembly `GameCult.CultLib`).
2026-05-24 19:30:46 +01:00
## Use
2026-09-14 13:43:45 +02:00
1. Add this package; it depends on `org.gamecult.cultlib`.
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
2. Open `GameCult/CultCache Studio`.
2026-09-14 13:43:45 +02:00
3. `Open` a `.cc` store. `Directory` opens a directory store (a manifest beside
its `.records` folder; an existing one is detected without the toggle).
`Read Only` opens the store read-only. `New` creates an empty writable
single-file store; it is disabled while `Read Only` or `Directory` is on and
refuses a path that already exists.
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
4. Pick a document type, then a record. Edits upsert into the cache as you make
them; the toolbar shows `Dirty` until `Save` flushes the store.
2026-09-14 13:43:45 +02:00
Game data stores do not live under the project's `Assets` folder: Unity would
import and manage them, and CultCache exists so Unity does not manage game
data. `New` refuses a path under `Assets`, `Open` warns about one, and the file
dialogs start in the last store's folder or the project root.
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
Document types come from the cache's `CultDocumentRegistry`. A type lists its
own records and those of its subclasses, by `[CultName]` with the key as
fallback. `Add`, `Duplicate` and `Delete` act on the selected type and record.
A `[CultGlobal]` type with no record shows as absent with a `Create` action; the
Studio never creates one on its own.
A document class marked `[CultInspectorGroupBy(nameof(Kind), nameof(Owner))]`
lists its records as foldouts nested in that order, one per value in use; a
derived type listed under a marked base groups the same way. Each foldout has
a `Create` button that makes a new record with the grouped members preset to
that foldout's values, so it lands there. A declaration the model refuses (an
unknown, hidden, read-only, repeated or ungroupable member, or a global type)
lists the records flat under a warning that says why. A variant sits in the
foldout its resolved values name.
Drag a record row onto any record-reference value in the inspector (a member,
a list element, a dictionary key or value) to set it. The drop is accepted
exactly when the reference's picker would offer that record; it is refused
in a read-only store, for the record the reference already holds, and for a
record from another Studio window. The reference picker itself is not grouped.
2026-09-14 13:43:45 +02:00
Opening a store never writes it, directory stores included. Closing or
reloading scripts drops unsaved edits.
## Inspection Model
`CultInspectorModel` is engine-free and lives beside the inspector attributes
in `GameCult.Caching`; `CultCacheMessagePack.CreateInspectorModel` builds it
over a `.cc` store's codec. It gives the member list of a type (registry
catalog slots, `CultInspector*` metadata, whether a member is assignable), the
shape of any value (string, integer, float, bool, enum, `CultRecordRef<T>` with
its candidate records, rank-1 list or array, dictionary, `[Union]` with only
its declared subtypes, nested keyed object, struct edited in place through its
public fields, or its settable properties when it has none, or unsupported with a reason), drawer claim resolution
(`CultInspectorDrawerClaims`), and the edit decisions: the key a dictionary
entry keeps and the notice when a key is refused (null, an empty record
reference, a duplicate: serialized the same as another key under the owning
document's serializer or equal by the rebuilt dictionary type's default
comparer, or a key that document cannot serialize), the fresh key an added entry gets, what a new list
element, dictionary value or union pick may be, and how an integer edit clamps
to its type. Edits work on a copy (`CultInspectorEdit`): a refused upsert
leaves the cached object unchanged. The Studio is one lowering of that model
and owns only widgets and layout; a runtime CultUI panel needs only its own
renderer and drawers to show and edit the same documents under the same rules.
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
Grouping is the model's too: `GroupingOf` resolves a listed type's
`[CultInspectorGroupBy]` members (or the notice for a refused declaration),
`GroupRecords` returns the tree of nodes (id, label, depth, values, children,
records) that a lowering draws, and `CreateInGroup` makes the record for a
node. `IsRecordCandidate` is the one test for whether a record may be a
reference's value, shared by the picker's candidates and a drop, and
`RecordRefLabel` is the one spelling of `None`, a target's label and `Missing`.
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
## Drawers
Built in: every model shape above. A struct without `[Key]` members is edited
in place. With public fields it folds out to those fields only (readonly ones
read-only), so aliasing properties such as `Quaternion.eulerAngles` or
`Rect.min` add no rows; without public fields it folds out to its public
properties with a setter, `init` ones read-only (record structs and CultMath
matrices work as written). Get-only properties are never shown. Unity object
references draw as object fields. A value no drawer claims and no shape covers
shows a red error row with the model's reason, as does a multi-dimensional
array.
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
2026-09-14 13:43:45 +02:00
A project adds or overrides a drawer with an editor class. `Claimed` is either
a value type (an open generic definition claims every closed form) or an
attribute type, which claims every member carrying it. Attribute claims win
over type claims, which win over built-in drawing. A claim two drawers make is
used by neither: both are logged and the member shows the error row.
A drawer returns the new value and lets its IMGUI controls set `GUI.changed`;
only a frame that reports a change is saved. Mutating the value in place
without reporting a change is not saved reliably. A drawer that throws shows
an error row and discards that frame's edit copy, so nothing edited in that
frame is saved.
2026-05-24 19:30:46 +01:00
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
```csharp
2026-09-14 13:43:45 +02:00
using System;
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
using System.Reflection;
2026-09-14 13:43:45 +02:00
using GameCult.Caching;
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
using GameCult.Unity.Caching.Editor;
using UnityEditor;
using UnityEngine;
2026-05-24 19:30:46 +01:00
// Lives beside the documents; an attribute needs no Unity reference.
2026-09-14 13:43:45 +02:00
public sealed class ColorAttribute : Attribute
{
}
// Draws a "#RRGGBBAA" string member as a color field.
2026-09-14 13:43:45 +02:00
[CultInspectorDrawer(typeof(ColorAttribute))]
public sealed class ColorDrawer : ICultInspectorDrawer
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
{
2026-09-14 13:43:45 +02:00
public object Draw(CultInspector inspector, string label, Type type, object value, MemberInfo member)
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
{
if (type != typeof(string))
2026-09-14 13:43:45 +02:00
return inspector.DrawDefault(label, type, value, member);
ColorUtility.TryParseHtmlString(value as string ?? string.Empty, out var color);
var next = EditorGUILayout.ColorField(label, color);
return next == color ? value : "#" + ColorUtility.ToHtmlStringRGBA(next);
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
}
}
```
2026-05-24 19:30:46 +01:00
2026-09-14 13:43:45 +02:00
`Draw` receives the value's declared type and the member it belongs to, also
for list elements and dictionary keys and values, so an attribute drawer
checks the type it is handed. `inspector.DrawDefault` hands a value back to
built-in drawing; `inspector.DrawValue` draws a sub-value with claims applied.
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
`inspector.Record` is the whole document the value sits in, for drawers that
read sibling members (a texture path, a hull's tints). It is read-only by
contract: the model's `CultInspectorEdit.Record`, a second copy of the stored
document as the edit began, made on first read. It is neither the cached
object nor the edit copy the Studio saves, so writing to it saves nothing; an
edit reaches the record only through the value `Draw` returns. Within one frame
it does not show edits other drawers made earlier in that frame; after a save
the next frame's edit starts from the saved record.
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
## Inspector Annotations
2026-05-24 19:30:46 +01:00
2026-09-14 13:43:45 +02:00
The annotations live in `GameCult.Caching`, so headless shared models carry
them without referencing Unity.
2026-05-24 19:30:46 +01:00
```csharp
using GameCult.Caching;
using MessagePack;
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
[MessagePackObject]
2026-05-24 19:30:46 +01:00
[CultDocument("game.item", "game.item.v1")]
public sealed class ItemData
{
[Key(0)]
[CultName]
[CultInspectorLabel("Display Name")]
public string Name = string.Empty;
[Key(1)]
[CultInspectorRange(0, 999)]
public int Value;
[Key(2)]
[CultInspectorTextArea]
public string Notes = string.Empty;
[Key(3)]
[CultInspectorAssetGuid]
public string IconGuid = string.Empty;
2026-05-24 19:30:46 +01:00
}
```
- `CultInspectorLabel`
- `CultInspectorHidden`
- `CultInspectorReadOnly`
- `CultInspectorOrder`
- `CultInspectorTextArea`
- `CultInspectorRange`
- `CultInspectorAssetGuid` (a string member holding an engine asset's stable
identity: in Unity, the `.meta` GUID for a main asset, or `guid[subAssetName]`
when a sub-asset such as one sprite of a sheet is picked — the same key form
`AssetReference` keeps and `Addressables.LoadAssetAsync<T>` accepts; optional
engine asset `Type`, named by the consumer; the Studio uses it when it is a
`UnityEngine.Object` type, refuses to store a built-in resource's GUID since
it has no Addressables entry (checked by asking AssetDatabase whether the
picked object is a main or sub-asset under `Assets/` or `Packages/`, not by
guessing from the GUID's hex digits), and never silently clears a stored
value that no longer resolves — it warns and offers a Clear button instead)
Reference CultCache from the Studio at compile time; add drawers Cut 6. CultCache Studio 1.0.0 -> 1.1.0. Deleted: the CultCacheBridge string-reflection bridge (type lookups by name, GetMethod/GetProperty invocation, PullOnOpen, FlushAsync(bool)), its DescriptorInfo/CatalogMemberInfo/RecordInfo shadows, and the disabled-text-field fallback in DrawValue. The window calls CultCacheMessagePack.Create, UpsertAsync(Type, object, key), Remove, FlushAsync, IsDirty, Registry.AllDescriptors, AllStoredDocuments and BackingStores directly through GameCult.CultLib. Window: single-file and directory stores, optional read-only open with edits disabled and the reason shown, document types from the registry, records by [CultName] with key fallback including subclasses, Add, Duplicate (MessagePack round trip), Delete, immediate upsert on edit, Save = flush, Dirty indicator. An absent [CultGlobal] shows as absent with an explicit Create; nothing is invented. Opening and closing never writes. Drawers (new CultCacheStudioDrawers.cs): dictionaries with recursive keys and values, abstract/interface members through their MessagePack [Union] declarations only, CultRecordRef<T> record picker plus raw key, CultMath float2/3/4, double2/3, int2, bool2, quaternion, rect, Color32, enums including flags, lists and arrays with add/remove, nested keyed types, a red error row for unclaimed types, and the [CultInspectorDrawer(typeof(T))] extension point discovered through TypeCache (ICultInspectorDrawer). Existing inspector attributes keep working. package.json depends on org.gamecult.cultlib 1.0.57 (Cut 7) and org.gamecult.cultmath 0.1.2. No Unity.Mathematics reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:02:49 +02:00
- `CultInspectorDrawer` (on drawer classes)
2026-05-24 19:30:46 +01:00
CultMesh collaboration should feed the same CultCache mutation surface rather
than becoming a second owner for document state.