@fundamental-engine/core 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +128 -0
- package/dist/agents/element-agent.d.ts +38 -0
- package/dist/agents/element-agent.d.ts.map +1 -0
- package/dist/agents/element-agent.js +70 -0
- package/dist/agents/element-agent.js.map +1 -0
- package/dist/agents/event-agent.d.ts +47 -0
- package/dist/agents/event-agent.d.ts.map +1 -0
- package/dist/agents/event-agent.js +82 -0
- package/dist/agents/event-agent.js.map +1 -0
- package/dist/agents/index.d.ts +17 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +57 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/region-agents.d.ts +40 -0
- package/dist/agents/region-agents.d.ts.map +1 -0
- package/dist/agents/region-agents.js +22 -0
- package/dist/agents/region-agents.js.map +1 -0
- package/dist/agents/relationship.d.ts +55 -0
- package/dist/agents/relationship.d.ts.map +1 -0
- package/dist/agents/relationship.js +40 -0
- package/dist/agents/relationship.js.map +1 -0
- package/dist/agents/user-agent.d.ts +57 -0
- package/dist/agents/user-agent.d.ts.map +1 -0
- package/dist/agents/user-agent.js +45 -0
- package/dist/agents/user-agent.js.map +1 -0
- package/dist/config/forces.config.d.ts +101 -0
- package/dist/config/forces.config.d.ts.map +1 -0
- package/dist/config/forces.config.js +239 -0
- package/dist/config/forces.config.js.map +1 -0
- package/dist/config/manual.d.ts +134 -0
- package/dist/config/manual.d.ts.map +1 -0
- package/dist/config/manual.js +604 -0
- package/dist/config/manual.js.map +1 -0
- package/dist/config/palettes.d.ts +18 -0
- package/dist/config/palettes.d.ts.map +1 -0
- package/dist/config/palettes.js +34 -0
- package/dist/config/palettes.js.map +1 -0
- package/dist/config/presets.d.ts +48 -0
- package/dist/config/presets.d.ts.map +1 -0
- package/dist/config/presets.js +87 -0
- package/dist/config/presets.js.map +1 -0
- package/dist/config/tokens.d.ts +3 -0
- package/dist/config/tokens.d.ts.map +1 -0
- package/dist/config/tokens.js +16 -0
- package/dist/config/tokens.js.map +1 -0
- package/dist/conformance/expectations.d.ts +40 -0
- package/dist/conformance/expectations.d.ts.map +1 -0
- package/dist/conformance/expectations.js +347 -0
- package/dist/conformance/expectations.js.map +1 -0
- package/dist/conformance/experiments.d.ts +17 -0
- package/dist/conformance/experiments.d.ts.map +1 -0
- package/dist/conformance/experiments.js +875 -0
- package/dist/conformance/experiments.js.map +1 -0
- package/dist/conformance/run.d.ts +18 -0
- package/dist/conformance/run.d.ts.map +1 -0
- package/dist/conformance/run.js +240 -0
- package/dist/conformance/run.js.map +1 -0
- package/dist/conformance/types.d.ts +100 -0
- package/dist/conformance/types.d.ts.map +1 -0
- package/dist/conformance/types.js +2 -0
- package/dist/conformance/types.js.map +1 -0
- package/dist/contracts/guards.d.ts +51 -0
- package/dist/contracts/guards.d.ts.map +1 -0
- package/dist/contracts/guards.js +100 -0
- package/dist/contracts/guards.js.map +1 -0
- package/dist/contracts/index.d.ts +18 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +107 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/passport.d.ts +88 -0
- package/dist/contracts/passport.d.ts.map +1 -0
- package/dist/contracts/passport.js +135 -0
- package/dist/contracts/passport.js.map +1 -0
- package/dist/contracts/types.d.ts +120 -0
- package/dist/contracts/types.d.ts.map +1 -0
- package/dist/contracts/types.js +24 -0
- package/dist/contracts/types.js.map +1 -0
- package/dist/core/accretion.d.ts +50 -0
- package/dist/core/accretion.d.ts.map +1 -0
- package/dist/core/accretion.js +98 -0
- package/dist/core/accretion.js.map +1 -0
- package/dist/core/agents.d.ts +31 -0
- package/dist/core/agents.d.ts.map +1 -0
- package/dist/core/agents.js +51 -0
- package/dist/core/agents.js.map +1 -0
- package/dist/core/attention.d.ts +72 -0
- package/dist/core/attention.d.ts.map +1 -0
- package/dist/core/attention.js +122 -0
- package/dist/core/attention.js.map +1 -0
- package/dist/core/causality.d.ts +38 -0
- package/dist/core/causality.d.ts.map +1 -0
- package/dist/core/causality.js +64 -0
- package/dist/core/causality.js.map +1 -0
- package/dist/core/conditions.d.ts +10 -0
- package/dist/core/conditions.d.ts.map +1 -0
- package/dist/core/conditions.js +22 -0
- package/dist/core/conditions.js.map +1 -0
- package/dist/core/currents.d.ts +53 -0
- package/dist/core/currents.d.ts.map +1 -0
- package/dist/core/currents.js +65 -0
- package/dist/core/currents.js.map +1 -0
- package/dist/core/dock.d.ts +35 -0
- package/dist/core/dock.d.ts.map +1 -0
- package/dist/core/dock.js +39 -0
- package/dist/core/dock.js.map +1 -0
- package/dist/core/events.d.ts +23 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +34 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/feedback-sink.d.ts +32 -0
- package/dist/core/feedback-sink.d.ts.map +1 -0
- package/dist/core/feedback-sink.js +53 -0
- package/dist/core/feedback-sink.js.map +1 -0
- package/dist/core/feedback.d.ts +11 -0
- package/dist/core/feedback.d.ts.map +1 -0
- package/dist/core/feedback.js +16 -0
- package/dist/core/feedback.js.map +1 -0
- package/dist/core/field-store.d.ts +26 -0
- package/dist/core/field-store.d.ts.map +1 -0
- package/dist/core/field-store.js +54 -0
- package/dist/core/field-store.js.map +1 -0
- package/dist/core/field.d.ts +18 -0
- package/dist/core/field.d.ts.map +1 -0
- package/dist/core/field.js +1943 -0
- package/dist/core/field.js.map +1 -0
- package/dist/core/fieldline-seeds.d.ts +25 -0
- package/dist/core/fieldline-seeds.d.ts.map +1 -0
- package/dist/core/fieldline-seeds.js +32 -0
- package/dist/core/fieldline-seeds.js.map +1 -0
- package/dist/core/fieldlines.d.ts +75 -0
- package/dist/core/fieldlines.d.ts.map +1 -0
- package/dist/core/fieldlines.js +111 -0
- package/dist/core/fieldlines.js.map +1 -0
- package/dist/core/flow.d.ts +38 -0
- package/dist/core/flow.d.ts.map +1 -0
- package/dist/core/flow.js +27 -0
- package/dist/core/flow.js.map +1 -0
- package/dist/core/formations.d.ts +11 -0
- package/dist/core/formations.d.ts.map +1 -0
- package/dist/core/formations.js +22 -0
- package/dist/core/formations.js.map +1 -0
- package/dist/core/geometry.d.ts +67 -0
- package/dist/core/geometry.d.ts.map +1 -0
- package/dist/core/geometry.js +68 -0
- package/dist/core/geometry.js.map +1 -0
- package/dist/core/heatmap.d.ts +22 -0
- package/dist/core/heatmap.d.ts.map +1 -0
- package/dist/core/heatmap.js +55 -0
- package/dist/core/heatmap.js.map +1 -0
- package/dist/core/host.d.ts +46 -0
- package/dist/core/host.d.ts.map +1 -0
- package/dist/core/host.js +11 -0
- package/dist/core/host.js.map +1 -0
- package/dist/core/integrator.d.ts +24 -0
- package/dist/core/integrator.d.ts.map +1 -0
- package/dist/core/integrator.js +375 -0
- package/dist/core/integrator.js.map +1 -0
- package/dist/core/math.d.ts +37 -0
- package/dist/core/math.d.ts.map +1 -0
- package/dist/core/math.js +77 -0
- package/dist/core/math.js.map +1 -0
- package/dist/core/reactions.d.ts +32 -0
- package/dist/core/reactions.d.ts.map +1 -0
- package/dist/core/reactions.js +45 -0
- package/dist/core/reactions.js.map +1 -0
- package/dist/core/registry.d.ts +13 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +20 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/render-backend.d.ts +46 -0
- package/dist/core/render-backend.d.ts.map +1 -0
- package/dist/core/render-backend.js +75 -0
- package/dist/core/render-backend.js.map +1 -0
- package/dist/core/render-modes.d.ts +42 -0
- package/dist/core/render-modes.d.ts.map +1 -0
- package/dist/core/render-modes.js +141 -0
- package/dist/core/render-modes.js.map +1 -0
- package/dist/core/reservoir.d.ts +43 -0
- package/dist/core/reservoir.d.ts.map +1 -0
- package/dist/core/reservoir.js +207 -0
- package/dist/core/reservoir.js.map +1 -0
- package/dist/core/scalar-grid.d.ts +51 -0
- package/dist/core/scalar-grid.d.ts.map +1 -0
- package/dist/core/scalar-grid.js +146 -0
- package/dist/core/scalar-grid.js.map +1 -0
- package/dist/core/scanner.d.ts +59 -0
- package/dist/core/scanner.d.ts.map +1 -0
- package/dist/core/scanner.js +260 -0
- package/dist/core/scanner.js.map +1 -0
- package/dist/core/shadow.d.ts +69 -0
- package/dist/core/shadow.d.ts.map +1 -0
- package/dist/core/shadow.js +84 -0
- package/dist/core/shadow.js.map +1 -0
- package/dist/core/spatial-hash.d.ts +30 -0
- package/dist/core/spatial-hash.d.ts.map +1 -0
- package/dist/core/spatial-hash.js +64 -0
- package/dist/core/spatial-hash.js.map +1 -0
- package/dist/core/streamlines.d.ts +29 -0
- package/dist/core/streamlines.d.ts.map +1 -0
- package/dist/core/streamlines.js +70 -0
- package/dist/core/streamlines.js.map +1 -0
- package/dist/core/surface.d.ts +19 -0
- package/dist/core/surface.d.ts.map +1 -0
- package/dist/core/surface.js +21 -0
- package/dist/core/surface.js.map +1 -0
- package/dist/core/temporal.d.ts +110 -0
- package/dist/core/temporal.d.ts.map +1 -0
- package/dist/core/temporal.js +139 -0
- package/dist/core/temporal.js.map +1 -0
- package/dist/core/thermo.d.ts +48 -0
- package/dist/core/thermo.d.ts.map +1 -0
- package/dist/core/thermo.js +48 -0
- package/dist/core/thermo.js.map +1 -0
- package/dist/core/types.d.ts +610 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/weights.d.ts +111 -0
- package/dist/core/weights.d.ts.map +1 -0
- package/dist/core/weights.js +128 -0
- package/dist/core/weights.js.map +1 -0
- package/dist/diagnostics/energy.d.ts +21 -0
- package/dist/diagnostics/energy.d.ts.map +1 -0
- package/dist/diagnostics/energy.js +27 -0
- package/dist/diagnostics/energy.js.map +1 -0
- package/dist/diagnostics/fields.d.ts +23 -0
- package/dist/diagnostics/fields.d.ts.map +1 -0
- package/dist/diagnostics/fields.js +30 -0
- package/dist/diagnostics/fields.js.map +1 -0
- package/dist/diagnostics/index.d.ts +46 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/index.js +23 -0
- package/dist/diagnostics/index.js.map +1 -0
- package/dist/diagnostics/modes.d.ts +108 -0
- package/dist/diagnostics/modes.d.ts.map +1 -0
- package/dist/diagnostics/modes.js +181 -0
- package/dist/diagnostics/modes.js.map +1 -0
- package/dist/diagnostics/potential.d.ts +30 -0
- package/dist/diagnostics/potential.d.ts.map +1 -0
- package/dist/diagnostics/potential.js +43 -0
- package/dist/diagnostics/potential.js.map +1 -0
- package/dist/diagnostics/probes.d.ts +31 -0
- package/dist/diagnostics/probes.d.ts.map +1 -0
- package/dist/diagnostics/probes.js +61 -0
- package/dist/diagnostics/probes.js.map +1 -0
- package/dist/diagnostics/render.d.ts +49 -0
- package/dist/diagnostics/render.d.ts.map +1 -0
- package/dist/diagnostics/render.js +132 -0
- package/dist/diagnostics/render.js.map +1 -0
- package/dist/export.d.ts +18 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +17 -0
- package/dist/export.js.map +1 -0
- package/dist/forces/extended.d.ts +121 -0
- package/dist/forces/extended.d.ts.map +1 -0
- package/dist/forces/extended.js +674 -0
- package/dist/forces/extended.js.map +1 -0
- package/dist/forces/index.d.ts +33 -0
- package/dist/forces/index.d.ts.map +1 -0
- package/dist/forces/index.js +237 -0
- package/dist/forces/index.js.map +1 -0
- package/dist/forces/natural.d.ts +106 -0
- package/dist/forces/natural.d.ts.map +1 -0
- package/dist/forces/natural.js +385 -0
- package/dist/forces/natural.js.map +1 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +71 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect/budget.d.ts +17 -0
- package/dist/inspect/budget.d.ts.map +1 -0
- package/dist/inspect/budget.js +19 -0
- package/dist/inspect/budget.js.map +1 -0
- package/dist/inspect/index.d.ts +10 -0
- package/dist/inspect/index.d.ts.map +1 -0
- package/dist/inspect/index.js +10 -0
- package/dist/inspect/index.js.map +1 -0
- package/dist/inspect/report.d.ts +17 -0
- package/dist/inspect/report.d.ts.map +1 -0
- package/dist/inspect/report.js +44 -0
- package/dist/inspect/report.js.map +1 -0
- package/dist/inspect/snapshot.d.ts +21 -0
- package/dist/inspect/snapshot.d.ts.map +1 -0
- package/dist/inspect/snapshot.js +30 -0
- package/dist/inspect/snapshot.js.map +1 -0
- package/dist/recipes/catalog.d.ts +51 -0
- package/dist/recipes/catalog.d.ts.map +1 -0
- package/dist/recipes/catalog.js +1496 -0
- package/dist/recipes/catalog.js.map +1 -0
- package/dist/recipes/charge.d.ts +18 -0
- package/dist/recipes/charge.d.ts.map +1 -0
- package/dist/recipes/charge.js +27 -0
- package/dist/recipes/charge.js.map +1 -0
- package/dist/recipes/compile.d.ts +93 -0
- package/dist/recipes/compile.d.ts.map +1 -0
- package/dist/recipes/compile.js +113 -0
- package/dist/recipes/compile.js.map +1 -0
- package/dist/recipes/explain.d.ts +8 -0
- package/dist/recipes/explain.d.ts.map +1 -0
- package/dist/recipes/explain.js +46 -0
- package/dist/recipes/explain.js.map +1 -0
- package/dist/recipes/gallery.d.ts +6 -0
- package/dist/recipes/gallery.d.ts.map +1 -0
- package/dist/recipes/gallery.js +6 -0
- package/dist/recipes/gallery.js.map +1 -0
- package/dist/recipes/gravity.d.ts +16 -0
- package/dist/recipes/gravity.d.ts.map +1 -0
- package/dist/recipes/gravity.js +27 -0
- package/dist/recipes/gravity.js.map +1 -0
- package/dist/recipes/index.d.ts +18 -0
- package/dist/recipes/index.d.ts.map +1 -0
- package/dist/recipes/index.js +36 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/recipes/intent.d.ts +44 -0
- package/dist/recipes/intent.d.ts.map +1 -0
- package/dist/recipes/intent.js +46 -0
- package/dist/recipes/intent.js.map +1 -0
- package/dist/recipes/schema.d.ts +103 -0
- package/dist/recipes/schema.d.ts.map +1 -0
- package/dist/recipes/schema.js +123 -0
- package/dist/recipes/schema.js.map +1 -0
- package/dist/recipes/wayfinding.d.ts +39 -0
- package/dist/recipes/wayfinding.d.ts.map +1 -0
- package/dist/recipes/wayfinding.js +77 -0
- package/dist/recipes/wayfinding.js.map +1 -0
- package/dist/semantic/index.d.ts +13 -0
- package/dist/semantic/index.d.ts.map +1 -0
- package/dist/semantic/index.js +31 -0
- package/dist/semantic/index.js.map +1 -0
- package/dist/semantic/layers.d.ts +24 -0
- package/dist/semantic/layers.d.ts.map +1 -0
- package/dist/semantic/layers.js +27 -0
- package/dist/semantic/layers.js.map +1 -0
- package/dist/semantic/materials.d.ts +20 -0
- package/dist/semantic/materials.d.ts.map +1 -0
- package/dist/semantic/materials.js +17 -0
- package/dist/semantic/materials.js.map +1 -0
- package/dist/semantic/states.d.ts +11 -0
- package/dist/semantic/states.d.ts.map +1 -0
- package/dist/semantic/states.js +26 -0
- package/dist/semantic/states.js.map +1 -0
- package/dist/visual/channels.d.ts +71 -0
- package/dist/visual/channels.d.ts.map +1 -0
- package/dist/visual/channels.js +70 -0
- package/dist/visual/channels.js.map +1 -0
- package/dist/visual/index.d.ts +39 -0
- package/dist/visual/index.d.ts.map +1 -0
- package/dist/visual/index.js +30 -0
- package/dist/visual/index.js.map +1 -0
- package/dist/visual/lint.d.ts +41 -0
- package/dist/visual/lint.d.ts.map +1 -0
- package/dist/visual/lint.js +58 -0
- package/dist/visual/lint.js.map +1 -0
- package/dist/visual/mapping.d.ts +13 -0
- package/dist/visual/mapping.d.ts.map +1 -0
- package/dist/visual/mapping.js +43 -0
- package/dist/visual/mapping.js.map +1 -0
- package/dist/visual/semantic-text.d.ts +28 -0
- package/dist/visual/semantic-text.d.ts.map +1 -0
- package/dist/visual/semantic-text.js +36 -0
- package/dist/visual/semantic-text.js.map +1 -0
- package/dist/visual/tokens.d.ts +23 -0
- package/dist/visual/tokens.d.ts.map +1 -0
- package/dist/visual/tokens.js +54 -0
- package/dist/visual/tokens.js.map +1 -0
- package/dist/visual/visualization.d.ts +31 -0
- package/dist/visual/visualization.d.ts.map +1 -0
- package/dist/visual/visualization.js +47 -0
- package/dist/visual/visualization.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The force + condition registry (§4). The engine owns the loop; forces and
|
|
3
|
+
* conditions register here. Built-in conditions (§5) are seeded automatically.
|
|
4
|
+
*/
|
|
5
|
+
import { conditions as builtinConditions } from "./conditions.js";
|
|
6
|
+
export function createRegistry() {
|
|
7
|
+
const forces = {};
|
|
8
|
+
const conditions = { ...builtinConditions };
|
|
9
|
+
return {
|
|
10
|
+
forces,
|
|
11
|
+
conditions,
|
|
12
|
+
force(f) {
|
|
13
|
+
forces[f.token] = f;
|
|
14
|
+
},
|
|
15
|
+
condition(id, fn) {
|
|
16
|
+
conditions[id] = fn;
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AASlE,MAAM,UAAU,cAAc;IAC5B,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,UAAU,GAAsB,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAC/D,OAAO;QACL,MAAM;QACN,UAAU;QACV,KAAK,CAAC,CAAC;YACL,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;QACD,SAAS,CAAC,EAAE,EAAE,EAAE;YACd,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RenderBackend (#373) — the structural drawing contract between the engine and a surface. The
|
|
3
|
+
* agnostic-primitive pattern (FieldHost for the DOM, ContourFont for fonts, FeedbackSink for
|
|
4
|
+
* write-back) applied to rendering: the engine describes WHAT to draw in primitive calls; the
|
|
5
|
+
* backend owns HOW — today a Canvas 2D context, tomorrow a WebGL/WebGPU/offscreen implementation
|
|
6
|
+
* (the GPU IntegratorBackend frontier builds on exactly this seam).
|
|
7
|
+
*
|
|
8
|
+
* Scope (the first slice, deliberate): the OVERLAY surface renders exclusively through this
|
|
9
|
+
* contract — every reading is line/text work, the primitive set below covers it completely. The
|
|
10
|
+
* underlay matter modes (dots' radial gradients, metaballs, voronoi) still draw on the raw 2D
|
|
11
|
+
* context and convert in a later slice; their needs (gradients, composite modes) will grow the
|
|
12
|
+
* contract additively when they arrive.
|
|
13
|
+
*
|
|
14
|
+
* All coordinates are CSS pixels — the backend owns the dpr transform internally.
|
|
15
|
+
*/
|
|
16
|
+
/** One stroke pass: color as r,g,b 0-255 + alpha, a width, and the cap the arrows want. */
|
|
17
|
+
export interface Stroke {
|
|
18
|
+
r: number;
|
|
19
|
+
g: number;
|
|
20
|
+
b: number;
|
|
21
|
+
alpha: number;
|
|
22
|
+
width: number;
|
|
23
|
+
}
|
|
24
|
+
export interface RenderBackend {
|
|
25
|
+
/** size the backing store for a css-pixel viewport at a device-pixel ratio. */
|
|
26
|
+
size(width: number, height: number, dpr: number): void;
|
|
27
|
+
/** clear the whole surface. */
|
|
28
|
+
clear(): void;
|
|
29
|
+
/** stroke disjoint line segments packed [x1,y1,x2,y2, ...] — arrows, contours, grid walls. */
|
|
30
|
+
segments(packed: ArrayLike<number>, stroke: Stroke): void;
|
|
31
|
+
/** stroke one connected polyline through points packed [x,y, ...] — traced paths, grid lines. */
|
|
32
|
+
polyline(points: ArrayLike<number>, stroke: Stroke): void;
|
|
33
|
+
/** a filled rectangle — the data-reading chip plate. */
|
|
34
|
+
rect(x: number, y: number, w: number, h: number, r: number, g: number, b: number, alpha: number): void;
|
|
35
|
+
/** filled text at a baseline-middle anchor — the data-reading label. */
|
|
36
|
+
text(value: string, x: number, y: number, r: number, g: number, b: number, alpha: number): void;
|
|
37
|
+
/** measure a label at the backend's chip font — for plate sizing. */
|
|
38
|
+
measureText(value: string): number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The canonical Canvas 2D implementation. Wraps a context the caller acquired (core never touches
|
|
42
|
+
* the DOM); the engine's default surface. Pure call-through — no state beyond the context, so a
|
|
43
|
+
* recording stub satisfies the same contract in tests.
|
|
44
|
+
*/
|
|
45
|
+
export declare function canvas2dBackend(canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D): RenderBackend;
|
|
46
|
+
//# sourceMappingURL=render-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-backend.d.ts","sourceRoot":"","sources":["../../src/core/render-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,2FAA2F;AAC3F,MAAM,WAAW,MAAM;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,+EAA+E;IAC/E,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACvD,+BAA+B;IAC/B,KAAK,IAAI,IAAI,CAAC;IACd,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,iGAAiG;IACjG,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,wDAAwD;IACxD,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACvG,wEAAwE;IACxE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAChG,qEAAqE;IACrE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACpC;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,iBAAiB,EAAE,GAAG,EAAE,wBAAwB,GAAG,aAAa,CAkDvG"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RenderBackend (#373) — the structural drawing contract between the engine and a surface. The
|
|
3
|
+
* agnostic-primitive pattern (FieldHost for the DOM, ContourFont for fonts, FeedbackSink for
|
|
4
|
+
* write-back) applied to rendering: the engine describes WHAT to draw in primitive calls; the
|
|
5
|
+
* backend owns HOW — today a Canvas 2D context, tomorrow a WebGL/WebGPU/offscreen implementation
|
|
6
|
+
* (the GPU IntegratorBackend frontier builds on exactly this seam).
|
|
7
|
+
*
|
|
8
|
+
* Scope (the first slice, deliberate): the OVERLAY surface renders exclusively through this
|
|
9
|
+
* contract — every reading is line/text work, the primitive set below covers it completely. The
|
|
10
|
+
* underlay matter modes (dots' radial gradients, metaballs, voronoi) still draw on the raw 2D
|
|
11
|
+
* context and convert in a later slice; their needs (gradients, composite modes) will grow the
|
|
12
|
+
* contract additively when they arrive.
|
|
13
|
+
*
|
|
14
|
+
* All coordinates are CSS pixels — the backend owns the dpr transform internally.
|
|
15
|
+
*/
|
|
16
|
+
const CHIP_FONT = '10px ui-monospace, SFMono-Regular, Menlo, monospace';
|
|
17
|
+
/**
|
|
18
|
+
* The canonical Canvas 2D implementation. Wraps a context the caller acquired (core never touches
|
|
19
|
+
* the DOM); the engine's default surface. Pure call-through — no state beyond the context, so a
|
|
20
|
+
* recording stub satisfies the same contract in tests.
|
|
21
|
+
*/
|
|
22
|
+
export function canvas2dBackend(canvas, ctx) {
|
|
23
|
+
let W = 0;
|
|
24
|
+
let H = 0;
|
|
25
|
+
return {
|
|
26
|
+
size(width, height, dpr) {
|
|
27
|
+
W = width;
|
|
28
|
+
H = height;
|
|
29
|
+
canvas.width = Math.floor(width * dpr);
|
|
30
|
+
canvas.height = Math.floor(height * dpr);
|
|
31
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
32
|
+
},
|
|
33
|
+
clear() {
|
|
34
|
+
ctx.clearRect(0, 0, W, H);
|
|
35
|
+
},
|
|
36
|
+
segments(packed, stroke) {
|
|
37
|
+
ctx.strokeStyle = `rgba(${stroke.r},${stroke.g},${stroke.b},${stroke.alpha})`;
|
|
38
|
+
ctx.lineWidth = stroke.width;
|
|
39
|
+
ctx.lineCap = 'round';
|
|
40
|
+
ctx.beginPath();
|
|
41
|
+
for (let i = 0; i + 3 < packed.length; i += 4) {
|
|
42
|
+
ctx.moveTo(packed[i], packed[i + 1]);
|
|
43
|
+
ctx.lineTo(packed[i + 2], packed[i + 3]);
|
|
44
|
+
}
|
|
45
|
+
ctx.stroke();
|
|
46
|
+
},
|
|
47
|
+
polyline(points, stroke) {
|
|
48
|
+
if (points.length < 4)
|
|
49
|
+
return;
|
|
50
|
+
ctx.strokeStyle = `rgba(${stroke.r},${stroke.g},${stroke.b},${stroke.alpha})`;
|
|
51
|
+
ctx.lineWidth = stroke.width;
|
|
52
|
+
ctx.lineCap = 'round';
|
|
53
|
+
ctx.beginPath();
|
|
54
|
+
ctx.moveTo(points[0], points[1]);
|
|
55
|
+
for (let i = 2; i + 1 < points.length; i += 2)
|
|
56
|
+
ctx.lineTo(points[i], points[i + 1]);
|
|
57
|
+
ctx.stroke();
|
|
58
|
+
},
|
|
59
|
+
rect(x, y, w, h, r, g, b, alpha) {
|
|
60
|
+
ctx.fillStyle = `rgba(${r},${g},${b},${alpha})`;
|
|
61
|
+
ctx.fillRect(x, y, w, h);
|
|
62
|
+
},
|
|
63
|
+
text(value, x, y, r, g, b, alpha) {
|
|
64
|
+
ctx.font = CHIP_FONT;
|
|
65
|
+
ctx.textBaseline = 'middle';
|
|
66
|
+
ctx.fillStyle = `rgba(${r},${g},${b},${alpha})`;
|
|
67
|
+
ctx.fillText(value, x, y);
|
|
68
|
+
},
|
|
69
|
+
measureText(value) {
|
|
70
|
+
ctx.font = CHIP_FONT;
|
|
71
|
+
return ctx.measureText(value).width;
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=render-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-backend.js","sourceRoot":"","sources":["../../src/core/render-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Opacity of a particle↔particle link by separation (§20.6 links mode). */
|
|
2
|
+
export declare function linkAlpha(d: number, r: number, max?: number): number;
|
|
3
|
+
/** A line segment in cell-local coordinates ([0,1]², origin top-left, +y down). */
|
|
4
|
+
export interface IsoSeg {
|
|
5
|
+
x1: number;
|
|
6
|
+
y1: number;
|
|
7
|
+
x2: number;
|
|
8
|
+
y2: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The fractional crossing of the iso level between two corner values `a → b`.
|
|
12
|
+
* Linear interpolation `t = (iso − a)/(b − a)`, clamped to [0,1]; `0.5` if flat.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isoCross(a: number, b: number, iso: number): number;
|
|
15
|
+
export declare function marchingCell(tl: number, tr: number, br: number, bl: number, level: number): readonly IsoSeg[];
|
|
16
|
+
/**
|
|
17
|
+
* Splat one particle's smooth density kernel onto a scalar grid (additive). `grid` is a
|
|
18
|
+
* row-major `cols × rows` Float array of node densities at world `(gx·step, gy·step)`;
|
|
19
|
+
* each particle contributes `(1 − d/radius)²` to every node within `radius`. Returns the
|
|
20
|
+
* peak single-node contribution it wrote (handy for tests). Pure — no rendering.
|
|
21
|
+
*/
|
|
22
|
+
export declare function splatDensity(grid: Float32Array, cols: number, rows: number, step: number, px: number, py: number, radius: number, weight?: number): void;
|
|
23
|
+
/** Index of the nearest site to `(x, y)`, or `-1` if `sites` is empty. */
|
|
24
|
+
export declare function nearestSite(x: number, y: number, sites: readonly {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
}[]): number;
|
|
28
|
+
/** A wall segment between two Voronoi cells, in grid-node units (×step at draw time). */
|
|
29
|
+
export interface GridSeg {
|
|
30
|
+
x1: number;
|
|
31
|
+
y1: number;
|
|
32
|
+
x2: number;
|
|
33
|
+
y2: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The Voronoi cell walls of an owner grid (row-major `cols × rows` of site indices).
|
|
37
|
+
* A wall sits on the shared edge between any two orthogonally-adjacent nodes whose
|
|
38
|
+
* owners differ (an unowned node is `-1`); coordinates are in node units, so the
|
|
39
|
+
* vertical wall between columns `gx` and `gx+1` lies at `x = gx + 0.5`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function voronoiWalls(owners: ArrayLike<number>, cols: number, rows: number): GridSeg[];
|
|
42
|
+
//# sourceMappingURL=render-modes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-modes.d.ts","sourceRoot":"","sources":["../../src/core/render-modes.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,SAAO,GAAG,MAAM,CAGlE;AASD,mFAAmF;AACnF,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIlE;AAUD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CA2C7G;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,MAAM,SAAI,GACT,IAAI,CAkBN;AASD,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,MAAM,CAcpG;AAED,yFAAyF;AACzF,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAgB7F"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/** Opacity of a particle↔particle link by separation (§20.6 links mode). */
|
|
2
|
+
export function linkAlpha(d, r, max = 0.12) {
|
|
3
|
+
if (d >= r)
|
|
4
|
+
return 0;
|
|
5
|
+
return (1 - d / r) * max;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The fractional crossing of the iso level between two corner values `a → b`.
|
|
9
|
+
* Linear interpolation `t = (iso − a)/(b − a)`, clamped to [0,1]; `0.5` if flat.
|
|
10
|
+
*/
|
|
11
|
+
export function isoCross(a, b, iso) {
|
|
12
|
+
if (a === b)
|
|
13
|
+
return 0.5;
|
|
14
|
+
const t = (iso - a) / (b - a);
|
|
15
|
+
return t < 0 ? 0 : t > 1 ? 1 : t;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Marching-squares contour for one cell (§20.6 metaballs). Given the densities at the
|
|
19
|
+
* four corners — `tl, tr, br, bl` (clockwise from top-left) — and the iso `level`,
|
|
20
|
+
* return the 0–2 line segments where the iso-contour crosses the cell's edges, in
|
|
21
|
+
* cell-local [0,1]² coordinates. The two ambiguous saddle cases (5, 10) are resolved
|
|
22
|
+
* the conventional way (two separate segments).
|
|
23
|
+
*/
|
|
24
|
+
const NO_SEGS = Object.freeze([]);
|
|
25
|
+
export function marchingCell(tl, tr, br, bl, level) {
|
|
26
|
+
// edge crossing points (only the ones a case uses are read)
|
|
27
|
+
const T = { x: isoCross(tl, tr, level), y: 0 }; // top edge tl→tr
|
|
28
|
+
const R = { x: 1, y: isoCross(tr, br, level) }; // right edge tr→br
|
|
29
|
+
const B = { x: isoCross(bl, br, level), y: 1 }; // bottom edge bl→br
|
|
30
|
+
const L = { x: 0, y: isoCross(tl, bl, level) }; // left edge tl→bl
|
|
31
|
+
const seg = (a, b) => ({
|
|
32
|
+
x1: a.x,
|
|
33
|
+
y1: a.y,
|
|
34
|
+
x2: b.x,
|
|
35
|
+
y2: b.y,
|
|
36
|
+
});
|
|
37
|
+
// case index: one bit per corner above the level (tl=8, tr=4, br=2, bl=1)
|
|
38
|
+
const c = (tl > level ? 8 : 0) | (tr > level ? 4 : 0) | (br > level ? 2 : 0) | (bl > level ? 1 : 0);
|
|
39
|
+
switch (c) {
|
|
40
|
+
case 0:
|
|
41
|
+
case 15:
|
|
42
|
+
return NO_SEGS;
|
|
43
|
+
case 1:
|
|
44
|
+
case 14:
|
|
45
|
+
return [seg(L, B)];
|
|
46
|
+
case 2:
|
|
47
|
+
case 13:
|
|
48
|
+
return [seg(B, R)];
|
|
49
|
+
case 3:
|
|
50
|
+
case 12:
|
|
51
|
+
return [seg(L, R)];
|
|
52
|
+
case 4:
|
|
53
|
+
case 11:
|
|
54
|
+
return [seg(T, R)];
|
|
55
|
+
case 6:
|
|
56
|
+
case 9:
|
|
57
|
+
return [seg(T, B)];
|
|
58
|
+
case 7:
|
|
59
|
+
case 8:
|
|
60
|
+
return [seg(L, T)];
|
|
61
|
+
case 5: // tr & bl above — saddle
|
|
62
|
+
return [seg(L, T), seg(B, R)];
|
|
63
|
+
case 10: // tl & br above — saddle
|
|
64
|
+
return [seg(L, B), seg(T, R)];
|
|
65
|
+
default:
|
|
66
|
+
return NO_SEGS;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Splat one particle's smooth density kernel onto a scalar grid (additive). `grid` is a
|
|
71
|
+
* row-major `cols × rows` Float array of node densities at world `(gx·step, gy·step)`;
|
|
72
|
+
* each particle contributes `(1 − d/radius)²` to every node within `radius`. Returns the
|
|
73
|
+
* peak single-node contribution it wrote (handy for tests). Pure — no rendering.
|
|
74
|
+
*/
|
|
75
|
+
export function splatDensity(grid, cols, rows, step, px, py, radius, weight = 1) {
|
|
76
|
+
if (radius <= 0)
|
|
77
|
+
return;
|
|
78
|
+
const gx0 = Math.max(0, Math.floor((px - radius) / step));
|
|
79
|
+
const gx1 = Math.min(cols - 1, Math.ceil((px + radius) / step));
|
|
80
|
+
const gy0 = Math.max(0, Math.floor((py - radius) / step));
|
|
81
|
+
const gy1 = Math.min(rows - 1, Math.ceil((py + radius) / step));
|
|
82
|
+
const r2 = radius * radius;
|
|
83
|
+
for (let gy = gy0; gy <= gy1; gy++) {
|
|
84
|
+
for (let gx = gx0; gx <= gx1; gx++) {
|
|
85
|
+
const dx = gx * step - px;
|
|
86
|
+
const dy = gy * step - py;
|
|
87
|
+
const d2 = dx * dx + dy * dy;
|
|
88
|
+
if (d2 >= r2)
|
|
89
|
+
continue;
|
|
90
|
+
const f = 1 - Math.sqrt(d2) / radius;
|
|
91
|
+
const idx = gy * cols + gx;
|
|
92
|
+
grid[idx] = grid[idx] + weight * f * f;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// ── Voronoi (§20.6) — nearest-site cells over the particle field ────────────────
|
|
97
|
+
//
|
|
98
|
+
// Each grid node is assigned the index of its nearest particle (its "owner"); cell
|
|
99
|
+
// walls are then the boundaries between adjacent nodes with different owners. The
|
|
100
|
+
// shattered-glass look without a full Delaunay triangulation. Both halves are pure
|
|
101
|
+
// and golden-tested; the renderer feeds owners from the spatial hash.
|
|
102
|
+
/** Index of the nearest site to `(x, y)`, or `-1` if `sites` is empty. */
|
|
103
|
+
export function nearestSite(x, y, sites) {
|
|
104
|
+
let best = -1;
|
|
105
|
+
let bestD2 = Infinity;
|
|
106
|
+
for (let i = 0; i < sites.length; i++) {
|
|
107
|
+
const s = sites[i];
|
|
108
|
+
const dx = s.x - x;
|
|
109
|
+
const dy = s.y - y;
|
|
110
|
+
const d2 = dx * dx + dy * dy;
|
|
111
|
+
if (d2 < bestD2) {
|
|
112
|
+
bestD2 = d2;
|
|
113
|
+
best = i;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return best;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The Voronoi cell walls of an owner grid (row-major `cols × rows` of site indices).
|
|
120
|
+
* A wall sits on the shared edge between any two orthogonally-adjacent nodes whose
|
|
121
|
+
* owners differ (an unowned node is `-1`); coordinates are in node units, so the
|
|
122
|
+
* vertical wall between columns `gx` and `gx+1` lies at `x = gx + 0.5`.
|
|
123
|
+
*/
|
|
124
|
+
export function voronoiWalls(owners, cols, rows) {
|
|
125
|
+
const walls = [];
|
|
126
|
+
for (let gy = 0; gy < rows; gy++) {
|
|
127
|
+
for (let gx = 0; gx < cols; gx++) {
|
|
128
|
+
const o = owners[gy * cols + gx];
|
|
129
|
+
if (gx + 1 < cols && owners[gy * cols + gx + 1] !== o) {
|
|
130
|
+
// vertical wall on the edge shared with the right neighbour
|
|
131
|
+
walls.push({ x1: gx + 0.5, y1: gy - 0.5, x2: gx + 0.5, y2: gy + 0.5 });
|
|
132
|
+
}
|
|
133
|
+
if (gy + 1 < rows && owners[(gy + 1) * cols + gx] !== o) {
|
|
134
|
+
// horizontal wall on the edge shared with the bottom neighbour
|
|
135
|
+
walls.push({ x1: gx - 0.5, y1: gy + 0.5, x2: gx + 0.5, y2: gy + 0.5 });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return walls;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=render-modes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-modes.js","sourceRoot":"","sources":["../../src/core/render-modes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bound↔free reservoir (§2.4) — the conserved exchange between the calm
|
|
3
|
+
* matter riding the Currents (bound) and the roaming matter (free).
|
|
4
|
+
*
|
|
5
|
+
* - **Wave-healing:** calm free particles already near a line drift onto it and,
|
|
6
|
+
* when very close and slow, snap to bound — but only up to `boundTarget`, so
|
|
7
|
+
* the lines never vacuum the open field.
|
|
8
|
+
* - **Tearing:** a disturbance (supernova / burst) rips nearby bound matter
|
|
9
|
+
* loose, returning it to the free pool with an outward kick.
|
|
10
|
+
*
|
|
11
|
+
* Count is conserved throughout: nothing is created or destroyed, only moved.
|
|
12
|
+
*/
|
|
13
|
+
import type { FieldStore } from './field-store.ts';
|
|
14
|
+
import type { Body, Particle, ForceRegistry } from './types.ts';
|
|
15
|
+
import { type Wave, type BoundParticle } from './currents.ts';
|
|
16
|
+
/** Reclaim calm free matter onto the nearest line, up to `boundTarget` (§2.4). */
|
|
17
|
+
export declare function healWaves(store: FieldStore, bound: BoundParticle[], boundTarget: number, waves: readonly Wave[], W: number, H: number, time: number, rand: () => number): void;
|
|
18
|
+
/** Tear bound matter within `radius` of (cx, cy) loose into the free pool (§6.9). */
|
|
19
|
+
export declare function tearBoundNear(bound: BoundParticle[], waves: readonly Wave[], cx: number, cy: number, radius: number, W: number, H: number, time: number, spawn: (p: Partial<Particle>) => void): void;
|
|
20
|
+
/**
|
|
21
|
+
* Force-tearing (§2.4): any force reaching a bound particle tears it loose into
|
|
22
|
+
* the free pool with a kick, so it then *feels* the force (otherwise the shimmer
|
|
23
|
+
* would ride the lines straight through a body). Selective gates act on free
|
|
24
|
+
* matter only, so only always/active bodies tear bound.
|
|
25
|
+
*/
|
|
26
|
+
export declare function tearBoundByForces(bound: BoundParticle[], waves: readonly Wave[], bodies: readonly Body[], forces: ForceRegistry, W: number, H: number, time: number, spawn: (p: Partial<Particle>) => void): void;
|
|
27
|
+
/**
|
|
28
|
+
* Charge induction (§20.10) — a *field-level* polarization, separate from the force.
|
|
29
|
+
*
|
|
30
|
+
* The pure `charge`/`magnetism` force ignores neutral matter (`q = 0 → return`), so on
|
|
31
|
+
* the live field — where every particle starts neutral — it would do nothing at all. A
|
|
32
|
+
* charge or magnetism body therefore polarizes the matter that enters its field: a
|
|
33
|
+
* neutral particle picks up a sign by which side of the body it sits on, splitting the
|
|
34
|
+
* region into the +/- domains the force then sorts. Charge is induced once — matter
|
|
35
|
+
* carries its sign thereafter — so an already-charged particle is never overwritten.
|
|
36
|
+
*
|
|
37
|
+
* This lives here, not in the force's `apply`, on purpose: the bare integrator (which the
|
|
38
|
+
* conformance suite drives) never runs it, so the force's golden contract ("ignores
|
|
39
|
+
* neutral matter") stays exactly true; only the live field, which calls this each frame,
|
|
40
|
+
* has charged matter for the force to push.
|
|
41
|
+
*/
|
|
42
|
+
export declare function induceCharges(bodies: readonly Body[], particles: readonly Particle[]): void;
|
|
43
|
+
//# sourceMappingURL=reservoir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reservoir.d.ts","sourceRoot":"","sources":["../../src/core/reservoir.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAW,KAAK,IAAI,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAEvE,kFAAkF;AAClF,wBAAgB,SAAS,CACvB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,aAAa,EAAE,EACtB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,MAAM,GACjB,IAAI,CAsCN;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,aAAa,EAAE,EACtB,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,GACpC,IAAI,CAkBN;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,aAAa,EAAE,EACtB,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,MAAM,EAAE,SAAS,IAAI,EAAE,EACvB,MAAM,EAAE,aAAa,EACrB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,GACpC,IAAI,CAmFN;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,QAAQ,EAAE,GAAG,IAAI,CAc3F"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bound↔free reservoir (§2.4) — the conserved exchange between the calm
|
|
3
|
+
* matter riding the Currents (bound) and the roaming matter (free).
|
|
4
|
+
*
|
|
5
|
+
* - **Wave-healing:** calm free particles already near a line drift onto it and,
|
|
6
|
+
* when very close and slow, snap to bound — but only up to `boundTarget`, so
|
|
7
|
+
* the lines never vacuum the open field.
|
|
8
|
+
* - **Tearing:** a disturbance (supernova / burst) rips nearby bound matter
|
|
9
|
+
* loose, returning it to the free pool with an outward kick.
|
|
10
|
+
*
|
|
11
|
+
* Count is conserved throughout: nothing is created or destroyed, only moved.
|
|
12
|
+
*/
|
|
13
|
+
import { waveYat } from "./currents.js";
|
|
14
|
+
/** Reclaim calm free matter onto the nearest line, up to `boundTarget` (§2.4). */
|
|
15
|
+
export function healWaves(store, bound, boundTarget, waves, W, H, time, rand) {
|
|
16
|
+
if (waves.length === 0)
|
|
17
|
+
return;
|
|
18
|
+
const ps = store.particles;
|
|
19
|
+
for (let i = ps.length - 1; i >= 0; i--) {
|
|
20
|
+
if (bound.length >= boundTarget)
|
|
21
|
+
break;
|
|
22
|
+
const p = ps[i];
|
|
23
|
+
if (!p || p.cap || p.heat >= 0.12)
|
|
24
|
+
continue;
|
|
25
|
+
// nearest wave line
|
|
26
|
+
let nwi = -1;
|
|
27
|
+
let nwd = 1e9;
|
|
28
|
+
let nwy = 0;
|
|
29
|
+
for (let wi = 0; wi < waves.length; wi++) {
|
|
30
|
+
const wy = waveYat(waves[wi], p.x, time, H);
|
|
31
|
+
const dd = Math.abs(wy - p.y);
|
|
32
|
+
if (dd < nwd) {
|
|
33
|
+
nwd = dd;
|
|
34
|
+
nwi = wi;
|
|
35
|
+
nwy = wy;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (nwi < 0 || nwd >= 64)
|
|
39
|
+
continue;
|
|
40
|
+
// drift toward the line; snap home when very close, calm, and (rarely) lucky.
|
|
41
|
+
const pull = Math.min(0.012, nwd * 0.0004) * (1 - p.heat / 0.12);
|
|
42
|
+
p.vy += nwy > p.y ? pull : -pull;
|
|
43
|
+
if (nwd < 20 && p.vx * p.vx + p.vy * p.vy < 0.3 && rand() < 0.03) {
|
|
44
|
+
bound.push({
|
|
45
|
+
wi: nwi,
|
|
46
|
+
progress: p.x / W,
|
|
47
|
+
phase: (rand() - 0.5) * 0.22 * Math.PI,
|
|
48
|
+
size: p.size,
|
|
49
|
+
glow: rand() < 0.3,
|
|
50
|
+
speed: (0.00035 + rand() * 0.0009) * (rand() < 0.5 ? 1 : -1),
|
|
51
|
+
});
|
|
52
|
+
store.remove(p);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Tear bound matter within `radius` of (cx, cy) loose into the free pool (§6.9). */
|
|
57
|
+
export function tearBoundNear(bound, waves, cx, cy, radius, W, H, time, spawn) {
|
|
58
|
+
for (let i = bound.length - 1; i >= 0; i--) {
|
|
59
|
+
const p = bound[i];
|
|
60
|
+
if (!p)
|
|
61
|
+
continue;
|
|
62
|
+
const w = waves[p.wi];
|
|
63
|
+
if (!w)
|
|
64
|
+
continue;
|
|
65
|
+
const x = p.progress * W;
|
|
66
|
+
const y = waveYat(w, x, time, H) + p.phase * 32;
|
|
67
|
+
const dx = x - cx;
|
|
68
|
+
const dy = y - cy;
|
|
69
|
+
const d = Math.hypot(dx, dy);
|
|
70
|
+
if (d < radius && d > 0.5) {
|
|
71
|
+
const f = (1 - d / radius) * 4;
|
|
72
|
+
spawn({ x, y, vx: (dx / d) * f, vy: (dy / d) * f, size: p.size, heat: 0.9 });
|
|
73
|
+
const last = bound.pop();
|
|
74
|
+
if (last && i < bound.length)
|
|
75
|
+
bound[i] = last;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Force-tearing (§2.4): any force reaching a bound particle tears it loose into
|
|
81
|
+
* the free pool with a kick, so it then *feels* the force (otherwise the shimmer
|
|
82
|
+
* would ride the lines straight through a body). Selective gates act on free
|
|
83
|
+
* matter only, so only always/active bodies tear bound.
|
|
84
|
+
*/
|
|
85
|
+
export function tearBoundByForces(bound, waves, bodies, forces, W, H, time, spawn) {
|
|
86
|
+
// a body "exerts force" if it carries any non-modifier, non-source token — those are
|
|
87
|
+
// the ones whose apply() actually pushes matter. Modifiers (resonate/spotlight) and
|
|
88
|
+
// pure sources (spawn) don't move existing matter, so they never tear bound particles.
|
|
89
|
+
const exertsForce = (b) => b.tokens.some((t) => {
|
|
90
|
+
const f = forces[t];
|
|
91
|
+
return !!f && !f.modify && !f.source;
|
|
92
|
+
});
|
|
93
|
+
for (let i = bound.length - 1; i >= 0; i--) {
|
|
94
|
+
const p = bound[i];
|
|
95
|
+
if (!p)
|
|
96
|
+
continue;
|
|
97
|
+
const w = waves[p.wi];
|
|
98
|
+
if (!w)
|
|
99
|
+
continue;
|
|
100
|
+
const x = p.progress * W;
|
|
101
|
+
const y = waveYat(w, x, time, H) + p.phase * 32;
|
|
102
|
+
let hit = false;
|
|
103
|
+
let kx = 0;
|
|
104
|
+
let ky = 0;
|
|
105
|
+
for (const b of bodies) {
|
|
106
|
+
if (!b.vis)
|
|
107
|
+
continue;
|
|
108
|
+
if (b.when === 'active' && !b.on)
|
|
109
|
+
continue;
|
|
110
|
+
if (b.when && b.when !== 'active')
|
|
111
|
+
continue; // selective → free agents only
|
|
112
|
+
const toks = b.tokens;
|
|
113
|
+
const dx = b.cx - x;
|
|
114
|
+
const dy = b.cy - y;
|
|
115
|
+
const dist = Math.hypot(dx, dy) || 1;
|
|
116
|
+
const range = b.range * (b.on ? 1.4 : 1);
|
|
117
|
+
if (toks.indexOf('wall') >= 0) {
|
|
118
|
+
const pad = 6;
|
|
119
|
+
if (Math.abs(x - b.cx) < b.hw + pad && Math.abs(y - b.cy) < b.hh + pad) {
|
|
120
|
+
kx = (x < b.cx ? -1 : 1) * 1.6;
|
|
121
|
+
ky = (y < b.cy ? -1 : 1) * 0.8;
|
|
122
|
+
hit = true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (!hit && (toks.indexOf('attract') >= 0 || toks.indexOf('sink') >= 0 || toks.indexOf('jet') >= 0)) {
|
|
126
|
+
if (dist < range * 0.8) {
|
|
127
|
+
const k = 1.2 + (b.on ? 1.6 : 0);
|
|
128
|
+
kx = (dx / dist) * k;
|
|
129
|
+
ky = (dy / dist) * k;
|
|
130
|
+
hit = true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (!hit && toks.indexOf('repel') >= 0 && dist < range * 0.8) {
|
|
134
|
+
const k = 1.2 + (b.on ? 1.2 : 0);
|
|
135
|
+
kx = -(dx / dist) * k;
|
|
136
|
+
ky = -(dy / dist) * k;
|
|
137
|
+
hit = true;
|
|
138
|
+
}
|
|
139
|
+
if (!hit && toks.indexOf('swirl') >= 0 && dist < range * 0.75) {
|
|
140
|
+
kx = (dy / dist) * 1.2;
|
|
141
|
+
ky = -(dx / dist) * 1.2;
|
|
142
|
+
hit = true;
|
|
143
|
+
}
|
|
144
|
+
if (!hit && toks.indexOf('stream') >= 0 && dist < range * 0.75) {
|
|
145
|
+
kx = b.ux * 1.3;
|
|
146
|
+
ky = b.uy * 1.3;
|
|
147
|
+
hit = true;
|
|
148
|
+
}
|
|
149
|
+
// every other force-bearing body — gravity, charge, thermal, collide, diffuse,
|
|
150
|
+
// propagate, cohesion, pressure, viscosity, tether, … — also frees nearby bound matter,
|
|
151
|
+
// with a gentle inward nudge, so the integrator's real force can act on it. A force
|
|
152
|
+
// can't reach a particle that's riding a wave line; without this, only the seven
|
|
153
|
+
// canonical tokens above ever disturbed the resting field. Gentle forces then read
|
|
154
|
+
// gently and strong ones strongly, since the real apply() pass does the shaping (§2.4).
|
|
155
|
+
if (!hit && dist < range * 0.8 && exertsForce(b)) {
|
|
156
|
+
const k = 0.8 + (b.on ? 0.8 : 0);
|
|
157
|
+
kx = (dx / dist) * k;
|
|
158
|
+
ky = (dy / dist) * k;
|
|
159
|
+
hit = true;
|
|
160
|
+
}
|
|
161
|
+
if (hit)
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
if (hit) {
|
|
165
|
+
spawn({ x, y, vx: kx, vy: ky, size: p.size, heat: 0.5 });
|
|
166
|
+
const last = bound.pop();
|
|
167
|
+
if (last && i < bound.length)
|
|
168
|
+
bound[i] = last;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Charge induction (§20.10) — a *field-level* polarization, separate from the force.
|
|
174
|
+
*
|
|
175
|
+
* The pure `charge`/`magnetism` force ignores neutral matter (`q = 0 → return`), so on
|
|
176
|
+
* the live field — where every particle starts neutral — it would do nothing at all. A
|
|
177
|
+
* charge or magnetism body therefore polarizes the matter that enters its field: a
|
|
178
|
+
* neutral particle picks up a sign by which side of the body it sits on, splitting the
|
|
179
|
+
* region into the +/- domains the force then sorts. Charge is induced once — matter
|
|
180
|
+
* carries its sign thereafter — so an already-charged particle is never overwritten.
|
|
181
|
+
*
|
|
182
|
+
* This lives here, not in the force's `apply`, on purpose: the bare integrator (which the
|
|
183
|
+
* conformance suite drives) never runs it, so the force's golden contract ("ignores
|
|
184
|
+
* neutral matter") stays exactly true; only the live field, which calls this each frame,
|
|
185
|
+
* has charged matter for the force to push.
|
|
186
|
+
*/
|
|
187
|
+
export function induceCharges(bodies, particles) {
|
|
188
|
+
for (const b of bodies) {
|
|
189
|
+
if (!b.vis)
|
|
190
|
+
continue;
|
|
191
|
+
if (b.tokens.indexOf('charge') < 0 && b.tokens.indexOf('magnetism') < 0)
|
|
192
|
+
continue;
|
|
193
|
+
if (b.range <= 0)
|
|
194
|
+
continue; // a global (range 0) charge field has no side to polarize by
|
|
195
|
+
const r2 = b.range * b.range;
|
|
196
|
+
for (const p of particles) {
|
|
197
|
+
if (p.charge)
|
|
198
|
+
continue; // already signed — matter carries its charge
|
|
199
|
+
const dx = b.cx - p.x;
|
|
200
|
+
const dy = b.cy - p.y;
|
|
201
|
+
if (dx * dx + dy * dy >= r2)
|
|
202
|
+
continue;
|
|
203
|
+
p.charge = dx >= 0 ? 1 : -1; // polarize by side → a two-domain +/- split
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=reservoir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reservoir.js","sourceRoot":"","sources":["../../src/core/reservoir.ts"],"names":[],"mappings":"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"}
|