game-maker / suite (push) Failing after 3m59s
A shader is an asset carrying a node graph (Texture color, Output, Property, Color, Add/Subtract/Multiply/Divide, Mix, Luminance) that compiles to the GLSL fragment of a Pixi filter. The Shader tab reuses the Behavior canvas; a sprite wears a shader through its Shader picker, and the rows below it are the graph's Property nodes. Property schema, resolution and deviation take the project because a sprite's rows now live in another asset. The built-in registry of the prototype is gone; "Adjust colors" ships as a graph in the fixture and the three example games. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
67 lines
2.6 KiB
TypeScript
67 lines
2.6 KiB
TypeScript
import type { Asset } from '../model/Asset';
|
||
import { type PropertyBag, type PropertyValue, sameValue } from '../model/Properties';
|
||
import type { Project } from '../model/Project';
|
||
import type { SceneObject } from '../model/SceneObject';
|
||
import { propDef, schemaForAsset, schemaForObject } from './PropertySchema';
|
||
|
||
/**
|
||
* Schema defaults filled with the asset's own values. Keys unknown to the schema are ignored, so
|
||
* stale data never leaks into the editor.
|
||
*/
|
||
export function resolveAssetProps(project: Project, asset: Asset): PropertyBag {
|
||
return valuesOver(schemaForAsset(project, asset), asset.props);
|
||
}
|
||
|
||
/**
|
||
* The only place where overrides are merged onto asset values. The rows are the object's: a
|
||
* sprite overriding its shader has that shader's parameters, not the asset's.
|
||
*/
|
||
export function resolveSceneObjectProps(project: Project, asset: Asset, object: SceneObject): PropertyBag {
|
||
const schema = schemaForObject(project, asset, object);
|
||
const bag = valuesOver(schema, asset.props);
|
||
for (const def of schema) {
|
||
const override = object.overrides[def.key];
|
||
if (override !== undefined) bag[def.key] = override;
|
||
}
|
||
return bag;
|
||
}
|
||
|
||
function valuesOver(
|
||
schema: readonly { key: string; default: PropertyValue }[],
|
||
values: PropertyBag,
|
||
): PropertyBag {
|
||
const bag: PropertyBag = {};
|
||
for (const def of schema) {
|
||
const own = values[def.key];
|
||
bag[def.key] = own !== undefined ? own : def.default;
|
||
}
|
||
return bag;
|
||
}
|
||
|
||
/** Whether the asset's own value differs from the schema default – the asset-level override. */
|
||
export function isModified(project: Project, asset: Asset, key: string): boolean {
|
||
const def = propDef(project, asset, key);
|
||
if (!def) return false;
|
||
const own = asset.props[key];
|
||
return own !== undefined && !sameValue(own, def.default);
|
||
}
|
||
|
||
/** The value the object would have without its override for `key`. */
|
||
export function inheritedValue(project: Project, asset: Asset, key: string): PropertyValue | undefined {
|
||
return resolveAssetProps(project, asset)[key];
|
||
}
|
||
|
||
/** An override that happens to carry the asset's own value does not count as a deviation. */
|
||
export function deviatesFromAsset(project: Project, object: SceneObject, asset: Asset, key: string): boolean {
|
||
const own = object.overrides[key];
|
||
return own !== undefined && !sameValue(own, inheritedValue(project, asset, key));
|
||
}
|
||
|
||
/**
|
||
* Compared as overrides, not as effective values: both sides resolve against the same asset, so
|
||
* "neither overrides" means equal even when the asset value changed since.
|
||
*/
|
||
export function deviatesFromTemplate(object: SceneObject, base: SceneObject, key: string): boolean {
|
||
return !sameValue(object.overrides[key], base.overrides[key]);
|
||
}
|