startshape START[b .5]
shape START{
recurse([s .95 b .1],CIRCLE)[]
recurse([s .95 b -.1],TRIANGLE)[x 1]
recurse([s .95 h -5 r 3 a .05],SQUARE)[x 2 b 1 sat 1 a -1]
recurse([s .95 h -5 r -5 a -.05],NGON(5))[x 3 b 1 sat 1]
A[y -1.1]
B[y -1.1 x 1]
C[y -1.1 x 2 b 1 sat 1 a -1]
D[y -1.1 x 3 b 1 sat 1]
}
shape A{CIRCLE[] A[s .95 b .1]}
shape B{TRIANGLE[] B[s .95 b -.1]}
shape C{SQUARE[] C[s .95 h -5 r 3 a .05]}
shape D{NGON(5)[] D[s .95 h -5 r -5 a -.05]}
shape recurse(adjustment change, shape thingie)
{
thingie[] // invoke thingie with parameters already bound
recurse(=) [transform change] // can be abbreviated as trans
}
path NGON(number n){
MOVETO(0,.5)
loop n [r (360/n)] LINETO(0,.5)
CLOSEPOLY()
}
produces this
transform-param-bug.png (42.1 KiB) Viewed 55647 times
So it looks like any saturation/brightness/alpha values in a transform parameter are being pinned to [0,1]. I suppose it shouldn't do this without prior knowledge of this attribute of the shape it is applied to. As the code shows, it does this whether or not it is a valid adjustment to the parent shape.
Hue seems OK.
I haven't checked two-value versions of these adjustments.
Ugh. I thought that I handled this situation, but it looks like I didn't. The ultimate cause is mathematical. The world state of a shape has four parts: geometry, Z, time, and color (there is also a random number seed). Geometry, Z, and time adjustments are all associative, [[s 1.05 s 1.05]] is exactly the same as [s (1.05*1.05)]. Hue adjustments are associative as long as you don't use the two value form.
But brightness, saturation and alpha adjustments are not associative. [[b 0.5 b 0.5]] cannot be replaced with a single [b n]. You have to hang onto both of those b 0.5 adjustments and apply them sequentially when it is time to do a shape replacement. This doesn't play nicely at all with CF3 adjustment variables and shape parameters.
If we had known in 2005 that associativity was a useful property for color components then we wouldn't be in this predicament today. But I can fix things so that a single color component change can be stored in a parameter. Some kind of warning will be issued if a design tries to accumulate more than one color change in a variable or parameter.