Most of the time, the fields and other widgets on different cards of a deck contain entirely different data. Occasionally though, as in this question, you might have data like a game's score counter that you want to display on and modify from many cards. There's an elegant way to (ab)use Prototypes and Contraptions to create this kind of "singleton" widget state:
When the value of a field in a Contraption instance has never been modified, the value of the corresponding field in the Contraption's Prototype is inherited. By exposing a ".value" attribute for our Contraptions which read from and write to a field in the Prototype, rather than the Contraption instance, every instance of the Contraption will share a single value:
on get_value do card.def.widgets.f.data end on set_value x do card.def.widgets.f.data:x end
This becomes slightly more complicated if we want the field to be unlocked and user-editable, since we can no longer rely on inheriting the prototype's value automatically. In this case, we will need to explicitly replicate changes back to the prototype and poll the value from the prototype when the contraption is updated by a view[] event:
on get_value do card.def.widgets.f.data end on set_value x do card.def.widgets.f.data:x end on change do set_value[f.data] end on view do f.data:get_value[] end
As a complete example, here's a "scoreCounter" prototype which uses this mechanism:
%%WGT0{"w":[{"name":"sc","type":"contraption","size":[100,20],"pos":[302,95],"def":"scoreCounter","widgets":{"f":{}}}],"d":{"scoreCounter":{"name":"scoreCounter","size":[100,20],"margin":[0,0,0,0],"description":"an example of a \"singleton\" contraption which shares data across every instance.","script":"on get_value do card.def.widgets.f.data end\non set_value x do card.def.widgets.f.data:x end\non change do set_value[f.data] end\non view do f.data:get_value[] end\n","attributes":{"name":["value"],"label":["Value"],"type":["number"]},"widgets":{"f":{"type":"field","size":[100,20],"pos":[0,0],"style":"plain","align":"center","value":"0"}}}}}
Anywhere a scoreCounter appears within a deck, it will represent an identical view of the same underlying value. A pleasant side-effect of this approach is that scripts on cards can refer to any scoreCounter when they want to read or modify the game's score; there's no need to reach for a "source of truth" on some specific card.
I hope some of you find this to be a useful technique for your projects!
