Add a driver to a red bone and set the world x-positions of the blue bones as two variables in the driver editor.
Initially, $L_1 = 0$ and $L_2 = 3$ with your setup.
Then, check Use Self in the driver and enable Auto-Execution for python script in the preferences.
We need the original x-position of the red bone in regards to the space between $L_1$ and $L_2$. But we can't read and write its x-position at the same time. You will either have to use and alternate bone for supplying the initial position (like a parent bone), hard-code the starting value or use the rest position of the armature. I will use the rest position. We shall assume, that the system is not rotated via a parent, and we can rely on only the x-values.
To access the edit bone (which holds the rest position) from the pose bone, use this expression: self.bone.matrix_local.to_4x4().to_translation().x
. We need to use the matrix_local
in order to get world coordinates.
If the edit bone's global x-position was $1$, the driver would show the following.
Next, normalize the position to the range $(L_1, L_2)$.
(self.bone.matrix_local.to_4x4().to_translation().x - L1) / (L2-L1)
To prevent a division by zero (when L1 and L2 share the same x-position), add a max()
expression, to stop L2-l1
from going below 0. Since we have fitted the range of $(0, 1)$ between the blue bones, multiply by your desired range $(0, 0.1)$ at the end.
[...] / max(0.001, L2-L1)) * 0.1
To clamp self.bone.matrix_local.to_4x4().to_translation().x - L1
to the range $(0, 1), use a min(1, [...])
and max(0, [...])` expression.
Python does not have a clamp function.
This is the resulting expression.
min(1, max(0, self.bone.matrix_local.to_4x4().to_translation().x - L1) / max(0.001, L2-L1)) * 0.1
Right click on the driven property and copy-paste it the remaining red bones.
We don't need to alter the expression, because it uses self
to target its own rest pose location and L1/L2 are shared by all red bones.