Skip to content

Hostile Consumer Panels

This folder contains hostile-consumer teachable panels for the Attributes system.

These panels are intentionally written as if they lived in a completely separate Unity project consuming RevFramework from the outside.

They verify that the Attributes public API surface is complete, stable, and usable without internal access.


What "Hostile Consumer" Means

Panels in this folder are restricted to using only:

  • Public APIs
  • Documented runtime types
  • Supported extension seams
  • Teaching UI utilities

They may not:

  • reference .Internal namespaces
  • use reflection to access private state
  • call undocumented .Core helpers
  • depend on sample/demo utilities
  • attach teaching-only helper components to targets they do not own

If a panel requires any of those behaviours, the panel must not live in this folder.


Panels in This Folder

Panel Teaches
AttributesBasicsPanel The container: string ids and float values, authored rows versus ids created at runtime, bounds and clamping, what SetBaseValue's bool does and does not promise, the two writes that are refused, and why creating an attribute raises a change event whose before and after are identical.
AttributesSavePanel Persistence: why the payload holds base values and nothing else, why a restore rewinds instead of merging, why it raises no events, and which owners a capture will and will not reach.

Neither adds, removes, or reconfigures a component on any object in the scene.


What These Two Panels Prove Between Them

Attributes is the smallest system in the framework and the newest, which makes it the one where "the public API is sufficient" is least established by habit. These panels are the argument.

AttributesBasicsPanel never predicts a value. Every number it shows is read back out of the container immediately after the write that produced it — which is the only way a consumer can observe clamping, because bounds are not readable through the public API. Where it says requested 500, stored 100, the second number came from TryGetBaseValue, not from arithmetic the panel did itself. A panel that computed the expected answer would agree with a broken container.

AttributesSavePanel constructs the real participant and hands it to the real RevSaveCoordinator. The JSON it displays is the string that would go to disk, not a rendering of one. That matters here more than elsewhere: the interesting claim is about what is absent from the payload, and only the actual payload can settle it.

Both read eligibility through StableIdOwners, the same helper the participant uses, rather than running a second scan of their own — so what the panel says will be captured is what the participant will actually capture, and the two cannot drift apart.


Why The Third Panel Is Not Here

AttributesCombinerProvidersPanel lives in Demos/, and the reason is worth being precise about, because it is easy to read as a quality ranking and is not one.

Everything that panel calls is public. It does not reach into the framework and it does not touch your scene. What it does is build an owner of its own — a GameObject with an AttributeSet, three provider components, and a combiner supplied through SetCombiner.

That is disqualifying for this folder for a reason specific to what this folder's panels are for. A hostile-consumer panel's evidence is that it touched nothing it did not own, so when it compiles and runs, the public API was demonstrably sufficient for an outsider. A panel that constructs its own object graph has weakened that claim — not broken it, but weakened it enough that the folder's guarantee would no longer be uniform.

And there is no way around it. Providers are components found on the owner's parent chain, so demonstrating anything about them requires components to exist. The honest options were to build them and move the panel, or to demand the sample scene author them and teach less. The panel builds them.


Reading These Panels

Copy the TryGetValue / SetBaseValue calls, the event subscription, and the participant construction. Ignore the IMGUI layout — it is scaffolding, not a UI recommendation.

Note in particular how both panels re-check their binding every frame rather than resolving it once in OnEnable. That is not defensiveness for its own sake: a collaborator whose own Awake has not run on frame 0 is the exact shape of every panel bug found in v1.0.3.


Related