Keep behavior variables private to their own graph (#257)
A behavior often needs working state such as a timer or a counter. Until now every variable showed up on each placed object and in the Properties menu, so the inspector filled up with values nobody should touch. A private variable works like any other inside its graph but is not offered anywhere outside. - Each behavior variable gets a lock switch next to Keep. It starts off, so existing projects stay as they are (`privateVariables`). - A placed object shows no private variable, neither in the inspector nor while the game runs. If all are private, it says so. - Switching a variable to private drops its overrides on every placed object in one undo step. Switching back does not restore them. - A running game does not write a private value back as an override, and a project change during the run does not reset it. - `+ Property` no longer offers private variables. A port that names one by hand still reads and writes it without a warning. - The default value of a private variable is read-only in the asset inspector. Its shape (name, fields, type, delete) stays editable. - Keep is now a pin icon instead of a word. With the lock added, the header of a list variable had no room left and the lock covered `+ Item`. Not done: the animation track picker still offers private variables. Tests: ./check.sh -> 186 files, 2711 tests, CHECK EXIT 0. e2e 1,19,20,21,56 -> ALL PASSED, 119 checks. New module 56 has 7 checks with a real mouse. Counter-checks fail as expected: unit without the write-back filter, the sync guard, dropping overrides or loading the flag. Browser with all variables on the object, an unfiltered menu, or no value lock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cf6565d108
commit
e8b3ac0a3b
16 files changed
+455
-49
No files matched your search
+27
-3
@@ -37,14 +37,20 @@ export interface SceneAsset extends AssetBase {
|
||||
* `keptVariables` names the variables a `Run behavior` call hands on to the next call from the same
|
||||
* node on the same object (#229); the others start at their default every call. Absent keeps none,
|
||||
* so a project from before the switch runs as it did, and a new variable starts out not kept.
|
||||
*
|
||||
* `privateVariables` names the variables only the behavior's own graph sees (#257): a placed object
|
||||
* neither shows nor overrides them, and a `Properties` node does not offer them. Absent is none.
|
||||
*/
|
||||
export interface BehaviorAsset extends AssetBase {
|
||||
type: 'behavior';
|
||||
variables: PropertyDef[];
|
||||
keptVariables?: string[];
|
||||
privateVariables?: string[];
|
||||
graph: Graph;
|
||||
}
|
||||
|
||||
type VariableSwitch = 'keptVariables' | 'privateVariables';
|
||||
|
||||
/** Whether a call of this behavior hands `key` on to the next call (#229). */
|
||||
export function isKeptVariable(asset: BehaviorAsset, key: string): boolean {
|
||||
return asset.keptVariables?.includes(key) === true;
|
||||
@@ -52,10 +58,28 @@ export function isKeptVariable(asset: BehaviorAsset, key: string): boolean {
|
||||
|
||||
/** Writes the switch for one variable; an empty list is dropped rather than stored. */
|
||||
export function setKeptVariable(asset: BehaviorAsset, key: string, on: boolean): void {
|
||||
const rest = (asset.keptVariables ?? []).filter((k) => k !== key);
|
||||
setSwitch(asset, 'keptVariables', key, on);
|
||||
}
|
||||
|
||||
/** Whether `key` is hidden from everything outside the behavior's own graph (#257). */
|
||||
export function isPrivateVariable(asset: Asset, key: string): boolean {
|
||||
return asset.type === 'behavior' && asset.privateVariables?.includes(key) === true;
|
||||
}
|
||||
|
||||
export function setPrivateVariable(asset: BehaviorAsset, key: string, on: boolean): void {
|
||||
setSwitch(asset, 'privateVariables', key, on);
|
||||
}
|
||||
|
||||
/** The variables a placed object shows and overrides: all but the private ones. */
|
||||
export function publicVariables(asset: BehaviorAsset): PropertyDef[] {
|
||||
return asset.variables.filter((def) => !isPrivateVariable(asset, def.key));
|
||||
}
|
||||
|
||||
function setSwitch(asset: BehaviorAsset, list: VariableSwitch, key: string, on: boolean): void {
|
||||
const rest = (asset[list] ?? []).filter((k) => k !== key);
|
||||
const next = on ? [...rest, key] : rest;
|
||||
if (next.length > 0) asset.keptVariables = next;
|
||||
else delete asset.keptVariables;
|
||||
if (next.length > 0) asset[list] = next;
|
||||
else delete asset[list];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user