Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion engraphis/dashboard_assets/engraphis-graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -9320,10 +9320,17 @@
fg.linkDirectionalArrowLength(dense ? 0 : 0.625).linkDirectionalArrowRelPos(1);
applyLinkLabels();
if (fg.linkDirectionalParticles) {
const flowSpeed = Number(state.settings.flowSpeed);
/* flowSpeed=0 means "stop" — particles must not render at all. The every-node engine
already enforces this via a `moving = speed > 0` check; the compat engine must do
the same. Otherwise the slider visibly does nothing at the low end (particles keep
crawling at the residual 0.002 floor). */
const flowActive = Number.isFinite(flowSpeed) ? flowSpeed > 0 : true;
const flowing = !fullGraph
&& state.settings.flow !== false
&& motion
&& !reducedMotion
&& flowActive
Comment thread
Coding-Dev-Tools marked this conversation as resolved.
Outdated
&& data.links.length <= PARTICLE_LINK_LIMIT;
const particles = !flowing
? 0
Expand All @@ -9332,7 +9339,10 @@
.linkDirectionalParticleWidth(1)
.linkDirectionalParticleCanvasObject(paintFlowArrow)
.linkDirectionalParticleColor(l => alpha(layerColor(l.layer), 0.95))
.linkDirectionalParticleSpeed(l => 0.002 + ((state.settings.flowSpeed || 45) / 100) * 0.008);
/* Widened from `0.002 + (flowSpeed/100)*0.008` (a 5x range, 0.002..0.01) to
`0.0005 + (flowSpeed/100)*0.025` (a ~34x range, 0.00075..0.0255) so the slider
is visibly responsive end-to-end. */
.linkDirectionalParticleSpeed(l => flowActive ? (0.0005 + (flowSpeed / 100) * 0.025) : 0);
Comment thread
Coding-Dev-Tools marked this conversation as resolved.
}
if (!galaxyMode && reheat && motion && !staticFullLayout && !state.settings.frozen) {
prepareReheat();
Expand Down
50 changes: 50 additions & 0 deletions tests/test_graph_engine_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -10631,6 +10631,56 @@ def test_physics_sliders_reheat_the_simulation_the_way_the_classic_renderer_does
assert report["reducedMotion"] == 1, "reduced motion silently disabled live physics"


@requires_node
def test_flow_speed_slider_has_a_visible_range_in_compat_engine() -> None:
"""The compat engine's flow-speed slider must produce a visibly larger particle speed at
the top of the range than at the bottom. Earlier the speed formula
`0.002 + (flowSpeed/100)*0.008` produced a 5x range (0.002..0.01) that was too small to be
noticeable end-to-end. The fix widens that to a 34x range
(`0.0005 + (flowSpeed/100)*0.025` -> 0.00075..0.0255). The test snapshots the per-link
speed closure at the two ends of the slider and asserts the high end is materially
larger than the low end.
"""
report = _run_engine(
"""
const api = G.create(el, {});
api.setPreset('compact');
api.setData(chain(40));
const linkForSample = { layer: 'semantic' };
const sample = (flowSpeed) => {
api.setSettings({ flowSpeed, flow: true });
// linkDirectionalParticleSpeed is a chainable setter; the engine has stored a
// per-link function on the stub. Sample it on a non-suggested, non-ghost link.
const speedFn = store.linkDirectionalParticleSpeed;
return typeof speedFn === 'function' ? speedFn(linkForSample) : null;
};
const low = sample(1);
const mid = sample(50);
const high = sample(100);
const stop = sample(0);
emit({ low, mid, high, stop });
"""
)
# At flowSpeed=0 the engine short-circuits the closure to 0 (particles do not move).
assert report["stop"] == 0, (
f"flowSpeed=0 must yield particle speed 0 (compat engine stop-at-zero), "
f"got {report['stop']}"
)
# At flowSpeed=1 the closure must return a non-zero, low-end value.
assert report["low"] > 0, f"flowSpeed=1 must yield non-zero speed, got {report['low']}"
# End-to-end the slider must show a wide range: high is materially larger than low.
# The fix targets a 34x range; allow some headroom for d3 stub arithmetic.
assert report["high"] >= report["low"] * 10, (
f"flowSpeed slider must produce a visible range (>=10x low-to-high). "
f"low={report['low']} high={report['high']}"
)
# Monotonicity: low < mid < high.
assert report["low"] < report["mid"] < report["high"], (
f"flow speed must be monotonic in the slider value: low={report['low']} "
f"mid={report['mid']} high={report['high']}"
)


@requires_node
def test_full_graph_within_the_force_budget_keeps_centre_gravity_live() -> None:
"""Full mode must not turn a normal large workspace into a pinned, inert ring.
Expand Down