; @param pparent typically 'this' from the parent or zero func MMF_UserGradient(Generic pparent) m_Parent = pparent endfunc ;
; @param i gradient index ; @return colour from gradient color func GetColour(float i) return RGBA(0,0,0,1) endfunc default: int param v_mmfgradientbase caption = "Version (MMF_GradientBase)" default = 100 hint = "This version parameter is used to detect when a change \ has been made to the formula that is incompatible with \ the previous version. When that happens, this field will \ reflect the old version number to alert you to the fact \ that an alternate rendering is being used." visible = @v_mmfgradientbase < 100 endparam } class MMF_DefaultGradient(MMF_UserGradient) { public: import "common.ulb" ;
; @param pparent typically 'this' from the parent or zero func MMF_UserGradient(Generic pparent) m_Parent = pparent endfunc ;
; @param i gradient index ; @return colour from gradient color func GetColour(float i) return gradient(i) endfunc default: title = "MMF Default Gradient" } class MMF_Gradient101(MMF_UserGradient) { import "common.ulb" ;
; @param pparent typically 'this' from the parent or zero
func MMF_Gradient101(Generic pparent)
m_Parent = pparent
m_Transfer = new @f_transfer(this)
col[1] = @col1
pstn[1] = @pos1/400.0
col[2] = @col2
pstn[2] = @pos2/400.0
col[3] = @col3
pstn[3] = @pos3/400.0
col[4] = @col4
pstn[4] = @pos4/400.0
col[5] = @col5
pstn[5] = @pos5/400.0
col[6] = @col6
pstn[6] = @pos6/400.0
col[7] = @col7
pstn[7] = @pos7/400.0
col[8] = @col8
pstn[8] = @pos8/400.0
col[9] = @col9
pstn[9] = @pos9/400.0
col[10] = @col10
pstn[10] = @pos10/400.0
col[11] = @col11
pstn[11] = @pos11/400.0
col[12] = @col12
pstn[12] = @pos12/400.0
col[13] = @col13
pstn[13] = @pos13/400.0
col[14] = @col14
pstn[14] = @pos14/400.0
col[15] = @col15
pstn[15] = @pos15/400.0
col[16] = @col16
pstn[16] = @pos16/400.0
col[17] = @col17
pstn[17] = @pos17/400.0
col[18] = @col18
pstn[18] = @pos18/400.0
col[19] = @col19
pstn[19] = @pos19/400.0
col[20] = @col20
pstn[20] = @pos20/400.0
col[21] = @col21
pstn[21] = @pos21/400.0
col[22] = @col22
pstn[22] = @pos22/400.0
col[23] = @col23
pstn[23] = @pos23/400.0
col[24] = @col24
pstn[24] = @pos24/400.0
col[25] = @col25
pstn[25] = @pos25/400.0
col[26] = @col26
pstn[26] = @pos26/400.0
col[27] = @col27
pstn[27] = @pos27/400.0
col[28] = @col28
pstn[28] = @pos28/400.0
col[29] = @col29
pstn[29] = @pos29/400.0
col[30] = @col30
pstn[30] = @pos30/400.0
col[31] = @col31
pstn[31] = @pos31/400.0
col[32] = @col32
pstn[32] = @pos32/400.0
col[33] = @col33
pstn[33] = @pos33/400.0
col[34] = @col34
pstn[34] = @pos34/400.0
col[35] = @col35
pstn[35] = @pos35/400.0
col[36] = @col36
pstn[36] = @pos36/400.0
col[37] = @col37
pstn[37] = @pos37/400.0
col[38] = @col38
pstn[38] = @pos38/400.0
col[39] = @col39
pstn[39] = @pos39/400.0
col[40] = @col40
pstn[40] = @pos40/400.0
col[41] = @col41
pstn[41] = @pos41/400.0
col[42] = @col42
pstn[42] = @pos42/400.0
col[43] = @col43
pstn[43] = @pos43/400.0
col[44] = @col44
pstn[44] = @pos44/400.0
col[45] = @col45
pstn[45] = @pos45/400.0
col[46] = @col46
pstn[46] = @pos46/400.0
col[47] = @col47
pstn[47] = @pos47/400.0
col[48] = @col48
pstn[48] = @pos48/400.0
col[49] = @col49
pstn[49] = @pos49/400.0
col[50] = @col50
pstn[50] = @pos50/400.0
col[51] = @col51
pstn[51] = @pos51/400.0
col[52] = @col52
pstn[52] = @pos52/400.0
col[53] = @col53
pstn[53] = @pos53/400.0
col[54] = @col54
pstn[54] = @pos54/400.0
col[55] = @col55
pstn[55] = @pos55/400.0
col[56] = @col56
pstn[56] = @pos56/400.0
col[57] = @col57
pstn[57] = @pos57/400.0
col[58] = @col58
pstn[58] = @pos58/400.0
col[59] = @col59
pstn[59] = @pos59/400.0
col[60] = @col60
pstn[60] = @pos60/400.0
col[61] = @col61
pstn[61] = @pos61/400.0
col[62] = @col62
pstn[62] = @pos62/400.0
col[63] = @col63
pstn[63] = @pos63/400.0
col[64] = @col64
pstn[64] = @pos64/400.0
col[65] = @col65
pstn[65] = @pos65/400.0
col[66] = @col66
pstn[66] = @pos66/400.0
col[67] = @col67
pstn[67] = @pos67/400.0
col[68] = @col68
pstn[68] = @pos68/400.0
col[69] = @col69
pstn[69] = @pos69/400.0
col[70] = @col70
pstn[70] = @pos70/400.0
col[71] = @col71
pstn[71] = @pos71/400.0
col[72] = @col72
pstn[72] = @pos72/400.0
col[73] = @col73
pstn[73] = @pos73/400.0
col[74] = @col74
pstn[74] = @pos74/400.0
col[75] = @col75
pstn[75] = @pos75/400.0
col[76] = @col76
pstn[76] = @pos76/400.0
col[77] = @col77
pstn[77] = @pos77/400.0
col[78] = @col78
pstn[78] = @pos78/400.0
col[79] = @col79
pstn[79] = @pos79/400.0
col[80] = @col80
pstn[80] = @pos80/400.0
col[81] = @col81
pstn[81] = @pos81/400.0
col[82] = @col82
pstn[82] = @pos82/400.0
col[83] = @col83
pstn[83] = @pos83/400.0
col[84] = @col84
pstn[84] = @pos84/400.0
col[85] = @col85
pstn[85] = @pos85/400.0
col[86] = @col86
pstn[86] = @pos86/400.0
col[87] = @col87
pstn[87] = @pos87/400.0
col[88] = @col88
pstn[88] = @pos88/400.0
col[89] = @col89
pstn[89] = @pos89/400.0
col[90] = @col90
pstn[90] = @pos90/400.0
col[91] = @col91
pstn[91] = @pos91/400.0
col[92] = @col92
pstn[92] = @pos92/400.0
col[93] = @col93
pstn[93] = @pos93/400.0
col[94] = @col94
pstn[94] = @pos94/400.0
col[95] = @col95
pstn[95] = @pos95/400.0
col[96] = @col96
pstn[96] = @pos96/400.0
col[97] = @col97
pstn[97] = @pos97/400.0
col[98] = @col98
pstn[98] = @pos98/400.0
col[99] = @col99
pstn[99] = @pos99/400.0
col[100] = @col100
pstn[100] = @pos100/400.0
int i = 0
repeat
col[i] = col[i+1]
pstn[i] = pstn[i+1]
until (i=i+1)>=100
col[100] = @col101
pstn[100] = @pos101/400.0
if @numcols>1
i = 0
repeat
float min = pstn[i]
int k = i
int j = i + 1
repeat
if pstn[j]
; @param i gradient index
; @return colour from gradient
color func GetColour(float i)
if @showpalette
i = real(#screenpixel)/#width
else
i = m_Transfer.Iterate(i)
endif
if @numcols==1
return col[0]
endif
if @rept
if (i = i%1)<0.0
i = i + 1.0
endif
elseif i<0.0
i = 0.0
elseif i>399.0/400.0
i = 399.0/400.0
endif
int j = -1
int k = 0
repeat
j = j + 1
until pstn[j]>i || j>=@numcols
if j>=@numcols
j = 0
k = @numcols - 1
elseif (k=j-1)<0
k = @numcols - 1
endif
float d = pstn[j] - pstn[k]
float v = i - pstn[k]
if d<0.0
d = 1.0 + d
if d==0.0
d = 1.0
endif
endif
if v<0.0
v = 1.0 + v
endif
if @smooth
; Our point is between p1 at x1 with height h1 and p2 at x2 with height h2
; First if h1==h2 then h==h1
; Else get gradient g1 at p1 and g2 at p2 and use:
;
; h = ax^3 + bx^2 + cx + d
; g = 3*a*x^2 + 2*b*x + c
;
; h1 = a*x1^3 +b*x1^2 + c*x1 + d
; g1 = 3*a*x1^2 + 2*b*x1 + c
; h2 = a*x2^3 + b*x2^2 + c*x2 + d
; g2 = 3*a*x2^2 + 2*b*x2 + c
;
; But we can use 0 for x1 and (x2-x1) for x2, giving:
;
; h1 = d
; g1 = c
; h2 = a*(x2-x1)^3 + b*(x2-x1)^2 + c*(x2-x1) + d
; g2 = 3*a*(x2-x1)^2 + 2*b*(x2-x1) + c
;
; Hence:
;
; a*(x2-x1)^3 + b*(x2-x1)^2 + g1*(x2-x1) + h1 = h2
; 3*a*(x2-x1)^2 + 2*b*(x2-x1) + g1 = g2
;
; a = (g2 - g1 - 2*b*(x2-x1))/(3*(x2-x1)^2)
;
; (g2-g1)(x2-x1)/3 - 2*b*(x2-x1)^2/3 + b*(x2-x1)^2 + g1*(x2-x1) + h1 = h2
;
; (2*g1+g2)(x2-x1)/3 + b*(x2-x1)^2/3 + h1 = h2
;
; b = 3*(h2-h1)/(x2-x1)^2 - (2*g1+g2)/(x2-x1)
;
; h1
float r1 = red(col[k])
float g1 = green(col[k])
float b1 = blue(col[k])
float a1 = alpha(col[k])
; h2
float r2 = red(col[j])
float g2 = green(col[j])
float b2 = blue(col[j])
float a2 = alpha(col[j])
if r1==r2 && g1==g2 && b1==b2 && a1==a2
return col[k]
endif
; g1
float gr1 = 0.0
float gg1 = 0.0
float gb1 = 0.0
float ga1 =0.0
; g2
float gr2 = 0.0
float gg2 = 0.0
float gb2 = 0.0
float ga2 = 0.0
; temp gradients
float id = 1.0/d
float tr = (red(col[j])-red(col[k]))*id
float tg = (green(col[j])-green(col[k]))*id
float tb = (blue(col[j])-blue(col[k]))*id
float ta = (alpha(col[j])-alpha(col[k]))*id
int l = k - 1
int m = j + 1
if l<0
l = @numcols - 1
if pstn[k]==0.0 && pstn[l]==1.0
l = k
endif
endif
if m>=@numcols
m = 0
if pstn[j]==1.0 && pstn[m]==0.0
m = j
endif
endif
if pstn[l]==pstn[k]
gr1 = gg1 = gb1 = ga1 = 0.0
else
float d1 = pstn[k] - pstn[l]
if d1<0.0
d1 = d1 + 1.0
endif
d1 = 1.0/d1
gr1 = (red(col[k])-red(col[l]))*d1
gg1 = (green(col[k])-green(col[l]))*d1
gb1 = (blue(col[k])-blue(col[l]))*d1
ga1 = (alpha(col[k])-alpha(col[l]))*d1
if (gr1>=0.0 && tr<=0.0) || (gr1<=0.0 && tr>=0.0)
gr1 = 0.0
else
gr1 = 0.5*(gr1 + tr)
endif
if (gg1>=0.0 && tg<=0.0) || (gg1<=0.0 && tg>=0.0)
gg1 = 0.0
else
gg1 = 0.5*(gg1 + tg)
endif
if (gb1>=0.0 && tb<=0.0) || (gb1<=0.0 && tb>=0.0)
gb1 = 0.0
else
gb1 = 0.5*(gb1 + tb)
endif
if (ga1>=0.0 && ta<=0.0) || (ga1<=0.0 && ta>=0.0)
ga1 = 0.0
else
ga1 = 0.5*(ga1 + ta)
endif
endif
if pstn[m]==pstn[j]
gr2 = gg2 = gb2 = ga2 = 0.0
else
float d1 = pstn[m] - pstn[j]
if d1<0.0
d1 = d1 + 1.0
endif
d1 = 1.0/d1
gr2 = (red(col[m])-red(col[j]))*d1
gg2 = (green(col[m])-green(col[j]))*d1
gb2 = (blue(col[m])-blue(col[j]))*d1
ga2 = (alpha(col[m])-alpha(col[j]))*d1
if (gr2>=0.0 && tr<=0.0) || (gr2<=0.0 && tr>=0.0)
gr2 = 0.0
else
gr2 = 0.5*(gr2 + tr)
endif
if (gg2>=0.0 && tg<=0.0) || (gg2<=0.0 && tg>=0.0)
gg2 = 0.0
else
gg2 = 0.5*(gg2 + tg)
endif
if (gb2>=0.0 && tb<=0.0) || (gb2<=0.0 && tb>=0.0)
gb2 = 0.0
else
gb2 = 0.5*(gb2 + tb)
endif
if (ga2>=0.0 && ta<=0.0) || (ga2<=0.0 && ta>=0.0)
ga2 = 0.0
else
ga2 = 0.5*(ga2 + ta)
endif
endif
; b = 3*(h2-h1)/(x2-x1)^2 - (2*g1+g2)/(x2-x1)
; a = (g2 - g1 - 2*b*(x2-x1))/(3*(x2-x1)^2)
; h = ax^3 + bx^2 + cx + d
float a = 0.0
float b = 0.0
if r1!=r2
b = 3*(r2-r1)*sqr(id) - (2*gr1+gr2)*id
a = (gr2-gr1-2.0*b*d)*sqr(id)/3
r1 = a*v^3 + b*sqr(v) + gr1*v + r1
endif
if g1!=g2
b = 3*(g2-g1)*sqr(id) - (2*gg1+gg2)*id
a = (gg2-gg1-2.0*b*d)*sqr(id)/3
g1 = a*v^3 + b*sqr(v) + gg1*v + g1
endif
if b1!=b2
b = 3*(b2-b1)*sqr(id) - (2*gb1+gb2)*id
a = (gb2-gb1-2.0*b*d)*sqr(id)/3
b1 = a*v^3 + b*sqr(v) + gb1*v + b1
endif
if a1!=a2
b = 3*(a2-a1)*sqr(id) - (2*ga1+ga2)*id
a = (ga2-ga1-2.0*b*d)*sqr(id)/3
a1 = a*v^3 + b*sqr(v) + ga1*v + a1
endif
return RGBA(r1,g1,b1,a1)
else
return col[k] + (col[j] - col[k])*v/d
endif
endfunc
private:
Transfer m_Transfer
color col[101]
float pstn[101]
default:
title = "MMF Gradient 101"
rating = recommended
int param v_mmfgradient101
caption = "Version (MMF Gradient 101)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
heading
caption = "Gradient Control"
endheading
Transfer param f_transfer
caption = "Gradient Transfer"
default = DefaultGradientTransfer
hint = "Use to modify the value from the colouring before the colour \
is looked up in the gradient."
visible = !@showpalette
endparam
bool param rept
caption = "Repeat Gradient ?"
default = true
endparam
bool param smooth
caption = "Smooth Curves ?"
default = true
endparam
bool param showpalette
caption = "Show Gradient Only"
default = false
hint = "When enabled the gradient is shown as vertical stripes on the \
fractal, position 0.0 to the left and 1.0 to the right."
endparam
int param numcols
caption = "Number of Key Colours"
default = 4
min = 1
max = 101
hint = "You can specify from 1 to 101 key colours in your gradient, \
each of which can be at any position in the gradient from \
>=0.0 to <=400.0"
endparam
heading
caption = "Key Colour 1"
endheading
color param col1
caption = "Colour"
default = RGBA(0,0,0.52156862745098039215686274509804,1)
endparam
float param pos1
caption = "Gradient Index"
default = 0.0
min = 0.0
max = 400.0
endparam
heading
caption = "Key Colour 2"
visible = @numcols>=2
endheading
color param col2
caption = "Colour"
default = RGBA(1,1,1,1)
visible = @numcols>=2
endparam
float param pos2
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=2
endparam
heading
caption = "Key Colour 3"
visible = @numcols>=3
endheading
color param col3
caption = "Colour"
default = RGBA(1,0.70980392156862745098039215686275,0,1)
visible = @numcols>=3
endparam
float param pos3
caption = "Gradient Index"
default = 200.0
min = 0.0
max = 400.0
visible = @numcols>=3
endparam
heading
caption = "Key Colour 4"
visible = @numcols>=4
endheading
color param col4
caption = "Colour"
default = RGBA(0.61176470588235294117647058823529,0,0,1)
visible = @numcols>=4
endparam
float param pos4
caption = "Gradient Index"
default = 300.0
min = 0.0
max = 400.0
visible = @numcols>=4
endparam
heading
caption = "Key Colour 5"
visible = @numcols>=5
endheading
color param col5
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=5
endparam
float param pos5
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=5
endparam
heading
caption = "Key Colour 6"
visible = @numcols>=6
endheading
color param col6
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=6
endparam
float param pos6
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=6
endparam
heading
caption = "Key Colour 7"
visible = @numcols>=7
endheading
color param col7
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=7
endparam
float param pos7
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=7
endparam
heading
caption = "Key Colour 8"
visible = @numcols>=8
endheading
color param col8
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=8
endparam
float param pos8
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=8
endparam
heading
caption = "Key Colour 9"
visible = @numcols>=9
endheading
color param col9
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=9
endparam
float param pos9
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=9
endparam
heading
caption = "Key Colour 10"
visible = @numcols>=10
endheading
color param col10
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=10
endparam
float param pos10
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=10
endparam
heading
caption = "Key Colour 11"
visible = @numcols>=11
endheading
color param col11
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=11
endparam
float param pos11
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=11
endparam
heading
caption = "Key Colour 12"
visible = @numcols>=12
endheading
color param col12
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=12
endparam
float param pos12
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=12
endparam
heading
caption = "Key Colour 13"
visible = @numcols>=13
endheading
color param col13
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=13
endparam
float param pos13
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=13
endparam
heading
caption = "Key Colour 14"
visible = @numcols>=14
endheading
color param col14
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=14
endparam
float param pos14
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=14
endparam
heading
caption = "Key Colour 15"
visible = @numcols>=15
endheading
color param col15
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=15
endparam
float param pos15
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=15
endparam
heading
caption = "Key Colour 16"
visible = @numcols>=16
endheading
color param col16
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=16
endparam
float param pos16
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=16
endparam
heading
caption = "Key Colour 17"
visible = @numcols>=17
endheading
color param col17
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=17
endparam
float param pos17
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=17
endparam
heading
caption = "Key Colour 18"
visible = @numcols>=18
endheading
color param col18
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=18
endparam
float param pos18
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=18
endparam
heading
caption = "Key Colour 19"
visible = @numcols>=19
endheading
color param col19
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=19
endparam
float param pos19
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=19
endparam
heading
caption = "Key Colour 20"
visible = @numcols>=20
endheading
color param col20
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=20
endparam
float param pos20
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=20
endparam
heading
caption = "Key Colour 21"
visible = @numcols>=21
endheading
color param col21
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=21
endparam
float param pos21
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=21
endparam
heading
caption = "Key Colour 22"
visible = @numcols>=22
endheading
color param col22
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=22
endparam
float param pos22
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=22
endparam
heading
caption = "Key Colour 23"
visible = @numcols>=23
endheading
color param col23
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=23
endparam
float param pos23
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=23
endparam
heading
caption = "Key Colour 24"
visible = @numcols>=24
endheading
color param col24
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=24
endparam
float param pos24
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=24
endparam
heading
caption = "Key Colour 25"
visible = @numcols>=25
endheading
color param col25
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=25
endparam
float param pos25
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=25
endparam
heading
caption = "Key Colour 26"
visible = @numcols>=26
endheading
color param col26
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=26
endparam
float param pos26
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=26
endparam
heading
caption = "Key Colour 27"
visible = @numcols>=27
endheading
color param col27
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=27
endparam
float param pos27
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=27
endparam
heading
caption = "Key Colour 28"
visible = @numcols>=28
endheading
color param col28
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=28
endparam
float param pos28
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=28
endparam
heading
caption = "Key Colour 29"
visible = @numcols>=29
endheading
color param col29
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=29
endparam
float param pos29
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=29
endparam
heading
caption = "Key Colour 30"
visible = @numcols>=30
endheading
color param col30
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=30
endparam
float param pos30
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=30
endparam
heading
caption = "Key Colour 31"
visible = @numcols>=31
endheading
color param col31
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=31
endparam
float param pos31
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=31
endparam
heading
caption = "Key Colour 32"
visible = @numcols>=32
endheading
color param col32
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=32
endparam
float param pos32
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=32
endparam
heading
caption = "Key Colour 33"
visible = @numcols>=33
endheading
color param col33
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=33
endparam
float param pos33
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=33
endparam
heading
caption = "Key Colour 34"
visible = @numcols>=34
endheading
color param col34
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=34
endparam
float param pos34
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=34
endparam
heading
caption = "Key Colour 35"
visible = @numcols>=35
endheading
color param col35
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=35
endparam
float param pos35
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=35
endparam
heading
caption = "Key Colour 36"
visible = @numcols>=36
endheading
color param col36
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=36
endparam
float param pos36
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=36
endparam
heading
caption = "Key Colour 37"
visible = @numcols>=37
endheading
color param col37
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=37
endparam
float param pos37
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=37
endparam
heading
caption = "Key Colour 38"
visible = @numcols>=38
endheading
color param col38
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=38
endparam
float param pos38
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=38
endparam
heading
caption = "Key Colour 39"
visible = @numcols>=39
endheading
color param col39
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=39
endparam
float param pos39
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=39
endparam
heading
caption = "Key Colour 40"
visible = @numcols>=40
endheading
color param col40
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=40
endparam
float param pos40
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=40
endparam
heading
caption = "Key Colour 41"
visible = @numcols>=41
endheading
color param col41
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=41
endparam
float param pos41
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=41
endparam
heading
caption = "Key Colour 42"
visible = @numcols>=42
endheading
color param col42
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=42
endparam
float param pos42
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=42
endparam
heading
caption = "Key Colour 43"
visible = @numcols>=43
endheading
color param col43
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=43
endparam
float param pos43
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=43
endparam
heading
caption = "Key Colour 44"
visible = @numcols>=44
endheading
color param col44
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=44
endparam
float param pos44
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=44
endparam
heading
caption = "Key Colour 45"
visible = @numcols>=45
endheading
color param col45
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=45
endparam
float param pos45
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=45
endparam
heading
caption = "Key Colour 46"
visible = @numcols>=46
endheading
color param col46
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=46
endparam
float param pos46
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=46
endparam
heading
caption = "Key Colour 47"
visible = @numcols>=47
endheading
color param col47
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=47
endparam
float param pos47
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=47
endparam
heading
caption = "Key Colour 48"
visible = @numcols>=48
endheading
color param col48
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=48
endparam
float param pos48
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=48
endparam
heading
caption = "Key Colour 49"
visible = @numcols>=49
endheading
color param col49
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=49
endparam
float param pos49
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=49
endparam
heading
caption = "Key Colour 50"
visible = @numcols>=50
endheading
color param col50
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=50
endparam
float param pos50
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=50
endparam
heading
caption = "Key Colour 51"
visible = @numcols>=51
endheading
color param col51
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=51
endparam
float param pos51
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=51
endparam
heading
caption = "Key Colour 52"
visible = @numcols>=52
endheading
color param col52
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=52
endparam
float param pos52
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=52
endparam
heading
caption = "Key Colour 53"
visible = @numcols>=53
endheading
color param col53
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=53
endparam
float param pos53
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=53
endparam
heading
caption = "Key Colour 54"
visible = @numcols>=54
endheading
color param col54
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=54
endparam
float param pos54
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=54
endparam
heading
caption = "Key Colour 55"
visible = @numcols>=55
endheading
color param col55
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=55
endparam
float param pos55
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=55
endparam
heading
caption = "Key Colour 56"
visible = @numcols>=56
endheading
color param col56
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=56
endparam
float param pos56
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=56
endparam
heading
caption = "Key Colour 57"
visible = @numcols>=57
endheading
color param col57
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=57
endparam
float param pos57
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=57
endparam
heading
caption = "Key Colour 58"
visible = @numcols>=58
endheading
color param col58
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=58
endparam
float param pos58
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=58
endparam
heading
caption = "Key Colour 59"
visible = @numcols>=59
endheading
color param col59
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=59
endparam
float param pos59
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=59
endparam
heading
caption = "Key Colour 60"
visible = @numcols>=60
endheading
color param col60
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=60
endparam
float param pos60
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=60
endparam
heading
caption = "Key Colour 61"
visible = @numcols>=61
endheading
color param col61
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=61
endparam
float param pos61
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=61
endparam
heading
caption = "Key Colour 62"
visible = @numcols>=62
endheading
color param col62
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=62
endparam
float param pos62
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=62
endparam
heading
caption = "Key Colour 63"
visible = @numcols>=63
endheading
color param col63
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=63
endparam
float param pos63
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=63
endparam
heading
caption = "Key Colour 64"
visible = @numcols>=64
endheading
color param col64
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=64
endparam
float param pos64
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=64
endparam
heading
caption = "Key Colour 65"
visible = @numcols>=65
endheading
color param col65
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=65
endparam
float param pos65
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=65
endparam
heading
caption = "Key Colour 66"
visible = @numcols>=66
endheading
color param col66
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=66
endparam
float param pos66
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=66
endparam
heading
caption = "Key Colour 67"
visible = @numcols>=67
endheading
color param col67
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=67
endparam
float param pos67
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=67
endparam
heading
caption = "Key Colour 68"
visible = @numcols>=68
endheading
color param col68
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=68
endparam
float param pos68
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=68
endparam
heading
caption = "Key Colour 69"
visible = @numcols>=69
endheading
color param col69
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=69
endparam
float param pos69
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=69
endparam
heading
caption = "Key Colour 70"
visible = @numcols>=70
endheading
color param col70
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=70
endparam
float param pos70
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=70
endparam
heading
caption = "Key Colour 71"
visible = @numcols>=71
endheading
color param col71
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=71
endparam
float param pos71
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=71
endparam
heading
caption = "Key Colour 72"
visible = @numcols>=72
endheading
color param col72
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=72
endparam
float param pos72
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=72
endparam
heading
caption = "Key Colour 73"
visible = @numcols>=73
endheading
color param col73
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=73
endparam
float param pos73
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=73
endparam
heading
caption = "Key Colour 74"
visible = @numcols>=74
endheading
color param col74
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=74
endparam
float param pos74
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=74
endparam
heading
caption = "Key Colour 75"
visible = @numcols>=75
endheading
color param col75
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=75
endparam
float param pos75
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=75
endparam
heading
caption = "Key Colour 76"
visible = @numcols>=76
endheading
color param col76
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=76
endparam
float param pos76
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=76
endparam
heading
caption = "Key Colour 77"
visible = @numcols>=77
endheading
color param col77
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=77
endparam
float param pos77
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=77
endparam
heading
caption = "Key Colour 78"
visible = @numcols>=78
endheading
color param col78
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=78
endparam
float param pos78
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=78
endparam
heading
caption = "Key Colour 79"
visible = @numcols>=79
endheading
color param col79
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=79
endparam
float param pos79
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=79
endparam
heading
caption = "Key Colour 80"
visible = @numcols>=80
endheading
color param col80
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=80
endparam
float param pos80
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=80
endparam
heading
caption = "Key Colour 81"
visible = @numcols>=81
endheading
color param col81
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=81
endparam
float param pos81
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=81
endparam
heading
caption = "Key Colour 82"
visible = @numcols>=82
endheading
color param col82
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=82
endparam
float param pos82
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=82
endparam
heading
caption = "Key Colour 83"
visible = @numcols>=83
endheading
color param col83
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=83
endparam
float param pos83
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=83
endparam
heading
caption = "Key Colour 84"
visible = @numcols>=84
endheading
color param col84
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=84
endparam
float param pos84
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=84
endparam
heading
caption = "Key Colour 85"
visible = @numcols>=85
endheading
color param col85
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=85
endparam
float param pos85
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=85
endparam
heading
caption = "Key Colour 86"
visible = @numcols>=86
endheading
color param col86
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=86
endparam
float param pos86
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=86
endparam
heading
caption = "Key Colour 87"
visible = @numcols>=87
endheading
color param col87
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=87
endparam
float param pos87
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=87
endparam
heading
caption = "Key Colour 88"
visible = @numcols>=88
endheading
color param col88
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=88
endparam
float param pos88
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=88
endparam
heading
caption = "Key Colour 89"
visible = @numcols>=89
endheading
color param col89
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=89
endparam
float param pos89
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=89
endparam
heading
caption = "Key Colour 90"
visible = @numcols>=90
endheading
color param col90
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=90
endparam
float param pos90
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=90
endparam
heading
caption = "Key Colour 91"
visible = @numcols>=91
endheading
color param col91
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=91
endparam
float param pos91
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=91
endparam
heading
caption = "Key Colour 92"
visible = @numcols>=92
endheading
color param col92
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=92
endparam
float param pos92
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=92
endparam
heading
caption = "Key Colour 93"
visible = @numcols>=93
endheading
color param col93
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=93
endparam
float param pos93
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=93
endparam
heading
caption = "Key Colour 94"
visible = @numcols>=94
endheading
color param col94
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=94
endparam
float param pos94
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=94
endparam
heading
caption = "Key Colour 95"
visible = @numcols>=95
endheading
color param col95
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=95
endparam
float param pos95
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=95
endparam
heading
caption = "Key Colour 96"
visible = @numcols>=96
endheading
color param col96
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=96
endparam
float param pos96
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=96
endparam
heading
caption = "Key Colour 97"
visible = @numcols>=97
endheading
color param col97
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=97
endparam
float param pos97
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=97
endparam
heading
caption = "Key Colour 98"
visible = @numcols>=98
endheading
color param col98
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=98
endparam
float param pos98
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=98
endparam
heading
caption = "Key Colour 99"
visible = @numcols>=99
endheading
color param col99
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=99
endparam
float param pos99
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=99
endparam
heading
caption = "Key Colour 100"
visible = @numcols>=100
endheading
color param col100
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=100
endparam
float param pos100
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=100
endparam
heading
caption = "Key Colour 101"
visible = @numcols>=101
endheading
color param col101
caption = "Colour"
default = RGBA(1,0,0,1)
visible = @numcols>=101
endparam
float param pos101
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
visible = @numcols>=101
endparam
}
class MMF_KeyColourBase(common.ulb:Generic) {
import "common.ulb"
func MMF_KeyColourBase(Generic pparent)
m_Parent = pparent
endfunc
int func GetNumCols()
return 0
endfunc
color func GetNextColour()
return RGBA(0,0,0,1)
endfunc
float func GetNextIndex()
return 0
endfunc
default:
int param v_mmfkeycolourbase
caption = "Version (MMF_KeyColourBase)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmfkeycolourbase < 100
endparam
}
class MMF_NullKeyColour(MMF_KeyColourBase) {
default:
title = "Null Key Colour"
}
class MMF_OneKeyColour(MMF_KeyColourBase) {
import "common.ulb"
func MMF_OneKeyColour(Generic pparent)
m_Parent = pparent
endfunc
int func GetNumCols()
return 1
endfunc
color func GetNextColour()
return @colour
endfunc
float func GetNextIndex()
return 0.0025*@index
endfunc
default:
title = "One Key Colour"
int param v_mmfonekeycolour
caption = "Version (MMF_OneKeyColour)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmfonekeycolour < 100
endparam
color param colour
caption = "Colour"
default = RGBA(0,0,0,1)
endparam
float param index
caption = "Gradient Index"
default = 0.0
min = 0.0
max = 400.0
endparam
}
class MMF_TwoKeyColours(MMF_KeyColourBase) {
import "common.ulb"
func MMF_TwoKeyColours(Generic pparent)
m_Parent = pparent
cols = indexes = 0
endfunc
int func GetNumCols()
cols = indexes = 0
return 2
endfunc
color func GetNextColour()
if cols==0
cols = 1
return @colour0
endif
cols = 0
return @colour1
endfunc
float func GetNextIndex()
if indexes==0
indexes = 1
return 0.0025*@index0
endif
indexes = 0
return 0.0025*@index1
endfunc
private:
int cols
int indexes
default:
title = "Two Key Colours"
int param v_mmftwokeycolours
caption = "Version (MMF_TwoKeyColours)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmftwokeycolours < 100
endparam
heading
endheading
color param colour0
caption = "Colour"
default = RGBA(0,0,0,1)
endparam
float param index0
caption = "Gradient Index"
default = 0.0
min = 0.0
max = 400.0
endparam
heading
endheading
color param colour1
caption = "Colour"
default = RGBA(1,1,1,1)
endparam
float param index1
caption = "Gradient Index"
default = 400.0
min = 0.0
max = 400.0
endparam
}
class MMF_ThreeKeyColours(MMF_KeyColourBase) {
import "common.ulb"
func MMF_ThreeKeyColours(Generic pparent)
m_Parent = pparent
cols = indexes = 0
endfunc
int func GetNumCols()
cols = indexes = 0
return 3
endfunc
color func GetNextColour()
if cols==0
cols = 1
return @colour0
elseif cols==1
cols = 2
return @colour1
endif
cols = 0
return @colour2
endfunc
float func GetNextIndex()
if indexes==0
indexes = 1
return 0.0025*@index0
elseif indexes==1
indexes = 2
return 0.0025*@index1
endif
indexes = 0
return 0.0025*@index2
endfunc
private:
int cols
int indexes
default:
title = "Three Key Colours"
int param v_mmfthreekeycolours
caption = "Version (MMF_ThreeKeyColours)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmfthreekeycolours < 100
endparam
heading
endheading
color param colour0
caption = "Colour"
default = RGBA(1,0,0,1)
endparam
float param index0
caption = "Gradient Index"
default = 0.0
min = 0.0
max = 400.0
endparam
heading
endheading
color param colour1
caption = "Colour"
default = RGBA(0,1,0,1)
endparam
float param index1
caption = "Gradient Index"
default = 200.0
min = 0.0
max = 400.0
endparam
heading
endheading
color param colour2
caption = "Colour"
default = RGBA(0,0,1,1)
endparam
float param index2
caption = "Gradient Index"
default = 400.0
min = 0.0
max = 400.0
endparam
}
class MMF_FourKeyColours(MMF_KeyColourBase) {
import "common.ulb"
func MMF_FourKeyColours(Generic pparent)
m_Parent = pparent
cols = indexes = 0
col[0] = @colour0
col[1] = @colour1
col[2] = @colour2
col[3] = @colour3
col[4] = @colour4
col[5] = @colour5
col[6] = @colour6
col[7] = @colour7
col[8] = @colour8
col[9] = @colour9
index[0] = @index0
index[1] = @index1
index[2] = @index2
index[3] = @index3
index[4] = @index4
index[5] = @index5
index[6] = @index6
index[7] = @index7
index[8] = @index8
index[9] = @index9
endfunc
int func GetNumCols()
cols = indexes = 0
return @numcols+4
endfunc
color func GetNextColour()
color c = col[cols]
if (cols=cols+1)>=@numcols+4
cols = 0
endif
return c
endfunc
float func GetNextIndex()
float i = index[indexes]
if (indexes=indexes+1)>@numcols+4
indexes = 0
endif
return 0.0025*i
endfunc
private:
color col[10]
float index[10]
int cols
int indexes
default:
title = "4 to 10 Key Colours"
int param v_mmffourkeycolours
caption = "Version (MMF_FourKeyColours)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmffourkeycolours < 100
endparam
int param numcols
caption = "#Key colours"
enum = "4" "5" "6" "7" "8" "9" "10"
default = 0
endparam
heading
endheading
color param colour0
caption = "Colour"
default = RGBA(0,0,0.52156862745098039215686274509804,1)
endparam
float param index0
caption = "Gradient Index"
default = 0.0
min = 0.0
max = 400.0
endparam
heading
endheading
color param colour1
caption = "Colour"
default = RGBA(1,1,1,1)
endparam
float param index1
caption = "Gradient Index"
default = 100.0
min = 0.0
max = 400.0
endparam
heading
endheading
color param colour2
caption = "Colour"
default = RGBA(1,0.70980392156862745098039215686275,0,1)
endparam
float param index2
caption = "Gradient Index"
default = 200.0
min = 0.0
max = 400.0
endparam
heading
endheading
color param colour3
caption = "Colour"
default = RGBA(0.61176470588235294117647058823529,0,0,1)
endparam
float param index3
caption = "Gradient Index"
default = 300.0
min = 0.0
max = 400.0
endparam
heading
visible = @numcols>0
endheading
color param colour4
caption = "Colour"
default = RGBA(1,1,0,1)
visible = @numcols>0
endparam
float param index4
caption = "Gradient Index"
default = 50.0
min = 0.0
max = 400.0
visible = @numcols>0
endparam
heading
visible = @numcols>1
endheading
color param colour5
caption = "Colour"
default = RGBA(0,1,1,1)
visible = @numcols>1
endparam
float param index5
caption = "Gradient Index"
default = 150.0
min = 0.0
max = 400.0
visible = @numcols>1
endparam
heading
visible = @numcols>2
endheading
color param colour6
caption = "Colour"
default = RGBA(1,0,1,1)
visible = @numcols>2
endparam
float param index6
caption = "Gradient Index"
default = 250.0
min = 0.0
max = 400.0
visible = @numcols>2
endparam
heading
visible = @numcols>3
endheading
color param colour7
caption = "Colour"
default = RGBA(1,1,1,1)
visible = @numcols>3
endparam
float param index7
caption = "Gradient Index"
default = 350.0
min = 0.0
max = 400.0
visible = @numcols>3
endparam
heading
visible = @numcols>4
endheading
color param colour8
caption = "Colour"
default = RGBA(1,0.5,1,1)
visible = @numcols>4
endparam
float param index8
caption = "Gradient Index"
default = 75.0
min = 0.0
max = 400.0
visible = @numcols>4
endparam
heading
visible = @numcols>5
endheading
color param colour9
caption = "Colour"
default = RGBA(0.5,1,1,1)
visible = @numcols>5
endparam
float param index9
caption = "Gradient Index"
default = 325.0
min = 0.0
max = 400.0
visible = @numcols>5
endparam
}
class MMF_MultiKeyColours(MMF_KeyColourBase) {
import "common.ulb"
func MMF_MultiKeyColours(Generic pparent)
m_Parent = pparent
m_KeyColour[0] = new @f_keycolour0(this)
m_KeyColour[1] = new @f_keycolour1(this)
m_KeyColour[2] = new @f_keycolour2(this)
m_KeyColour[3] = new @f_keycolour3(this)
m_KeyColour[4] = new @f_keycolour4(this)
m_KeyColour[5] = new @f_keycolour5(this)
m_KeyColour[6] = new @f_keycolour6(this)
m_KeyColour[7] = new @f_keycolour7(this)
m_KeyColour[8] = new @f_keycolour8(this)
m_KeyColour[9] = new @f_keycolour9(this)
cols = indexes = 0
int i = 0
repeat
total[i] = 0
until (i=i+1)>=10
endfunc
int func GetNumCols()
int t = 0
int i = 0
cols = 0
indexes = 0
repeat
t = total[i] = t + m_KeyColour[i].GetNumCols()
until (i=i+1)>=@numcols+2
return t
endfunc
color func GetNextColour()
color c = RGBA(0,0,0,1)
int i = 0
repeat
if cols
; @param pparent typically 'this' from the parent or zero
func MMF_Gradient(Generic pparent)
int i
m_Parent = pparent
m_Transfer = new @f_transfer(this)
m_KeyColours = new @f_keycolours(this)
; calculate numcols and assign values
numcols = m_KeyColours.GetNumCols()
if numcols==0
col[0] = rgba(0,0,0,1)
else
if numcols>500
$define DEBUG
print(numcols," colours defined, the max. is 500. Some will be ignored.")
numcols = 500
endif
i = 0
repeat
col[i] = m_KeyColours.GetNextColour()
pstn[i] = m_KeyColours.GetNextIndex()
until (i=i+1)>=numcols
endif
if numcols>1
i = 0
repeat
float min = pstn[i]
int k = i
int j = i + 1
repeat
if pstn[j]
; @param i gradient index
; @return colour from gradient
color func GetColour(float i)
if @showpalette
i = real(#screenpixel)/#width
else
i = m_Transfer.Iterate(i)
endif
if numcols<=1
return col[0]
endif
if @rept
if (i = i%1)<0.0
i = i + 1.0
endif
elseif i<0.0
i = 0.0
elseif i>399.0/400.0
i = 399.0/400.0
endif
int j = -1
int k = 0
repeat
j = j + 1
until pstn[j]>i || j>=numcols
if j>=numcols
j = 0
k = numcols - 1
elseif (k=j-1)<0
k = numcols - 1
endif
float d = pstn[j] - pstn[k]
float v = i - pstn[k]
if d<0.0
d = 1.0 + d
if d==0.0
d = 1.0
endif
endif
if v<0.0
v = 1.0 + v
endif
if @smooth
; Our point is between p1 at x1 with height h1 and p2 at x2 with height h2
; First if h1==h2 then h==h1
; Else get gradient g1 at p1 and g2 at p2 and use:
;
; h = ax^3 + bx^2 + cx + d
; g = 3*a*x^2 + 2*b*x + c
;
; h1 = a*x1^3 +b*x1^2 + c*x1 + d
; g1 = 3*a*x1^2 + 2*b*x1 + c
; h2 = a*x2^3 + b*x2^2 + c*x2 + d
; g2 = 3*a*x2^2 + 2*b*x2 + c
;
; But we can use 0 for x1 and (x2-x1) for x2, giving:
;
; h1 = d
; g1 = c
; h2 = a*(x2-x1)^3 + b*(x2-x1)^2 + c*(x2-x1) + d
; g2 = 3*a*(x2-x1)^2 + 2*b*(x2-x1) + c
;
; Hence:
;
; a*(x2-x1)^3 + b*(x2-x1)^2 + g1*(x2-x1) + h1 = h2
; 3*a*(x2-x1)^2 + 2*b*(x2-x1) + g1 = g2
;
; a = (g2 - g1 - 2*b*(x2-x1))/(3*(x2-x1)^2)
;
; (g2-g1)(x2-x1)/3 - 2*b*(x2-x1)^2/3 + b*(x2-x1)^2 + g1*(x2-x1) + h1 = h2
;
; (2*g1+g2)(x2-x1)/3 + b*(x2-x1)^2/3 + h1 = h2
;
; b = 3*(h2-h1)/(x2-x1)^2 - (2*g1+g2)/(x2-x1)
;
; h1
float r1 = red(col[k])
float g1 = green(col[k])
float b1 = blue(col[k])
float a1 = alpha(col[k])
; h2
float r2 = red(col[j])
float g2 = green(col[j])
float b2 = blue(col[j])
float a2 = alpha(col[j])
if r1==r2 && g1==g2 && b1==b2 && a1==a2
return col[k]
endif
; g1
float gr1 = 0.0
float gg1 = 0.0
float gb1 = 0.0
float ga1 =0.0
; g2
float gr2 = 0.0
float gg2 = 0.0
float gb2 = 0.0
float ga2 = 0.0
; temp gradients
float id = 1.0/d
float tr = (red(col[j])-red(col[k]))*id
float tg = (green(col[j])-green(col[k]))*id
float tb = (blue(col[j])-blue(col[k]))*id
float ta = (alpha(col[j])-alpha(col[k]))*id
int l = k - 1
int m = j + 1
if l<0
l = numcols - 1
if pstn[k]==0.0 && pstn[l]==1.0
l = k
endif
endif
if m>=numcols
m = 0
if pstn[j]==1.0 && pstn[m]==0.0
m = j
endif
endif
if pstn[l]==pstn[k]
gr1 = gg1 = gb1 = ga1 = 0.0
else
float d1 = pstn[k] - pstn[l]
if d1<0.0
d1 = d1 + 1.0
endif
d1 = 1.0/d1
gr1 = (red(col[k])-red(col[l]))*d1
gg1 = (green(col[k])-green(col[l]))*d1
gb1 = (blue(col[k])-blue(col[l]))*d1
ga1 = (alpha(col[k])-alpha(col[l]))*d1
if (gr1>=0.0 && tr<=0.0) || (gr1<=0.0 && tr>=0.0)
gr1 = 0.0
else
gr1 = 0.5*(gr1 + tr)
endif
if (gg1>=0.0 && tg<=0.0) || (gg1<=0.0 && tg>=0.0)
gg1 = 0.0
else
gg1 = 0.5*(gg1 + tg)
endif
if (gb1>=0.0 && tb<=0.0) || (gb1<=0.0 && tb>=0.0)
gb1 = 0.0
else
gb1 = 0.5*(gb1 + tb)
endif
if (ga1>=0.0 && ta<=0.0) || (ga1<=0.0 && ta>=0.0)
ga1 = 0.0
else
ga1 = 0.5*(ga1 + ta)
endif
endif
if pstn[m]==pstn[j]
gr2 = gg2 = gb2 = ga2 = 0.0
else
float d1 = pstn[m] - pstn[j]
if d1<0.0
d1 = d1 + 1.0
endif
d1 = 1.0/d1
gr2 = (red(col[m])-red(col[j]))*d1
gg2 = (green(col[m])-green(col[j]))*d1
gb2 = (blue(col[m])-blue(col[j]))*d1
ga2 = (alpha(col[m])-alpha(col[j]))*d1
if (gr2>=0.0 && tr<=0.0) || (gr2<=0.0 && tr>=0.0)
gr2 = 0.0
else
gr2 = 0.5*(gr2 + tr)
endif
if (gg2>=0.0 && tg<=0.0) || (gg2<=0.0 && tg>=0.0)
gg2 = 0.0
else
gg2 = 0.5*(gg2 + tg)
endif
if (gb2>=0.0 && tb<=0.0) || (gb2<=0.0 && tb>=0.0)
gb2 = 0.0
else
gb2 = 0.5*(gb2 + tb)
endif
if (ga2>=0.0 && ta<=0.0) || (ga2<=0.0 && ta>=0.0)
ga2 = 0.0
else
ga2 = 0.5*(ga2 + ta)
endif
endif
; b = 3*(h2-h1)/(x2-x1)^2 - (2*g1+g2)/(x2-x1)
; a = (g2 - g1 - 2*b*(x2-x1))/(3*(x2-x1)^2)
; h = ax^3 + bx^2 + cx + d
float a = 0.0
float b = 0.0
if r1!=r2
b = 3*(r2-r1)*sqr(id) - (2*gr1+gr2)*id
a = (gr2-gr1-2.0*b*d)*sqr(id)/3
r1 = a*v^3 + b*sqr(v) + gr1*v + r1
endif
if g1!=g2
b = 3*(g2-g1)*sqr(id) - (2*gg1+gg2)*id
a = (gg2-gg1-2.0*b*d)*sqr(id)/3
g1 = a*v^3 + b*sqr(v) + gg1*v + g1
endif
if b1!=b2
b = 3*(b2-b1)*sqr(id) - (2*gb1+gb2)*id
a = (gb2-gb1-2.0*b*d)*sqr(id)/3
b1 = a*v^3 + b*sqr(v) + gb1*v + b1
endif
if a1!=a2
b = 3*(a2-a1)*sqr(id) - (2*ga1+ga2)*id
a = (ga2-ga1-2.0*b*d)*sqr(id)/3
a1 = a*v^3 + b*sqr(v) + ga1*v + a1
endif
return RGBA(r1,g1,b1,a1)
else
return col[k] + (col[j] - col[k])*v/d
endif
endfunc
private:
Transfer m_Transfer
MMF_KeyColourBase m_KeyColours
color col[500]
float pstn[500]
int numcols
default:
title = "MMF Gradient"
rating = recommended
int param v_mmfgradient
caption = "Version (MMF Gradient)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
heading
caption = "Gradient Control"
endheading
Transfer param f_transfer
caption = "Gradient Transfer"
default = DefaultGradientTransfer
hint = "Use to modify the value from the colouring before the colour \
is looked up in the gradient."
visible = !@showpalette
endparam
bool param rept
caption = "Repeat Gradient ?"
default = true
endparam
bool param smooth
caption = "Smooth Curves ?"
default = true
endparam
bool param showpalette
caption = "Show Gradient Only"
default = false
hint = "When enabled the gradient is shown as vertical stripes on the \
fractal, position 0.0 to the left and 1.0 to the right."
endparam
MMF_KeyColourBase param f_keycolours
caption = "Key Colours"
default = MMF_FourKeyColours
hint = "You can use up to 500 separate colours via the key colour \
plug-ins. Note that plug-ins containing more than one key \
colour parameter can be nested."
endparam
}
class MMF_LayerMergeBase(common.ulb:Generic) {
; PLEASE NOTE This class is obsolete/deprecated.
; @param pparent typically 'this' from the parent or zero
func MMF_LayerMergeBase(Generic pparent)
Generic.Generic(pparent)
endfunc
;
; @param pbottom the base color
; @param ptop the top color
; @return merged color
color func Merge(color pbottom, color ptop)
return ptop
endfunc
;
; @param pbottom the base color
; @param ptop the top color
; @return layer merged color
color func FullMerge(color pbottom, color ptop)
if @f_invertcompose
if @f_invertmerge
return compose(ptop, \
blend(pbottom,Merge(ptop,pbottom),alpha(ptop)), \
@f_opacity)
else
return compose(ptop, \
blend(ptop,Merge(pbottom,ptop),alpha(pbottom)), \
@f_opacity)
endif
elseif @f_invertmerge
return compose(pbottom, \
blend(pbottom,Merge(ptop,pbottom),alpha(ptop)), \
@f_opacity)
else
return compose(pbottom, \
blend(ptop,Merge(pbottom,ptop),alpha(pbottom)), \
@f_opacity)
endif
endfunc
;
; @param clr the base color
; @param index the gradient index for the top colour
; @return layer merged color
color func GradientMerge(color clr,float index)
return FullMerge(clr, gradient(index))
endfunc
;
; @param clr the base color
; @return layer merged color
color func SolidMerge(color clr)
return FullMerge(clr, @f_solid)
endfunc
default:
rating = notRecommended
int param v_mmflayermergebase
caption = "Version (MMF_LayerMergeBase)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmflayermergebase < 100
endparam
heading
text = "PLEASE NOTE that this class is obsolete/deprecated. If you are \
using the old 'MMF Multi Layer' formula and you are creating a \
new UPR then you should switch to using 'MMF Layered' instead."
endheading
color param f_solid
caption = "Solid Colour"
default = RGBA(0,0,0,1)
endparam
bool param f_invertmerge
caption = "Inverted Merge"
default = false
hint = "When enabled this layer is treated as the lower layer in the \
merge instead of as the upper layer, this inverts the way the \
RGBA values are treated."
endparam
bool param f_invertcompose
caption = "Inverted Compose"
default = false
hint = "When enabled this layer is treated as the lower layer in the \
compose instead of as the upper layer, so reduced opacity \
fades to this layer's colour instead of the underlying colour."
endparam
float param f_opacity
caption = "Layer Opacity"
default = 1.0
hint = "The normal range to use is from 0.0 to 1.0."
endparam
}
class MMF_LayerMerge(MMF_LayerMergeBase) {
; PLEASE NOTE This class is obsolete/deprecated.
; @param pparent typically 'this' from the parent or zero
func MMF_LayerMerge(Generic pparent)
MMF_LayerMergeBase.MMF_LayerMergeBase(pparent)
endfunc
;
; @param pbottom the base color
; @param ptop the top color
; @return merged color
color func Merge(color pbottom, color ptop)
if @p_modeselect=="MMF Merge Modes"
if @clamp
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.0
r = 0.0
elseif r>1.0
r = 1.0
endif
if g<0.0
g = 0.0
elseif g>1.0
g = 1.0
endif
if b<0.0
b = 0.0
elseif b>1.0
b = 1.0
endif
ptop = rgba(r,g,b,alpha(ptop))
r = red(pbottom)
g = green(pbottom)
b = blue(pbottom)
if r<0.0
r = 0.0
elseif r>1.0
r = 1.0
endif
if g<0.0
g = 0.0
elseif g>1.0
g = 1.0
endif
if b<0.0
b = 0.0
elseif b>1.0
b = 1.0
endif
pbottom = rgba(r,g,b,alpha(pbottom))
endif
if @p_mmfmergemode=="Exclusion"
return rgba(red(pbottom) + red(ptop) - 2*red(pbottom)*red(ptop), \
green(pbottom) + green(ptop) - 2*green(pbottom)*green(ptop), \
blue(pbottom) + blue(ptop) - 2*blue(pbottom)*blue(ptop), \
alpha(ptop) )
elseif @p_mmfmergemode=="Fade Down"
return rgba( red(ptop) * (1 - red(ptop) + red(pbottom)), \
green(ptop) * (1 - green(ptop) + green(pbottom)), \
blue(ptop) * (1 - blue(ptop) + blue(pbottom)), alpha(ptop) )
elseif @p_mmfmergemode=="Fade Up"
return rgba(red(pbottom) + red(ptop)*(red(ptop) - red(pbottom)), \
green(pbottom) + green(ptop)*(green(ptop) - green(pbottom)), \
blue(pbottom) + blue(ptop)*(blue(ptop) - blue(pbottom)), \
alpha(ptop) )
elseif @p_mmfmergemode=="Contrast Down"
return rgba( 0.5 + red(ptop)*(red(pbottom) - 0.5), \
0.5 + green(ptop)*(green(pbottom) - 0.5), \
0.5 + blue(ptop)*(blue(pbottom) - 0.5), alpha(ptop) )
elseif @p_mmfmergemode=="Contrast Up"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = r - 2.0*red(ptop)*r*(0.5 - r)
else
r = r + 2.0*red(ptop)*(1.0 - r)*(r - 0.5)
endif
if g<0.5
g = g - 2.0*green(ptop)*g*(0.5 - g)
else
g = g + 2.0*green(ptop)*(1.0 - g)*(g - 0.5)
endif
if b<0.5
b = b - 2.0*blue(ptop)*b*(0.5 - b)
else
b = b + 2.0*blue(ptop)*(1.0 - b)*(b - 0.5)
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Dodge"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
float r = 1.0 - red(ptop)
float g = 1.0 - green(ptop)
float b = 1.0 - blue(ptop)
if red(pbottom)<=0
r = 0.0
elseif r<=0.0
r = 1.0
else
r = red(pbottom)/r
if r>1.0
r = 1.0
endif
endif
if green(pbottom)<=0
g = 0
elseif g<=0.0
g = 1.0
else
g = green(pbottom)/g
if g>1.0
g = 1.0
endif
endif
if blue(pbottom)<=0
b = 0
elseif b<=0.0
b = 1.0
else
b = blue(pbottom)/b
if b>1.0
b = 1.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Burn"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<=0.0
r = 0.0
else
r = 1.0 - (1.0 - red(pbottom))/r
if r<0.0
r = 0.0
endif
endif
if g<=0.0
g = 0.0
else
g = 1.0 - (1.0 - green(pbottom))/g
if g<0.0
g = 0.0
endif
endif
if b<=0.0
b = 0.0
else
b = 1.0 - (1.0 - blue(pbottom))/b
if b<0.0
b = 0.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Negation"
return rgba( 1.0 - abs(1.0 - red(ptop) - red(pbottom)), \
1.0 - abs(1.0 - green(ptop) - green(pbottom)), \
1.0 - abs(1.0 - blue(ptop) - blue(pbottom)), alpha(ptop) )
elseif @p_mmfmergemode=="Reflect"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
float r = 1.0 - red(ptop)
float g = 1.0 - green(ptop)
float b = 1.0 - blue(ptop)
if red(pbottom)<=0
r = 0.0
elseif r<=0.0
r = 1.0
else
r = sqr(red(pbottom))/r
if r>1.0
r = 1.0
endif
endif
if green(pbottom)<=0
g = 0.0
elseif g<=0.0
g = 1.0
else
g = sqr(green(pbottom))/g
if g>1.0
g = 1.0
endif
endif
if blue(pbottom)<=0
b = 0.0
elseif b<=0.0
b = 1.0
else
b = sqr(blue(pbottom))/b
if b>1.0
b = 1.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Freeze"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<=0.0
r = 0.0
else
r = 1.0 - sqr(1.0 - red(pbottom))/r
if r<0.0
r = 0.0
endif
endif
if g<=0.0
g = 0.0
else
g = 1.0 - sqr(1.0 - green(pbottom))/g
if g<0.0
g = 0.0
endif
endif
if b<=0.0
b = 0.0
else
b = 1.0 - sqr(1.0 - blue(pbottom))/b
if b<0.0
b = 0.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Rev. Contrast Down"
return rgba( 0.5 + (1.0 - red(ptop))*(red(pbottom) - 0.5), \
0.5 + (1.0 - green(ptop))*(green(pbottom) - 0.5), \
0.5 + (1.0 - blue(ptop))*(blue(pbottom) - 0.5), alpha(ptop) )
elseif @p_mmfmergemode=="Rev. Contrast Up"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = r - 2.0*(1.0 - red(ptop))*r*(0.5 - r)
else
r = r + 2.0*(1.0 - red(ptop))*(1.0 - r)*(r - 0.5)
endif
if g<0.5
g = g - 2.0*(1.0 - green(ptop))*g*(0.5 - g)
else
g = g + 2.0*(1.0 - green(ptop))*(1.0 - g)*(g - 0.5)
endif
if b<0.5
b = b - 2.0*(1.0 - blue(ptop))*b*(0.5 - b)
else
b = b + 2.0*(1.0 - blue(ptop))*(1.0 - b)*(b - 0.5)
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Fade"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = 2.0 * r * (0.5 - r + red(pbottom))
else
r = red(pbottom) + 2.0 * (r - 0.5)*(r - red(pbottom))
endif
if g<0.5
g = 2.0 * g * (0.5 - g + green(pbottom))
else
g = green(pbottom) + 2.0 * (g - 0.5)*(g - green(pbottom))
endif
if b<0.5
b = 2.0 * b * (0.5 - b + blue(pbottom))
else
b = blue(pbottom) + 2.0 * (b - 0.5)*(b - blue(pbottom))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Reverse Fade"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = red(pbottom) + 2.0 * r * (r - red(pbottom))
else
r = red(pbottom) + 2.0 * (1.0 - r)*(r - red(pbottom))
endif
if g<0.5
g = green(pbottom) + 2.0 * g * (g - green(pbottom))
else
g = green(pbottom) + 2.0 * (1.0 - g)*(g - green(pbottom))
endif
if b<0.5
b = blue(pbottom) + 2.0 * b * (b - blue(pbottom))
else
b = blue(pbottom) + 2.0 * (1.0 - b)*(b - blue(pbottom))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Contrast" || @p_mmfmergemode=="Reverse Contrast"
float r1 = red(ptop)
float g1 = green(ptop)
float b1 = blue(ptop)
if @p_mmfmergemode=="Reverse Contrast"
r1 = 1.0 - r1
g1 = 1.0 - g1
b1 = 1.0 - b1
endif
if r1<0.5
r1 = 0.5 + 2.0 * r1 * (red(pbottom) - 0.5)
else
r1 = 2.0 * (r1 - 0.5)
float r = red(pbottom)
if r<0.5
r1 = r - 2.0*r1*r*(0.5 - r)
else
r1 = r + 2.0*r1*(1.0 - r)*(r - 0.5)
endif
endif
if g1<0.5
g1 = 0.5 + 2.0 * g1 * (green(pbottom) - 0.5)
else
g1 = 2.0 * (g1 - 0.5)
float g = green(pbottom)
if g<0.5
g1 = g - 2.0*g1*g*(0.5 - g)
else
g1 = g + 2.0*g1*(1.0 - g)*(g - 0.5)
endif
endif
if b1<0.5
b1 = 0.5 + 2.0 * b1 * (blue(pbottom) - 0.5)
else
b1 = 2.0 * (b1 - 0.5)
float b = blue(pbottom)
if b<0.5
b1 = b - 2.0*b1*b*(0.5 - b)
else
b1 = b + 2.0*b1*(1.0 - b)*(b - 0.5)
endif
endif
return rgba(r1,g1,b1,alpha(ptop))
elseif @p_mmfmergemode=="Quantize"
int nr = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + red(ptop)) - 1.0)) - 1
int ng = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + green(ptop)) - 1.0)) - 1
int nb = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + blue(ptop)) - 1.0)) - 1
return rgba(floor(red(pbottom)*(nr+0.999))/nr, \
floor(green(pbottom)*(ng+0.999))/ng, \
floor(blue(pbottom)*(nb+0.999))/nb,alpha(ptop))
elseif @p_mmfmergemode=="Reverse Quantize"
int nr = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - red(ptop)) - 1.0)) - 1
int ng = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - green(ptop)) - 1.0)) - 1
int nb = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - blue(ptop)) - 1.0)) - 1
return rgba(floor(red(pbottom)*(nr+0.999))/nr, \
floor(green(pbottom)*(ng+0.999))/ng, \
floor(blue(pbottom)*(nb+0.999))/nb,alpha(ptop))
elseif @p_mmfmergemode=="Gamma"
return rgba(red(pbottom)^(@mingamma+(@maxgamma-@mingamma)*red(ptop)), \
green(pbottom)^(@mingamma+(@maxgamma-@mingamma)*green(ptop)), \
blue(pbottom)^(@mingamma+(@maxgamma-@mingamma)*blue(ptop)), \
alpha(ptop))
elseif @p_mmfmergemode=="Inverse Gamma"
return rgba(red(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*red(ptop))), \
green(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*green(ptop))), \
blue(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*blue(ptop))), \
alpha(ptop))
elseif @p_mmfmergemode=="Reverse Gamma"
return rgba(red(pbottom)^(@mingamma+(@maxgamma-@mingamma)*(1.0-red(ptop))), \
green(pbottom)^(@mingamma+(@maxgamma-@mingamma)*(1.0-green(ptop))), \
blue(pbottom)^(@mingamma+(@maxgamma-@mingamma)*(1.0-blue(ptop))), \
alpha(ptop))
elseif @p_mmfmergemode=="Rev. Inv. Gamma"
return rgba(red(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-red(ptop)))), \
green(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-green(ptop)))), \
blue(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-blue(ptop)))), \
alpha(ptop))
elseif @p_mmfmergemode=="Combined Gamma"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = red(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-red(ptop)))
else
r = red(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(red(ptop)-0.5)))
endif
if g<0.5
g = green(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-green(ptop)))
else
g = green(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(green(ptop)-0.5)))
endif
if b<0.5
b = blue(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-blue(ptop)))
else
b = blue(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(blue(ptop)-0.5)))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Rev. Comb. Gamma"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = red(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-red(ptop))))
else
r = red(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(red(ptop)-0.5))
endif
if g<0.5
g = green(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-green(ptop))))
else
g = green(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(green(ptop)-0.5))
endif
if b<0.5
b = blue(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-blue(ptop))))
else
b = blue(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(blue(ptop)-0.5))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Stamp"
float r = red(pbottom) + 2.0*red(ptop) - 1.0
float g = green(pbottom) + 2.0*green(ptop) - 1.0
float b = blue(pbottom) + 2.0*blue(ptop) - 1.0
if r<0.0
r = 0.0
elseif r>1.0
r = 1.0
endif
if g<0.0
g = 0.0
elseif g>1.0
g = 1.0
endif
if b<0.0
b = 0.0
elseif b>1.0
b = 1.0
endif
return RGBA(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Soft Dodge"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<=0
r = 0
elseif r+red(ptop)<=1.0
if red(ptop)>=1.0
r = 1.0
elseif (r = 0.5*r/(1.0 - red(ptop)))>1.0
r = 1.0
endif
elseif (r = 1.0 - 0.5*(1.0 - red(ptop))/r)<0.0
r = 0.0
endif
if g<=0
g = 0
elseif g+green(ptop)<=1.0
if green(ptop)>=1.0
g = 1.0
elseif (g = 0.5*g/(1.0 - green(ptop)))>1.0
g = 1.0
endif
elseif (g = 1.0 - 0.5*(1.0 - green(ptop))/g)<0.0
g = 0.0
endif
if b<=0
b = 0
elseif b+blue(ptop)<=1.0
if blue(ptop)>=1.0
b = 1.0
elseif (b = 0.5*b/(1.0 - blue(ptop)))>1.0
b = 1.0
endif
elseif (b = 1.0 - 0.5*(1.0 - blue(ptop))/b)<0.0
b = 0.0
endif
return RGBA(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Soft Burn"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<=0
r = 0
elseif r+red(pbottom)<=1.0
if red(pbottom)>=1.0
r = 1.0
elseif (r = 0.5*r/(1.0 - red(pbottom)))>1.0
r = 1.0
endif
elseif (r = 1.0 - 0.5*(1.0 - red(pbottom))/r)<0.0
r = 0.0
endif
if g<=0
g = 0
elseif g+green(pbottom)<=1.0
if green(pbottom)>=1.0
g = 1.0
elseif (g = 0.5*g/(1.0 - green(pbottom)))>1.0
g = 1.0
endif
elseif (g = 1.0 - 0.5*(1.0 - green(pbottom))/g)<0.0
g = 0.0
endif
if b<=0
b = 0
elseif b+blue(pbottom)<=1.0
if blue(pbottom)>=1.0
b = 1.0
elseif (b = 0.5*b/(1.0 - blue(pbottom)))>1.0
b = 1.0
endif
elseif (b = 1.0 - 0.5*(1.0 - blue(pbottom))/b)<0.0
b = 0.0
endif
return RGBA(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Dodge"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
float r = 1.0 - red(pbottom)
float g = 1.0 - green(pbottom)
float b = 1.0 - blue(pbottom)
if red(ptop)<=0
r = 0
elseif r<=0.0
r = 1.0
else
r = red(ptop)/r
if r>1.0
r = 1.0
endif
endif
if green(ptop)<=0
g = 0
elseif g<=0.0
g = 1.0
else
g = green(ptop)/g
if g>1.0
g = 1.0
endif
endif
if blue(ptop)<=0
b = 0
elseif b<=0.0
b = 1.0
else
b = blue(ptop)/b
if b>1.0
b = 1.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Burn"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<=0.0
r = 0.0
else
r = 1.0 - (1.0 - red(ptop))/r
if r<0.0
r = 0.0
endif
endif
if g<=0.0
g = 0.0
else
g = 1.0 - (1.0 - green(ptop))/g
if g<0.0
g = 0.0
endif
endif
if b<=0.0
b = 0.0
else
b = 1.0 - (1.0 - blue(ptop))/b
if b<0.0
b = 0.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Glow"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
float r = 1.0 - red(pbottom)
float g = 1.0 - green(pbottom)
float b = 1.0 - blue(pbottom)
if red(ptop)<=0
r = 0.0
elseif r<=0.0
r = 1.0
else
r = sqr(red(ptop))/r
if r>1.0
r = 1.0
endif
endif
if green(ptop)<=0
g = 0.0
elseif g<=0.0
g = 1.0
else
g = sqr(green(ptop))/g
if g>1.0
g = 1.0
endif
endif
if blue(ptop)<=0
b = 0.0
elseif b<=0.0
b = 1.0
else
b = sqr(blue(ptop))/b
if b>1.0
b = 1.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Heat"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<=0.0
r = 0.0
else
r = 1.0 - sqr(1.0 - red(ptop))/r
if r<0.0
r = 0.0
endif
endif
if g<=0.0
g = 0.0
else
g = 1.0 - sqr(1.0 - green(ptop))/g
if g<0.0
g = 0.0
endif
endif
if b<=0.0
b = 0.0
else
b = 1.0 - sqr(1.0 - blue(ptop))/b
if b<0.0
b = 0.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Fade Down"
return rgba( red(pbottom) * (1 - red(pbottom) + red(ptop)), \
green(pbottom) * (1 - green(pbottom) + green(ptop)), \
blue(pbottom) * (1 - blue(pbottom) + blue(ptop)), alpha(ptop) )
elseif @p_mmfmergemode=="Inv. Fade Up"
return rgba(red(ptop) + red(pbottom)*(red(pbottom) - red(ptop)), \
green(ptop) + green(pbottom)*(green(pbottom) - green(ptop)), \
blue(ptop) + blue(pbottom)*(blue(pbottom) - blue(ptop)), \
alpha(ptop) )
elseif @p_mmfmergemode=="Inv. Contrast Down"
return rgba( 0.5 + red(pbottom)*(red(ptop) - 0.5), \
0.5 + green(pbottom)*(green(ptop) - 0.5), \
0.5 + blue(pbottom)*(blue(ptop) - 0.5), alpha(ptop) )
elseif @p_mmfmergemode=="Inv. Contrast Up"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = r - 2.0*red(pbottom)*r*(0.5 - r)
else
r = r + 2.0*red(pbottom)*(1.0 - r)*(r - 0.5)
endif
if g<0.5
g = g - 2.0*green(pbottom)*g*(0.5 - g)
else
g = g + 2.0*green(pbottom)*(1.0 - g)*(g - 0.5)
endif
if b<0.5
b = b - 2.0*blue(pbottom)*b*(0.5 - b)
else
b = b + 2.0*blue(pbottom)*(1.0 - b)*(b - 0.5)
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Con. Down"
return rgba( 0.5 + (1.0 - red(pbottom))*(red(ptop) - 0.5), \
0.5 + (1.0 - green(pbottom))*(green(ptop) - 0.5), \
0.5 + (1.0 - blue(pbottom))*(blue(ptop) - 0.5), alpha(ptop) )
elseif @p_mmfmergemode=="Inv. Rev. Con. Up"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = r - 2.0*(1.0 - red(pbottom))*r*(0.5 - r)
else
r = r + 2.0*(1.0 - red(pbottom))*(1.0 - r)*(r - 0.5)
endif
if g<0.5
g = g - 2.0*(1.0 - green(pbottom))*g*(0.5 - g)
else
g = g + 2.0*(1.0 - green(pbottom))*(1.0 - g)*(g - 0.5)
endif
if b<0.5
b = b - 2.0*(1.0 - blue(pbottom))*b*(0.5 - b)
else
b = b + 2.0*(1.0 - blue(pbottom))*(1.0 - b)*(b - 0.5)
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Fade"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = 2.0 * r * (0.5 - r + red(ptop))
else
r = red(ptop) + 2.0 * (r - 0.5)*(r - red(ptop))
endif
if g<0.5
g = 2.0 * g * (0.5 - g + green(ptop))
else
g = green(ptop) + 2.0 * (g - 0.5)*(g - green(ptop))
endif
if b<0.5
b = 2.0 * b * (0.5 - b + blue(ptop))
else
b = blue(ptop) + 2.0 * (b - 0.5)*(b - blue(ptop))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Fade"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = red(ptop) + 2.0 * r * (r - red(ptop))
else
r = red(ptop) + 2.0 * (1.0 - r)*(r - red(ptop))
endif
if g<0.5
g = green(ptop) + 2.0 * g * (g - green(ptop))
else
g = green(ptop) + 2.0 * (1.0 - g)*(g - green(ptop))
endif
if b<0.5
b = blue(ptop) + 2.0 * b * (b - blue(ptop))
else
b = blue(ptop) + 2.0 * (1.0 - b)*(b - blue(ptop))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Contrast" \
|| @p_mmfmergemode=="Inv. Rev. Contrast"
float r1 = red(pbottom)
float g1 = green(pbottom)
float b1 = blue(pbottom)
if @p_mmfmergemode=="Inv. Rev. Contrast"
r1 = 1.0 - r1
g1 = 1.0 - g1
b1 = 1.0 - b1
endif
if r1<0.5
r1 = 0.5 + 2.0 * r1 * (red(ptop) - 0.5)
else
r1 = 2.0 * (r1 - 0.5)
float r = red(ptop)
if r<0.5
r1 = r - 2.0*r1*r*(0.5 - r)
else
r1 = r + 2.0*r1*(1.0 - r)*(r - 0.5)
endif
endif
if g1<0.5
g1 = 0.5 + 2.0 * g1 * (green(ptop) - 0.5)
else
g1 = 2.0 * (g1 - 0.5)
float g = green(ptop)
if g<0.5
g1 = g - 2.0*g1*g*(0.5 - g)
else
g1 = g + 2.0*g1*(1.0 - g)*(g - 0.5)
endif
endif
if b1<0.5
b1 = 0.5 + 2.0 * b1 * (blue(ptop) - 0.5)
else
b1 = 2.0 * (b1 - 0.5)
float b = blue(ptop)
if b<0.5
b1 = b - 2.0*b1*b*(0.5 - b)
else
b1 = b + 2.0*b1*(1.0 - b)*(b - 0.5)
endif
endif
return rgba(r1,g1,b1,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Quantize"
int nr = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + red(pbottom)) - 1.0)) - 1
int ng = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + green(pbottom)) - 1.0)) - 1
int nb = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + blue(pbottom)) - 1.0)) - 1
return rgba(floor(red(ptop)*(nr+0.999))/nr, \
floor(green(ptop)*(ng+0.999))/ng, \
floor(blue(ptop)*(nb+0.999))/nb,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Quantize"
int nr = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - red(pbottom)) - 1.0)) - 1
int ng = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - green(pbottom)) - 1.0)) - 1
int nb = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - blue(pbottom)) - 1.0)) - 1
return rgba(floor(red(ptop)*(nr+0.999))/nr, \
floor(green(ptop)*(ng+0.999))/ng, \
floor(blue(ptop)*(nb+0.999))/nb,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Gamma"
return rgba(red(ptop)^(@mingamma+(@maxgamma-@mingamma)*red(pbottom)), \
green(ptop)^(@mingamma+(@maxgamma-@mingamma)*green(pbottom)), \
blue(ptop)^(@mingamma+(@maxgamma-@mingamma)*blue(pbottom)), \
alpha(ptop))
elseif @p_mmfmergemode=="Inv. Inverse Gamma"
return rgba(red(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*red(pbottom))), \
green(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*green(pbottom))), \
blue(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*blue(pbottom))), \
alpha(ptop))
elseif @p_mmfmergemode=="Inv. Reverse Gamma"
return rgba(red(ptop)^(@mingamma+(@maxgamma-@mingamma)*(1.0-red(pbottom))), \
green(ptop)^(@mingamma+(@maxgamma-@mingamma)*(1.0-green(pbottom))), \
blue(ptop)^(@mingamma+(@maxgamma-@mingamma)*(1.0-blue(pbottom))), \
alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Inv. Gamma"
return rgba(red(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-red(pbottom)))), \
green(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-green(pbottom)))), \
blue(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-blue(pbottom)))), \
alpha(ptop))
elseif @p_mmfmergemode=="Inv. Combined Gamma"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = red(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-r))
else
r = red(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(r-0.5)))
endif
if g<0.5
g = green(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-g))
else
g = green(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(g-0.5)))
endif
if b<0.5
b = blue(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-b))
else
b = blue(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(b-0.5)))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Comb. Gamma"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = red(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-r)))
else
r = red(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(r-0.5))
endif
if g<0.5
g = green(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-g)))
else
g = green(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(g-0.5))
endif
if b<0.5
b = blue(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-b)))
else
b = blue(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(b-0.5))
endif
return rgba(r,g,b,alpha(ptop))
else;if @p_mmfmergemode=="Inverse Stamp"
float r = red(ptop) + 2.0*red(pbottom) - 1.0
float g = green(ptop) + 2.0*green(pbottom) - 1.0
float b = blue(ptop) + 2.0*blue(pbottom) - 1.0
if r<0.0
r = 0.0
elseif r>1.0
r = 1.0
endif
if g<0.0
g = 0.0
elseif g>1.0
g = 1.0
endif
if b<0.0
b = 0.0
elseif b>1.0
b = 1.0
endif
return RGBA(r,g,b,alpha(ptop))
endif ; @p_mmfmergemode
else;if @pmodeselect=="Original Merge Modes"
return @f_mergemode(pbottom, ptop)
endif ; @p_modeselect
endfunc
default:
title = "MMF Layer Merge"
rating = notRecommended
int param v_mmflayermerge
caption = "Version (MMF Layer Merge)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
int param p_modeselect
caption = "Merge Modes to choose from"
enum = "Original Merge Modes" "MMF Merge Modes"
default = 0
hint = "Choose from different collections of merge modes."
endparam
color func f_mergemode
caption = "Merge Mode"
default = mergemultiply()
hint = "Sets the method used to merge input colors with."
visible = @p_modeselect=="Original Merge Modes"
endfunc
bool param clamp
caption = "Clamp Values"
default = false
hint = "When enabled the RGB values in both the top and bottom colours \
are clamped to the range 0<=v<=1. Should not be necessary most \
of the time."
visible = @p_modeselect=="MMF Merge Modes"
endparam
int param p_mmfmergemode
caption = "MMF Merge Mode"
enum = "Exclusion" "Fade Down" "Fade Up" "Contrast Down" "Contrast Up" \
"Dodge" "Burn" "Negation" "Reflect" "Freeze" "Rev. Contrast Down" \
"Rev. Contrast Up" "Fade" "Reverse Fade" "Contrast" \
"Reverse Contrast" "Quantize" "Reverse Quantize" "Gamma" \
"Inverse Gamma" "Reverse Gamma" "Rev. Inv. Gamma" "Combined Gamma" \
"Rev. Comb. Gamma" "Stamp" "Soft Dodge" "Soft Burn" \
"Inverse Dodge" "Inverse Burn" "Glow" "Heat" "Inv. Fade Down" \
"Inv. Fade Up" "Inv. Contrast Down" "Inv. Contrast Up" \
"Inv. Rev. Con. Down" "Inv. Rev. Con. Up" "Inverse Fade" \
"Inv. Rev. Fade" "Inverse Contrast" "Inv. Rev. Contrast" \
"Inverse Quantize" "Inv. Rev. Quantize" "Inv. Gamma" \
"Inv. Inverse Gamma" "Inv. Reverse Gamma" "Inv. Rev. Inv. Gamma" \
"Inv. Combined Gamma" "Inv. Rev. Comb. Gamma" "Inverse Stamp"
default = 0
hint = "Extra merge modes, just try them out !"
visible = @p_modeselect=="MMF Merge Modes"
endparam
int param qmin
caption = "Minimum Quantize"
default = 2
min = 2
hint = "Sets the minimum number of colour levels used after merging."
visible = @p_modeselect=="MMF Merge Modes" && \
(@p_mmfmergemode=="Quantize" || @p_mmfmergemode=="Reverse Quantize")
endparam
int param qmax
caption = "Maximum Quantize"
default = 32
min = 2
hint = "Sets the maximum number of colour levels used after merging. \
Should be set larger than 'Minimum Quantize' for correct use."
visible = @p_modeselect=="MMF Merge Modes" && \
(@p_mmfmergemode=="Quantize" || @p_mmfmergemode=="Reverse Quantize")
endparam
float param mingamma
caption = "Minimum Gamma"
default = 1.0
min = 1.0
hint = "Sets the minimum gamma to be used, use 1.0 for 'no change'."
visible = @p_modeselect=="MMF Merge Modes" && \
(@p_mmfmergemode=="Gamma" || @p_mmfmergemode=="Inverse Gamma" \
|| @p_mmfmergemode=="Reverse Gamma" \
|| @p_mmfmergemode=="Rev. Inv. Gamma" \
|| @p_mmfmergemode=="Combined Gamma" \
|| @p_mmfmergemode=="Rev. Comb. Gamma")
endparam
float param maxgamma
caption = "Maximum Gamma"
default = 2.0
min = 1.0
hint = "Sets the maximum gamma to be used. Should be set larger than \
'Minimum Gamma' for correct use."
visible = @p_modeselect=="MMF Merge Modes" && \
(@p_mmfmergemode=="Gamma" || @p_mmfmergemode=="Inverse Gamma" \
|| @p_mmfmergemode=="Reverse Gamma" \
|| @p_mmfmergemode=="Rev. Inv. Gamma" \
|| @p_mmfmergemode=="Combined Gamma" \
|| @p_mmfmergemode=="Rev. Comb. Gamma")
endparam
}
class MMF_GradientLayerMerge(MMF_LayerMerge) {
; PLEASE NOTE This class is obsolete/deprecated.
; @param pparent typically 'this' from the parent or zero
func MMF_GradientLayerMerge(Generic pparent)
MMF_LayerMergeBase.MMF_LayerMergeBase(pparent)
if @f_grad==0
m_Gradient = new @f_gradient(this)
endif
endfunc
;
; @param clr the base color
; @param index the gradient index for the top colour
; @return layer merged color
color func GradientMerge(color clr,float index)
if @f_grad==0
return FullMerge(clr, m_Gradient.GetColour(index))
else
return FullMerge(clr, gradient(index))
endif
endfunc
private:
MMF_UserGradient m_Gradient
default:
title = "MMF Layer Merge with Gradient"
rating = notRecommended
int param v_mmfgradientlayermerge
caption = "Version (MMF Layer Merge with Gradient)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
int param f_grad
caption = "Gradient to use"
enum = "Custom Gradient" "UF's Gradient"
default = 0
endparam
MMF_UserGradient param f_gradient
caption = "Layer Gradient"
default = MMF_Gradient
hint = "Allows you to customise the colours for this layer."
visible = @f_grad==0
endparam
}
class MMF_MultiLayerBase(common.ulb:DirectColoring) {
public:
;
; @param pz the z value
; @param clr the colour to use as the base layer colour
; @return colour
color func ResultUsingBaseColor(complex pz, color clr)
return clr
endfunc
default:
int param v_mmfmultilayerbase
caption = "Version (MMF_MultiLayerBase)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmfmultilayerbase < 100
endparam
}
class MMF_MultiLayerNone(MMF_MultiLayerBase) {
default:
title = "MMF No Layers"
heading
text = "This is just a dummy, to add extra layers select a multi-layer \
colouring formula such as 'MMF Layered' from mmf.ulb."
endheading
int param MMF_MultiLayerNone
caption = "Version (MMF Multi Layer None)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
}
class MMF_QuickGradient(common.ulb:GradientColoring) {
public:
; @param pparent usually "this" from the parent or zero
func MMF_QuickGradient(Generic pparent)
GradientColoring.GradientColoring(pparent)
endfunc
; @param pz
; @return gradient index
float func ResultIndex(complex pz)
if @type=="Linear"
if @offset
return 16.5 + 0.25*(real(m_Pixel)*cos(@angle*(#pi/180)) \
- imag(m_Pixel)*sin(@angle*(#pi/180)))
else
return 16.5 + 0.25*(real(m_Pixel)*cos(@angle*(#pi/180) - #angle) \
- imag(m_Pixel)*sin(@angle*(#pi/180) - #angle))
endif
elseif @type=="Cone"
if @offset
pz = cos(@angle*(#pi/180)) + flip(sin(@angle*(#pi/180)))
else
pz = cos(@angle*(#pi/180) - #angle) \
+ flip(sin(@angle*(#pi/180) - #angle))
endif
if @usecentre
m_Pixel = m_Pixel - #center
else
m_Pixel = m_Pixel - @centre
endif
pz = real(m_Pixel)*real(pz) - imag(m_Pixel)*imag(pz) \
+ flip(real(m_Pixel)*imag(pz) + imag(m_Pixel)*real(pz))
return 0.5 - atan2(pz) / (2 * #pi)
elseif @usecentre
return cabs(m_Pixel - #center)
else
return cabs(m_Pixel - @centre)
endif
endfunc
default:
title = "MMF Quick Gradient"
int param type
caption = "Gradient Type"
enum = "Linear" "Circular" "Cone"
default = 0
endparam
bool param offset
caption = "Offset from UF Angle ?"
default = true
hint = "When enabled the rotation angle you supply will be added to your \
default UF rotation angle, when disabled the angle is always \
from the horizontal."
visible = @type==0 || @type==2
endparam
float param angle
caption = "Angle (degrees)"
default = 0.0
hint = "The angle for the gradient."
visible = @type==0 || @type==2
endparam
bool param usecentre
caption = "Use Screen Centre ?"
default = true
visible = @type==1 || @type==2
endparam
complex param centre
caption = "Circle Centre"
default = (0,0)
visible = (@type==1 || @type==2) && !@usecentre
endparam
}
class AdjustmentLayer(common.ulb:Generic) {
public:
;
; @param pparent typically 'this' from the parent or zero
func AdjustmentLayer(Generic pparent)
Generic.Generic(pparent)
endfunc
;
; @param pbottom the base color
; @return adjusted color
color func Adjust(color pbottom)
return pbottom
endfunc
default:
int param v_adjustmentlayer
caption = "Version (AdjustmentLayer)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_adjustmentlayer < 100
endparam
}
class MMF_AdjustmentLayer(AdjustmentLayer) {
public:
import "common.ulb"
;
; @param pparent typically 'this' from the parent or zero
func MMF_AdjustmentLayer(Generic pparent)
Generic.Generic(pparent)
m_Adjust = new @f_adjust(this)
endfunc
;
; @param pbottom the base color
; @return adjusted color
color func Adjust(color pbottom)
color ptop
if @adjusttype==0
ptop = RGB(@adjred, @adjgreen, @adjblue)
else
ptop = @f_adjustcolour
endif
ptop = compose(pbottom, m_Adjust.Merge(pbottom, ptop), @f_opacity)
return RGBA(red(ptop), green(ptop), blue(ptop), alpha(pbottom))
endfunc
private:
ColorMerge m_Adjust
default:
title = "MMF Adjustment Layer"
param v_mmfadjustmentlayer
caption = "Version (MMF Adjustment Layer)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
int param adjusttype
caption = "Colour or RGB"
enum = "RGB values" "Colour Parameter"
default = 1
hint = "This option is specifically added so that if you choose \
'RGB values' you can 'explore' them and see changes to the image \
as you change the RGB. The option may become redundant in a \
future version of UF."
endparam
float param adjred
caption = "Red Value"
default = 1.0
hint = "The red part of the adjust colour (0 to 1)."
visible = @adjusttype==0
endparam
float param adjgreen
caption = "Green Value"
default = 1.0
hint = "The green part of the adjust colour (0 to 1)."
visible = @adjusttype==0
endparam
float param adjblue
caption = "Blue Value"
default = 1.0
hint = "The blue part of the adjust colour (0 to 1)."
visible = @adjusttype==0
endparam
color param f_adjustcolour
caption = "Adjust Layer Colour"
default = RGB(1,1,1)
hint = "Allows you to apply overall adjustments to your colouring."
visible = @adjusttype==1
endparam
ColorMerge param f_adjust
caption = "Adjustment Layer Merge"
default = MMF_ExtendedColorMerge
hint = "How the adjust colour is applied to the layer."
endparam
float param f_opacity
caption = "Adjustment Opacity"
default = 1.0
hint = "Use to modify the adjustment opacity, the normal range is from \
0 to 1."
endparam
}
class Layer(common.ulb:Generic) {
public:
;
; @param pparent typically 'this' from the parent or zero
func Layer(Generic pparent)
Generic.Generic(pparent)
m_Merge = new @f_merge(this)
if @adjustlayer
m_Adjustment = new @f_adjustment(this)
endif
endfunc
;
; @param pbottom the base color
; @param ptop the top color
; @return layer merged color
color func FullMerge(color pbottom, color ptop)
if @f_invertcompose
if @f_invertmerge
pbottom = m_Merge.FullMerge(ptop, pbottom, @f_opacity)
else
pbottom = compose(ptop, \
blend(ptop,m_Merge.Merge(pbottom,ptop),alpha(pbottom)), \
@f_opacity)
endif
elseif @f_invertmerge
pbottom = compose(pbottom, \
blend(pbottom,m_Merge.Merge(ptop,pbottom),alpha(ptop)), \
@f_opacity)
else
pbottom = m_Merge.FullMerge(pbottom, ptop, @f_opacity)
endif
if @adjustlayer
pbottom = m_Adjustment.Adjust(pbottom)
endif
return pbottom
endfunc
;
; @param clr the base color
; @param index the gradient index for the top colour
; @return layer merged color
color func GradientMerge(color clr,float index)
return FullMerge(clr, gradient(index))
endfunc
;
; @param clr the base color
; @return layer merged color
color func SolidMerge(color clr)
return FullMerge(clr, @f_solid)
endfunc
private:
ColorMerge m_Merge
AdjustmentLayer m_Adjustment
default:
int param v_layer
caption = "Version (Layer)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_layer < 100
endparam
color param f_solid
caption = "Solid Colour"
default = RGBA(0,0,0,1)
endparam
bool param f_invertmerge
caption = "Inverted Merge"
default = false
hint = "When enabled this layer is treated as the lower layer in the \
merge instead of as the upper layer, this inverts the way the \
RGBA values are treated."
endparam
bool param f_invertcompose
caption = "Inverted Compose"
default = false
hint = "When enabled this layer is treated as the lower layer in the \
compose instead of as the upper layer, so reduced opacity \
fades to this layer's colour instead of the underlying colour."
endparam
float param f_opacity
caption = "Layer Opacity"
default = 1.0
hint = "The normal range to use is from 0.0 to 1.0."
endparam
ColorMerge param f_merge
caption = "Layer Merge"
default = MMF_ExtendedColorMerge
endparam
bool param adjustlayer
caption = "Add Adjust layer"
default = false
hint = "Enable to add an adjustment layer in a given colour to merge \
on top of this layer prior to combining the result with the other \
layers. This allows you to tweak the colours of this layer, for \
instance adjusting the gamma, or colourising etc."
endparam
AdjustmentLayer param f_adjustment
caption = "Adjustment layer"
default = MMF_AdjustmentLayer
hint = "Use to tweak the layer colours."
visible = @adjustlayer
endparam
}
class DirectLayer(Layer) {
; Note that this class is not intended for use with gradients.
; @param pparent typically 'this' from the parent or zero
func DirectLayer(Generic pparent)
Layer.Layer(pparent)
endfunc
default:
int param v_directlayer
caption = "Version (DirectLayer)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_directlayer < 100
endparam
}
class GradientLayer(Layer) {
public:
import "common.ulb"
;
; @param pparent typically 'this' from the parent or zero
func GradientLayer(Generic pparent)
Layer.Layer(pparent)
if @f_grad==0
m_Gradient = new @f_gradient(this)
endif
endfunc
;
; @param clr the base color
; @param index the gradient index for the top colour
; @return layer merged color
color func GradientMerge(color clr,float index)
if @f_grad==0
return FullMerge(clr, m_Gradient.GetColour(index))
else
return FullMerge(clr, gradient(index))
endif
endfunc
private:
MMF_UserGradient m_Gradient
default:
int param v_gradientlayer
caption = "Version (GradientLayer)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_gradientlayer < 100
endparam
int param f_grad
caption = "Gradient to use"
enum = "Custom Gradient" "UF's Gradient"
default = 0
endparam
MMF_UserGradient param f_gradient
caption = "Layer Gradient"
default = MMF_Gradient
hint = "Allows you to customise the colours for this layer."
visible = @f_grad==0
endparam
bool param adjustlayer
caption = "Add Adjust layer"
default = false
hint = "Enable to add an adjustment layer in a given colour to merge \
on top of this layer prior to combining the result with the other \
layers. This allows you to tweak the colours of this layer, for \
instance adjusting the gamma, or colourising etc."
endparam
AdjustmentLayer param f_adjustment
caption = "Adjustment layer"
default = MMF_AdjustmentLayer
hint = "Use to tweak the layer colours."
visible = @adjustlayer
endparam
}
class MMF_DirectLayer(DirectLayer) {
public:
import "common.ulb"
;
; @param pparent typically 'this' from the parent or zero
func MMF_DirectLayer(Generic pparent)
DirectLayer.DirectLayer(pparent)
endfunc
default:
title = "MMF Direct Layer"
param v_mmfdirectlayer
caption = "Version (MMF Direct Layer)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
}
class MMF_GradientLayer(GradientLayer) {
public:
import "common.ulb"
;
; @param pparent typically 'this' from the parent or zero
func MMF_GradientLayer(Generic pparent)
GradientLayer.GradientLayer(pparent)
endfunc
default:
title = "MMF Gradient Layer"
param v_mmfgradientlayer
caption = "Version (MMF Gradient Layer)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
}
class MMF_Layered(MMF_MultiLayerBase) {
; This colouring allows you to use multiple colouring layers for a single
; fractal formula. This gives 3 main advantages over normal UF layering:
; @param pparent typically 'this' from the parent or zero
func MMF_Layered(Generic pparent)
DirectColoring.DirectColoring(pparent)
int i = 0
repeat
m_Use[i] = false
m_QuickGradient[i] = 0
until (i=i+1)>=10
m_Use[10] = false
if @colour0>0 && @colour0<11
m_Use[@colour0-1] = true
endif
if @colour1>0 && @colour1<11
m_Use[@colour1-1] = true
endif
if @colour2>0 && @colour2<11
m_Use[@colour2-1] = true
endif
if @colour3>0 && @colour3<11
m_Use[@colour3-1] = true
endif
if @colour4>0 && @colour4<11
m_Use[@colour4-1] = true
endif
if @colour5>0 && @colour5<11
m_Use[@colour5-1] = true
endif
if @colour6>0 && @colour6<11
m_Use[@colour6-1] = true
endif
if @colour7>0 && @colour7<11
m_Use[@colour7-1] = true
endif
if @colour8>0 && @colour8<11
m_Use[@colour8-1] = true
endif
if @colour9>0 && @colour9<11
m_Use[@colour9-1] = true
endif
if m_Use[0]
m_Colouring[0] = new @f_colouring0(this)
m_Direct[0] = @f_direct0
endif
if m_Use[1]
m_Colouring[1] = new @f_colouring1(this)
m_Direct[1] = @f_direct1
endif
if m_Use[2]
m_Colouring[2] = new @f_colouring2(this)
m_Direct[2] = @f_direct2
endif
if m_Use[3]
m_Colouring[3] = new @f_colouring3(this)
m_Direct[3] = @f_direct3
endif
if m_Use[4]
m_Colouring[4] = new @f_colouring4(this)
m_Direct[4] = @f_direct4
endif
if m_Use[5]
m_Colouring[5] = new @f_colouring5(this)
m_Direct[5] = @f_direct5
endif
if m_Use[6]
m_Colouring[6] = new @f_colouring6(this)
m_Direct[6] = @f_direct6
endif
if m_Use[7]
m_Colouring[7] = new @f_colouring7(this)
m_Direct[7] = @f_direct7
endif
if m_Use[8]
m_Colouring[8] = new @f_colouring8(this)
m_Direct[8] = @f_direct8
endif
if m_Use[9]
m_Colouring[9] = new @f_colouring9(this)
m_Direct[9] = @f_direct9
endif
if @f_colouring10!=MMF_MultiLayerNone
m_Use[10] = true
m_LayerColouring = MMF_MultiLayerBase(m_Colouring[10] = new @f_colouring10(this))
endif
if @colour0>0
if @colour0==11
m_Layer0 = new @f_layer0(this)
elseif @colour0==12
m_QuickGradient[0] = new @f_quickgradient0(this)
m_Layer0 = new @f_gradientlayer0(this)
elseif GradientColoring(m_Colouring[@colour0-1]) && !m_Direct[@colour0-1]
m_Layer0 = new @f_gradientlayer0(this)
else
m_Layer0 = new @f_layer0(this)
endif
endif
if @colour1>0
if @colour1==11
m_Layer1 = new @f_layer1(this)
elseif @colour1==12
m_QuickGradient[1] = new @f_quickgradient1(this)
m_Layer1 = new @f_gradientlayer1(this)
elseif GradientColoring(m_Colouring[@colour1-1]) && !m_Direct[@colour1-1]
m_Layer1 = new @f_gradientlayer1(this)
else
m_Layer1 = new @f_layer1(this)
endif
endif
if @colour2>0
if @colour2==11
m_Layer2 = new @f_layer2(this)
elseif @colour2==12
m_QuickGradient[2] = new @f_quickgradient2(this)
m_Layer2 = new @f_gradientlayer2(this)
elseif GradientColoring(m_Colouring[@colour2-1]) && !m_Direct[@colour2-1]
m_Layer2 = new @f_gradientlayer2(this)
else
m_Layer2 = new @f_layer2(this)
endif
endif
if @colour3>0
if @colour3==11
m_Layer3 = new @f_layer3(this)
elseif @colour3==12
m_QuickGradient[3] = new @f_quickgradient3(this)
m_Layer3 = new @f_gradientlayer3(this)
elseif GradientColoring(m_Colouring[@colour3-1]) && !m_Direct[@colour3-1]
m_Layer3 = new @f_gradientlayer3(this)
else
m_Layer3 = new @f_layer3(this)
endif
endif
if @colour4>0
if @colour4==11
m_Layer4 = new @f_layer4(this)
elseif @colour4==12
m_QuickGradient[4] = new @f_quickgradient4(this)
m_Layer4 = new @f_gradientlayer4(this)
elseif GradientColoring(m_Colouring[@colour4-1]) && !m_Direct[@colour4-1]
m_Layer4 = new @f_gradientlayer4(this)
else
m_Layer4 = new @f_layer4(this)
endif
endif
if @colour5>0
if @colour5==11
m_Layer5 = new @f_layer5(this)
elseif @colour5==12
m_QuickGradient[5] = new @f_quickgradient5(this)
m_Layer5 = new @f_gradientlayer5(this)
elseif GradientColoring(m_Colouring[@colour5-1]) && !m_Direct[@colour5-1]
m_Layer5 = new @f_gradientlayer5(this)
else
m_Layer5 = new @f_layer5(this)
endif
endif
if @colour6>0
if @colour6==11
m_Layer6 = new @f_layer6(this)
elseif @colour6==12
m_QuickGradient[6] = new @f_quickgradient6(this)
m_Layer6 = new @f_gradientlayer6(this)
elseif GradientColoring(m_Colouring[@colour6-1]) && !m_Direct[@colour6-1]
m_Layer6 = new @f_gradientlayer6(this)
else
m_Layer6 = new @f_layer6(this)
endif
endif
if @colour7>0
if @colour7==11
m_Layer7 = new @f_layer7(this)
elseif @colour7==12
m_QuickGradient[7] = new @f_quickgradient7(this)
m_Layer7 = new @f_gradientlayer7(this)
elseif GradientColoring(m_Colouring[@colour7-1]) && !m_Direct[@colour7-1]
m_Layer7 = new @f_gradientlayer7(this)
else
m_Layer7 = new @f_layer7(this)
endif
endif
if @colour8>0
if @colour8==11
m_Layer8 = new @f_layer8(this)
elseif @colour8==12
m_QuickGradient[8] = new @f_quickgradient8(this)
m_Layer8 = new @f_gradientlayer8(this)
elseif GradientColoring(m_Colouring[@colour8-1]) && !m_Direct[@colour8-1]
m_Layer8 = new @f_gradientlayer8(this)
else
m_Layer8 = new @f_layer8(this)
endif
endif
if @colour9>0
if @colour9==11
m_Layer9 = new @f_layer9(this)
elseif @colour9==12
m_QuickGradient[9] = new @f_quickgradient9(this)
m_Layer9 = new @f_gradientlayer9(this)
elseif GradientColoring(m_Colouring[@colour9-1]) && !m_Direct[@colour9-1]
m_Layer9 = new @f_gradientlayer9(this)
else
m_Layer9 = new @f_layer9(this)
endif
endif
endfunc
;
; Initialisation (per pixel)
; @param pz the z value
func Iterate(complex pz)
int i = 0
repeat
if m_Use[i]
m_Colouring[i].Iterate(pz)
endif
until (i=i+1)>=11
endfunc
;
; @param pz the z value
; @param clr the colour to use as the base colour
; @return the colour
color func ResultUsingBaseColor(complex pz, color clr)
bool m_Solid[10]
int i = 0
repeat
if m_Use[i]
if GradientColoring(m_Colouring[i]) && !m_Direct[i]
GradientColoring tmpGC = GradientColoring(m_Colouring[i])
m_Index[i] = tmpGC.ResultIndex(pz)
else
m_Colour[i] = m_Colouring[i].Result(pz)
endif
m_Solid[i] = m_Colouring[i].IsSolid()
endif
until (i=i+1)>=10
if @colour0>0
if @colour0==11
clr = m_Layer0.FullMerge(clr, @clr0)
elseif @colour0==12
clr = m_Layer0.GradientMerge(clr, m_QuickGradient[0].ResultIndex(pz))
elseif m_Solid[@colour0-1]
clr = m_Layer0.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour0-1]) && !m_Direct[@colour0-1]
clr = m_Layer0.GradientMerge(clr, m_Index[@colour0-1])
else
clr = m_Layer0.FullMerge(clr, m_Colour[@colour0-1])
endif
endif
if @colour1>0
if @colour1==11
clr = m_Layer1.FullMerge(clr, @clr1)
elseif @colour1==12
clr = m_Layer1.GradientMerge(clr, m_QuickGradient[1].ResultIndex(pz))
elseif m_Solid[@colour1-1]
clr = m_Layer1.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour1-1]) && !m_Direct[@colour1-1]
clr = m_Layer1.GradientMerge(clr, m_Index[@colour1-1])
else
clr = m_Layer1.FullMerge(clr, m_Colour[@colour1-1])
endif
endif
if @colour2>0
if @colour2==11
clr = m_Layer2.FullMerge(clr, @clr2)
elseif @colour2==12
clr = m_Layer2.GradientMerge(clr, m_QuickGradient[2].ResultIndex(pz))
elseif m_Solid[@colour2-1]
clr = m_Layer2.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour2-1]) && !m_Direct[@colour2-1]
clr = m_Layer2.GradientMerge(clr, m_Index[@colour2-1])
else
clr = m_Layer2.FullMerge(clr, m_Colour[@colour2-1])
endif
endif
if @colour3>0
if @colour3==11
clr = m_Layer3.FullMerge(clr, @clr3)
elseif @colour3==12
clr = m_Layer3.GradientMerge(clr, m_QuickGradient[3].ResultIndex(pz))
elseif m_Solid[@colour3-1]
clr = m_Layer3.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour3-1]) && !m_Direct[@colour3-1]
clr = m_Layer3.GradientMerge(clr, m_Index[@colour3-1])
else
clr = m_Layer3.FullMerge(clr, m_Colour[@colour3-1])
endif
endif
if @colour4>0
if @colour4==11
clr = m_Layer4.FullMerge(clr, @clr4)
elseif @colour4==12
clr = m_Layer4.GradientMerge(clr, m_QuickGradient[4].ResultIndex(pz))
elseif m_Solid[@colour4-1]
clr = m_Layer4.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour4-1]) && !m_Direct[@colour4-1]
clr = m_Layer4.GradientMerge(clr, m_Index[@colour4-1])
else
clr = m_Layer4.FullMerge(clr, m_Colour[@colour4-1])
endif
endif
if @colour5>0
if @colour5==11
clr = m_Layer5.FullMerge(clr, @clr5)
elseif @colour5==12
clr = m_Layer5.GradientMerge(clr, m_QuickGradient[5].ResultIndex(pz))
elseif m_Solid[@colour5-1]
clr = m_Layer5.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour5-1]) && !m_Direct[@colour5-1]
clr = m_Layer5.GradientMerge(clr, m_Index[@colour5-1])
else
clr = m_Layer5.FullMerge(clr, m_Colour[@colour5-1])
endif
endif
if @colour6>0
if @colour6==11
clr = m_Layer6.FullMerge(clr, @clr6)
elseif @colour6==12
clr = m_Layer6.GradientMerge(clr, m_QuickGradient[6].ResultIndex(pz))
elseif m_Solid[@colour6-1]
clr = m_Layer6.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour6-1]) && !m_Direct[@colour6-1]
clr = m_Layer6.GradientMerge(clr, m_Index[@colour6-1])
else
clr = m_Layer6.FullMerge(clr, m_Colour[@colour6-1])
endif
endif
if @colour7>0
if @colour7==11
clr = m_Layer7.FullMerge(clr, @clr7)
elseif @colour7==12
clr = m_Layer7.GradientMerge(clr, m_QuickGradient[7].ResultIndex(pz))
elseif m_Solid[@colour7-1]
clr = m_Layer7.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour7-1]) && !m_Direct[@colour7-1]
clr = m_Layer7.GradientMerge(clr, m_Index[@colour7-1])
else
clr = m_Layer7.FullMerge(clr, m_Colour[@colour7-1])
endif
endif
if @colour8>0
if @colour8==11
clr = m_Layer8.FullMerge(clr, @clr8)
elseif @colour8==12
clr = m_Layer8.GradientMerge(clr, m_QuickGradient[8].ResultIndex(pz))
elseif m_Solid[@colour8-1]
clr = m_Layer8.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour8-1]) && !m_Direct[@colour8-1]
clr = m_Layer8.GradientMerge(clr, m_Index[@colour8-1])
else
clr = m_Layer8.FullMerge(clr, m_Colour[@colour8-1])
endif
endif
if @colour9>0
if @colour9==11
clr = m_Layer9.FullMerge(clr, @clr9)
elseif @colour9==12
clr = m_Layer9.GradientMerge(clr, m_QuickGradient[9].ResultIndex(pz))
elseif m_Solid[@colour9-1]
clr = m_Layer9.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour9-1]) && !@f_direct9
clr = m_Layer9.GradientMerge(clr, m_Index[@colour9-1])
else
clr = m_Layer9.FullMerge(clr, m_Colour[@colour9-1])
endif
endif
if m_Use[10]
clr = m_LayerColouring.ResultUsingBaseColor(pz, clr)
endif
return clr
endfunc
;
; @param pz the z value
; @return the colour
color func Result(complex pz)
return ResultUsingBaseColor(pz, @basecolour)
endfunc
private:
Coloring m_Colouring[11]
GradientColoring m_QuickGradient[10]
MMF_MultiLayerBase m_LayerColouring
Layer m_Layer0
Layer m_Layer1
Layer m_Layer2
Layer m_Layer3
Layer m_Layer4
Layer m_Layer5
Layer m_Layer6
Layer m_Layer7
Layer m_Layer8
Layer m_Layer9
color m_Colour[10]
float m_Index[10]
bool m_Use[11]
bool m_Direct[10]
default:
title = "MMF Layered"
rating = recommended
param v_mmflayered
caption = "Version (MMF Layered)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
MMF_MultiLayerBase param f_colouring10
caption = "More Layers"
default = MMF_MultiLayerNone
hint = "Use to add more layers."
endparam
heading
enabled = false
endheading
param colour9
caption = "Layer 9 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 9"
visible = @colour9>0
endheading
color param clr9
caption = "Layer 9 Colour"
default = RGBA(1,1,1,1)
visible = @colour9==11
endparam
MMF_QuickGradient param f_quickgradient9
caption = "Layer 9 Gradient Colouring"
visible = @colour9==12
endparam
DirectLayer param f_layer9
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour9==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour9==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour9==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour9==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour9==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour9==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour9==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour9==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour9==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour9==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour9==11)
endparam
GradientLayer param f_gradientlayer9
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour9==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour9==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour9==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour9==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour9==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour9==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour9==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour9==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour9==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour9==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour9==12)
endparam
heading
enabled = false
visible = @colour9>0
endheading
param colour8
caption = "Layer 8 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 8"
visible = @colour8>0
endheading
color param clr8
caption = "Layer 8 Colour"
default = RGBA(1,1,1,1)
visible = @colour8==11
endparam
MMF_QuickGradient param f_quickgradient8
caption = "Layer 8 Gradient Colouring"
visible = @colour8==12
endparam
DirectLayer param f_layer8
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour8==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour8==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour8==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour8==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour8==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour8==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour8==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour8==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour8==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour8==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour8==11)
endparam
GradientLayer param f_gradientlayer8
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour8==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour8==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour8==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour8==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour8==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour8==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour8==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour8==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour8==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour8==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour8==12)
endparam
heading
enabled = false
visible = @colour8>0
endheading
param colour7
caption = "Layer 7 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 7"
visible = @colour7>0
endheading
color param clr7
caption = "Layer 7 Colour"
default = RGBA(1,1,1,1)
visible = @colour7==11
endparam
MMF_QuickGradient param f_quickgradient7
caption = "Layer 7 Gradient Colouring"
visible = @colour7==12
endparam
DirectLayer param f_layer7
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour7==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour7==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour7==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour7==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour7==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour7==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour7==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour7==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour7==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour7==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour7==11)
endparam
GradientLayer param f_gradientlayer7
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour7==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour7==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour7==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour7==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour7==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour7==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour7==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour7==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour7==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour7==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour7==12)
endparam
heading
enabled = false
visible = @colour7>0
endheading
param colour6
caption = "Layer 6 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 6"
visible = @colour6>0
endheading
color param clr6
caption = "Layer 6 Colour"
default = RGBA(1,1,1,1)
visible = @colour6==11
endparam
MMF_QuickGradient param f_quickgradient6
caption = "Layer 6 Gradient Colouring"
visible = @colour6==12
endparam
DirectLayer param f_layer6
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour6==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour6==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour6==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour6==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour6==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour6==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour6==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour6==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour6==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour6==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour6==11)
endparam
GradientLayer param f_gradientlayer6
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour6==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour6==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour6==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour6==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour6==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour6==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour6==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour6==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour6==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour6==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour6==12)
endparam
heading
enabled = false
visible = @colour6>0
endheading
param colour5
caption = "Layer 5 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 5"
visible = @colour5>0
endheading
color param clr5
caption = "Layer 5 Colour"
default = RGBA(1,1,1,1)
visible = @colour5==11
endparam
MMF_QuickGradient param f_quickgradient5
caption = "Layer 5 Gradient Colouring"
visible = @colour5==12
endparam
DirectLayer param f_layer5
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour5==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour5==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour5==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour5==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour5==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour5==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour5==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour5==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour5==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour5==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour5==11)
endparam
GradientLayer param f_gradientlayer5
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour5==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour5==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour5==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour5==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour5==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour5==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour5==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour5==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour5==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour5==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour5==12)
endparam
heading
enabled = false
visible = @colour5>0
endheading
param colour4
caption = "Layer 4 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 4"
visible = @colour4>0
endheading
color param clr4
caption = "Layer 4 Colour"
default = RGBA(1,1,1,1)
visible = @colour4==11
endparam
MMF_QuickGradient param f_quickgradient4
caption = "Layer 4 Gradient Colouring"
visible = @colour4==12
endparam
DirectLayer param f_layer4
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour4==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour4==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour4==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour4==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour4==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour4==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour4==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour4==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour4==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour4==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour4==11)
endparam
GradientLayer param f_gradientlayer4
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour4==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour4==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour4==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour4==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour4==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour4==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour4==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour4==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour4==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour4==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour4==12)
endparam
heading
enabled = false
visible = @colour4>0
endheading
param colour3
caption = "Layer 3 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 3"
visible = @colour3>0
endheading
color param clr3
caption = "Layer 3 Colour"
default = RGBA(1,1,1,1)
visible = @colour3==11
endparam
MMF_QuickGradient param f_quickgradient3
caption = "Layer 3 Gradient Colouring"
visible = @colour3==12
endparam
DirectLayer param f_layer3
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour3==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour3==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour3==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour3==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour3==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour3==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour3==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour3==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour3==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour3==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour3==11)
endparam
GradientLayer param f_gradientlayer3
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour3==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour3==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour3==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour3==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour3==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour3==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour3==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour3==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour3==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour3==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour3==12)
endparam
heading
enabled = false
visible = @colour3>0
endheading
param colour2
caption = "Layer 2 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 2"
visible = @colour2>0
endheading
color param clr2
caption = "Layer 2 Colour"
default = RGBA(1,1,1,1)
visible = @colour2==11
endparam
MMF_QuickGradient param f_quickgradient2
caption = "Layer 2 Gradient Colouring"
visible = @colour2==12
endparam
DirectLayer param f_layer2
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour2==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour2==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour2==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour2==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour2==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour2==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour2==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour2==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour2==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour2==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour2==11)
endparam
GradientLayer param f_gradientlayer2
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour2==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour2==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour2==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour2==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour2==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour2==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour2==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour2==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour2==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour2==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour2==12)
endparam
heading
enabled = false
visible = @colour2>0
endheading
param colour1
caption = "Layer 1 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 2
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 1"
visible = @colour1>0
endheading
color param clr1
caption = "Layer 1 Colour"
default = RGBA(1,1,1,1)
visible = @colour1==11
endparam
MMF_QuickGradient param f_quickgradient1
caption = "Layer 1 Gradient Colouring"
visible = @colour1==12
endparam
DirectLayer param f_layer1
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour1==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour1==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour1==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour1==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour1==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour1==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour1==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour1==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour1==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour1==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour1==11)
endparam
GradientLayer param f_gradientlayer1
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour1==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour1==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour1==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour1==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour1==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour1==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour1==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour1==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour1==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour1==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour1==12)
endparam
heading
enabled = false
visible = @colour1>0
endheading
param colour0
caption = "Layer 0 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 1
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 0"
visible = @colour0>0
endheading
color param clr0
caption = "Layer 0 Colour"
default = RGBA(1,1,1,1)
visible = @colour0==11
endparam
MMF_QuickGradient param f_quickgradient0
caption = "Layer 0 Gradient Colouring"
visible = @colour0==12
endparam
DirectLayer param f_layer0
caption = "Layer Merge"
default = MMF_DirectLayer
visible = ((@colour0==1 && (@f_colouring0==DirectColoring || @f_direct0)) \
|| (@colour0==2 && (@f_colouring1==DirectColoring || @f_direct1)) \
|| (@colour0==3 && (@f_colouring2==DirectColoring || @f_direct2)) \
|| (@colour0==4 && (@f_colouring3==DirectColoring || @f_direct3)) \
|| (@colour0==5 && (@f_colouring4==DirectColoring || @f_direct4)) \
|| (@colour0==6 && (@f_colouring5==DirectColoring || @f_direct5)) \
|| (@colour0==7 && (@f_colouring6==DirectColoring || @f_direct6)) \
|| (@colour0==8 && (@f_colouring7==DirectColoring || @f_direct7)) \
|| (@colour0==9 && (@f_colouring8==DirectColoring || @f_direct8)) \
|| (@colour0==10 && (@f_colouring9==DirectColoring || @f_direct9)) \
|| @colour0==11)
endparam
GradientLayer param f_gradientlayer0
caption = "Gradient Layer Merge"
default = MMF_GradientLayer
visible = ((@colour0==1 && @f_colouring0==GradientColoring && !@f_direct0) \
|| (@colour0==2 && @f_colouring1==GradientColoring && !@f_direct1) \
|| (@colour0==3 && @f_colouring2==GradientColoring && !@f_direct2) \
|| (@colour0==4 && @f_colouring3==GradientColoring && !@f_direct3) \
|| (@colour0==5 && @f_colouring4==GradientColoring && !@f_direct4) \
|| (@colour0==6 && @f_colouring5==GradientColoring && !@f_direct5) \
|| (@colour0==7 && @f_colouring6==GradientColoring && !@f_direct6) \
|| (@colour0==8 && @f_colouring7==GradientColoring && !@f_direct7) \
|| (@colour0==9 && @f_colouring8==GradientColoring && !@f_direct8) \
|| (@colour0==10 && @f_colouring9==GradientColoring && !@f_direct9) \
|| @colour0==12)
endparam
heading
caption = "Base Colour"
text = "Only used if below the lowest layer."
endheading
color param basecolour
caption = "Base Colour"
default = RGBA(0,0,0,0)
hint = "Note that if there are 'Layer' parameters below this parameter in \
the parameter list then this colour is unused i.e. this colour \
is only used if it is part of the lowest 10 layers."
endparam
heading
caption = "Colouring 9"
visible = @colour0==10 || @colour1==10 || @colour2==10 || @colour3==10 \
|| @colour4==10 || @colour5==10 || @colour6==10 || @colour7==10 \
|| @colour8==10 || @colour9==10
endheading
bool param f_direct9
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==10 || @colour1==10 || @colour2==10 || @colour3==10 \
|| @colour4==10 || @colour5==10 || @colour6==10 || @colour7==10 \
|| @colour8==10 || @colour9==10) && @f_Colouring9==GradientColoring
endparam
Coloring param f_Colouring9
caption = "Colouring 9"
default = Standard_Gradient
visible = @colour0==10 || @colour1==10 || @colour2==10 || @colour3==10 \
|| @colour4==10 || @colour5==10 || @colour6==10 || @colour7==10 \
|| @colour8==10 || @colour9==10
endparam
heading
caption = "Colouring 8"
visible = @colour0==9 || @colour1==9 || @colour2==9 || @colour3==9 \
|| @colour4==9 || @colour5==9 || @colour6==9 || @colour7==9 \
|| @colour8==9 || @colour9==9
endheading
bool param f_direct8
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==9 || @colour1==9 || @colour2==9 || @colour3==9 \
|| @colour4==9 || @colour5==9 || @colour6==9 || @colour7==9 \
|| @colour8==9 || @colour9==9) && @f_Colouring8==GradientColoring
endparam
Coloring param f_Colouring8
caption = "Colouring 8"
default = Standard_Gradient
visible = @colour0==9 || @colour1==9 || @colour2==9 || @colour3==9 \
|| @colour4==9 || @colour5==9 || @colour6==9 || @colour7==9 \
|| @colour8==9 || @colour9==9
endparam
heading
caption = "Colouring 7"
visible = @colour0==8 || @colour1==8 || @colour2==8 || @colour3==8 \
|| @colour4==8 || @colour5==8 || @colour6==8 || @colour7==8 \
|| @colour8==8 || @colour9==8
endheading
bool param f_direct7
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==8 || @colour1==8 || @colour2==8 || @colour3==8 \
|| @colour4==8 || @colour5==8 || @colour6==8 || @colour7==8 \
|| @colour8==8 || @colour9==8) && @f_Colouring7==GradientColoring
endparam
Coloring param f_Colouring7
caption = "Colouring 7"
default = Standard_Gradient
visible = @colour0==8 || @colour1==8 || @colour2==8 || @colour3==8 \
|| @colour4==8 || @colour5==8 || @colour6==8 || @colour7==8 \
|| @colour8==8 || @colour9==8
endparam
heading
caption = "Colouring 6"
visible = @colour0==7 || @colour1==7 || @colour2==7 || @colour3==7 \
|| @colour4==7 || @colour5==7 || @colour6==7 || @colour7==7 \
|| @colour8==7 || @colour9==7
endheading
bool param f_direct6
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==7 || @colour1==7 || @colour2==7 || @colour3==7 \
|| @colour4==7 || @colour5==7 || @colour6==7 || @colour7==7 \
|| @colour8==7 || @colour9==7) && @f_Colouring6==GradientColoring
endparam
Coloring param f_Colouring6
caption = "Colouring 6"
default = Standard_Gradient
visible = @colour0==7 || @colour1==7 || @colour2==7 || @colour3==7 \
|| @colour4==7 || @colour5==7 || @colour6==7 || @colour7==7 \
|| @colour8==7 || @colour9==7
endparam
heading
caption = "Colouring 5"
visible = @colour0==6 || @colour1==6 || @colour2==6 || @colour3==6 \
|| @colour4==6 || @colour5==6 || @colour6==6 || @colour7==6 \
|| @colour8==6 || @colour9==6
endheading
bool param f_direct5
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==6 || @colour1==6 || @colour2==6 || @colour3==6 \
|| @colour4==6 || @colour5==6 || @colour6==6 || @colour7==6 \
|| @colour8==6 || @colour9==6) && @f_Colouring5==GradientColoring
endparam
Coloring param f_Colouring5
caption = "Colouring 5"
default = Standard_Gradient
visible = @colour0==6 || @colour1==6 || @colour2==6 || @colour3==6 \
|| @colour4==6 || @colour5==6 || @colour6==6 || @colour7==6 \
|| @colour8==6 || @colour9==6
endparam
heading
caption = "Colouring 4"
visible = @colour0==5 || @colour1==5 || @colour2==5 || @colour3==5 \
|| @colour4==5 || @colour5==5 || @colour6==5 || @colour7==5 \
|| @colour8==5 || @colour9==5
endheading
bool param f_direct4
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==5 || @colour1==5 || @colour2==5 || @colour3==5 \
|| @colour4==5 || @colour5==5 || @colour6==5 || @colour7==5 \
|| @colour8==5 || @colour9==5) && @f_Colouring4==GradientColoring
endparam
Coloring param f_Colouring4
caption = "Colouring 4"
default = Standard_Gradient
visible = @colour0==5 || @colour1==5 || @colour2==5 || @colour3==5 \
|| @colour4==5 || @colour5==5 || @colour6==5 || @colour7==5 \
|| @colour8==5 || @colour9==5
endparam
heading
caption = "Colouring 3"
visible = @colour0==4 || @colour1==4 || @colour2==4 || @colour3==4 \
|| @colour4==4 || @colour5==4 || @colour6==4 || @colour7==4 \
|| @colour8==4 || @colour9==4
endheading
bool param f_direct3
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==4 || @colour1==4 || @colour2==4 || @colour3==4 \
|| @colour4==4 || @colour5==4 || @colour6==4 || @colour7==4 \
|| @colour8==4 || @colour9==4) && @f_Colouring3==GradientColoring
endparam
Coloring param f_Colouring3
caption = "Colouring 3"
default = Standard_Gradient
visible = @colour0==4 || @colour1==4 || @colour2==4 || @colour3==4 \
|| @colour4==4 || @colour5==4 || @colour6==4 || @colour7==4 \
|| @colour8==4 || @colour9==4
endparam
heading
caption = "Colouring 2"
visible = @colour0==3 || @colour1==3 || @colour2==3 || @colour3==3 \
|| @colour4==3 || @colour5==3 || @colour6==3 || @colour7==3 \
|| @colour8==3 || @colour9==3
endheading
bool param f_direct2
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==3 || @colour1==3 || @colour2==3 || @colour3==3 \
|| @colour4==3 || @colour5==3 || @colour6==3 || @colour7==3 \
|| @colour8==3 || @colour9==3) && @f_Colouring2==GradientColoring
endparam
Coloring param f_Colouring2
caption = "Colouring 2"
default = Standard_Gradient
visible = @colour0==3 || @colour1==3 || @colour2==3 || @colour3==3 \
|| @colour4==3 || @colour5==3 || @colour6==3 || @colour7==3 \
|| @colour8==3 || @colour9==3
endparam
heading
caption = "Colouring 1"
visible = @colour0==2 || @colour1==2 || @colour2==2 || @colour3==2 \
|| @colour4==2 || @colour5==2 || @colour6==2 || @colour7==2 \
|| @colour8==2 || @colour9==2
endheading
bool param f_direct1
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==2 || @colour1==2 || @colour2==2 || @colour3==2 \
|| @colour4==2 || @colour5==2 || @colour6==2 || @colour7==2 \
|| @colour8==2 || @colour9==2) && @f_Colouring1==GradientColoring
endparam
Coloring param f_Colouring1
caption = "Colouring 1"
default = Standard_OrbitTraps
visible = @colour0==2 || @colour1==2 || @colour2==2 || @colour3==2 \
|| @colour4==2 || @colour5==2 || @colour6==2 || @colour7==2 \
|| @colour8==2 || @colour9==2
endparam
heading
caption = "Colouring 0"
visible = @colour0==1 || @colour1==1 || @colour2==1 || @colour3==1 \
|| @colour4==1 || @colour5==1 || @colour6==1 || @colour7==1 \
|| @colour8==1 || @colour9==1
endheading
bool param f_direct0
caption = "Use in Direct Mode"
default = false
hint = "Some gradient colourings behave differently when used in direct \
mode rather than gradient mode. Enabling this option will use \
the gradient colouring in direct colouring mode."
visible = (@colour0==1 || @colour1==1 || @colour2==1 || @colour3==1 \
|| @colour4==1 || @colour5==1 || @colour6==1 || @colour7==1 \
|| @colour8==1 || @colour9==1) && @f_Colouring0==GradientColoring
endparam
Coloring param f_Colouring0
caption = "Colouring 0"
default = Standard_Smooth
visible = @colour0==1 || @colour1==1 || @colour2==1 || @colour3==1 \
|| @colour4==1 || @colour5==1 || @colour6==1 || @colour7==1 \
|| @colour8==1 || @colour9==1
endparam
}
class MMF_MultiLayer(MMF_MultiLayerBase) {
; PLEASE NOTE This class is obsolete/deprecated.
; @param pparent typically 'this' from the parent or zero
func MMF_MultiLayer(Generic pparent)
DirectColoring.DirectColoring(pparent)
int i = 0
repeat
m_Use[i] = false
m_QuickGradient[i] = 0
until (i=i+1)>=10
m_Use[10] = false
if @colour0>0 && @colour0<11
m_Use[@colour0-1] = true
endif
if @colour1>0 && @colour1<11
m_Use[@colour1-1] = true
endif
if @colour2>0 && @colour2<11
m_Use[@colour2-1] = true
endif
if @colour3>0 && @colour3<11
m_Use[@colour3-1] = true
endif
if @colour4>0 && @colour4<11
m_Use[@colour4-1] = true
endif
if @colour5>0 && @colour5<11
m_Use[@colour5-1] = true
endif
if @colour6>0 && @colour6<11
m_Use[@colour6-1] = true
endif
if @colour7>0 && @colour7<11
m_Use[@colour7-1] = true
endif
if @colour8>0 && @colour8<11
m_Use[@colour8-1] = true
endif
if @colour9>0 && @colour9<11
m_Use[@colour9-1] = true
endif
if m_Use[0]
m_Colouring[0] = new @f_colouring0(this)
endif
if m_Use[1]
m_Colouring[1] = new @f_colouring1(this)
endif
if m_Use[2]
m_Colouring[2] = new @f_colouring2(this)
endif
if m_Use[3]
m_Colouring[3] = new @f_colouring3(this)
endif
if m_Use[4]
m_Colouring[4] = new @f_colouring4(this)
endif
if m_Use[5]
m_Colouring[5] = new @f_colouring5(this)
endif
if m_Use[6]
m_Colouring[6] = new @f_colouring6(this)
endif
if m_Use[7]
m_Colouring[7] = new @f_colouring7(this)
endif
if m_Use[8]
m_Colouring[8] = new @f_colouring8(this)
endif
if m_Use[9]
m_Colouring[9] = new @f_colouring9(this)
endif
if @f_colouring10!=MMF_MultiLayerNone
m_Use[10] = true
m_LayerColouring = MMF_MultiLayerBase(m_Colouring[10] = new @f_colouring10(this))
endif
if @colour0>0
if @colour0==11
m_Merge0 = new @f_merge0(this)
elseif @colour0==12
m_QuickGradient[0] = new @f_quickgradient0(this)
m_Merge0 = new @f_gradientmerge0(this)
elseif GradientColoring(m_Colouring[@colour0-1])
m_Merge0 = new @f_gradientmerge0(this)
else
m_Merge0 = new @f_merge0(this)
endif
endif
if @colour1>0
if @colour1==11
m_Merge1 = new @f_merge1(this)
elseif @colour1==12
m_QuickGradient[1] = new @f_quickgradient1(this)
m_Merge1 = new @f_gradientmerge1(this)
elseif GradientColoring(m_Colouring[@colour1-1])
m_Merge1 = new @f_gradientmerge1(this)
else
m_Merge1 = new @f_merge1(this)
endif
endif
if @colour2>0
if @colour2==11
m_Merge2 = new @f_merge2(this)
elseif @colour2==12
m_QuickGradient[2] = new @f_quickgradient2(this)
m_Merge2 = new @f_gradientmerge2(this)
elseif GradientColoring(m_Colouring[@colour2-1])
m_Merge2 = new @f_gradientmerge2(this)
else
m_Merge2 = new @f_merge2(this)
endif
endif
if @colour3>0
if @colour3==11
m_Merge3 = new @f_merge3(this)
elseif @colour3==12
m_QuickGradient[3] = new @f_quickgradient3(this)
m_Merge3 = new @f_gradientmerge3(this)
elseif GradientColoring(m_Colouring[@colour3-1])
m_Merge3 = new @f_gradientmerge3(this)
else
m_Merge3 = new @f_merge3(this)
endif
endif
if @colour4>0
if @colour4==11
m_Merge4 = new @f_merge4(this)
elseif @colour4==12
m_QuickGradient[4] = new @f_quickgradient4(this)
m_Merge4 = new @f_gradientmerge4(this)
elseif GradientColoring(m_Colouring[@colour4-1])
m_Merge4 = new @f_gradientmerge4(this)
else
m_Merge4 = new @f_merge4(this)
endif
endif
if @colour5>0
if @colour5==11
m_Merge5 = new @f_merge5(this)
elseif @colour5==12
m_QuickGradient[5] = new @f_quickgradient5(this)
m_Merge5 = new @f_gradientmerge5(this)
elseif GradientColoring(m_Colouring[@colour5-1])
m_Merge5 = new @f_gradientmerge5(this)
else
m_Merge5 = new @f_merge5(this)
endif
endif
if @colour6>0
if @colour6==11
m_Merge6 = new @f_merge6(this)
elseif @colour6==12
m_QuickGradient[6] = new @f_quickgradient6(this)
m_Merge6 = new @f_gradientmerge6(this)
elseif GradientColoring(m_Colouring[@colour6-1])
m_Merge6 = new @f_gradientmerge6(this)
else
m_Merge6 = new @f_merge6(this)
endif
endif
if @colour7>0
if @colour7==11
m_Merge7 = new @f_merge7(this)
elseif @colour7==12
m_QuickGradient[7] = new @f_quickgradient7(this)
m_Merge7 = new @f_gradientmerge7(this)
elseif GradientColoring(m_Colouring[@colour7-1])
m_Merge7 = new @f_gradientmerge7(this)
else
m_Merge7 = new @f_merge7(this)
endif
endif
if @colour8>0
if @colour8==11
m_Merge8 = new @f_merge8(this)
elseif @colour8==12
m_QuickGradient[8] = new @f_quickgradient8(this)
m_Merge8 = new @f_gradientmerge8(this)
elseif GradientColoring(m_Colouring[@colour8-1])
m_Merge8 = new @f_gradientmerge8(this)
else
m_Merge8 = new @f_merge8(this)
endif
endif
if @colour9>0
if @colour9==11
m_Merge9 = new @f_merge9(this)
elseif @colour9==12
m_QuickGradient[9] = new @f_quickgradient9(this)
m_Merge9 = new @f_gradientmerge9(this)
elseif GradientColoring(m_Colouring[@colour9-1])
m_Merge9 = new @f_gradientmerge9(this)
else
m_Merge9 = new @f_merge9(this)
endif
endif
endfunc
;
; Initialisation (per pixel)
; @param pz the z value
func Iterate(complex pz)
int i = 0
repeat
if m_Use[i]
m_Colouring[i].Iterate(pz)
endif
until (i=i+1)>=11
endfunc
;
; @param pz the z value
; @param clr the colour to use as the base colour
; @return the colour
color func ResultUsingBaseColor(complex pz, color clr)
bool m_Solid[10]
int i = 0
repeat
if m_Use[i]
if GradientColoring(m_Colouring[i])
GradientColoring tmpGC = GradientColoring(m_Colouring[i])
m_Index[i] = tmpGC.ResultIndex(pz)
else
m_Colour[i] = m_Colouring[i].Result(pz)
endif
if @v_mmfmultilayer>0
m_Solid[i] = m_Colouring[i].IsSolid()
endif
endif
until (i=i+1)>=10
if @colour0>0
if @colour0==11
clr = m_Merge0.FullMerge(clr, @clr0)
elseif @colour0==12
clr = m_Merge0.GradientMerge(clr, m_QuickGradient[0].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour0-1]
clr = m_Merge0.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour0-1])
clr = m_Merge0.GradientMerge(clr, m_Index[@colour0-1])
else
clr = m_Merge0.FullMerge(clr, m_Colour[@colour0-1])
endif
endif
if @colour1>0
if @colour1==11
clr = m_Merge1.FullMerge(clr, @clr1)
elseif @colour1==12
clr = m_Merge1.GradientMerge(clr, m_QuickGradient[1].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour1-1]
clr = m_Merge1.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour1-1])
clr = m_Merge1.GradientMerge(clr, m_Index[@colour1-1])
else
clr = m_Merge1.FullMerge(clr, m_Colour[@colour1-1])
endif
endif
if @colour2>0
if @colour2==11
clr = m_Merge2.FullMerge(clr, @clr2)
elseif @colour2==12
clr = m_Merge2.GradientMerge(clr, m_QuickGradient[2].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour2-1]
clr = m_Merge2.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour2-1])
clr = m_Merge2.GradientMerge(clr, m_Index[@colour2-1])
else
clr = m_Merge2.FullMerge(clr, m_Colour[@colour2-1])
endif
endif
if @colour3>0
if @colour3==11
clr = m_Merge3.FullMerge(clr, @clr3)
elseif @colour3==12
clr = m_Merge3.GradientMerge(clr, m_QuickGradient[3].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour3-1]
clr = m_Merge3.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour3-1])
clr = m_Merge3.GradientMerge(clr, m_Index[@colour3-1])
else
clr = m_Merge3.FullMerge(clr, m_Colour[@colour3-1])
endif
endif
if @colour4>0
if @colour4==11
clr = m_Merge4.FullMerge(clr, @clr4)
elseif @colour4==12
clr = m_Merge4.GradientMerge(clr, m_QuickGradient[4].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour4-1]
clr = m_Merge4.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour4-1])
clr = m_Merge4.GradientMerge(clr, m_Index[@colour4-1])
else
clr = m_Merge4.FullMerge(clr, m_Colour[@colour4-1])
endif
endif
if @colour5>0
if @colour5==11
clr = m_Merge5.FullMerge(clr, @clr5)
elseif @colour5==12
clr = m_Merge5.GradientMerge(clr, m_QuickGradient[5].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour5-1]
clr = m_Merge5.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour5-1])
clr = m_Merge5.GradientMerge(clr, m_Index[@colour5-1])
else
clr = m_Merge5.FullMerge(clr, m_Colour[@colour5-1])
endif
endif
if @colour6>0
if @colour6==11
clr = m_Merge6.FullMerge(clr, @clr6)
elseif @colour6==12
clr = m_Merge6.GradientMerge(clr, m_QuickGradient[6].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour6-1]
clr = m_Merge6.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour6-1])
clr = m_Merge6.GradientMerge(clr, m_Index[@colour6-1])
else
clr = m_Merge6.FullMerge(clr, m_Colour[@colour6-1])
endif
endif
if @colour7>0
if @colour7==11
clr = m_Merge7.FullMerge(clr, @clr7)
elseif @colour7==12
clr = m_Merge7.GradientMerge(clr, m_QuickGradient[7].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour7-1]
clr = m_Merge7.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour7-1])
clr = m_Merge7.GradientMerge(clr, m_Index[@colour7-1])
else
clr = m_Merge7.FullMerge(clr, m_Colour[@colour7-1])
endif
endif
if @colour8>0
if @colour8==11
clr = m_Merge8.FullMerge(clr, @clr8)
elseif @colour8==12
clr = m_Merge8.GradientMerge(clr, m_QuickGradient[8].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour8-1]
clr = m_Merge8.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour8-1])
clr = m_Merge8.GradientMerge(clr, m_Index[@colour8-1])
else
clr = m_Merge8.FullMerge(clr, m_Colour[@colour8-1])
endif
endif
if @colour9>0
if @colour9==11
clr = m_Merge9.FullMerge(clr, @clr9)
elseif @colour9==12
clr = m_Merge9.GradientMerge(clr, m_QuickGradient[9].ResultIndex(pz))
elseif @v_mmfmultilayer>0 && m_Solid[@colour9-1]
clr = m_Merge9.SolidMerge(clr)
elseif GradientColoring(m_Colouring[@colour9-1])
clr = m_Merge9.GradientMerge(clr, m_Index[@colour9-1])
else
clr = m_Merge9.FullMerge(clr, m_Colour[@colour9-1])
endif
endif
if m_Use[10]
clr = m_LayerColouring.ResultUsingBaseColor(pz, clr)
endif
return clr
endfunc
;
; @param pz the z value
; @return the colour
color func Result(complex pz)
return ResultUsingBaseColor(pz, @basecolour)
endfunc
private:
Coloring m_Colouring[11]
GradientColoring m_QuickGradient[10]
MMF_MultiLayerBase m_LayerColouring
MMF_LayerMerge m_Merge0
MMF_LayerMerge m_Merge1
MMF_LayerMerge m_Merge2
MMF_LayerMerge m_Merge3
MMF_LayerMerge m_Merge4
MMF_LayerMerge m_Merge5
MMF_LayerMerge m_Merge6
MMF_LayerMerge m_Merge7
MMF_LayerMerge m_Merge8
MMF_LayerMerge m_Merge9
color m_Colour[10]
float m_Index[10]
bool m_Use[11]
default:
title = "MMF Multi Layer"
rating = notRecommended
heading
text = "PLEASE NOTE that this colouring is obsolete/deprecated. If \
creating a new UPR then you should use colourings such as \
'MMF Layered' instead."
endheading
int param v_mmfmultilayer
caption = "Version (MMF Multi Layer)"
enum = "1.0" "1.1"
default = 1
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = @v_mmfmultilayer<1
endparam
MMF_MultiLayerBase param f_colouring10
caption = "More Layers"
default = MMF_MultiLayerNone
hint = "Use to add more layers."
endparam
heading
enabled = false
endheading
int param colour9
caption = "Layer 9 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 9"
visible = @colour9>0
endheading
color param clr9
caption = "Layer 9 Colour"
default = RGBA(1,1,1,1)
visible = @colour9==11
endparam
MMF_QuickGradient param f_quickgradient9
caption = "Layer 9 Gradient Colouring"
visible = @colour9==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour9==1 && @f_colouring0!=GradientColoring) \
|| (@colour9==2 && @f_colouring1!=GradientColoring) \
|| (@colour9==3 && @f_colouring2!=GradientColoring) \
|| (@colour9==4 && @f_colouring3!=GradientColoring) \
|| (@colour9==5 && @f_colouring4!=GradientColoring) \
|| (@colour9==6 && @f_colouring5!=GradientColoring) \
|| (@colour9==7 && @f_colouring6!=GradientColoring) \
|| (@colour9==8 && @f_colouring7!=GradientColoring) \
|| (@colour9==9 && @f_colouring8!=GradientColoring) \
|| (@colour9==10 && @f_colouring9!=GradientColoring) \
|| @colour9==11) && @f_merge9==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge9
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour9==1 && @f_colouring0==DirectColoring) \
|| (@colour9==2 && @f_colouring1==DirectColoring) \
|| (@colour9==3 && @f_colouring2==DirectColoring) \
|| (@colour9==4 && @f_colouring3==DirectColoring) \
|| (@colour9==5 && @f_colouring4==DirectColoring) \
|| (@colour9==6 && @f_colouring5==DirectColoring) \
|| (@colour9==7 && @f_colouring6==DirectColoring) \
|| (@colour9==8 && @f_colouring7==DirectColoring) \
|| (@colour9==9 && @f_colouring8==DirectColoring) \
|| (@colour9==10 && @f_colouring9==DirectColoring) \
|| @colour9==11
endparam
MMF_GradientLayerMerge param f_gradientmerge9
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour9==1 && @f_colouring0==GradientColoring) \
|| (@colour9==2 && @f_colouring1==GradientColoring) \
|| (@colour9==3 && @f_colouring2==GradientColoring) \
|| (@colour9==4 && @f_colouring3==GradientColoring) \
|| (@colour9==5 && @f_colouring4==GradientColoring) \
|| (@colour9==6 && @f_colouring5==GradientColoring) \
|| (@colour9==7 && @f_colouring6==GradientColoring) \
|| (@colour9==8 && @f_colouring7==GradientColoring) \
|| (@colour9==9 && @f_colouring8==GradientColoring) \
|| (@colour9==10 && @f_colouring9==GradientColoring) \
|| @colour9==12
endparam
heading
enabled = false
visible = @colour9>0
endheading
int param colour8
caption = "Layer 8 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 8"
visible = @colour8>0
endheading
color param clr8
caption = "Layer 8 Colour"
default = RGBA(1,1,1,1)
visible = @colour8==11
endparam
MMF_QuickGradient param f_quickgradient8
caption = "Layer 8 Gradient Colouring"
visible = @colour8==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour8==1 && @f_colouring0!=GradientColoring) \
|| (@colour8==2 && @f_colouring1!=GradientColoring) \
|| (@colour8==3 && @f_colouring2!=GradientColoring) \
|| (@colour8==4 && @f_colouring3!=GradientColoring) \
|| (@colour8==5 && @f_colouring4!=GradientColoring) \
|| (@colour8==6 && @f_colouring5!=GradientColoring) \
|| (@colour7==7 && @f_colouring6!=GradientColoring) \
|| (@colour8==8 && @f_colouring7!=GradientColoring) \
|| (@colour8==9 && @f_colouring8!=GradientColoring) \
|| (@colour8==10 && @f_colouring9!=GradientColoring) \
|| @colour8==11) && @f_merge8==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge8
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour8==1 && @f_colouring0==DirectColoring) \
|| (@colour8==2 && @f_colouring1==DirectColoring) \
|| (@colour8==3 && @f_colouring2==DirectColoring) \
|| (@colour8==4 && @f_colouring3==DirectColoring) \
|| (@colour8==5 && @f_colouring4==DirectColoring) \
|| (@colour8==6 && @f_colouring5==DirectColoring) \
|| (@colour8==7 && @f_colouring6==DirectColoring) \
|| (@colour8==8 && @f_colouring7==DirectColoring) \
|| (@colour8==9 && @f_colouring8==DirectColoring) \
|| (@colour8==10 && @f_colouring9==DirectColoring) \
|| @colour8==11
endparam
MMF_GradientLayerMerge param f_gradientmerge8
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour8==1 && @f_colouring0==GradientColoring) \
|| (@colour8==2 && @f_colouring1==GradientColoring) \
|| (@colour8==3 && @f_colouring2==GradientColoring) \
|| (@colour8==4 && @f_colouring3==GradientColoring) \
|| (@colour8==5 && @f_colouring4==GradientColoring) \
|| (@colour8==6 && @f_colouring5==GradientColoring) \
|| (@colour8==7 && @f_colouring6==GradientColoring) \
|| (@colour8==8 && @f_colouring7==GradientColoring) \
|| (@colour8==9 && @f_colouring8==GradientColoring) \
|| (@colour8==10 && @f_colouring9==GradientColoring) \
|| @colour8==12
endparam
heading
enabled = false
visible = @colour8>0
endheading
int param colour7
caption = "Layer 7 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 7"
visible = @colour7>0
endheading
color param clr7
caption = "Layer 7 Colour"
default = RGBA(1,1,1,1)
visible = @colour7==11
endparam
MMF_QuickGradient param f_quickgradient7
caption = "Layer 7 Gradient Colouring"
visible = @colour7==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour7==1 && @f_colouring0!=GradientColoring) \
|| (@colour7==2 && @f_colouring1!=GradientColoring) \
|| (@colour7==3 && @f_colouring2!=GradientColoring) \
|| (@colour7==4 && @f_colouring3!=GradientColoring) \
|| (@colour7==5 && @f_colouring4!=GradientColoring) \
|| (@colour7==6 && @f_colouring5!=GradientColoring) \
|| (@colour7==7 && @f_colouring6!=GradientColoring) \
|| (@colour7==8 && @f_colouring7!=GradientColoring) \
|| (@colour7==9 && @f_colouring8!=GradientColoring) \
|| (@colour7==10 && @f_colouring9!=GradientColoring) \
|| @colour7==11) && @f_merge7==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge7
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour7==1 && @f_colouring0==DirectColoring) \
|| (@colour7==2 && @f_colouring1==DirectColoring) \
|| (@colour7==3 && @f_colouring2==DirectColoring) \
|| (@colour7==4 && @f_colouring3==DirectColoring) \
|| (@colour7==5 && @f_colouring4==DirectColoring) \
|| (@colour7==6 && @f_colouring5==DirectColoring) \
|| (@colour7==7 && @f_colouring6==DirectColoring) \
|| (@colour7==8 && @f_colouring7==DirectColoring) \
|| (@colour7==9 && @f_colouring8==DirectColoring) \
|| (@colour7==10 && @f_colouring9==DirectColoring) \
|| @colour7==11
endparam
MMF_GradientLayerMerge param f_gradientmerge7
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour7==1 && @f_colouring0==GradientColoring) \
|| (@colour7==2 && @f_colouring1==GradientColoring) \
|| (@colour7==3 && @f_colouring2==GradientColoring) \
|| (@colour7==4 && @f_colouring3==GradientColoring) \
|| (@colour7==5 && @f_colouring4==GradientColoring) \
|| (@colour7==6 && @f_colouring5==GradientColoring) \
|| (@colour7==7 && @f_colouring6==GradientColoring) \
|| (@colour7==8 && @f_colouring7==GradientColoring) \
|| (@colour7==9 && @f_colouring8==GradientColoring) \
|| (@colour7==10 && @f_colouring9==GradientColoring) \
|| @colour7==12
endparam
heading
enabled = false
visible = @colour7>0
endheading
int param colour6
caption = "Layer 6 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 6"
visible = @colour6>0
endheading
color param clr6
caption = "Layer 6 Colour"
default = RGBA(1,1,1,1)
visible = @colour6==11
endparam
MMF_QuickGradient param f_quickgradient6
caption = "Layer 6 Gradient Colouring"
visible = @colour6==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour6==1 && @f_colouring0!=GradientColoring) \
|| (@colour6==2 && @f_colouring1!=GradientColoring) \
|| (@colour6==3 && @f_colouring2!=GradientColoring) \
|| (@colour6==4 && @f_colouring3!=GradientColoring) \
|| (@colour6==5 && @f_colouring4!=GradientColoring) \
|| (@colour6==6 && @f_colouring5!=GradientColoring) \
|| (@colour6==7 && @f_colouring6!=GradientColoring) \
|| (@colour6==8 && @f_colouring7!=GradientColoring) \
|| (@colour6==9 && @f_colouring8!=GradientColoring) \
|| (@colour6==10 && @f_colouring9!=GradientColoring) \
|| @colour6==11) && @f_merge6==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge6
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour6==1 && @f_colouring0==DirectColoring) \
|| (@colour6==2 && @f_colouring1==DirectColoring) \
|| (@colour6==3 && @f_colouring2==DirectColoring) \
|| (@colour6==4 && @f_colouring3==DirectColoring) \
|| (@colour6==5 && @f_colouring4==DirectColoring) \
|| (@colour6==6 && @f_colouring5==DirectColoring) \
|| (@colour6==7 && @f_colouring6==DirectColoring) \
|| (@colour6==8 && @f_colouring7==DirectColoring) \
|| (@colour6==9 && @f_colouring8==DirectColoring) \
|| (@colour6==10 && @f_colouring9==DirectColoring) \
|| @colour6==11
endparam
MMF_GradientLayerMerge param f_gradientmerge6
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour6==1 && @f_colouring0==GradientColoring) \
|| (@colour6==2 && @f_colouring1==GradientColoring) \
|| (@colour6==3 && @f_colouring2==GradientColoring) \
|| (@colour6==4 && @f_colouring3==GradientColoring) \
|| (@colour6==5 && @f_colouring4==GradientColoring) \
|| (@colour6==6 && @f_colouring5==GradientColoring) \
|| (@colour6==7 && @f_colouring6==GradientColoring) \
|| (@colour6==8 && @f_colouring7==GradientColoring) \
|| (@colour6==9 && @f_colouring8==GradientColoring) \
|| (@colour6==10 && @f_colouring9==GradientColoring) \
|| @colour6==12
endparam
heading
enabled = false
visible = @colour6>0
endheading
int param colour5
caption = "Layer 5 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 5"
visible = @colour5>0
endheading
color param clr5
caption = "Layer 5 Colour"
default = RGBA(1,1,1,1)
visible = @colour5==11
endparam
MMF_QuickGradient param f_quickgradient5
caption = "Layer 5 Gradient Colouring"
visible = @colour5==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour5==1 && @f_colouring0!=GradientColoring) \
|| (@colour5==2 && @f_colouring1!=GradientColoring) \
|| (@colour5==3 && @f_colouring2!=GradientColoring) \
|| (@colour5==4 && @f_colouring3!=GradientColoring) \
|| (@colour5==5 && @f_colouring4!=GradientColoring) \
|| (@colour5==6 && @f_colouring5!=GradientColoring) \
|| (@colour5==7 && @f_colouring6!=GradientColoring) \
|| (@colour5==8 && @f_colouring7!=GradientColoring) \
|| (@colour5==9 && @f_colouring8!=GradientColoring) \
|| (@colour5==10 && @f_colouring9!=GradientColoring) \
|| @colour5==11) && @f_merge5==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge5
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour5==1 && @f_colouring0==DirectColoring) \
|| (@colour5==2 && @f_colouring1==DirectColoring) \
|| (@colour5==3 && @f_colouring2==DirectColoring) \
|| (@colour5==4 && @f_colouring3==DirectColoring) \
|| (@colour5==5 && @f_colouring4==DirectColoring) \
|| (@colour5==6 && @f_colouring5==DirectColoring) \
|| (@colour5==7 && @f_colouring6==DirectColoring) \
|| (@colour5==8 && @f_colouring7==DirectColoring) \
|| (@colour5==9 && @f_colouring8==DirectColoring) \
|| (@colour5==10 && @f_colouring9==DirectColoring) \
|| @colour5==11
endparam
MMF_GradientLayerMerge param f_gradientmerge5
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour5==1 && @f_colouring0==GradientColoring) \
|| (@colour5==2 && @f_colouring1==GradientColoring) \
|| (@colour5==3 && @f_colouring2==GradientColoring) \
|| (@colour5==4 && @f_colouring3==GradientColoring) \
|| (@colour5==5 && @f_colouring4==GradientColoring) \
|| (@colour5==6 && @f_colouring5==GradientColoring) \
|| (@colour5==7 && @f_colouring6==GradientColoring) \
|| (@colour5==8 && @f_colouring7==GradientColoring) \
|| (@colour5==9 && @f_colouring8==GradientColoring) \
|| (@colour5==10 && @f_colouring9==GradientColoring) \
|| @colour5==12
endparam
heading
enabled = false
visible = @colour5>0
endheading
int param colour4
caption = "Layer 4 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 4"
visible = @colour4>0
endheading
color param clr4
caption = "Layer 4 Colour"
default = RGBA(1,1,1,1)
visible = @colour4==11
endparam
MMF_QuickGradient param f_quickgradient4
caption = "Layer 4 Gradient Colouring"
visible = @colour4==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour4==1 && @f_colouring0!=GradientColoring) \
|| (@colour4==2 && @f_colouring1!=GradientColoring) \
|| (@colour4==3 && @f_colouring2!=GradientColoring) \
|| (@colour4==4 && @f_colouring3!=GradientColoring) \
|| (@colour4==5 && @f_colouring4!=GradientColoring) \
|| (@colour4==6 && @f_colouring5!=GradientColoring) \
|| (@colour4==7 && @f_colouring6!=GradientColoring) \
|| (@colour4==8 && @f_colouring7!=GradientColoring) \
|| (@colour4==9 && @f_colouring8!=GradientColoring) \
|| (@colour4==10 && @f_colouring9!=GradientColoring) \
|| @colour4==11) && @f_merge4==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge4
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour4==1 && @f_colouring0==DirectColoring) \
|| (@colour4==2 && @f_colouring1==DirectColoring) \
|| (@colour4==3 && @f_colouring2==DirectColoring) \
|| (@colour4==4 && @f_colouring3==DirectColoring) \
|| (@colour4==5 && @f_colouring4==DirectColoring) \
|| (@colour4==6 && @f_colouring5==DirectColoring) \
|| (@colour4==7 && @f_colouring6==DirectColoring) \
|| (@colour4==8 && @f_colouring7==DirectColoring) \
|| (@colour4==9 && @f_colouring8==DirectColoring) \
|| (@colour4==10 && @f_colouring9==DirectColoring) \
|| @colour4==11
endparam
MMF_GradientLayerMerge param f_gradientmerge4
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour4==1 && @f_colouring0==GradientColoring) \
|| (@colour4==2 && @f_colouring1==GradientColoring) \
|| (@colour4==3 && @f_colouring2==GradientColoring) \
|| (@colour4==4 && @f_colouring3==GradientColoring) \
|| (@colour4==5 && @f_colouring4==GradientColoring) \
|| (@colour4==6 && @f_colouring5==GradientColoring) \
|| (@colour4==7 && @f_colouring6==GradientColoring) \
|| (@colour4==8 && @f_colouring7==GradientColoring) \
|| (@colour4==9 && @f_colouring8==GradientColoring) \
|| (@colour4==10 && @f_colouring9==GradientColoring) \
|| @colour4==12
endparam
heading
enabled = false
visible = @colour4>0
endheading
int param colour3
caption = "Layer 3 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 3"
visible = @colour3>0
endheading
color param clr3
caption = "Layer 3 Colour"
default = RGBA(1,1,1,1)
visible = @colour3==11
endparam
MMF_QuickGradient param f_quickgradient3
caption = "Layer 3 Gradient Colouring"
visible = @colour3==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour3==1 && @f_colouring0!=GradientColoring) \
|| (@colour3==2 && @f_colouring1!=GradientColoring) \
|| (@colour3==3 && @f_colouring2!=GradientColoring) \
|| (@colour3==4 && @f_colouring3!=GradientColoring) \
|| (@colour3==5 && @f_colouring4!=GradientColoring) \
|| (@colour3==6 && @f_colouring5!=GradientColoring) \
|| (@colour3==7 && @f_colouring6!=GradientColoring) \
|| (@colour3==8 && @f_colouring7!=GradientColoring) \
|| (@colour3==9 && @f_colouring8!=GradientColoring) \
|| (@colour3==10 && @f_colouring9!=GradientColoring) \
|| @colour3==11) && @f_merge3==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge3
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour3==1 && @f_colouring0==DirectColoring) \
|| (@colour3==2 && @f_colouring1==DirectColoring) \
|| (@colour3==3 && @f_colouring2==DirectColoring) \
|| (@colour3==4 && @f_colouring3==DirectColoring) \
|| (@colour3==5 && @f_colouring4==DirectColoring) \
|| (@colour3==6 && @f_colouring5==DirectColoring) \
|| (@colour3==7 && @f_colouring6==DirectColoring) \
|| (@colour3==8 && @f_colouring7==DirectColoring) \
|| (@colour3==9 && @f_colouring8==DirectColoring) \
|| (@colour3==10 && @f_colouring9==DirectColoring) \
|| @colour3==11
endparam
MMF_GradientLayerMerge param f_gradientmerge3
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour3==1 && @f_colouring0==GradientColoring) \
|| (@colour3==2 && @f_colouring1==GradientColoring) \
|| (@colour3==3 && @f_colouring2==GradientColoring) \
|| (@colour3==4 && @f_colouring3==GradientColoring) \
|| (@colour3==5 && @f_colouring4==GradientColoring) \
|| (@colour3==6 && @f_colouring5==GradientColoring) \
|| (@colour3==7 && @f_colouring6==GradientColoring) \
|| (@colour3==8 && @f_colouring7==GradientColoring) \
|| (@colour3==9 && @f_colouring8==GradientColoring) \
|| (@colour3==10 && @f_colouring9==GradientColoring) \
|| @colour3==12
endparam
heading
enabled = false
visible = @colour3>0
endheading
int param colour2
caption = "Layer 2 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 0
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 2"
visible = @colour2>0
endheading
color param clr2
caption = "Layer 2 Colour"
default = RGBA(1,1,1,1)
visible = @colour2==11
endparam
MMF_QuickGradient param f_quickgradient2
caption = "Layer 2 Gradient Colouring"
visible = @colour2==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour2==1 && @f_colouring0!=GradientColoring) \
|| (@colour2==2 && @f_colouring1!=GradientColoring) \
|| (@colour2==3 && @f_colouring2!=GradientColoring) \
|| (@colour2==4 && @f_colouring3!=GradientColoring) \
|| (@colour2==5 && @f_colouring4!=GradientColoring) \
|| (@colour2==6 && @f_colouring5!=GradientColoring) \
|| (@colour2==7 && @f_colouring6!=GradientColoring) \
|| (@colour2==8 && @f_colouring7!=GradientColoring) \
|| (@colour2==9 && @f_colouring8!=GradientColoring) \
|| (@colour2==10 && @f_colouring9!=GradientColoring) \
|| @colour2==11) && @f_merge2==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge2
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour2==1 && @f_colouring0==DirectColoring) \
|| (@colour2==2 && @f_colouring1==DirectColoring) \
|| (@colour2==3 && @f_colouring2==DirectColoring) \
|| (@colour2==4 && @f_colouring3==DirectColoring) \
|| (@colour2==5 && @f_colouring4==DirectColoring) \
|| (@colour2==6 && @f_colouring5==DirectColoring) \
|| (@colour2==7 && @f_colouring6==DirectColoring) \
|| (@colour2==8 && @f_colouring7==DirectColoring) \
|| (@colour2==9 && @f_colouring8==DirectColoring) \
|| (@colour2==10 && @f_colouring9==DirectColoring) \
|| @colour2==11
endparam
MMF_GradientLayerMerge param f_gradientmerge2
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour2==1 && @f_colouring0==GradientColoring) \
|| (@colour2==2 && @f_colouring1==GradientColoring) \
|| (@colour2==3 && @f_colouring2==GradientColoring) \
|| (@colour2==4 && @f_colouring3==GradientColoring) \
|| (@colour2==5 && @f_colouring4==GradientColoring) \
|| (@colour2==6 && @f_colouring5==GradientColoring) \
|| (@colour2==7 && @f_colouring6==GradientColoring) \
|| (@colour2==8 && @f_colouring7==GradientColoring) \
|| (@colour2==9 && @f_colouring8==GradientColoring) \
|| (@colour2==10 && @f_colouring9==GradientColoring) \
|| @colour2==12
endparam
heading
enabled = false
visible = @colour2>0
endheading
int param colour1
caption = "Layer 1 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 2
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 1"
visible = @colour1>0
endheading
color param clr1
caption = "Layer 1 Colour"
default = RGBA(1,1,1,1)
visible = @colour1==11
endparam
MMF_QuickGradient param f_quickgradient1
caption = "Layer 1 Gradient Colouring"
visible = @colour1==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour1==1 && @f_colouring0!=GradientColoring) \
|| (@colour1==2 && @f_colouring1!=GradientColoring) \
|| (@colour1==3 && @f_colouring2!=GradientColoring) \
|| (@colour1==4 && @f_colouring3!=GradientColoring) \
|| (@colour1==5 && @f_colouring4!=GradientColoring) \
|| (@colour1==6 && @f_colouring5!=GradientColoring) \
|| (@colour1==7 && @f_colouring6!=GradientColoring) \
|| (@colour1==8 && @f_colouring7!=GradientColoring) \
|| (@colour1==9 && @f_colouring8!=GradientColoring) \
|| (@colour1==10 && @f_colouring9!=GradientColoring) \
|| @colour1==11) && @f_merge1==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge1
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour1==1 && @f_colouring0==DirectColoring) \
|| (@colour1==2 && @f_colouring1==DirectColoring) \
|| (@colour1==3 && @f_colouring2==DirectColoring) \
|| (@colour1==4 && @f_colouring3==DirectColoring) \
|| (@colour1==5 && @f_colouring4==DirectColoring) \
|| (@colour1==6 && @f_colouring5==DirectColoring) \
|| (@colour1==7 && @f_colouring6==DirectColoring) \
|| (@colour1==8 && @f_colouring7==DirectColoring) \
|| (@colour1==9 && @f_colouring8==DirectColoring) \
|| (@colour1==10 && @f_colouring9==DirectColoring) \
|| @colour1==11
endparam
MMF_GradientLayerMerge param f_gradientmerge1
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour1==1 && @f_colouring0==GradientColoring) \
|| (@colour1==2 && @f_colouring1==GradientColoring) \
|| (@colour1==3 && @f_colouring2==GradientColoring) \
|| (@colour1==4 && @f_colouring3==GradientColoring) \
|| (@colour1==5 && @f_colouring4==GradientColoring) \
|| (@colour1==6 && @f_colouring5==GradientColoring) \
|| (@colour1==7 && @f_colouring6==GradientColoring) \
|| (@colour1==8 && @f_colouring7==GradientColoring) \
|| (@colour1==9 && @f_colouring8==GradientColoring) \
|| (@colour1==10 && @f_colouring9==GradientColoring) \
|| @colour1==12
endparam
heading
enabled = false
visible = @colour1>0
endheading
int param colour0
caption = "Layer 0 Colouring"
enum = "None" "Colouring 0" "Colouring 1" "Colouring 2" "Colouring 3" \
"Colouring 4" "Colouring 5" "Colouring 6" "Colouring 7" \
"Colouring 8" "Colouring 9" "Single Colour" "Gradient Colouring"
default = 1
hint = "To enable this layer just select one of the 10 colourings to \
use on the layer."
endparam
heading
caption = "Layer 0"
visible = @colour0>0
endheading
color param clr0
caption = "Layer 0 Colour"
default = RGBA(1,1,1,1)
visible = @colour0==11
endparam
MMF_QuickGradient param f_quickgradient0
caption = "Layer 0 Gradient Colouring"
visible = @colour0==12
endparam
heading
text = "Please note that you have chosen a Layer Merge that includes \
gradient options on a layer that is using a Direct mode \
colouring. The gradient parameters in the Layer Merge will be \
ignored - it's better to use a Layer Merge that is not \
'with Gradient'."
visible = ((@colour0==1 && @f_colouring0!=GradientColoring) \
|| (@colour0==2 && @f_colouring1!=GradientColoring) \
|| (@colour0==3 && @f_colouring2!=GradientColoring) \
|| (@colour0==4 && @f_colouring3!=GradientColoring) \
|| (@colour0==5 && @f_colouring4!=GradientColoring) \
|| (@colour0==6 && @f_colouring5!=GradientColoring) \
|| (@colour0==7 && @f_colouring6!=GradientColoring) \
|| (@colour0==8 && @f_colouring7!=GradientColoring) \
|| (@colour0==9 && @f_colouring8!=GradientColoring) \
|| (@colour0==10 && @f_colouring9!=GradientColoring) \
|| @colour0==11) && @f_merge0==MMF_GradientLayerMerge
endheading
MMF_LayerMerge param f_merge0
caption = "Layer Merge"
default = MMF_LayerMerge
visible = (@colour0==1 && @f_colouring0!=GradientColoring) \
|| (@colour0==2 && @f_colouring1!=GradientColoring) \
|| (@colour0==3 && @f_colouring2!=GradientColoring) \
|| (@colour0==4 && @f_colouring3!=GradientColoring) \
|| (@colour0==5 && @f_colouring4!=GradientColoring) \
|| (@colour0==6 && @f_colouring5!=GradientColoring) \
|| (@colour0==7 && @f_colouring6!=GradientColoring) \
|| (@colour0==8 && @f_colouring7!=GradientColoring) \
|| (@colour0==9 && @f_colouring8!=GradientColoring) \
|| (@colour0==10 && @f_colouring9!=GradientColoring) \
|| @colour0==11
endparam
MMF_GradientLayerMerge param f_gradientmerge0
caption = "Gradient Layer Merge"
default = MMF_GradientLayerMerge
visible = (@colour0==1 && @f_colouring0==GradientColoring) \
|| (@colour0==2 && @f_colouring1==GradientColoring) \
|| (@colour0==3 && @f_colouring2==GradientColoring) \
|| (@colour0==4 && @f_colouring3==GradientColoring) \
|| (@colour0==5 && @f_colouring4==GradientColoring) \
|| (@colour0==6 && @f_colouring5==GradientColoring) \
|| (@colour0==7 && @f_colouring6==GradientColoring) \
|| (@colour0==8 && @f_colouring7==GradientColoring) \
|| (@colour0==9 && @f_colouring8==GradientColoring) \
|| (@colour0==10 && @f_colouring9==GradientColoring) \
|| @colour0==12
endparam
heading
caption = "Base Colour"
text = "Only used if below the lowest layer."
endheading
color param basecolour
caption = "Base Colour"
default = RGBA(0,0,0,0)
hint = "Note that if there are 'Layer' parameters below this parameter in \
the parameter list then this colour is unused i.e. this colour \
is only used if it is part of the lowest 10 layers."
endparam
heading
caption = "Colouring 9"
visible = @colour0==10 || @colour1==10 || @colour2==10 || @colour3==10 \
|| @colour4==10 || @colour5==10 || @colour6==10 || @colour7==10 \
|| @colour8==10 || @colour9==10
endheading
Coloring param f_Colouring9
caption = "Colouring 9"
default = Standard_Gradient
visible = @colour0==10 || @colour1==10 || @colour2==10 || @colour3==10 \
|| @colour4==10 || @colour5==10 || @colour6==10 || @colour7==10 \
|| @colour8==10 || @colour9==10
endparam
heading
caption = "Colouring 8"
visible = @colour0==9 || @colour1==9 || @colour2==9 || @colour3==9 \
|| @colour4==9 || @colour5==9 || @colour6==9 || @colour7==9 \
|| @colour8==9 || @colour9==9
endheading
Coloring param f_Colouring8
caption = "Colouring 8"
default = Standard_Gradient
visible = @colour0==9 || @colour1==9 || @colour2==9 || @colour3==9 \
|| @colour4==9 || @colour5==9 || @colour6==9 || @colour7==9 \
|| @colour8==9 || @colour9==9
endparam
heading
caption = "Colouring 7"
visible = @colour0==8 || @colour1==8 || @colour2==8 || @colour3==8 \
|| @colour4==8 || @colour5==8 || @colour6==8 || @colour7==8 \
|| @colour8==8 || @colour9==8
endheading
Coloring param f_Colouring7
caption = "Colouring 7"
default = Standard_Gradient
visible = @colour0==8 || @colour1==8 || @colour2==8 || @colour3==8 \
|| @colour4==8 || @colour5==8 || @colour6==8 || @colour7==8 \
|| @colour8==8 || @colour9==8
endparam
heading
caption = "Colouring 6"
visible = @colour0==7 || @colour1==7 || @colour2==7 || @colour3==7 \
|| @colour4==7 || @colour5==7 || @colour6==7 || @colour7==7 \
|| @colour8==7 || @colour9==7
endheading
Coloring param f_Colouring6
caption = "Colouring 6"
default = Standard_Gradient
visible = @colour0==7 || @colour1==7 || @colour2==7 || @colour3==7 \
|| @colour4==7 || @colour5==7 || @colour6==7 || @colour7==7 \
|| @colour8==7 || @colour9==7
endparam
heading
caption = "Colouring 5"
visible = @colour0==6 || @colour1==6 || @colour2==6 || @colour3==6 \
|| @colour4==6 || @colour5==6 || @colour6==6 || @colour7==6 \
|| @colour8==6 || @colour9==6
endheading
Coloring param f_Colouring5
caption = "Colouring 5"
default = Standard_Gradient
visible = @colour0==6 || @colour1==6 || @colour2==6 || @colour3==6 \
|| @colour4==6 || @colour5==6 || @colour6==6 || @colour7==6 \
|| @colour8==6 || @colour9==6
endparam
heading
caption = "Colouring 4"
visible = @colour0==5 || @colour1==5 || @colour2==5 || @colour3==5 \
|| @colour4==5 || @colour5==5 || @colour6==5 || @colour7==5 \
|| @colour8==5 || @colour9==5
endheading
Coloring param f_Colouring4
caption = "Colouring 4"
default = Standard_Gradient
visible = @colour0==5 || @colour1==5 || @colour2==5 || @colour3==5 \
|| @colour4==5 || @colour5==5 || @colour6==5 || @colour7==5 \
|| @colour8==5 || @colour9==5
endparam
heading
caption = "Colouring 3"
visible = @colour0==4 || @colour1==4 || @colour2==4 || @colour3==4 \
|| @colour4==4 || @colour5==4 || @colour6==4 || @colour7==4 \
|| @colour8==4 || @colour9==4
endheading
Coloring param f_Colouring3
caption = "Colouring 3"
default = Standard_Gradient
visible = @colour0==4 || @colour1==4 || @colour2==4 || @colour3==4 \
|| @colour4==4 || @colour5==4 || @colour6==4 || @colour7==4 \
|| @colour8==4 || @colour9==4
endparam
heading
caption = "Colouring 2"
visible = @colour0==3 || @colour1==3 || @colour2==3 || @colour3==3 \
|| @colour4==3 || @colour5==3 || @colour6==3 || @colour7==3 \
|| @colour8==3 || @colour9==3
endheading
Coloring param f_Colouring2
caption = "Colouring 2"
default = Standard_Gradient
visible = @colour0==3 || @colour1==3 || @colour2==3 || @colour3==3 \
|| @colour4==3 || @colour5==3 || @colour6==3 || @colour7==3 \
|| @colour8==3 || @colour9==3
endparam
heading
caption = "Colouring 1"
visible = @colour0==2 || @colour1==2 || @colour2==2 || @colour3==2 \
|| @colour4==2 || @colour5==2 || @colour6==2 || @colour7==2 \
|| @colour8==2 || @colour9==2
endheading
Coloring param f_Colouring1
caption = "Colouring 1"
default = Standard_OrbitTraps
visible = @colour0==2 || @colour1==2 || @colour2==2 || @colour3==2 \
|| @colour4==2 || @colour5==2 || @colour6==2 || @colour7==2 \
|| @colour8==2 || @colour9==2
endparam
heading
caption = "Colouring 0"
visible = @colour0==1 || @colour1==1 || @colour2==1 || @colour3==1 \
|| @colour4==1 || @colour5==1 || @colour6==1 || @colour7==1 \
|| @colour8==1 || @colour9==1
endheading
Coloring param f_Colouring0
caption = "Colouring 0"
default = Standard_Smooth
visible = @colour0==1 || @colour1==1 || @colour2==1 || @colour3==1 \
|| @colour4==1 || @colour5==1 || @colour6==1 || @colour7==1 \
|| @colour8==1 || @colour9==1
endparam
}
class MMF_SmoothOrbitTraps(common.ulb:GradientColoring) {
;
; Written by David Makin based on normal Orbit Traps by Damien Jones
; Note that you can use any normal trap plug-ins with this formula
; but you'll only get smoothing for Trap Modes derived from
; MMF_TrapModeSmooth or MMF_TrapModeSmoothWithThreshold, generally
; that means Trap Modes with "Smooth" in the title such as those
; in mmf.ulb.
; Note that if the texturing is set to position only and texturing
; is enabled then the texture Iterate() function is called here.
; Note that the texture calculation is skipped if there's no texture
; (using DMJ_TrapShapeFlat) or texturing is position only
; Note that if "Process final iteration" is enabled then Iterate()
; is called first one last time using the final value of pz.
; Note that if "Process final iteration" is enabled then Iterate()
; is called first one last time using the final value of pz. Note that derived functions should update zold, zolder, zoldok
; and zolderok as necessary This is basically IterateSilent extended so that the values of
; zold and zolder are kept up to date. It takes a sequence of complex point pairs (untransformed
; and transformed) and distances and produces a final result,
; storing old values for smoothing. Note that derived functions should always copy all used
; parameters to the "old" versions when they are changed as here.
; m_wastrapped should be set to true in the derived
; function when the main (current) values get changed Should be called only after the usual result has been returned
; by the appropriate Get function.
; Derived from TrapModeThreshold to ensure that the threshold parameter
; will be visible if used with non-smoothed orbit traps. Note that derived functions should always copy all used
; parameters to the "old" versions when they are changed as here.
; m_wastrapped should be set to true in the derived
; function when the main (current) values get changed
; This should only be called after previously calling Result()
; and getting the actual result value using the Trap Color Mode
; since the original result values are destroyed by this call.
; Note that in this class the Results are taken care of in the child
; TrapMode "m_trapmode".
public:
import "common.ulb"
func MMF_TrapModeSmoothTurningPoints(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
m_trapmode = new @p_trapmode(this)
endfunc
func Init(complex pz)
m_Iterations = 0
m_trapmode.Init(pz)
m_dir = 0
m_olddist = 0.0
m_oldv = 0.0
m_pzold = (0,0)
m_pztold = (0,0)
m_pdold = 0.0
m_ptold = 0.0
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
float v = pdistance
int dir = 0
if @p_mode=="Differences"
v = pdistance - m_olddist
endif
if v - m_oldv < 0.0
dir = -1 ; decreasing
elseif v - m_oldv > 0.0
dir = 1 ; increasing
endif
if (@p_trap=="All" && dir!=m_dir) || (@p_trap=="Maxima" && dir
; It's up to the derived function to copy zold to zolder and
; pz to zold after using the values of zolder, zold and pz
; (without modifying them obviously).
; And to (finally) copy zoldok to zolderok and set zoldok to true.
; Note that if there's no result (due to no zold or zolder) then
; the function could return +infinity as the value to ensure the
; value is outside any threshold. Here note the search loop to find a parent that is a Coloring object
; in order to get the ppixel value
; @param pparent the parent, generally "this" for the parent, or zero
; @return the colouring value for the trap
; @return flag for using "image all"
; @param ptrapmode the trapmode
; @param ptrapmode the trapmode
; @param clr image colour
; This is designed to be called once per change of texture, so normally
; just once say in a global section or in a constructor but it could be
; recalled if initiators were included in the class that could be set up
; in the constructor and modified later - allowing reconfiguration of the fBm.
; The initialisation is done here (in it's own function) instead of in the
; constructor mainly so that it's possible to avoid the init when texturing
; is disabled at run time e.g.
; Here pz is actually unused but is included in case derived functions
; want to initiate based on an external value.
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_RGBColorMerge(Generic pparent)
DefaultColorMerge.DefaultColorMerge(pparent)
endfunc
;
; @param pbottom the base color
; @param ptop the top color
; @return merged color
color func Merge(color pbottom, color ptop)
float red
float green
float blue
float bottom
float top
if @redtop=="Red"
top = red(ptop)
elseif @redtop=="Green"
top = green(ptop)
else
top = blue(ptop)
endif
if @redbtm=="Red"
bottom = red(pbottom)
elseif @redbtm=="Green"
bottom = green(pbottom)
else
bottom = blue(pbottom)
endif
if @p_modeselectred==1
red = MergeChannels(bottom, top, @p_mmfmergemodered, @qminred, @qmaxred, \
@mingammared, @maxgammared)
else
red = red(@f_mergemode(RGB(bottom,bottom,bottom), RGB(top,top,top)))
endif
if @greentop=="Red"
top = red(ptop)
elseif @greentop=="Green"
top = green(ptop)
else
top = blue(ptop)
endif
if @greenbtm=="Red"
bottom = red(pbottom)
elseif @greenbtm=="Green"
bottom = green(pbottom)
else
bottom = blue(pbottom)
endif
if @p_modeselectgreen==1
green = MergeChannels(bottom, top, @p_mmfmergemodegreen, @qmingreen, \
@qmaxgreen, @mingammagreen, @maxgammagreen)
else
green = green(@f_mergemodegreen(RGB(bottom,bottom,bottom), RGB(top,top,top)))
endif
if @bluetop=="Red"
top = red(ptop)
elseif @bluetop=="Green"
top = green(ptop)
else
top = blue(ptop)
endif
if @bluebtm=="Red"
bottom = red(pbottom)
elseif @bluebtm=="Green"
bottom = green(pbottom)
else
bottom = blue(pbottom)
endif
if @p_modeselectblue==1
blue = MergeChannels(bottom, top, @p_mmfmergemodeblue, @qminblue, \
@qmaxblue, @mingammablue, @maxgammablue)
else
blue = blue(@f_mergemodeblue(RGB(bottom,bottom,bottom), RGB(top,top,top)))
endif
return RGBA(red, green, blue, alpha(ptop))
endfunc
float func MergeChannels(float bottom, float top, int mode, int qmin, \
int qmax, float mingamma, float maxgamma)
if @clamp
if top<0.0
top = 0.0
elseif top>1.0
top = 1.0
endif
if bottom<0.0
bottom = 0.0
elseif bottom>1.0
bottom = 1.0
endif
endif
if mode==0;"Exclusion"
return bottom + top - 2*bottom*top
elseif mode==1;"Fade Down"
return top * (1 - top + bottom)
elseif mode==2;"Fade Up"
return bottom + top*(top - bottom)
elseif mode==3;"Contrast Down"
return 0.5 + top*(bottom - 0.5)
elseif mode==4;"Contrast Up"
if bottom<0.5
return bottom - 2.0*top*bottom*(0.5 - bottom)
else
return bottom + 2.0*top*(1.0 - bottom)*(bottom - 0.5)
endif
elseif mode==5;"Dodge"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
top = 1.0 - top
if bottom<=0
return 0.0
elseif top<=0.0
return 1.0
else
top = bottom/top
if top>1.0
top = 1.0
endif
return top
endif
elseif mode==6;"Burn"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
if top<=0.0
return 0.0
else
top = 1.0 - (1.0 - bottom)/top
if top<0.0
top = 0.0
endif
return top
endif
elseif mode==7;"Negation"
return 1.0 - abs(1.0 - top - bottom)
elseif mode==8;"Reflect"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
top = 1.0 - top
if bottom<=0
return 0.0
elseif top<=0.0
return 1.0
else
top = sqr(bottom)/top
if top>1.0
top = 1.0
endif
return top
endif
elseif mode==9;"Freeze"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
if top<=0.0
return 0.0
else
top = 1.0 - sqr(1.0 - bottom)/top
if top<0.0
top = 0.0
endif
return top
endif
elseif mode==10;"Rev. Contrast Down"
return 0.5 + (1.0 - top)*(bottom - 0.5)
elseif mode==11;"Rev. Contrast Up"
if bottom<0.5
return bottom - 2.0*(1.0 - top)*bottom*(0.5 - bottom)
else
return bottom + 2.0*(1.0 - top)*(1.0 - bottom)*(bottom - 0.5)
endif
elseif mode==12;"Fade"
if top<0.5
return 2.0 * top * (0.5 - top + bottom)
else
return bottom + 2.0 * (top - 0.5)*(top - bottom)
endif
elseif mode==13;"Reverse Fade"
if top<0.5
return bottom + 2.0 * top * (top - bottom)
else
return bottom + 2.0 * (1.0 - top)*(top - bottom)
endif
elseif mode==14 || mode==15;"Contrast" || "Reverse Contrast"
if mode==15;"Reverse Contrast"
top = 1.0 - top
endif
if top<0.5
return 0.5 + 2.0 * top * (bottom - 0.5)
else
top = 2.0 * (top - 0.5)
if bottom<0.5
return bottom - 2.0*top*bottom*(0.5 - bottom)
else
return bottom + 2.0*top*(1.0 - bottom)*(bottom - 0.5)
endif
endif
elseif mode==16;"Quantize"
int nr = round(qmax - (qmax-qmin)*(2.0/(1.0 + top) - 1.0)) - 1
return floor(bottom*(nr+0.999))/nr
elseif mode==17;"Reverse Quantize"
int nr = round(qmax - (qmax-qmin)*(2.0/(2.0 - top) - 1.0)) - 1
return floor(bottom*(nr+0.999))/nr
elseif mode==18;"Gamma"
return bottom^(mingamma+(maxgamma-mingamma)*top)
elseif mode==19;"Inverse Gamma"
return bottom^(1.0/(mingamma+(maxgamma-mingamma)*top))
elseif mode==20;"Reverse Gamma"
return bottom^(mingamma+(maxgamma-mingamma)*(1.0-top))
elseif mode==21;"Rev. Inv. Gamma"
return bottom^(1.0/(mingamma+(maxgamma-mingamma)*(1.0-top)))
elseif mode==22;"Combined Gamma"
if top<0.5
return bottom^(mingamma+2.0*(maxgamma-mingamma)*(0.5-top))
else
return bottom^(1.0/(mingamma+2.0*(maxgamma-mingamma)*(top-0.5)))
endif
elseif mode==23;"Rev. Comb. Gamma"
if top<0.5
return bottom^(1.0/(mingamma+2.0*(maxgamma-mingamma)*(0.5-top)))
else
return bottom^(mingamma+2.0*(maxgamma-mingamma)*(top-0.5))
endif
elseif mode==24;"Stamp"
top = bottom + 2.0*top - 1.0
if top<0.0
return 0.0
elseif top>1.0
return 1.0
endif
return top
elseif mode==25;"Soft Dodge"
if bottom<=0
return 0.0
elseif bottom+top<=1.0
if top>=1.0
return 1.0
elseif (top = 0.5*bottom/(1.0 - top))>1.0
return 1.0
endif
elseif (top = 1.0 - 0.5*(1.0 - top)/bottom)<0.0
return 0.0
endif
return top
elseif mode==26;"Soft Burn"
if top<=0
return 0.0
elseif top+bottom<=1.0
if bottom>=1.0
return 1.0
elseif (top = 0.5*top/(1.0 - bottom))>1.0
return 1.0
endif
elseif (top = 1.0 - 0.5*(1.0 - bottom)/top)<0.0
return 0.0
endif
return top
elseif mode==27;"Inverse Dodge"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
bottom = 1.0 - bottom
if top<=0
return 0
elseif bottom<=0.0
return 1.0
else
top = top/bottom
if top>1.0
return 1.0
endif
return top
endif
elseif mode==28;"Inverse Burn"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
if bottom<=0.0
return 0.0
else
top = 1.0 - (1.0 - top)/bottom
if top<0.0
return 0.0
endif
return top
endif
elseif mode==29;"Glow"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
bottom = 1.0 - bottom
if top<=0
return 0.0
elseif bottom<=0.0
return 1.0
else
top = sqr(top)/bottom
if top>1.0
return 1.0
endif
return top
endif
elseif mode==30;"Heat"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
if bottom<=0.0
return 0.0
else
top = 1.0 - sqr(1.0 - top)/bottom
if top<0.0
return 0.0
endif
return top
endif
elseif mode==31;"Inv. Fade Down"
return bottom * (1 - bottom + top)
elseif mode==32;"Inv. Fade Up"
return top + bottom*(bottom - top)
elseif mode==33;"Inv. Contrast Down"
return 0.5 + bottom*(top - 0.5)
elseif mode==34;"Inv. Contrast Up"
if top<0.5
return top - 2.0*bottom*top*(0.5 - top)
else
return top + 2.0*bottom*(1.0 - top)*(top - 0.5)
endif
elseif mode==35;"Inv. Rev. Con. Down"
return 0.5 + (1.0 - bottom)*(top - 0.5)
elseif mode==36;"Inv. Rev. Con. Up"
if top<0.5
return top - 2.0*(1.0 - bottom)*top*(0.5 - top)
else
return top + 2.0*(1.0 - bottom)*(1.0 - top)*(top - 0.5)
endif
elseif mode==37;"Inverse Fade"
if bottom<0.5
return 2.0 * bottom * (0.5 - bottom + top)
else
return top + 2.0 * (bottom - 0.5)*(bottom - top)
endif
elseif mode==38;"Inv. Rev. Fade"
if bottom<0.5
return top + 2.0 * bottom * (bottom - top)
else
return top + 2.0 * (1.0 - bottom)*(bottom - top)
endif
elseif mode==39 \
|| mode==40 ;"Inverse Contrast" || "Inv. Rev. Contrast"
if mode==40
bottom = 1.0 - bottom
endif
if bottom<0.5
return 0.5 + 2.0 * bottom * (top - 0.5)
else
bottom = 2.0 * (bottom - 0.5)
if top<0.5
return top - 2.0*bottom*top*(0.5 - top)
else
return top + 2.0*bottom*(1.0 - top)*(top - 0.5)
endif
endif
elseif mode==41;"Inverse Quantize"
int nr = round(qmax - (qmax-qmin)*(2.0/(1.0 + bottom) - 1.0)) - 1
return floor(top*(nr+0.999))/nr
elseif mode==42;"Inv. Rev. Quantize"
int nr = round(qmax - (qmax-qmin)*(2.0/(2.0 - bottom) - 1.0)) - 1
return floor(top*(nr+0.999))/nr
elseif mode==43;"Inv. Gamma"
return top^(mingamma+(maxgamma-mingamma)*bottom)
elseif mode==44;"Inv. Inverse Gamma"
return top^(1.0/(mingamma+(maxgamma-mingamma)*bottom))
elseif mode==45;"Inv. Reverse Gamma"
return top^(mingamma+(maxgamma-mingamma)*(1.0-bottom))
elseif mode==46;"Inv. Rev. Inv. Gamma"
return top^(1.0/(mingamma+(maxgamma-mingamma)*(1.0-bottom)))
elseif mode==47;"Inv. Combined Gamma"
if bottom<0.5
return top^(mingamma+2.0*(maxgamma-mingamma)*(0.5-bottom))
else
return top^(1.0/(mingamma+2.0*(maxgamma-mingamma)*(bottom-0.5)))
endif
elseif mode==48;"Inv. Rev. Comb. Gamma"
if bottom<0.5
return top^(1.0/(mingamma+2.0*(maxgamma-mingamma)*(0.5-bottom)))
else
return top^(mingamma+2.0*(maxgamma-mingamma)*(bottom-0.5))
endif
elseif mode==49;"Inverse Stamp"
top = top + 2.0*bottom - 1.0
if top<0.0
return 0.0
elseif top>1.0
return 1.0
endif
return top
elseif mode==50;"Pin Light"
if (top>=0.5 && top
; This is a combination of Distance Estimator or Smooth Iteration or
; Exponential Smoothing and Distance Estimator Angles or Field Lines
; that allows the use of either the distance estimate or the smooth
; iteration value or the exponential smoothing value combined with
; either the distance estimator angles or the field line angles for
; mapping an image into a fractal.
; It can use the "finalz" smoothing where a smoothing
; fraction is passed from the main formula based on
; a method suggested by Earl Hinrichs and it has a new
; extension to standard logarithmic smoothing in which
; the power/degree/exponent required for smoothing is
; calculated automagically by the formula - this works
; extremely well as long as the bailout/s are correct.
; It's also extended to allow Cilia for convergent areas
; and has new double-smoothed options that produce
; smooth results for those formulas with a smoothing
; power other than 2 (this is a cheat, there is a 'proper'
; way to do it but that only really works for whole
; integer powers (which you can now do using the "split"
; options with 'Interpolated', 'Sine Waves', 'Cells' or 'Bricks').
; This version includes options to "fix" the rotation and skew.
; NB. When using Hinrich's smoothing since the real part
; of the final z value is the smoothing fraction the
; formula doesn't know the actual final z value for
; the cilia hence only using older iterations will
; work unless you choose a main fractal formula using
; "+Atan" Hinrich's smoothing in which case 'No' for
; 'Old iterations' will work.
;
; Written by David Makin including ideas from many sources
; What it's initialised to is normally irrelevant unless the derived
; formula uses zold in its main calculations in which case the user
; should be given the choice of initialising zold to either the location,
; the initial z value or a fixed constant.
;
; This class extends Formula to provide automatic, simple
; bailout tests. Formulas for which the outside points
; converge on points OR grow without bound should derive
; from this class so as to avoid having to write the
; bailout tests and the GetUpperBailout() and
; GetLowerBailout() function.
; What it's initialised to is normally irrelevant unless the derived
; formula uses zold in its main calculations in which case the user
; should be given the choice of initialising zold to either the location,
; the initial z value or a fixed constant.
;
; Note that for historical reasons this formula uses its own
; bailout values instead of those defined in the base class
; doing so should not be taken as a model for other formulas.
; Note that for historical reasons this formula uses its own
; zold and bailout values instead of those defined in the base class
; doing so should not be taken as a model for other formulas.
; Note that for historical reasons this formula uses its own
; zold and bailout values instead of those defined in the base class
; doing so should not be taken as a model for other formulas.
; Note that for historical reasons this formula uses its own
; zold and bailout values instead of those defined in the base class
; doing so should not be taken as a model for other formulas.
; Note that for historical reasons this formula uses its own
; zold and bailout values instead of those defined in the base class
; doing so should not be taken as a model for other formulas.
; @param pbottom the base color
; @return adjusted color
color func Adjust(color pbottom)
color ptop
color pbase = pbottom
if @stretch
pbottom = rgb( stretch(red(pbottom)), stretch(green(pbottom)), \
stretch(blue(pbottom)) )
endif
if @adjusttype==0
ptop = RGB(@adjred, @adjgreen, @adjblue)
else
ptop = @f_adjustcolour
endif
ptop = compose(pbottom, m_Adjust.Merge(pbottom, ptop), @f_opacity)
if @stretch
ptop = rgb( contract(red(ptop),red(pbase)), \
contract(green(ptop),green(pbase)), \
contract(blue(ptop),blue(pbase)) )
endif
if @rept
ptop = m_Adjustmore.Adjust(ptop)
endif
if @domore
ptop = compose(ptop, \
m_Adjust1.Merge(ptop, m_Adjustmore1.Adjust(pbase)), @f_opacity1)
endif
return RGBA(red(ptop), green(ptop), blue(ptop), alpha(pbottom))
endfunc
private:
ColorMerge m_Adjust
ColorMerge m_Adjust1
Adjustmentlayer m_Adjustmore
Adjustmentlayer m_Adjustmore1
default:
title = "MMF Adjustment Layers"
param v_mmfadjustmentlayer
caption = "Version (MMF Adjustment Layers)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
int param adjusttype
caption = "Colour or RGB"
enum = "RGB values" "Colour Parameter"
default = 1
hint = "This option is specifically added so that if you choose \
'RGB values' you can 'explore' them and see changes to the image \
as you change the RGB. The option may become redundant in a \
future version of UF."
endparam
float param adjred
caption = "Red Value"
default = 1.0
hint = "The red part of the adjust colour (0 to 1)."
visible = @adjusttype==0
endparam
float param adjgreen
caption = "Green Value"
default = 1.0
hint = "The green part of the adjust colour (0 to 1)."
visible = @adjusttype==0
endparam
float param adjblue
caption = "Blue Value"
default = 1.0
hint = "The blue part of the adjust colour (0 to 1)."
visible = @adjusttype==0
endparam
color param f_adjustcolour
caption = "Adjust Layer Colour"
default = RGB(1,1,1)
hint = "Allows you to apply overall adjustments to your colouring."
visible = @adjusttype==1
endparam
bool param stretch
caption = "Restrict range"
default = false
hint = "When enabled you can set a range between 0 and 1 using a specified \
minimum and maximum such that the adjustment is restricted to that \
range."
endparam
float param min
caption = "Range Minimum"
default = 0.2
hint = "Value should be less than Range Maximum"
visible = @stretch
endparam
float param max
caption = "Range Maximum"
default = 0.8
hint = "Value should be more than Range Minimum"
visible = @stretch
endparam
bool param skew
caption = "Skew centre"
default = false
hint = "When enabled the chosen range is skewed by using the specified \
value as the centre of the range"
endparam
float param centre
caption = "Range Centre"
default = 0.5
hint = "Value should be between Range Minimum and Range Maximum"
visible = @stretch && @skew
endparam
ColorMerge param f_adjust
caption = "Adjustment Layer Merge"
default = MMF_ExtendedColorMerge
hint = "How the adjust colour is applied to the layer."
endparam
float param f_opacity
caption = "Adjustment Opacity"
default = 1.0
hint = "Use to modify the adjustment opacity, the normal range is from \
0 to 1."
endparam
heading
text = "Additional adjustments"
endheading
bool param rept
caption = "Add another adjustment"
default = false
endparam
Adjustmentlayer param f_adjustmore
caption = "Extra adjustment"
default = MMF_AdjustmentLayer
visible = @rept
endparam
bool param domore
caption = "Add another layer"
default = true
endparam
ColorMerge param f_adjust1
caption = "Adjustment Layers Merge"
default = MMF_ExtendedColorMerge
hint = "How the two adjusted layers are merged."
visible = @domore
endparam
float param f_opacity1
caption = "Merge Opacity"
default = 1.0
hint = "Use to modify the merge opacity, the normal range is from \
0 to 1."
visible = @domore
endparam
Adjustmentlayer param f_adjustmore1
caption = "Extra adjustment layer"
default = MMF_AdjustmentLayer
visible = @domore
endparam
}
; Instead of using this class and its derived classes you should use
; the Layer class and its derived classes.
public:
;
; Instead of using this class and its derived classes you should use
; the Layer class and its derived classes.
; Note that this class is not intended for use with gradients.
; If GradientMerge is called then UF's in-built gradient will be used.
; For layer gradients the MMF_GradientLayerMerge class should be used instead.
public:
import "common.ulb"
;
; Instead of using this class and its derived classes you should use
; the Layer class and its derived classes.
public:
import "common.ulb"
;
; If GradientMerge is called then UF's in-built gradient will be used.
; For layer gradients the GradientLayer class should be used instead.
public:
import "common.ulb"
;
; 1. The main fractal formula calculation is only done once no matter how
; many layers you use in this colouring.
; 2. You may use the extended "MMF" merge modes for merging the layers.
; 3. You can use the exact same colouring on different layers at different
; positions in the layer "stack" each using separate merge modes and palettes.
; Doing so means that the colouring value for the layers concerned is only
; calculated once.
; The only real disadvantages are that this layer colouring only works as a
; direct colouring and the custom palettes available for each layer are not
; quite as straightforward to use as the standard UF palette.
; @param pz initial z from the formula
; @param ppixel the location (normally #pixel)
func Init(complex pz, complex ppixel)
int i = 0
repeat
if m_Use[i]
m_Colouring[i].Init(pz, ppixel)
endif
if m_QuickGradient[i]
m_QuickGradient[i].Init(pz, ppixel)
endif
until (i=i+1)>=10
if m_Use[10]
m_Colouring[10].Init(pz, ppixel)
endif
endfunc
;
; Instead of using this class and its derived classes you should use
; the MMF Layered class and its derived classes.
public:
import "common.ulb"
import "Standard.ulb"
;
; @param pz initial z from the formula
; @param ppixel the location (normally #pixel)
func Init(complex pz, complex ppixel)
int i = 0
repeat
if m_Use[i]
m_Colouring[i].Init(pz, ppixel)
endif
if m_QuickGradient[i]
m_QuickGradient[i].Init(pz, ppixel)
endif
until (i=i+1)>=10
if m_Use[10]
m_Colouring[10].Init(pz, ppixel)
endif
endfunc
;
; Started May 2008
;
;
public:
import "common.ulb"
import "dmj5.ulb"
; Constructor - note the inititialisation of smoothing variables
; if necessary.
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SmoothOrbitTraps(Generic pparent)
GradientColoring.GradientColoring(pparent)
m_TrapSelect = new @f_trapselect(this)
m_TrapTransform = new @f_traptransform(this)
m_TrapShape = new @f_trapshape(this)
m_TrapTransfer = new @f_traptransfer(this)
m_TrapMode = new @f_trapmode(this)
m_TrapTexture = new @f_traptexture(this)
m_TrapColoring = new @f_trapcoloring(this)
m_FinalTransfer = new @f_finaltransfer(this)
m_IterTransfer = new @f_itertransfer(this)
m_TrapShape.SetThreshold(@p_threshold)
m_TrapMode.SetThreshold(@p_threshold)
if @smoothing<3 && (@f_trapmode==MMF_TrapModeSmooth \
|| @f_trapmode==MMF_TrapModeSmoothWithThreshold \
|| @f_additer)
il = real(1.0/log(@power)) ; for divergent smoothing
lp = log(0.5*log(@bailout))
ilp = il*lp
cil = real(1/log(@cpower)) ; for convergent smoothing
clp = log(-0.5*log(@smallbail))
cilp = cil*clp
endif
if @f_trapcoloring==MMF_TrapColoring \
&& @f_traptexture==DMJ_TrapShapeFlat
MMF_TrapColoring(m_TrapColoring).SetTextureFlag(false)
endif
m_texture = 0.0
endfunc
; Initialisation (per pixel)
; Standard colour Init()
; This version:
; @param pz initial z from the formula
; @param ppixel the location (normally #pixel)
func Init(complex pz, complex ppixel)
GradientColoring.Init(pz, ppixel)
m_TrapSelectSequence = m_TrapSelect.InitDefault()
m_TrapTransform.Init(pz)
m_TrapShape.Init(pz)
m_TrapTransfer.Init(pz)
m_TrapMode.Init(pz)
m_TrapTexture.Init(pz)
m_FinalTransfer.Init(pz)
m_IterTransfer.Init(pz)
if @smoothing<3 && (@f_trapmode==MMF_TrapModeSmooth \
|| @f_trapmode==MMF_TrapModeSmoothWithThreshold \
|| @f_additer)
m_zold = m_zolder = pz
m_zolderok = m_zoldok = false
endif
m_notlast = true
if @p_texturepositiononly && @f_traptexture!=DMJ_TrapShapeFlat
m_texture = m_TrapTexture.Iterate(ppixel)
endif
endfunc
;
; @param pz the z value
func Iterate(complex pz)
GradientColoring.Iterate(pz)
if @smoothing<3 && (@f_trapmode==MMF_TrapModeSmooth \
|| @f_trapmode==MMF_TrapModeSmoothWithThreshold \
|| @f_additer) \
&& m_notlast
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
endif
m_TrapSelectSequence = m_TrapSelect.Iterate(m_TrapSelectSequence)
if ((@f_trapselect==DMJ_TrapSelect && m_TrapSelectSequence>0.5) \
|| m_TrapSelectSequence > @p_trapselectthreshold)
complex zt = m_TrapTransform.Iterate(pz)
float distance = m_TrapShape.Iterate(zt)
float texture = m_texture
distance = m_TrapTransfer.Iterate(distance)
zt = m_TrapShape.GetTransformedPoint()
if @f_traptexture!=DMJ_TrapShapeFlat && !@p_texturepositiononly
texture = m_TrapShape.GetTextureValue()
if (@p_textureposttransform)
texture = texture + m_TrapTexture.Iterate(zt)
else
texture = texture + m_TrapTexture.Iterate(pz)
endif
texture = (texture + m_TrapTexture.GetTextureValue()) \
* @p_texturestrength
endif
if (!m_TrapTransform.IsSolid())
m_TrapMode.Iterate(pz, zt, distance, texture)
else
m_TrapMode.IterateSilent()
endif
else
if @f_TrapShape==MMF_TrapShapeZold && @f_fixzold
complex zt = m_TrapTransform.Iterate(pz)
MMF_TrapShapeZold(m_TrapShape).IterateSilentZold(zt)
else
if @f_TrapTransform==MMF_TrapTransformZold
MMF_TrapTransformZold(m_TrapTransform).IterateSilentZold(pz)
else
m_TrapTransform.IterateSilent()
endif
m_TrapShape.IterateSilent()
endif
m_TrapTransfer.IterateSilent()
m_TrapMode.IterateSilent()
if @f_traptexture!=DMJ_TrapShapeFlat && !@p_texturepositiononly
m_TrapTexture.IterateSilent()
endif
endif
endfunc
;
; @param pz the final z value
; @return index value
float func ResultIndex(complex pz)
float result
if @processlast
m_notlast = false
Iterate(pz)
endif
GradientColoring.ResultIndex(pz)
m_TrapMode.Result()
m_Solid = @p_usesolid && m_TrapMode.IsSolid()
result = m_TrapColoring.Result(m_TrapMode)
float f = 0.0
if @smoothing<3 && (@f_trapmode==MMF_TrapModeSmooth \
|| @f_trapmode==MMF_TrapModeSmoothWithThreshold \
|| @f_additer)
float m
if (@smoothing==0 || @smoothing==2) && |pz - m_zold|>1 \
&& (m=|pz|)>=@bailout
m = log(m)
if @dauto && m_zoldok
f = @fudge*real(lp - log(0.5*m))/log(m/log(|m_zold|))
else
f = @fudge*real(ilp - il*log(0.5*m))
endif
elseif (@smoothing==1 || @smoothing==2) \
&& ( (|pz - m_zold|<=@smallbail && !@cfixed) \
|| (|pz - @cfixedval|<=@smallbail && @cfixed) )
if @cfixed
m = log(|pz - @cfixedval|)
if @cauto && m_zoldok
f = @fudgec*real(clp - log(-0.5*m)) \
/log(m/log(|m_zold-@cfixedval|))
else
f = @fudgec*real(cilp - cil*log(-0.5*m))
endif
elseif @cauto && m_zolderok
m = log(|pz - m_zold|)
f = @fudgec*real(clp - log(-0.5*m)) \
/log(m/log(|m_zold-m_zolder|))
elseif m_zoldok
f = @fudgec*real(cilp - cil*log(-0.5*log(|pz - m_zold|)))
endif
endif
if (@f_TrapMode==MMF_TrapModeSmooth \
|| @f_trapmode==MMF_TrapModeSmoothWithThreshold) && f!=0.0
if @f_TrapMode==MMF_TrapModeSmooth
MMF_TrapModeSmooth(m_TrapMode).OldResult()
else
MMF_TrapModeSmoothWithThreshold(m_TrapMode).OldResult()
endif
result = result + f*(result - m_TrapColoring.Result(m_TrapMode))
endif
endif
if @f_additer
if @processlast
return m_FinalTransfer.Iterate(result) \
+ m_IterTransfer.Iterate(0.05*(m_Iterations + f))
else
return m_FinalTransfer.Iterate(result) \
+ m_IterTransfer.Iterate(0.05*(1.0 + m_Iterations + f))
endif
else
return m_FinalTransfer.Iterate(result)
endif
endfunc
;
; @param pz the final z value
; @return color value
color func Result(complex pz)
MMF_TrapColoring mmftc
if (mmftc = MMF_TrapColoring(m_TrapColoring))
if mmftc.UseColor()
float result
color icol
if @processlast
m_notlast = false
Iterate(pz)
endif
GradientColoring.ResultIndex(pz)
m_TrapMode.Result()
m_Solid = @p_usesolid && m_TrapMode.IsSolid()
icol = mmftc.ResultColor(m_TrapMode)
result = mmftc.ResultTexture(m_TrapMode)
float f = 0.0
if @smoothing<3 && (@f_trapmode==MMF_TrapModeSmooth \
|| @f_trapmode==MMF_TrapModeSmoothWithThreshold \
|| @f_additer)
float m
if (@smoothing==0 || @smoothing==2) && |pz - m_zold|>1 \
&& (m=|pz|)>=@bailout
m = log(m)
if @dauto && m_zoldok
f = @fudge*real(lp - log(0.5*m))/log(m/log(|m_zold|))
else
f = @fudge*real(ilp - il*log(0.5*m))
endif
elseif (@smoothing==1 || @smoothing==2) \
&& ( (|pz - m_zold|<=@smallbail && !@cfixed) \
|| (|pz - @cfixedval|<=@smallbail && @cfixed) )
if @cfixed
m = log(|pz - @cfixedval|)
if @cauto && m_zoldok
f = @fudgec*real(clp - log(-0.5*m)) \
/log(m/log(|m_zold-@cfixedval|))
else
f = @fudgec*real(cilp - cil*log(-0.5*m))
endif
elseif @cauto && m_zolderok
m = log(|pz - m_zold|)
f = @fudgec*real(clp - log(-0.5*m)) \
/log(m/log(|m_zold-m_zolder|))
elseif m_zoldok
f = @fudgec*real(cilp - cil*log(-0.5*log(|pz - m_zold|)))
endif
endif
if (@f_TrapMode==MMF_TrapModeSmooth \
|| @f_trapmode==MMF_TrapModeSmoothWithThreshold) && f!=0.0
if @f_TrapMode==MMF_TrapModeSmooth
MMF_TrapModeSmooth(m_TrapMode).OldResult()
else
MMF_TrapModeSmoothWithThreshold(m_TrapMode).OldResult()
endif
icol = icol + (icol - mmftc.ResultColor(m_TrapMode))*f
result = result + f*(result - mmftc.ResultTexture(m_TrapMode))
endif
endif
if @f_additer
if @f_traptexture==DMJ_TrapShapeFlat
mmftc.SetTextureFlag(true)
if @processlast
result = m_IterTransfer.Iterate(0.05*(m_Iterations + f))
else
result = m_IterTransfer.Iterate(0.05*(1.0 + m_Iterations + f))
endif
elseif @processlast
result = m_FinalTransfer.Iterate(result) \
+ m_IterTransfer.Iterate(0.05*(m_Iterations + f))
else
result = m_FinalTransfer.Iterate(result) \
+ m_IterTransfer.Iterate(0.05*(1.0 + m_Iterations + f))
endif
else
result = m_FinalTransfer.Iterate(result)
endif
icol = mmftc.MergeResult(icol,result)
if @smoothing<3 && @f_traptexture==DMJ_TrapShapeFlat && @f_additer
mmftc.SetTextureFlag(false)
endif
return icol
endif
endif
return gradient(ResultIndex(pz))
endfunc
protected:
Generator m_TrapSelect
UserTransform m_TrapTransform
TrapShape m_TrapShape
Transfer m_TrapTransfer
TrapMode m_TrapMode
TrapShape m_TrapTexture
TrapColoring m_TrapColoring
Transfer m_FinalTransfer
Transfer m_IterTransfer
float m_texture
float m_TrapSelectSequence
private:
complex m_zold
complex m_zolder
float il ; for divergent smoothing
float lp
float ilp
float cil ; for convergent smoothing
float clp
float cilp
bool m_zoldok
bool m_zolderok
bool m_notlast
default:
title = "MMF Smooth Orbit Traps (Gradient)"
rating = recommended
int param v_mmfsmoothorbittraps
caption = "Version (MMF Smooth Orbit Traps)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
heading
caption = "Information"
text = "Note that you can use any normal trap plug-ins with \
this colouring but you'll only get smoothing for Trap \
Modes written for it - generally trap modes with 'Smooth' \
in the title, e.g. in mmf.ulb. \
This colouring class is mainly intended for \
use on 'outside' areas, i.e. areas where bailout occurs, \
but for some of the mmf.ulb trap shapes it is required \
for 'inside' areas in preference to standard orbit trap \
formulas. If used 'inside' then it's best to select \
'Neither' as the 'Smoothing method' and not to enable \
'Process final iteration'. Note that when not wanting \
any texturing you should always set 'Trap Texture' to \
dmj5.ulb->Flat Texture."
endheading
heading
caption = "Smoothing parameters"
endheading
int param smoothing
caption = "Smoothing method"
enum = "Divergent" "Convergent" "Both" "Neither"
default = 0
hint = "Choose the smoothing that matches your main formula type \
e.g. 'Divergent' for z^2+c, 'Convergent' for Newton, \
'Both' for Magnet formulas. If using this colouring for \
'inside' areas then it's best to select 'Neither'."
endparam
heading
text = "Divergent Smoothing parameters"
visible = @smoothing==0 || @smoothing==2
endheading
float param bailout
caption = "Bailout"
default = 128.0
hint = "This should match the bailout in the fractal formula."
visible = @smoothing==0 || @smoothing==2
endparam
bool param dauto
caption = "Auto-power"
default = true
hint = "When enabled should produce smoothing for most divergent \
areas without you needing to set the divergent power value \
for the colouring."
visible = @smoothing==0 || @smoothing==2
endparam
complex param power
caption = "Power/exponent/degree"
default = (2,0)
hint = "This should match the power/degree/exponent in the \
fractal formula. When using 'Auto-power' it's only used \
for areas that bailed on the first or second iteration."
visible = @smoothing==0 || @smoothing==2
endparam
float param fudge
caption = "Scaling fudge"
default = 1.0
hint = "This is a scaling fudge value, it's used to scale \
the calculated iteration fraction when the value \
doesn't reach 1, it's unlikely to be required for \
divergent smoothing but I added it just in case. If \
'Auto-power' or the best value you can find for \
the power parameter don't produce smooth results then \
modifying this value may help."
visible = @smoothing==0 || @smoothing==2
endparam
heading
text = "Convergent Smoothing parameters"
visible = @smoothing==1 || @smoothing==2
endheading
float param smallbail
caption = "Bailout"
default = 1e-5
hint = "This should match the small bailout in your fractal formula."
visible = @smoothing==1 || @smoothing==2
endparam
bool param cauto
caption = "Auto-power"
default = true
hint = "When enabled should produce smoothing for most convergent \
areas without you needing to set a convergent power value \
for the colouring."
visible = @smoothing==1 || @smoothing==2
endparam
complex param cpower
caption = "Power/exponent/degree"
default = (2,0)
hint = "This should match the power (exponent/degree) for the \
convergent areas of your main fractal formula. When \
using 'Auto-power' it's only used for areas that bailed \
on the first or second iteration."
visible = @smoothing==1 || @smoothing==2
endparam
float param fudgec
caption = "Scaling Fudge"
default = 1.0
hint = "This is a scaling fudge value, it's used to scale \
the calculated iteration fraction when the value \
doesn't reach 1. If 'Auto-power' or the best value you can \
find for the 'Convergent Power' parameter don't \
produce smooth results then modifying this value \
should help."
visible = @smoothing==1 || @smoothing==2
endparam
bool param cfixed
caption = "Absolute convergence"
default = false
hint = "For when using a main formula that tests for convergence by \
using (only) |#z-value| rather than |#z-zold|, a typical \
example would be a Magnet formula where |#z-1.0| is often \
used. When enabled set the value of 'Convergence root' \
appropriately."
visible = @smoothing==1 || @smoothing==2
endparam
complex param cfixedval
caption = "Convergence root"
default = (1,0)
hint = "Use (1.0,0) for some Magnet formulas."
visible = (@smoothing==1 || @smoothing==2) && @cfixed
endparam
heading
caption = "Trapping parameters"
endheading
bool param processlast
caption = "Process final iteration"
default = true
hint = "When enabled then the final (bailed out) value of z is \
trapped in addition to the previous values. Should not \
be enabled if colouring 'inside'."
endparam
Generator param f_trapselect
caption = "Trap Iteration"
default = DMJ_TrapSelect
expanded = false
endparam
float param p_trapselectthreshold
caption = "Threshold"
default = 0.5
hint = "When using a Generator other than a TrapSelect type, values \
could range anywhere from 0 to 1. This threshold sets which \
values will be interpreted as 'do not trap' and which will be \
interpreted as 'trap'."
visible = (@f_trapselect != DMJ_TrapSelect)
endparam
UserTransform param f_traptransform
caption = "Trap Position"
default = TrapTransform
hint = "This transform is commonly used to set the position of the \
trap. You can load any Transform object here, but if you \
replace the TrapTransform you will lose the ability to \
position the trap. To regain that ability, use the \
TransformMerge class here so you can load any Transform \
and still be able to use a TrapTransform object."
expanded = false
endparam
TrapShape param f_trapshape
caption = "Trap Shape"
default = MMF_TrapShapeTriangleInequality
hint = "The trap shape sets the overall shape of the trap. Its only \
task is to measure the distance from any point to the trap \
shape."
endparam
bool param f_fixzold
caption = "Fix zold ?"
default = true
hint = "When enabled this improves the functionality of your trap \
shape when skipping iterations but can cause problems when \
combined with some Trap Positions so you may disable it if \
necessary."
visible = @f_TrapShape==MMF_TrapShapeZold
endparam
Transfer param f_traptransfer
caption = "Trap Transfer"
default = TrapTransfer
hint = "A transfer allows you to manipulate the distances provided \
by the trap shape."
expanded = false
endparam
TrapMode param f_trapmode
caption = "Trap Mode"
default = MMF_TrapModeSmoothAverage
endparam
heading
text = "Warning - The currently selected Trap Mode will not be \
smoothed. You should use a Trap Mode with 'Smooth' in the \
title."
visible = @f_trapmode!=MMF_TrapModeSmooth \
&& @f_trapmode!=MMF_TrapModeSmoothWithThreshold
endheading
float param p_threshold
caption = "Trap Threshold"
default = 1.0
hint = "This is the overall size or thickness of the trap area. \
(Some trap modes may not use the threshold value.)"
visible = (@f_trapmode == TrapModeWithThreshold)
endparam
bool param p_usesolid
caption = "Use Solid Color"
default = false
hint = "If checked, any areas not inside any trap shape will be \
colored using the solid color."
endparam
TrapShape param f_traptexture
caption = "Trap Texture"
default = DMJ_TrapShapeFlat
hint = "A trap shape that is used as a texture. Textures do not \
change the shape of the trap but may change its coloring."
endparam
bool param p_texturepositiononly
caption = "Texture from location only"
default = false
hint = "When enabled the texturing is based on the location. \
This is equivalent to basing the texture on #pixel. \
The rendering time is reduced \
considerably when this is enabled. Note that when \
used the texture density will be completely \
independant of the trap shape but may still change \
depending on the trap mode."
visible = @f_traptexture!=DMJ_TrapShapeFlat
endparam
bool param p_textureposttransform
caption = "Use Transformed Coordinate"
default = false
hint = "If checked, texturing will be based on the final transformed \
coordinate used in the trap shape (i.e. it will follow the \
trap shape, rather than being separate from it)."
visible = (@f_traptexture != DMJ_TrapShapeFlat) \
&& !@p_texturepositiononly
endparam
float param p_texturestrength
caption = "Texture Amount"
default = 1.0
hint = "Sets the overall amount of texture to be used. Larger \
numbers will increase the effect of the texture. A value \
of 0 will remove the effects of the texture."
visible = (@f_traptexture != DMJ_TrapShapeFlat) \
&& !@p_texturepositiononly
endparam
TrapColoring param f_trapcoloring
caption = "Trap Color Mode"
default = MMF_TrapColoring
endparam
Transfer param f_finaltransfer
caption = "Final Transfer"
default = MMF_TrapTransfer
hint = "Allows you to manipulate the final combined value of \
the trap colour and the texturing."
endparam
param f_additer
caption = "Add the smooth iteration count"
default = false
endparam
Transfer param f_itertransfer
caption = "Iteration Transfer"
default = MMF_TrapTransfer
hint = "Allows you to manipulate the final combined value of \
the trap colour and the texturing."
visible = @f_additer
endparam
}
class MMF_TrapTransformZold(common.ulb:UserTransform) {
; Base class for trap transforms requiring zold and/or zolder
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TrapTransformZold(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
; Initialise m_zolder, m_zold, m_zolderok and m_zoldok
; @param pz the z value
func Init(complex pz)
UserTransform.Init(pz)
m_zolder = m_zold = pz
m_zolderok = m_zoldok = false
endfunc
;
; @param pz the z value
; @return new z
complex func Iterate(complex pz)
m_Iterations = m_Iterations + 1
return pz
endfunc
; Here the "old" flags are set to false
func IterateSilent()
m_Iterations = m_Iterations + 1
m_zolderok = m_zoldok = false
endfunc
;
; @param pz the z value
func IterateSilentZold(complex pz)
m_Iterations = m_Iterations + 1
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
endfunc
protected:
complex m_zold
complex m_zolder
bool m_zoldok
bool m_zolderok
default:
int param v_mmftraptransformzold
caption = "Version (MMF_TrapTransformZold)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmftraptransformzold < 100
endparam
heading
text = "This transform is designed for use with formulas that \
understand the use of zold and zolder such as MMF Smooth \
Orbit Traps from mmf.ulb or similar formulas but will \
work with reduced functionality in other situations."
endheading
}
class MMF_TrapTransformInterpolation(MMF_TrapTransformZold) {
; Trapping based on interpolation of a*zold^p1 + b*zold^p2
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TrapTransformInterpolation(Generic pparent)
MMF_TrapTransformZold.MMF_TrapTransformZold(pparent)
endfunc
; Sets the m_gotold variable to false i.e. "no old trapped values"
; @param pz the initial z value
func Init(complex pz)
MMF_TrapTransformZold.Init(pz)
m_gotold = false
endfunc
; @param pz the z value
complex func Iterate(complex pz)
complex zt = (0,0)
complex a = (0,0)
complex b = (0,0)
bool gotz = false
; m_Iterations = m_Iterations + 1 not used in this transform
if (@usevar=="Predict1" || @usevar=="Predict2") \
&& m_gotold && m_zoldok
if @usevar=="Predict1"
zt = m_oa*m_zold^@pwr1 + m_ob*m_zold^@pwr2
else
zt = m_oa*m_zold^@pwr1 + @valb*m_zold^@pwr2
endif
gotz = true
endif
m_gotold = false
if @usevar=="Just a" || @usevar=="Just b" || @usevar=="Combined" \
|| @usevar=="Predict1"
if m_zolderok
if @pwr1!=(0,0)
if @pwr2!=(0,0)
a = m_zold^@pwr1*m_zolder^@pwr2 - m_zolder^@pwr1*m_zold^@pwr2
else
a = m_zold^@pwr1 - m_zolder^@pwr1
endif
elseif @pwr2!=(0,0)
a = m_zolder^@pwr2 - m_zold^@pwr2
endif
m_gotold = true
endif
elseif m_zoldok
if @pwr1!=(0,0)
a = m_zold^@pwr1
else
a = 1.0
endif
m_gotold = true
endif
if m_gotold
if @usevar=="Just a" || @usevar=="Just b" || @usevar=="Combined" \
|| @usevar=="Predict1"
a = 1.0/a
if @pwr1!=(0,0)
if @pwr2!=(0,0)
if @usevar!="Just a"
b = (m_zold^(@pwr1+1.0) - pz*m_zolder^@pwr1)*a
endif
if @usevar!="Just b"
a = (pz*m_zolder^@pwr2 - m_zold^(@pwr2+1.0))*a
endif
else
if @usevar!="Just a"
b = (m_zold^(@pwr1+1.0) - pz*m_zolder^@pwr1)*a
endif
if @usevar!="Just b"
a = (pz - m_zold)*a
endif
endif
elseif @pwr2!=(0,0)
if @usevar!="Just a"
b = (m_zold - pz)*a
endif
if @usevar!="Just b"
a = (pz*m_zolder^@pwr2 - m_zold^(@pwr2+1.0))*a
endif
endif
elseif @pwr2!=(0,0)
a = (pz - @valb*m_zold^@pwr2)/a
else
a = (pz - @valb)/a
endif
if @usevar=="Predict1" || @usevar=="Predict2"
m_oa = a
m_ob = b
endif
endif
if ((@usevar=="Just a" || @usevar=="Just b" || @usevar=="Combined" \
|| @usevar=="Fixed b") && m_gotold) || ((@usevar=="Predict1" \
|| @usevar=="Predict2") && gotz)
if @usevar=="Predict1" || @usevar=="Predict2"
a = zt
if @trapz
a = pz - zt
endif
endif
if @usevar!="Just b"
if @fna==1
a = log(a)
elseif @fna==2
a = sin(a)
elseif @fna==3
a = cos(a)
elseif @fna==4
a = tan(a)
elseif @fna==5
a = sinh(a)
elseif @fna==6
a = cosh(a)
elseif @fna==7
a = tanh(a)
elseif @fna==8
a = exp(a)
elseif @fna==9
a = sqrt(a)
elseif @fna==10
a = a^(1.0/3.0)
elseif @fna==11
a = a*a
elseif @fna==12
a = a^3.0
endif
endif
if @usevar=="Just b" || @usevar=="Combined"
if @fnb==1
b = log(b)
elseif @fnb==2
b = sin(b)
elseif @fnb==3
b = cos(b)
elseif @fnb==4
b = tan(b)
elseif @fnb==5
b = sinh(b)
elseif @fnb==6
b = cosh(b)
elseif @fnb==7
b = tanh(b)
elseif @fnb==8
b = exp(b)
elseif @fnb==9
b = sqrt(b)
elseif @fnb==10
b = b^(1.0/3.0)
elseif @fnb==11
b = b*b
elseif @fnb==12
b = b^3.0
endif
endif
if @usevar=="Just b"
zt = b
elseif @usevar=="Combined"
if @mix=="Minimum"
if |a|<=|b|
zt = a
else
zt = b
endif
elseif @mix=="Maximum"
if |a|>|b|
zt = a
else
zt = b
endif
else;if @mix=="Mix %age"
zt = (0.01*@percent)*a + (1.0 - 0.01*@percent)*b
endif
else
zt = a
endif
m_solid = false
else
zt = pz
m_solid = true
endif
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
return zt
endfunc
; Set the "old" flags to false
func IterateSilent()
; m_Iterations = m_Iterations + 1 not used in this transform
m_zolderok = m_zoldok = m_gotold = false
endfunc
; Keep the "old" z values up to date, set the m_gotold flag to false
; @param pz the z value
func IterateSilentZold(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
m_gotold = false
endfunc
private:
complex m_oa
complex m_ob
bool m_gotold
default:
title = "Interpolation Transform"
heading
text = "The interpolation requires that the transform is used \
in an iterated manner, so in situations where the \
transform is applied in a 'one-shot' manner interpolation \
is not applicable."
endheading
complex param pwr1
caption = "Power 1"
default = (2,0)
hint = "n1 in 'a*z^n1 + b*z^n2'. Note that if it is (0,0) then the \
interpolation formula becomes 'a + b*z^n2'."
endparam
complex param pwr2
caption = "Power 2"
default = (1,0)
hint = "n2 in 'a*z^n1 + b*z^n2'. Note that if it is (0,0) then the \
interpolation formula becomes 'a*z^n1 + b'."
endparam
int param usevar
caption = "Variable/s to use"
enum = "Just a" "Just b" "Combined" "Fixed b" "Predict1" "Predict2"
default = 0
hint = " \
'Combined' calculates values using a and b separately and then \
allows you to set the final value by combining the two \
separate values. 'Fixed b' allows you to specify a fixed value \
for b in a*z^n1 + b*z^n2 and colours based on a. \
Predict1 calculates both a and b and uses the values from \
the previous iteration to interpolate z and traps the \
interpolated value. Predict2 is the same \
as Predict1 but uses the 'Fixed b' interpolation method."
endparam
bool param trapz
caption = "Trap z ?"
default = false
hint = "Normally just the interpolated value is used for \
'Predict1' and 'Predict2' but you can choose to trap \
the actual z value to the predicted z value instead."
visible = @usevar>3
endparam
complex param valb
caption = "Value of b"
default = (0,0)
visible = @usevar==3 || @usevar==5
endparam
int param mix
caption = "Colour mixing"
enum = "Minimum" "Maximum" "Mix %age"
default = 0
visible = @usevar==2
endparam
float param percent
caption = "Mix %age"
default = 50.0
hint = "100% uses the value from a only, 0% uses the value from b only."
visible = @usevar==2 && @mix==2
endparam
int param fna
caption = "Function for a (or interpolated z)"
enum = "Ident" "Log" "Sin" "Cos" "Tan" "Sinh" "Cosh" "Tanh" "Exp" \
"Sqrt" "Cubert" "Square" "Cube"
default = 0
hint = "Applied to the calculated value of a or the interpolated \
z value before use in any trapping or colouring."
visible = @usevar!=1
endparam
int param fnb
caption = "Function for b"
enum = "Ident" "Log" "Sin" "Cos" "Tan" "Sinh" "Cosh" "Tanh" "Exp" \
"Sqrt" "Cubert" "Square" "Cube"
default = 0
hint = "Applied to the calculated value of b before use in any \
trapping or colouring."
visible = @usevar>0 && @usevar<3
endparam
}
class MMF_TrapModeSmooth(common.ulb:TrapMode) {
;
; This is a generic trap mode class for use with MMF_SmoothOrbitTraps.
;
;
public:
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TrapModeSmooth(Generic pparent)
TrapMode.TrapMode(pparent)
endfunc
; call this at the beginning of each sequence
; @param pz the initial z value
func Init(complex pz)
m_Iterations = 0
m_Solid = false
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (0,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (0,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 0.0
m_Textures[j] = m_OldTextures[j] = 0.0
until (j=j-1)<0
m_wastrapped = false
endfunc
; call this for each point
;
; @param pz the z value
; @param pzt the transformed z value
; @param pdistance the trap distance
; @param ptexture tyhe texture value
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
if m_wastrapped
m_OldDistances[0] = m_Distances[0]
m_OldTextures[0] = m_Textures[0]
m_OldUntransformedPoints[0] = m_UntransformedPoints[0]
m_OldTransformedPoints[0] = m_TransformedPoints[0]
m_OldIterationPoints[0] = m_IterationPoints[0]
endif
m_Iterations = m_Iterations + 1
endfunc
; call this for each point that is ignored (for smooth orbit traps)
; if the last point was trapped then copy the current values into
; the "old" ones
func IterateSilent()
if m_wastrapped
m_OldDistances[0] = m_Distances[0]
m_OldTextures[0] = m_Textures[0]
m_OldUntransformedPoints[0] = m_UntransformedPoints[0]
m_OldTransformedPoints[0] = m_TransformedPoints[0]
m_OldIterationPoints[0] = m_IterationPoints[0]
m_wastrapped = false
endif
m_Iterations = m_Iterations + 1
endfunc
; call this to compute final results
; func Result()
; endfunc
; call this to compute penultimate results
;
func OldResult()
; Note that in some cases if less than two values were trapped this
; should be skipped i.e. old result should be the same as result
m_Distances[0] = m_OldDistances[0]
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endfunc
protected:
complex m_OldUntransformedPoints[4]
complex m_OldTransformedPoints[4]
float m_OldIterationPoints[4]
float m_OldDistances[4]
float m_OldTextures[4]
bool m_wastrapped
default:
int param v_mmf_trapmodesmooth
caption = "Version (MMF_TrapModeSmooth)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmf_trapmodesmooth < 100
endparam
}
class MMF_TrapModeSmoothWithThreshold(common.ulb:TrapModeWithThreshold) {
;
; Essentially a variant of TrapModeSmooth that is thresholdable
;
public:
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TrapModeSmoothWithThreshold(Generic pparent)
TrapModeWithThreshold.TrapModeWithThreshold(pparent)
endfunc
; call this at the beginning of each sequence
; @param pz the initial z value
func Init(complex pz)
m_Iterations = 0
m_Solid = false
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (0,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (0,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 0.0
m_Textures[j] = m_OldTextures[j] = 0.0
until (j=j-1)<0
m_wastrapped = false
endfunc
; call this for each point
;
; @param pz the z value
; @param pzt the transformed z value
; @param pdistance the trap distance
; @param ptexture tyhe texture value
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
if m_wastrapped
m_OldDistances[0] = m_Distances[0]
m_OldTextures[0] = m_Textures[0]
m_OldUntransformedPoints[0] = m_UntransformedPoints[0]
m_OldTransformedPoints[0] = m_TransformedPoints[0]
m_OldIterationPoints[0] = m_IterationPoints[0]
endif
m_Iterations = m_Iterations + 1
endfunc
; call this for each point that is ignored (for smooth orbit traps)
; if the last point was trapped then copy the current values into
; the "old" ones
func IterateSilent()
if m_wastrapped
m_OldDistances[0] = m_Distances[0]
m_OldTextures[0] = m_Textures[0]
m_OldUntransformedPoints[0] = m_UntransformedPoints[0]
m_OldTransformedPoints[0] = m_TransformedPoints[0]
m_OldIterationPoints[0] = m_IterationPoints[0]
m_wastrapped = false
endif
m_Iterations = m_Iterations + 1
endfunc
; call this to compute penultimate results
func OldResult()
; Note that in some cases if less than two values were trapped this
; should be skipped i.e. old result should be the same as result
m_Distances[0] = m_OldDistances[0]
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endfunc
protected:
complex m_OldUntransformedPoints[4]
complex m_OldTransformedPoints[4]
float m_OldIterationPoints[4]
float m_OldDistances[4]
float m_OldTextures[4]
bool m_wastrapped
default:
int param v_mmf_trapmodesmoothwiththreshold
caption = "Version (MMF_TrapModeSmoothWithThreshold)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmf_trapmodesmoothwiththreshold < 100
endparam
}
class MMF_TrapModeSmoothSum(MMF_TrapModeSmoothWithThreshold) {
; Sums the trapped values within the threshold.
public:
import "common.ulb"
func MMF_TrapModeSmoothSum(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
if (pdistance < m_Threshold)
m_Distances[0] = m_Distances[0] + pdistance
m_Textures[0] = m_Textures[0] + ptexture
m_UntransformedPoints[0] = m_UntransformedPoints[0] + pz
m_TransformedPoints[0] = m_TransformedPoints[0] + pzt
m_IterationPoints[0] = m_IterationPoints[0] + m_Iterations
m_Solid = false
m_wastrapped = true
endif
endfunc
default:
title = "Smooth Sum"
rating = recommended
heading
caption = "Information"
text = "Note that when using Trap Color Mode Iteration this differs \
slightly from normal 'Sum' by giving the sum of the iteration \
counts when values were trapped rather than the trap count. \
To colour by the trap counts just use say 'Smooth Average' \
instead."
endheading
}
class MMF_TrapModeSmoothAverage(MMF_TrapModeSmoothWithThreshold) {
; Sums the trapped values within the threshold and converts the
; results to averages.
public:
import "common.ulb"
func MMF_TrapModeSmoothAverage(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
if (pdistance < m_Threshold)
m_Distances[0] = m_Distances[0] + pdistance
m_Textures[0] = m_Textures[0] + ptexture
m_UntransformedPoints[0] = m_UntransformedPoints[0] + pz
m_TransformedPoints[0] = m_TransformedPoints[0] + pzt
m_IterationPoints[0] = m_IterationPoints[0] + 1
m_Solid = false
m_wastrapped = true
endif
endfunc
func Result()
float ii = 1.0 / m_IterationPoints[0]
m_Distances[0] = m_Distances[0] * ii
m_Textures[0] = m_Textures[0] * ii
m_UntransformedPoints[0] = m_UntransformedPoints[0] * ii
m_TransformedPoints[0] = m_TransformedPoints[0] * ii
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
float ii = 1.0 / m_OldIterationPoints[0]
m_Distances[0] = m_OldDistances[0] * ii
m_Textures[0] = m_OldTextures[0] * ii
m_UntransformedPoints[0] = m_OldUntransformedPoints[0] * ii
m_TransformedPoints[0] = m_OldTransformedPoints[0] * ii
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Average"
rating = recommended
}
class MMF_TrapModeSmoothLast(MMF_TrapModeSmoothWithThreshold) {
; Returns the values from the last trapped iteration within
; the threshold.
public:
import "common.ulb"
func MMF_TrapModeSmoothLast(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
if pdistance < m_Threshold
m_Distances[0] = pdistance
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_Textures[0] = ptexture
m_Solid = false
m_wastrapped = true
endif
endfunc
default:
title = "Smooth Last"
rating = recommended
}
class MMF_TrapModeSmoothClosest(MMF_TrapModeSmoothWithThreshold) {
; Returns trapped values from when the distance was a minimum.
public:
import "common.ulb"
func MMF_TrapModeSmoothClosest(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
m_Iterations = 0
m_Solid = true
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (0,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (0,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 1e20
m_Textures[j] = m_OldTextures[j] = 0.0
until (j=j-1)<0
m_wastrapped = false
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
if (pdistance < m_Threshold)
m_Solid = false
endif
if (pdistance < m_Distances[0])
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_wastrapped = true
endif
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
m_Distances[0] = m_OldDistances[0]
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Closest"
rating = recommended
}
class MMF_TrapModeSmoothSecondClosest(MMF_TrapModeSmoothWithThreshold) {
; Returns the differences between the closest and second closest trapped
; iterations.
public:
import "common.ulb"
func MMF_TrapModeSmoothSecondClosest(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
m_Iterations = 0
m_Solid = true
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (0,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (0,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 1e20
m_Textures[j] = m_OldTextures[j] = 0.0
until (j=j-1)<0
m_wastrapped = false
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
if m_wastrapped
m_OldDistances[0] = m_Distances[0]
m_OldTextures[0] = m_Textures[0]
m_OldUntransformedPoints[0] = m_UntransformedPoints[0]
m_OldTransformedPoints[0] = m_TransformedPoints[0]
m_OldIterationPoints[0] = m_IterationPoints[0]
m_OldDistances[1] = m_Distances[1]
m_OldTextures[1] = m_Textures[1]
m_OldUntransformedPoints[1] = m_UntransformedPoints[1]
m_OldTransformedPoints[1] = m_TransformedPoints[1]
m_OldIterationPoints[1] = m_IterationPoints[1]
endif
m_Iterations = m_Iterations + 1
if (pdistance < m_Threshold)
m_Solid = false
endif
if pdistance < m_Distances[0]
m_Distances[1] = m_Distances[0]
m_Textures[1] = m_Textures[0]
m_UntransformedPoints[1] = m_UntransformedPoints[0]
m_TransformedPoints[1] = m_TransformedPoints[0]
m_IterationPoints[1] = m_IterationPoints[0]
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_wastrapped = true
elseif pdistance
public:
import "common.ulb"
func MMF_TrapModeSmoothFarthest(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
if (pdistance < m_Threshold && pdistance >= m_Distances[0])
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_Solid = false
m_wastrapped = true
endif
endfunc
default:
title = "Smooth Farthest"
rating = recommended
}
class MMF_TrapModeSmoothSecondFarthest(MMF_TrapModeSmoothWithThreshold) {
; Returns the difference in the values from the farthest trapped
; iteration within the threshold and the second farthest.
public:
import "common.ulb"
func MMF_TrapModeSmoothSecondFarthest(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
if m_wastrapped
m_OldDistances[0] = m_Distances[0]
m_OldTextures[0] = m_Textures[0]
m_OldUntransformedPoints[0] = m_UntransformedPoints[0]
m_OldTransformedPoints[0] = m_TransformedPoints[0]
m_OldIterationPoints[0] = m_IterationPoints[0]
m_OldDistances[1] = m_Distances[1]
m_OldTextures[1] = m_Textures[1]
m_OldUntransformedPoints[1] = m_UntransformedPoints[1]
m_OldTransformedPoints[1] = m_TransformedPoints[1]
m_OldIterationPoints[1] = m_IterationPoints[1]
endif
m_Iterations = m_Iterations + 1
if pdistance >= m_Distances[0] && pdistance < m_Threshold
m_Distances[1] = m_Distances[0]
m_Textures[1] = m_Textures[0]
m_UntransformedPoints[1] = m_UntransformedPoints[0]
m_TransformedPoints[1] = m_TransformedPoints[0]
m_IterationPoints[1] = m_IterationPoints[0]
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_wastrapped = true
m_Solid = false
elseif pdistance>=m_Distances[1] && pdistance < m_Threshold
m_Distances[1] = pdistance
m_Textures[1] = ptexture
m_UntransformedPoints[1] = pz
m_TransformedPoints[1] = pzt
m_IterationPoints[1] = m_Iterations
m_wastrapped = true
m_Solid = false
endif
endfunc
func IterateSilent()
if m_wastrapped
m_OldDistances[0] = m_Distances[0]
m_OldTextures[0] = m_Textures[0]
m_OldUntransformedPoints[0] = m_UntransformedPoints[0]
m_OldTransformedPoints[0] = m_TransformedPoints[0]
m_OldIterationPoints[0] = m_IterationPoints[0]
m_OldDistances[1] = m_Distances[1]
m_OldTextures[1] = m_Textures[1]
m_OldUntransformedPoints[1] = m_UntransformedPoints[1]
m_OldTransformedPoints[1] = m_TransformedPoints[1]
m_OldIterationPoints[1] = m_IterationPoints[1]
m_wastrapped = false
endif
m_Iterations = m_Iterations + 1
endfunc
func Result()
m_Distances[0] = abs(m_Distances[0] - m_Distances[1])
m_Textures[0] = m_Textures[0] - m_Textures[1]
m_UntransformedPoints[0] = m_UntransformedPoints[0] \
- m_UntransformedPoints[1]
m_TransformedPoints[0] = m_TransformedPoints[0] \
- m_TransformedPoints[1]
m_IterationPoints[0] = abs(m_IterationPoints[0] \
- m_IterationPoints[1])
endfunc
func OldResult()
if m_OldIterationPoints[1]>0
m_Distances[0] = abs(m_OldDistances[0] - m_OldDistances[1])
m_Textures[0] = m_OldTextures[0] - m_OldTextures[1]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0] \
- m_OldUntransformedPoints[1]
m_TransformedPoints[0] = m_OldTransformedPoints[0] \
- m_OldTransformedPoints[1]
m_IterationPoints[0] = abs(m_OldIterationPoints[0] \
- m_OldIterationPoints[1])
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Second Farthest"
rating = recommended
}
class MMF_TrapModeSmoothTwoFarthest(MMF_TrapModeSmoothSecondFarthest) {
; Returns the averages of the values from the trapped iteration with the
; farthest distance within the threshold and the second farthest.
public:
import "common.ulb"
func MMF_TrapModeSmoothTwoFarthest(Generic pparent)
MMF_TrapModeSmoothSecondFarthest.MMF_TrapModeSmoothSecondFarthest(pparent)
endfunc
func Result()
m_Distances[0] = 0.5*(m_Distances[0] + m_Distances[1])
m_Textures[0] = 0.5*(m_Textures[0] + m_Textures[1])
m_UntransformedPoints[0] = 0.5*(m_UntransformedPoints[0] \
+ m_UntransformedPoints[1])
m_TransformedPoints[0] = 0.5*(m_TransformedPoints[0] \
+ m_TransformedPoints[1])
m_IterationPoints[0] = round(0.5*(m_IterationPoints[0] \
+ m_IterationPoints[1]))
endfunc
func OldResult()
if m_OldIterationPoints[1]>0
m_Distances[0] = 0.5*(m_OldDistances[0] + m_OldDistances[1])
m_Textures[0] = 0.5*(m_OldTextures[0] + m_OldTextures[1])
m_UntransformedPoints[0] = 0.5*(m_OldUntransformedPoints[0] \
+ m_OldUntransformedPoints[1])
m_TransformedPoints[0] = 0.5*(m_OldTransformedPoints[0] \
+ m_OldTransformedPoints[1])
m_IterationPoints[0] = round(0.5*(m_OldIterationPoints[0] \
+ m_OldIterationPoints[1]))
endif
endfunc
default:
title = "Smooth Two Farthest"
}
class MMF_TrapModeSmoothChangeAverage(MMF_TrapModeSmooth) {
; Total differences in distance within threshold.
public:
import "common.ulb"
func MMF_TrapModeSmoothChangeAverage(Generic pparent)
MMF_TrapModeSmooth.MMF_TrapModeSmooth(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmooth.Init(pz)
m_Solid = true
m_PreviousDistance = 0.0
m_PreviousTexture = 0.0
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmooth.Iterate(pz, pzt, pdistance, ptexture)
if (pdistance < m_PreviousDistance)
m_Distances[0] = m_Distances[0] + m_PreviousDistance-pdistance
m_Textures[0] = m_Textures[0] + m_PreviousTexture-ptexture
m_UntransformedPoints[0] = m_UntransformedPoints[0] + pz
m_TransformedPoints[0] = m_TransformedPoints[0] + pzt
m_IterationPoints[0] = m_IterationPoints[0] + 1
m_Solid = false
m_wastrapped = true
endif
m_PreviousDistance = pdistance
m_PreviousTexture = ptexture
endfunc
protected:
float m_PreviousDistance
float m_PreviousTexture
default:
title = "Smooth Change Average"
}
class MMF_TrapModeSmoothNth(MMF_TrapModeSmoothWithThreshold) {
; This trap mode traps to the nth trapped point that is within the
; threshold.
public:
import "common.ulb"
func MMF_TrapModeSmoothNth(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
m_count = @p_count
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
if (pdistance < m_Threshold && m_count>0)
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_Solid = false
m_wastrapped = true
m_count = m_count - 1
endif
endfunc
private:
int m_count
default:
title = "Smooth First N"
rating = recommended
int param p_count
caption = "Trap Count, N"
default = 1
min = 1
hint = "The algorithm will stop trapping after trapping this many \
values. Colouring will be from the last values trapped \
even if less than this many traps occurred."
endparam
}
class MMF_TrapModeSmoothTurningPoints(MMF_TrapModeSmoothWithThreshold) {
; Traps the values occurring when the distance found hits maxima
; and/or minima.
bool func IsSolid()
return m_trapmode.IsSolid()
endfunc
; get a final untransformed point
complex func GetUntransformedPoint(int pindex)
return m_trapmode.GetUntransformedPoint(pindex)
endfunc
; get a final transformed point
complex func GetTransformedPoint(int pindex)
return m_trapmode.GetTransformedPoint(pindex)
endfunc
; get a final distance
float func GetDistance(int pindex)
return m_trapmode.GetDistance(pindex)
endfunc
; get a final texture
float func GetTexture(int pindex)
return m_trapmode.GetTexture(pindex)
endfunc
; get a final iteration
float func GetIteration(int pindex)
return m_trapmode.GetIteration(pindex)
endfunc
; get threshold value
float func GetThreshold()
return m_trapmode.GetThreshold()
endfunc
; set threshold value
func SetThreshold(float pthreshold)
m_trapmode.SetThreshold(pthreshold)
endfunc
; get whether threshold is even used
bool func UsesThreshold()
return m_trapmode.UsesThreshold()
endfunc
private:
TrapMode m_trapmode
complex m_pzold
complex m_pztold
float m_pdold
float m_ptold
float m_olddist
float m_oldv
int m_dir
default:
title = "Smooth Turning Points"
rating = recommended
int param p_version
caption = "Version"
enum = "Original" "Fixed"
default = 0
hint = "In the original version the values to be trapped are those \
from the iteration after the maxima or minima actually \
occurred. In the fixed version the algorithm is corrected \
so the values from when the maxima or minima occurred are \
trapped. Note that when iteration skipping is used the \
'Fixed' option will only work properly if it is plugged \
into compatible formulas such as mmf.ulb Smooth Orbit Traps."
endparam
int param p_trap
caption = "Turning Points to Trap"
enum = "All" "Maxima" "Minima"
default = 0
hint = "You can choose to trap all turning points, or just minima, or \
just maxima."
endparam
int param p_mode
caption = "Values to use"
enum = "Distances" "Differences"
default = 0
hint = "When using distances the turning points in the distances \
are trapped. When using differences the turning points in \
the changes to the distances are trapped."
endparam
TrapMode param p_trapmode
caption = "Trap Mode for the Turning Points"
default = MMF_TrapModeSmoothAverage
hint = "If using mmf.ulb Smooth Orbit Traps then it's best to choose \
a 'Smooth' trap mode for example from mmf.ulb, obviously don't \
choose 'Smooth Turning Points' here."
endparam
}
class MMF_TrapModeSmoothProduct(MMF_TrapModeSmoothWithThreshold) {
;
; Note that this implimentation is slightly different to normal
; TrapModeProduct in that IterationPoints is kept as a trap counter
; and TransformedPoints and UntransformedPoints are initialised to
; 1 and multiplied by (1 + pz/cabs(pz)) and (1 + pzt/cabs(pzt))
; respectively.
;
public:
import "common.ulb"
func MMF_TrapModeSmoothProduct(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
m_Iterations = 0
m_Solid = true
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (1,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (1,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 1.0
m_Textures[j] = m_OldTextures[j] = 1.0
until (j=j-1)<0
m_wastrapped = false
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
if (pdistance < m_Threshold)
float id = 1.0 / m_Threshold
m_Distances[0] = m_Distances[0] * (pdistance + @adjust) * id
m_Textures[0] = m_Textures[0] * ptexture * id
m_UntransformedPoints[0] = m_UntransformedPoints[0] \
* (1.0 + pz / cabs(pz))
m_TransformedPoints[0] = m_TransformedPoints[0] \
* (1.0 + pzt / cabs(pzt))
m_IterationPoints[0] = m_IterationPoints[0] + 1
m_Solid = false
m_wastrapped = true
endif
endfunc
func Result()
m_Distances[0] = abs(m_Distances[0])
; Note that texture is not forced to positive here.
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
m_Distances[0] = abs(m_OldDistances[0])
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
; Note that texture is not forced to positive here.
endif
endfunc
default:
title = "Smooth Product"
heading
text = "Note that this implimentation is slightly different to \
normal Trap Mode Product in that the Iteration value is \
kept as a trap counter and TransformedPoints and \
UntransformedPoints will actually produce values when \
using an appropriate Trap Color Mode such as Magnitude, \
Real or Imaginary etc."
endheading
float param adjust
caption = "Offset Distance"
default = 0.0
hint = "Modifies the distances found by this value before \
multiplying. Try non-zero values if you get little \
or no colouring variation, note that often increases \
in the Trap Threshold will require increases in this \
value and vice-versa."
endparam
}
class MMF_TrapModeSmoothProductDist(MMF_TrapModeSmoothWithThreshold) {
;
; Note that this implimentation is slightly different to normal
; TrapModeProduct in that IterationPoints is kept as a trap counter
; and TransformedPoints and UntransformedPoints are initialised to
; 1 and multiplied by (1 + pz/cabs(pz)) and (1 + pzt/cabs(pzt))
; respectively.
;
public:
import "common.ulb"
func MMF_TrapModeSmoothProductDist(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
m_Iterations = 0
m_Solid = true
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (1,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (1,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 1.0
m_Textures[j] = m_OldTextures[j] = 1.0
until (j=j-1)<0
m_wastrapped = false
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = abs(pdistance - @p_testdist)
if (pdistance < m_Threshold)
float id = 1.0 / m_Threshold
m_Distances[0] = m_Distances[0] * (pdistance + @adjust) * id
m_Textures[0] = m_Textures[0] * ptexture * id
m_UntransformedPoints[0] = m_UntransformedPoints[0] \
* (1.0 + pz / cabs(pz))
m_TransformedPoints[0] = m_TransformedPoints[0] \
* (1.0 + pzt / cabs(pzt))
m_IterationPoints[0] = m_IterationPoints[0] + 1
m_Solid = false
m_wastrapped = true
endif
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
m_Distances[0] = m_OldDistances[0]
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Product (from Test Distance)"
heading
text = "Note that this implimentation is slightly different to \
normal Trap Mode Product in that the Iteration value is \
kept as a trap counter and TransformedPoints and \
UntransformedPoints will actually produce values when \
using an appropriate Trap Color Mode such as Magnitude, \
Real or Imaginary etc."
endheading
float param adjust
caption = "Offset Distance"
default = 0.0
hint = "Modifies the distances found by this value before \
multiplying. Try non-zero values if you get little \
or no colouring variation, note that often increases \
in the Trap Threshold will require increases in this \
value and vice-versa."
endparam
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Multiplies the results of distances from this distance \
from the trap."
endparam
}
class MMF_TrapModeSmoothProductAbove(MMF_TrapModeSmoothWithThreshold) {
;
; Note that this implimentation is slightly different to normal
; TrapModeProduct in that IterationPoints is kept as a trap counter
; and TransformedPoints and UntransformedPoints are initialised to
; 1 and multiplied by (1 + pz/cabs(pz)) and (1 + pzt/cabs(pzt))
; respectively.
;
public:
import "common.ulb"
func MMF_TrapModeSmoothProductAbove(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
m_Iterations = 0
m_Solid = true
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (1,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (1,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 1.0
m_Textures[j] = m_OldTextures[j] = 1.0
until (j=j-1)<0
m_wastrapped = false
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = pdistance - @p_testdist
if pdistance>=0 && pdistance < m_Threshold
float id = 1.0 / m_Threshold
m_Distances[0] = m_Distances[0] * (pdistance + @adjust) * id
m_Textures[0] = m_Textures[0] * ptexture * id
m_UntransformedPoints[0] = m_UntransformedPoints[0] \
* (1.0 + pz / cabs(pz))
m_TransformedPoints[0] = m_TransformedPoints[0] \
* (1.0 + pzt / cabs(pzt))
m_IterationPoints[0] = m_IterationPoints[0] + 1
m_Solid = false
m_wastrapped = true
endif
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
m_Distances[0] = m_OldDistances[0]
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Product Above"
heading
text = "Note that this implimentation is slightly different to \
normal Trap Mode Product in that the Iteration value is \
kept as a trap counter and TransformedPoints and \
UntransformedPoints will actually produce values when \
using an appropriate Trap Color Mode such as Magnitude, \
Real or Imaginary etc."
endheading
float param adjust
caption = "Offset Distance"
default = 0.0
hint = "Modifies the distances found by this value before \
multiplying. Try non-zero values if you get little \
or no colouring variation, note that often increases \
in the Trap Threshold will require increases in this \
value and vice-versa."
endparam
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Multiplies the results of distances from this distance \
from the trap."
endparam
}
class MMF_TrapModeSmoothProductBelow(MMF_TrapModeSmoothWithThreshold) {
;
; Note that this implimentation is slightly different to normal
; TrapModeProduct in that IterationPoints is kept as a trap counter
; and TransformedPoints and UntransformedPoints are initialised to
; 1 and multiplied by (1 + pz/cabs(pz)) and (1 + pzt/cabs(pzt))
; respectively.
;
public:
import "common.ulb"
func MMF_TrapModeSmoothProductBelow(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
m_Iterations = 0
m_Solid = true
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (1,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (1,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 1.0
m_Textures[j] = m_OldTextures[j] = 1.0
until (j=j-1)<0
m_wastrapped = false
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = @p_testdist - pdistance
if pdistance>=0 && pdistance < m_Threshold
float id = 1.0 / m_Threshold
m_Distances[0] = m_Distances[0] * (pdistance + @adjust) * id
m_Textures[0] = m_Textures[0] * ptexture * id
m_UntransformedPoints[0] = m_UntransformedPoints[0] \
* (1.0 + pz / cabs(pz))
m_TransformedPoints[0] = m_TransformedPoints[0] \
* (1.0 + pzt / cabs(pzt))
m_IterationPoints[0] = m_IterationPoints[0] + 1
m_Solid = false
m_wastrapped = true
endif
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
m_Distances[0] = m_OldDistances[0]
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Product Below"
heading
text = "Note that this implimentation is slightly different to \
normal Trap Mode Product in that the Iteration value is \
kept as a trap counter and TransformedPoints and \
UntransformedPoints will actually produce values when \
using an appropriate Trap Color Mode such as Magnitude, \
Real or Imaginary etc."
endheading
float param adjust
caption = "Offset Distance"
default = 0.0
hint = "Modifies the distances found by this value before \
multiplying. Try non-zero values if you get little \
or no colouring variation, note that often increases \
in the Trap Threshold will require increases in this \
value and vice-versa."
endparam
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Multiplies the results of distances from this distance \
from the trap."
endparam
}
class MMF_TrapModeSmoothNearest(MMF_TrapModeSmoothWithThreshold) {
; Returns values from the trapped iteration where the distance is nearest
; to the user value and within the threshold of it.
public:
import "common.ulb"
func MMF_TrapModeSmoothNearest(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
m_Iterations = 0
m_Solid = true
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (0,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (0,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 1e20
m_Textures[j] = m_OldTextures[j] = 0.0
until (j=j-1)<0
m_wastrapped = false
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = abs(pdistance - @p_testdist)
if (pdistance < m_Threshold)
m_Solid = false
endif
if (pdistance < m_Distances[0])
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_wastrapped = true
endif
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
m_Distances[0] = m_OldDistances[0]
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Nearest"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Traps the result nearest this distance from the trap."
endparam
}
class MMF_TrapModeSmoothFarthestDist(MMF_TrapModeSmoothWithThreshold) {
; Returns values from the trapped iteration where the distance is farthest
; from the user value and within the threshold of it.
public:
import "common.ulb"
func MMF_TrapModeSmoothFarthestDist(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = abs(pdistance - @p_testdist)
if (pdistance < m_Threshold && pdistance >= m_Distances[0])
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_Solid = false
m_wastrapped = true
endif
endfunc
default:
title = "Smooth Farthest (from Test Distance)"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Traps the result farthest from this distance from the trap \
provided the distance from this distance is within the \
threshold."
endparam
}
class MMF_TrapModeSmoothNearestBelow(MMF_TrapModeSmoothWithThreshold) {
; Returns values from the trapped iteration with the nearest distance
; less than or equal to the user value and within the threshold of it.
public:
import "common.ulb"
func MMF_TrapModeSmoothNearestBelow(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
m_Iterations = 0
m_Solid = true
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (0,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (0,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 1e20
m_Textures[j] = m_OldTextures[j] = 0.0
until (j=j-1)<0
m_wastrapped = false
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
if (pdistance = @p_testdist - pdistance)>=0
if (pdistance < m_Threshold)
m_Solid = false
endif
if (pdistance < m_Distances[0])
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_wastrapped = true
endif
endif
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
m_Distances[0] = m_OldDistances[0]
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Nearest Below"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Traps the result nearest this distance from the trap but only \
if it's less than this distance from the trap."
endparam
}
class MMF_TrapModeSmoothNearestAbove(MMF_TrapModeSmoothWithThreshold) {
; Returns values from the trapped iteration with the nearest distance
; greater than or equal to the user value and within the threshold of it.
public:
import "common.ulb"
func MMF_TrapModeSmoothNearestAbove(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
m_Iterations = 0
m_Solid = true
int j = 3
repeat
m_UntransformedPoints[j] = m_OldUntransformedPoints[j] = (0,0)
m_TransformedPoints[j] = m_OldTransformedPoints[j] = (0,0)
m_IterationPoints[j] = m_OldIterationPoints[j] = 0
m_Distances[j] = m_OldDistances[j] = 1e20
m_Textures[j] = m_OldTextures[j] = 0.0
until (j=j-1)<0
m_wastrapped = false
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
if (pdistance = pdistance - @p_testdist)>=0
if (pdistance < m_Threshold)
m_Solid = false
endif
if (pdistance < m_Distances[0])
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_wastrapped = true
endif
endif
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
m_Distances[0] = m_OldDistances[0]
m_Textures[0] = m_OldTextures[0]
m_UntransformedPoints[0] = m_OldUntransformedPoints[0]
m_TransformedPoints[0] = m_OldTransformedPoints[0]
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Nearest Above"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Traps the result nearest this distance from the trap but only \
if it's more than this distance from the trap."
endparam
}
class MMF_TrapModeSmoothFarthestBelow(MMF_TrapModeSmoothWithThreshold) {
; Returns values from the trapped iteration with the farthest distance
; less than or equal to the user value and within the threshold of it.
public:
import "common.ulb"
func MMF_TrapModeSmoothFarthestBelow(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = @p_testdist - pdistance
if (pdistance < m_Threshold && pdistance >= m_Distances[0])
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_Solid = false
m_wastrapped = true
endif
endfunc
default:
title = "Smooth Farthest Below"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Traps the result farthest from this distance from the trap \
provided it's less than this distance from the trap and \
provided the distance from this distance is within the \
threshold."
endparam
}
class MMF_TrapModeSmoothFarthestAbove(MMF_TrapModeSmoothWithThreshold) {
; Returns values from the trapped iteration with the farthest distance
; greater than or equal to the user value and within the threshold of it.
public:
import "common.ulb"
func MMF_TrapModeSmoothFarthestAbove(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = pdistance - @p_testdist
if (pdistance < m_Threshold && pdistance >= m_Distances[0])
m_Distances[0] = pdistance
m_Textures[0] = ptexture
m_UntransformedPoints[0] = pz
m_TransformedPoints[0] = pzt
m_IterationPoints[0] = m_Iterations
m_Solid = false
m_wastrapped = true
endif
endfunc
default:
title = "Smooth Farthest Above"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Traps the result farthest from this distance from the trap \
provided it's more than this distance from the trap and \
provided the distance from this distance is within the \
threshold."
endparam
}
class MMF_TrapModeSmoothSumDist(MMF_TrapModeSmoothWithThreshold) {
; Sums the values with distamce within the threshold of the user distance.
public:
import "common.ulb"
func MMF_TrapModeSmoothSumDist(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = abs(@p_testdist - pdistance)
if pdistance < m_Threshold
m_Distances[0] = m_Distances[0] + pdistance
m_Textures[0] = m_Textures[0] + ptexture
m_UntransformedPoints[0] = m_UntransformedPoints[0] + pz
m_TransformedPoints[0] = m_TransformedPoints[0] + pzt
m_IterationPoints[0] = m_IterationPoints[0] + m_Iterations
m_Solid = false
m_wastrapped = true
endif
endfunc
default:
title = "Smooth Sum (from Test Distance)"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Gets the sum of the distances from the test distance \
that are within the threshold."
endparam
}
class MMF_TrapModeSmoothAverageDist(MMF_TrapModeSmoothSumDist) {
; Sums the values with distamce within the threshold of the user distance
; and converts the values to averages.
public:
import "common.ulb"
func MMF_TrapModeSmoothAverageDist(Generic pparent)
MMF_TrapModeSmoothSumDist.MMF_TrapModeSmoothSumDist(pparent)
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = abs(@p_testdist - pdistance)
if pdistance < m_Threshold
m_Distances[0] = m_Distances[0] + pdistance
m_Textures[0] = m_Textures[0] + ptexture
m_UntransformedPoints[0] = m_UntransformedPoints[0] + pz
m_TransformedPoints[0] = m_TransformedPoints[0] + pzt
m_IterationPoints[0] = m_IterationPoints[0] + 1
m_Solid = false
m_wastrapped = true
endif
endfunc
func Result()
float ii = 1.0 / m_IterationPoints[0]
m_Distances[0] = m_Distances[0] * ii
m_Textures[0] = m_Textures[0] * ii
m_UntransformedPoints[0] = m_UntransformedPoints[0] * ii
m_TransformedPoints[0] = m_TransformedPoints[0] * ii
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
float ii = 1.0 / m_OldIterationPoints[0]
m_Distances[0] = m_OldDistances[0] * ii
m_Textures[0] = m_OldTextures[0] * ii
m_UntransformedPoints[0] = m_OldUntransformedPoints[0] * ii
m_TransformedPoints[0] = m_OldTransformedPoints[0] * ii
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Average (from Test Distance)"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Gets the average of the distances from the test distance \
that are within the threshold."
endparam
}
class MMF_TrapModeSmoothSumBelow(MMF_TrapModeSmoothWithThreshold) {
; Sums the values less than the user value and within the threshold of it.
public:
import "common.ulb"
func MMF_TrapModeSmoothSumBelow(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = @p_testdist - pdistance
if pdistance>=0 && pdistance < m_Threshold
m_Distances[0] = m_Distances[0] + pdistance
m_Textures[0] = m_Textures[0] + ptexture
m_UntransformedPoints[0] = m_UntransformedPoints[0] + pz
m_TransformedPoints[0] = m_TransformedPoints[0] + pzt
m_IterationPoints[0] = m_IterationPoints[0] + m_Iterations
m_Solid = false
m_wastrapped = true
endif
endfunc
default:
title = "Smooth Sum Below"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Gets the sum of the distances from the test distance \
where the original distance was below the test distance \
and provided the distance from this distance is within \
the threshold."
endparam
}
class MMF_TrapModeSmoothAverageBelow(MMF_TrapModeSmoothSumBelow) {
; Sums the values less than the user value and within the threshold of it
; and converts the values to averages.
public:
import "common.ulb"
func MMF_TrapModeSmoothAverageBelow(Generic pparent)
MMF_TrapModeSmoothSumBelow.MMF_TrapModeSmoothSumBelow(pparent)
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = @p_testdist - pdistance
if pdistance>=0 && pdistance < m_Threshold
m_Distances[0] = m_Distances[0] + pdistance
m_Textures[0] = m_Textures[0] + ptexture
m_UntransformedPoints[0] = m_UntransformedPoints[0] + pz
m_TransformedPoints[0] = m_TransformedPoints[0] + pzt
m_IterationPoints[0] = m_IterationPoints[0] + 1
m_Solid = false
m_wastrapped = true
endif
endfunc
func Result()
float ii = 1.0 / m_IterationPoints[0]
m_Distances[0] = m_Distances[0] * ii
m_Textures[0] = m_Textures[0] * ii
m_UntransformedPoints[0] = m_UntransformedPoints[0] * ii
m_TransformedPoints[0] = m_TransformedPoints[0] * ii
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
float ii = 1.0 / m_OldIterationPoints[0]
m_Distances[0] = m_OldDistances[0] * ii
m_Textures[0] = m_OldTextures[0] * ii
m_UntransformedPoints[0] = m_OldUntransformedPoints[0] * ii
m_TransformedPoints[0] = m_OldTransformedPoints[0] * ii
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Average Below"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Gets the average of the distances from the test distance \
where the original distance was below the test distance \
and provided the distance from this distance is within \
the threshold."
endparam
}
class MMF_TrapModeSmoothSumAbove(MMF_TrapModeSmoothWithThreshold) {
; Sums the values above than the user value and within the threshold of it.
public:
import "common.ulb"
func MMF_TrapModeSmoothSumAbove(Generic pparent)
MMF_TrapModeSmoothWithThreshold.MMF_TrapModeSmoothWithThreshold(pparent)
endfunc
func Init(complex pz)
MMF_TrapModeSmoothWithThreshold.Init(pz)
m_Solid = true
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = pdistance - @p_testdist
if pdistance>=0 && pdistance < m_Threshold
m_Distances[0] = m_Distances[0] + pdistance
m_Textures[0] = m_Textures[0] + ptexture
m_UntransformedPoints[0] = m_UntransformedPoints[0] + pz
m_TransformedPoints[0] = m_TransformedPoints[0] + pzt
m_IterationPoints[0] = m_IterationPoints[0] + m_Iterations
m_Solid = false
m_wastrapped = true
endif
endfunc
default:
title = "Smooth Sum Above"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Gets the sum of the distances from the test distance \
where the original distance was above the test distance \
and provided the distance from this distance is within \
the threshold."
endparam
}
class MMF_TrapModeSmoothAverageAbove(MMF_TrapModeSmoothSumAbove) {
; Sums the values above than the user value and within the threshold of it
; and converts the values to averages.
public:
import "common.ulb"
func MMF_TrapModeSmoothAverageAbove(Generic pparent)
MMF_TrapModeSmoothSumAbove.MMF_TrapModeSmoothSumAbove(pparent)
endfunc
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
MMF_TrapModeSmoothWithThreshold.Iterate(pz, pzt, pdistance, ptexture)
pdistance = pdistance - @p_testdist
if pdistance>=0 && pdistance < m_Threshold
m_Distances[0] = m_Distances[0] + pdistance
m_Textures[0] = m_Textures[0] + ptexture
m_UntransformedPoints[0] = m_UntransformedPoints[0] + pz
m_TransformedPoints[0] = m_TransformedPoints[0] + pzt
m_IterationPoints[0] = m_IterationPoints[0] + 1
m_Solid = false
m_wastrapped = true
endif
endfunc
func Result()
float ii = 1.0 / m_IterationPoints[0]
m_Distances[0] = m_Distances[0] * ii
m_Textures[0] = m_Textures[0] * ii
m_UntransformedPoints[0] = m_UntransformedPoints[0] * ii
m_TransformedPoints[0] = m_TransformedPoints[0] * ii
endfunc
func OldResult()
if m_OldIterationPoints[0]>0
float ii = 1.0 / m_OldIterationPoints[0]
m_Distances[0] = m_OldDistances[0] * ii
m_Textures[0] = m_OldTextures[0] * ii
m_UntransformedPoints[0] = m_OldUntransformedPoints[0] * ii
m_TransformedPoints[0] = m_OldTransformedPoints[0] * ii
m_IterationPoints[0] = m_OldIterationPoints[0]
m_Iterations = m_Iterations - 1
endif
endfunc
default:
title = "Smooth Average Above"
rating = recommended
float param p_testdist
caption = "Trap Test Distance"
default = 0.5
hint = "Gets the average of the distances from the test distance \
where the original distance was above the test distance \
and provided the distance from this distance is within \
the threshold."
endparam
}
class MMF_TrapShapeZold(common.ulb:TrapShape) {
; This is a base class specifically for Trap Shapes that require
; old values of z.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TrapShapeZold(Generic pparent)
TrapShape.TrapShape(pparent)
endfunc
; call this before each sequence of values to be trapped
; @param pz the initial z value
func Init(complex pz)
m_Iterations = 0
m_LastZ = m_zold = m_zolder = pz
m_zoldok = m_zolderok = false
endfunc
; call this for each iteration being trapped
; @param pz the z value
; @return trap distance
float func Iterate(complex pz)
m_Iterations = m_Iterations + 1
m_LastZ = pz
return real(pz)
endfunc
; Update internal counters without transforming a value
; Flag for "got old z values" set to false
func IterateSilent()
m_zoldok = m_zolderok = false
m_Iterations = m_Iterations + 1
endfunc
; Update internal counters without transforming a value
; Keep updating old z values
; @param pz the z value
func IterateSilentZold(complex pz)
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
m_Iterations = m_Iterations + 1
endfunc
protected:
complex m_zold
complex m_zolder
bool m_zoldok
bool m_zolderok
default:
int param v_mmftrapshapezold
caption = "Version (MMF TrapShapeZold)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmftrapshapezold < 100
endparam
}
class MMF_TrapShapeOldAngles(MMF_TrapShapeZold) {
; Trap various old angle values.
public:
import "common.ulb"
func MMF_TrapShapeOldAngles(Generic pparent)
MMF_TrapShapeZold.MMF_TrapShapeZold(pparent)
endfunc
float func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this trapshape
m_LastZ = pz
float r = recip(0.0)
if (@mode=="Raw Old Angles" || @mode=="Absolute Old Angles" \
|| @mode=="All Old Angles" || @mode=="Old Cosines" \
|| @mode=="All Old Angles 2") && m_zoldok
if @mode=="Raw Old Angles"
r = atan2(pz + @offset - m_zold)
elseif @mode=="Absolute Old Angles"
r = abs(atan2(pz + @offset - m_zold))
elseif @mode=="All Old Angles"
r = #pi + atan2(pz + @offset - m_zold)
elseif @mode=="Old Cosines"
r = cos(0.5*atan2(pz + @offset - m_zold))
elseif @mode=="All Old Angles 2"
r = atan2(pz + @offset - m_zold)
if r<0.0
r = r + 2.0*#pi
endif
endif
elseif (@mode=="Raw Older Angles" || @mode=="Absolute Older Angles" \
|| @mode=="All Older Angles" || @mode=="Older Cosines" \
|| @mode=="All Older Angles 2") && m_zolderok
if @mode=="Raw Older Angles"
r = atan2(pz + @offset - m_zolder)
elseif @mode=="Absolute Older Angles"
r = abs(atan2(pz + @offset - m_zolder))
elseif @mode=="All Older Angles"
r = #pi + atan2(pz + @offset - m_zolder)
elseif @mode=="Older Cosines"
r = cos(0.5*atan2(pz + @offset - m_zolder))
elseif @mode=="All Older Angles 2"
r = atan2(pz + @offset - m_zolder)
if r<0.0
r = r + 2.0*#pi
endif
endif
endif
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
return r
endfunc
default:
title = "Angles (of z-zold or z-zolder)"
heading
text = "Intended for use with 'MMF Smooth Orbit Traps (Gradient)' or \
similar smoothing formulas since smoothing is usually required."
endheading
int param mode
caption = "Method"
enum = "Raw Old Angles" "Absolute Old Angles" "All Old Angles" \
"Old Cosines" "All Old Angles 2" "Raw Older Angles" \
"Absolute Older Angles" "All Older Angles" "Older Cosines" \
"All Older Angles 2"
default = 3
hint = "Inspired by Cilia mode colouring."
endparam
complex param offset
caption = "Z Offset"
default = (0,0)
hint = "Offsets z by this amount, useful for animation."
endparam
}
class MMF_TrapShapeSimpleVergence(MMF_TrapShapeZold) {
; Trap the divergence or convergence in the orbit.
public:
import "common.ulb"
func MMF_TrapShapeSimpleVergence(Generic pparent)
MMF_TrapShapeZold.MMF_TrapShapeZold(pparent)
endfunc
float func Iterate(complex pz)
float r = recip(0) ; ensures that "no result" due to no zold or zolder
; returns a value outside the threshold
; m_Iterations = m_Iterations + 1 not used in this trapshape
m_LastZ = pz
if @type=="Divergence" && m_zoldok
r = cabs(log(pz)/log(m_zold))
elseif @type=="Convergence" && m_zolderok
r = cabs(log(pz-m_zold)/log(m_zold-m_zolder))
endif
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
return r
endfunc
default:
title = "Simple 'Vergence"
int param type
caption = "Type of 'Vergence"
enum = "Divergence" "Convergence"
default = 0
hint = "Divergence uses log(z)/log(zold), Convergence uses \
log(z-zold)/log(zold-zolder). Either type should \
work on any fractal whether convergent or divergent."
endparam
}
class MMF_TrapShapeOrbitals(MMF_TrapShapeZold) {
; Traps the change in z or z-zold relative to z or z-zold.
public:
import "common.ulb"
func MMF_TrapShapeOrbitals(Generic pparent)
MMF_TrapShapeZold.MMF_TrapShapeZold(pparent)
endfunc
; The recip(0) ensures that "no result" due to no zold or zolder
; returns a value outside the threshold
float func Iterate(complex pz)
float r = recip(0)
; m_Iterations = m_Iterations + 1 not used in this trapshape
m_LastZ = pz
if @type=="Divergent" && m_zoldok
r = sqrt(|pz-m_zold|/|pz|)
elseif m_zolderok
if @type=="Convergent"
r = sqrt(|pz-2.0*m_zold+m_zolder|/|pz-m_zold|)
elseif @type=="Old Divergent"
r = sqrt(|pz-m_zolder|/|pz|)
endif
endif
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
return r
endfunc
default:
title = "Orbitals"
heading
text = "Intended for use with 'MMF Smooth Orbit Traps (Gradient)' or \
similar smoothing formulas since smoothing is often required."
endheading
int param type
caption = "Orbital Type"
enum = "Divergent" "Convergent" "Old Divergent"
default = 0
hint = "Divergent traps z to zold, Convergent traps z-zold to \
zold-zolder, Old Divergent traps z to zolder. \
All may work for any main formula whether it's \
convergent or divergent."
endparam
}
class MMF_TrapShapeModulus(common.ulb:TrapShape) {
public:
import "common.ulb"
import "Standard.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TrapShapeModulus(Generic pparent)
TrapShape.TrapShape(pparent)
fTrapShape1 = new @p_TrapShape1(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fTrapShape1.Init(pz)
endfunc
float func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
pz = pz*@p_scale
return fTrapShape1.Iterate(real(pz)%real(@p_modulus) \
+flip(imag(pz)%imag(@p_modulus)))
endfunc
private:
TrapShape fTrapShape1
default:
title = "Trap Shape Modulus"
complex param p_modulus
caption = "Modulus"
default = (1.0,1.0)
hint = "Both real and imaginay pats are used, being applied to the real \
and imaginay input values respectively."
endparam
complex param p_scale
caption = "Scale"
default = (1.0,0.0)
hint = "Normally you'd stick to using a wholly real number."
endparam
TrapShape param p_TrapShape1
caption = "Following trap shape"
default = Standard_TrapShapePoint
hint = "The modified value is passsed on to this trap shape."
endparam
}
class MMF_TrapShapeCurvature(MMF_TrapShapeZold) {
;
; Based on the original curvature formula by Damien Jones.
;
public:
import "common.ulb"
func MMF_TrapShapeCurvature(Generic pparent)
MMF_TrapShapeZold.MMF_TrapShapeZold(pparent)
endfunc
; The recip(0) ensures that "no result" due to no zold or zolder
; returns a value outside the threshold
float func Iterate(complex pz)
float r = recip(0)
; m_Iterations = m_Iterations + 1 not used in this trapshape
m_LastZ = pz
if @type=="Original" && m_zolderok
r = atan2((pz - m_zold)/(m_zold - m_zolder))
elseif @type=="One Centre" && m_zoldok
r = atan2((pz - @centre1)/(m_zold - @centre1))
elseif @type=="Two Centres" && m_zoldok
r = atan2((pz - @centre1)/(m_zold - @centre2))
elseif @type=="Centre Offsets" && m_zolderok
r = atan2((pz - m_zold - @centre1)/(m_zold - m_zolder - @centre2))
endif
if r<1e100
if @method=="Absolute Angles"
r = 2.0*abs(r)
elseif @method=="All Angles #1"
r = abs(#pi + r)
elseif @method=="All Angles #2"
if r<0
r = r + 2.0*#pi
endif
endif
if @usesine
r = 0.5*abs(1.0 + sin(r))
else
r = r/(2.0*#pi)
endif
endif
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
return r
endfunc
default:
title = "Curvature"
heading
text = "Intended for use with 'MMF Smooth Orbit Traps (Gradient)' or \
similar smoothing formulas since smoothing is often required."
endheading
int param type
caption = "Curvature Type"
enum = "Original" "One Centre" "Two Centres" "Centre Offsets"
default = 0
endparam
complex param centre1
caption = "Centre 1"
default = (0,0)
visible = @type>0
endparam
complex param centre2
caption = "Centre 2"
default = (0,0)
visible = @type>1
endparam
int param method
caption = "Angle method"
enum = "Absolute Angles" "All Angles #1" "All Angles #2" "Raw Angles"
default = 0
endparam
bool param usesine
caption = "Use Sine"
default = false
hint = "When enabled the sine of the angle is taken."
endparam
}
class MMF_TrapShapeInterpolation(MMF_TrapShapeZold) {
;
; Based on the interpolation methods in mmf3.ucl Orbitals+.
;
public:
import "common.ulb"
func MMF_TrapShapeInterpolation(Generic pparent)
MMF_TrapShapeZold.MMF_TrapShapeZold(pparent)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this trapshape
m_LastZ = m_zold = m_zolder = pz
m_zoldok = m_zolderok = m_gotold = false
endfunc
; The recip(0) ensures that "no result" due to no zold or zolder
; returns a value outside the threshold
float func Iterate(complex pz)
complex zt = (0,0)
complex a = (0,0)
complex b = (0,0)
float r = recip(0.0)
float t = 0.0
bool gotz = false
; m_Iterations = m_Iterations + 1 not used in this trapshape
m_LastZ = pz
if (@usevar=="Predict1" || @usevar=="Predict2") \
&& m_gotold && m_zoldok
if @usevar=="Predict1"
zt = m_oa*m_zold^@pwr1 + m_ob*m_zold^@pwr2
else
zt = m_oa*m_zold^@pwr1 + @valb*m_zold^@pwr2
endif
gotz = true
endif
m_gotold = false
if @usevar=="Just a" || @usevar=="Just b" || @usevar=="Combined" \
|| @usevar=="Predict1"
if m_zolderok
if @pwr1!=(0,0)
if @pwr2!=(0,0)
a = m_zold^@pwr1*m_zolder^@pwr2 - m_zolder^@pwr1*m_zold^@pwr2
else
a = m_zold^@pwr1 - m_zolder^@pwr1
endif
elseif @pwr2!=(0,0)
a = m_zolder^@pwr2 - m_zold^@pwr2
endif
m_gotold = true
endif
elseif m_zoldok
if @pwr1!=(0,0)
a = m_zold^@pwr1
else
a = 1.0
endif
m_gotold = true
endif
if m_gotold
if @usevar=="Just a" || @usevar=="Just b" || @usevar=="Combined" \
|| @usevar=="Predict1"
a = 1.0/a
if @pwr1!=(0,0)
if @pwr2!=(0,0)
if @usevar!="Just a"
b = (m_zold^(@pwr1+1.0) - pz*m_zolder^@pwr1)*a
endif
if @usevar!="Just b"
a = (pz*m_zolder^@pwr2 - m_zold^(@pwr2+1.0))*a
endif
else
if @usevar!="Just a"
b = (m_zold^(@pwr1+1.0) - pz*m_zolder^@pwr1)*a
endif
if @usevar!="Just b"
a = (pz - m_zold)*a
endif
endif
elseif @pwr2!=(0,0)
if @usevar!="Just a"
b = (m_zold - pz)*a
endif
if @usevar!="Just b"
a = (pz*m_zolder^@pwr2 - m_zold^(@pwr2+1.0))*a
endif
endif
elseif @pwr2!=(0,0)
a = (pz - @valb*m_zold^@pwr2)/a
else
a = (pz - @valb)/a
endif
if @usevar=="Predict1" || @usevar=="Predict2"
m_oa = a
m_ob = b
endif
endif
if ((@usevar=="Just a" || @usevar=="Just b" || @usevar=="Combined" \
|| @usevar=="Fixed b") && m_gotold) || ((@usevar=="Predict1" \
|| @usevar=="Predict2") && gotz)
if @usevar=="Predict1" || @usevar=="Predict2"
a = zt
if @trapz
a = pz - zt
endif
endif
if @usevar!="Just b"
if @fna==1
a = log(a)
elseif @fna==2
a = sin(a)
elseif @fna==3
a = cos(a)
elseif @fna==4
a = tan(a)
elseif @fna==5
a = sinh(a)
elseif @fna==6
a = cosh(a)
elseif @fna==7
a = tanh(a)
elseif @fna==8
a = exp(a)
elseif @fna==9
a = sqrt(a)
elseif @fna==10
a = a^(1.0/3.0)
elseif @fna==11
a = a*a
elseif @fna==12
a = a^3.0
endif
if @trap=="Magnitude"
r = cabs(a)
elseif @trap=="Real"
r = abs(real(a))
elseif @trap=="Imaginary"
r = abs(imag(a))
elseif @trap=="Angle"
r = atan2(a)
if @angle=="Absolute"
r = 2.0*abs(r)
elseif @angle=="All Angles 1"
if r<0.0
r = 2.0*#pi + r
endif
elseif @angle=="All Angles 2"
r = abs(#pi + r)
endif
if @usesin
r = abs(1.0 + sin(r))
else
r = r/(2.0*#pi)
endif
endif
endif
if @usevar=="Just b" || @usevar=="Combined"
if @fnb==1
b = log(b)
elseif @fnb==2
b = sin(b)
elseif @fnb==3
b = cos(b)
elseif @fnb==4
b = tan(b)
elseif @fnb==5
b = sinh(b)
elseif @fnb==6
b = cosh(b)
elseif @fnb==7
b = tanh(b)
elseif @fnb==8
b = exp(b)
elseif @fnb==9
b = sqrt(b)
elseif @fnb==10
b = b^(1.0/3.0)
elseif @fnb==11
b = b*b
elseif @fnb==12
b = b^3.0
endif
if @trap=="Magnitude"
t = cabs(b)
elseif @trap=="Real"
t = abs(real(b))
elseif @trap=="Imaginary"
t = abs(imag(b))
elseif @trap=="Angle"
t = atan2(b)
if @angle=="Absolute"
t = 2.0*abs(t)
elseif @angle=="All Angles 1"
if t<0.0
t = 2.0*#pi + t
endif
elseif @angle=="All Angles 2"
t = abs(#pi + t)
endif
if @usesin
t = abs(1.0 + sin(t))
else
t = t/(2.0*#pi)
endif
endif
if @usevar=="Just b"
r = t
elseif @mix=="Minimum" && t
public:
import "common.ulb"
func MMF_TrapShapeCentreOfCurvature(Generic pparent)
MMF_TrapShapeZold.MMF_TrapShapeZold(pparent)
endfunc
; The recip(0) ensures that "no result" due to no zold or zolder
; returns a value outside the threshold
float func Iterate(complex pz)
float r = recip(0)
; m_Iterations = m_Iterations + 1 not used in this trapshape
m_LastZ = pz
if m_zoldok
float x2m1 = real(m_zold) - real(pz)
float y2m1 = imag(m_zold) - imag(pz)
float x3m1 = real(m_zolder) - real(pz)
float y3m1 = imag(m_zolder) - imag(pz)
float x2y2s = x2m1*(real(m_zold) + real(pz)) \
+ y2m1*(imag(m_zold) + imag(pz))
float x3y3s = x3m1*(real(m_zolder) + real(pz)) \
+ y3m1*(imag(m_zolder) + imag(pz))
float d = 2.0*(x2m1*y3m1-x3m1*y2m1)
complex c = y3m1*x2y2s - y2m1*x3y3s + flip(x2m1*x3y3s - x3m1*x2y2s)
if abs(d)<1e-5
if abs(d)*1e100
public:
import "common.ulb"
func MMF_TrapShapeTriangleInequality(Generic pparent)
TrapShape.TrapShape(pparent)
tcentre = @p_tcentre
fAC = cabs(@p_tcentre)
endfunc
;
; @param pz the z value
func Init(complex pz)
TrapShape.Init(pz)
if @p_usepixel
Generic obj = Generic(GetParent())
if obj
repeat
if Coloring(obj)
tcentre = Coloring(obj).GetPixel() + @p_tcentre
obj = 0
else
obj = Generic(obj.GetParent())
if obj==0
tcentre = pz + @p_tcentre
endif
endif
until obj==0
else
tcentre = pz + @p_tcentre
endif
fAC = cabs(tcentre)
endif
endfunc
float func Iterate(complex pz)
TrapShape.Iterate(pz)
float az2 = cabs(pz - tcentre)
float lowbound = abs(az2 - fAC)
if abs(az2 = az2 + fAC - lowbound)>1e-100
return (cabs(pz) - lowbound) / az2
else
return (cabs(pz) - lowbound)*1e100
endif
endfunc
private:
complex tcentre
float fAC
default:
title = "Triangle Inequality"
heading
text = "Intended for use with 'MMF Smooth Orbit Traps (Gradient)' or \
similar smoothing formulas since smoothing is usually required."
endheading
bool param p_usepixel
caption = "Use Location/Initial Z ?"
default = true
hint = "The original Triangle Inequality Average used #pixel as the \
base point, enabling this option normally replicates that. \
However in some cases the location value equivalent to #pixel \
may not be available and in such cases when this option is \
enabled then the start z value will be used instead i.e. if \
used with Julia formulas the location value will be used \
since start z is the location in a Julia formula but when \
used with Mandelbrot formulas the start z is not the location."
endparam
complex param p_tcentre
caption = "Base Point or Offset"
default = (1,0)
hint = "If you choose to use initial z as the base point then this value \
is applied as an offset, otherwise it's used as the actual \
base point value. Note that to closely replicate standard \
Triangle Inequality Average colouring on a Julia Set then have \
'Use Initial z ?' enabled, set 'Base Point or Offset' to (0,0) \
and use 'Smooth Average' from mmf.ulb as the Trap Mode."
endparam
}
class MMF_TrapShapeFnz(common.ulb:TrapShape) {
; Simple functions of z converted to floats.
public:
import "common.ulb"
func MMF_TrapShapeFnz(Generic pparent)
TrapShape.TrapShape(pparent)
endfunc
float func Iterate(complex pz)
TrapShape.Iterate(pz)
if @mode=="real(fn(z))"
return real(@fn(pz))
elseif @mode=="abs(real(fn(z)))"
return abs(real(@fn(pz)))
elseif @mode=="imag(fn(z))"
return imag(@fn(pz))
elseif @mode=="abs(imag(fn(z)))"
return abs(imag(@fn(pz)))
else;if @mode=="cabs(fn(z))"
return cabs(@fn(pz))
endif
endfunc
default:
title = "Functions"
heading
text = "Intended for use with 'MMF Smooth Orbit Traps (Gradient)' or \
similar smoothing formulas since smoothing is usually required."
endheading
func fn
caption = "Function to use"
default = sqrt()
endfunc
int param mode
caption = "Method"
enum = "real(fn(z))" "abs(real(fn(z)))" "imag(fn(z))" \
"abs(imag(fn(z)))" "cabs(fn(z))"
default = 0
hint = "Original inspired by the idea of trapping the values of \
atan2(z)."
endparam
}
class MMF_TrapShapeAngle(common.ulb:TrapShape) {
; Trapping values based on the angle of z.
public:
import "common.ulb"
func MMF_TrapShapeAngle(Generic pparent)
TrapShape.TrapShape(pparent)
endfunc
float func Iterate(complex pz)
TrapShape.Iterate(pz + @offset)
if @mode=="Raw Angles"
return atan2(pz + @offset)
elseif @mode=="Absolute Angles"
return abs(atan2(pz + @offset))
elseif @mode=="All Angles"
return #pi + atan2(pz + @offset)
elseif @mode=="Cosines"
return cos(0.5*atan2(pz + @offset))
else;if @mode=="All Angles 2"
float r = atan2(pz + @offset)
if r<0.0
r = r + 2.0*#pi
endif
return r
endif
endfunc
default:
title = "Angles (of z)"
heading
text = "Intended for use with 'MMF Smooth Orbit Traps (Gradient)' or \
similar smoothing formulas since smoothing is usually required."
endheading
int param mode
caption = "Method"
enum = "Raw Angles" "Absolute Angles" "All Angles" "Cosines" \
"All Angles 2"
default = 3
hint = "Inspired by Cilia mode colouring."
endparam
complex param offset
caption = "Z Offset"
default = (0,0)
hint = "Offsets the z value by this amount - good for animation."
endparam
}
class MMF_TrapModeIteration(Standard.ulb:Standard_TrapModeBase) {
public:
func Iterate(complex pz, complex pzt, float pdistance, float ptexture)
Standard_TrapModeBase.Iterate(pz, pzt, pdistance, ptexture)
if m_Iterations == @p_iter
m_Solid = false
SetTrapInfo(0, pz, pzt, pdistance)
m_Textures[0] = ptexture
endif
endfunc
default:
title = "Given Iteration"
int param p_iter
caption = "Iteration to trap"
default = 10
min = 1
hint = "Note that areas which did not reach this iteration count will \
be marked as 'solid'."
endparam
}
class MMF_TrapColoring(common.ulb:TrapColoring) {
; Some extensions to the standard trap colouring.
public:
import "common.ulb"
;
func MMF_TrapColoring(Generic pparent)
TrapColoring.TrapColoring(pparent)
m_ColorTransfer = new @f_colortransfer(this)
m_TextureTransfer = new @f_texturetransfer(this)
m_ColorTransfer.Init(0)
m_TextureTransfer.Init(0)
m_TextureFlag = true
if @colourby>7
m_Image = new @f_image(this)
endif
if @colourby=="Image All"
m_Merge = new @f_merge(this)
if @adjustlayer
m_Adjust = new @f_adjust(this)
endif
endif
endfunc
;
float func Result(TrapMode ptrapmode)
complex v = (0,0)
float f = 0.0
if @colourby=="Distance"
f = ptrapmode.GetDistance(0)
elseif @colourby=="Iteration"
f = 0.05*ptrapmode.GetIteration(0)
else
if @usetrap=="Original Z value"
v = ptrapmode.GetUntransformedPoint(0)
elseif @usetrap=="Trapped Z value"
v = ptrapmode.GetTransformedPoint(0)
endif
if @colourby=="Angle" || @colourby=="Sine"
if (f = atan2(v))<0.0
f = 2.0*#pi + f
endif
if @colourby=="Angle"
f = f/(2.0*#pi)
else
f = abs(1.0 + sin(f))
endif
elseif @colourby=="Magnitude"
f = cabs(v)
elseif @colourby=="Real"
f = real(v)
elseif @colourby=="Imaginary"
f = imag(v)
elseif @colourby!="Texture Only"
color clr = m_Image.GetColor(v)
if @colourby=="Image All"
f = 0.299*red(clr) + 0.587*green(clr) + 0.114*blue(clr)
elseif @colourby=="Image Red"
f = red(clr)
elseif @colourby=="Image Green"
f = green(clr)
elseif @colourby=="Image Blue"
f = blue(clr)
elseif @colourby=="Image Alpha"
f = alpha(clr)
elseif @colourby=="Image Hue"
f = hue(clr)/6.0
elseif @colourby=="Image Saturation"
f = sat(clr)
elseif @colourby=="Image Luminance"
f = lum(clr)
endif
endif
endif
if @colourby!="Texture Only" && m_TextureFlag
return m_ColorTransfer.Iterate(f) \
+ m_TextureTransfer.Iterate(ptrapmode.GetTexture(0))
elseif m_TextureFlag
return m_TextureTransfer.Iterate(ptrapmode.GetTexture(0))
else
return m_ColorTransfer.Iterate(f)
endif
endfunc
;
bool func UseColor()
if @colourby=="Image All"
return true
endif
return false
endfunc
;
; @return texture value
float func ResultTexture(TrapMode ptrapmode)
return m_TextureTransfer.Iterate(ptrapmode.GetTexture(0))
endfunc
;
; @return the colour
color func ResultColor(TrapMode ptrapmode)
complex v
if @usetrap=="Original Z value"
v = ptrapmode.GetUntransformedPoint(0)
else;if @usetrap=="Trapped Z value"
v = ptrapmode.GetTransformedPoint(0)
endif
return m_Image.GetColor(v)
endfunc
;
; @param tex texture index
; @return merged colour
color func MergeResult(color clr, float tex)
if @adjustlayer
if m_TextureFlag
clr = m_Merge.GradientMerge(clr, tex)
endif
color c = @f_adjustcolour
if @adjusttype==0
c = RGB(@adjred, @adjgreen, @adjblue)
endif
c = compose(clr, m_Adjust.Merge(clr, c), @f_opacity)
return RGBA(red(c), green(c), blue(c), alpha(clr))
endif
if m_TextureFlag
return m_Merge.GradientMerge(clr, tex)
endif
return clr
endfunc
; @param flag indicates whether texturing is used or not
func SetTextureFlag(bool flag)
m_TextureFlag = flag
endfunc
protected:
Transfer m_ColorTransfer
Transfer m_TextureTransfer
ImageWrapper m_Image
GradientLayer m_Merge
ColorMerge m_Adjust
BOOL m_TextureFlag
default:
title = "MMF Colour Selector"
int param v_mmf_trapcoloring
caption = "Version (MMF_TrapColoring)"
default = 100
hint = "This version parameter is used to detect when a change \
has been made to the formula that is incompatible with \
the previous version. When that happens, this field will \
reflect the old version number to alert you to the fact \
that an alternate rendering is being used."
visible = @v_mmf_trapcoloring < 100
endparam
int param colourby
caption = "Colour By"
enum = "Distance" "Iteration" "Angle" "Magnitude" "Real" "Imaginary" \
"Sine" "Texture Only" "Image All""Image Red" "Image Green" \
"Image Blue" "Image Alpha" "Image Hue" "Image Saturation" \
"Image Luminance"
default = 0
hint = "Note that 'Texture Only' will only produce colouring if \
you're using a texture other than dmj5->Flat Texture. \
'Image All' maps the image brightness (Yiq) to UF's gradient \
if the colouring is being used as a gradient colouring or uses \
the image colours if the colouring is being used as a direct \
colouring. 'Image Red' maps the image red to a gradient, \
'Image Green' the green, 'Image Blue' the blue, 'Image Hue' \
the hue, 'Image Saturation' the saturation and 'Image Luminance' \
the luminance."
endparam
ImageWrapper param f_image
caption = "Image Object"
default = MMF_ImageImport
hint = "This is the image object to use for your trap colouring."
visible = @colourby>7
endparam
int param usetrap
caption = "Z value"
enum = "Original Z value" "Trapped Z value"
default = 0
hint = "When using 'Angle' as the value to colour by 'Original \
Z value' gives 'Angle' or 'Angle of Z' and 'Trapped \
Z value' gives 'Angle to Trap'."
visible = @colourby>1
endparam
Transfer param f_colortransfer
caption = "Colour Transfer"
default = NullTransfer
hint = "Allows you to manipulate the colour value from the trap \
before combining with any texture. Does not apply to 'Image All' \
if the main colouring is in direct mode."
visible = @colourby!=7
endparam
Transfer param f_texturetransfer
caption = "Texture Transfer"
default = NullTransfer
hint = "Allows you to manipulate any texture value before \
combining with the colour value from the trap."
endparam
GradientLayer param f_merge
caption = "Texture/Iteration Merge"
default = MMF_GradientLayer
hint = "Only used if the main colouring is being used in direct colouring \
mode and texturing and/or adding the smooth iteration count \
is/are in use. Use to merge the texture/iteration value with the \
image. Note that the gradient you choose controls the colour of \
the texture/iteration layer which is normally treated as the top \
layer."
visible = @colourby=="Image All"
expanded = false
endparam
bool param adjustlayer
caption = "Add Adjust layer"
default = false
hint = "Allows you to add an adjustment layer in a given colour to merge \
on top of the image/texture. Only active if the main colouring \
is in direct mode."
visible = @colourby=="Image All"
endparam
int param adjusttype
caption = "Colour or RGB"
enum = "RGB values" "Colour Parameter"
default = 1
hint = "This option is specifically added so that if you choose \
'RGB values' you can 'explore' them and see changes to the image \
as you change the RGB. The option may become redundant in a \
future version of UF."
visible = @colourby=="Image All" && @adjustlayer
endparam
float param adjred
caption = "Red Value"
default = 1.0
hint = "The red part of the adjust colour (0 to 1)."
visible = @colourby=="Image All" && @adjustlayer && @adjusttype==0
endparam
float param adjgreen
caption = "Green Value"
default = 1.0
hint = "The green part of the adjust colour (0 to 1)."
visible = @colourby=="Image All" && @adjustlayer && @adjusttype==0
endparam
float param adjblue
caption = "Blue Value"
default = 1.0
hint = "The blue part of the adjust colour (0 to 1)."
visible = @colourby=="Image All" && @adjustlayer && @adjusttype==0
endparam
color param f_adjustcolour
caption = "Adjust Layer Colour"
default = RGB(1,1,1)
hint = "Allows you to apply overall adjustments to your colouring."
visible = @colourby=="Image All" && @adjustlayer && @adjusttype==1
endparam
ColorMerge param f_adjust
caption = "Adjustment Layer Merge"
default = MMF_ExtendedColorMerge
visible = @colourby=="Image All" && @adjustlayer
endparam
float param f_opacity
caption = "Adjustment Opacity"
default = 1.0
hint = "Use to modify the adjustment opacity, the normal range is from \
0 to 1."
visible = @colourby=="Image All" && @adjustlayer
endparam
}
class MMF_TrapTransfer(common.ulb:Transfer) {
;
; This transfer method is based on the original UF gradient transfer
; but with added options.
; David Makin, May 2008
public:
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TrapTransfer(Generic pparent)
Transfer.Transfer(pparent)
endfunc
; @param pr the float value to manipulate
; @return the manipulated value
float func Iterate(float pr)
float x = @p_offset1 + (pr + @p_offset0) * @p_zscale0
if @p_forcepos && x<0.0
x = abs(x)
endif
if x<0.0
x = 0.0
else
if (@p_xfer == "Sqr")
x = 2.0*sqr(x)
elseif (@p_xfer == "Sqrt")
x = 0.5*sqrt(x)
elseif (@p_xfer == "Cube")
x = 3.0*x^3.0
elseif (@p_xfer == "CubeRoot")
x = (x^(1.0/3.0))/3.0
elseif (@p_xfer == "Log")
x = log(1.0 + x)
elseif (@p_xfer == "Exp")
if (x >= 100.0)
x = exp(100.0)
else
x = exp(x)
endif
elseif (@p_xfer == "Sin")
x = abs(sin(x))
elseif (@p_xfer == "ArcTan")
x = abs(atan(x))
elseif (@p_xfer == "Cos")
x = 1.0 + cos(x)
elseif (@p_xfer == "LogTan")
x = log(1.0 + abs(tan(x)))
elseif (@p_xfer == "LogLog")
x = log(1.0 + log(1.0 + x))
elseif (@p_xfer == "InvArcTan")
x = 0.0005*((2.0*#pi/atan(x))^@p_iatpower - 1.0)
elseif (@p_xfer == "Power")
x = x^@p_power
endif
endif
return @p_offset3 + (x + @p_offset2) * @p_zscale1
endfunc
default:
title = "Trap/Gradient Transfer"
int param v_mmf_traptransfer
caption = "Version (MMF_TrapTransfer)"
default = 100
hint = "This version parameter is used to detect when a change has been made to the formula that is incompatible with the previous version. When that happens, this field will reflect the old version number to alert you to the fact that an alternate rendering is being used."
visible = @v_mmf_traptransfer < 100
endparam
float param p_offset0
caption = "Initial Pre-Offset"
default = 0.0
hint = "Applied prior to the pre-scale."
endparam
float param p_zscale0
caption = "Pre-Scale"
default = 1.0
exponential = true
hint = "Applied prior to the 'Transfer Function'."
endparam
float param p_offset1
caption = "Final Pre-Offset"
default = 0.0
hint = "Applied after the pre-scale but before the 'Transfer \
Function'."
endparam
bool param p_forcepos
caption = "Force positive"
default = false
hint = "When enabled the value passed to the transfer function is made \
positive using abs(). If disabled then negative values are made \
zero and the transfer function is skipped."
endparam
int param p_xfer
caption = "Transfer Function"
default = 0
enum = "Linear" "Sqr" "Sqrt" "Cube" "CubeRoot" "Log" "Exp" "Sin" \
"ArcTan" "Cos" "LogTan" "LogLog" "InvArcTan" "Power"
hint = "This function will be applied to the value. 'InvArcTan' is \
specifically designed to produce evenly spread smooth \
iteration colouring - use the power adjust to compensate \
for different bailout values."
endparam
float param p_iatpower
caption = "Power adjust (for InvArcTan)"
default = 2.0
hint = "For when adjusting smooth iteration colouring, this power \
adjust allows you to compensate for different bailout values, \
the larger the bailout, the larger you'll need to make the \
power value e.g. around 2 for a bailout of 128 or around 3.5 \
for a bailout of 65536."
visible = @p_xfer==12
endparam
float param p_power
caption = "Power"
default = 4.0
visible = @p_xfer==13
endparam
float param p_offset2
caption = "Initial Post-Offset"
default = 0.0
hint = "Applied prior to the post-scale."
endparam
float param p_zscale1
caption = "Post-Scale"
default = 1.0
exponential = true
hint = "Applied after the 'Transfer Function'."
endparam
float param p_offset3
caption = "Final Post-Offset"
default = 0.0
hint = "The final offset."
endparam
}
class MMF_TransferMerge(common.ulb:Transfer) {
; Allows the combination of multiple transfer options
public:
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TransferMerge(Generic pparent)
Transfer.Transfer(pparent)
m_transfer[0] = new @transfer0(pparent)
m_transfer[1] = new @transfer1(pparent)
if @numtrans>0
m_transfer[2] = new @transfer2(pparent)
if @numtrans>1
m_transfer[3] = new @transfer3(pparent)
if @numtrans>2
m_transfer[4] = new @transfer4(pparent)
if @numtrans>3
m_transfer[5] = new @transfer5(pparent)
if @numtrans>4
m_transfer[6] = new @transfer6(pparent)
if @numtrans>5
m_transfer[7] = new @transfer7(pparent)
if @numtrans>6
m_transfer[8] = new @transfer8(pparent)
if @numtrans>7
m_transfer[9] = new @transfer9(pparent)
endif
endif
endif
endif
endif
endif
endif
endif
endfunc
; @param pz complex to initialise
func Init(complex pz)
int i = 1
m_transfer[0].Init(pz)
m_transfer[1].Init(pz)
while (i=i+1)<@numtrans+2
m_transfer[i].Init(pz)
endwhile
endfunc
; @param pr the float value to manipulate
; @return the manipulated value
float func Iterate(float pr)
int i = 1
pr = m_transfer[1].Iterate(m_transfer[0].Iterate(pr))
while (i=i+1)<@numtrans+2
pr = m_transfer[i].Iterate(pr)
endwhile
return pr
endfunc
func IterateSilent()
int i = 1
m_transfer[0].IterateSilent()
m_transfer[1].IterateSilent()
while (i=i+1)<@numtrans+2
m_transfer[i].IterateSilent()
endwhile
endfunc
protected:
Transfer m_transfer[10]
default:
title = "MMF Transfer Merge"
int param v_mmftransfermerge
caption = "Version (MMF Transfer Merge)"
default = 100
hint = "This version parameter is used to detect when a change has been \
made to the formula that is incompatible with the previous \
version. When that happens, this field will reflect the old \
version number to alert you to the fact that an alternate \
rendering is being used."
visible = @v_mmftransfermerge < 100
endparam
int param numtrans
caption = "Number of Transfers"
enum = "2" "3" "4" "5" "6" "7" "8" "9" "10"
default = 0
endparam
Transfer param transfer0
caption = "1st Transfer"
default = NullTransfer
endparam
Transfer param transfer1
caption = "2nd Transfer"
default = NullTransfer
endparam
Transfer param transfer2
caption = "3rd Transfer"
default = NullTransfer
visible = @numtrans>0
endparam
Transfer param transfer3
caption = "4th Transfer"
default = NullTransfer
visible = @numtrans>1
endparam
Transfer param transfer4
caption = "5th Transfer"
default = NullTransfer
visible = @numtrans>2
endparam
Transfer param transfer5
caption = "6th Transfer"
default = NullTransfer
visible = @numtrans>3
endparam
Transfer param transfer6
caption = "7th Transfer"
default = NullTransfer
visible = @numtrans>4
endparam
Transfer param transfer7
caption = "8th Transfer"
default = NullTransfer
visible = @numtrans>5
endparam
Transfer param transfer8
caption = "9th Transfer"
default = NullTransfer
visible = @numtrans>6
endparam
Transfer param transfer9
caption = "10th Transfer"
default = NullTransfer
visible = @numtrans>7
endparam
}
class MMF_AltfBm(common.ulb:Generic) {
; This is an fBm texture class. It simply has an an init for the
; internal texturing variable set-up and a function to return the
; texture value (float) for a given complex value.
public:
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_AltfBm(Generic pparent)
Generic.Generic(pparent)
endfunc
; Initialisation of the texture variables.
; if @fBm
; GlobalInit(value)
; endif
; @param pz a complex value for initialisation of the fBm
func GlobalInit(complex pz)
float d=#pi/180.0 ; for conversion to radians
float c=4096.0*@rs ; overall frequency
; fBm level 1
float ang=@ang0*d ; convert rotation to rads
; q[level,0] and q[level,1] are the scaling factors for the
; x+y and x-y arrays, the "correct" value should be the same
; for both (ie. 1/sqrt(2)) but to increase variation the
; values used are in the neighbourhood of 0.7071, being n/8192
; where n is a prime number.
q[0,0]=5471.0/8192.0
q[0,1]=6143.0/8192.0
; The rotation values
q[0,2]=cos(ang)
q[0,3]=sin(ang)
; Combine the overall sharpness and frequency with the
; sharpness and frequency for this level.
q[0,4]=@frac0*@frac
q[0,5]=c*@rs0
; Put the amplitude in the array so it can be indexed
q[0,6]=@amp0
; Put the enabled flag in an array so it can be indexed
f[0]=@flag0
; fBm level 2 (Note slightly different values q[1,0] and q[1,1])
ang=@ang1*d
q[1,0]=6079.0/8192.0
q[1,1]=5521.0/8192.0
q[1,2]=cos(ang)
q[1,3]=sin(ang)
q[1,4]=@frac1*@frac
q[1,5]=c*@rs1
q[1,6]=@amp1
f[1]=@flag1
; fBm level 3
ang=@ang2*d
q[2,0]=5501.0/8192.0
q[2,1]=6113.0/8192.0
q[2,2]=cos(ang)
q[2,3]=sin(ang)
q[2,4]=@frac2*@frac
q[2,5]=c*@rs2
q[2,6]=@amp2
f[2]=@flag2
; fBm level 4
ang=@ang3*d
q[3,0]=6047.0/8192.0
q[3,1]=5563.0/8192.0
q[3,2]=cos(ang)
q[3,3]=sin(ang)
q[3,4]=@frac3*@frac
q[3,5]=c*@rs3
q[3,6]=@amp3
f[3]=@flag3
; fBm level 5
ang=@ang4*d
q[4,0]=5507.0/8192.0
q[4,1]=6091.0/8192.0
q[4,2]=cos(ang)
q[4,3]=sin(ang)
q[4,4]=@frac4*@frac
q[4,5]=c*@rs4
q[4,6]=@amp4
f[4]=@flag4
; fBm level 6
ang=@ang5*d
q[5,0]=6037.0/8192.0
q[5,1]=5573.0/8192.0
q[5,2]=cos(ang)
q[5,3]=sin(ang)
q[5,4]=@frac5*@frac
q[5,5]=c*@rs5
q[5,6]=@amp5
f[5]=@flag5
; fBm level 7
ang=@ang6*d
q[6,0]=5531.0/8192.0
q[6,1]=6067.0/8192.0
q[6,2]=cos(ang)
q[6,3]=sin(ang)
q[6,4]=@frac6*@frac
q[6,5]=c*@rs6
q[6,6]=@amp6
f[6]=@flag6
; fBm level 8
ang=@ang7*d
q[7,0]=6131.0/8192.0
q[7,1]=5479.0/8192.0
q[7,2]=cos(ang)
q[7,3]=sin(ang)
q[7,4]=@frac7*@frac
q[7,5]=c*@rs7
q[7,6]=@amp7
f[7]=@flag7
; fBm level 9
ang=@ang8*d
q[8,0]=5503.0/8192.0
q[8,1]=6101.0/8192.0
q[8,2]=cos(ang)
q[8,3]=sin(ang)
q[8,4]=@frac8*@frac
q[8,5]=c*@rs8
q[8,6]=@amp8
f[8]=@flag8
; fBm level 10
ang=@ang9*d
q[9,0]=6133.0/8192.0
q[9,1]=5477.0/8192.0
q[9,2]=cos(ang)
q[9,3]=sin(ang)
q[9,4]=@frac9*@frac
q[9,5]=c*@rs9
q[9,6]=@amp9
f[9]=@flag9
; fBm level 11
ang=@ang10*d
q[10,0]=5557.0/8192.0
q[10,1]=6053.0/8192.0
q[10,2]=cos(ang)
q[10,3]=sin(ang)
q[10,4]=@frac10*@frac
q[10,5]=c*@rs10
q[10,6]=@amp10
f[10]=@flag10
; fBm level 12
ang=@ang11*d
q[11,0]=6029.0/8192.0
q[11,1]=5581.0/8192.0
q[11,2]=cos(ang)
q[11,3]=sin(ang)
q[11,4]=@frac11*@frac
q[11,5]=c*@rs11
q[11,6]=@amp11
f[11]=@flag11
; fBm level 13
ang=@ang12*d
q[12,0]=5527.0/8192.0
q[12,1]=6073.0/8192.0
q[12,2]=cos(ang)
q[12,3]=sin(ang)
q[12,4]=@frac12*@frac
q[12,5]=c*@rs12
q[12,6]=@amp12
f[12]=@flag12
; fBm level 14
ang=@ang13*d
q[13,0]=6121.0/8192.0
q[13,1]=5483.0/8192.0
q[13,2]=cos(ang)
q[13,3]=sin(ang)
q[13,4]=@frac13*@frac
q[13,5]=c*@rs13
q[13,6]=@amp13
f[13]=@flag13
; fBm level 15
ang=@ang14*d
q[14,0]=5569.0/8192.0
q[14,1]=6043.0/8192.0
q[14,2]=cos(ang)
q[14,3]=sin(ang)
q[14,4]=@frac14*@frac
q[14,5]=c*@rs14
q[14,6]=@amp14
f[14]=@flag14
; fBm level 16
ang=@ang15*d
q[15,0]=6089.0/8192.0
q[15,1]=5519.0/8192.0
q[15,2]=cos(ang)
q[15,3]=sin(ang)
q[15,4]=@frac15*@frac
q[15,5]=c*@rs15
q[15,6]=@amp15
f[15]=@flag15
; Now initialise the height arrays ready for fBm creation.
int r=@seed ; initialise the random variable
float r1=r
int l=0 ; level count
int step=16384 ; initially assume all fBm
while l<@levels
int i=0
while i<4
h[l,i,0]=0 ; set entry 0 to 0
h[l,i,16384]=0 ; and entry 16384
; If using Div 2, Div 4 or Div 8 initialise further array
; entries and adjust the binary step to be used later
; accordingly.
if @mode>0
h[l,i,8192]=0
step=8192
if @mode>1
r=random(r)
h[l,i,4096]=r/#randomrange
r=random(r)
h[l,i,12288]=r/#randomrange
step=4096
if @mode>2
r=random(r)
h[l,i,2048]=r/#randomrange
r=random(r)
h[l,i,6144]=r/#randomrange
r=random(r)
h[l,i,10240]=r/#randomrange
r=random(r)
h[l,i,14336]=r/#randomrange
step=2048
if @mode>3
r=random(r)
h[l,i,1024]=r/#randomrange
r=random(r)
h[l,i,3072]=r/#randomrange
r=random(r)
h[l,i,5120]=r/#randomrange
r=random(r)
h[l,i,7168]=r/#randomrange
r=random(r)
h[l,i,9216]=r/#randomrange
r=random(r)
h[l,i,11264]=r/#randomrange
r=random(r)
h[l,i,13312]=r/#randomrange
r=random(r)
h[l,i,15360]=r/#randomrange
step=1024
endif
endif
endif
endif
i=i+1
endwhile
l=l+1
endwhile
; Now calculate the number of extra (dummy) dice rolls to use
; (The dummy rolls mean the shape of the fBm will not change
; in great jumps as the number of dice used is changed -
; provided @dice is <= @dummy)
int nd=0
if @dummy>0
nd=@dummy-ceil(@dice)
if (nd<0 && (!@morph))||(nd<-1 && @morph)
$define DEBUG
print("Not enough dummy rolls")
$undef DEBUG
nd=0
endif
endif
; Now proceed with the actual fBm creation
l=0
float th=0 ; For the "Total height"
while l<@levels
i=0
while i<4
float rs=1.0 ; Initial fBm scale factor
int s=step ; initial step
float mx=0 ; for the maximum
float mn=0 ; for the minimum
while s>1 ; we've finished when s=1
int o=floor(s/2) ; offset is s/2
int p=o ; start index
while p<16384
; Now roll up the next random
if @morph
float nr=@dice
if nr<=@dummy
while nr>=1
r=random(r)
nr=nr-1
endwhile
r1=r
if nr>0
r=random(r)
r1=(1-nr)*r1+nr*r
endif
else
r=random(r)
r1=r
nr=nr-1
while nr>=1
r=random(r)
nr=nr-1
endwhile
r1=nr*r1+(1-nr)*r
endif
else
r1=0
float nr=@dice
while nr>=1
r=random(r)
r1=r1+r/#randomrange
nr=nr-1
endwhile
if nr>0
r=random(r)
r1=r1+nr*r/#randomrange
endif
r1=r1/@dice
endif
; Do any dummy rolls
int n=nd
while n>0
r=random(r)
n=n-1
endwhile
; Height = (previous+next)/2 + random*scale factor
; or cubic interpolation + random*scale factor
if @average==0
h[l,i,p]=(h[l,i,p-o]+h[l,i,p+o])/2+rs*r1
else
int w=(p-o-s)%16384
if w<0
w=w+16384
endif
float hh0=h[l,i,w]
float hh1=h[l,i,p-o]
float hh2=h[l,i,p+o]
w=(p+o+s)%16384
float hh3=h[l,i,w]
h[l,i,p]=(5*(hh1+hh2)-(hh0+hh3))/8+rs*r1
endif
; Check for max and min
if h[l,i,p]>mx
mx=h[l,i,p]
endif
if h[l,i,p]
public:
func MMF_TrapShapefBm(Generic pparent)
TrapShape.TrapShape(pparent)
texture = new @texture(this)
texture.GlobalInit(0)
endfunc
float func Iterate(complex pz)
TrapShape.Iterate(pz)
if @diviter=="Divide by Iterations"
return texture.GetfBm(pz/m_Iterations)
elseif @diviter=="Divide by Iterations^2"
return texture.GetfBm(pz/sqr(m_Iterations))
else
return texture.GetfBm(pz)
endif
endfunc
private:
MMF_AltfBm texture
default:
title = "MMF Alternative fBm Trap Shape"
int param v_mmftrapshapefbm
caption = "Trap Shape fBm (MMF)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
MMF_AltfBm param texture
caption = "Trap Texture"
default = MMF_AltfBm
endparam
int param diviter
caption = "Texture Density Reduction"
enum = "None" "Divide by Iterations" "Divide by Iterations^2"
default = 0
hint = "Sometimes the change in density of the texturing can be \
a bit high with respect to changes in iteration value. \
Use the divide options to somewhat reduce this."
endparam
}
class MMF_ExtendedColorMerge(common.ulb:DefaultColorMerge) {
;
; Extended colour merges.
; David Makin May 2008
;
; Anyone interested in merge modes may like to look here:
; http://www.pegtop.net/delphi/articles/blendmodes/
public:
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_ExtendedColorMerge(Generic pparent)
DefaultColorMerge.DefaultColorMerge(pparent)
endfunc
; @param pbottom the base color
; @param ptop the top color
; @return merged color
color func Merge(color pbottom, color ptop)
if @p_modeselect=="MMF Merge Modes"
if @clamp
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.0
r = 0.0
elseif r>1.0
r = 1.0
endif
if g<0.0
g = 0.0
elseif g>1.0
g = 1.0
endif
if b<0.0
b = 0.0
elseif b>1.0
b = 1.0
endif
ptop = rgba(r,g,b,alpha(ptop))
r = red(pbottom)
g = green(pbottom)
b = blue(pbottom)
if r<0.0
r = 0.0
elseif r>1.0
r = 1.0
endif
if g<0.0
g = 0.0
elseif g>1.0
g = 1.0
endif
if b<0.0
b = 0.0
elseif b>1.0
b = 1.0
endif
pbottom = rgba(r,g,b,alpha(pbottom))
endif
if @p_mmfmergemode=="Exclusion"
return rgba(red(pbottom) + red(ptop) - 2*red(pbottom)*red(ptop), \
green(pbottom) + green(ptop) - 2*green(pbottom)*green(ptop), \
blue(pbottom) + blue(ptop) - 2*blue(pbottom)*blue(ptop), \
alpha(ptop) )
elseif @p_mmfmergemode=="Fade Down"
return rgba( red(ptop) * (1 - red(ptop) + red(pbottom)), \
green(ptop) * (1 - green(ptop) + green(pbottom)), \
blue(ptop) * (1 - blue(ptop) + blue(pbottom)), alpha(ptop) )
elseif @p_mmfmergemode=="Fade Up"
return rgba(red(pbottom) + red(ptop)*(red(ptop) - red(pbottom)), \
green(pbottom) + green(ptop)*(green(ptop) - green(pbottom)), \
blue(pbottom) + blue(ptop)*(blue(ptop) - blue(pbottom)), \
alpha(ptop) )
elseif @p_mmfmergemode=="Contrast Down"
return rgba( 0.5 + red(ptop)*(red(pbottom) - 0.5), \
0.5 + green(ptop)*(green(pbottom) - 0.5), \
0.5 + blue(ptop)*(blue(pbottom) - 0.5), alpha(ptop) )
elseif @p_mmfmergemode=="Contrast Up"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = r - 2.0*red(ptop)*r*(0.5 - r)
else
r = r + 2.0*red(ptop)*(1.0 - r)*(r - 0.5)
endif
if g<0.5
g = g - 2.0*green(ptop)*g*(0.5 - g)
else
g = g + 2.0*green(ptop)*(1.0 - g)*(g - 0.5)
endif
if b<0.5
b = b - 2.0*blue(ptop)*b*(0.5 - b)
else
b = b + 2.0*blue(ptop)*(1.0 - b)*(b - 0.5)
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Dodge"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
float r = 1.0 - red(ptop)
float g = 1.0 - green(ptop)
float b = 1.0 - blue(ptop)
if red(pbottom)<=0
r = 0.0
elseif r<=0.0
r = 1.0
else
r = red(pbottom)/r
if r>1.0
r = 1.0
endif
endif
if green(pbottom)<=0
g = 0
elseif g<=0.0
g = 1.0
else
g = green(pbottom)/g
if g>1.0
g = 1.0
endif
endif
if blue(pbottom)<=0
b = 0
elseif b<=0.0
b = 1.0
else
b = blue(pbottom)/b
if b>1.0
b = 1.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Burn"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<=0.0
r = 0.0
else
r = 1.0 - (1.0 - red(pbottom))/r
if r<0.0
r = 0.0
endif
endif
if g<=0.0
g = 0.0
else
g = 1.0 - (1.0 - green(pbottom))/g
if g<0.0
g = 0.0
endif
endif
if b<=0.0
b = 0.0
else
b = 1.0 - (1.0 - blue(pbottom))/b
if b<0.0
b = 0.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Negation"
return rgba( 1.0 - abs(1.0 - red(ptop) - red(pbottom)), \
1.0 - abs(1.0 - green(ptop) - green(pbottom)), \
1.0 - abs(1.0 - blue(ptop) - blue(pbottom)), alpha(ptop) )
elseif @p_mmfmergemode=="Reflect"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
float r = 1.0 - red(ptop)
float g = 1.0 - green(ptop)
float b = 1.0 - blue(ptop)
if red(pbottom)<=0
r = 0.0
elseif r<=0.0
r = 1.0
else
r = sqr(red(pbottom))/r
if r>1.0
r = 1.0
endif
endif
if green(pbottom)<=0
g = 0.0
elseif g<=0.0
g = 1.0
else
g = sqr(green(pbottom))/g
if g>1.0
g = 1.0
endif
endif
if blue(pbottom)<=0
b = 0.0
elseif b<=0.0
b = 1.0
else
b = sqr(blue(pbottom))/b
if b>1.0
b = 1.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Freeze"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<=0.0
r = 0.0
else
r = 1.0 - sqr(1.0 - red(pbottom))/r
if r<0.0
r = 0.0
endif
endif
if g<=0.0
g = 0.0
else
g = 1.0 - sqr(1.0 - green(pbottom))/g
if g<0.0
g = 0.0
endif
endif
if b<=0.0
b = 0.0
else
b = 1.0 - sqr(1.0 - blue(pbottom))/b
if b<0.0
b = 0.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Rev. Contrast Down"
return rgba( 0.5 + (1.0 - red(ptop))*(red(pbottom) - 0.5), \
0.5 + (1.0 - green(ptop))*(green(pbottom) - 0.5), \
0.5 + (1.0 - blue(ptop))*(blue(pbottom) - 0.5), alpha(ptop) )
elseif @p_mmfmergemode=="Rev. Contrast Up"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = r - 2.0*(1.0 - red(ptop))*r*(0.5 - r)
else
r = r + 2.0*(1.0 - red(ptop))*(1.0 - r)*(r - 0.5)
endif
if g<0.5
g = g - 2.0*(1.0 - green(ptop))*g*(0.5 - g)
else
g = g + 2.0*(1.0 - green(ptop))*(1.0 - g)*(g - 0.5)
endif
if b<0.5
b = b - 2.0*(1.0 - blue(ptop))*b*(0.5 - b)
else
b = b + 2.0*(1.0 - blue(ptop))*(1.0 - b)*(b - 0.5)
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Fade"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = 2.0 * r * (0.5 - r + red(pbottom))
else
r = red(pbottom) + 2.0 * (r - 0.5)*(r - red(pbottom))
endif
if g<0.5
g = 2.0 * g * (0.5 - g + green(pbottom))
else
g = green(pbottom) + 2.0 * (g - 0.5)*(g - green(pbottom))
endif
if b<0.5
b = 2.0 * b * (0.5 - b + blue(pbottom))
else
b = blue(pbottom) + 2.0 * (b - 0.5)*(b - blue(pbottom))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Reverse Fade"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = red(pbottom) + 2.0 * r * (r - red(pbottom))
else
r = red(pbottom) + 2.0 * (1.0 - r)*(r - red(pbottom))
endif
if g<0.5
g = green(pbottom) + 2.0 * g * (g - green(pbottom))
else
g = green(pbottom) + 2.0 * (1.0 - g)*(g - green(pbottom))
endif
if b<0.5
b = blue(pbottom) + 2.0 * b * (b - blue(pbottom))
else
b = blue(pbottom) + 2.0 * (1.0 - b)*(b - blue(pbottom))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Contrast" || @p_mmfmergemode=="Reverse Contrast"
float r1 = red(ptop)
float g1 = green(ptop)
float b1 = blue(ptop)
if @p_mmfmergemode=="Reverse Contrast"
r1 = 1.0 - r1
g1 = 1.0 - g1
b1 = 1.0 - b1
endif
if r1<0.5
r1 = 0.5 + 2.0 * r1 * (red(pbottom) - 0.5)
else
r1 = 2.0 * (r1 - 0.5)
float r = red(pbottom)
if r<0.5
r1 = r - 2.0*r1*r*(0.5 - r)
else
r1 = r + 2.0*r1*(1.0 - r)*(r - 0.5)
endif
endif
if g1<0.5
g1 = 0.5 + 2.0 * g1 * (green(pbottom) - 0.5)
else
g1 = 2.0 * (g1 - 0.5)
float g = green(pbottom)
if g<0.5
g1 = g - 2.0*g1*g*(0.5 - g)
else
g1 = g + 2.0*g1*(1.0 - g)*(g - 0.5)
endif
endif
if b1<0.5
b1 = 0.5 + 2.0 * b1 * (blue(pbottom) - 0.5)
else
b1 = 2.0 * (b1 - 0.5)
float b = blue(pbottom)
if b<0.5
b1 = b - 2.0*b1*b*(0.5 - b)
else
b1 = b + 2.0*b1*(1.0 - b)*(b - 0.5)
endif
endif
return rgba(r1,g1,b1,alpha(ptop))
elseif @p_mmfmergemode=="Quantize"
int nr = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + red(ptop)) - 1.0)) - 1
int ng = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + green(ptop)) - 1.0)) - 1
int nb = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + blue(ptop)) - 1.0)) - 1
return rgba(floor(red(pbottom)*(nr+0.999))/nr, \
floor(green(pbottom)*(ng+0.999))/ng, \
floor(blue(pbottom)*(nb+0.999))/nb,alpha(ptop))
elseif @p_mmfmergemode=="Reverse Quantize"
int nr = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - red(ptop)) - 1.0)) - 1
int ng = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - green(ptop)) - 1.0)) - 1
int nb = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - blue(ptop)) - 1.0)) - 1
return rgba(floor(red(pbottom)*(nr+0.999))/nr, \
floor(green(pbottom)*(ng+0.999))/ng, \
floor(blue(pbottom)*(nb+0.999))/nb,alpha(ptop))
elseif @p_mmfmergemode=="Gamma"
return rgba(red(pbottom)^(@mingamma+(@maxgamma-@mingamma)*red(ptop)), \
green(pbottom)^(@mingamma+(@maxgamma-@mingamma)*green(ptop)), \
blue(pbottom)^(@mingamma+(@maxgamma-@mingamma)*blue(ptop)), \
alpha(ptop))
elseif @p_mmfmergemode=="Inverse Gamma"
return rgba(red(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*red(ptop))), \
green(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*green(ptop))), \
blue(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*blue(ptop))), \
alpha(ptop))
elseif @p_mmfmergemode=="Reverse Gamma"
return rgba(red(pbottom)^(@mingamma+(@maxgamma-@mingamma)*(1.0-red(ptop))), \
green(pbottom)^(@mingamma+(@maxgamma-@mingamma)*(1.0-green(ptop))), \
blue(pbottom)^(@mingamma+(@maxgamma-@mingamma)*(1.0-blue(ptop))), \
alpha(ptop))
elseif @p_mmfmergemode=="Rev. Inv. Gamma"
return rgba(red(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-red(ptop)))), \
green(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-green(ptop)))), \
blue(pbottom)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-blue(ptop)))), \
alpha(ptop))
elseif @p_mmfmergemode=="Combined Gamma"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = red(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-red(ptop)))
else
r = red(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(red(ptop)-0.5)))
endif
if g<0.5
g = green(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-green(ptop)))
else
g = green(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(green(ptop)-0.5)))
endif
if b<0.5
b = blue(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-blue(ptop)))
else
b = blue(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(blue(ptop)-0.5)))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Rev. Comb. Gamma"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = red(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-red(ptop))))
else
r = red(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(red(ptop)-0.5))
endif
if g<0.5
g = green(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-green(ptop))))
else
g = green(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(green(ptop)-0.5))
endif
if b<0.5
b = blue(pbottom)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-blue(ptop))))
else
b = blue(pbottom)^(@mingamma+2.0*(@maxgamma-@mingamma)*(blue(ptop)-0.5))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Stamp"
float r = red(pbottom) + 2.0*red(ptop) - 1.0
float g = green(pbottom) + 2.0*green(ptop) - 1.0
float b = blue(pbottom) + 2.0*blue(ptop) - 1.0
if r<0.0
r = 0.0
elseif r>1.0
r = 1.0
endif
if g<0.0
g = 0.0
elseif g>1.0
g = 1.0
endif
if b<0.0
b = 0.0
elseif b>1.0
b = 1.0
endif
return RGBA(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Soft Dodge"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<=0
r = 0
elseif r+red(ptop)<=1.0
if red(ptop)>=1.0
r = 1.0
elseif (r = 0.5*r/(1.0 - red(ptop)))>1.0
r = 1.0
endif
elseif (r = 1.0 - 0.5*(1.0 - red(ptop))/r)<0.0
r = 0.0
endif
if g<=0
g = 0
elseif g+green(ptop)<=1.0
if green(ptop)>=1.0
g = 1.0
elseif (g = 0.5*g/(1.0 - green(ptop)))>1.0
g = 1.0
endif
elseif (g = 1.0 - 0.5*(1.0 - green(ptop))/g)<0.0
g = 0.0
endif
if b<=0
b = 0
elseif b+blue(ptop)<=1.0
if blue(ptop)>=1.0
b = 1.0
elseif (b = 0.5*b/(1.0 - blue(ptop)))>1.0
b = 1.0
endif
elseif (b = 1.0 - 0.5*(1.0 - blue(ptop))/b)<0.0
b = 0.0
endif
return RGBA(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Soft Burn"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<=0
r = 0
elseif r+red(pbottom)<=1.0
if red(pbottom)>=1.0
r = 1.0
elseif (r = 0.5*r/(1.0 - red(pbottom)))>1.0
r = 1.0
endif
elseif (r = 1.0 - 0.5*(1.0 - red(pbottom))/r)<0.0
r = 0.0
endif
if g<=0
g = 0
elseif g+green(pbottom)<=1.0
if green(pbottom)>=1.0
g = 1.0
elseif (g = 0.5*g/(1.0 - green(pbottom)))>1.0
g = 1.0
endif
elseif (g = 1.0 - 0.5*(1.0 - green(pbottom))/g)<0.0
g = 0.0
endif
if b<=0
b = 0
elseif b+blue(pbottom)<=1.0
if blue(pbottom)>=1.0
b = 1.0
elseif (b = 0.5*b/(1.0 - blue(pbottom)))>1.0
b = 1.0
endif
elseif (b = 1.0 - 0.5*(1.0 - blue(pbottom))/b)<0.0
b = 0.0
endif
return RGBA(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Dodge"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
float r = 1.0 - red(pbottom)
float g = 1.0 - green(pbottom)
float b = 1.0 - blue(pbottom)
if red(ptop)<=0
r = 0
elseif r<=0.0
r = 1.0
else
r = red(ptop)/r
if r>1.0
r = 1.0
endif
endif
if green(ptop)<=0
g = 0
elseif g<=0.0
g = 1.0
else
g = green(ptop)/g
if g>1.0
g = 1.0
endif
endif
if blue(ptop)<=0
b = 0
elseif b<=0.0
b = 1.0
else
b = blue(ptop)/b
if b>1.0
b = 1.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Burn"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<=0.0
r = 0.0
else
r = 1.0 - (1.0 - red(ptop))/r
if r<0.0
r = 0.0
endif
endif
if g<=0.0
g = 0.0
else
g = 1.0 - (1.0 - green(ptop))/g
if g<0.0
g = 0.0
endif
endif
if b<=0.0
b = 0.0
else
b = 1.0 - (1.0 - blue(ptop))/b
if b<0.0
b = 0.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Glow"
; Here we clamp the maximum returned to 1.0 because of the special case
; when the color channel in ptop is one (or more).
float r = 1.0 - red(pbottom)
float g = 1.0 - green(pbottom)
float b = 1.0 - blue(pbottom)
if red(ptop)<=0
r = 0.0
elseif r<=0.0
r = 1.0
else
r = sqr(red(ptop))/r
if r>1.0
r = 1.0
endif
endif
if green(ptop)<=0
g = 0.0
elseif g<=0.0
g = 1.0
else
g = sqr(green(ptop))/g
if g>1.0
g = 1.0
endif
endif
if blue(ptop)<=0
b = 0.0
elseif b<=0.0
b = 1.0
else
b = sqr(blue(ptop))/b
if b>1.0
b = 1.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Heat"
; Here we clamp the minimum returned to 0 because of the special case
; when the color channel in ptop is zero (or less).
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<=0.0
r = 0.0
else
r = 1.0 - sqr(1.0 - red(ptop))/r
if r<0.0
r = 0.0
endif
endif
if g<=0.0
g = 0.0
else
g = 1.0 - sqr(1.0 - green(ptop))/g
if g<0.0
g = 0.0
endif
endif
if b<=0.0
b = 0.0
else
b = 1.0 - sqr(1.0 - blue(ptop))/b
if b<0.0
b = 0.0
endif
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Fade Down"
return rgba( red(pbottom) * (1 - red(pbottom) + red(ptop)), \
green(pbottom) * (1 - green(pbottom) + green(ptop)), \
blue(pbottom) * (1 - blue(pbottom) + blue(ptop)), alpha(ptop) )
elseif @p_mmfmergemode=="Inv. Fade Up"
return rgba(red(ptop) + red(pbottom)*(red(pbottom) - red(ptop)), \
green(ptop) + green(pbottom)*(green(pbottom) - green(ptop)), \
blue(ptop) + blue(pbottom)*(blue(pbottom) - blue(ptop)), \
alpha(ptop) )
elseif @p_mmfmergemode=="Inv. Contrast Down"
return rgba( 0.5 + red(pbottom)*(red(ptop) - 0.5), \
0.5 + green(pbottom)*(green(ptop) - 0.5), \
0.5 + blue(pbottom)*(blue(ptop) - 0.5), alpha(ptop) )
elseif @p_mmfmergemode=="Inv. Contrast Up"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = r - 2.0*red(pbottom)*r*(0.5 - r)
else
r = r + 2.0*red(pbottom)*(1.0 - r)*(r - 0.5)
endif
if g<0.5
g = g - 2.0*green(pbottom)*g*(0.5 - g)
else
g = g + 2.0*green(pbottom)*(1.0 - g)*(g - 0.5)
endif
if b<0.5
b = b - 2.0*blue(pbottom)*b*(0.5 - b)
else
b = b + 2.0*blue(pbottom)*(1.0 - b)*(b - 0.5)
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Con. Down"
return rgba( 0.5 + (1.0 - red(pbottom))*(red(ptop) - 0.5), \
0.5 + (1.0 - green(pbottom))*(green(ptop) - 0.5), \
0.5 + (1.0 - blue(pbottom))*(blue(ptop) - 0.5), alpha(ptop) )
elseif @p_mmfmergemode=="Inv. Rev. Con. Up"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if r<0.5
r = r - 2.0*(1.0 - red(pbottom))*r*(0.5 - r)
else
r = r + 2.0*(1.0 - red(pbottom))*(1.0 - r)*(r - 0.5)
endif
if g<0.5
g = g - 2.0*(1.0 - green(pbottom))*g*(0.5 - g)
else
g = g + 2.0*(1.0 - green(pbottom))*(1.0 - g)*(g - 0.5)
endif
if b<0.5
b = b - 2.0*(1.0 - blue(pbottom))*b*(0.5 - b)
else
b = b + 2.0*(1.0 - blue(pbottom))*(1.0 - b)*(b - 0.5)
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Fade"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = 2.0 * r * (0.5 - r + red(ptop))
else
r = red(ptop) + 2.0 * (r - 0.5)*(r - red(ptop))
endif
if g<0.5
g = 2.0 * g * (0.5 - g + green(ptop))
else
g = green(ptop) + 2.0 * (g - 0.5)*(g - green(ptop))
endif
if b<0.5
b = 2.0 * b * (0.5 - b + blue(ptop))
else
b = blue(ptop) + 2.0 * (b - 0.5)*(b - blue(ptop))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Fade"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = red(ptop) + 2.0 * r * (r - red(ptop))
else
r = red(ptop) + 2.0 * (1.0 - r)*(r - red(ptop))
endif
if g<0.5
g = green(ptop) + 2.0 * g * (g - green(ptop))
else
g = green(ptop) + 2.0 * (1.0 - g)*(g - green(ptop))
endif
if b<0.5
b = blue(ptop) + 2.0 * b * (b - blue(ptop))
else
b = blue(ptop) + 2.0 * (1.0 - b)*(b - blue(ptop))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Contrast" \
|| @p_mmfmergemode=="Inv. Rev. Contrast"
float r1 = red(pbottom)
float g1 = green(pbottom)
float b1 = blue(pbottom)
if @p_mmfmergemode=="Inv. Rev. Contrast"
r1 = 1.0 - r1
g1 = 1.0 - g1
b1 = 1.0 - b1
endif
if r1<0.5
r1 = 0.5 + 2.0 * r1 * (red(ptop) - 0.5)
else
r1 = 2.0 * (r1 - 0.5)
float r = red(ptop)
if r<0.5
r1 = r - 2.0*r1*r*(0.5 - r)
else
r1 = r + 2.0*r1*(1.0 - r)*(r - 0.5)
endif
endif
if g1<0.5
g1 = 0.5 + 2.0 * g1 * (green(ptop) - 0.5)
else
g1 = 2.0 * (g1 - 0.5)
float g = green(ptop)
if g<0.5
g1 = g - 2.0*g1*g*(0.5 - g)
else
g1 = g + 2.0*g1*(1.0 - g)*(g - 0.5)
endif
endif
if b1<0.5
b1 = 0.5 + 2.0 * b1 * (blue(ptop) - 0.5)
else
b1 = 2.0 * (b1 - 0.5)
float b = blue(ptop)
if b<0.5
b1 = b - 2.0*b1*b*(0.5 - b)
else
b1 = b + 2.0*b1*(1.0 - b)*(b - 0.5)
endif
endif
return rgba(r1,g1,b1,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Quantize"
int nr = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + red(pbottom)) - 1.0)) - 1
int ng = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + green(pbottom)) - 1.0)) - 1
int nb = round(@qmax - (@qmax-@qmin)*(2.0/(1.0 + blue(pbottom)) - 1.0)) - 1
return rgba(floor(red(ptop)*(nr+0.999))/nr, \
floor(green(ptop)*(ng+0.999))/ng, \
floor(blue(ptop)*(nb+0.999))/nb,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Quantize"
int nr = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - red(pbottom)) - 1.0)) - 1
int ng = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - green(pbottom)) - 1.0)) - 1
int nb = round(@qmax - (@qmax-@qmin)*(2.0/(2.0 - blue(pbottom)) - 1.0)) - 1
return rgba(floor(red(ptop)*(nr+0.999))/nr, \
floor(green(ptop)*(ng+0.999))/ng, \
floor(blue(ptop)*(nb+0.999))/nb,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Gamma"
return rgba(red(ptop)^(@mingamma+(@maxgamma-@mingamma)*red(pbottom)), \
green(ptop)^(@mingamma+(@maxgamma-@mingamma)*green(pbottom)), \
blue(ptop)^(@mingamma+(@maxgamma-@mingamma)*blue(pbottom)), \
alpha(ptop))
elseif @p_mmfmergemode=="Inv. Inverse Gamma"
return rgba(red(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*red(pbottom))), \
green(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*green(pbottom))), \
blue(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*blue(pbottom))), \
alpha(ptop))
elseif @p_mmfmergemode=="Inv. Reverse Gamma"
return rgba(red(ptop)^(@mingamma+(@maxgamma-@mingamma)*(1.0-red(pbottom))), \
green(ptop)^(@mingamma+(@maxgamma-@mingamma)*(1.0-green(pbottom))), \
blue(ptop)^(@mingamma+(@maxgamma-@mingamma)*(1.0-blue(pbottom))), \
alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Inv. Gamma"
return rgba(red(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-red(pbottom)))), \
green(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-green(pbottom)))), \
blue(ptop)^(1.0/(@mingamma+(@maxgamma-@mingamma)*(1.0-blue(pbottom)))), \
alpha(ptop))
elseif @p_mmfmergemode=="Inv. Combined Gamma"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = red(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-r))
else
r = red(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(r-0.5)))
endif
if g<0.5
g = green(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-g))
else
g = green(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(g-0.5)))
endif
if b<0.5
b = blue(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-b))
else
b = blue(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(b-0.5)))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inv. Rev. Comb. Gamma"
float r = red(pbottom)
float g = green(pbottom)
float b = blue(pbottom)
if r<0.5
r = red(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-r)))
else
r = red(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(r-0.5))
endif
if g<0.5
g = green(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-g)))
else
g = green(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(g-0.5))
endif
if b<0.5
b = blue(ptop)^(1.0/(@mingamma+2.0*(@maxgamma-@mingamma)*(0.5-b)))
else
b = blue(ptop)^(@mingamma+2.0*(@maxgamma-@mingamma)*(b-0.5))
endif
return rgba(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Inverse Stamp"
float r = red(ptop) + 2.0*red(pbottom) - 1.0
float g = green(ptop) + 2.0*green(pbottom) - 1.0
float b = blue(ptop) + 2.0*blue(pbottom) - 1.0
if r<0.0
r = 0.0
elseif r>1.0
r = 1.0
endif
if g<0.0
g = 0.0
elseif g>1.0
g = 1.0
endif
if b<0.0
b = 0.0
elseif b>1.0
b = 1.0
endif
return RGBA(r,g,b,alpha(ptop))
elseif @p_mmfmergemode=="Brightness (Yiq)"
float btop = 0.299*red(ptop) + 0.587*green(ptop) + 0.114*blue(ptop)
float bbtm = 0.299*red(pbottom) + 0.587*green(pbottom) \
+ 0.114*blue(pbottom)
if bbtm==0
return RGBA(btop,btop,btop,alpha(ptop))
else
pbottom = pbottom*(btop/bbtm)
return RGBA(red(pbottom),green(pbottom),blue(pbottom),alpha(ptop))
endif
elseif @p_mmfmergemode=="Colour (Inverse Yiq)"
float btop = 0.299*red(ptop) + 0.587*green(ptop) + 0.114*blue(ptop)
float bbtm = 0.299*red(pbottom) + 0.587*green(pbottom) \
+ 0.114*blue(pbottom)
if btop==0
return RGBA(bbtm,bbtm,bbtm,alpha(ptop))
else
pbottom = ptop*(bbtm/btop)
return RGBA(red(pbottom),green(pbottom),blue(pbottom),alpha(ptop))
endif
elseif @p_mmfmergemode=="Brightness (Custom)"
float btop = (@redlvl*red(ptop) + @greenlvl*green(ptop) \
+ @bluelvl*blue(ptop))/(@redlvl + @greenlvl +@bluelvl)
float bbtm = (@redlvl*red(pbottom) + @greenlvl*green(pbottom) \
+ @bluelvl*blue(pbottom))/(@redlvl + @greenlvl +@bluelvl)
if bbtm==0
return RGBA(btop,btop,btop,alpha(ptop))
else
pbottom = pbottom*(btop/bbtm)
return RGBA(red(pbottom),green(pbottom),blue(pbottom),alpha(ptop))
endif
elseif @p_mmfmergemode=="Colour (Custom)"
float btop = (@redlvl*red(ptop) + @greenlvl*green(ptop) \
+ @bluelvl*blue(ptop))/(@redlvl + @greenlvl +@bluelvl)
float bbtm = (@redlvl*red(pbottom) + @greenlvl*green(pbottom) \
+ @bluelvl*blue(pbottom))/(@redlvl + @greenlvl +@bluelvl)
if btop==0
return RGBA(bbtm,bbtm,bbtm,alpha(ptop))
else
pbottom = ptop*(bbtm/btop)
return RGBA(red(pbottom),green(pbottom),blue(pbottom),alpha(ptop))
endif
elseif @p_mmfmergemode=="Pin Light"
float r = red(ptop)
float g = green(ptop)
float b = blue(ptop)
if (r>=0.5 && r
; David Makin May 2008
;
; Anyone interested in merge modes may like to look here:
; http://www.pegtop.net/delphi/articles/blendmodes/
public:
;
; David Makin May 2008
;
public:
; @param pparent the parent,generally "this" for the parent, or zero
func MMF_MixedLighting(Generic pparent)
DirectColoring(pparent)
fBm = new @fBm(this)
transfbm = new @transfbm(this)
trans = new @trans(this)
ltrans = new @ltrans(this)
merge = new @merge(this)
trap = new @trap(this)
if @perturb && @usefbm
fBm.GlobalInit(0)
endif
endfunc
; @param pz the initial z value
; @param ppixel the location, usually #pixel
func Init(complex pz,complex ppixel)
if !@usefbm
transfbm.Init(pz)
endif
trans.Init(pz)
ltrans.Init(pz)
trap.init(pz)
if @InitfBm=="Pixel"
fBmInit = 4.0*ppixel
elseif @InitfBm=="Initial z"
fBmInit = 4.0*pz
endif
endfunc
; @param pz the z value
; @return a colour
color func Result(complex pz)
float v = @ambient + (1.0 - @ambient)*imag(pz)
if @mode!=1
if @perturb
if @InitfBm!="Colour and Light"
if @usefbm
v = @str*transfbm.Iterate(fBm.GetfBm(fBmInit)) \
+ (1.0-@str)*ltrans.Iterate(v)
else
v = @str*transfbm.Iterate(trap.Iterate(fBmInit)) \
+ (1.0-@str)*ltrans.Iterate(v)
endif
else
if @usefbm
v = @str*transfbm.Iterate(fBm.GetfBm(100*pz)) \
+ (1.0-@str)*ltrans.Iterate(v)
else
v = @str*transfbm.Iterate(trap.Iterate(100*pz)) \
+ (1.0-@str)*ltrans.Iterate(v)
endif
endif
elseif @v_MixedLighting>0
v = ltrans.Iterate(v)
endif
if @invert
v = 1.0 - v
endif
if @lpos
v = abs(v)
endif
endif
if @mode<2
float b = trans.Iterate(real(pz))
if @pos0
b = abs(b)
endif
color c = gradient(b)
if @mode==0
color l = @lightcol*v
l = rgba(red(l), green(l), blue(l), @lightop)
if @reverse
return merge.FullMerge(l,c,@opacity)
else
return merge.FullMerge(c,l,@opacity)
endif
else
return c
endif
elseif @mode==2
color l = @lightcol*v
return rgba(red(l), green(l), blue(l), @lightop)
elseif @mode==3
return gradient(0.9975*v)
else
float b = trans.iterate(real(pz))
; if @v_MixedLighting=="1.0"
; b = trans.iterate(real(#z)) ; NB. using #z here was a mistake in v1.0
; endif
if @pos
b = abs(b)
endif
; if @v_MixedLighting!="1.0"
if !@lrept
if v<0.0
v = 0.0
elseif v>1.0
v = 1.0
endif
endif
v = v*0.99999 ; so the %1 won't wrap to 0 for 1
; endif
if !@rept
if b<0.0
b = 0.0
elseif b>0.99999
b = 0.99999
endif
endif
; if @v_MixedLighting=="1.0"
; v = 0.5 + 0.4975*v
; b = 0.4975*(b%1)
; else
if (v = v%1)<0
v = 1.0 + v
endif
if (b = b%1)<0
b = 1.0 + b
endif
v = 0.5 + 0.4975*v
b = 0.4975*b
; endif
if @reverse
return merge.FullMerge(gradient(v),gradient(b),@opacity)
else
return merge.FullMerge(gradient(b),gradient(v),@opacity)
endif
endif
endfunc
private:
DefaultColorMerge merge
Transfer transfbm
Transfer trans
Transfer ltrans
MMF_AltfBm fBm
TrapShape trap
complex fBmInit
default:
title = "MMF Mixed Lighting (direct)"
heading
text = "Intended for use with the 'MMF Gradient Slope' class formula."
endheading
int param v_MixedLighting
caption = "Version (MMF Mixed Lighting)"
enum = "1.1" "1.2"
default = 1
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number. Version 1.2 enables the 'Light \
transfer' when not using perturbation."
visible = @v_MixedLighting<1
endparam
int param mode
caption = "Method"
enum = "Mixed" "Just colouring" "Lighting (greyscale)" \
"Lighting (gradient)" "Split Palette"
default =0
hint = "In 'Split Palette' mode colours 0 to 199 in the palette are used \
for the colouring and colours 200 to 399 are used for the \
lighting allowing coloured lighting combined with the base \
colouring. Note that this \
mode will only work properly with 'Color Density' set to 1, \
'Transfer Function' set to Linear and 'Gradient Offset' set to 0. \
Also note that to avoid hard colour breaks colour 0 should be the \
same as colour 199 if the colouring wraps and colour 200 should \
be the same as colour 399 if the lighting wraps."
endparam
heading
caption = "Combined parameters"
visible = @mode==0 || @mode==4
endheading
DefaultColorMerge param merge
caption = "Merge method"
default = MMF_ExtendedColorMerge
visible = @mode==0 || @mode==4
endparam
float param opacity
caption = "Merge Opacity"
default = 1.0
visible = @mode==0 || @mode==4
endparam
bool param reverse
caption = "Reverse colour and light"
default = false
hint = "Normally the lighting is applied as the top layer in the merge, \
enable this to reverse the order so the colouring is the top \
layer."
visible = @mode==0 || @mode==4
endparam
heading
caption = "Colouring parameters"
visible = @mode<2 || @mode==4
endheading
Transfer param trans
caption = "Colouring transfer"
default = DefaultGradientTransfer
hint = "Note that normally you should ensure that the returned value is \
positive."
visible = @mode<2 || @mode==4
endparam
bool param pos0
caption = "Force Positive Colour"
default = false
hint = "When enabled the absolute value of the colour is taken."
visible = @mode<2
endparam
bool param pos
caption = "Force Positive Colour"
default = true
hint = "When enabled the absolute value of the colour is taken."
visible = @mode==4
endparam
bool param rept
caption = "Repeat Colouring"
default = true
hint = "Allows you to specify whether the colouring value should be \
allowed to wrap around the gradient or not."
visible = @mode==4
endparam
heading
caption = "Lighting parameters"
visible = @mode!=1
endheading
color param lightcol
caption = "Light Colour"
default = rgb(1.0, 1.0, 1.0)
hint = "Sets the colour of the light."
visible = @mode==0 || @mode==2
endparam
float param lightop
caption = "Light Opacity"
default = 1.0
hint = "Sets the opacity of the light."
visible = @mode==0 || @mode==2
endparam
float param ambient
caption = "Ambient Light"
default = 0.0
min = -1.0
max = 1.0
hint = "Note that this will combine with any ambient light setting in the \
main formula."
visible = @mode!=1
endparam
bool param invert
caption = "Invert lighting"
default = false
visible = @mode!=1
endparam
bool param perturb
caption = "Perturb the lighting"
default = false
hint = "When enabled you can perturb the light values using fBm."
visible = @mode!=1
endparam
int param InitfBm
caption = "Perturbation initialisation"
enum = "Pixel" "Initial z" "Colour and Light"
default = 0
endparam
float param str
caption = "Perturbation strength"
default = 0.5
min = 0.0
max = 1.0
hint = "Using 0.0 will produce no perturbation, using 1.0 will produce \
fBm only as the lighting."
visible = @mode!=1 && @perturb
endparam
bool param usefbm
caption = "Use Plain Alternative fBm ?"
default = true
hint = "If you disable this then you'll get a choice of plug-ins."
visible = @mode!=1 && @perturb
endparam
MMF_AltfBm param fBm
caption = "Perturbation"
default = MMF_AltfBm
visible = @mode!=1 && @perturb && @usefbm
endparam
Trapshape param trap
caption = "Perturbation"
default = MMF_TrapShapefBm
visible = @mode!=1 && @perturb && !@usefbm
endparam
Transfer param transfbm
caption = "Perturbation transfer"
default = NullTransfer
hint = "Normally transfers that take a number in the range 0..1 and \
return a number in the range 0..1 should be used."
visible = @mode!=1 && @perturb
endparam
Transfer param ltrans
caption = "Light transfer"
default = NullTransfer
hint = "Normally transfers that take a number in the range 0..1 and \
return a number in the range 0..1 should be used."
visible = @mode!=1
endparam
bool param lpos
caption = "Force Positive Light"
default = false
hint = "When enabled the absolute value of the light is taken."
visible = @mode!=1
endparam
bool param lrept
caption = "Repeat Lighting"
default = false
hint = "Allows you to specify whether the lighting value should be \
allowed to wrap around the gradient or not."
visible = @mode==4
endparam
}
class MMF_ImageImport(common.ulb:ImageWrapper) {
public:
func MMF_ImageImport(Generic pparent)
ImageWrapper.ImageWrapper(pparent)
m_ImportedImage = new @p_importedimage
if @p_seamless && @p_wrap && @p_twotile
m_TileImage = new @p_tileimage
endif
m_Transform = new @p_transform(this)
m_Transform.Init(0)
m_Transform1 = new @p_transform1(this)
m_Transform1.Init(0)
m_fbm = new @p_fbm(this)
m_fbm.GlobalInit(0)
if @adjustlayer
if @v_imageimport<101
m_Adjust = new @f_adjust(this)
else
m_Adjustment = new @f_adjustment(this)
endif
endif
if !getEmpty() && @p_seamless
m_Widthm1 = getWidth()
m_Heightm1 = getHeight()
m_InvWidth = 1.0/m_Widthm1
m_InvHeight = 1.0/m_Heightm1
m_Widthm1 = m_Widthm1 - 1.0
m_Heightm1 = m_Heightm1 - 1.0
if @p_wrap && @p_twotile
m_tWidthm1 = m_TileImage.getWidth()
m_tHeightm1 = m_TileImage.getHeight()
m_tInvWidth = 1.0/m_tWidthm1
m_tInvHeight = 1.0/m_tHeightm1
m_tWidthm1 = m_tWidthm1 - 1.0
m_tHeightm1 = m_tHeightm1 - 1.0
endif
m_i[0]=7
m_i[1]=11
m_i[2]=12
m_i[3]=13
m_i[4]=17
endif
if @p_seedit
srand(@p_seed)
endif
endfunc
func fold(complex &pz, float &x, float &y, float &u, int &q, int &r, int &s)
x = real(pz)
u = -1.0
y = 1.0
s = random(@p_seed)
q = 0
while xy
q = q + 1
if x1.0
y = 1.0
endif
else
x = 2.0*y - x
u = y - abs(s=random(s+@p_seed))/(0.6*#randomrange)-0.1
if u<-1.0
u = -1.0
endif
endif
endwhile
if real(pz)<0.0
q = -q
endif
y = imag(pz)
pz = ((x+1.0)%2.0)-1.0
x = y
u = -1.0
y = 1.0
s = random(@p_seed)
r = 0
while xy
r = r + 1
if x1.0
y = 1.0
endif
else
x = 2.0*y - x
u = y - abs(s=random(s+347))/(0.8*#randomrange)-0.1
if u<-1.0
u = -1.0
endif
endif
endwhile
if imag(pz)>=0
r = -r
endif
pz = pz - flip(((1.0-x)%2.0)-1.0)
endfunc
color func getColor(complex pz)
if getEmpty()
return rgba(0,0,0,0)
endif
complex pz1
complex pz2
complex pz3
complex tpz
float x
float y
float u
float xg = @p_xgutter
float yg = @p_ygutter
float xo = @p_xoff
float yo = @p_yoff
int p[5]
int t[5]
int q
int r
int s
if @p_tile && @p_seamless && @p_wrap && @p_usefbm
pz = m_fbm.GetfBm(pz)+flip(m_fbm.GetfBm(flip(pz)))
endif
pz = m_Transform.Iterate(pz)
if @p_maintainaspect
pz = NormalizePixel(pz)
endif
color temp
if @p_tile
if @p_iterate
pz1 = pz
fold(pz,x,y,u,q,r,s)
x = real(pz1)
y = -imag(pz1)
else
x = real(pz)
y = -imag(pz)
endif
if @p_seamless && @p_wrap && @p_twotile
q = floor(((x+1.0)%10.0)/2.0)
r = floor(((1.0+y)%10.0)/2.0)
if q<0
q = 5+q
endif
if r<0
r = 5+r
endif
q = 1+2*r+q
r = 0
repeat
s=(q+2*floor(0.2*m_i[r]+0.01)+m_i[r])%5
if (s==0 && @p_patterny>=2) || (s==1 && @p_patternx>=4) \
|| (s==2 && (@p_patternx%4)>=2) || (s==3 && (@p_patternx%2)) \
|| (s==4 && (@p_patterny%2))
p[r] = 1
else
p[r] = 0
endif
until (r=r+1)>=5
endif
if @p_iterate
x = real(pz1)
y = -imag(pz1)
u = (x+1.0)%2.0
q = round(0.5*(x+1.4-u))
if u<0.0
q = q-1
endif
u = (1.0+y)%2.0
s = round(0.5*(y + 1.4 - u))
if u<0.0
s = s-1
endif
x = real(pz)
y = -imag(pz)
endif
u = (x+1.0)%2.0
if !@p_iterate
q = round(0.5*(x+1.4-u))
endif
if u<0.0
if !@p_iterate
q = q-1
endif
x = u + 1.0
else
x = u - 1.0
endif
u = (1.0+y)%2.0
if !@p_iterate
s = round(0.5*(y + 1.4 - u))
endif
if u<0.0
if !@p_iterate
s = s-1
endif
y = u + 1.0
else
y = u - 1.0
endif
if @p_seamless && @p_wrap && @p_twotile && @p_advanced
if @p_random
r = 0
repeat
t[r] = random((random(q+(m_i[r]%5)+12345678)%65536)+93427-@p_seed)
if (t[r]%65536)>((u=random((random(s+floor(0.2*m_i[r]+0.01)+12345678)%65536)*@p_seed))%65536)
p[r] = (p[r]+1)%2
endif
t[r] = random(t[r]+random(round(u)))
until (r=r+1)>=5
else
r = 0
repeat
t[r] = 0
until (r=r+1)>=5
endif
endif
pz = x - flip(y)
endif
pz = m_Transform1.Iterate(pz)
if @p_retile && @p_tile
x = (real(pz)+1.0)%2.0
if x<0.0
x = x + 1.0
else
x = x - 1.0
endif
y = (1.0-imag(pz))%2.0
if y<0.0
y = y + 1.0
else
y = y - 1.0
endif
pz = x - flip(y)
endif
if @p_mirror
if @p_flip
pz = -pz
else
pz = -conj(pz)
endif
elseif @p_flip
pz = conj(pz)
endif
if @p_seamless && @p_wrap
if @p_twotile
if @p_iterate
x = (real(pz1)+1.0)%2.0
if x<0.0
x = x + 1.0
else
x = x - 1.0
endif
y = (1.0-imag(pz1))%2.0
if y<0.0
y = y + 1.0
else
y = y - 1.0
endif
pz3 = x - flip(y)
if p[2]
tpz = (real(pz)*m_tWidthm1 - 1.0)*m_tInvWidth \
+ flip((imag(pz)*m_tHeightm1 + 1.0)*m_tInvHeight)
else
tpz = (real(pz)*m_Widthm1 - 1.0)*m_InvWidth \
+ flip((imag(pz)*m_Heightm1 + 1.0)*m_InvHeight)
endif
else
pz3 = pz
endif
if p[2]
pz = (real(pz3)*m_tWidthm1 - 1.0)*m_tInvWidth \
+ flip((imag(pz3)*m_tHeightm1 + 1.0)*m_tInvHeight)
else
pz = (real(pz3)*m_Widthm1 - 1.0)*m_InvWidth \
+ flip((imag(pz3)*m_Heightm1 + 1.0)*m_InvHeight)
endif
r = s = 0
if @p_advanced
r = random(@p_seed)
if real(pz)<0
if p[1]==0
r = random(r+t[1])
if p[2]==0
r = random(r+t[2])
xg = @p_xgutter00
xo = @p_xoff00
else
xg = @p_xgutter01
xo = @p_xoff01
endif
elseif p[2]==0
r = random(r+@p_seed+t[2]+657321)
xg = @p_xgutter10
xo = @p_xoff10
else
xg = @p_xgutter11
xo = @p_xoff11
endif
elseif p[2]==0
r = random(r+t[2])
if p[3]==0
r = random(r+t[3])
xg = @p_xgutter00
xo = @p_xoff00
else
xg = @p_xgutter01
xo = @p_xoff01
endif
elseif p[3]==0
r = random(r+@p_seed+t[3]+657321)
xg = @p_xgutter10
xo = @p_xoff10
else
xg = @p_xgutter11
xo = @p_xoff11
endif
if @p_rand
xg = @p_gbasex + (@p_gmaxx-@p_gbasex)*abs(r=random(r))/#randomrange
xo = abs((r=random(r))/#randomrange)
endif
s = random(@p_seed+564863)
if imag(pz)>=0
if p[0]==0
s = random(s + t[0])
if p[2]==0
s = random(s+t[2])
yg = @p_ygutter00
yo = @p_yoff00
else
yg = @p_ygutter01
yo = @p_yoff01
endif
elseif p[2]==0
s = random(s+t[2]+6847334)
yg = @p_ygutter10
yo = @p_yoff10
else
yg = @p_ygutter11
yo = @p_yoff11
endif
elseif p[2]==0
s = random(s+t[2])
if p[4]==0
s = random(s+t[4])
yg = @p_ygutter00
yo = @p_yoff00
else
yg = @p_ygutter01
yo = @p_yoff01
endif
elseif p[4]==0
s = random(s+t[4]+6847334)
yg = @p_ygutter10
yo = @p_yoff10
else
yg = @p_ygutter11
yo = @p_yoff11
endif
if @p_rand
yg = @p_gbasey + (@p_gmaxy-@p_gbasey)*abs(s=random(s))/#randomrange
yo = abs((s=random(s))/#randomrange)
r = random(r)
s = random(s)
else
r = s = 0
endif
endif
if @p_iterate
pz = tpz
tpz = pz3
endif
pz1 = pz3+flip(1.0-yo*(1.0-yg))
pz2 = pz3+1.0-xo*(1.0-xg)
pz3 = pz3+1.0-xo*(1.0-xg)+flip(1.0-yo*(1.0-yg))
x = (real(pz1)+1.0)%2.0
if x<0.0
x = x + 1.0
else
x = x - 1.0
endif
y = (1.0-imag(pz1))%2.0
if y<0.0
y = y + 1.0
else
y = y - 1.0
endif
pz1 = x - flip(y)
x = (real(pz2)+1.0)%2.0
if x<0.0
x = x + 1.0
else
x = x - 1.0
endif
y = (1.0-imag(pz2))%2.0
if y<0.0
y = y + 1.0
else
y = y - 1.0
endif
pz2 = x - flip(y)
x = (real(pz3)+1.0)%2.0
if x<0.0
x = x + 1.0
else
x = x - 1.0
endif
y = (1.0-imag(pz3))%2.0
if y<0.0
y = y + 1.0
else
y = y - 1.0
endif
pz3 = x - flip(y)
else
pz1 = conj(pz)
pz2 = -conj(pz)
pz3 = -pz
pz = (real(pz)*m_Widthm1 - 1.0)*m_InvWidth \
+ flip((imag(pz)*m_Heightm1 + 1.0)*m_InvHeight)
endif
elseif @p_seamless
pz = (real(pz)*m_Widthm1 - 1.0)*m_InvWidth \
+ flip((imag(pz)*m_Heightm1 + 1.0)*m_InvHeight)
endif
color clr = m_ImportedImage.getColor(pz)
color clr1
if @p_seamless && @p_wrap
if @p_twotile
if p[2]
clr = m_TileImage.getColor((real(pz)*m_tWidthm1 - 1.0)*m_tInvWidth \
+ flip((imag(pz)*m_tHeightm1 + 1.0)*m_tInvHeight))
endif
endif
if @p_twotile && @p_iterate
pz = tpz
endif
x=abs(1.0-abs(real(pz)))
y=abs(1.0-abs(imag(pz)))
if x
; Updated May 2009
; This is an extension of Damien's Cilia colouring.
; Original mmf3 formula November 2004
; Updated May 2009
;
public:
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_ExtendedCilia(Generic pparent)
float rv = @rot*@split^-@rpwr
float crv = @crot*@csplit^-@crpwr
int gi = 0
il = real(1.0/log(@power)) ; for divergent smoothing
lp = log(0.5*log(@bailout))
ilp = il*lp
cil = real(1.0/log(@cpower)) ; for convergent smoothing
clp = log(-0.5*log(@smallbail))
cilp = cil*clp
iv = 0.0001*@iterval*@iterweight
ivc = 0.0001*@citerval*@iterweightc
iw = 1.0 - 0.01*@iterweight
iwc = 1.0 - 0.01*@iterweightc
co = 0.0025*@convoffset
if @ciliamode!=6 && @ciliamode!=7
if @fixrot
repeat
rv = @split*rv
rval[gi] = rv = rv - floor(rv)
until (gi=gi+1)>#maxiter
if @fixskew && @skew!=0.0
rv = 0.0
gi = 0
repeat
rval[gi] = rval[gi] + rv
rv = (rv + @skew)*@split
rv = rv - floor(rv)
until (gi=gi+1)>#maxiter
endif
endif
if @cfixrot
gi = 0
repeat
crv = @csplit*crv
crval[gi] = crv = crv - floor(crv)
until (gi=gi+1)>#maxiter
if @cfixskew && @cskew!=0.0
crv = 0.0
gi = 0
repeat
crval[gi] = crval[gi] + crv
crv = (crv + @cskew)*@csplit
crv = crv - floor(crv)
until (gi=gi+1)>#maxiter
endif
endif
endif
if @mapimage
m_Image = new @f_image(this)
m_Transform = new @f_transform(this)
if @iterval>0
m_Merge = new @f_merge(this)
endif
if (@method==0 || @method==2 || @method==3 || @method>4) \
&& @mapmethod!="Image All" && @v_mmfextendedcilia>=3 && @usegradient
usergradient = new @usergradient(this)
endif
if @adjustlayer
m_Adjust = new @f_adjust(this)
endif
endif
if @mapimagec
m_Imagec = new @f_imagec(this)
m_Transformc = new @f_transformc(this)
if @citerval>0 || @zbasin>0
m_Mergec = new @f_mergec(this)
endif
if (@method==1 || @method==2 || @method>3) \
&& @mapmethodc!="Image All" && @v_mmfextendedcilia>=3 && @usegradientc
usergradientc = new @usergradientc(this)
endif
if @adjustlayerc
m_Adjustc = new @f_adjustc(this)
endif
endif
endfunc
; @param pz the initial z value
; @param ppixel the location, normally #pixel
func Init(complex pz, complex ppixel)
GradientColoring.Init(pz, ppixel)
if @mapimage
m_Transform.Init(pz)
endif
if @mapimagec
m_Transformc.Init(pz)
endif
z1 = z2 = z3 = z4 = z5 = z6 = pz
endfunc
; @param pz the z value
func Iterate(complex pz)
GradientColoring.Iterate(pz)
z6 = z5
z5 = z4
z4 = z3; save them
z3 = z2
z2 = z1
z1 = pz
endfunc
; @param pz the z value
; @return colour gradient index value
float func ResultIndex(complex pz)
float d1 = 0.0
float d2 = 0.0
float od = 0.0
float of = 0.0
float fz = 0.0
float fz1 = 0.0
float fz4 = 0.0
float fz5 = 0.0
float r = 0.0
float or = 0.0
float s = 0.0
int cm = 0
int oi = 0
float ivuse = 0.0
float iwuse = 0.0
int li = 0
bool usebasins = false
bool isstandard = true
int it = m_iterations + 1
float d = 0.0
float f = 0.0
float o = 0.0
iterbasin = 0.0
; determine potential and decomposition
; this gives us a "coordinate" in d and f, ranging from 0 to 1
f = real(pz); fractional iteration if using Hinrich's smoothing
fz = imag(pz) ; atan2(finalz) if using Hinrich's+Atan
d1 = |pz|
if @cfixed
d2 = |pz-@cfixedval|
else
d2 = |pz-z1|
endif
if f<0 && d1<@bailout && (@method==4 || @method==5 || @method==6)
usebasins = true
isstandard = false
o = co
f = 1.0+@fudge1c*f
IF (@colditer == 0)
z6 = z3
z5 = z2
z4 = z1
ELSEIF (@colditer == 1)
z6 = z4
z5 = z3
z4 = z2
ELSEIF (@colditer == 2)
z6 = z5
z5 = z4
z4 = z3
ENDIF
fz1 = atan2(z1 - z2)
fz4 = atan2(z4 - z5)
fz5 = atan2(z5 - z6)
if @fixconv
d1 = #pi - atan2(z1)
fz = fz + d1
fz1 = fz1 + d1
fz4 = fz4 + d1
fz5 = fz5 + d1
endif
if @cfixrot && @cciliamode!=6 && @cciliamode!=7
r = crval[it]
or = crval[it-1]
else
r = @crot
endif
s = @cskew
cm = @cciliamode
oi = @colditer
ivuse = ivc
iwuse = iwc
li = @logiterc
wasdivergent = false
elseif d1>=@bailout && (@method==0 || @method==2 || @method==6)
IF (@olditer == 0)
z6 = z3
z5 = z2
z4 = z1
ELSEIF (@olditer == 1)
z6 = z4
z5 = z3
z4 = z2
ELSEIF (@olditer == 2)
z6 = z5
z5 = z4
z4 = z3
ENDIF
if @dauto && it>1
f = 1.0 + @fudge*real(lp - log(0.5*log(|pz|)))/log(log(|pz|)/log(|z1|))
else
f = 1.0 + @fudge*real(ilp - il*log(0.5*log(|pz|)))
endif
fz = atan2(pz)
fz1 = atan2(z1)
fz4 = atan2(z4)
fz5 = atan2(z5)
if @fixrot && @ciliamode!=6 && @ciliamode!=7
r = rval[it]
or = rval[it-1]
else
r = @rot
endif
s = @skew
cm = @ciliamode
oi = @olditer
ivuse = iv
iwuse = iw
li = @logiter
wasdivergent = true
elseif f>=0 && d2>@smallbail && d1<@bailout \
&& (@method==3 || @method==5 || @method==7)
isstandard = false
f = @fudge1*f
IF (@olditer == 0)
z6 = z3
z5 = z2
z4 = z1
ELSEIF (@olditer == 1)
z6 = z4
z5 = z3
z4 = z2
ELSEIF (@olditer == 2)
z6 = z5
z5 = z4
z4 = z3
ENDIF
fz1 = atan2(z1)
fz4 = atan2(z4)
fz5 = atan2(z5)
if @fixrot && @ciliamode!=6 && @ciliamode!=7
r = rval[it]
or = rval[it-1]
else
r = @rot
endif
s = @skew
cm = @ciliamode
oi = @olditer
ivuse = iv
iwuse = iw
li = @logiter
wasdivergent = true
elseif d2<=@smallbail && (@method==1 || @method==2 || @method==7)
usebasins = true
o = co
IF (@colditer == 0)
z6 = z3
z5 = z2
z4 = z1
ELSEIF (@colditer == 1)
z6 = z4
z5 = z3
z4 = z2
ELSEIF (@colditer == 2)
z6 = z5
z5 = z4
z4 = z3
ENDIF
if @cfixed
if @cauto && it>2
f = 1.0 + @fudgec*real(clp - log(-0.5*log(|pz-@cfixedval|))) \
/log(log(|pz-@cfixedval|)/log(|z1-@cfixedval|))
else
f = 1.0 + @fudgec*real(cilp - cil*log(-0.5*log(|pz-@cfixedval|)))
endif
elseif @cauto && it>2
f = 1.0 + @fudgec*real(clp - log(-0.5*log(|pz-z1|))) \
/log(log(|pz-z1|)/log(|z1-z2|))
else
f = 1.0 + @fudgec*real(cilp - cil*log(-0.5*log(|pz-z1|)))
endif
fz = atan2(pz - z1)
fz1 = atan2(z1 - z2)
fz4 = atan2(z4 - z5)
fz5 = atan2(z5 - z6)
if @fixconv
d1 = #pi - atan2(pz)
fz = fz + d1
fz1 = fz1 + d1
fz4 = fz4 + d1
fz5 = fz5 + d1
endif
if @cfixrot && @cciliamode!=6 && @cciliamode!=7
r = crval[it]
or = crval[it-1]
else
r = @crot
endif
s = @cskew
cm = @cciliamode
oi = @colditer
ivuse = ivc
iwuse = iwc
li = @logiterc
wasdivergent = false
else
m_solid = true
wasdivergent = true
if @v_mmfextendedcilia>0
return 0
endif
endif
if cm>7 && cm!=14
of = 1-f ; this is the cheating method !!
if (oi<4)
od = fz5; angle of z
else
od = fz1; angle of z
endif
if (od < 0); it's negative
od = od + #pi * 2; make it positive
endif
od = od / (#pi * 2); scale so full angle range is 0..1
; apply rotation and skew
od = od + or + s*of
od = od - floor(od)
; convert decomp and pot to tileable value d
; this is where the patterns are made
IF cm==8; sawtooth
IF (od < 0.5)
od = od * (of+1.0)
ELSE
od = (od-0.5) * (of+1.0) - 0.5*of + 0.5
ENDIF
od = abs(1.0-od*2.0)
ELSEIF cm==9; interpolated
d1 = abs(1.0-od*2.0)
if @v_mmfextendedcilia<2 || wasdivergent
d2 = abs(1.0-(od*@split-floor(od*@split))*2.0)
else
d2 = abs(1.0-(od*@csplit-floor(od*@csplit))*2.0)
endif
od = d1 + of*(d2-d1)
ELSEIF cm==10; sine waves
d1 = cos(od*#pi*2.0)*0.5 + 0.5
if @v_mmfextendedcilia<2 || wasdivergent
d2 = cos(od*#pi*2.0*@split)*0.5 + 0.5
else
d2 = cos(od*#pi*2.0*@csplit)*0.5 + 0.5
endif
od = d1 + of*(d2-d1)
ELSEIF cm==11; cells
od = ((0.25-sqr(od-0.5)) * (0.25-sqr(of-0.5))) * 16.0
ELSEIF cm==12; bricks
d1 = 1.0 - abs(od-0.5)*2.0
d2 = 1.0 - abs(of-0.5)*2.0
IF (d1 < d2)
od = d1
ELSE
od = d2
ENDIF
ELSEIF cm==13; diamonds
od = 0.5 - abs(od - 0.5)
IF (of < 2.0/3.0)
od = od + of*0.75
od = abs(1.0-od*2.0)
ELSE
IF (od < of*0.75-0.5)
od = of*3.0-2.0-od*4.0
ELSE
od = 1.0-(0.5-od)/(1.0-of*0.75)
ENDIF
ENDIF
endif
endif
if (oi<4)
d = fz4; angle of z
else
d = fz
endif
IF (d < 0); it's negative
d = d + #pi * 2.0; make it positive
ENDIF
d = d / (#pi * 2.0); scale so full angle range is 0..1
; apply rotation and skew
d = d + r + s*f
d = d - floor(d)
; convert decomp and pot to tileable value d
; this is where the patterns are made
IF (cm == 0) || cm==8; sawtooth
IF (d < 0.5)
d = d * (f+1.0)
ELSE
d = (d-0.5) * (f+1.0) - 0.5*f + 0.5
ENDIF
d = abs(1.0-d*2.0)
ELSEIF (cm == 1) || cm==9; interpolated
d1 = abs(1.0-d*2.0)
if @v_mmfextendedcilia<2 || wasdivergent
d2 = abs(1.0-(d*@split-floor(d*@split))*2.0)
else
d2 = abs(1.0-(d*@csplit-floor(d*@csplit))*2.0)
endif
d = d1 + f*(d2-d1)
ELSEIF (cm == 2) || cm==10; sine waves
d1 = cos(d*#pi*2.0)*0.5 + 0.5
if @v_mmfextendedcilia<2 || wasdivergent
d2 = cos(d*#pi*2.0*@split)*0.5 + 0.5
else
d2 = cos(d*#pi*2.0*@csplit)*0.5 + 0.5
endif
d = d1 + f*(d2-d1)
ELSEIF (cm == 3) || cm==11; cells
d = ((0.25-sqr(d-0.5)) * (0.25-sqr(f-0.5))) * 16.0
ELSEIF (cm == 4) || cm==12; bricks
d1 = 1.0 - abs(d-0.5)*2.0
d2 = 1.0 - abs(f-0.5)*2.0
IF (d1 < d2)
d = d1
ELSE
d = d2
ENDIF
ELSEIF (cm == 5) || cm==13; diamonds
d = 0.5 - abs(d - 0.5)
IF (f < 2.0/3.0)
d = d + f*0.75
d = abs(1.0-d*2.0)
ELSE
IF (d < f*0.75-0.5)
d = f*3.0-2.0-d*4.0
ELSE
d = 1.0-(0.5-d)/(1.0-f*0.75)
ENDIF
ENDIF
elseif (cm == 6) ;Smoothed angles
if oi<4
if fz4<-#pi
fz4 = fz4 + 2*#pi
elseif fz4>#pi
fz4 = fz4 - 2*#pi
endif
if fz5<-#pi
fz5 = fz5 + 2*#pi
elseif fz5>#pi
fz5 = fz5 - 2*#pi
endif
d = cos(0.5*fz4)
d1 = cos(0.5*fz5); angle of older z
else
if fz<-#pi
fz = fz + 2*#pi
elseif fz>#pi
fz = fz - 2*#pi
endif
if fz1<-#pi
fz1 = fz1 + 2*#pi
elseif fz1>#pi
fz1 = fz1 - 2*#pi
endif
d = cos(0.5*fz)
d1 = cos(0.5*fz1)
endif
d1 = d1 + s*f
d = d + r*f
d1 = d1 + r*(1-f)
d = abs(d1 + (d-d1)*f)
elseif (cm == 7) ;Just smooth iteration
d = (-0.125 + 0.05*(it+f))^@ip
ENDIF
if cm>7 && cm!=14
d = od+(d-od)*f
endif
duse = d
if cm != 7 && ivuse>0
d1 = it + f
if li==1
d1 = log(1.0+d1)
elseif li==2
d1 = log(1.0+log(1.0+d1))
endif
if @v_mmfextendedcilia>=3
if wasdivergent
iterbasin = @iterval*d1
else
iterbasin = @citerval*d1
endif
else
iterbasin = d1
endif
d = ivuse*d1 + iwuse*d
endif
if usebasins && @zbasin>0
if isstandard
z2 = z1
z1 = pz
endif
if @zbasin==1
d1 = abs(real(2.0*#pi+atan2(z1)))
od = abs(real(2.0*#pi+atan2(z2)))
elseif @zbasin==2
d1 = abs(real(z1))
od = abs(real(z2))
elseif @zbasin==3
d1 = abs(imag(z1))
od = abs(imag(z2))
elseif @zbasin==4
d1 = abs(real(z1)+imag(z1))
od = abs(real(z2)+imag(z2))
elseif @zbasin==5
d1 = abs(2.0*real(z1)+imag(z1))
od = abs(2.0*real(z2)+imag(z2))
elseif @zbasin==6
d1 = abs(real(z1)+2.0*imag(z1))
od = abs(real(z2)+2.0*imag(z2))
elseif @zbasin==7
d1 = abs(real(z1)/(abs(imag(z1))+1.0))
od = abs(real(z2)/(abs(imag(z2))+1.0))
elseif @zbasin==8
d1 = abs(imag(z1)/(abs(real(z1))+1.0))
od = abs(imag(z2)/(abs(real(z2))+1.0))
elseif @zbasin==9
d1 = abs(2.0*real(sqrt(z1))+imag(sqrt(z1)))
od = abs(2.0*real(sqrt(z2))+imag(sqrt(z2)))
elseif @zbasin==10
d1 = abs(real(sqrt(z1))+2.0*imag(sqrt(z1)))
od = abs(real(sqrt(z2))+2.0*imag(sqrt(z2)))
endif
d = d + (od=@zscale*(od+(d1-od)*f))
iterbasin = iterbasin + od
endif
if @mapimage && wasdivergent
if f<0.0
f = f + 1.0
endif
d = 2*((o+d)- floor(o+d)) - 1
duse = 2*((o+duse)- floor(o+duse)) - 1
fuse = f = 2*((it%@spread) + f)/@spread - 1
clr = m_Image.GetColor(m_Transform.Iterate(d+flip(f)))
if @mapmethod=="Image All" || @mapmethod=="Image Brightness"
return 0.299*red(clr) + 0.587*green(clr) + 0.114*blue(clr)
elseif @mapmethod=="Image Red"
return red(clr)
elseif @mapmethod=="Image Green"
return green(clr)
elseif @mapmethod=="Image Blue"
return blue(clr)
elseif @mapmethod=="Image Alpha"
return alpha(clr)
elseif @mapmethod=="Image Hue"
return hue(clr)/6.0
elseif @mapmethod=="Image Saturation"
return sat(clr)
elseif @mapmethod=="Image Luminance"
return lum(clr)
endif
elseif @mapimagec && !wasdivergent
d = 2*((o + d)- floor(o+d)) - 1
duse = 2*((o+duse)- floor(o+duse)) - 1
fuse = f = 2*((it%@spreadc) + f)/@spreadc - 1
clr = m_Imagec.GetColor(m_Transformc.Iterate(d+flip(f)))
if @mapmethodc=="Image All" || @mapmethodc=="Image Brightness"
return 0.299*red(clr) + 0.587*green(clr) + 0.114*blue(clr)
elseif @mapmethodc=="Image Red"
return red(clr)
elseif @mapmethodc=="Image Green"
return green(clr)
elseif @mapmethodc=="Image Blue"
return blue(clr)
elseif @mapmethodc=="Image Alpha"
return alpha(clr)
elseif @mapmethodc=="Image Hue"
return hue(clr)/6.0
elseif @mapmethodc=="Image Saturation"
return sat(clr)
elseif @mapmethodc=="Image Luminance"
return lum(clr)
endif
endif
return o + d * 0.9975
endfunc
; @param pz the z value
; @return colour value
color func Result(complex pz)
float v = ResultIndex(pz)
if (@mapimage && (@mapmethod=="Image All" || @v_mmfextendedcilia>=3) \
&& wasdivergent) \
|| (@mapimagec && (@mapmethodc=="Image All" || @v_mmfextendedcilia>=3) \
&& !wasdivergent)
if wasdivergent
clr = m_Image.GetColor(m_Transform.Iterate(duse+flip(fuse)))
if @v_mmfextendedcilia>=3 && @mapmethod!="Image All"
if @usegradient
if @mapmethod=="Image Red"
clr = usergradient.GetColour(red(clr))
elseif @mapmethod=="Image Green"
clr = usergradient.GetColour(green(clr))
elseif @mapmethod=="Image Blue"
clr = usergradient.GetColour(blue(clr))
elseif @mapmethod=="Image Alpha"
clr = usergradient.GetColour(alpha(clr))
elseif @mapmethod=="Image Hue"
clr = usergradient.GetColour(hue(clr)/6.0)
elseif @mapmethod=="Image Saturation"
clr = usergradient.GetColour(sat(clr))
elseif @mapmethod=="Image Luminance"
clr = usergradient.GetColour(lum(clr))
elseif @mapmethod=="Image Brightness"
clr = usergradient.GetColour(0.299*red(clr) + 0.587*green(clr) \
+ 0.114*blue(clr))
endif
elseif @mapmethod=="Image Red"
clr = gradient(red(clr))
elseif @mapmethod=="Image Green"
clr = gradient(green(clr))
elseif @mapmethod=="Image Blue"
clr = gradient(blue(clr))
elseif @mapmethod=="Image Alpha"
clr = gradient(alpha(clr))
elseif @mapmethod=="Image Hue"
clr = gradient(hue(clr)/6.0)
elseif @mapmethod=="Image Saturation"
clr = gradient(sat(clr))
elseif @mapmethod=="Image Luminance"
clr = gradient(lum(clr))
elseif @mapmethod=="Image Brightness"
clr = gradient(0.299*red(clr) + 0.587*green(clr) + 0.114*blue(clr))
endif
endif
if @adjustlayer
if @iterval>0
clr = m_Merge.GradientMerge(clr, iterbasin)
endif
color c = @f_adjustcolour
if @adjusttype==0
c = RGB(@adjred, @adjgreen, @adjblue)
endif
c = compose(clr, m_Adjust.Merge(clr, c), @f_opacity)
return RGBA(red(c), green(c), blue(c), alpha(clr))
endif
if @iterval>0
return m_Merge.GradientMerge(clr, iterbasin)
endif
return clr
else
clr = m_Imagec.GetColor(m_Transformc.Iterate(duse+flip(fuse)))
if @v_mmfextendedcilia>=3 && @mapmethodc!="Image All"
if @usegradientc
if @mapmethodc=="Image Red"
clr = usergradientc.GetColour(red(clr))
elseif @mapmethodc=="Image Green"
clr = usergradientc.GetColour(green(clr))
elseif @mapmethodc=="Image Blue"
clr = usergradientc.GetColour(blue(clr))
elseif @mapmethodc=="Image Alpha"
clr = usergradientc.GetColour(alpha(clr))
elseif @mapmethodc=="Image Hue"
clr = usergradientc.GetColour(hue(clr)/6.0)
elseif @mapmethodc=="Image Saturation"
clr = usergradientc.GetColour(sat(clr))
elseif @mapmethodc=="Image Luminance"
clr = usergradientc.GetColour(lum(clr))
elseif @mapmethodc=="Image Brightness"
clr = usergradientc.GetColour(0.299*red(clr) + 0.587*green(clr) \
+ 0.114*blue(clr))
endif
elseif @mapmethodc=="Image Red"
clr = gradient(red(clr))
elseif @mapmethodc=="Image Green"
clr = gradient(green(clr))
elseif @mapmethodc=="Image Blue"
clr = gradient(blue(clr))
elseif @mapmethodc=="Image Alpha"
clr = gradient(alpha(clr))
elseif @mapmethodc=="Image Hue"
clr = gradient(hue(clr)/6.0)
elseif @mapmethodc=="Image Saturation"
clr = gradient(sat(clr))
elseif @mapmethodc=="Image Luminance"
clr = gradient(lum(clr))
elseif @mapmethodc=="Image Brightness"
clr = gradient(0.299*red(clr) + 0.587*green(clr) + 0.114*blue(clr))
endif
endif
if @adjustlayerc
if @citerval>0
clr = m_Mergec.GradientMerge(clr, iterbasin)
endif
color c = @f_adjustcolourc
if @adjusttypec==0
c = RGB(@adjredc, @adjgreenc, @adjbluec)
endif
c = compose(clr, m_Adjustc.Merge(clr, c), @f_opacityc)
return RGBA(red(c), green(c), blue(c), alpha(clr))
endif
if @citerval>0
return m_Mergec.GradientMerge(clr, iterbasin)
endif
return clr
endif
endif
return gradient(v)
endfunc
private:
ImageWrapper m_Image
Transform m_Transform
GradientLayer m_Merge
ColorMerge m_Adjust
MMF_UserGradient usergradient
ImageWrapper m_Imagec
Transform m_Transformc
GradientLayer m_Mergec
ColorMerge m_Adjustc
MMF_UserGradient usergradientc
float rval[#maxiter+1]
float crval[#maxiter+1]
complex z1
complex z2
complex z3
complex z4
complex z5
complex z6
color clr
float iterbasin
float duse
float fuse
float il
float lp
float ilp
float cil
float clp
float cilp
float iv
float ivc
float iw
float iwc
float co
bool wasdivergent
default:
title = "MMF Extended Cilia"
rating = recommended
int param v_mmfextendedcilia
caption = "Version (MMF Extended Cilia)"
enum = "1.0" "1.1" "1.2" "1.3"
default = 3
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number. Version 1.1 has a minor change for \
when the 'solid' flag gets set. Version 1.2 fixes an issue with \
the convergent 'Split' value."
visible = @v_mmfextendedcilia<3
endparam
heading
caption = "Main control"
endheading
int param method
caption = "Smoothing"
default = 0
enum = "Standard Div." "Standard Conv." "Standard both" \
"Hinrich's Div." "Hinrich's Conv." "Hinrich's both" \
"St.Div. H.Conv." "H.Div St.Conv."
hint = "Specifies the type of smoothing to use and whether to \
colour divergent or convergent areas or both. \
Standard uses standard iteration smoothing and hence \
requires appropriate bailout (and power and fudge) values. \
Hinrich's uses what I've previously called 'finalz' \
smoothing where the final value of z from the main formula \
passes a smoothing fraction as real(z) and maybe atan(#z) \
as imag(z)."
endparam
heading
caption = "Divergent smoothing"
endheading
float param bailout
caption = "Bailout"
default = 128.0
hint = "This should match the bailout in the fractal formula. \
Larger values work best, especially when using 'Old iterations'. \
When NOT using standard divergent smoothing \
you should still ensure this is a suitable value (eg. >=10)."
endparam
bool param dauto
caption = "Auto-power"
default = true
hint = "When enabled should produce smoothing for any divergent \
areas without you needing to set a divergent power value \
for the colouring."
visible = @method==0 || @method==2 || @method==6
endparam
complex param power
caption = "Power/exponent/degree"
default = (2,0)
hint = "This should match the power/degree/exponent in the \
fractal formula. If the value to use isn't immediately \
obvious from the main formula itself then it's best to \
choose the 'Just iteration' mode and modify this value \
(and maybe the Scaling fudge) until you get completely \
smooth colouring, or just enable auto-power."
visible = @method==0 || @method==2 || @method==6
endparam
float param fudge
caption = "Scaling fudge"
default = 1.0
hint = "This is a scaling fudge value, it's used to scale \
the calculated iteration fraction when the value \
doesn't reach 1, it's unlikely to be required for \
divergent smoothing but I added it just in case. If \
'Auto-power' or the best value you can find for \
the power parameter don't produce smooth results then \
modifying this value may help."
visible = @method==0 || @method==2 || @method==6
endparam
float param fudge1
caption = "Scaling fudge 1"
default = 1.0
hint = "This is a scaling fudge value, it's used to scale \
the calculated iteration fraction when the value \
doesn't reach 1, it's unlikely to be required for \
divergent smoothing but I added it just in case."
visible = @method==3 || @method==5 || @method==7
endparam
heading
caption = "Divergent colouring"
visible = @method==0 || @method==2 || @method==3 || @method>4
endheading
bool param mapimage
caption = "Image Mapping"
default = false
hint = "When enabled you can map an image into the Cilia. Note that the \
'Image Only' Cilia Mode is specifically designed for the use of \
images but you may get interesting results for images in any of \
the Cilia Modes."
visible = @method==0 || @method==2 || @method==3 || @method>4
endparam
ImageWrapper param f_image
caption = "Image Object"
default = MMF_ImageImport
hint = "The image to use."
visible = @mapimage && (@method==0 || @method==2 || @method==3 || @method>4)
endparam
Transform param f_transform
caption = "Image Transform"
default = NullTransform
hint = "Use to position/flip/mirror/scale your image mapping."
visible = @mapimage && (@method==0 || @method==2 || @method==3 || @method>4)
endparam
int param mapmethod
caption = "Image Method"
enum = "Image All" "Image Red" "Image Green" "Image Blue" "Image Alpha" \
"Image Hue" "Image Saturation" "Image Luminance" "Image Brightness"
hint = "'Image All' maps the image brightness (Yiq) to UF's gradient \
if the colouring is being used as a gradient colouring or uses \
the image colours if the colouring is being used as a direct \
colouring. 'Image Red' maps the image red to a gradient, \
'Image Green' the green, 'Image Blue' the blue, 'Image Hue' \
the hue, 'Image Saturation' the saturation and 'Image Luminance' \
the luminance. 'Image Brightness' works the same as 'Image All' \
if in gradient mode or maps the brightness to a gradient if in \
direct mode."
visible = @mapimage && (@method==0 || @method==2 || @method==3 || @method>4)
endparam
int param spread
caption = "Image Spread"
default = 1
min = 1
hint = "The number of iteration bands over which to spread your image."
visible = @mapimage && (@method==0 || @method==2 || @method==3 || @method>4)
endparam
bool param usegradient
caption = "Use Custom Gradient ?"
default = false
hint = "Only relevant if in direct colouring mode. If disabled then the \
value from the image is translated to a colour using UF's in-built \
gradient (as is always the case in gradient colouring mode), \
enable if you wish to use a gradient specified as user \
parameters instead."
visible = @mapimage && (@method==0 || @method==2 || @method==3 || @method>4) \
&& @mapmethod!="Image All" && @v_mmfextendedcilia>=3
endparam
MMF_UserGradient param usergradient
caption = "Custom Gradient"
default = MMF_Gradient
hint = "Create a custom gradient."
visible = @mapimage && (@method==0 || @method==2 || @method==3 || @method>4) \
&& @mapmethod!="Image All" && @v_mmfextendedcilia>=3 && @usegradient
endparam
GradientLayer param f_merge
caption = "Iteration Merge"
default = MMF_GradientLayer
hint = "Only used if the main colouring is being used in direct colouring \
mode and add iteration is in use. Use to merge the iteration value \
and the image. Note that the gradient you choose controls the \
colour of the iteration layer which is normally treated as the top \
layer."
visible = @mapimage && (@v_mmfextendedcilia>=3 || @mapmethod=="Image All") \
&& @iterval>0 && (@method==0 || @method==2 || @method==3 || @method>4)
expanded = false
endparam
bool param adjustlayer
caption = "Add Adjust layer"
default = false
hint = "Allows you to add an adjustment layer in a given colour to merge \
on top of the image/texture. Only works if the main colouring \
is in direct mode."
visible = @mapimage && (@v_mmfextendedcilia>=3 || @mapmethod=="Image All") \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
int param adjusttype
caption = "Colour or RGB"
enum = "RGB values" "Colour Parameter"
default = 1
hint = "This option is specifically added so that if you choose \
'RGB values' you can 'explore' them and see changes to the image \
as you change the RGB. The option may become redundant in a \
future version of UF. Only works if the main colouring \
is in direct mode."
visible = @mapimage && (@v_mmfextendedcilia>=3 || @mapmethod=="Image All") \
&& @adjustlayer \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
float param adjred
caption = "Red Value"
default = 1.0
hint = "The red part of the adjust colour (0 to 1). Only works if the \
main colouring is in direct mode."
visible = @mapimage && (@v_mmfextendedcilia>=3 || @mapmethod=="Image All") \
&& @adjustlayer && @adjusttype==0 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
float param adjgreen
caption = "Green Value"
default = 1.0
hint = "The green part of the adjust colour (0 to 1). Only works if the \
main colouring is in direct mode."
visible = @mapimage && (@v_mmfextendedcilia>=3 || @mapmethod=="Image All") \
&& @adjustlayer && @adjusttype==0 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
float param adjblue
caption = "Blue Value"
default = 1.0
hint = "The blue part of the adjust colour (0 to 1). Only works if the \
main colouring is in direct mode."
visible = @mapimage && (@v_mmfextendedcilia>=3 || @mapmethod=="Image All") \
&& @adjustlayer && @adjusttype==0 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
color param f_adjustcolour
caption = "Adjust Layer Colour"
default = RGB(1,1,1)
hint = "Allows you to apply overall adjustments to your colouring. Only \
works if the main colouring is in direct mode."
visible = @mapimage && (@v_mmfextendedcilia>=3 || @mapmethod=="Image All") \
&& @adjustlayer && @adjusttype==1 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
ColorMerge param f_adjust
caption = "Adjustment Layer Merge"
default = MMF_ExtendedColorMerge
hint = "Only works if the main colouring is in direct mode."
visible = @mapimage && (@v_mmfextendedcilia>=3 || @mapmethod=="Image All") \
&& @adjustlayer \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
float param f_opacity
caption = "Adjustment Opacity"
default = 1.0
hint = "Use to modify the adjustment opacity, the normal range is from \
0 to 1. Only works if the main colouring is in direct mode."
visible = @mapimage && (@v_mmfextendedcilia>=3 || @mapmethod=="Image All") \
&& @adjustlayer \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
int param ciliamode
caption = "Cilia Mode"
default = 0
enum = "Sawtooth" "Interpolated" "Sine waves" "Cells" "Bricks" \
"Diamonds" "Smoothed angles" "Just iteration" "Smooth saw" \
"Smooth interpolated" "Smooth sine" "Smooth cells" "Smooth bricks" \
"Smooth diamonds" "Image Only"
hint = "This is the periodic function used to generate the \
cilia pieces. Each has a different 'flavor'. \
The 'Smooth' versions produce smoothed results for \
Sawtooth, Interpolated, Sine waves and Diamonds when \
the degree of divergence or convergence is not 2, eg. z^3+c \
Note that 'Just iteration' is exactly that, the \
other parameters become irrelevant."
visible = @method==0 || @method==2 || @method==3 || @method>4
endparam
float param split
caption = "Split"
default = 2.0
hint = "Allows you to choose how the colouring 'splits' from one iteration \
to the next i.e. the increase in density of the colouring from one \
iteration to the next. Should 'correctly' be equal to the rate of \
divergence of the fractal e.g. 2 for z^2+c. Note that when using \
'Sawtooth' or 'Diamonds' then only fractals where the correct \
value is 2 will work as intended."
visible = @ciliamode!=6 && @ciliamode!=7 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
int param olditer
caption = "Old Iterations"
default = 4
enum = "1 older" "2 older" "3 older" "4 older" "No"
hint = "Uses older iterations for decomposition angle; this \
has the effect of spreading out the pattern. Best \
used to compensate for extreme bailouts. Note that \
'No' requires the angle passed as the imaginary \
part of final z when using Hinrich's smoothing."
visible = @ciliamode!=7 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
float param iterval
caption = "+Iter amount"
default = 0.0
min = 0.0
hint = "Adds some iteration count to the colour value, \
thus producing colour change over the iterations. \
The larger the value the faster the colour change \
per iteration."
visible = @ciliamode!=7 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
float param iterweight
caption = "Iter %age (div)"
default = 50.0
hint = "Allows you to control the mixing of the smooth iteration value \
and the normal formula colouring value. Zero will use no iteration \
value and 100 will use all iteration value. Unused if using Image \
Mapping and in direct colouring mode."
visible = @ciliamode!=7 && @iterval>0 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
int param logiter
caption = "+Iter function"
enum = "Ident" "Log()" "Log(Log())"
hint = "Allows you to apply log or double log to the iteration component."
visible = @ciliamode!=7 && @iterval>0 && @iterweight!=0 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
float param skew
caption = "Skew"
default = 0.0
hint = "This skews the pattern. Unless you enable 'Fix Rotation' and 'Fix \
Skew' then only certain values will maintain the pattern e.g. \
multiples of 0.5 for z^2+c whereas when the 'fixes' are enabled \
the pattern will be maintained whatever value you use. When using \
Smoothed angles it changes the pattern rather than skewing it."
visible = @ciliamode!=7 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
float param rot
caption = "Rotation"
default = 0.0
hint = "This rotates the pattern, only values from -1 to +1 \
make sense for rotation except when using 'Fix Rotation' in which \
case the entire pattern rotates together provided the 'Split' \
value is correct. When using Smoothed angles it \
changes the pattern rather than rotating it and any \
reasonable values make sense."
visible = @ciliamode!=7 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
bool param fixrot
caption = "Fix Rotation"
default = false
hint = "When enabled the rotation is 'fixed'."
visible = @ciliamode!=6 && @ciliamode!=7 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
float param rpwr
caption = "Rotation adjust"
default = 5.0
min = 0.0
max = 20.0
hint = "Use to scale the effect of the 'Rotation' value, the larger the \
value you use the smaller the effect of changes to 'Rotation'. \
Typically increase the value in areas of higher iteration counts. \
Only needed when using a 'Split' greater than 1."
visible = @fixrot && @ciliamode!=6 && @ciliamode!=7 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
bool param fixskew
caption = "Fix Skew"
default = false
hint = "When enabled the skew is 'fixed' for any skew values."
visible = @fixrot && @ciliamode!=6 && @ciliamode!=7 \
&& (@method==0 || @method==2 || @method==3 || @method>4)
endparam
heading
caption = "Convergent smoothing"
endheading
float param smallbail
caption = "Bailout"
default = 1e-5
hint = "This should match the small bailout in your fractal formula. \
When NOT using standard convergent smoothing \
you should still ensure this is a suitable value (eg. <=1e-5)."
endparam
bool param cauto
caption = "Auto-power"
default = true
hint = "When enabled should produce smoothing for any convergent \
areas without you needing to set a convergent power value \
for the colouring."
visible = @method==1 || @method==2 || @method==7
endparam
complex param cpower
caption = "Power/exponent/degree"
default = (2,0)
hint = "This should match the power (exponent/degree) for the \
convergent areas of your main fractal formula. If the \
value to use isn't immediately obvious from the main \
formula itself then it's best to choose the 'Just \
iteration' mode and modify this value (and maybe the \
Scaling fudge) until you get completely smooth colouring, \
or just try auto-power."
visible = @method==1 || @method==2 || @method==7
endparam
float param fudgec
caption = "Scaling Fudge"
default = 1.0
hint = "This is a scaling fudge value, it's used to scale \
the calculated iteration fraction when the value \
doesn't reach 1. If 'Auto-power' or the best value you can \
find for the 'Convergent Power' parameter don't \
produce smooth results then modifying this value \
should help."
visible = @method==1 || @method==2 || @method==7
endparam
float param fudge1c
caption = "Scaling Fudge 1"
default = 1.0
hint = "This is a scaling fudge value, it's used to scale \
the calculated iteration fraction when the value \
doesn't reach 1."
visible = @method==4 || @method==5 || @method==6
endparam
bool param cfixed
caption = "Absolute convergence"
default = false
hint = "For when using a main formula that tests for convergence by \
using (only) |#z-value| rather than |#z-zold|, a typical example \
would be a Magnet formula where |#z-1.0| is often used. When \
enabled set the value of 'Convergence root' appropriately."
visible = @method==1 || @method==2 || @method==7
endparam
complex param cfixedval
caption = "Convergence root"
default = (1,0)
hint = "Use (1.0,0) for some Magnet formulas."
visible = (@method==1 || @method==2 || @method==7) && @cfixed
endparam
heading
caption = "Convergent colouring"
visible = @method==1 || @method==2 || @method>3
endheading
bool param mapimagec
caption = "Image Mapping"
default = false
hint = "When enabled you can map an image into the Cilia. Note that the \
'Image Only' Cilia Mode is specifically designed for the use of \
images but you may get interesting results for images in any of \
the Cilia Modes."
visible = @method==1 || @method==2 || @method>3
endparam
ImageWrapper param f_imagec
caption = "Image Object"
default = MMF_ImageImport
hint = "The image to use."
visible = @mapimagec && (@method==1 || @method==2 || @method>3)
endparam
Transform param f_transformc
caption = "Image Transform"
default = NullTransform
hint = "Use to position/flip/mirror/scale your image mapping."
visible = @mapimagec && (@method==1 || @method==2 || @method>3)
endparam
int param mapmethodc
caption = "Image Method"
enum = "Image All" "Image Red" "Image Green" "Image Blue" "Image Alpha" \
"Image Hue" "Image Saturation" "Image Luminance" "Image Brightness"
hint = "'Image All' maps the image brightness (Yiq) to UF's gradient \
if the colouring is being used as a gradient colouring or uses \
the image colours if the colouring is being used as a direct \
colouring. 'Image Red' maps the image red to a gradient, \
'Image Green' the green, 'Image Blue' the blue, 'Image Hue' \
the hue, 'Image Saturation' the saturation and 'Image Luminance' \
the luminance. 'Image Brightness' works the same as 'Image All' \
if in gradient mode or maps the brightness to a gradient if in \
direct mode."
visible = @mapimagec && (@method==1 || @method==2 || @method>3)
endparam
int param spreadc
caption = "Image Spread"
default = 1
min = 1
hint = "The number of iteration bands over which to spread your image."
visible = @mapimagec && (@method==1 || @method==2 || @method>3)
endparam
bool param usegradientc
caption = "Use Custom Gradient ?"
default = false
hint = "Only relevant if in direct colouring mode. If disabled then the \
value from the image is translated to a colour using UF's in-built \
gradient (as is always the case in gradient colouring mode), \
enable if you wish to use a gradient specified as user \
parameters instead."
visible = @mapimagec && (@method==1 || @method==2 || @method>3) \
&& @mapmethodc!="Image All" && @v_mmfextendedcilia>=3
endparam
MMF_UserGradient param usergradientc
caption = "Custom Gradient"
default = MMF_Gradient
hint = "Create a custom gradient."
visible = @mapimagec && (@method==1 || @method==2 || @method>3) \
&& @mapmethodc!="Image All" && @v_mmfextendedcilia>=3 && @usegradientc
endparam
GradientLayer param f_mergec
caption = "Iteration/Zbasin Merge"
default = MMF_GradientLayer
hint = "Only used if the main colouring is being used in direct colouring \
mode and add iteration or z basins is in use. Use to merge the \
iteration/z basin value with the image. Note that the gradient you \
choose controls the colour of the iteration/z basin layer which \
is normally treated as the top layer."
visible = @mapimagec && (@v_mmfextendedcilia>=3 || @mapmethodc=="Image All") \
&& (@citerval>0 || @zbasin>0) \
&& (@method==1 || @method==2 || @method>3)
expanded = false
endparam
bool param adjustlayerc
caption = "Add Adjust layer"
default = false
hint = "Allows you to add an adjustment layer in a given colour to merge \
on top of the image/texture. Only works if the main colouring \
is in direct mode."
visible = @mapimagec && (@v_mmfextendedcilia>=3 || @mapmethodc=="Image All") \
&& (@method==1 || @method==2 || @method>3)
endparam
int param adjusttypec
caption = "Colour or RGB"
enum = "RGB values" "Colour Parameter"
default = 1
hint = "This option is specifically added so that if you choose \
'RGB values' you can 'explore' them and see changes to the image \
as you change the RGB. The option may become redundant in a \
future version of UF. Only works if the main colouring \
is in direct mode."
visible = @mapimagec && (@v_mmfextendedcilia>=3 || @mapmethodc=="Image All") \
&& @adjustlayerc \
&& (@method==1 || @method==2 || @method>3)
endparam
float param adjredc
caption = "Red Value"
default = 1.0
hint = "The red part of the adjust colour (0 to 1). Only works if the \
main colouring is in direct mode."
visible = @mapimagec && (@v_mmfextendedcilia>=3 || @mapmethodc=="Image All") \
&& @adjustlayerc \
&& @adjusttypec==0 && (@method==1 || @method==2 || @method>3)
endparam
float param adjgreenc
caption = "Green Value"
default = 1.0
hint = "The green part of the adjust colour (0 to 1). Only works if the \
main colouring is in direct mode."
visible = @mapimagec && (@v_mmfextendedcilia>=3 || @mapmethodc=="Image All") \
&& @adjustlayerc \
&& @adjusttypec==0 && (@method==1 || @method==2 || @method>3)
endparam
float param adjbluec
caption = "Blue Value"
default = 1.0
hint = "The blue part of the adjust colour (0 to 1). Only works if the \
main colouring is in direct mode."
visible = @mapimagec && (@v_mmfextendedcilia>=3 || @mapmethodc=="Image All") \
&& @adjustlayerc \
&& @adjusttypec==0 && (@method==1 || @method==2 || @method>3)
endparam
color param f_adjustcolourc
caption = "Adjust Layer Colour"
default = RGB(1,1,1)
hint = "Allows you to apply overall adjustments to your colouring. Only \
works if the ain colouring is in direct mode."
visible = @mapimagec && (@v_mmfextendedcilia>=3 || @mapmethodc=="Image All") \
&& @adjustlayerc \
&& @adjusttypec==1 && (@method==1 || @method==2 || @method>3)
endparam
ColorMerge param f_adjustc
caption = "Adjustment Layer Merge"
default = MMF_ExtendedColorMerge
hint = "Only works if the main colouring is in direct mode."
visible = @mapimagec && (@v_mmfextendedcilia>=3 || @mapmethodc=="Image All") \
&& @adjustlayerc \
&& (@method==1 || @method==2 || @method>3)
endparam
float param f_opacityc
caption = "Adjustment Opacity"
default = 1.0
hint = "Use to modify the adjustment opacity, the normal range is from \
0 to 1. Only works if the main colouring is in direct mode."
visible = @mapimagec && (@v_mmfextendedcilia>=3 || @mapmethodc=="Image All") \
&& @adjustlayerc \
&& (@method==1 || @method==2 || @method>3)
endparam
int param cciliamode
caption = "Cilia Mode"
default = 0
enum = "Sawtooth" "Interpolated" "Sine waves" "Cells" "Bricks" \
"Diamonds" "Smoothed angles" "Just iteration" "Smooth saw" \
"Smooth interpolated" "Smooth sine" "Smooth cells" "Smooth bricks" \
"Smooth diamonds" "Image Only"
hint = "This is the periodic function used to generate the \
cilia pieces. Each has a different 'flavor'. \
The 'Smooth' versions produce smoothed results for \
Sawtooth, Interpolated, Sine waves and diamonds when \
the degree of divergence or convergence is not 2, eg. Nova formulas. \
Note that 'Just iteration' is exactly that, the \
other parameters become irrelevant."
visible = @method==1 || @method==2 || @method>3
endparam
float param csplit
caption = "Split"
default = 2.0
hint = "Allows you to choose how the colouring 'splits' from one iteration \
to the next i.e. the increase in density of the colouring from one \
iteration to the next. Should 'correctly' be 2 for the Newton or \
Magnet fractals. Note that when using 'Sawtooth' or 'Diamonds' \
then only fractals where the correct value is 2 will work as \
intended."
visible = @cciliamode!=6 && @cciliamode!=7 \
&& (@method==1 || @method==2 || @method>3)
endparam
bool param fixconv
caption = "Convergent 'fix'"
default = true
hint = "Fixes the convergent areas of some fractals (eg. Newton) \
so areas in different z basins will have consistent colouring. \
Turn this off to get more variety in your fractal \
but then plain Sawtooth, Sine and Interpolated will \
have iteration bands in some areas - you could use the \
Smooth versions instead. You may find 'Smoothed angles' better \
with this switched off."
visible = @cciliamode!=7 && (@method==1 || @method==2 || @method>3)
endparam
int param colditer
caption = "Old Iterations"
default = 0
enum = "1 older" "2 older" "3 older" "4 older" "No"
hint = "Uses older iterations for decomposition angle; this \
has the effect of spreading out the pattern. Best \
used to compensate for extreme bailouts. Note that \
'No' requires the angle passed as the imaginary \
part of final z when using Hinrich's smoothing."
visible = @cciliamode!=7 && (@method==1 || @method==2 || @method>3)
endparam
float param citerval
caption = "+Iter amount"
default = 0.0
min = 0.0
hint = "Adds some iteration count to the colour value, \
thus producing colour change over the iterations. \
The larger the value the faster the colour change \
per iteration."
visible = @cciliamode!=7 && (@method==1 || @method==2 || @method>3)
endparam
float param iterweightc
caption = "Iter %age (conv)"
default = 50.0
hint = "Allows you to control the mixing of the smooth iteration value \
and the normal formula colouring value. Zero will use no iteration \
value and 100 will use all iteration value."
visible = @cciliamode!=7 && @citerval>0 \
&& (@method==1 || @method==2 || @method>3)
endparam
int param logiterc
caption = "+Iter function"
enum = "Ident" "Log()" "Log(Log())"
hint = "Allows you to apply log or double log to the iteration component."
visible = @cciliamode!=7 && @citerval>0 && @iterweightc!=0 \
&& (@method==1 || @method==2 || @method>3)
endparam
float param cskew
caption = "Skew"
default = 0.0
hint = "This skews the pattern. Unless you enable 'Fix Rotation' and 'Fix \
Skew' then only certain values will maintain the pattern e.g. \
multiples of 0.5 for Newton whereas when the 'fixes' are enabled \
the pattern will be maintained whatever value you use. When using \
Smoothed angles it changes the pattern rather than skewing it."
visible = @cciliamode!=7 && (@method==1 || @method==2 || @method>3)
endparam
float param crot
caption = "Rotation"
default = 0.0
hint = "This rotates the pattern, only values from -1 to +1 \
make sense for rotation except when using 'Fix Rotation' in which \
case the entire pattern rotates together provided the 'Split' \
value is correct. When using Smoothed angles it \
changes the pattern rather than rotating it and any \
reasonable values make sense."
visible = @cciliamode!=7 && (@method==1 || @method==2 || @method>3)
endparam
bool param cfixrot
caption = "Fix Rotation"
default = false
hint = "When enabled the rotation is 'fixed'."
visible = @cciliamode!=6 && @cciliamode!=7 \
&& (@method==1 || @method==2 || @method>3)
endparam
float param crpwr
caption = "Rotation adjust"
default = 5.0
min = 0.0
max = 20.0
hint = "Use to scale the effect of the 'Rotation' value, the larger the \
value you use the smaller the effect of changes to 'Rotation'. \
Typically increase the value in areas of higher iteration counts. \
Only needed when using a 'Split' greater than 1."
visible = @cfixrot && @cciliamode!=6 && @cciliamode!=7 \
&& (@method==1 || @method==2 || @method>3)
endparam
bool param cfixskew
caption = "Fix Skew"
default = false
hint = "When enabled the skew is 'fixed' for any skew value."
visible = @cfixrot && @cciliamode!=6 && @cciliamode!=7 \
&& (@method==1 || @method==2 || @method>3)
endparam
float param convoffset
caption = "Colour offset"
default = 0.0
hint = "Adds an offset to the final colour value in convergent areas, for \
when the main fractal has both convergent and divergent areas. \
The offset value corresponds to the number of gradient points when \
Color Density is 1 and Transfer Function is linear."
visible = @method==1 || @method==2 || @method>3
endparam
int param zbasin
caption = "Add z basins"
enum = "Off" "abs(atan2())" "abs(real())" "abs(imag())" "abs(real+imag)" \
"abs(2*real+imag)" "abs(2*imag+real)" "abs(real/(abs(imag)+1))" \
"abs(imag/(abs(real)+1))" "Roots 1" "Roots 2"
default = 0
hint = "Allows you to add a value to the final colouring based on the \
penultimate value of z."
visible = (@method==1 || @method==2 || @method>3)
endparam
float param zscale
caption = "Basin scale"
default = 0.1
hint = "Scales the effect of the z basin value."
visible = (@method==1 || @method==2 || @method>3) && @zbasin>0
endparam
float param ip
caption = "Iteration Power"
default = 1.0
visible = @ciliamode==7
endparam
}
class MMF_SwitchFormula(common.ulb:Formula) {
; Base class for formulas that allow switching to be used with
; mmf5.ufm-Generic Switch Formula
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchFormula(Generic pparent)
Formula.Formula(pparent)
if (fType = @p_mandy)
fValue = fConstant = @p_start
else
fValue = fConstant = @p_seed
endif
endfunc
; @param f flag for Mandelbrot or Julia mode, is true for Mandelbrots
; @param v the value to be used as the start value or constant
func SetParams(bool f,complex v)
if !@p_manual
fType = f
fValue = fConstant = v
endif
endfunc
protected:
complex fConstant
complex fValue
bool fType
default:
int param v_mmfswitchformula
caption = "Version (MMF_SwitchFormula)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @v_mmfswitchformula < 100
endparam
heading
caption = "Information"
text = "This formula object is intended for use with the 'Generic \
Switch Formula' in mmf5.ufm and in formula objects that \
allow switching, however it will still function without \
switching in non-switching formulas and formula objects."
endheading
heading
enabled = false
endheading
bool param p_manual
caption = "Manual Over-ride"
default = false
hint = "When enabled you will have manual control of the \
Mandelbrot/Julia switching and the associated parameters \
i.e. you will be able to over-ride the settings from the \
parent object. Note that this will effectively disable \
UF's built-in switching but allow full use of this formula \
when not used with a compatible switching parent."
endparam
bool param p_mandy
caption = "Mandelbrot ?"
default = true
hint = "Disable for Julia mode."
visible = @p_manual
endparam
complex param p_start
caption = "Mandelbrot Start Value"
default = (0,0)
visible = @p_manual && @p_mandy
endparam
complex param p_seed
caption = "Julia Constant"
default = (-1.25,0)
visible = @p_manual && !@p_mandy
endparam
}
class MMF_SwitchDivergentFormula(common.ulb:DivergentFormula) {
; Base class for Divergent formulas that allow switching to be used with
; mmf5.ufm-Generic Switch Formula
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchDivergentFormula(Generic pparent)
DivergentFormula.DivergentFormula(pparent)
if (fType = @p_mandy)
fValue = fConstant = @p_start
else
fValue = fConstant = @p_seed
endif
endfunc
; @param pz the initial location
; @return initial z for iteration
complex func Init(complex pz)
DivergentFormula.Init(pz)
if fType
fConstant = pz
if @p_addpixel
return fValue + fConstant
else
return fValue
endif
else
return pz
endif
endfunc
; @param f flag for Mandelbrot or Julia mode, is true for Mandelbrots
; @param v the value to be used as the start value or constant
func SetParams(bool f,complex v)
if !@p_manual
fType = f
fValue = fConstant = v
endif
endfunc
protected:
complex fConstant
complex fValue
bool fType
default:
int param v_switchdivergentformula
caption = "Version (MMF_DivergentFormula)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @v_switchdivergentformula < 100
endparam
heading
caption = "Information"
text = "This formula object is intended for use with the 'Generic \
Switch Formula' in mmf5.ufm and in formula objects that \
allow switching, however it will still function without \
switching in non-switching formulas and formula objects."
endheading
heading
enabled = false
endheading
bool param p_manual
caption = "Manual Over-ride"
default = false
hint = "When enabled you will have manual control of the \
Mandelbrot/Julia switching and the associated parameters \
i.e. you will be able to over-ride the settings from the \
parent object. Note that this will effectively disable \
UF's built-in switching but allow full use of this formula \
when not used with a compatible switching parent."
endparam
bool param p_mandy
caption = "Mandelbrot ?"
default = true
hint = "Disable for Julia mode."
visible = @p_manual
endparam
complex param p_start
caption = "Mandelbrot Start Value"
default = (0,0)
visible = @p_manual && @p_mandy
endparam
complex param p_seed
caption = "Julia Constant"
default = (-1.25,0)
visible = @p_manual && !@p_mandy
endparam
bool param p_addpixel
caption = "Offset z start"
default = false
hint = "When enabled the z start value (in Mandelbrot mode) is offset \
by the constant for the current position - normally '#pixel'."
visible = !@p_manual || @p_mandy
endparam
float param p_bailout
caption = "Bailout"
default = 128.0
hint = "Defines how soon an orbit bails out, i.e. doesn't belong \
to the fractal set anymore. Note: larger values result in \
more iterations being calculated."
endparam
}
class MMF_SwitchConvergentFormula(common.ulb:ConvergentFormula) {
; Base class for Convergent formulas that allow switching to be used with
; mmf5.ufm-Generic Switch Formula
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchConvergentFormula(Generic pparent)
ConvergentFormula.ConvergentFormula(pparent)
if (fType = @p_mandy)
fValue = fConstant = @p_start
else
fValue = fConstant = @p_seed
endif
endfunc
; Note that here zold is initialised to initial z
; @param pz the initial location
; @return initial z for iteration
complex func Init(complex pz)
ConvergentFormula.Init(pz)
if fType
fConstant = pz
if @p_addpixel
m_ZOld = fValue + fConstant
return m_ZOld
else
m_ZOld = fValue
return fValue
endif
else
m_ZOld = pz
return pz
endif
endfunc
; @param f flag for Mandelbrot or Julia mode, is true for Mandelbrots
; @param v the value to be used as the start value or constant
func SetParams(bool f,complex v)
if !@p_manual
fType = f
fValue = fConstant = v
endif
endfunc
protected:
complex fConstant
complex fValue
bool fType
default:
int param v_mmfswitchconvergentformula
caption = "Version (MMF_ConvergentFormula)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @v_mmfswitchconvergentformula < 100
endparam
heading
caption = "Information"
text = "This formula object is intended for use with the 'Generic \
Switch Formula' in mmf5.ufm and in formula objects that \
allow switching, however it will still function without \
switching in non-switching formulas and formula objects."
endheading
heading
enabled = false
endheading
bool param p_manual
caption = "Manual Over-ride"
default = false
hint = "When enabled you will have manual control of the \
Mandelbrot/Julia switching and the associated parameters \
i.e. you will be able to over-ride the settings from the \
parent object. Note that this will effectively disable \
UF's built-in switching but allow full use of this formula \
when not used with a compatible switching parent."
endparam
bool param p_mandy
caption = "Mandelbrot ?"
default = true
hint = "Disable for Julia mode."
visible = @p_manual
endparam
complex param p_start
caption = "Mandelbrot Start Value"
default = (0,0)
visible = @p_manual && @p_mandy
endparam
complex param p_seed
caption = "Julia Constant"
default = (-1.25,0)
visible = @p_manual && !@p_mandy
endparam
bool param p_addpixel
caption = "Offset z start"
default = false
hint = "When enabled the z start value (in Mandelbrot mode) is offset \
by the constant for the current position - normally '#pixel'."
visible = !@p_manual || @p_mandy
endparam
float param p_bailout
caption = "Bailout"
default = 1.0e-5
hint = "Defines how soon an orbit bails out, i.e. doesn't belong \
to the fractal set anymore. Note: smaller values result in \
more iterations being calculated."
endparam
}
class MMF_SwitchConvergentDivergentFormula(common.ulb:ConvergentDivergentFormula) {
; Switch Convergent/Divergent Formula base class.
public:
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchConvergentDivergentFormula(Generic pparent)
ConvergentDivergentFormula.ConvergentDivergentFormula(pparent)
if (fType = @p_mandy)
fValue = fConstant = @p_start
else
fValue = fConstant = @p_seed
endif
endfunc
; Note that here zold is initialised to initial z
; @param pz the location (normally #pixel)
; @return initial z for iteration
complex func Init(complex pz)
ConvergentDivergentFormula.Init(pz)
if fType
fConstant = pz
if @p_addpixel
m_ZOld = fValue + fConstant
return m_ZOld
else
m_ZOld = fValue
return fValue
endif
else
m_ZOld = pz
return pz
endif
endfunc
; @param f flag for Mandelbrot or Julia mode, is true for Mandelbrots
; @param v the value to be used as the start value or constant
func SetParams(bool f,complex v)
if !@p_manual
fType = f
fValue = fConstant = v
endif
endfunc
protected:
complex fConstant
complex fValue
bool fType
default:
int param v_mmfswitchconvergentdivergentformula
caption = "Version (MMF_SwitchConvergentDivergentFormula)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @v_mmfswitchconvergentdivergentformula < 100
endparam
heading
caption = "Information"
text = "This formula object is intended for use with the 'Generic \
Switch Formula' in mmf5.ufm and in formula objects that \
allow switching, however it will still function without \
switching in non-switching formulas and formula objects."
endheading
heading
enabled = false
endheading
bool param p_manual
caption = "Manual Over-ride"
default = false
hint = "When enabled you will have manual control of the \
Mandelbrot/Julia switching and the associated parameters \
i.e. you will be able to over-ride the settings from the \
parent object. Note that this will effectively disable \
UF's built-in switching but allow full use of this formula \
when not used with a compatible switching parent."
endparam
bool param p_mandy
caption = "Mandelbrot ?"
default = true
hint = "Disable for Julia mode."
visible = @p_manual
endparam
complex param p_start
caption = "Mandelbrot Start Value"
default = (0,0)
visible = @p_manual && @p_mandy
endparam
complex param p_seed
caption = "Julia Constant"
default = (-1.25,0)
visible = @p_manual && !@p_mandy
endparam
bool param p_addpixel
caption = "Offset z start"
default = false
hint = "When enabled the z start value (in Mandelbrot mode) is offset \
by the constant for the current position - normally '#pixel'."
visible = !@p_manual || @p_mandy
endparam
}
class MMF_SwitchStandard(MMF_SwitchDivergentFormula) {
;
; Generic Switchable Mandelbrot set.
;
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchStandard(Generic pparent)
MMF_SwitchDivergentFormula.MMF_SwitchDivergentFormula(pparent)
endfunc
complex func Iterate(complex pz)
if @p_advanced && @p_switch=="Power"
return pz^fConstant + @p_seed1
else
return pz^@p_power + fConstant
endif
endfunc
default:
title = "Switch Standard"
rating = recommended
bool param p_advanced
caption = "Enable Advanced Settings"
default = false
hint = "When enabled you can choose which variable is switchable."
endparam
int param p_switch
caption = "Switch Value"
enum = "Normal" "Power"
default = 1
hint = "In 'Normal' mode the constant c in z^p+c is the switchable \
variable, in 'Power' mode the power p in z^p+c is used \
instead."
visible = @p_advanced
endparam
complex param p_seed1
caption = "Seed"
default = (0.25,0)
hint = "The constant c in z^p+c."
visible = @p_advanced && @p_switch>0
endparam
complex param p_power
caption = "Power"
default = (2,0)
hint = "This parameter sets the exponent for the standard z^p+c \
formula. Increasing the real part to 3, 4, and so on, \
will add discs to the Mandelbrot figure. Non-integer \
real values and non-zero imaginary values will create \
distorted sets. Use (2, 0) for the standard Mandelbrot/Julia \
sets."
visible = !@p_advanced || @p_switch!=1
endparam
}
class MMF_SwitchCardioid(MMF_SwitchDivergentFormula) {
;
; This formula is based on the generic form for a cardioid.
;
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchCardioid(Generic pparent)
MMF_SwitchDivergentFormula.MMF_SwitchDivergentFormula(pparent)
endfunc
complex func Iterate(complex pz)
if @p_advanced && @p_switch=="Offset"
return (sqr(pz+fConstant)+@p_diameter*real(pz+fConstant))^@p_power \
-(sqr(@p_diameter2)*sqr(pz+@p_offset2))^@p_power2+@p_seed1
elseif @p_advanced && @p_switch=="Offset 2"
return (sqr(pz+@p_offset)+@p_diameter*real(pz+@p_offset))^@p_power \
-(sqr(@p_diameter2)*sqr(pz+fConstant))^@p_power2+@p_seed1
elseif @p_advanced && @p_switch=="Diameter"
return (sqr(pz+@p_offset)+fConstant*real(pz+@p_offset))^@p_power \
-(sqr(@p_diameter2)*sqr(pz+@p_offset2))^@p_power2+@p_seed1
elseif @p_advanced && @p_switch=="Diameter 2"
return (sqr(pz+@p_offset)+@p_diameter*real(pz+@p_offset))^@p_power \
-(sqr(fConstant)*sqr(pz+@p_offset2))^@p_power2+@p_seed1
elseif @p_advanced && @p_switch=="Power"
return (sqr(pz+@p_offset)+@p_diameter*real(pz+@p_offset))^fConstant \
-(sqr(@p_diameter2)*sqr(pz+@p_offset2))^@p_power2+@p_seed1
elseif @p_advanced && @p_switch=="Power 2"
return (sqr(pz+@p_offset)+@p_diameter*real(pz+@p_offset))^@p_power \
-(sqr(@p_diameter2)*sqr(pz+@p_offset2))^fConstant+@p_seed1
else
return (sqr(pz+@p_offset)+@p_diameter*real(pz+@p_offset))^@p_power \
-(sqr(@p_diameter2)*sqr(pz+@p_offset2))^@p_power2+fConstant
endif
endfunc
default:
title = "Switch Cardioid"
rating = recommended
bool param p_advanced
caption = "Enable Advanced Settings"
default = false
hint = "When enabled you can choose which variable is switchable."
endparam
int param p_switch
caption = "Switch Value"
enum = "Normal" "Power" "Power 2" "Diameter" "Diameter 2" "Offset" \
"Offset 2"
default = 0
hint = "In 'Normal' mode the constant c in \
(sqr(z+offset)+diameter*real(z+offset))^power \
-(sqr(diameter2)*sqr(pz+offset2))^power2+c is the switchable \
variable (Seed), in the other modes the chosen parameter is used \
instead."
visible = @p_advanced
endparam
complex param p_seed1
caption = "Seed"
default = (0.25,0)
hint = "The constant c"
visible = @p_advanced && @p_switch>0
endparam
complex param p_power
caption = "Power"
default = (2,0)
hint = "This parameter sets the exponent for the first part pf the cardioid \
formula. Increasing the real part to 3, 4, and so on, \
will add discs to the Mandelbrot figure. Non-integer \
real values and non-zero imaginary values will create \
distorted sets. Use (2, 0) for the standard Cardioid"
visible = !@p_advanced || @p_switch!=1
endparam
complex param p_power2
caption = "Power 2"
default = (1,0)
hint = "This parameter sets the exponent for the secons part of the \
cardioid formula. Use (1, 0) for the standard Cardioid."
visible = !@p_advanced || @p_switch!=2
endparam
complex param p_diameter
caption = "Diameter"
default = (0.5,0)
hint = "The diameter for the first part of the cardioid formula"
visible = !@p_advanced || @p_switch!=3
endparam
complex param p_diameter2
caption = "Diameter 2"
default = (0.5,0)
hint = "The diameter for the second part of the cardioid formula"
visible = !@p_advanced || @p_switch!=4
endparam
complex param p_offset
caption = "Offset"
default = (0,0)
hint = "The offset for the first part of the cardioid formula"
visible = !@p_advanced || @p_switch!=5
endparam
complex param p_offset2
caption = "Offset 2"
default = (0,0)
hint = "The offset for the second part of the cardioid formula"
visible = !@p_advanced || @p_switch!=6
endparam
}
class MMF_SwitchPhoenix(MMF_SwitchDivergentFormula) {
;
; Switchable object version of the Phoenix.
; The general equation is of the form
;
; z(n+1) = z(n)^a + c*z(n)^b + p*z(n-1)
;
; Originators: Damien M. Jones, Shigehiro Ushiki
;
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchPhoenix(Generic pparent)
MMF_SwitchDivergentFormula.MMF_SwitchDivergentFormula(pparent)
endfunc
complex func Init(complex pz)
fOld = (0, 0)
return MMF_SwitchDivergentFormula.Init(pz)
endfunc
complex func Iterate(complex pz)
complex newz
if !@p_advanced || @p_switch=="Normal"
newz = pz^@p_power + pz^@power2 * fConstant + @induct * fOld
elseif @p_switch=="Exponent 1"
newz = pz^fConstant + pz^@power2 * @p_seed1 + @induct * fOld
elseif @p_switch=="Exponent 2"
newz = pz^@p_power + pz^fConstant * @p_seed1 + @induct * fOld
else;if @p_switch=="Distortion"
newz = pz^@p_power + pz^@power2 * @p_seed1 + fConstant * fOld
endif
fOld = pz
return newz
endfunc
private:
complex fOld
default:
title = "Switch Phoenix"
rating = recommended
bool param p_addpixel
caption = "Offset z start"
default = false
hint = "When enabled the z start value (in Mandelbrot mode) is offset \
by the constant for the current position - normally '#pixel'. \
When your z start value is (0,0) then enable this for the \
original functionality of the Phoenix formula i.e. so that \
non-zero values of 'Exponent 2' will produce a Mandelbrot \
although it should be noted that leaving this disabled and \
using a Mandelbrot Start value of say 1e-5 may give a \
better Mandelbrot guide to the available Julia Sets."
visible = !@p_manual || @p_mandy
endparam
bool param p_advanced
caption = "Enable Advanced Settings"
default = false
hint = "When enabled you can choose which variable is switchable."
endparam
int param p_switch
caption = "Switch Value"
enum = "Normal" "Exponent 1" "Exponent 2" "Distortion"
default = 3
hint = "In 'Normal' mode the additive constant is the switchable \
variable, in the other modes the relevant values are made \
switchable instead."
visible = @p_advanced
endparam
complex param p_seed1
caption = "Seed"
default = (-1,0)
hint = "The constant c in z(n)^a + c*z(n)^b + p*z(n-1)."
visible = @p_advanced && @p_switch>0
endparam
complex param p_power ; Overrides p_power from Formula
caption = "Exponent 1"
default = (2,0)
hint = "Defines the primary exponent for the fractal. The classic \
Phoenix curve uses exponent (2, 0)."
visible = !@p_advanced || @p_switch!=1
endparam
complex param power2
caption = "Exponent 2"
default = (0,0)
hint = "Defines the secondary exponent for the fractal. The classic \
Phoenix curve uses exponent (0, 0)."
visible = !@p_advanced || @p_switch!=2
endparam
complex param induct
caption = "Distortion"
default = (0.5,0)
hint = "Sets how 'strong' the previous iteration's effect should be \
on the fractal."
visible = !@p_advanced || @p_switch!=3
endparam
float param p_bailout ; Overrides p_bailout from DivergentFormula
caption = "Bailout"
default = 1.0e20
exponential = true
hint = "This parameter defines how soon an orbit bails out while \
iterating. Larger values will give smoother outlines."
endparam
}
class MMF_SwitchNova(MMF_SwitchConvergentDivergentFormula) {
;
; Object version of NovaMandel for switching
;
; Nova fractal (Mandelbrot form), a modified Newtonian-style fractal.
; Object switch version by David Makin
;
; Originators Damien M. Jones, Paul Derbyshire
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchNova(Generic pparent)
MMF_SwitchConvergentDivergentFormula.MMF_SwitchConvergentDivergentFormula(pparent)
endfunc
; Note that here if the formula is in Mandelbrot mode then one is added
; to the start value by default.
; @param f flag, true for Mandelbrot mode, false for Julia mode
; @param v either the start value or the constant
func SetParams(bool f,complex v)
if !@p_manual
if (fType = f)
fValue = fConstant = v + 1.0
else
fValue = fConstant = v
endif
endif
endfunc
complex func Init(complex pz)
complex zz = MMF_SwitchConvergentDivergentFormula.Init(pz)
if @p_advanced && @p_switch=="Exponent"
pm1 = fConstant - 1.0
endif
return zz
endfunc
complex func Iterate(complex pz)
MMF_SwitchConvergentDivergentFormula.Iterate(pz)
if !@p_advanced || @p_switch=="Normal"
if @p_power == (3, 0) ; special optimized routine for power 3
complex zsquared = sqr(pz)
return pz - @relax * (zsquared*pz-1.0) / (3.0*zsquared) + fConstant
else
return pz - @relax * (pz^@p_power-1.0) \
/ (@p_power * pz^(@p_power-1.0)) + fConstant
endif
elseif @p_switch=="Exponent"
return pz - @relax * (pz^fConstant-1.0) \
/ (fConstant * pz^pm1) + @p_seed1
else;if @p_switch=="Relaxation"
return pz - fConstant * (pz^@p_power-1.0) \
/ (@p_power * pz^(@p_power-1.0)) + @p_seed1
endif
endfunc
bool func IsBailedOut(complex pz)
if ((@p_BailType=="Divergent" || @p_BailType=="Both") \
&& |pz|>@p_bailout1) \
|| ((@p_BailType=="Convergent" || @p_BailType=="Both") \
&& |pz-m_ZOld|<@p_bailout)
m_BailedOut = true
endif
return m_BailedOut
endfunc
float func GetUpperBailout()
return @p_bailout1
endfunc
float func GetLowerBailout()
return @p_bailout
endfunc
private:
complex pm1
default:
title = "Switch Nova"
rating = recommended
float param p_lowerbailout
visible = false
endparam
float param p_upperbailout
visible = false
endparam
complex param p_start
caption = "Mandelbrot Start Value"
default = (1,0)
visible = @p_manual && @p_mandy
endparam
complex param p_seed
caption = "Julia Seed"
default = (0,0)
visible = @p_manual && !@p_mandy
endparam
heading
caption = "Information"
text = "It should be noted that when using the Mandelbrot Start \
Value from a parent switching formula 1 is added to the \
value since generally the parental default will be (0,0) \
and the standard start value for Nova is (1,0)."
endheading
heading
enabled = false
endheading
bool param p_advanced
caption = "Enable Advanced Settings"
default = false
hint = "When enabled you can choose which variable is switchable."
endparam
int param p_switch
caption = "Switch Value"
enum = "Normal" "Exponent" "Relaxation"
default = 2
hint = "In 'Normal' mode the additive constant is the switchable \
variable, in the other modes the relevant values are made \
switchable instead."
visible = @p_advanced
endparam
complex param p_seed1
caption = "Seed"
default = (-0.4,0.425)
hint = "The additive constant."
visible = @p_advanced && @p_switch>0
endparam
complex param p_power
caption = "Exponent"
default = (3,0)
hint = "Overall exponent for the equation. The value (3,0) gives \
the classic Nova fractals."
visible = !@p_advanced || @p_switch!=1
endparam
complex param relax
caption = "Relaxation"
default = (1,0)
hint = "This can be used to slow down the convergence of \
the formula."
visible = !@p_advanced || @p_switch!=2
endparam
int param p_BailType
caption = "Bailout Type"
enum = "Divergent" "Convergent" "Both"
default = 1
endparam
float param p_bailout
caption = "Convergent Bailout"
default = 0.00001
exponential = true
hint = "Convergent bailout value; smaller values will cause more \
iterations to be done for each point."
visible = @p_BailType>0
endparam
float param p_bailout1
caption = "Divergent Bailout"
default = 1e20
exponential = true
hint = "Divergent bailout value; it's best to use large values to \
avoid erroneous detection of divergent bailout in convergent \
areas."
visible = @p_BailType!=1
endparam
}
class MMF_SwitchMagnet1(MMF_SwitchConvergentDivergentFormula) {
;
; Object version of Magnet 1 for switching
;
; Object switch version by David Makin
;
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchMagnet1(Generic pparent)
MMF_SwitchConvergentDivergentFormula.MMF_SwitchConvergentDivergentFormula(pparent)
endfunc
complex func Iterate(complex pz)
MMF_SwitchConvergentDivergentFormula.Iterate(pz)
return sqr( (pz^2 + fConstant - 1) / (2*pz + fConstant - 2) )
endfunc
bool func IsBailedOut(complex pz)
if ((@p_BailType=="Divergent" || @p_BailType=="Both") \
&& |pz|>@p_upperbailout) \
|| ((@p_BailType=="Convergent" || @p_BailType=="Both") \
&& ((!fType && |pz-m_ZOld|<@p_lowerbailout) \
|| (fType && |pz-1.0|<@p_lowerbailout)))
m_BailedOut = true
endif
return m_BailedOut
endfunc
float func GetUpperBailout()
return @p_upperbailout
endfunc
float func GetLowerBailout()
return @p_lowerbailout
endfunc
default:
title = "Switch Magnet 1"
rating = recommended
complex param p_power
visible = false
endparam
complex param p_start
caption = "Mandelbrot Start Value"
default = (0,0)
visible = @p_manual && @p_mandy
endparam
complex param p_seed
caption = "Julia Seed"
default = (0,0)
visible = @p_manual && !@p_mandy
endparam
int param p_BailType
caption = "Bailout Type"
enum = "Divergent" "Convergent" "Both"
default = 2
endparam
float param p_lowerbailout
caption = "Convergent Bailout"
default = 1e-14
exponential = true
hint = "Convergent bailout value; smaller values will cause more \
iterations to be done for each point."
visible = @p_BailType>0
endparam
float param p_upperbailout
caption = "Divergent Bailout"
default = 1e20
exponential = true
hint = "Divergent bailout value; it's best to use large values to \
avoid erroneous detection of divergent bailout in convergent \
areas."
visible = @p_BailType!=1
endparam
}
class MMF_SwitchMagnet2(MMF_SwitchConvergentDivergentFormula) {
;
; Object version of Magnet 2 for switching
;
; Object switch version by David Makin
;
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchMagnet2(Generic pparent)
MMF_SwitchConvergentDivergentFormula.MMF_SwitchConvergentDivergentFormula(pparent)
endfunc
complex func Iterate(complex pz)
MMF_SwitchConvergentDivergentFormula.Iterate(pz)
return sqr((pz^3.0 + 3.0*(fConstant-1.0)*pz \
+ (fConstant-1.0)*(fConstant-2.0)) \
/(3.0*sqr(pz) + 3.0*(fConstant-2.0)*pz \
+ (fConstant-1.0)*(fConstant-2.0) + 1.0))
endfunc
bool func IsBailedOut(complex pz)
if ((@p_BailType=="Divergent" || @p_BailType=="Both") \
&& |pz|>@p_upperbailout) \
|| ((@p_BailType=="Convergent" || @p_BailType=="Both") \
&& ((!fType && |pz-m_ZOld|<@p_lowerbailout) \
|| (fType && |pz-1.0|<@p_lowerbailout)))
m_BailedOut = true
endif
return m_BailedOut
endfunc
float func GetUpperBailout()
return @p_upperbailout
endfunc
float func GetLowerBailout()
return @p_lowerbailout
endfunc
default:
title = "Switch Magnet 2"
rating = recommended
complex param p_power
visible = false
endparam
complex param p_start
caption = "Mandelbrot Start Value"
default = (0,0)
visible = @p_manual && @p_mandy
endparam
complex param p_seed
caption = "Julia Seed"
default = (0,0)
visible = @p_manual && !@p_mandy
endparam
int param p_BailType
caption = "Bailout Type"
enum = "Divergent" "Convergent" "Both"
default = 2
endparam
float param p_lowerbailout
caption = "Convergent Bailout"
default = 1e-9
exponential = true
hint = "Convergent bailout value; smaller values will cause more \
iterations to be done for each point."
visible = @p_BailType>0
endparam
float param p_upperbailout
caption = "Divergent Bailout"
default = 1e20
exponential = true
hint = "Divergent bailout value; it's best to use large values to \
avoid erroneous detection of divergent bailout in convergent \
areas."
visible = @p_BailType!=1
endparam
}
class MMF_SwitchFormulaWars2(MMF_SwitchConvergentDivergentFormula) {
; Object version of the MMF Formula Wars 2 formula
; Extended to allow the combination of up to 6 formulae
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchFormulaWars2(Generic pparent)
MMF_SwitchConvergentDivergentFormula.MMF_SwitchConvergentDivergentFormula(pparent)
fFormula1=new @classFormula1(this)
fFormula2=new @classFormula2(this)
fFormula3=new @classFormula3(this)
fFormula4=new @classFormula4(this)
fFormula5=new @classFormula5(this)
fFormula6=new @classFormula6(this)
SetParams(fType,fConstant)
endfunc
complex func Init(complex pz)
m_Iterations = 0
m_BailedOut = false
fz[0] = fFormula1.Init(pz)
fz[1] = fFormula2.Init(pz)
if @p_NumFormulas=="3" || @p_NumFormulas=="4" || @p_NumFormulas=="5" \
|| @p_NumFormulas=="6"
fz[2] = fFormula3.Init(pz)
if @p_NumFormulas=="4" || @p_NumFormulas=="5" || @p_NumFormulas=="6"
fz[3] = fFormula4.Init(pz)
if @p_NumFormulas=="5" || @p_NumFormulas=="6"
fz[4] = fFormula5.Init(pz)
if @p_NumFormulas=="6"
fz[5] = fFormula6.Init(pz)
endif
endif
endif
endif
if fType
fConstant = pz
return fValue
else
return pz
endif
endfunc
func SetParams(bool f,complex v)
if !@p_manual
fType = f
fValue = fConstant = v
endif
if @classFormula1==MMF_SwitchFormula
MMF_SwitchFormula(fFormula1).SetParams(fType,fConstant)
elseif @classFormula1==MMF_SwitchDivergentFormula
MMF_SwitchDivergentFormula(fFormula1).SetParams(fType,fConstant)
elseif @classFormula1==MMF_SwitchConvergentFormula
MMF_SwitchConvergentFormula(fFormula1).SetParams(fType,fConstant)
elseif @classFormula1==MMF_SwitchConvergentDivergentFormula
MMF_SwitchConvergentDivergentFormula(fFormula1).SetParams(fType,fConstant)
endif
if @classFormula2==MMF_SwitchFormula
MMF_SwitchFormula(fFormula2).SetParams(fType,fConstant)
elseif @classFormula2==MMF_SwitchDivergentFormula
MMF_SwitchDivergentFormula(fFormula2).SetParams(fType,fConstant)
elseif @classFormula2==MMF_SwitchConvergentFormula
MMF_SwitchConvergentFormula(fFormula2).SetParams(fType,fConstant)
elseif @classFormula2==MMF_SwitchConvergentDivergentFormula
MMF_SwitchConvergentDivergentFormula(fFormula2).SetParams(fType,fConstant)
endif
if @p_NumFormulas=="3" || @p_NumFormulas=="4" || @p_NumFormulas=="5" \
|| @p_NumFormulas=="6"
if @classFormula3==MMF_SwitchFormula
MMF_SwitchFormula(fFormula3).SetParams(fType,fConstant)
elseif @classFormula3==MMF_SwitchDivergentFormula
MMF_SwitchDivergentFormula(fFormula3).SetParams(fType,fConstant)
elseif @classFormula3==MMF_SwitchConvergentFormula
MMF_SwitchConvergentFormula(fFormula3).SetParams(fType,fConstant)
elseif @classFormula3==MMF_SwitchConvergentDivergentFormula
MMF_SwitchConvergentDivergentFormula(fFormula3).SetParams(fType,fConstant)
endif
if @p_NumFormulas=="4" || @p_NumFormulas=="5" || @p_NumFormulas=="6"
if @classFormula4==MMF_SwitchFormula
MMF_SwitchFormula(fFormula4).SetParams(fType,fConstant)
elseif @classFormula4==MMF_SwitchDivergentFormula
MMF_SwitchDivergentFormula(fFormula4).SetParams(fType,fConstant)
elseif @classFormula4==MMF_SwitchConvergentFormula
MMF_SwitchConvergentFormula(fFormula4).SetParams(fType,fConstant)
elseif @classFormula4==MMF_SwitchConvergentDivergentFormula
MMF_SwitchConvergentDivergentFormula(fFormula4).SetParams(fType,fConstant)
endif
if @p_NumFormulas=="5" || @p_NumFormulas=="6"
if @classFormula5==MMF_SwitchFormula
MMF_SwitchFormula(fFormula5).SetParams(fType,fConstant)
elseif @classFormula5==MMF_SwitchDivergentFormula
MMF_SwitchDivergentFormula(fFormula5).SetParams(fType,fConstant)
elseif @classFormula5==MMF_SwitchConvergentFormula
MMF_SwitchConvergentFormula(fFormula5).SetParams(fType,fConstant)
elseif @classFormula5==MMF_SwitchConvergentDivergentFormula
MMF_SwitchConvergentDivergentFormula(fFormula5).SetParams(fType,fConstant)
endif
if @p_NumFormulas=="6"
if @classFormula6==MMF_SwitchFormula
MMF_SwitchFormula(fFormula6).SetParams(fType,fConstant)
elseif @classFormula6==MMF_SwitchDivergentFormula
MMF_SwitchDivergentFormula(fFormula6).SetParams(fType,fConstant)
elseif @classFormula6==MMF_SwitchConvergentFormula
MMF_SwitchConvergentFormula(fFormula6).SetParams(fType,fConstant)
elseif @classFormula6==MMF_SwitchConvergentDivergentFormula
MMF_SwitchConvergentDivergentFormula(fFormula6).SetParams(fType,fConstant)
endif
endif
endif
endif
endif
endfunc
complex func Iterate(complex pz)
fzt = pz
if m_Iterations==0
fZold = fzt = fz[0]
else
fZold = pz
endif
if @p_Method=="Alternate"
int i = m_Iterations%(@p_NumFormulas+2)
m_Iterations = m_Iterations + 1
if i==0
fzz = fFormula1.Iterate(fzt)
elseif i==1
fzz = fFormula2.Iterate(fzt)
elseif i==2
fzz = fFormula3.Iterate(fzt)
elseif i==3
fzz = fFormula4.Iterate(fzt)
elseif i==4
fzz = fFormula5.Iterate(fzt)
elseif i==5
fzz = fFormula6.Iterate(fzt)
endif
else; @p_Method!="Alternate"
m_Iterations = m_Iterations + 1
fzz = fzt = fFormula1.Iterate(fzt)
if @p_Method!="Mix All"
if m_Iterations==1
fzt = fz[1]
else
fzt = pz
endif
endif
fzt = fFormula2.Iterate(fzt)
CheckVals(1)
if @p_NumFormulas=="3" || @p_NumFormulas=="4" || @p_NumFormulas=="5" \
|| @p_NumFormulas=="6"
if @p_Method!="Mix All"
if m_Iterations==1
fzt = fz[2]
else
fzt = pz
endif
endif
fzt = fFormula3.Iterate(fzt)
CheckVals(2)
if @p_NumFormulas=="4" || @p_NumFormulas=="5" || @p_NumFormulas=="6"
if @p_Method!="Mix All"
if m_Iterations==1
fzt = fz[3]
else
fzt = pz
endif
endif
fzt = fFormula4.Iterate(fzt)
CheckVals(3)
if @p_NumFormulas=="5" || @p_NumFormulas=="6"
if @p_Method!="Mix All"
if m_Iterations==1
fzt = fz[4]
else
fzt = pz
endif
endif
fzt = fFormula5.Iterate(fzt)
CheckVals(4)
if @p_NumFormulas=="6"
if @p_Method!="Mix All"
if m_Iterations==1
fzt = fz[5]
else
fzt = pz
endif
endif
fzt = fFormula6.Iterate(fzt)
CheckVals(5)
endif
endif
endif
endif
if @p_Method=="Mix All"
fzz = fzt
endif
endif; @p_Method=="Alternate"
return fzz
endfunc
bool func IsBailedOut(complex pz)
if ((@p_BailType=="Divergent" || @p_BailType=="Both" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz|>=@p_Bailout) \
|| ((@p_BailType=="Convergent" || @p_BailType=="Both") \
&& |pz-fZold|<=@p_SmallBail) \
|| ((@p_BailType=="Absolute Convergence" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz-@p_root|<=@p_SmallBail )
m_BailedOut = true
endif
return m_BailedOut
endfunc
float func GetUpperBailout()
return @p_Bailout
endfunc
float func GetLowerBailout()
return @p_SmallBail
endfunc
private:
; Updates the z value to use according to the selected condition
; @param i the formula number
func CheckVals(int i)
if @p_Method=="Minimum Magnitude"
if |fzt-@p_Coord|<|fzz-@p_Coord|
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Maximum Magnitude"
if |fzt-@p_Coord|>|fzz-@p_Coord|
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Minimum Abs. Real"
if abs(real(fzt)-real(@p_coord))<=abs(real(fzz)-real(@p_coord))
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Maximum Abs. Real"
if abs(real(fzt)-real(@p_coord))>abs(real(fzz)-real(@p_coord))
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Minimum Abs. Imaginary"
if abs(imag(fzt)-imag(@p_coord))<=abs(imag(fzz)-imag(@p_coord))
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Maximum Abs. Imaginary"
if abs(imag(fzt)-imag(@p_coord))>abs(imag(fzz)-imag(@p_coord))
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Minimum Real"
if real(fzt)-real(@p_coord)<=real(fzz)-real(@p_coord)
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Maximum Real"
if real(fzt)-real(@p_coord)>real(fzz)-real(@p_coord)
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Minimum Imaginary"
if imag(fzt)-imag(@p_coord)<=imag(fzz)-imag(@p_coord)
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Maximum Imaginary"
if imag(fzt)-imag(@p_coord)>imag(fzz)-imag(@p_coord)
fzz = fzt
if m_Iterations==1
fZold = fz[i]
endif
endif
elseif @p_Method=="Abs. Minima"
if abs(real(fzt)-real(@p_coord))<=abs(real(fzz)-real(@p_coord))
fzz = real(fzt) + flip(imag(fzz))
if m_Iterations==1
fZold = real(fz[i]) + flip(imag(fZold))
endif
endif
if abs(imag(fzt)-imag(@p_coord))<=abs(imag(fzz)-imag(@p_coord))
fzz = real(fzz) + flip(imag(fzt))
if m_Iterations==1
fZold = real(fZold) + flip(imag(fz[i]))
endif
endif
elseif @p_Method=="Abs. Maxima"
if abs(real(fzt)-real(@p_coord))>abs(real(fzz)-real(@p_coord))
fzz = real(fzt) + flip(imag(fzz))
if m_Iterations==1
fZold = real(fz[i]) + flip(imag(fZold))
endif
endif
if abs(imag(fzt)-imag(@p_coord))>abs(imag(fzz)-imag(@p_coord))
fzz = real(fzz) + flip(imag(fzt))
if m_Iterations==1
fZold = real(fZold) + flip(imag(fz[i]))
endif
endif
elseif @p_Method=="Minima"
if real(fzt)-real(@p_coord)<=real(fzz)-real(@p_coord)
fzz = real(fzt) + flip(imag(fzz))
if m_Iterations==1
fZold = real(fz[i]) + flip(imag(fZold))
endif
endif
if imag(fzt)-imag(@p_coord)<=imag(fzz)-imag(@p_coord)
fzz = real(fzz) + flip(imag(fzt))
if m_Iterations==1
fZold = real(fZold) + flip(imag(fz[i]))
endif
endif
elseif @p_Method=="Maxima"
if real(fzt)-real(@p_coord)>real(fzz)-real(@p_coord)
fzz = real(fzt) + flip(imag(fzz))
if m_Iterations==1
fZold = real(fz[i]) + flip(imag(fZold))
endif
endif
if imag(fzt)-imag(@p_coord)>imag(fzz)-imag(@p_coord)
fzz = real(fzz) + flip(imag(fzt))
if m_Iterations==1
fZold = real(fZold) + flip(imag(fz[i]))
endif
endif
endif
endfunc
Formula fFormula1
Formula fFormula2
Formula fFormula3
Formula fFormula4
Formula fFormula5
Formula fFormula6
complex fz[6]
complex fZold
complex fzt
complex fzz
default:
title = "Switch Formula Wars #2"
rating = recommended
int param v_mmfswitchformulawars2
caption = "Version (Switch Formula Wars #2)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
complex param p_power
visible = false
endparam
float param p_upperbailout
visible = false
endparam
float param p_lowerbailout
visible = false
endparam
bool param p_addpixel
visible = false
endparam
heading
caption = "Bailout Options"
text = "You should note that the bailout options and values you set \
here will override the bailout settings in the various formula \
parameters. This is because your chosen warring combination \
could produce either convergent or divergent results whereas \
some of your warring formulas may be convergent and others \
divergent."
endheading
int param p_BailType
caption = "Bailout Type"
enum = "Divergent" "Convergent" "Both" "Absolute Convergence" \
"Div.+Abs.Conv."
default = 0
hint = "If you get an empty or nearly empty fractal try switching \
from 'Divergent' to 'Convergent' or vice-versa or choosing \
'Both'. Note that in some cases if your fractal is a \
Mandelbrot you may need to ensure that the zstart value \
is non-zero."
endparam
complex param p_root
caption = "Convergence Value"
default = (1,0)
hint = "This is the value for testing for convergence to. For the \
'Magnet' formulas the value should be (1,0), if you don't \
know the value to use it's best to stick to the plain \
'Convergent' 'Bailout Type'. It's always worth trying (0,0)."
visible = @p_BailType>2
endparam
float param p_Bailout
caption = "Divergent Bailout"
default = 128.0
hint = "In general larger values will require higher iterations."
visible = @p_BailType==0 || @p_BailType==2 || @p_BailType==4
endparam
float param p_SmallBail
caption = "Convergent Bailout"
default = 1e-5
hint = "In general smaller values will require higher iterations."
visible = @p_BailType>0
endparam
heading
caption = "War Settings"
endheading
int param p_Method
caption = "Method of choice"
enum = "Minimum Magnitude" "Maximum Magnitude" "Minimum Abs. Real" \
"Maximum Abs. Real" "Minimum Abs. Imaginary" \
"Maximum Abs. Imaginary" "Minimum Real" "Maximum Real" \
"Minimum Imaginary" "Maximum Imaginary" "Abs. Minima" \
"Abs. Maxima" "Minima" "Maxima" "Mix All" "Alternate"
default = 0
endparam
complex param p_Coord
caption = "Centre"
default = (0,0)
hint = "Used as the centre for the testing to decide which \
formula to use on each iteration."
visible = @p_Method<6
endparam
int param p_NumFormulas
caption = "Number of Formulas"
enum = "2" "3" "4" "5" "6"
default = 0
endparam
heading
caption = "The Warring Formulas"
endheading
heading
caption = "Warring Formula #1"
endheading
heading
text = "'Fractal Formula #1' is not a switch formula and so will \
not switch using UFs built-in switch method."
visible = @classFormula1!=MMF_SwitchFormula \
&& @classFormula1!=MMF_SwitchDivergentFormula \
&& @classFormula1!=MMF_SwitchConvergentFormula \
&& @classFormula1!=MMF_SwitchConvergentDivergentFormula
endheading
Formula param classFormula1
caption = "Fractal Formula #1"
default = MMF_SwitchStandard
endparam
heading
caption = "Warring Formula #2"
endheading
heading
text = "'Fractal Formula #2' is not a switch formula and so will \
not switch using UFs built-in switch method."
visible = @classFormula2!=MMF_SwitchFormula \
&& @classFormula2!=MMF_SwitchDivergentFormula \
&& @classFormula2!=MMF_SwitchConvergentFormula \
&& @classFormula2!=MMF_SwitchConvergentDivergentFormula
endheading
Formula param classFormula2
caption = "Fractal Formula #2"
default = MMF_SwitchStandard
endparam
heading
caption = "Warring Formula #3"
visible = @p_NumFormulas>0
endheading
heading
text = "'Fractal Formula #3' is not a switch formula and so will \
not switch using UFs built-in switch method."
visible = @p_NumFormulas>0 && @classFormula3!=MMF_SwitchFormula \
&& @classFormula3!=MMF_SwitchDivergentFormula \
&& @classFormula3!=MMF_SwitchConvergentFormula \
&& @classFormula3!=MMF_SwitchConvergentDivergentFormula
endheading
Formula param classFormula3
caption = "Fractal Formula #3"
default = MMF_SwitchStandard
visible = @p_NumFormulas>0
endparam
heading
caption = "Warring Formula #4"
visible = @p_NumFormulas>1
endheading
heading
text = "'Fractal Formula #4' is not a switch formula and so will \
not switch using UFs built-in switch method."
visible = @p_NumFormulas>1 && @classFormula4!=MMF_SwitchFormula \
&& @classFormula4!=MMF_SwitchDivergentFormula \
&& @classFormula4!=MMF_SwitchConvergentFormula \
&& @classFormula4!=MMF_SwitchConvergentDivergentFormula
endheading
Formula param classFormula4
caption = "Fractal Formula #4"
default = MMF_SwitchStandard
visible = @p_NumFormulas>1
endparam
heading
caption = "Warring Formula #5"
visible = @p_NumFormulas>2
endheading
heading
text = "'Fractal Formula #5' is not a switch formula and so will \
not switch using UFs built-in switch method."
visible = @p_NumFormulas>2 && @classFormula5!=MMF_SwitchFormula \
&& @classFormula5!=MMF_SwitchDivergentFormula \
&& @classFormula5!=MMF_SwitchConvergentFormula \
&& @classFormula5!=MMF_SwitchConvergentDivergentFormula
endheading
Formula param classFormula5
caption = "Fractal Formula #5"
default = MMF_SwitchStandard
visible = @p_NumFormulas>2
endparam
heading
caption = "Warring Formula #6"
visible = @p_NumFormulas>3
endheading
heading
text = "'Fractal Formula #6' is not a switch formula and so will \
not switch using UFs built-in switch method."
visible = @p_NumFormulas>3 && @classFormula6!=MMF_SwitchFormula \
&& @classFormula6!=MMF_SwitchDivergentFormula \
&& @classFormula6!=MMF_SwitchConvergentFormula \
&& @classFormula6!=MMF_SwitchConvergentDivergentFormula
endheading
Formula param classFormula6
caption = "Fractal Formula #6"
default = MMF_SwitchStandard
visible = @p_NumFormulas>3
endparam
}
class MMF_TransformMod(common.ulb:UserTransform) {
; Applies a modulus
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TransformMod(Generic pparent)
UserTransform.UserTransform(pparent)
fTransform1 = new @p_Transform1(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fTransform1.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
pz = pz*@p_scale
return fTransform1.Iterate(real(pz)%real(@p_modulus) \
+flip(imag(pz)%imag(@p_modulus)))
endfunc
private:
Transform fTransform1
default:
title = "Transform Modulus"
complex param p_modulus
caption = "Modulus"
default = (1.0,1.0)
hint = "Both real and imaginay pats are used, being applied to the real \
and imaginay input values respectively."
endparam
complex param p_scale
caption = "Scale"
default = (1.0,0.0)
hint = "Normally you'd stick to using a wholly real number."
endparam
Transform param p_Transform1
caption = "Following transfom"
default = MMF_GeneralTransform
hint = "The modified value is passsed on to this transform."
endparam
}
class MMF_GeneralTransform(common.ulb:UserTransform) {
; offset,scale,offset,function,offset,scale,offset
public:
complex func Iterate(complex pz)
return ( @p_func((pz + @p_offset)*@p_scale + @p_offset1) \
+ @p_offset2) * @p_scale1 + @p_offset3
endfunc
default:
title = "General Transform"
complex param p_offset
caption = "Initial Pre-Offset"
default = (0,0)
endparam
complex param p_scale
caption = "Pre-Scale"
default = (1,0)
endparam
complex param p_offset1
caption = "Final Pre-Offset"
default = (0,0)
endparam
func p_func
caption = "Function"
default = ident()
endfunc
complex param p_offset2
caption = "Initial Post-Offset"
default = (0,0)
endparam
complex param p_scale1
caption = "Post-Scale"
default = (1,0)
endparam
complex param p_offset3
caption = "Final Post-Offset"
default = (0,0)
endparam
}
class MMF_SwitchRecursion(MMF_SwitchConvergentDivergentFormula) {
; This formula is an adaption of 'Switch Recursion' from mmfs.ufm
; which itself was based on the Lucas recursion formula found on Mathworld.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchRecursion(Generic pparent)
MMF_SwitchConvergentDivergentFormula.MMF_SwitchConvergentDivergentFormula(pparent)
fTransform0 = new @p_Transform0(this)
fTransform1 = new @p_Transform1(this)
fTransformPZ = new @p_TransformPZ(this)
fTransformP = new @p_TransformP(this)
fTransformQZ = new @p_TransformQZ(this)
fTransformQ = new @p_TransformQ(this)
fTransformX = new @p_TransformX(this)
fTransformD = new @p_TransformD(this)
endfunc
complex func Init(complex pz)
; m_Iterations = 0 not used in this formula
m_BailedOut = false
fTransform0.Init(pz)
fTransform1.Init(pz)
fTransformPZ.Init(pz)
fTransformP.Init(pz)
fTransformQZ.Init(pz)
fTransformQ.Init(pz)
fTransformX.Init(pz)
fTransformD.Init(pz)
if fType
fConstant = pz
if @p_addpixel
fZold = pz = fValue + fConstant
else
fZold = pz = fValue
endif
else
fZold = pz
endif
if @p_type=="Iterative"
m_p = m_p0 = fTransform0.Iterate(pz)
m_p1 = fTransform1.Iterate(pz)
m_recursecount = 2
endif
return pz
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this formula
if @p_type=="Normal"
complex p
complex p0 = fTransform0.Iterate(pz)
complex p1 = fTransform1.Iterate(pz)
int i = 2
repeat
p = ((fTransformPZ.Iterate(i)*pz + fTransformP.Iterate(i))*p1 \
+ (fTransformQZ.Iterate(i)*pz + fTransformQ.Iterate(i))*p0) \
/ fTransformD.Iterate(i)
p0 = p1
p1 = p
until (i=i+1)>@p_recurse
m_p = p1
else;if @p_type=="Iterative"
m_p = ((fTransformPZ.Iterate(m_recursecount)*pz \
+ fTransformP.Iterate(m_recursecount))*m_p1 \
+ (fTransformQZ.Iterate(m_recursecount)*pz \
+ fTransformQ.Iterate(m_recursecount))*m_p0) \
/ fTransformD.Iterate(m_recursecount)
m_p0 = m_p1
m_p1 = m_p
m_recursecount = m_recursecount + 1
endif
if @p_fractal=="Pn(z)+c"
m_p = fTransformX.Iterate(m_p) + fConstant
elseif @p_fractal=="c*Pn(z)"
m_p = fConstant*fTransformX.Iterate(m_p)
elseif @p_fractal=="Pn(z)+zold+c"
m_p = fTransformX.Iterate(m_p) + fZold + fConstant
elseif @p_fractal=="c*Pn(z)+zold"
m_p = fConstant*fTransformX.Iterate(m_p) + fZold
elseif @p_fractal=="zold*Pn(z)+c"
m_p = fZold*fTransformX.Iterate(m_p) + fConstant
else;if @p_fractal=="c*zold*Pn(z)"
m_p = fConstant*fZold*fTransformX.Iterate(m_p)
endif
fZold = pz
return m_p
endfunc
bool func IsBailedOut(complex pz)
if ((@p_BailType=="Divergent" || @p_BailType=="Both" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz|>=@p_Bailout) \
|| ((@p_BailType=="Convergent" || @p_BailType=="Both") \
&& |pz-fZold|<=@p_SmallBail) \
|| ((@p_BailType=="Absolute Convergence" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz-@p_root|<=@p_SmallBail )
m_BailedOut = true
endif
return m_BailedOut
endfunc
float func GetUpperBailout()
return @p_Bailout
endfunc
float func GetLowerBailout()
return @p_SmallBail
endfunc
complex func GetPrimaryExponent()
return @p_recurse
endfunc
private:
Transform fTransform0
Transform fTransform1
Transform fTransformPZ
Transform fTransformP
Transform fTransformQZ
Transform fTransformQ
Transform fTransformX
Transform fTransformD
complex fZold
complex m_p
complex m_p0
complex m_p1
int m_recursecount
default:
title = "Switch Recursion"
int param v_mmfswitchrecursion
caption = "Version (MMF Switch Recursion)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
float param p_upperbailout
visible = false
endparam
float param p_lowerbailout
visible = false
endparam
bool param p_addpixel
caption = "Offset z start"
default = false
hint = "When enabled the z start value (in Mandelbrot mode) is offset \
by the constant for the current position - normally '#pixel'."
visible = !@p_manual || @p_mandy
endparam
complex param p_power
visible = false
endparam
heading
caption = "Information"
text = "This formula is an adaptation of 'Switch Recursion' from \
mmfs.ufm which itself was based on the Lucas recursion \
formula found on Mathworld. Tip: You'll often find that \
the best Mandelbrot start value (critical value) is \
non-zero when you change the recursion parameters. You \
can use the switch back from the Julia to the Mandelbrot \
to help find the critical value - it's usually when the \
Mandelbrot 'lake' is at its largest, if you stick to real \
values for the recursion parameters then the critical \
value should also be real. Note that it's often worth trying \
values such as -1, -0.5, 0.5 or 1 as the Mandelbrot start \
value. For those more mathematically inclined see the details \
of the 'Transpoly' formula in mmf.html for details of several \
classic polynomial functions that you can create using this \
formula by setting the recursion transforms and values \
appropriately."
endheading
heading
caption = "Bailout Options"
text = "Depending on the transforms you choose your fractal could \
be either divergent or convergent. You need to choose the \
correct type to produce a result, a symptom of choosing the \
wrong type is an image in a single solid colour e.g. black. \
Sometimes fractals produce both types of 'vergence and for \
these you can choose 'Both'."
endheading
int param p_BailType
caption = "Bailout Type"
enum = "Divergent" "Convergent" "Both" "Absolute Convergence" \
"Div.+Abs.Conv."
default = 0
hint = "If you get an empty or nearly empty fractal try switching \
from 'Divergent' to 'Convergent' or vice-versa or choosing \
'Both'. Note that in some cases if your fractal is a \
Mandelbrot you may need to ensure that the zstart value \
is non-zero."
endparam
complex param p_root
caption = "Convergence Value"
default = (1,0)
hint = "This is the value for testing for convergence to. For the \
'Magnet' formulas the value should be (1,0), if you don't \
know the value to use it's best to stick to the plain \
'Convergent' 'Bailout Type'. It's always worth trying (0,0)."
visible = @p_BailType>2
endparam
float param p_Bailout
caption = "Divergent Bailout"
default = 128.0
hint = "In general larger values will require higher iterations."
visible = @p_BailType==0 || @p_BailType==2 || @p_BailType==4
endparam
float param p_SmallBail
caption = "Convergent Bailout"
default = 1e-5
hint = "In general smaller values will require higher iterations."
visible = @p_BailType>0
endparam
heading
caption = "Fractal Method"
endheading
int param p_type
caption = "Recursion Type"
enum = "Normal" "Iterative"
default = 0
hint = "When you specify 'Normal' a set number of recursions are \
performed on each iteration, the number of recursions will \
control the degree (exponent) of the fractal (at least for \
divergent fractals). When you choose 'Iterative' the \
recurrence relation is performed as the iterations i.e. for \
divergent fractals the degree increases with the number of \
iterations."
endparam
int param p_recurse
caption = "Number of Recursions"
default = 6
min = 2
hint = "The number of recursions to perform on each iteration. The \
minimum is 2. Using the defaults a count of 2 will produce \
a degree 2 fractal, 3 will produce a degree 3 fractal and so \
on."
visible = @p_type==0
endparam
Transform param p_TransformX
caption = "Transform of Pn(z)"
default = NullTransform
hint = "Here you may specify a transform of the recurrence \
function Pn(z) before it is plugged into the 'Fractal \
Formula'."
endparam
int param p_fractal
caption = "Fractal Formula"
enum = "Pn(z)+c" "c*Pn(z)" "Pn(z)+zold+c" "c*Pn(z)+zold" \
"zold*Pn(z)+c" "c*zold*Pn(z)"
default = 0
hint = "Normally the recurrence relation you set using the \
transforms will produce a polynomial in z, Pn(z). \
Here you can choose how Pn(z) is used to produce a \
fractal."
endparam
heading
caption = "Recursion Equations"
text = "Here you can set the equations used for the recurrence \
relation by choosing appropriate transforms. \
The recurrence relation works as follows: Two base \
equations are used, P0(z) and P1(z) and on each recursion \
Pn(z) is created as Pn(z) = ((Q(n)*z + R(n))*Pn-1(z) + \
(S(n)*z + T(n))*Pn-2(z))/D(n) where Q(n), R(n), S(n), T(n) \
and D(n) are functions of the recurrence level n. You \
specify P0 as 'Transform 0', P1 as 'Transform 1', Q as \
'Transform Q', R as 'Transform R', S as 'Transform S', T \
as 'Transform T' and D as 'Transform D'. The formula is \
really designed so you should use either the 'Constant Value', \
'Simple Scale' or 'Linear' transforms from mmf.ulb but \
interesting results may arise from almost any transform :)"
endheading
Transform param p_Transform0
caption = "Transform 0"
default = MMF_Scale
hint = "P0(z)"
endparam
Transform param p_Transform1
caption = "Transform 1"
default = MMF_Scale
hint = "P1(z)"
endparam
Transform param p_TransformPZ
caption = "Transform Q"
default = MMF_Constant
hint = "Q(n) in (Q(n)*z + R(n))*Pn-1(z) + (S(n)*z + T(n))*Pn-2(z)"
endparam
Transform param p_TransformP
caption = "Transform R"
default = MMF_Constant
hint = "R(n) in (Q(n)*z + R(n))*Pn-1(z) + (S(n)*z + T(n))*Pn-2(z)"
endparam
Transform param p_TransformQZ
caption = "Transform S"
default = MMF_Constant
hint = "S(n) in (Q(n)*z + R(n))*Pn-1(z) + (S(n)*z + T(n))*Pn-2(z)"
endparam
Transform param p_TransformQ
caption = "Transform T"
default = MMF_Constant
hint = "T(n) in (Q(n)*z + R(n))*Pn-1(z) + (S(n)*z + T(n))*Pn-2(z)"
endparam
Transform param p_TransformD
caption = "Transform D"
default = MMF_Constant
hint = "The polynomial is divided by this transform of the \
recurrence level at each stage."
endparam
}
class MMF_SwitchGradientSlopeHelper {
;
; Helper class for SwitchGradientSlope.
; By David Makin
; First version May 2008
;
public:
import "common.ulb"
import "Standard.ulb"
func MMF_SwitchGradientSlopeHelper(MMF_SwitchGradientSlope owner)
fFormula = new @formulaClass(owner)
fColouring = new @coloringClass(owner)
endfunc
complex func Init(const complex pz)
fZ = fFormula.Init(pz)
fColouring.Init(fZ,pz)
return fZ
endfunc
func SetParams(bool f,complex v)
if @formulaClass==MMF_SwitchFormula
MMF_SwitchFormula(fFormula).SetParams(f,v)
elseif @formulaClass==MMF_SwitchDivergentFormula
MMF_SwitchDivergentFormula(fFormula).SetParams(f,v)
elseif @formulaClass==MMF_SwitchConvergentFormula
MMF_SwitchConvergentFormula(fFormula).SetParams(f,v)
elseif @formulaClass==MMF_SwitchConvergentDivergentFormula
MMF_SwitchConvergentDivergentFormula(fFormula).SetParams(f,v)
endif
endfunc
complex func Iterate()
return (fZ = fFormula.Iterate(fZ))
endfunc
func IterateCol()
fColouring.Iterate(fZ)
return
endfunc
bool func IsBailedOut()
return fFormula.IsBailedOut(fZ)
endfunc
float func GetHeight()
return fColouring.ResultIndex(fZ)
endfunc
complex func GetPrimaryExponent()
return fFormula.GetPrimaryExponent()
endfunc
float func GetUpperBailout()
return fFormula.GetUpperBailout()
endfunc
float func GetLowerBailout()
return fFormula.GetLowerBailout()
endfunc
private:
Formula fFormula
GradientColoring fColouring
complex fZ
default:
title = "Switch Gradient Slope Helper"
int param v_mmfgradientslopehelper
caption = "Version (MMF Gradient Slope Helper)"
default = 100
hint = "This version parameter is used to detect when a change has been \
made to the formula that is incompatible with the previous \
version. When that happens, this field will reflect the old \
version number to alert you to the fact that an alternate \
rendering is being used."
visible = @v_mmfgradientslopehelper<100
endparam
heading
text = "'Fractal Formula' is not a switch formula and so will \
not switch using UFs built-in switch method."
visible = @formulaClass!=MMF_SwitchFormula \
&& @formulaClass!=MMF_SwitchDivergentFormula \
&& @formulaClass!=MMF_SwitchConvergentFormula \
&& @formulaClass!=MMF_SwitchConvergentDivergentFormula
endheading
Formula param formulaClass
caption = "Fractal Formula"
default = MMF_SwitchStandard
hint = "Sets the actual fractal formula to use for the lighting effect."
endparam
GradientColoring param coloringClass
caption = "Colouring Algorithm"
default = Standard_Smooth
hint = "Selects the colouring algorithm to be used. Note that where \
necessary you should ensure duplicate parameters in the 'Fractal \
Formula' and the 'Colouring Algorithm' match each other - \
typically bailout values and degree/exponent/power values."
endparam
}
class MMF_SwitchGradientSlope(MMF_SwitchFormula) {
;
; Creates 3D lighting effects when combined with the
; Lighting or Mixed Lighting (direct) colouring algorithms.
; Allows "slope" colouring from any formula, any colouring.
;
; Written by David Makin based on Standard_Slope by Damien Jones
; Original May 2008
;
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchGradientSlope(Generic pparent)
MMF_SwitchFormula(pparent)
fHelper[0] = new @helperClass(this)
fHelper[1] = new @helperClass(this)
fHelper[2] = new @helperClass(this)
fTransfer[0] = new @transferClass(this)
fTransfer[1] = new @transferClass(this)
fTransfer[2] = new @transferClass(this)
if @mode>0
; If using 'Colouring+Lighting" pre-compute some constants
float rot = (270.0-@angle)*(#pi/180.0) ; degrees to radians conversion
float ele = @elevation*(#pi/180.0)
; The lighting Normal
lx = cos(rot) * cos(ele)
ly = sin(rot) * cos(ele)
lz = sin(ele)
; Scale for adjusting light value accounting for ambient level
amb = 0.5*(1.0 - @ambient)
endif
endfunc
func SetParams(bool f,complex v)
if !@p_manual
fType = f
fValue = fConstant = v
endif
fHelper[0].SetParams(f,v) ; This was a bug in the first release but
fHelper[1].SetParams(f,v) ; as it happens the problem was simply fixed
fHelper[2].SetParams(f,v) ; by removing the "manual override" params
; from future use since they aren't needed
; because the manual override in the child
; switch formula is sufficient.
; f,v here should have been fType,fConstant
endfunc
complex func Init(complex pz)
complex z1 = fHelper[0].Init(pz) ; primary iterated point
fHelper[1].Init(pz + @offset) ; horizontally offset point
fHelper[2].Init(pz + flip(@offset)) ; vertically offset point
fTransfer[0].Init(pz)
fTransfer[1].Init(pz + @offset)
fTransfer[2].Init(pz + flip(@offset))
fIteration = 0
return z1
endfunc
complex func Iterate(complex pz)
; We can't use the pz value because we need to keep track of three z values.
fIteration = fIteration + 1
complex z1 = fHelper[0].Iterate()
m_BailedOut = fHelper[0].IsBailedOut()
fHelper[1].Iterate()
if @earlyout
m_BailedOut = m_BailedOut || fHelper[1].IsBailedOut()
endif
fHelper[2].Iterate()
if @earlyout
m_BailedOut = m_BailedOut || fHelper[2].IsBailedOut()
endif
if !m_BailedOut ; for normal UF behaviour don't call iterate for
; the colouring formula if we've bailed out
fHelper[0].IterateCol()
fHelper[1].IterateCol()
fHelper[2].IterateCol()
endif
if m_BailedOut || fIteration == #maxiter ; done or last
; Get "height" offsets - note that "vz" would be -@offset
float e1 = fHelper[0].GetHeight()
float vy = fTransfer[0].Iterate(e1)
float vx = fTransfer[1].Iterate(fHelper[1].GetHeight()) - vy
float vy = fTransfer[2].Iterate(fHelper[2].GetHeight()) - vy
; normalising scale
float vd = 1.0/sqrt(sqr(vx)+sqr(vy)+sqr(@offset))
if @mode==0
return vd*(vx + flip(vy)); fudge z from vector (vz is implied)
else
; return the colouring value as real and the light value as imaginary
; note that + lz*offset is a double negative i.e. + -lz*-@offset
return e1 + flip(@ambient + amb*(1.0+vd*(lx*vx + ly*vy + lz*@offset)))
endif
else ; didn't compute z this time
; use primary iteration value to keep periodicity working
return z1
endif
endfunc
complex func GetPrimaryExponent()
return fHelper[0].GetPrimaryExponent()
endfunc
float func GetUpperBailout()
return fHelper[0].GetUpperBailout()
endfunc
float func GetLowerBailout()
return fHelper[0].GetLowerBailout()
endfunc
private:
MMF_SwitchGradientSlopeHelper fHelper[3]
Transfer fTransfer[3]
float lx
float ly
float lz
float amb
int fIteration
default:
title = "Switch Gradient Slope"
rating = recommended
heading
text = "Tip: Use with the Standard Lighting coloring algorithms \
or reb5.ucl-Lighting with Textures or the Mixed \
Lighting (direct) colouring algorithm from mmf.ulb."
endheading
int param v_mmfswitchgradientslope
caption = "Version (Switch Gradient Slope)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
bool param p_manual
visible = false
endparam
bool param p_mandy
visible = false
endparam
complex param p_start
visible = false
endparam
complex param p_seed
visible = false
endparam
float param offset
caption = "Orbit Separation"
default = 0.00000001
exponential = true
hint = "Defines how far apart the simultaneous orbits are. Smaller \
distances will produce more accurate results, the deeper you zoom \
the smaller the value needs to be to keep detail."
endparam
bool param earlyout
caption = "Early Out"
default = false
hint = "This formula iterates 3 points to get the normal for the slope \
colouring, normally all 3 points are iterated until the primary \
point bails out. Unfortunately with some colourings this can lead \
to a NAN (not a number) problem, typically at higher zooms \
producing areas of solid flat lighting. If you think you have \
this problem try enabling 'Early Out' which terminates iteration \
as soon as any one of the three points bails out."
endparam
int param mode
caption = "Method"
enum = "Lighting" "Colouring+Lighting"
default = 0
hint = "'Lighting' is for colouring using the standard 'Lighting' method \
'Colouring+Lighting' is for use with the \
'Mixed Lighting (direct)' colouring."
endparam
float param angle
caption = "Light Rotation"
default = 90.0
hint = "Gives the rotation of the light source, in degrees. With 0 \
degrees, the light comes from above. Positive values give \
clockwise rotation."
visible = @mode==1
endparam
float param elevation
caption = "Light Elevation"
default = 30.0
hint = "Gives the elevation of the light source, in degrees."
visible = @mode==1
endparam
float param ambient
caption = "Ambient Light"
default = 0.0
min = -1.0
max = 1.0
hint = "Specifies the level of ambient light."
visible = @mode==1
endparam
Transfer param transferClass
caption = "Height Transfer"
default = TrapTransfer
hint = "Selects a class to transform the calculated height value."
expanded = false
endparam
MMF_SwitchGradientSlopeHelper param helperClass
selectable = false
endparam
complex param p_power ; Hide p_power from Formula
visible = false
endparam
}
class MMF_FormulaTransformWrapper(common.ulb:ConvergentDivergentFormula) {
; A formula that wraps two transforms around any formula iteration.
public:
import "common.ulb"
import "Standard.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_FormulaTransformWrapper(Generic pparent)
ConvergentDivergentFormula.ConvergentDivergentFormula(pparent)
fFormula = new @classFormula(this)
fPreTransform = new @classPreTransform(this)
fPostTransform = new @classPostTransform(this)
endfunc
complex func Init(complex pz)
; m_Iterations = 0 not used in this formula
m_BailedOut = false
fPreTransform.Init(pz)
fPostTransform.Init(pz)
return fFormula.Init(pz)
endfunc
complex func Iterate(complex pz)
fZold = pz
; m_Iterations = m_Iterations + 1 not used in this formula
return fPostTransform.Iterate(fFormula.Iterate(fPreTransform.Iterate(pz)))
endfunc
complex func GetPrimaryExponent()
return fFormula.GetPrimaryExponent()
endfunc
bool func IsBailedOut(complex pz)
if ((@p_BailType=="Divergent" || @p_BailType=="Both" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz|>=@p_Bailout) \
|| ((@p_BailType=="Convergent" || @p_BailType=="Both") \
&& |pz-fZold|<=@p_SmallBail) \
|| ((@p_BailType=="Absolute Convergence" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz-@p_root|<=@p_SmallBail )
m_BailedOut = true
endif
return m_BailedOut
endfunc
float func GetUpperBailout()
return @p_Bailout
endfunc
float func GetLowerBailout()
return @p_SmallBail
endfunc
protected:
Formula fFormula
UserTransform fPreTransform
UserTransform fPostTransform
complex fZold
default:
title = "Formula Transformations"
int param v_mmfformulatransformwrapper
caption = "Version (MMF_FormulaTransformWrapper)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @v_mmfformulatransformwrapper < 100
endparam
complex param p_power
visible = false
endparam
float param p_upperbailout
visible = false
endparam
float param p_lowerbailout
visible = false
endparam
heading
caption = "Bailout Options"
text = "You should note that the bailout options and values you set \
here will override the bailout settings in the 'Formula' \
parameters. This is because your chosen transforms may cause \
a divergent formula to become convergent or vice-versa."
endheading
int param p_BailType
caption = "Bailout Type"
enum = "Divergent" "Convergent" "Both" "Absolute Convergence" \
"Div.+Abs.Conv."
default = 0
hint = "If you get an empty or nearly empty fractal try switching \
from 'Divergent' to 'Convergent' or vice-versa or choosing \
'Both'. Note that in some cases if your fractal is a \
Mandelbrot you may need to ensure that the zstart value \
is non-zero."
endparam
complex param p_root
caption = "Convergence Value"
default = (1,0)
hint = "This is the value for testing for convergence to. For the \
'Magnet' formulas the value should be (1,0), if you don't \
know the value to use it's best to stick to the plain \
'Convergent' 'Bailout Type'. It's always worth trying (0,0)."
visible = @p_BailType>2
endparam
float param p_Bailout
caption = "Divergent Bailout"
default = 128.0
hint = "In general larger values will require higher iterations."
visible = @p_BailType==0 || @p_BailType==2 || @p_BailType==4
endparam
float param p_SmallBail
caption = "Convergent Bailout"
default = 1e-5
hint = "In general smaller values will require higher iterations."
visible = @p_BailType>0
endparam
heading
caption = "The Pre-Transform"
text = "Transforms z on each iteration prior to the main formula \
calculation."
endheading
UserTransform param classPreTransform
caption = "Pre-Transform"
default = NullTransform
hint = "Transforms z on each iteration prior to the main formula \
calculation."
endparam
heading
caption = "The Main Formula"
endheading
Formula param classFormula
caption = "Formula"
default = Standard_Mandelbrot
hint = "The main formula."
endparam
heading
caption = "The Post-Transform"
text = "Transforms z on each iteration after the main formula \
calculation."
endheading
UserTransform param classPostTransform
caption = "Post-Transform"
default = NullTransform
hint = "Transforms z on each iteration after the main formula \
calculation."
endparam
}
class MMF_SwitchFormulaTransformWrapper(MMF_SwitchConvergentDivergentFormula) {
; A formula that wraps two transforms around any formula iteration.
; With switching when used with mmf5.ufm-Generic Switch Formula
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchFormulaTransformWrapper(Generic pparent)
MMF_SwitchConvergentDivergentFormula.MMF_SwitchConvergentDivergentFormula(pparent)
fFormula = new @classFormula(this)
fPreTransform = new @classPreTransform(this)
fPostTransform = new @classPostTransform(this)
endfunc
func SetParams(bool f,complex v)
if @classFormula==MMF_SwitchFormula
MMF_SwitchFormula(fFormula).SetParams(f,v)
elseif @classFormula==MMF_SwitchDivergentFormula
MMF_SwitchDivergentFormula(fFormula).SetParams(f,v)
elseif @classFormula==MMF_SwitchConvergentFormula
MMF_SwitchConvergentFormula(fFormula).SetParams(f,v)
elseif @classFormula==MMF_SwitchConvergentDivergentFormula
MMF_SwitchConvergentDivergentFormula(fFormula).SetParams(f,v)
endif
endfunc
complex func Init(complex pz)
; m_Iterations = 0 not used in this formula
m_BailedOut = false
fPreTransform.Init(pz)
fPostTransform.Init(pz)
return fFormula.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this formula
fZold = pz
return fPostTransform.Iterate(fFormula.Iterate(fPreTransform.Iterate(pz)))
endfunc
complex func GetPrimaryExponent()
return fFormula.GetPrimaryExponent()
endfunc
bool func IsBailedOut(complex pz)
if ((@p_BailType=="Divergent" || @p_BailType=="Both" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz|>=@p_Bailout) \
|| ((@p_BailType=="Convergent" || @p_BailType=="Both") \
&& |pz-fZold|<=@p_SmallBail) \
|| ((@p_BailType=="Absolute Convergence" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz-@p_root|<=@p_SmallBail )
m_BailedOut = true
endif
return m_BailedOut
endfunc
float func GetUpperBailout()
return @p_Bailout
endfunc
float func GetLowerBailout()
return @p_SmallBail
endfunc
protected:
Formula fFormula
UserTransform fPreTransform
UserTransform fPostTransform
complex fZold
default:
title = "Switch Formula Transformations"
rating = recommended
int param v_mmfswitchformulatransformwrapper
caption = "Version (MMF_SwitchFormulaTransformWrapper)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @v_mmfswitchformulatransformwrapper < 100
endparam
bool param p_manual
visible = false
endparam
complex param p_power
visible = false
endparam
float param p_upperbailout
visible = false
endparam
float param p_lowerbailout
visible = false
endparam
bool param p_addpixel
visible = false
endparam
heading
caption = "Bailout Options"
text = "You should note that the bailout options and values you set \
here will override the bailout settings in the 'Formula' \
parameters. This is because your chosen transforms may cause \
a divergent formula to become convergent or vice-versa."
endheading
int param p_BailType
caption = "Bailout Type"
enum = "Divergent" "Convergent" "Both" "Absolute Convergence" \
"Div.+Abs.Conv."
default = 0
hint = "If you get an empty or nearly empty fractal try switching \
from 'Divergent' to 'Convergent' or vice-versa or choosing \
'Both'. Note that in some cases if your fractal is a \
Mandelbrot you may need to ensure that the zstart value \
is non-zero."
endparam
complex param p_root
caption = "Convergence Value"
default = (1,0)
hint = "This is the value for testing for convergence to. For the \
'Magnet' formulas the value should be (1,0), if you don't \
know the value to use it's best to stick to the plain \
'Convergent' 'Bailout Type'. It's always worth trying (0,0)."
visible = @p_BailType>2
endparam
float param p_Bailout
caption = "Divergent Bailout"
default = 128.0
hint = "In general larger values will require higher iterations."
visible = @p_BailType==0 || @p_BailType==2 || @p_BailType==4
endparam
float param p_SmallBail
caption = "Convergent Bailout"
default = 1e-5
hint = "In general smaller values will require higher iterations."
visible = @p_BailType>0
endparam
heading
caption = "The Pre-Transform"
text = "Transforms z on each iteration prior to the main formula \
calculation."
endheading
UserTransform param classPreTransform
caption = "Pre-Transform"
default = NullTransform
hint = "Transforms z on each iteration prior to the main formula \
calculation. To use multiple transforms select 'Transform \
Merge' from common.ulb."
endparam
heading
caption = "The Main Formula"
endheading
heading
text = "Note that the current 'Formula' is not a switch formula \
and so will not switch using UFs built-in switch method."
visible = @classFormula!=MMF_SwitchFormula \
&& @classFormula!=MMF_SwitchDivergentFormula \
&& @classFormula!=MMF_SwitchConvergentFormula \
&& @classFormula!=MMF_SwitchConvergentDivergentFormula
endheading
Formula param classFormula
caption = "Formula"
default = MMF_SwitchStandard
hint = "The main formula."
endparam
heading
caption = "The Post-Transform"
text = "Transforms z on each iteration after the main formula \
calculation."
endheading
UserTransform param classPostTransform
caption = "Post-Transform"
default = NullTransform
hint = "Transforms z on each iteration after the main formula \
calculation. To use multiple transforms select 'Transform \
Merge' from common.ulb."
endparam
}
class MMF_SelfRotation(common.ulb:UserTransform) {
; Rotates the complex value by multiples of its own angle.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SelfRotation(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
if pz!=(0,0)
float m = cabs(pz)
if @degree==(1,0)
pz = sqr(pz)/m
else
pz = pz^(@degree+1.0)/m^@degree
endif
endif
return pz
endfunc
default:
title = "Self Rotation"
complex param degree
caption = "Degree of rotation"
default = (1,0)
hint = "The larger the value, the more rotation involved. Using 1.0 \
means that the z value is rotated by its own angle, using \
2.0 means that it's rotated by twice its own angle, 3.0 by \
three times and so on. Values less than 1, non-integer values, \
negative values, imaginary values etc. will produce strange \
results, not that results aren't strange anyway - in \
particular when self-rotation is applied the chance of \
Strangely Attractive orbits is increased :)"
endparam
}
class MMF_RunningSum(common.ulb:UserTransform) {
; Returns the sum of pz and all previous values of pz
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_RunningSum(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
m_Sum = (0,0)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return m_Sum = m_Sum + pz
endfunc
func IterateSilent()
; m_Iterations = m_Iterations + 1 not used in this transform
if @p_restart
m_Sum = (0,0)
endif
endfunc
protected:
complex m_Sum
default:
title = "Running Sum"
bool param p_restart
caption = "Reset the Sum"
default = false
hint = "This is only for when the transform is used in a situation \
where there may be iteration skipping, for example in a \
colouring formula. If you enable this option then the sum \
is reset to zero each time iteration skipping occurs."
endparam
}
class MMF_RunningProduct(common.ulb:UserTransform) {
; Returns the product of pz and all previous values of pz.
; Fudges used when pz is zero.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_RunningProduct(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
m_Product = (1,0)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
if pz!=(0,0)
return m_Product = m_Product*pz
elseif @p_method=="Alternative"
return m_Product
else;if @p_method=="Original"
return pz
endif
endfunc
func IterateSilent()
; m_Iterations = m_Iterations + 1 not used in this transform
if @p_restart
m_Product = (1,0)
endif
endfunc
protected:
complex m_Product
default:
title = "Running Product"
int param p_method
caption = "Method"
enum = "Original" "Alternative"
default = 0
hint = "The original method matches 'Iterate the Product' as used in \
various older mmf formulas."
endparam
bool param p_restart
caption = "Reset the Product"
default = false
hint = "This is only for when the transform is used in a situation \
where there may be iteration skipping, for example in a \
colouring formula. If you enable this option then the product \
is reset to one each time iteration skipping occurs."
endparam
}
class MMF_PowerFunctions(common.ulb:UserTransform) {
; fn(z)^power
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_PowerFunctions(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return @p_fn(pz)^@p_power
endfunc
default:
title = "Power Functions"
heading
text = "Simply function(z)^power."
endheading
func p_fn
caption = "Function to use"
default = ident()
hint = "For most applications it's best not to use 'cabs'."
endfunc
complex param p_power
caption = "Power"
default = (2,0)
endparam
}
class MMF_SimpleMatrixTransform(common.ulb:UserTransform) {
; Transforms pz by a general 2*2 matrix.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SimpleMatrixTransform(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SimpleMatrix(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return real(pz)*real(@p_r0) + imag(pz)*real(@p_r1) \
+ flip(real(pz)*imag(@p_r0) + imag(pz)*imag(@p_r1))
endfunc
default:
title = "Simple Matrix Transform"
heading
text = "This matrix transform takes the form: \
z = x*Re(Row 0) + y*Re(Row 1) + flip(x*Im(Row 0) \
+ y*Im(Row 1))."
endheading
complex param p_r0
caption = "Row 0"
default = (1,0)
hint = "Use (1,0) for the identity matrix."
endparam
complex param p_r1
caption = "Row 1"
default = (0,1)
hint = "Use (0,1) for the identity matrix."
endparam
}
class MMF_OffsetMatrixTransform(common.ulb:UserTransform) {
; Transforms pz by an offset and a general 2*2 matrix.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_OffsetMatrixTransform(Generic pparent)
UserTransform.UserTransform(pparent)
offset = @p_offset
r0 = @p_r0
r1 = @p_r1
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
pz = pz + offset
return real(pz)*real(r0) + imag(pz)*real(r1) \
+ flip(real(pz)*imag(r0) + imag(pz)*imag(r1))
endfunc
complex offset
complex r0
complex r1
default:
title = "Offset Matrix Transform"
heading
text = "This matrix transform takes the form: \
z = x*Re(Row 0) + y*Re(Row 1) + flip(x*Im(Row 0) \
+ y*Im(Row 1))."
endheading
complex param p_offset
caption = "Offset"
default = (0,0)
endparam
complex param p_r0
caption = "Row 0"
default = (1,0)
hint = "Use (1,0) for the identity matrix."
endparam
complex param p_r1
caption = "Row 1"
default = (0,1)
hint = "Use (0,1) for the identity matrix."
endparam
}
class MMF_CrossProduct(MMF_TrapTransformZold) {
; Cross products involving z, zold and zolder
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_CrossProduct(Generic pparent)
MMF_TrapTransformZold.MMF_TrapTransformZold(pparent)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
m_zold = m_zolder = pz
m_zoldok = m_zolderok = false
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
complex z1 = pz
if @p_mode=="Z and Zold" && m_zoldok
z1 = real(pz)*imag(m_zold) - flip(real(m_zold)*imag(pz))
elseif @p_mode=="Z and Zolder" && m_zolderok
z1 = real(pz)*imag(m_zolder) - flip(real(m_zolder)*imag(pz))
elseif @p_mode=="Z-Zold and Z-Zolder" && m_zoldok && m_zolderok
complex z2 = pz - m_zolder
z1 = pz - m_zold
z1 = real(z1)*imag(z2) - flip(real(z2)*imag(z1))
elseif @p_mode=="Z-Zold and Zold-Zolder" && m_zoldok && m_zolderok
complex z2 = m_zold - m_zolder
z1 = pz - m_zold
z1 = real(z1)*imag(z2) - flip(real(z2)*imag(z1))
endif
m_zolder = m_zold
m_zold = pz
m_zolderok = m_zoldok
m_zoldok = true
return z1
endfunc
default:
title = "Cross Product"
heading
text = "It may also be used in main formulas that allow iterative \
transforms such as Switch Formula Transformations in mmf.ulb."
endheading
int param p_mode
caption = "Vectors to Cross"
enum = "Z and Zold" "Z and Zolder" "Z-Zold and Z-Zolder" \
"Z-Zold and Zold-Zolder"
default = 0
endparam
}
class MMF_UserFormulaTransform(common.ulb:UserTransform) {
; A roll-your-own formula
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_UserFormulaTransform(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
complex z1 = @p_coeff1*@p_func1(pz)^@p_power1
if @p_numterms>0
z1 = z1 + @p_coeff2*@p_func2(pz)^@p_power2
endif
if @p_numterms>1
z1 = z1 + @p_coeff3*@p_func3(pz)^@p_power3
endif
if @p_numterms>2
z1 = z1 + @p_coeff4*@p_func4(pz)^@p_power4
endif
if @p_numterms>3
z1 = z1 + @p_coeff5*@p_func5(pz)^@p_power5
endif
if @p_numterms>4
z1 = z1 + @p_coeff6*@p_func6(pz)^@p_power6
endif
if @p_numterms>5
z1 = z1 + @p_coeff7*@p_func7(pz)^@p_power7
endif
if @p_numterms>6
z1 = z1 + @p_coeff8*@p_func8(pz)^@p_power8
endif
if @p_numterms>7
z1 = z1 + @p_coeff9*@p_func9(pz)^@p_power9
endif
if @p_numterms>8
z1 = z1 + @p_coeff10*@p_func10(pz)^@p_power10
endif
return z1
endfunc
default:
title = "User Formula Transform"
int param p_numterms
caption = "Number of Terms"
enum = "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
default = 0
endparam
heading
text = "The first term."
endheading
complex param p_coeff1
caption = "Coefficient 1"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
endparam
func p_func1
caption = "Function 1"
default = ident()
hint = "The function, f, in c*f(z)^p."
endfunc
complex param p_power1
caption = "Power 1"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
endparam
heading
text = "The second term."
visible = @p_numterms>0
endheading
complex param p_coeff2
caption = "Coefficient 2"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
visible = @p_numterms>0
endparam
func p_func2
caption = "Function 2"
default = ident()
hint = "The function, f, in c*f(z)^p."
visible = @p_numterms>0
endfunc
complex param p_power2
caption = "Power 2"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
visible = @p_numterms>0
endparam
heading
text = "The third term."
visible = @p_numterms>1
endheading
complex param p_coeff3
caption = "Coefficient 3"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
visible = @p_numterms>1
endparam
func p_func3
caption = "Function 3"
default = ident()
hint = "The function, f, in c*f(z)^p."
visible = @p_numterms>1
endfunc
complex param p_power3
caption = "Power 3"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
visible = @p_numterms>1
endparam
heading
text = "The fourth term."
visible = @p_numterms>2
endheading
complex param p_coeff4
caption = "Coefficient 4"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
visible = @p_numterms>2
endparam
func p_func4
caption = "Function 4"
default = ident()
hint = "The function, f, in c*f(z)^p."
visible = @p_numterms>2
endfunc
complex param p_power4
caption = "Power 4"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
visible = @p_numterms>2
endparam
heading
text = "The fifth term."
visible = @p_numterms>3
endheading
complex param p_coeff5
caption = "Coefficient 5"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
visible = @p_numterms>3
endparam
func p_func5
caption = "Function 5"
default = ident()
hint = "The function, f, in c*f(z)^p."
visible = @p_numterms>3
endfunc
complex param p_power5
caption = "Power 5"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
visible = @p_numterms>3
endparam
heading
text = "The sixth term."
visible = @p_numterms>4
endheading
complex param p_coeff6
caption = "Coefficient 6"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
visible = @p_numterms>4
endparam
func p_func6
caption = "Function 6"
default = ident()
hint = "The function, f, in c*f(z)^p."
visible = @p_numterms>4
endfunc
complex param p_power6
caption = "Power 6"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
visible = @p_numterms>4
endparam
heading
text = "The seventh term."
visible = @p_numterms>5
endheading
complex param p_coeff7
caption = "Coefficient 7"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
visible = @p_numterms>5
endparam
func p_func7
caption = "Function 7"
default = ident()
hint = "The function, f, in c*f(z)^p."
visible = @p_numterms>5
endfunc
complex param p_power7
caption = "Power 7"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
visible = @p_numterms>5
endparam
heading
text = "The eighth term."
visible = @p_numterms>6
endheading
complex param p_coeff8
caption = "Coefficient 8"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
visible = @p_numterms>6
endparam
func p_func8
caption = "Function 8"
default = ident()
hint = "The function, f, in c*f(z)^p."
visible = @p_numterms>6
endfunc
complex param p_power8
caption = "Power 8"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
visible = @p_numterms>6
endparam
heading
text = "The ninth term."
visible = @p_numterms>7
endheading
complex param p_coeff9
caption = "Coefficient 9"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
visible = @p_numterms>7
endparam
func p_func9
caption = "Function 9"
default = ident()
hint = "The function, f, in c*f(z)^p."
visible = @p_numterms>7
endfunc
complex param p_power9
caption = "Power 9"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
visible = @p_numterms>7
endparam
heading
text = "The tenth term."
visible = @p_numterms>8
endheading
complex param p_coeff10
caption = "Coefficient 10"
default = (1,0)
hint = "The coefficient, c, in c*f(z)^p."
visible = @p_numterms>8
endparam
func p_func10
caption = "Function 10"
default = ident()
hint = "The function, f, in c*f(z)^p."
visible = @p_numterms>8
endfunc
complex param p_power10
caption = "Power 10"
default = (1,0)
hint = "The power, p, in c*f(z)^p."
visible = @p_numterms>8
endparam
}
class MMF_TransformAdd(common.ulb:UserTransform) {
; Adds the results of two transforms together
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TransformAdd(Generic pparent)
UserTransform.UserTransform(pparent)
fTransform1 = new @p_Transform1(this)
fTransform2 = new @p_Transform2(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fTransform1.Init(pz)
fTransform2.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return fTransform1.Iterate(pz) + fTransform2.Iterate(pz)
endfunc
private:
Transform fTransform1
Transform fTransform2
default:
title = "Transform Add"
Transform param p_Transform1
caption = "First Transform"
default = MMF_GeneralTransform
hint = "The result of this is added to the result of 'Second Transform'."
endparam
Transform param p_Transform2
caption = "Second Transform"
default = MMF_GeneralTransform
hint = "The result of this is added to the result of 'First Transform'."
endparam
}
class MMF_TransformSubtract(common.ulb:UserTransform) {
; Subtracts the result of one transform from another
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TransformSubtract(Generic pparent)
UserTransform.UserTransform(pparent)
fTransform1 = new @p_Transform1(this)
fTransform2 = new @p_Transform2(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fTransform1.Init(pz)
fTransform2.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return fTransform1.Iterate(pz) - fTransform2.Iterate(pz)
endfunc
private:
Transform fTransform1
Transform fTransform2
default:
title = "Transform Subtract"
heading
text = "Subtracts 'Second Transform' from 'First Transform'."
endheading
Transform param p_Transform1
caption = "First Transform"
default = MMF_GeneralTransform
hint = "The result of 'Second Transform' is subtracted from the \
result of this."
endparam
Transform param p_Transform2
caption = "Second Transform"
default = MMF_GeneralTransform
hint = "The result of this is subtracted from the result of \
'First Transform'."
endparam
}
class MMF_TransformMultiply(common.ulb:UserTransform) {
; Multiplies two transforms together
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TransformMultiply(Generic pparent)
UserTransform.UserTransform(pparent)
fTransform1 = new @p_Transform1(this)
fTransform2 = new @p_Transform2(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fTransform1.Init(pz)
fTransform2.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return fTransform1.Iterate(pz)*fTransform2.Iterate(pz)
endfunc
private:
Transform fTransform1
Transform fTransform2
default:
title = "Transform Multiply"
Transform param p_Transform1
caption = "First Transform"
default = MMF_GeneralTransform
hint = "The result of this is multiplied by the result of \
'Second Transform'."
endparam
Transform param p_Transform2
caption = "Second Transform"
default = MMF_GeneralTransform
hint = "The result of this is multiplied by the result of \
'First Transform'."
endparam
}
class MMF_TransformDivide(common.ulb:UserTransform) {
; Divides one transform by another
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TransformDivide(Generic pparent)
UserTransform.UserTransform(pparent)
fTransform1 = new @p_Transform1(this)
fTransform2 = new @p_Transform2(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fTransform1.Init(pz)
fTransform2.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return fTransform1.Iterate(pz)/fTransform2.Iterate(pz)
endfunc
private:
Transform fTransform1
Transform fTransform2
default:
title = "Transform Divide"
heading
text = "Divides 'First Transform' by 'Second Transform'."
endheading
Transform param p_Transform1
caption = "First Transform"
default = MMF_GeneralTransform
hint = "The result of this is divided by the result of \
'Second Transform'. Note that when the result of \
the second transform is zero there may be unwanted \
consequences."
endparam
Transform param p_Transform2
caption = "Second Transform"
default = MMF_GeneralTransform
hint = "The result of 'First Transform' is divided by the \
result of this. Note that when the result of \
this transform is zero there may be unwanted \
consequences."
endparam
}
class MMF_TransformSum(common.ulb:UserTransform) {
; Sums up to 10 transforms together (with coefficients)
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TransformSum(Generic pparent)
UserTransform.UserTransform(pparent)
fTransform1 = new @p_Transform1(this)
fTransform2 = new @p_Transform2(this)
fTransform3 = new @p_Transform3(this)
fTransform4 = new @p_Transform4(this)
fTransform5 = new @p_Transform5(this)
fTransform6 = new @p_Transform6(this)
fTransform7 = new @p_Transform7(this)
fTransform8 = new @p_Transform8(this)
fTransform9 = new @p_Transform9(this)
fTransform10 = new @p_Transform10(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fTransform1.Init(pz)
fTransform2.Init(pz)
fTransform3.Init(pz)
fTransform4.Init(pz)
fTransform5.Init(pz)
fTransform6.Init(pz)
fTransform7.Init(pz)
fTransform8.Init(pz)
fTransform9.Init(pz)
fTransform10.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
complex zz = @p_coeff1*fTransform1.Iterate(pz) \
+ @p_coeff2*fTransform2.Iterate(pz)
if @p_numtrans=="3" || @p_numtrans=="4" || @p_numtrans=="5" \
|| @p_numtrans=="6" || @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz + @p_coeff3*fTransform3.Iterate(pz)
endif
if @p_numtrans=="4" || @p_numtrans=="5" \
|| @p_numtrans=="6" || @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz + @p_coeff4*fTransform4.Iterate(pz)
endif
if @p_numtrans=="5" \
|| @p_numtrans=="6" || @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz + @p_coeff5*fTransform5.Iterate(pz)
endif
if @p_numtrans=="6" || @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz + @p_coeff6*fTransform6.Iterate(pz)
endif
if @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz + @p_coeff7*fTransform7.Iterate(pz)
endif
if @p_numtrans=="8" || @p_numtrans=="9" || @p_numtrans=="10"
zz = zz + @p_coeff8*fTransform8.Iterate(pz)
endif
if @p_numtrans=="9" || @p_numtrans=="10"
zz = zz + @p_coeff9*fTransform8.Iterate(pz)
endif
if @p_numtrans=="10"
zz = zz + @p_coeff10*fTransform8.Iterate(pz)
endif
return zz
endfunc
private:
Transform fTransform1
Transform fTransform2
Transform fTransform3
Transform fTransform4
Transform fTransform5
Transform fTransform6
Transform fTransform7
Transform fTransform8
Transform fTransform9
Transform fTransform10
default:
title = "Transform Sum"
int param p_numtrans
caption = "Number of terms"
enum = "2" "3" "4" "5" "6" "7" "8" "9" "10"
default = 0
hint = "Each transform term is multiplied by its coefficient \
and the results are summed together."
endparam
heading
text = "The first term in the sum."
endheading
complex param p_coeff1
caption = "Coefficient 1"
default = (1,0)
hint = "The coefficient of the first term."
endparam
Transform param p_Transform1
caption = "First Transform"
default = MMF_GeneralTransform
endparam
heading
text = "The second term in the sum."
endheading
complex param p_coeff2
caption = "Coefficient 2"
default = (1,0)
hint = "The coefficient of the second term."
endparam
Transform param p_Transform2
caption = "Second Transform"
default = MMF_GeneralTransform
endparam
heading
text = "The third term in the sum."
visible = @p_numtrans>0
endheading
complex param p_coeff3
caption = "Coefficient 3"
default = (1,0)
hint = "The coefficient of the third term."
visible = @p_numtrans>0
endparam
Transform param p_Transform3
caption = "Third Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>0
endparam
heading
text = "The fourth term in the sum."
visible = @p_numtrans>1
endheading
complex param p_coeff4
caption = "Coefficient 4"
default = (1,0)
hint = "The coefficient of the fourth term."
visible = @p_numtrans>1
endparam
Transform param p_Transform4
caption = "Fourth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>1
endparam
heading
text = "The fifth term in the sum."
visible = @p_numtrans>2
endheading
complex param p_coeff5
caption = "Coefficient 5"
default = (1,0)
hint = "The coefficient of the fifth term."
visible = @p_numtrans>2
endparam
Transform param p_Transform5
caption = "Fifth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>2
endparam
heading
text = "The sixth term in the sum."
visible = @p_numtrans>3
endheading
complex param p_coeff6
caption = "Coefficient 6"
default = (1,0)
hint = "The coefficient of the sixth term."
visible = @p_numtrans>3
endparam
Transform param p_Transform6
caption = "Sixth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>3
endparam
heading
text = "The seventh term in the sum."
visible = @p_numtrans>4
endheading
complex param p_coeff7
caption = "Coefficient 7"
default = (1,0)
hint = "The coefficient of the seventh term."
visible = @p_numtrans>4
endparam
Transform param p_Transform7
caption = "Seventh Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>4
endparam
heading
text = "The eighth term in the sum."
visible = @p_numtrans>5
endheading
complex param p_coeff8
caption = "Coefficient 8"
default = (1,0)
hint = "The coefficient of the eighth term."
visible = @p_numtrans>5
endparam
Transform param p_Transform8
caption = "Eighth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>5
endparam
heading
text = "The ninth term in the sum."
visible = @p_numtrans>6
endheading
complex param p_coeff9
caption = "Coefficient 9"
default = (1,0)
hint = "The coefficient of the ninth term."
visible = @p_numtrans>6
endparam
Transform param p_Transform9
caption = "Ninth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>6
endparam
heading
text = "The tenth term in the sum."
visible = @p_numtrans>7
endheading
complex param p_coeff10
caption = "Coefficient 10"
default = (1,0)
hint = "The coefficient of the tenth term."
visible = @p_numtrans>7
endparam
Transform param p_Transform10
caption = "Tenth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>7
endparam
}
class MMF_TransformProduct(common.ulb:UserTransform) {
; Multiplies up to 10 transforms together (with powers)
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TransformProduct(Generic pparent)
UserTransform.UserTransform(pparent)
fTransform1 = new @p_Transform1(this)
fTransform2 = new @p_Transform2(this)
fTransform3 = new @p_Transform3(this)
fTransform4 = new @p_Transform4(this)
fTransform5 = new @p_Transform5(this)
fTransform6 = new @p_Transform6(this)
fTransform7 = new @p_Transform7(this)
fTransform8 = new @p_Transform8(this)
fTransform9 = new @p_Transform9(this)
fTransform10 = new @p_Transform10(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fTransform1.Init(pz)
fTransform2.Init(pz)
fTransform3.Init(pz)
fTransform4.Init(pz)
fTransform5.Init(pz)
fTransform6.Init(pz)
fTransform7.Init(pz)
fTransform8.Init(pz)
fTransform9.Init(pz)
fTransform10.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
complex zz = fTransform1.Iterate(pz)^@p_power1 \
* fTransform2.Iterate(pz)^@p_power2
if @p_numtrans=="3" || @p_numtrans=="4" || @p_numtrans=="5" \
|| @p_numtrans=="6" || @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz * fTransform3.Iterate(pz)^@p_power3
endif
if @p_numtrans=="4" || @p_numtrans=="5" \
|| @p_numtrans=="6" || @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz * fTransform4.Iterate(pz)^@p_power4
endif
if @p_numtrans=="5" \
|| @p_numtrans=="6" || @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz * fTransform5.Iterate(pz)^@p_power5
endif
if @p_numtrans=="6" || @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz * fTransform6.Iterate(pz)^@p_power6
endif
if @p_numtrans=="7" || @p_numtrans=="8" \
|| @p_numtrans=="9" || @p_numtrans=="10"
zz = zz * fTransform7.Iterate(pz)^@p_power7
endif
if @p_numtrans=="8" || @p_numtrans=="9" || @p_numtrans=="10"
zz = zz * fTransform8.Iterate(pz)^@p_power8
endif
if @p_numtrans=="9" || @p_numtrans=="10"
zz = zz * fTransform9.Iterate(pz)^@p_power9
endif
if @p_numtrans=="10"
zz = zz * fTransform10.Iterate(pz)^@p_power10
endif
return zz
endfunc
private:
Transform fTransform1
Transform fTransform2
Transform fTransform3
Transform fTransform4
Transform fTransform5
Transform fTransform6
Transform fTransform7
Transform fTransform8
Transform fTransform9
Transform fTransform10
default:
title = "Transform Product"
int param p_numtrans
caption = "Number of terms"
enum = "2" "3" "4" "5" "6" "7" "8" "9" "10"
default = 0
hint = "Each transform term is raised to its power \
and the results are multiplied together."
endparam
heading
text = "The first term in the product."
endheading
complex param p_power1
caption = "Power 1"
default = (1,0)
hint = "The power of the first term."
endparam
Transform param p_Transform1
caption = "First Transform"
default = MMF_GeneralTransform
endparam
heading
text = "The second term in the product."
endheading
complex param p_power2
caption = "Power 2"
default = (1,0)
hint = "The power of the second term."
endparam
Transform param p_Transform2
caption = "Second Transform"
default = MMF_GeneralTransform
endparam
heading
text = "The third term in the product."
visible = @p_numtrans>0
endheading
complex param p_power3
caption = "Power 3"
default = (1,0)
hint = "The power of the third term."
visible = @p_numtrans>0
endparam
Transform param p_Transform3
caption = "Third Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>0
endparam
heading
text = "The fourth term in the product."
visible = @p_numtrans>1
endheading
complex param p_power4
caption = "Power 4"
default = (1,0)
hint = "The power of the fourth term."
visible = @p_numtrans>1
endparam
Transform param p_Transform4
caption = "Fourth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>1
endparam
heading
text = "The fifth term in the product."
visible = @p_numtrans>2
endheading
complex param p_power5
caption = "Power 5"
default = (1,0)
hint = "The power of the fifth term."
visible = @p_numtrans>2
endparam
Transform param p_Transform5
caption = "Fifth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>2
endparam
heading
text = "The sixth term in the product."
visible = @p_numtrans>3
endheading
complex param p_power6
caption = "Power 6"
default = (1,0)
hint = "The power of the sixth term."
visible = @p_numtrans>3
endparam
Transform param p_Transform6
caption = "Sixth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>3
endparam
heading
text = "The seventh term in the product."
visible = @p_numtrans>4
endheading
complex param p_power7
caption = "Power 7"
default = (1,0)
hint = "The power of the seventh term."
visible = @p_numtrans>4
endparam
Transform param p_Transform7
caption = "Seventh Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>4
endparam
heading
text = "The eighth term in the product."
visible = @p_numtrans>5
endheading
complex param p_power8
caption = "Power 8"
default = (1,0)
hint = "The power of the eighth term."
visible = @p_numtrans>5
endparam
Transform param p_Transform8
caption = "Eighth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>5
endparam
heading
text = "The ninth term in the product."
visible = @p_numtrans>6
endheading
complex param p_power9
caption = "Power 9"
default = (1,0)
hint = "The power of the ninth term."
visible = @p_numtrans>6
endparam
Transform param p_Transform9
caption = "Ninth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>6
endparam
heading
text = "The tenth term in the product."
visible = @p_numtrans>7
endheading
complex param p_power10
caption = "Power 10"
default = (1,0)
hint = "The power of the tenth term."
visible = @p_numtrans>7
endparam
Transform param p_Transform10
caption = "Tenth Transform"
default = MMF_GeneralTransform
visible = @p_numtrans>7
endparam
}
class MMF_TransformPowerFunctions(common.ulb:UserTransform) {
; fn(transform)^power
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_TransformPowerFunctions(Generic pparent)
UserTransform.UserTransform(pparent)
fTransform = new @p_Transform(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fTransform.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return @p_fn(fTransform.Iterate(pz))^@p_power
endfunc
private:
Transform fTransform
default:
title = "Transform Power Functions"
func p_fn
caption = "Function to use"
default = ident()
hint = "For most applications it's best not to use 'cabs'."
endfunc
complex param p_power
caption = "Power"
default = (2,0)
endparam
Transform param p_Transform
caption = "Transform"
default = MMF_GeneralTransform
endparam
}
class MMF_FormulaTransform(common.ulb:UserTransform) {
; Allows the use of any object main formula as a transform
public:
import "common.ulb"
import "Standard.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_FormulaTransform(Generic pparent)
UserTransform.UserTransform(pparent)
fFormula = new @p_Formula(this)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
fFormula.Init(pz)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return fFormula.Iterate(pz)
endfunc
private:
Formula fFormula
default:
title = "Any Formula"
heading
text = "Choose any main formula to be used as the transform, not \
all formulas will produce good results. Note that some of \
the main formula parameters will be superfluos, such as any \
bailout value/s."
endheading
Formula param p_Formula
caption = "Formula"
default = Standard_Mandelbrot
hint = "The normal iterative function of the chosen formula is used as \
the transform."
endparam
}
class MMF_SwitchTransformFormula(MMF_SwitchFormula) {
; Any Transform applied as a formula.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchTransformFormula(Generic pparent)
MMF_SwitchFormula.MMF_SwitchFormula(pparent)
fTransform = new @classTransform(this)
endfunc
complex func Init(complex pz)
; m_Iterations = 0 not used in this formula
m_BailedOut = false
if @p_initold=="Fixed Value"
fZold = @p_zold
elseif @p_initold=="Position"
fZold = pz
elseif @p_initold=="Start Value"
if fType
if @p_addpixel
fZold = fValue + pz
else
fZold = fValue
endif
else
fZold = pz
endif
else;if @p_initold=="Constant"
if fType
fZold = pz
else
fZold = fConstant
endif
endif
fTransform.Init(pz)
if fType
fConstant = pz
if @p_addpixel
return fValue + fConstant
else
return fValue
endif
else
return pz
endif
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this formula
complex zz = fTransform.Iterate(pz)
if @p_type=="tx(z)+c"
zz = zz + fConstant
elseif @p_type=="c*tx(z)"
return fConstant*zz
elseif @p_type=="tx(z)+zold+c"
zz = zz + fZold + fConstant
elseif @p_type=="c*tx(z)+zold"
zz = fConstant*zz + fZold
elseif @p_type=="zold*tx(z)+c"
zz = fZold*zz + fConstant
else;if @p_type=="c*zold*tx(z)"
zz = fConstant*fZold*zz
endif
fZold = pz
return zz
endfunc
bool func IsBailedOut(complex pz)
if ((@p_BailType=="Divergent" || @p_BailType=="Both" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz|>=@p_Bailout) \
|| ((@p_BailType=="Convergent" || @p_BailType=="Both") \
&& |pz-fZold|<=@p_SmallBail) \
|| ((@p_BailType=="Absolute Convergence" \
|| @p_BailType=="Div.+Abs.Conv.") \
&& |pz-@p_root|<=@p_SmallBail )
m_BailedOut = true
endif
return m_BailedOut
endfunc
float func GetUpperBailout()
return @p_Bailout
endfunc
float func GetLowerBailout()
return @p_SmallBail
endfunc
protected:
UserTransform fTransform
complex fZold
default:
title = "Switch Transform Formula"
rating = recommended
int param v_mmfswitchtransformformula
caption = "Version (MMF_SwitchTransformFormula)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @v_mmfswitchtransformformula < 100
endparam
complex param p_power
visible = false
endparam
bool param p_addpixel
caption = "Offset z start"
default = false
hint = "When enabled the z start value (in Mandelbrot mode) is offset \
by the constant for the current position - normally '#pixel'."
visible = !@p_manual || @p_mandy
endparam
heading
caption = "Bailout Options"
endheading
int param p_BailType
caption = "Bailout Type"
enum = "Divergent" "Convergent" "Both" "Absolute Convergence" \
"Div.+Abs.Conv."
default = 0
hint = "If you get an empty or nearly empty fractal try switching \
from 'Divergent' to 'Convergent' or vice-versa or choosing \
'Both'. Note that in some cases if your fractal is a \
Mandelbrot you may need to ensure that the zstart value \
is non-zero."
endparam
complex param p_root
caption = "Convergence Value"
default = (1,0)
hint = "This is the value for testing for convergence to. For the \
'Magnet' formulas the value should be (1,0), if you don't \
know the value to use it's best to stick to the plain \
'Convergent' 'Bailout Type'. It's always worth trying (0,0)."
visible = @p_BailType>2
endparam
float param p_Bailout
caption = "Divergent Bailout"
default = 128.0
hint = "In general larger values will require higher iterations."
visible = @p_BailType==0 || @p_BailType==2 || @p_BailType==4
endparam
float param p_SmallBail
caption = "Convergent Bailout"
default = 1e-5
hint = "In general smaller values will require higher iterations."
visible = @p_BailType>0
endparam
heading
caption = "The Formula method"
endheading
int param p_type
caption = "Fractal Type"
enum = "tx(z)+c" "c*tx(z)" "tx(z)+zold+c" "c*tx(z)+zold" \
"zold*tx(z)+c" "c*zold*tx(z)"
default = 0
endparam
int param p_initold
caption = "Initial Zold"
enum = "Fixed Value" "Position" "Start Value" "Constant"
default = 0
endparam
complex param p_zold
caption = "Initial Zold Value"
default = (0,0)
visible = @p_initold==0
endparam
heading
caption = "The Formula Transform"
text = "Transforms z on each iteration."
endheading
UserTransform param classTransform
caption = "The Transform"
default = MMF_PowerFunctions
hint = "Transforms z on each iteration. To use multiple \
transforms select 'Transform Merge' from common.ulb."
endparam
}
class MMF_Constant(common.ulb:UserTransform) {
; returns a user constant, whatever the value of pz
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_Constant(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return @p_constant
endfunc
default:
title = "Constant Value"
complex param p_constant
caption = "The Constant"
default = (1,0)
endparam
}
class MMF_Scale(common.ulb:UserTransform) {
; Simply scales pz by the user scale value.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_Scale(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return @p_scale*pz
endfunc
default:
title = "Simple Scale"
complex param p_scale
caption = "The Scale"
default = (1,0)
endparam
}
class MMF_Linear(common.ulb:UserTransform) {
; Simple linear transform
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_Linear(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
func Init(complex pz)
; m_Iterations = 0 not used in this transform
m_Solid = false
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return @p_scale*pz + @p_constant
endfunc
default:
title = "Linear"
complex param p_scale
caption = "The Scale"
default = (1,0)
hint = "The scale, s, in s*z + c."
endparam
complex param p_constant
caption = "The Constant"
default = (0,0)
hint = "The constant, c, in s*z + c."
endparam
}
class MMF_GammaTransform(common.ulb:UserTransform) {
; Complex Gamma(z)
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_GammaTransform(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
complex func Iterate(complex pz)
; m_Iterations = m_Iterations + 1 not used in this transform
return Math.ComplexGamma(pz)
endfunc
default:
title = "Gamma Transform"
}
class MMF_SwitchBeta(MMF_SwitchDivergentFormula) {
;
; Switchable Beta(z,c).
;
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_SwitchBeta(Generic pparent)
MMF_SwitchDivergentFormula.MMF_SwitchDivergentFormula(pparent)
endfunc
complex func Iterate(complex pz)
return Math.ComplexBeta(pz,fConstant)
endfunc
default:
title = "Switch Beta"
bool param p_addpixel
caption = "Offset z start"
default = true
hint = "When enabled the z start value (in Mandelbrot mode) is offset \
by the constant for the current position - normally '#pixel'."
visible = !@p_manual || @p_mandy
endparam
complex param p_power
visible = false
endparam
}
class Contraction(common.ulb:Generic) {
; Contraction base class.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func Contraction(Generic pparent)
Generic.Generic(pparent)
endfunc
; @param pz
; @param pc
func Init(complex pz, complex pc)
endfunc
; @param pz
; @param pc
; @return the contracted value
complex func Iterate(complex pz, complex pc)
return pz
endfunc
default:
int param v_contraction
caption = "Version (Contraction)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @v_contraction < 100
endparam
}
class DistanceEstimatorBase(common.ulb:GradientColoring) {
; Distance Estimator base class.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func DistanceEstimatorBase(Generic pparent)
GradientColoring.GradientColoring(pparent)
endfunc
; @param pz
; @return the distance
float func ResultDistance(complex pz)
return real(pz)
endfunc
; @param pz
; @return the angle (from 0 to 1)
float func ResultAngle(complex pz)
return real(pz)
endfunc
protected:
complex dz
default:
int param v_distanceestimatorbase
caption = "Version (Distance Estimator Base)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @v_distanceestimatorbase < 100
endparam
}
class MMF_NewtonDistanceEstimator(DistanceEstimatorBase) {
; Distance Estimator for Newton formulas solving z^p-c.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_NewtonDistanceEstimator(Generic pparent)
DistanceEstimatorBase.DistanceEstimatorBase(pparent)
endfunc
; @param pz
; @param ppixel
func Init(complex pz, complex ppixel)
DistanceEstimatorBase.Init(pz, ppixel)
zold = pz
odz = 1.0
dz = (@power - 1.0)/@power - @root*(@power - 1.0)*pz^(@power - 2.0) \
/(@power*pz^(2.0*(@power - 1.0)))
endfunc
; @param pz
func Iterate(complex pz)
m_Iterations = m_Iterations + 1
zold = pz
odz = dz
dz = dz *((@power - 1.0)/@power - @root*(@power - 1.0)*pz^(@power - 2.0) \
/(@power*pz^(2.0*(@power - 1.0))))
endfunc
; @param pz
; @return the gradient index
float func ResultIndex(complex pz)
float a = 0.0
float d = 0.0
complex zv = pz - zold
complex dzv = 1.0/(dz - odz)
if @mode=="Angle" || @mode=="Combined"
if (a = atan2(zv*dzv)*(0.5/#pi))<0.0
a = a + 1.0
endif
if @mode=="Angle"
return a
endif
endif
if @mode=="Distance" || @mode=="Combined"
d = 0.5*cabs((@power - 1.0)*zv)
d = -d*log(d)*cabs(dzv)
if @mode=="Distance"
return d
endif
endif
return a+d
endfunc
; @param pz
; @return the distance
float func ResultDistance(complex pz)
float v = 0.5*cabs((@power - 1.0)*(pz - zold))
return -v*log(v)/cabs(dz-odz)
endfunc
; @param pz
; @return the angle (from 0 to 1)
float func ResultAngle(complex pz)
float r
if (r=atan2((pz-zold)/(dz-odz))*(0.5/#pi))<0.0
r = r + 1.0
endif
return r
endfunc
protected:
complex zold
complex odz
default:
title = "MMF Newton Distance Estimator"
int param v_mmf_newtondistanceestimator
caption = "Version (MMF Newton Distance Estimator)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
int param mode
caption = "Mode"
enum = "Distance" "Angle" "Combined"
default = 0
endparam
complex param power
caption = "Power (p in z^p-r)"
default = (3,0)
endparam
complex param root
caption = "Root (r in z^p-r)"
default = (1,0)
endparam
}
class MMF_Magnet1DistanceEstimator(DistanceEstimatorBase) {
; Distance Estimator for the Magnet 1 formula.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_Magnet1DistanceEstimator(Generic pparent)
DistanceEstimatorBase.DistanceEstimatorBase(pparent)
endfunc
; @param pz
; @param ppixel
func Init(complex pz, complex ppixel)
DistanceEstimatorBase.Init(pz, ppixel)
zold = pz
odz = 1.0
if @fixit
complex fz = 0.0
complex gz = 0.0
if @julia
fz = sqr(pz) + (@seed - 1.0)
gz = 2.0*pz + (@seed - 2.0)
else
fz = sqr(pz) + (m_Pixel - 1.0)
gz = 2.0*pz + (m_Pixel - 2.0)
endif
complex dfz = 2.0*pz
complex dgz = 2.0
dz = 2.0*fz*(dfz*gz - fz*dgz)/gz^3.0
elseif @julia
dz = (2.0*sqr(pz) + (2.0*@seed - 4.0)*pz - 2.0*@seed + 2.0) \
/sqr(2.0*pz + @seed - 2.0)
else
dz = (2.0*sqr(pz) + (2.0*m_Pixel - 4.0)*pz - 2.0*m_Pixel + 2.0) \
/sqr(2.0*pz + m_Pixel - 2.0)
endif
endfunc
; @param pz
func Iterate(complex pz)
; m_Iterations = m_Iterations + 1
zold = pz
odz = dz
if @fixit
complex fz = 0.0
complex gz = 0.0
if @julia
fz = sqr(pz) + (@seed - 1.0)
gz = 2.0*pz + (@seed - 2.0)
else
fz = sqr(pz) + (m_Pixel - 1.0)
gz = 2.0*pz + (m_Pixel - 2.0)
endif
complex dfz = 2.0*pz
complex dgz = 2.0
dz = dz*2.0*fz*(dfz*gz - fz*dgz)/gz^3.0
elseif @julia
dz = dz*((2.0*sqr(pz) + (2.0*@seed - 4.0)*pz - 2.0*@seed + 2.0) \
/sqr(2.0*pz + @seed - 2.0))
else
dz = dz*((2.0*sqr(pz) + (2.0*m_Pixel - 4.0)*pz - 2.0*m_Pixel + 2.0) \
/sqr(2.0*pz + m_Pixel - 2.0))
endif
endfunc
; @param pz
; @return the gradient index
float func ResultIndex(complex pz)
float a = 0.0
float d = 0.0
complex zv = pz - zold
if |zv|<1.0 && @method!=1
if @modec=="Angle" || @modec=="Combined"
if (a = atan2(zv/(dz-odz))*(0.5/#pi))<0.0
a = a + 1.0
endif
if @modec=="Angle"
return a
endif
endif
if @modec=="Distance" || @modec=="Combined"
if @fixit
d = cabs(zv)
d = -d*log(d)/cabs(dz-odz)
else
d = |(dz-odz)/zv|^0.0625 ; Note that this is from trial and error
endif
if @modec=="Distance"
return d
endif
endif
elseif @method>0 && |zv|>=1.0
if @mode=="Angle" || @mode=="Combined"
if @fixit
if (a = atan2(pz/dz)*(0.5/#pi))<0.0
a = a + 1.0
endif
elseif (a = atan2(dz)*(0.5/#pi))<0.0
a = a + 1.0
endif
if @mode=="Angle"
return a
endif
endif
if @mode=="Distance" || @mode=="Combined"
if @fixit
d = cabs(pz)
d = d*log(d)/cabs(dz)
else
; again from trial and error:
d = ((1.0-log(0.5*log(|@bailout|))+log(0.5*log(|pz|)))*|dz|)^0.0625
endif
if @mode=="Distance"
return d
endif
endif
else
m_Solid = true
endif
return a+d
endfunc
; @param pz
; @return the distance
float func ResultDistance(complex pz)
if |pz-zold|<1.0
if @fixit
float d = cabs(pz-zold)
return -d*log(d)/cabs(dz-odz)
endif
return |(dz-odz)/(pz-zold)|^0.0625 ; Note that this is from trial and error
else
if @fixit
float d = cabs(pz)
return d*log(d)/cabs(dz)
endif
return ((1.0-log(0.5*log(|@bailout|))+log(0.5*log(|pz|)))*|dz|)^0.0625
endif
endfunc
; @param pz
; @return the angle (from 0 to 1)
float func ResultAngle(complex pz)
float r = 0.0
if |pz-zold|<1.0
if (r=atan2((pz-zold)/(dz-odz))*(0.5/#pi))<0.0
r = r + 1.0
endif
else
if @fixit
r = atan2(pz/dz)*(0.5/#pi)
else
r = atan2(dz)*(0.5/#pi)
endif
if r<0.0
r = r + 1.0
endif
endif
return r
endfunc
protected:
complex zold
complex odz
default:
title = "MMF Magnet 1 Distance Estimator"
int param v_mmf_magnet1distanceestimator
caption = "Version (MMF Magnet 1 Distance Estimator)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
heading
text = "Note that this colouring is only based on distance estimation, \
it's not accurate at true distance estimation."
endheading
bool param fixit
caption = "Fix the DE"
default = false
hint = "When enabled the colouring is closer to true distance estimation \
but less useful for image mapping."
endparam
bool param julia
caption = "Julia ?"
default = false
hint = "Enable when the main formula is a Julia."
endparam
complex param seed
caption = "Julia Seed"
default = (0,0)
hint = "Set to the value of the Julia seed in the main formula."
visible = @julia
endparam
int param method
caption = "Method"
enum = "Convergent" "Divergent" "Both"
default = 2
hint = "When plugged into 'MMF Field Estimator' you should use 'Both'."
endparam
int param modec
caption = "Convergent Mode"
enum = "Distance" "Angle" "Combined"
default = 0
visible = @method!=1
endparam
int param mode
caption = "Divergent Mode"
enum = "Distance" "Angle" "Combined"
default = 0
visible = @method>0
endparam
float param bailout
caption = "Divergent Bailout"
default = 1e20
visible = @method>0
endparam
}
class MMF_Magnet2DistanceEstimator(DistanceEstimatorBase) {
; Distance Estimator for the Magnet 2 formula.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_Magnet2DistanceEstimator(Generic pparent)
DistanceEstimatorBase.DistanceEstimatorBase(pparent)
endfunc
; @param pz
; @param ppixel
func Init(complex pz, complex ppixel)
DistanceEstimatorBase.Init(pz, ppixel)
complex fz = (0,0)
complex gz = (0,0)
complex dfz = (0,0)
complex dgz = (0,0)
zold = pz
odz = 1.0
; Note that the running derivative calculation could be optimised
if @julia
fz = pz^3.0 + (3.0*(@seed - 1.0))*pz + ((@seed - 1.0)*(@seed - 2.0))
gz = 3.0*sqr(pz) + (3.0*(@seed - 2.0))*pz \
+ ((@seed - 1.0)*(@seed - 2.0)) + 1.0
dfz = 3.0*sqr(pz) + (3.0*(@seed - 1.0))
dgz = 6.0*pz + (3.0*(@seed - 2.0))
else
fz = pz^3.0 + (3.0*(m_Pixel - 1.0))*pz + ((m_Pixel - 1.0)*(m_Pixel - 2.0))
gz = 3.0*sqr(pz) + (3.0*(m_Pixel - 2.0))*pz \
+ ((m_Pixel - 1.0)*(m_Pixel - 2.0)) + 1.0
dfz = 3.0*sqr(pz) + (3.0*(m_Pixel - 1.0))
dgz = 6.0*pz + (3.0*(m_Pixel - 2.0))
endif
dz = fz*(dfz*gz - fz*dgz)/gz^3.0
if @fixit
dz = 2.0*dz
endif
endfunc
; @param pz
func Iterate(complex pz)
if @fixit
m_Iterations = m_Iterations + 1
endif
complex fz = (0,0)
complex gz = (0,0)
complex dfz = (0,0)
complex dgz = (0,0)
zold = pz
odz = dz
if @julia
fz = pz^3.0 + (3.0*(@seed - 1.0))*pz + ((@seed - 1.0)*(@seed - 2.0))
gz = 3.0*sqr(pz) + (3.0*(@seed - 2.0))*pz \
+ ((@seed - 1.0)*(@seed - 2.0)) + 1.0
dfz = 3.0*sqr(pz) + (3.0*(@seed - 1.0))
dgz = 6.0*pz + (3.0*(@seed - 2.0))
else
fz = pz^3.0 + (3.0*(m_Pixel - 1.0))*pz + ((m_Pixel - 1.0)*(m_Pixel - 2.0))
gz = 3.0*sqr(pz) + (3.0*(m_Pixel - 2.0))*pz \
+ ((m_Pixel - 1.0)*(m_Pixel - 2.0)) + 1.0
dfz = 3.0*sqr(pz) + (3.0*(m_Pixel - 1.0))
dgz = 6.0*pz + (3.0*(m_Pixel - 2.0))
endif
dz = dz*fz*(dfz*gz - fz*dgz)/gz^3.0
if @fixit
dz = 2.0*dz
endif
endfunc
; @param pz
; @return the gradient index
float func ResultIndex(complex pz)
float a = 0.0
float d = 0.0
complex zv = pz - zold
if |zv|<1.0 && @method!=1
if @modec=="Angle" || @modec=="Combined"
if (a = atan2(zv/(dz-odz))*(0.5/#pi))<0.0
a = a + 1.0
endif
if @modec=="Angle"
return a
endif
endif
if @modec=="Distance" || @modec=="Combined"
if @fixit
d = cabs(zv)
d = -d*log(d)/cabs(dz-odz)
else
d = 3.0*|(dz-odz)/zv^@cfudge|^0.03125 ; Note that this is from trial and error
endif
if @modec=="Distance"
return d
endif
endif
elseif @method>0 && |zv|>=1.0
if @mode=="Angle" || @mode=="Combined"
if (a = atan2(pz/dz)*(0.5/#pi))<0.0
a = a + 1.0
endif
if @mode=="Angle"
return a
endif
endif
if @mode=="Distance" || @mode=="Combined"
if @fixit
d = cabs(pz*log(pz)/dz)
if m_Iterations>0
a = cabs(zold*log(zold)/odz)
d = d + (d - a)*(log(0.5*log(@bailout))-log(0.5*log(|pz|))) \
/log(log(|pz|)/log(|zold|))
endif
else
; again from trial and error:
d = |dz/pz|^0.0625
endif
if @mode=="Distance"
return d
endif
endif
else
m_Solid = true
endif
return a+d
endfunc
; @param pz
; @return the distance
float func ResultDistance(complex pz)
if |pz-zold|<1.0
if @fixit
float d = cabs(pz-zold)
return -d*log(d)/cabs(dz-odz)
else
return 3.0*|(dz-odz)/(pz-zold)^@cfudge|^0.03125 ; Note that this is from trial and error
endif
else
if @fixit
float d = cabs(pz*log(pz)/dz)
if m_Iterations>0
float a = cabs(zold*log(zold)/odz)
d = d + (d - a)*(log(0.5*log(@bailout))-log(0.5*log(|pz|))) \
/log(log(|pz|)/log(|zold|))
endif
return d
else
return |dz/pz|^0.0625
endif
endif
endfunc
; @param pz
; @return the angle (from 0 to 1)
float func ResultAngle(complex pz)
float r = 0.0
if |pz-zold|<1.0
if (r=atan2((pz-zold)/(dz-odz))*(0.5/#pi))<0.0
r = r + 1.0
endif
elseif (r = atan2(pz/dz)*(0.5/#pi))<0.0
r = r + 1.0
endif
return r
endfunc
protected:
complex zold
complex odz
default:
title = "MMF Magnet 2 Distance Estimator"
int param v_mmf_magnet2distanceestimator
caption = "Version (MMF Magnet 2 Distance Estimator)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
heading
text = "Note that this colouring is only based on distance estimation, \
it's not accurate at true distance estimation."
endheading
bool param julia
caption = "Julia ?"
default = false
hint = "Enable when the main formula is a Julia."
endparam
complex param seed
caption = "Julia Seed"
default = (0,0)
hint = "Set to the value of the Julia seed in the main formula."
visible = @julia
endparam
bool param fixit
caption = "True DE"
default = false
hint = "When enabled the distance modes are much closer to true \
distance estimation however this is probably not as useful \
a colouring method for image mapping as the default."
endparam
int param method
caption = "Method"
enum = "Convergent" "Divergent" "Both"
default = 2
hint = "When plugged into 'MMF Field Estimator' you should use 'Both'."
endparam
int param modec
caption = "Convergent Mode"
enum = "Distance" "Angle" "Combined"
default = 0
visible = @method!=1
endparam
float param cfudge
caption = "Convergent Adjust"
default = 0.962
hint = "Use to remove iteration breaks."
visible = @method!=1 && @modec!=1 && !@fixit
endparam
int param mode
caption = "Divergent Mode"
enum = "Distance" "Angle" "Combined"
default = 0
visible = @method>0
endparam
float param bailout
caption = "Divergent Bailout"
default = 65536.0
visible = @method>0
endparam
}
class MMF_NovaDistanceEstimator(DistanceEstimatorBase) {
; Distance Estimator for the Nova formula.
public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_NovaDistanceEstimator(Generic pparent)
DistanceEstimatorBase.DistanceEstimatorBase(pparent)
endfunc
; @param pz
; @param ppixel
func Init(complex pz, complex ppixel)
DistanceEstimatorBase.Init(pz, ppixel)
zold = pz
odz = 1.0
; Note that the running derivative calculation could be optimised
if @julia
complex fz = (@power - @relax)*pz^@power + @relax
complex gz = @power*pz^(@power - 1.0)
complex dfz = @power*(@power - @relax)*pz^(@power - 1.0)
complex dgz = @power*(@power - 1.0)*pz^(@power - 2.0)
dz = (dfz*gz - fz*dgz)/sqr(gz)
else
dz = 1.0
endif
endfunc
; @param pz
func Iterate(complex pz)
; m_Iterations = m_Iterations + 1
complex fz = (@power - @relax)*pz^@power + @relax
complex gz = @power*pz^(@power - 1.0)
complex dfz = @power*(@power - @relax)*pz^(@power - 1.0)
complex dgz = @power*(@power - 1.0)*pz^(@power - 2.0)
zold = pz
odz = dz
dz = dz*(dfz*gz - fz*dgz)/sqr(gz)
endfunc
; @param pz
; @return the gradient index
float func ResultIndex(complex pz)
float a = 0.0
float d = 0.0
pz = pz - zold
dz = dz - odz
if @modec=="Angle" || @modec=="Combined"
if (a = atan2(pz/dz)*(0.5/#pi))<0.0
a = a + 1.0
endif
if @modec=="Angle"
return a
endif
endif
if @modec=="Distance" || @modec=="Combined"
if @fixit && @julia
d = 0.5*cabs((@power - 1.0)*pz)
d = -d*log(d)/cabs(dz)
else
d = cabs(pz/dz)
endif
if @modec=="Distance"
return d
endif
endif
return a+d
endfunc
; @param pz
; @return the distance
float func ResultDistance(complex pz)
if @fixit && @julia
float v = 0.5*cabs((@power - 1.0)*(pz - zold))
return -v*log(v)/cabs(dz-odz)
endif
return cabs((pz-zold)/(dz-odz))
endfunc
; @param pz
; @return the angle (from 0 to 1)
float func ResultAngle(complex pz)
float r = 0.0
if (r=atan2((pz-zold)/(dz-odz))*(0.5/#pi))<0.0
r = r + 1.0
endif
return r
endfunc
protected:
complex zold
complex odz
default:
title = "MMF Nova Distance Estimator"
int param v_mmf_novadistanceestimator
caption = "Version (MMF Nova Distance Estimator)"
enum = "1.0"
default = 0
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = false
endparam
heading
text = "Note that this colouring is only based on distance estimation, \
it's not really accurate at true distance estimation."
endheading
bool param julia
caption = "Julia ?"
default = false
hint = "Enable when the main formula is a Julia."
endparam
bool param fixit
caption = "Fix Julias ?"
default = false
hint = "When enabled the DE is better for some Julia Sets."
visible = @julia
endparam
int param modec
caption = "Mode"
enum = "Distance" "Angle" "Combined"
default = 0
endparam
complex param power
caption = "Nova Power"
default = (3,0)
hint = "This should match the power in the main formula."
endparam
complex param relax
caption = "Relaxation"
default = (1,0)
hint = "This should match the relaxation in the main formula."
endparam
}
class MMF_StandardDistanceEstimator(DistanceEstimatorBase) {
; Distance Estimator for formulas of the form z^p+c.
;
; Derivative using the chain rule (f,g,h are functions)
;
; f = g(h)
; f' = g'(h).h'
;
; leads to
; dz = f'(z).dz
;
; Second derivative using the product rule
;
; f'' = g''(h)h'^2 + g'(h).h''
;
; leads to
; d2z = f''(z).dz^2 + f'(z).d2z
;
Public:
import "common.ulb"
; @param pparent the parent, generally "this" for the parent, or zero
func MMF_StandardDistanceEstimator(Generic pparent)
DistanceEstimatorBase.DistanceEstimatorBase(pparent)
if @doper \
&& (@addperiod || (@passedtype && @passedposition && @addposition))
pertrans = new @pertrans(this)
if @addperiod
periodtrans = new @periodtrans(this)
endif
if @passedtype && @passedposition && @addposition
postrans = new @postrans(this)
endif
endif
endfunc
; @param pz
; @param ppixel
func Init(complex pz, complex ppixel)
DistanceEstimatorBase.Init(pz, ppixel)
sz = dz = 1.0
if @v_mmf_standarddistanceestimator=="1.0"
if @julia && @mode=="Angle"
sz = @power*pz^(@power - 1)
m_Iterations = 1
endif
else
type = -1
if @passedtype
float m = abs(real(pz))
float n = 2.0^ceil(log(m)/log(2.0)-9.0)
type = floor(m/n)
m = 512.0*(m - n*type)
type = type - 256
if real(pz)<0.0
m = -m
endif
pz = m + flip(imag(#z))
if (@passedpoint && type==1) || (@passedposition && type>1)
;; recover the point or position and original imaginary value of #z
m = abs(imag(pz))
n = 2.0^ceil(log(m)/log(2.0)-9.0)
p = floor(m/n)
m = 512.0*(m - n*p)
p = p - 257
if imag(pz)<0.0
m = -m
endif
pz = real(pz) + flip(m)
endif
endif
if @doper && (@addperiod \
|| (@passedtype && @passedposition && @addposition && type>1))
pertrans.Init(pz)
if @addperiod
periodtrans.Init(pz)
endif
if @passedtype && @passedposition && @addposition && type>1
postrans.Init(pz)
endif
endif
zold = pz
odz = 1.0;= d2z = od2z = s2z = 1.0
if @julia
sz = @power*pz^(@power - 1.0)
m_Iterations = 1
endif
if @doper
zvals[0] = pz
dzvals[0] = dz
count = 1
endif
endif
endfunc
; @param pz
func Iterate(complex pz)
if @v_mmf_standarddistanceestimator!="1.0"
odz = dz
zold = pz
endif
if !@julia && m_Iterations==0
sz = @power*pz^(@power - 1)
elseif @julia || m_Iterations>0
dz = @power*dz*pz^(@power - 1)
; if @v_mmf_standarddistanceestimator!="1.0"
; d2z = @power*(@power-1)*pz^(@power-2)*dz^2 + @power*d2z*pz^(@power-1)
; endif
if @doper
zvals[count] = pz
dzvals[count] = dz
if (count=count+1)>=201
count = 0
endif
endif
endif
m_Iterations = m_Iterations + 1
endfunc
; @param pz
; @return the gradient index
float func ResultIndex(complex pz)
float a = 0.0
float d = 0.0
if @v_mmf_standarddistanceestimator=="1.0"
if @mode=="Angle" || @mode=="Combined"
if (a = atan2(pz/(dz*sz))*(0.5/#pi))<0.0
a = a + 1.0
endif
if @mode=="Angle"
return a
endif
endif
if @mode=="Distance" || @mode=="Combined"
d = cabs(pz)
d = cabs((@power*log(d)*d/cabs(dz))^(1.0/@power))
if @mode=="Distance"
return d
endif
endif
else
if type==0 || |pz|>=@bailout
if @dodiv
if @mode=="Angle" || @mode=="Combined"
if (a = atan2(pz/(sz*dz))*(0.5/#pi))<0.0
a = a + 1.0
endif
if @mode=="Angle"
return a
endif
endif
if @mode=="Distance" || @mode=="Combined"
d = cabs(pz)
d = (cabs(@power)*log(d)*d/cabs(dz))^(1.0/cabs(@power))
if @mode=="Distance"
return d
endif
endif
else
if @divsolid
m_Solid = true
endif
return @divfill
endif
elseif type==1 || |pz-zold|<=@smallbail
if @doconv
odz = dz
dz = @power*dz*pz^(@power-1.0)
if @cmode=="Angle" || @cmode=="Combined"
if (a = atan2(-(pz-zold)/(sz*(dz-odz)))*(0.5/#pi))<0.0
a = a + 1.0
endif
if @cmode=="Angle"
return a
endif
endif
if @cmode=="Distance" || @cmode=="Combined"
d = cabs(pz-zold)
d = 2.0*(cabs(@power)*d/cabs(dz-odz))^(1.0/cabs(@power))
if @cmode=="Distance"
return d
endif
endif
else
if @convsolid
m_Solid = true
endif
return @convfill
endif
elseif @doper
int i = 0
if type>1
if (i=count-type)<0
i = i + 201
endif
else
i = count - 2
if i<0
i = i + 201
endif
while i!=count && |zvals[i]-pz|>@perbail
if (i=i-1)<0
i = 200
endif
endwhile
if (type=count-i)<0
type = type + 201
endif
endif
if i!=count
dz = @power*dz*pz^(@power-1.0)
if @pmode=="Angle" || @pmode=="Combined"
if (a = atan2(-(pz-zvals[i])/(sz*(dz-dzvals[i])))*(0.5/#pi))<0.0
a = a + 1.0
endif
if @pmode=="Angle"
if @addperiod && @passedtype && @passedposition && @addposition
a = pertrans.Iterate(a) + periodtrans.Iterate(type) \
+ postrans.Iterate(p/type)
elseif @addperiod
a = pertrans.Iterate(a) + periodtrans.Iterate(type)
elseif @passedtype && @passedposition && @addposition
a = pertrans.Iterate(a) + postrans.Iterate(p/type)
endif
return a
endif
endif
if @pmode=="Distance" || @pmode=="Combined"
d = cabs(pz-zvals[i])
d = 2.0*(cabs(@power)*d/cabs(dz-dzvals[i]))^(1.0/cabs(@power))
if @pmode=="Distance"
if @addperiod && @passedtype && @passedposition && @addposition
d = pertrans.Iterate(d) + periodtrans.Iterate(type) \
+ postrans.Iterate(p/type)
elseif @addperiod
d = pertrans.Iterate(d) + periodtrans.Iterate(type)
elseif @passedtype && @passedposition && @addposition
d = pertrans.Iterate(d) + postrans.Iterate(p/type)
endif
return d
endif
endif
d = a + d
a = 0
if @addperiod && @passedtype && @passedposition && @addposition
d = pertrans.Iterate(d) + periodtrans.Iterate(type) \
+ postrans.Iterate(p/type)
elseif @addperiod
d = pertrans.Iterate(d) + periodtrans.Iterate(type)
elseif @passedtype && @passedposition && @addposition
d = pertrans.Iterate(d) + postrans.Iterate(p/type)
endif
else
if @persolid
m_Solid = true
endif
return @perfill
endif
else
if @persolid
m_Solid = true
endif
return @perfill
endif
endif
return a+d
endfunc
; @param pz
; @return the distance
float func ResultDistance(complex pz)
float d = 0.0
if @v_mmf_standarddistanceestimator=="1.0" || type==0 || |pz|>=@bailout
d = cabs(pz)
return (cabs(@power)*log(d)*d/cabs(dz))^(1.0/cabs(@power))
elseif type==1 || |pz-zold|<=@smallbail
complex ndz = @power*dz*pz^(@power-1.0)
d = cabs(pz-zold)
return 2.0*(cabs(@power)*d/cabs(ndz-dz))^(1.0/cabs(@power))
else
int i = 0
if type>1
if (i=count-type)<0
i = i + 201
endif
else
i = count - 2
if i<0
i = i + 201
endif
while i!=count && |zvals[i]-pz|>@perbail
if (i=i-1)<0
i = 200
endif
endwhile
endif
if i!=count
complex ndz = @power*dz*pz^(@power-1.0)
d = cabs(pz-zvals[i])
d = 2.0*(cabs(@power)*d/cabs(ndz-dzvals[i]))^(1.0/cabs(@power))
if @addperiod && @passedtype && @passedposition && @addposition
return pertrans.Iterate(d) + periodtrans.Iterate(type) \
+ postrans.Iterate(p/type)
elseif @addperiod
return pertrans.Iterate(d) + periodtrans.Iterate(type)
elseif @passedtype && @passedposition && @addposition
return pertrans.Iterate(d) + postrans.Iterate(p/type)
else
return d
endif
else
return 0.0
endif
endif
endfunc
; @param pz
; @return the angle (from 0 to 1)
float func ResultAngle(complex pz)
float r = 0.0
if @v_mmf_standarddistanceestimator=="1.0" || |pz|>=@bailout
if (r=atan2(pz/(dz*sz))*(0.5/#pi))<0.0
r = r + 1.0
endif
elseif |pz-zold|<=@smallbail
complex ndz = @power*dz*pz^(@power-1.0)
if (r = atan2(-(pz-zold)/(sz*(ndz-dz)))*(0.5/#pi))<0.0
r = r + 1.0
endif
else
int i = 0
if type>1
if (i=count-type)<0
i = i + 201
endif
else
i = count - 2
if i<0
i = i + 201
endif
while i!=count && |zvals[i]-pz|>@perbail
if (i=i-1)<0
i = 200
endif
endwhile
endif
while i!=count && |zvals[i]-pz|>@perbail
if (i=i-1)<0
i = 200
endif
endwhile
if i!=count
complex ndz = @power*dz*pz^(@power-1.0)
if (r = atan2(-(pz-zvals[i])/(sz*(ndz-dzvals[i])))*(0.5/#pi))<0.0
r = r + 1.0
endif
if @addperiod && @passedtype && @passedposition && @addposition
r = pertrans.Iterate(r) + periodtrans.Iterate(type) \
+ postrans.Iterate(p/type)
elseif @addperiod
r = pertrans.Iterate(r) + periodtrans.Iterate(type)
elseif @passedtype && @passedposition && @addposition
r = pertrans.Iterate(r) + postrans.Iterate(p/type)
endif
endif
endif
return r
endfunc
protected:
Transfer pertrans
Transfer periodtrans
Transfer postrans
complex zvals[201]
complex dzvals[201]
complex sz
complex zold
complex odz
int type
int count
int p
; complex d2z
; complex od2z
; complex s2z
default:
title = "MMF Standard Distance Estimator"
heading
caption = "Information"
text = "This colouring formula understands the mmf5.ufm:Multi Bailout \
Formula (and possibly other compatible formulas) that include \
periodic bailout testing and that can be set to pass the bailout \
type and other information to the colouring. Note that in this \
colouring the 'Periodic settings' will only work correctly when \
such a fractal formula is used with the fractal formula set to \
test for periodic bailout and either 'Colour using entire orbit' \
or 'Pass Bailout Type' is enabled - if neither of these is \
enabled then this colouring will treat periodic bailout as being \
standard convergence and the colouring in such areas will not be \
'correct'. Note that in this colouring 'Bailout type passed' \
should be enabled when 'Pass bailout type' is enabled in the \
fractal formula, 'Convergent point passed' should be enabled when \
'Pass which point' is in use and enabled in the fractal formula \
and 'Period position passed' should be enabled when 'Pass period \
position' is in use and enabled in the fractal formula."
endheading
heading
caption = "Main control"
endheading
int param v_mmf_standarddistanceestimator
caption = "Version (MMF Standard Distance Estimator)"
enum = "1.0" "1.1"
default = 1
hint = "This field is to absolutely ensure backward compatibility, \
the default will always be set to the latest version, but \
there may be some cases where an older effect that you like \
is lost in an update and you could still use it by selecting \
the older version number."
visible = true
endparam
complex param power
caption = "Power (p in z^p+c)"
default = (2,0)
endparam
bool param julia
caption = "Julia ?"
default = false
hint = "Enable if your main formula is a Julia."
endparam
bool param passedtype
caption = "Bailout type passed ?"
default = false
hint = "Enable if the main fractal formula has a parameter enabled to \
pass the bailout type to the colouring. At the moment the only \
formula with this parameter option is mmf5.ufm:Multi Bailout \
Formula."
visible = @v_mmf_standarddistanceestimator!="1.0"
endparam
bool param passedpoint
caption = "Convergent point passed ?"
default = false
hint = "Enable if the main fractal formula has a parameter enabled to \
pass the attraction point to the colouring. At the moment the only \
formula with this parameter option is mmf5.ufm:Multi Bailout \
Formula."
visible = @v_mmf_standarddistanceestimator!="1.0" && @passedtype
endparam
bool param passedposition
caption = "Period position passed ?"
default = false
hint = "Enable if the main fractal formula has a parameter enabled to \
pass the period position to the colouring. At the moment the only \
formula with this parameter option is mmf5.ufm:Multi Bailout \
Formula."
visible = @v_mmf_standarddistanceestimator!="1.0" && @passedtype
endparam
heading
caption = "Divergent settings"
visible = @v_mmf_standarddistanceestimator!="1.0"
endheading
float param bailout
caption = "Bailout (divergent)"
default = 128.0
hint = "You should set this to the divergent bailout value in the \
fractal formula."
visible = @v_mmf_standarddistanceestimator!="1.0"
endparam
bool param dodiv
caption = "Colour divergent ?"
default = true
hint = "When enabled divergent areas will be coloured using distance \
estimator values or angles, when disabled you can have them \
filled either in the solid colour or by specifying a value to \
use to look up a gradient colour."
visible = @v_mmf_standarddistanceestimator!="1.0"
endparam
int param mode
caption = "Mode (divergent)"
enum = "Distance" "Angle" "Combined"
default = 0
visible = @v_mmf_standarddistanceestimator=="1.0" || @dodiv
endparam
bool param divsolid
caption = "Solid ? (divergent)"
default = true
hint = "When enabled divergent areas are filled using the solid colour."
visible = @v_mmf_standarddistanceestimator!="1.0" && !@dodiv
endparam
float param divfill
caption = "Fill value (divergent)"
default = 0.0
hint = "The value to use to look up a fill colour from UF's gradient for \
divergent areas. When the standard colour parameters are at the \
default settings this value corresponds to the gradient positions \
i.e. from 0.0 to 399.999."
visible = @v_mmf_standarddistanceestimator!="1.0" && !@dodiv && !@divsolid
endparam
heading
caption = "Convergent settings"
text = "This is *not* a true distance estimate in convergent areas, \
it is merely based on the normal distance estimator formula as \
adapted to work on the Newton fractal and other convergent \
fractals. It is used here as it does provide a valuable \
colouring alternative."
visible = @v_mmf_standarddistanceestimator!="1.0"
endheading
float param smallbail
caption = "Bailout (convergent)"
default = 1e-8
hint = "You should set this to the convergent bailout value in the \
fractal formula."
visible = @v_mmf_standarddistanceestimator!="1.0"
endparam
bool param doconv
caption = "Colour convergent ?"
default = true
hint = "When enabled convergent areas will be coloured using distance \
estimator values or angles, when disabled you can have them \
filled either in the solid colour or by specifying a value to \
use to look up a gradient colour."
visible = @v_mmf_standarddistanceestimator!="1.0"
endparam
int param cmode
caption = "Mode (convergent)"
enum = "Distance" "Angle" "Combined"
default = 0
visible = @v_mmf_standarddistanceestimator!="1.0" && @doconv
endparam
bool param convsolid
caption = "Solid ? (convergent)"
default = true
hint = "When enabled convergent areas are filled using the solid colour."
visible = @v_mmf_standarddistanceestimator!="1.0" && !@doconv
endparam
float param convfill
caption = "Fill value (convergent)"
default = 0.0
hint = "The value to use to look up a fill colour from UF's gradient for \
convergent areas. When the standard colour parameters are at the \
default settings this value corresponds to the gradient positions \
i.e. from 0.0 to 399.999."
visible = @v_mmf_standarddistanceestimator!="1.0" && !@doconv && !@convsolid
endparam
heading
caption = "Periodic settings"
text = "This is *not* a true distance estimate in periodic areas, \
it is merely based on the normal distance estimator formula as \
adapted to work on the Newton fractal and other convergent \
fractals. It is used here as it does provide a valuable \
colouring alternative."
visible = @v_mmf_standarddistanceestimator!="1.0"
endheading
float param perbail
caption = "Bailout (periodic)"
default = 1e-8
hint = "You should set this to the periodic bailout value in the \
fractal formula (if any)."
visible = @v_mmf_standarddistanceestimator!="1.0"
endparam
bool param doper
caption = "Colour periodic ?"
default = true
hint = "When enabled periodic areas will be coloured using distance \
estimator values or angles, when disabled you can have them \
filled either in the solid colour or by specifying a value to \
use to look up a gradient colour."
visible = @v_mmf_standarddistanceestimator!="1.0"
endparam
int param pmode
caption = "Mode (periodic)"
enum = "Distance" "Angle" "Combined"
default = 0
visible = @v_mmf_standarddistanceestimator!="1.0" && @doper
endparam
bool param addperiod
caption = "Add period ?"
default = false
hint = "When enabled the period found will be mixed with your chosen \
periodic colouring."
visible = @v_mmf_standarddistanceestimator!="1.0" && @doper
endparam
bool param addposition
caption = "Add position ?"
default = false
hint = "When enabled the position of the attractor found within the \
period will be mixed in the final colouring value."
visible = @v_mmf_standarddistanceestimator!="1.0" && @doper \
&& @passedtype && @passedposition
endparam
Transfer param pertrans
caption = "Periodic colour transfer"
default = NullTransfer
hint = "Use to scale either your periodic distance or angle value \
before it is mixed with the period and/or position values."
visible = @v_mmf_standarddistanceestimator!="1.0" && @doper && (@addperiod \
|| (@passedtype && @passedposition && @addposition))
endparam
Transfer param periodtrans
caption = "Period transfer"
default = NullTransfer
hint = "Use to scale the period found before it is mixed with the final \
colour."
visible = @v_mmf_standarddistanceestimator!="1.0" && @doper && @addperiod
endparam
Transfer param postrans
caption = "Position transfer"
default = NullTransfer
hint = "Use to scale the position found before it is mixed with the final \
colour."
visible = @v_mmf_standarddistanceestimator!="1.0" && @doper \
&& @passedtype && @passedposition && @addposition
endparam
bool param persolid
caption = "Solid ? (periodic)"
default = true
hint = "When enabled periodic areas are filled using the solid colour."
visible = @v_mmf_standarddistanceestimator!="1.0" && !@doper
endparam
float param perfill
caption = "Fill value (periodic)"
default = 0.0
hint = "The value to use to look up a fill colour from UF's gradient for \
periodic areas. When the standard colour parameters are at the \
default settings this value corresponds to the gradient positions \
i.e. from 0.0 to 399.999."
visible = @v_mmf_standarddistanceestimator!="1.0" && !@doper && !@persolid
endparam
}
class MMF_SeedDLA(common.ulb:Generic) {
public:
import "common.ulb"
; @param pparent the parent, generally "this" from "DLA Inspired"
func MMF_SeedDLA(Generic pparent)
m_Parent = pparent
endfunc
default:
int param mmf_seeddla
caption = "Version (MMF_SeedDLA)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @mmf_seeddla < 100
endparam
}
class MMF_DeadDLA(common.ulb:Generic) {
public:
import "common.ulb"
; @param pparent the parent, generally "this" from "DLA Inspired"
func MMF_DeadDLA(Generic pparent)
m_Parent = pparent
endfunc
; @param x the x pixel position of a stimulus
; @param y the y pixel position of a stimulus
; @return the square of the pixel distance
float func DeadDistance(float x,float y)
return 1e200
endfunc
default:
int param mmf_deaddla
caption = "Version (MMF_DeadDLA)"
default = 100
hint = "This version parameter is used to detect when a change has \
been made to the formula that is incompatible with the \
previous version. When that happens, this field will reflect \
the old version number to alert you to the fact that an \
alternate rendering is being used."
visible = @mmf_deaddla < 100
endparam
color param colour
caption = "Dead Point Colour"
default = RGB(0,0,0)
hint = "Note that if not using a direct colouring mode then this \
parameter is ignored and 'dead' points are set to the palette \
colour from 'Dead Point Index'."
endparam
float param index
caption = "Dead Point Index"
default = 399.0
min = 0.0
max = 399.0
hint = "Note that if not using a gradient colouring mode then this \
parameter is ignored and 'dead' points are set to the colour \
from 'Dead Point Colour'."
endparam
}
class MMF_NoDeadDLA(MMF_DeadDLA) {
public:
import "common.ulb"
; @param pparent the parent, generally "this" from "DLA Inspired"
func MMF_NoDeadDLA(Generic pparent)
m_Parent = pparent
endfunc
; @param x the x pixel position of a stimulus
; @param y the y pixel position of a stimulus
; @return the square of the pixel distance
float func DeadDistance(float x,float y)
return 1e200
endfunc
default:
title = "No Dead Point DLA Seeding"
color param colour
default = RGB(0,0,0)
visible = false
endparam
float param index
default = 399.0
visible = false
endparam
}
class MMF_OnePointDeadDLA(MMF_DeadDLA) {
import "common.ulb"
; @param pparent the parent, generally "this" from "DLA Inspired"
func MMF_OnePointDeadDLA(Generic pparent)
m_Parent = pparent
MMF_DLA(pparent).SetDeadPoint(floor(@xco*#width)+2,floor(@yco*#height)+2, \
@colour,@index)
MMF_DLA(pparent).SetDeadPoint(floor(@xco*#width)+3,floor(@yco*#height)+2, \
@colour,@index)
MMF_DLA(pparent).SetDeadPoint(floor(@xco*#width)+2,floor(@yco*#height)+3, \
@colour,@index)
MMF_DLA(pparent).SetDeadPoint(floor(@xco*#width)+3,floor(@yco*#height)+3, \
@colour,@index)
endfunc
; @param x the x pixel position of a stimulus
; @param y the y pixel position of a stimulus
; @return the square of the pixel distance
float func DeadDistance(float x,float y)
return sqr(x-floor(@xco*#width)-2) + sqr(y-floor(@yco*#height)-2)
endfunc
default:
title = "Single Dead Point"
float param xco
caption = "Fraction Across Screen"
default = 0.25
min = 0.0
max = 1.0
hint = "Use 0.0 for the far left, use 1.0 for the far right."
endparam
float param yco
caption = "Fraction Down Screen"
default = 0.25
min = 0.0
max = 1.0
hint = "Use 0.0 for the top, use 1.0 for the bottom."
endparam
}
class MMF_LineDeadDLA(MMF_DeadDLA) {
public:
import "common.ulb"
; @param pparent the parent, generally "this" from "DLA Inspired"
func MMF_LineDeadDLA(Generic pparent)
m_Parent = pparent
d2 = sqr(dx=(real(@le)-real(@ls))*#width) \
+ sqr(dy=(imag(@le)-imag(@ls))*#height)
id2 = 1.0/d2
float x = real(@ls)*#width + 2
float y = imag(@ls)*#height + 2
if abs(dx)>=abs(dy)
if dx==0
MMF_DLA(pparent).SetDeadPoint(floor(x),floor(y),@colour,@index)
MMF_DLA(pparent).SetDeadPoint(floor(x)+1,floor(y),@colour,@index)
MMF_DLA(pparent).SetDeadPoint(floor(x),floor(y)+1,@colour,@index)
MMF_DLA(pparent).SetDeadPoint(floor(x)+1,floor(y)+1,@colour,@index)
elseif dx>0
float d = dy/dx
repeat
MMF_DLA(pparent).SetDeadPoint(floor(x),floor(y),@colour,@index)
MMF_DLA(pparent).SetDeadPoint(floor(x),floor(y)+1,@colour,@index)
y = y + d
until (x=x+1)>real(@le)*#width + 2
else
float d = -dy/dx
repeat
MMF_DLA(pparent).SetDeadPoint(floor(x),floor(y),@colour,@index)
MMF_DLA(pparent).SetDeadPoint(floor(x),floor(y)+1,@colour,@index)
y = y + d
until (x=x-1)