graphic design tool
git clone https://git.lucas.co/cce-designer.git
feat: the pull's Strength is a slider
A slider over 0..2 with one in the middle, stepping by 0.05, where it
was a box to type a number into: Strength is set by hand and by eye. It
still takes an expression, which is shown as text like any other and is
not clamped to the range.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CLAUDE.md | 6 ++++--
nodes/attribute.json | 5 ++++-
src/main.rs | 9 +++++++++
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index 8424c87..4313ac9 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1815,7 +1815,8 @@ unscaled on `pull_arrow_pairs`, and `rebuild_pull_arrow_verts` stretches
each arrow from its fixed base, so a slider drag re-evaluates nothing.
**Strength and Scale By scale the pull** (the Attribute node's Modify,
-since 2026-09-29). `Strength` is a `float`, `Scale By` an `attribute`
+since 2026-09-29). `Strength` is a `slider` over 0..2 with one in the
+middle (a `float` box for its first day), `Scale By` an `attribute`
naming a point attribute whose value weighs each point; the amount that
lands at a point is their product. They scale the EFFECT — the change the
node makes, `old + (combined - old) * amount` — so they mean one thing
@@ -1823,7 +1824,8 @@ under every Combine: an Add moves by that much of Value, a Set goes that
far toward it, a Multiply that far toward the product. Two rows rather
than a longer vector because the Value row is text holding three numbers
and takes no expression per component, while Strength is a number: `$F /
-10` ramps a pull in, and the trackball keeps the direction while one
+10` ramps a pull in (an expression is not clamped to the slider's range;
+a value set on the slider or typed into its readout is), and the trackball keeps the direction while one
slider sets how hard. At an amount of exactly one the combined value is
written as it always was, bit for bit, so a save from before the rows
(which the template merge gives a Strength of 1) solves to the same
diff --git a/nodes/attribute.json b/nodes/attribute.json
index b0bcd84..f5cd4eb 100644
--- a/nodes/attribute.json
+++ b/nodes/attribute.json
@@ -39,8 +39,11 @@
},
{
"name": "Strength",
- "type": "float",
+ "type": "slider",
"default": "1.00",
+ "min": 0.0,
+ "max": 2.0,
+ "step": 0.05,
"show_when": "Operation == Modify"
},
{
diff --git a/src/main.rs b/src/main.rs
index 6d89c97..955548a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4250,6 +4250,15 @@ mod tests {
assert_eq!(kind(ty, name), K::Float, "{ty}'s {name}");
}
assert_eq!(kind("neighbour", "Constant"), K::Float3);
+ // The pull's Strength is a slider over none-to-double, one in the
+ // middle: a number set by hand and by eye, where the `float` it
+ // was for a day is a box to type into. It still takes an
+ // expression, shown as text like any other.
+ let strength = root.children.iter().find(|t| t.node_type == "attribute").unwrap()
+ .params.iter().find(|p| p.name == "Strength").expect("attribute has a Strength");
+ assert_eq!(strength.kind(), K::Slider);
+ assert_eq!(strength.range().map(|(lo, hi, _)| (lo, hi)), Some((0.0, 2.0)));
+ assert_eq!(strength.text(), "1.00");
for (ty, name) in [
("attribute", "Attribute Name"), ("attribute", "Source B"), ("visualize", "Attribute"), ("neighbour", "Attribute"),
("neighbour", "Direction"), ("neighbour", "Source"), ("distance", "Direction"), ("develop", "Source"),