Index: source/blender/render/intern/source/texture.c =================================================================== --- source/blender/render/intern/source/texture.c (revision 12209) +++ source/blender/render/intern/source/texture.c (working copy) @@ -28,6 +28,9 @@ #include #include #include +#ifdef WIN32 +#define _USE_MATH_DEFINES +#endif #include #include "MTC_matrixops.h" @@ -73,9 +76,8 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#define M_PI_OVER_180 0.0174532925199 - - /* note; this is called WITH RENDER IS NULL in src/drawview.c for animated background image, option should move to kernel */ void init_render_texture(Render *re, Tex *tex) @@ -690,9 +692,1540 @@ } +/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ +/* Determines which side of the line a point is. Assume +ve for left of vector pointing from pa to pb. */ +#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1])) + +/* Determines if a point p0 is inside a triangle (p1, p2, p3). */ +#define POINT_IN_TRI(p0,p1,p2,p3) ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0)) + +/* Signed distance of point (x, y) from line Ax + By + C = 0. */ +#define DIST_POINT_TO_LINE(A, B, C, x, y) (((A) * (x) + (B) * (y) + (C)) / sqrt((A) * (A) + (B) * (B))) + +/* Given signed distance d from a line and bevel width b, compute a linear gradient for the positive + * side of the line. Points on the negative side will have intensity 0 and points beyond distance + * b will have intensity 1. + */ +#define LINE_BEVEL(d, b) d = (d < 0) ? 0 : ((d <= b) && (b > 0)) ? (d) / (b) : 1 + +/* Used to identify how neighbouring tiles are used to compute bump and colour */ +#define TILE_CURRENT 0 +#define TILE_ABOVE 1 +#define TILE_BELOW 2 +#define TILE_LEFT 3 +#define TILE_RIGHT 4 +#define TILE_RIGHT_ABOVE 5 +#define TILE_RIGHT_BELOW 6 +#define TILE_LEFT_ABOVE 7 +#define TILE_LEFT_BELOW 8 + +static float mod(float a, float b) +{ + /* Calculate a mod b for floating point numbers. + * NOTE: a can be negative however I'm not sure what behaviour this function + * has if b is negative + * + * NOTE: Copied from plugin brick.c by Unicorn. The original code was in Public + * Domain and is supplied with the Blender Texture Plugins repository. + */ + int n = (int)(a / b); + a -= n * b; + if (a < 0) a += b; + return a; +} + +static float smoothstep(float x, float a, float b) +{ + /* Calculate a step function as follows: + * y = 0 for x < 0 + * y = -2x^2 + 3x^3 for 0 <= x <= 1 + * y = 1 for x > 1 + * + * Since we're using an interval of [a, b] instead of [0, 1] + * we have to transform x with (x - a) / (b - a). + */ + float e; + + if (a == b) + { + return (x < a) ? 0 : 1; + } + + if (x < a) return 0; + if (x > b) return 1; + + e = (x - a) / (b - a); + return e * e * (3 - 2 * e); +} + +void tiles_precalc(Tex *tex) +{ + /* Compute a set of random widths for the tiles. The array tex->precalc->pat[] will + * accumulate the gap and tile widths in each cell starting at 0. + */ + Tex *t = (Tex *)tex; + float w = fabs(t->maxwidth - t->minwidth); + float h = fabs(t->maxheight - t->minheight); + float b = fabs(t->maxbump - t->minbump); + float r; + float sum; + float h1, s1, v1, h2, s2, v2; + float mh, ms, mv; + short i, j; + RNG *rng = rng_new(tex->seed); + + /* Initialize min/max values */ + t->precalc.minw = MAX2(t->minwidth, t->maxwidth); + t->precalc.maxw = 0; + t->precalc.minh = MAX2(t->minheight, t->maxheight); + t->precalc.maxh = 0; + + /* Compute random numbers between minwidth and maxwidth. Keep a running total + * of the width of the pattern. All the width's will then be scaled by this + * to bring into the [0, 1] range; otherwise, the pattern won't be seamless + * for the 2D->3D texture mapping functions. + */ + t->precalc.hpat[0] = 0; + sum = 0; + for (i = 1; i <= t->hcount; i++) { + r = rng_getFloat(rng); + r = t->minwidth + w * r; + t->precalc.hpat[i] = t->hgap + t->precalc.hpat[i - 1] + r; + sum += t->hgap + r; + + t->precalc.minw = MIN2(t->precalc.minw, r); + t->precalc.maxw = MAX2(t->precalc.maxw, r); + } + sum = 1.0/sum; + for (i = 1; i <= t->hcount; i++) { + t->precalc.hpat[i] *= sum; + } + t->precalc.minw *= sum; + t->precalc.maxw *= sum; + t->precalc.hgap = t->hgap * sum; + + /* Compute random numbers between minheight and maxheight. Keep a running total + * of the height of the pattern. All the height's will then be scaled by this + * to bring into the [0, 1] range; otherwise, the pattern won't be seamless + * for the 2D->3D texture mapping functions. + */ + t->precalc.vpat[0] = 0; + sum = 0; + for (i = 1; i <= t->vcount; i++) { + r = rng_getFloat(rng); + r = t->minheight + h * r; + t->precalc.vpat[i] = t->vgap + t->precalc.vpat[i - 1] + r; + sum += t->vgap + r; + + t->precalc.minh = MIN2(t->precalc.minh, r); + t->precalc.maxh = MAX2(t->precalc.maxh, r); + } + sum = 1.0/sum; + for (i = 1; i <= t->vcount; i++) { + t->precalc.vpat[i] *= sum; + } + t->precalc.minh *= sum; + t->precalc.maxh *= sum; + t->precalc.vgap = t->vgap * sum; + + /* Compute random numbers between minbump and maxbump */ + for (i = 0; i < t->hcount; i++) { + for (j = 0; j < t->vcount; j++) { + r = rng_getFloat(rng); + t->precalc.bpat[i][j] = t->minbump + b * r; + } + } + for (i = 0; i < 16; i++) { + r = rng_getFloat(rng); + t->precalc.rpat[i] = t->minbump + b * r; + } + + /* Compute random colours using the base colour [colr1, colg1, colb1] and the + * percentage variation in hue, saturation and value. + */ + rgb_to_hsv(t->colr1, t->colg1, t->colb1, &h1, &s1, &v1); + mh = 0.5 * t->fhue; + ms = 0.5 * t->fsat; + mv = 0.5 * t->fval; + for (i = 0; i < t->hcount; i++) { + for (j = 0; j < t->vcount; j++) { + r = rng_getFloat(rng); + h2 = h1 + r * t->fhue - mh; + s2 = s1 + r * t->fsat - ms; + v2 = v1 + r * t->fval - mv; + if (h2 > 1.0) h2 -= 1.0; else if (h2 < 0.0) h2 += 1.0; + if (s2 > 1.0) s2 -= 1.0; else if (s2 < 0.0) s2 += 1.0; + if (v2 > 1.0) v2 -= 1.0; else if (v2 < 0.0) v2 += 1.0; + hsv_to_rgb(h2, s2, v2, &t->precalc.r[i][j], &t->precalc.g[i][j], &t->precalc.b[i][j]); + } + } + + rng_free(rng); +} + +static float tiles_bevel_dim(Tex *tex, float w, float h) +{ + /* Determine the dimension of the tiles used to compute the bevel */ + float s; + switch (tex->bevoption) + { + case TEX_BEVEL_UNIFORMMIN: + s = MIN2(tex->precalc.minw, tex->precalc.minh); + break; + case TEX_BEVEL_UNIFORMMAX: + s = MIN2(tex->precalc.maxw, tex->precalc.maxh); + break; + default: + s = MIN2(w, h); + break; + } + return s; +} + +static float tiles_rect_func(float x, float y, float w, float h, float b) +{ + /* Calculate signed distance from the 4 sides of the rectangle bounded by: + * x = 0, y = 0, x = w, y = h. + * The sign indicates whether point is inside, on or outside the rectangle + * aiding us in applying gradients based on sidedness. + * + * NOTE: This is optimized version of tiles_poly_func() + */ + float dx1 = x; + float dy1 = y; + float dx2 = w - x; + float dy2 = h - y; + + /* Find minimum distance to point from the 4 sides */ + float dmin = MIN4(dx1, dx2, dy1, dy2); + + float v = 0; + if (dmin > b) { + v = 1; + } + else if ((dmin >= 0) && (b > 0)) { + v = dmin / b; + } + + return v; +} + +static float tiles_rect_func2(float x, float y, float w, float h, float b, float sx, float sy) +{ + /* Calculate signed distance from the 8 lines: + * x = 0, y = 0, x = w, y = h, + * sy * x + sx * y - sx * sy = 0, + * sy * x - sx * y + sx * (h - sy) = 0, + * -sy * x + sx * y + sy * (w - sx) = 0, + * -sy * x - sx * y + sy * (w - sx) + sx * h = 0 + * + * The sign indicates whether point is inside, on or outside the rectangle + * aiding us in applying gradients based on sidedness. + * + * NOTE: This is optimized version of tiles_poly_func() + */ + float v = tiles_rect_func(x, y, w, h, b); + float d1 = DIST_POINT_TO_LINE(sy, sx, -sx * sy, x, y); + float d2 = DIST_POINT_TO_LINE(sy, -sx, sx * (h - sy), x, y); + float d3 = DIST_POINT_TO_LINE(-sy, sx, sy * (w - sx), x, y); + float d4 = DIST_POINT_TO_LINE(-sy, -sx, sy * (w - sx) + sx * h, x, y); + float d; + + LINE_BEVEL(d1, b); + LINE_BEVEL(d2, b); + LINE_BEVEL(d3, b); + LINE_BEVEL(d4, b); + + d = MIN4(d1, d2, d3, d4); + + return MIN2(v, d); +} + +static float tiles_poly_func(float x, float y, float *vx, float *vy, short n, float b) +{ + /* Do a linear gradient for an n-sided polygon from 0 for outer edge to 1 + * for a distance b from outer edge inside the polygon. Any point beyond + * distance b inside the polygon gets intensity 1. + * + * NOTE: Specify polygon vertices counter-clockwise and n >= 3. + */ + int i, i1; + float p[2], p1[2], p2[2]; + float m, d, d1, dx; + + /* Determine if p lies in the polygon */ + p[0] = x; + p[1] = y; + for (i = 0; i < n; i++) + { + /* If point lies outside boundary just return 0. */ + i1 = (i + 1) % n; + p1[0] = vx[i]; + p1[1] = vy[i]; + p2[0] = vx[i1]; + p2[1] = vy[i1]; + if (SIDE_OF_LINE(p1, p2, p) < 0) { + return 0; + } + + /* Compute distance to the line containing current side */ + dx = p1[0] - p2[0]; + if (fabs(dx) > 0) { + m = (p1[1] - p2[1]) / dx; + d1 = fabs(DIST_POINT_TO_LINE(m, -1, p1[1] - p1[0] * m, x, y)); + } + else + { + d1 = fabs(x - p1[0]); + } + + /* Take minimum distance so far */ + d = (i == 0) ? d1 : MIN2(d, d1); + } + + LINE_BEVEL(d, b); + + return d; +} + +static float tiles_circle_func1(float x, float y, float cx, float cy, float b, float r) +{ + /* Calculate signed distance from the circle bounded by: + * (x - cx)^2 + (y - cy)^2 = r^2 + * The sign indicates whether point is inside, on or outside the circle + * aiding us in applying gradients based on sidedness. + * + * For points that lie within a distance of r - b from the center the intensity is 1. + * For points at distance of r - b to r, the intensity is linear from 1 to 0. + * For all other points the intensity is 0. + */ + float dx = (x - cx); + float dy = (y - cy); + float d = r - sqrt(dx * dx + dy * dy); + + float v = 0; + if (d > b) { + v = 1; + } + else if ((d >= 0) && (b > 0)) { + v = d / b; + } + + return v; +} + +static float tiles_circle_func2(float x, float y, float cx, float cy, float b, float r) +{ + /* Calculate signed distance from the circle bounded by: + * (x - cx)^2 + (y - cy)^2 = r^2 + * The sign indicates whether point is inside, on or outside the circle + * aiding us in applying gradients based on sidedness. + * + * For points that lie within a distance of r - b from the center the intensity is 0. + * For points at distance of r - b to r, the intensity is linear from 0 to 1. + * For all other points the intensity is 1. + */ + float dx = (x - cx); + float dy = (y - cy); + float d = sqrt(dx * dx + dy * dy) - r; + + float v = 0; + if (d > b) { + v = 1; + } + else if ((d >= 0) && (b > 0)) { + v = d / b; + } + + return v; +} + +static float tiles_roundrect_func(float x, float y, float w, float h, float b, float r, short flip) +{ + /* First compute the intensity inside the rectangle bounded by (0, 0) and (w, h). */ + float v = tiles_rect_func(x, y, w, h, b); + float t = v; + float hw = w * 0.5; + float hh = h * 0.5; + + if (flip) { + /* For points that lie inside the four corners determine if they fall inside the circle + * centered at the corners and apply a linear gradient. This does the inverted circular + * shape. + */ + if ((x >= 0) && (x <= hw)) { + if ((y >= 0) && (y <= hh)) { + t = tiles_circle_func2(x, y, 0, 0, b, r); + } + else if ((y > hh) && (y <= h)) { + t = tiles_circle_func2(x, y, 0, h, b, r); + } + } + else if ((x > hw) && (x <= w)) { + if ((y >= 0) && (y <= hh)) { + t = tiles_circle_func2(x, y, w, 0, b, r); + } + else if ((y > hh) && (y <= h)) { + t = tiles_circle_func2(x, y, w, h, b, r); + } + } + v = MIN2(t, v); + } + else { + /* For points that lie inside the four corners determine if they fall inside the circle + * centered at the offset by the radius and apply a linear gradient. + */ + if ((x >= 0) && (x <= r)) { + if ((y >= 0) && (y <= r)) { + v = tiles_circle_func1(x, y, r, r, b, r); + } + else if ((y >= h - r) && (y <= h)) { + v = tiles_circle_func1(x, y, r, h - r, b, r); + } + } + else if ((x >= w - r) && (x <= w)) { + if ((y >= 0) && (y <= r)) { + v = tiles_circle_func1(x, y, w - r, r, b, r); + } + else if ((y >= h - r) && (y <= h)) { + v = tiles_circle_func1(x, y, w - r, h - r, b, r); + } + } + } + + return v; +} + +static float tiles_ellipse_func1(float x, float y, float cx, float cy, float b, float rx, float ry) +{ + /* Calculate signed distance from the ellipse bounded by: + * [(x - cx) / rx]^2 + [(y - cy) / ry]^2 = 1 + * The sign indicates whether point is inside, on or outside the ellipse + * aiding us in applying gradients based on sidedness. + * + * For points inside the ellipse from the center to distance b from the curve, intensity is 1. + * For points starting at distance b from the curve to the curve, the intensity is linear from 1 to 0. + * For all other points the intensity is 0. + */ + float v, c, x1, y1, d, f, r2; + + /* Shift origin to (0, 0) */ + x -= cx; + y -= cy; + + /* Compute the point (x1, y1) on the ellipse that forms a line through + * (0, 0) and (x, y). + */ + f = sqrt(x * x * ry * ry + y * y * rx * rx); + r2 = rx * ry; + c = r2 / f; + x1 = x * c; + y1 = y * c; + + /* Compute distance between the given point and computed point */ + d = sqrt((x - x1)*(x - x1) + (y - y1)*(y - y1)); + + v = 0; + + /* Test signed distance to see if point is inside or outside the ellipse */ + if (f <= r2) { + /* Apply linear gradient */ + if (d > b) { + v = 1; + } + else if (b > 0) { + v = d / b; + } + } + + return v; +} + +static float tiles_ellipse_func2(float x, float y, float cx, float cy, float b, float rx, float ry) +{ + /* Calculate signed distance from the ellipse bounded by: + * [(x - cx) / rx]^2 + [(y - cy) / ry]^2 = 1 + * The sign indicates whether point is inside, on or outside the ellipse + * aiding us in applying gradients based on sidedness. + * + * For points inside the ellipse from the center to distance b from the curve, intensity is 0. + * For points starting at distance b from the curve to the curve, the intensity is linear from 0 to 1. + * For all other points the intensity is 1. + */ + float v, c, x1, y1, d, f, r2; + + /* Shift origin to (0, 0) */ + x -= cx; + y -= cy; + + /* Compute the point (x1, y1) on the ellipse that forms a line through + * (0, 0) and (x, y). + */ + f = sqrt(x * x * ry * ry + y * y * rx * rx); + r2 = rx * ry; + c = r2 / f; + x1 = x * c; + y1 = y * c; + + /* Compute distance between the given point and computed point */ + d = sqrt((x - x1)*(x - x1) + (y - y1)*(y - y1)); + + v = 0; + + /* Test signed distance to see if point is inside or outside the ellipse */ + if (f >= r2) { + /* Apply linear gradient */ + if (d > b) { + v = 1; + } + else if (b > 0) { + v = d / b; + } + } + + return v; +} + +static float tiles_ellipserect_func(float x, float y, float w, float h, float b, float rx, float ry, short flip) +{ + /* First compute the intensity inside the rectangle bounded by (0, 0) and (w, h). */ + float v = tiles_rect_func(x, y, w, h, b); + float t = v; + float hw = w * 0.5; + float hh = h * 0.5; + + if (flip) { + /* For points that lie inside the four corners determine if they fall inside the ellipse + * centered at the corners and apply a linear gradient. This does the inverted circular + * shape. + */ + if ((x >= 0) && (x <= hw)) { + if ((y >= 0) && (y <= hh)) { + t = tiles_ellipse_func2(x, y, 0, 0, b, rx, ry); + } + else if ((y > hh) && (y <= h)) { + t = tiles_ellipse_func2(x, y, 0, h, b, rx, ry); + } + } + else if ((x > hw) && (x <= w)) { + if ((y >= 0) && (y <= hh)) { + t = tiles_ellipse_func2(x, y, w, 0, b, rx, ry); + } + else if ((y > hh) && (y <= h)) { + t = tiles_ellipse_func2(x, y, w, h, b, rx, ry); + } + } + v = MIN2(t, v); + } + else { + /* For points that lie inside the four corners determine if they fall inside the ellipse + * centered at the offset (rx, ry) and apply a linear gradient. + */ + if ((x >= 0) && (x <= rx)) { + if ((y >= 0) && (y <= ry)) { + t = tiles_ellipse_func1(x, y, rx, ry, b, rx, ry); + v = MIN2(v, t); + } + else if ((y >= h - ry) && (y <= h)) { + t = tiles_ellipse_func1(x, y, rx, h - ry, b, rx, ry); + v = MIN2(v, t); + } + } + else if ((x >= w - rx) && (x <= w)) { + if ((y >= 0) && (y <= ry)) { + t = tiles_ellipse_func1(x, y, w - rx, ry, b, rx, ry); + v = MIN2(v, t); + } + else if ((y >= h - ry) && (y <= h)) { + t = tiles_ellipse_func1(x, y, w - rx, h - ry, b, rx, ry); + v = MIN2(v, t); + } + } + } + + return v; +} + +static float tiles_recthelper_int(Tex *tex, float x, float y, float w, float h, float dim) +{ + float b = dim * tex->bevel; + float rx, ry, intens; + + switch (tex->corner) { + case TEX_CORNER_ROUND1: + if (tex->hcorner == tex->vcorner) { + rx = tex->hcorner * dim; + intens = tiles_roundrect_func(x, y, w, h, b, rx, 0); + } + else { + rx = tex->hcorner * dim; + ry = tex->vcorner * dim; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 0); + } + break; + case TEX_CORNER_ROUND2: + if (tex->hcorner == tex->vcorner) { + rx = tex->hcorner * dim; + intens = tiles_roundrect_func(x, y, w, h, b, rx, 1); + } + else { + rx = tex->hcorner * dim; + ry = tex->vcorner * dim; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 1); + } + break; + case TEX_CORNER_ELLIPSE1: + rx = tex->hcorner * w; + ry = tex->vcorner * h; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 0); + break; + case TEX_CORNER_ELLIPSE2: + rx = tex->hcorner * w; + ry = tex->vcorner * h; + intens = tiles_ellipserect_func(x, y, w, h, b, rx, ry, 1); + break; + case TEX_CORNER_STRAIGHT: + rx = tex->hcorner * w; + ry = tex->vcorner * h; + intens = tiles_rect_func2(x, y, w, h, b, rx, ry); + break; + default: + intens = tiles_rect_func(x, y, w, h, b); + break; + } + + return intens; +} + +static void tiles_default_col(Tex *tex, float intens, short htileid, short vtileid, float *col) +{ + float intens1 = 1.0 - intens; + col[0] = tex->precalc.r[htileid][vtileid] * intens + tex->colr2 * intens1; + col[1] = tex->precalc.g[htileid][vtileid] * intens + tex->colg2 * intens1; + col[2] = tex->precalc.b[htileid][vtileid] * intens + tex->colb2 * intens1; +} + +static void tiles_neighbour_col(Tex *tex, float *intens, short htileid, short vtileid, short id, short i, float *col) +{ + float intens1 = 1.0 - (*intens); + float s; + short htileidl, htileidr, vtileida, vtileidb; + + /* Compute indices of neighbouring tiles */ + htileidr = (htileid + 1) % tex->hcount; /* Right */ + htileidl = (htileid - 1 + tex->hcount) % tex->hcount; /* Left */ + vtileida = (vtileid + 1) % tex->vcount; /* Above */ + vtileidb = (vtileid - 1 + tex->vcount) % tex->vcount; /* Below */ + + /* Default colour of current tile */ + col[0] = tex->precalc.r[htileid][vtileid]; + col[1] = tex->precalc.g[htileid][vtileid]; + col[2] = tex->precalc.b[htileid][vtileid]; + s = tex->precalc.bpat[htileid][vtileid]; + + /* Add colours of neighbouring tiles and do uniform average */ + switch (id) { + case TILE_BELOW: + col[0] += tex->precalc.r[htileid][vtileidb]; + col[1] += tex->precalc.g[htileid][vtileidb]; + col[2] += tex->precalc.b[htileid][vtileidb]; + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + + s += tex->precalc.bpat[htileid][vtileidb]; + s *= 0.5; + + break; + case TILE_ABOVE: + col[0] += tex->precalc.r[htileid][vtileida]; + col[1] += tex->precalc.g[htileid][vtileida]; + col[2] += tex->precalc.b[htileid][vtileida]; + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + + s += tex->precalc.bpat[htileid][vtileida]; + s *= 0.5; + + break; + case TILE_LEFT: + col[0] += tex->precalc.r[htileidl][vtileid]; + col[1] += tex->precalc.g[htileidl][vtileid]; + col[2] += tex->precalc.b[htileidl][vtileid]; + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + + s += tex->precalc.bpat[htileidl][vtileid]; + s *= 0.5; + + break; + case TILE_RIGHT: + col[0] += tex->precalc.r[htileidr][vtileid]; + col[1] += tex->precalc.g[htileidr][vtileid]; + col[2] += tex->precalc.b[htileidr][vtileid]; + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + + s += tex->precalc.bpat[htileidr][vtileid]; + s *= 0.5; + + break; + case TILE_LEFT_BELOW: + col[0] += tex->precalc.r[htileidl][vtileid] + tex->precalc.r[htileidl][vtileidb] + tex->precalc.r[htileid][vtileidb]; + col[1] += tex->precalc.g[htileidl][vtileid] + tex->precalc.g[htileid][vtileidb] + tex->precalc.g[htileidl][vtileidb]; + col[2] += tex->precalc.b[htileidl][vtileid] + tex->precalc.b[htileidl][vtileidb] + tex->precalc.b[htileid][vtileidb]; + col[0] *= 0.25; + col[1] *= 0.25; + col[2] *= 0.25; + + s += tex->precalc.bpat[htileidl][vtileid] + tex->precalc.bpat[htileidl][vtileidb] + tex->precalc.bpat[htileid][vtileidb]; + s *= 0.25; + + break; + case TILE_LEFT_ABOVE: + col[0] += tex->precalc.r[htileidl][vtileid] + tex->precalc.r[htileidl][vtileida] + tex->precalc.r[htileid][vtileida]; + col[1] += tex->precalc.g[htileidl][vtileid] + tex->precalc.g[htileid][vtileida] + tex->precalc.g[htileidl][vtileida]; + col[2] += tex->precalc.b[htileidl][vtileid] + tex->precalc.b[htileidl][vtileida] + tex->precalc.b[htileid][vtileida]; + col[0] *= 0.25; + col[1] *= 0.25; + col[2] *= 0.25; + + s += tex->precalc.bpat[htileidl][vtileid] + tex->precalc.bpat[htileidl][vtileida] + tex->precalc.bpat[htileid][vtileida]; + s *= 0.25; + + break; + case TILE_RIGHT_BELOW: + col[0] += tex->precalc.r[htileidr][vtileid] + tex->precalc.r[htileidr][vtileidb] + tex->precalc.r[htileid][vtileidb]; + col[1] += tex->precalc.g[htileidr][vtileid] + tex->precalc.g[htileid][vtileidb] + tex->precalc.g[htileidr][vtileidb]; + col[2] += tex->precalc.b[htileidr][vtileid] + tex->precalc.b[htileidr][vtileidb] + tex->precalc.b[htileid][vtileidb]; + col[0] *= 0.25; + col[1] *= 0.25; + col[2] *= 0.25; + + s += tex->precalc.bpat[htileidr][vtileid] + tex->precalc.bpat[htileidr][vtileidb] + tex->precalc.bpat[htileid][vtileidb]; + s *= 0.25; + + break; + case TILE_RIGHT_ABOVE: + col[0] += tex->precalc.r[htileidr][vtileid] + tex->precalc.r[htileidr][vtileida] + tex->precalc.r[htileid][vtileida]; + col[1] += tex->precalc.g[htileidr][vtileid] + tex->precalc.g[htileid][vtileida] + tex->precalc.g[htileidr][vtileida]; + col[2] += tex->precalc.b[htileidr][vtileid] + tex->precalc.b[htileidr][vtileida] + tex->precalc.b[htileid][vtileida]; + col[0] *= 0.25; + col[1] *= 0.25; + col[2] *= 0.25; + + s += tex->precalc.bpat[htileidr][vtileid] + tex->precalc.bpat[htileidr][vtileida] + tex->precalc.bpat[htileid][vtileida]; + s *= 0.25; + + break; + } + *intens *= s; + + /* Additional random scaling */ + if (i >= 0) *intens *= tex->precalc.rpat[i]; + + /* Linearly interpolate the 2 colours */ + col[0] = col[0] * (*intens) + tex->colr2 * intens1; + col[1] = col[1] * (*intens) + tex->colg2 * intens1; + col[2] = col[2] * (*intens) + tex->colb2 * intens1; +} + +static float tiles_bevel_func(Tex *tex, float intens) +{ + float icubic1, icubic2, i; + + /* Apply bevel strength and center the result in [0, 1] */ + intens *= tex->strength; + intens += (1.0 - tex->strength) * 0.5; + + /* Map the intensity x to the 2 functions: x^3, 1+(x-1)^3. */ + icubic1 = intens * intens * intens; + icubic2 = intens - 1.0; + icubic2 *= icubic2 * icubic2; + icubic2 += 1.0; + + if (tex->curve <= 0) { + /* Do a linear blend between 1 + (x - 1)^3 and x functions */ + i = tex->curve + 1; + intens = (1 - i) * icubic2 + i * intens; + } + else { + /* Do a linear blend between x and xi^3 functions */ + i = tex->curve; + intens = (1 - i) * intens + i * icubic1; + } + + /* Apply wave function */ + intens += tex->amp * sin(M_2_PI * intens * tex->freq); + + /* Smooth out the result using a cubic step function */ + if (tex->smooth) { + intens = smoothstep(intens, 0, 1); + } + + return intens; +} + +static float tiles_default_int(Tex *tex, float x, float y, float z, short htileid, short vtileid, float *col) +{ + /* This handles the default tiling with different corner styles */ + float intens; + float w, h, dim; + + /* Compute tile dimensions */ + w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->precalc.hgap; + h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->precalc.vgap; + + /* Offset by half-gap */ + x -= tex->precalc.hgap * 0.5; + y -= tex->precalc.vgap * 0.5; + + /* Bevel */ + dim = tiles_bevel_dim(tex, w, h); + + /* Compute intensity. */ + intens = tiles_recthelper_int(tex, x, y, w, h, dim); + intens *= tex->precalc.bpat[htileid][vtileid]; + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_default_col(tex, intens, htileid, vtileid, col); + + return intens; +} + +static float tiles_interlock1_int(Tex *tex, float x, float y, float z, short htileid, short vtileid, float *col) +{ + /* Generate a pattern as follows: + * _______ + * | | + * |_______| + * | | | + * |___|___| + * The pattern rotates 90 degrees and after 4 tile repitions it repeats. + * If tex->hcount is not a multiple of 4, the repitions will stop before + * multiple of 360 degrees is reached. + */ + + float w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->precalc.hgap; + float h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->precalc.vgap; + float w2 = 0.5 * w; + float h2 = 0.5 * h; + float dim = tiles_bevel_dim(tex, w2, h2); + float intens = 0; + short i = htileid % 4; + short id; + + /* Offset by half-gap */ + x -= tex->precalc.hgap * 0.5; + y -= tex->precalc.vgap * 0.5; + + if (i == 0) { + if (y >= h2) { + intens = tiles_recthelper_int(tex, x, y - h2, w, h2, dim); + id = TILE_ABOVE; + } + else if (x <= w2) { + intens = tiles_recthelper_int(tex, x, y, w2, h2, dim); + id = TILE_LEFT; + } + else { + intens = tiles_recthelper_int(tex, x - w2, y, w2, h2, dim); + id = TILE_RIGHT; + } + } + else if (i == 1) { + if (x >= w2) { + intens = tiles_recthelper_int(tex, x - w2, y, w2, h, dim); + id = TILE_LEFT; + } + else if (y <= h2) { + intens = tiles_recthelper_int(tex, x, y, w2, h2, dim); + id = TILE_RIGHT; + } + else { + intens = tiles_recthelper_int(tex, x, y - h2, w2, h2, dim); + id = TILE_ABOVE; + } + } + else if (i == 2) { + if (y <= h2) { + intens = tiles_recthelper_int(tex, x, y, w, h2, dim); + id = TILE_BELOW; + } + else if (x <= w2) { + intens = tiles_recthelper_int(tex, x, y - h2, w2, h2, dim); + id = TILE_LEFT; + } + else { + intens = tiles_recthelper_int(tex, x - w2, y - h2, w2, h2, dim); + id = TILE_RIGHT; + } + } + else { + if (x <= w2) { + intens = tiles_recthelper_int(tex, x, y, w2, h, dim); + id = TILE_RIGHT; + } + else if (y <= h2) { + intens = tiles_recthelper_int(tex, x - w2, y, w2, h2, dim); + id = TILE_BELOW; + } + else { + intens = tiles_recthelper_int(tex, x - w2, y - h2, w2, h2, dim); + id = TILE_ABOVE; + } + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static float tiles_interlock2_int(Tex *tex, float x, float y, float z, short htileid, short vtileid, short n, float *col) +{ + /* Generate a pattern of n blocks as follows: + * ___ ___ ___ ___ + * | | | | | + * | | | | | .... + * | | | | | + * |___|___|___|___| + * The pattern rotates 90 degrees and after 2 tile repitions it repeats. + * If tex->hcount is not a multiple of 2, the repitions will stop before + * multiple of 180 degrees is reached. + */ + float w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->precalc.hgap; + float h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->precalc.vgap; + float factor = 1.0 / (float)n; + float w2 = factor * w; + float h2 = factor * h; + float dim; + float intens = 0; + short i = htileid % 2; + short id = TILE_CURRENT; + short k; + short r = 0; + + /* Offset by half-gap */ + x -= tex->precalc.hgap * 0.5; + y -= tex->precalc.vgap * 0.5; + + if (i == 0) { + /* I don't understand why the following doesn't work: + * intens = tiles_recthelper_int(tex, x, y - floor(y / h2) * h2, w, h2, dim); + * Hence the looped version. + */ + for (k = 0; k < n; k++) { + if (y <= (k + 1) * h2) { + dim = tiles_bevel_dim(tex, w, h2); + intens = tiles_recthelper_int(tex, x, y - k * h2, w, h2, dim); + r = k; + break; + } + } + } + else { + for (k = 0; k < n; k++) { + if (x <= (k + 1) * w2) { + dim = tiles_bevel_dim(tex, w2, h); + intens = tiles_recthelper_int(tex, x - k * w2, y, w2, h, dim); + r = k; + break; + } + } + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, r % 16, col); + + return intens; +} + +static float tiles_hex_int(Tex *tex, float x, float y, float z, short htileid, short vtileid, float *col) +{ + /* The tight honeycomb pattern is generated using tiles that are not shifted every + * row. So assuming, the rows are not being shifted, we can do a "lollipop" shape + * with a hexagon which will stretch from one rectangular cell to another but will + * remain seamless as long as tex->hgap = tex->vgap = 0. + * _______ + * / \ + * / \_______ + * \ / + * \_______/ + * + * Now note that points that fall above and below the "stick" AND points that fall + * to the left of the hexagon have to be tested inside a hexagon that is in the neighbouring + * tile. A total of 5 hexagon's need to tested for inclusion of given point. + */ + float c = 1.0 / 6.0; + float w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->precalc.hgap; + float h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->precalc.vgap; + float d = w * c; + float r = h * 0.5; + float b = tiles_bevel_dim(tex, 4 * d, h) * tex->bevel; /* Hex part is 4*d wide */ + float wl, wr, dl, dr; + float ha, hb, ra, rb; + short htidl, htidr, vtida, vtidb; + float intens = 0; + float intens2; + short id = TILE_CURRENT; /* Determines how to use color and bump info from neighbouring tiles */ + float vx[6], vy[6]; + + /* Offset by half-gap */ + x -= tex->precalc.hgap * 0.5; + y -= tex->precalc.vgap * 0.5; + + /* Width of tile to right */ + htidr = (htileid + 1) % tex->hcount; + wr = tex->precalc.hpat[htidr + 1] - tex->precalc.hpat[htidr] - tex->precalc.hgap; + dr = wr * c; + /* Width of tile to left */ + htidl = (htileid - 1 + tex->hcount) % tex->hcount; + wl = tex->precalc.hpat[htidl + 1] - tex->precalc.hpat[htidl] - tex->precalc.hgap; + dl = wl * c; + /* Height of tile above */ + vtida = (vtileid + 1) % tex->vcount; + ha = tex->precalc.vpat[vtida + 1] - tex->precalc.vpat[vtida] - tex->precalc.vgap; + ra = ha * 0.5; + /* Height of tile below */ + vtidb = (vtileid - 1 + tex->vcount) % tex->vcount; + hb = tex->precalc.vpat[vtidb + 1] - tex->precalc.vpat[vtidb] - tex->precalc.vgap; + rb = hb * 0.5; + + /* Handle hexagon in current tile */ + vx[0] = d; vy[0] = 0; + vx[1] = 3 * d; vy[1] = 0; + vx[2] = 4 * d; vy[2] = r; + vx[3] = 3 * d; vy[3] = h; + vx[4] = d; vy[4] = h; + vx[5] = 0; vy[5] = r; + intens = tiles_poly_func(x, y, vx, vy, 6, b); + + /* Handle sections that overlap with other tiles. Note that we do a MAX of current + * intens value with the next tile in question. This cleans up the code and seems + * to fix up any artifacts in the bevels. + */ + if ((x >= 3 * d) && (x <= w)) { + /* Take the width of the next tile to the right into consideration */ + if ((y >= 0) && (y <= r)) { + /* Take the height of the next tile below into consideration */ + b = tiles_bevel_dim(tex, 3 * d + dr, r + rb) * tex->bevel; + vx[0] = 4 * d; vy[0] = -rb; + vx[1] = w; vy[1] = -rb; + vx[2] = w + dr; vy[2] = 0; + vx[3] = w; vy[3] = r; + vx[4] = 4 * d; vy[4] = r; + vx[5] = 3 * d; vy[5] = 0; + intens2 = tiles_poly_func(x, y, vx, vy, 6, b); + if (intens2 > intens) { + intens = intens2; + id = TILE_RIGHT_BELOW; + } + } + else if ((y > r) && (y <= h)) { + /* Take the height of the next tile above into consideration */ + b = tiles_bevel_dim(tex, 3 * d + dr, r + ra) * tex->bevel; + vx[0] = 4 * d; vy[0] = r; + vx[1] = w; vy[1] = r; + vx[2] = w + dr; vy[2] = h; + vx[3] = w; vy[3] = h + ra; + vx[4] = 4 * d; vy[4] = h + ra; + vx[5] = 3 * d; vy[5] = h; + intens2 = tiles_poly_func(x, y, vx, vy, 6, b); + if (intens2 > intens) { + intens = intens2; + id = TILE_RIGHT_ABOVE; + } + } + } + else if ((x >= 0) && (x <= d)) { + /* Take the width of the next tile to the left into consideration */ + if ((y >= 0) && (y <= r)) { + /* Take the height of the next tile below into consideration */ + b = tiles_bevel_dim(tex, 3 * dl + d, r + rb) * tex->bevel; + vx[0] = d; vy[0] = 0; + vx[1] = 0; vy[1] = r; + vx[2] = -2 * dl; vy[2] = r; + vx[3] = -3 * dl; vy[3] = 0; + vx[4] = -2 * dl; vy[4] = -rb; + vx[5] = 0; vy[5] = -rb; + intens2 = tiles_poly_func(x, y, vx, vy, 6, b); + if (intens2 > intens) { + intens = intens2; + id = TILE_LEFT_BELOW; + } + } + else if ((y > r) && (y <= h)) { + /* Take the height of the next tile above into consideration */ + b = tiles_bevel_dim(tex, 3 * dl + d, r + ra) * tex->bevel; + vx[0] = d; vy[0] = h; + vx[1] = 0; vy[1] = h + ra; + vx[2] = -2 * dl; vy[2] = h + ra; + vx[3] = -3 * dl; vy[3] = h; + vx[4] = -2 * dl; vy[4] = r; + vx[5] = 0; vy[5] = r; + intens2 = tiles_poly_func(x, y, vx, vy, 6, b); + if (intens2 > intens) { + intens = intens2; + id = TILE_LEFT_ABOVE; + } + } + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static float tiles_herringbone_int(Tex *tex, float x, float y, float z, short htileid, short vtileid, short n, float *col) +{ + /* Creates a nx1 seamless pattern for herringbone tiling where n >= 2. */ + + float w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->precalc.hgap; + float h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->precalc.vgap; + float w1 = 0.5 * w; + float h1 = 0.5 * h; + float half_over_n = 0.5 / (float)n; + float xstep = w * half_over_n; + float ystep = h * half_over_n; + float dim; + short loop = 1; + float xi, yi; + float intens = 0; + short i = -1; /* Used to determine sections that cross seams */ + short id = TILE_CURRENT; + + /* Offset by half-gap */ + x -= tex->precalc.hgap * 0.5; + y -= tex->precalc.vgap * 0.5; + + while (loop) { + if ((x < 0) || (x > w) || (y < 0) || (y > h)) break; + + /* Handle horizontal bars */ + yi = 0; + i = 0; + dim = tiles_bevel_dim(tex, w1, ystep); + if (tex->bevoption != TEX_BEVEL_DEFAULTMIN) dim *= half_over_n; + for (xi = 0; xi < w + xstep; xi += xstep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, w1, ystep, dim); + if (intens > 0) { + if (i > n) id = TILE_RIGHT; + i = i % 16; + break; + } + yi += ystep; + i++; + } + if (intens > 0) break; + + /* Handle the seamless sections of horizontal bars */ + yi = h - (n - 1) * ystep; + i = n + 1; + dim = tiles_bevel_dim(tex, w1, ystep); + if (tex->bevoption != TEX_BEVEL_DEFAULTMIN) dim *= half_over_n; + for (xi = (1 - n) * xstep; xi < 0; xi += xstep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, w1, ystep, dim); + if (intens > 0) { + id = TILE_LEFT; + i = i % 16; + break; + } + yi += ystep; + i++; + } + if (intens > 0) break; + + /* Handle vertical bars */ + xi = 0; + i = 0; + dim = tiles_bevel_dim(tex, xstep, h1); + if (tex->bevoption != TEX_BEVEL_DEFAULTMIN) dim *= half_over_n; + for (yi = ystep; yi < h + ystep; yi += ystep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, xstep, h1, dim); + if (intens > 0) { + if (i >= n) id = TILE_ABOVE; + i = 15 - i % 16; + break; + } + xi += xstep; + i++; + } + if (intens > 0) break; + + /* Handle the seamless sections of vertical bars */ + xi = w1; + i = n; + dim = tiles_bevel_dim(tex, xstep, h1); + if (tex->bevoption != TEX_BEVEL_DEFAULTMIN) dim *= half_over_n; + for (yi = (1 - n) * ystep; yi < ystep; yi += ystep) + { + intens = tiles_recthelper_int(tex, x - xi, y - yi, xstep, h1, dim); + if (intens > 0) { + if (i < 2*n-1) id = TILE_BELOW; + i = 15 - i % 16; + break; + } + xi += xstep; + i++; + } + if (intens > 0) break; + + /* Important: End loop */ + loop = 0; + i = -1; + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, i, col); + + return intens; +} + +static float tiles_weave_int(Tex *tex, float x, float y, float z, short htileid, short vtileid, float *col) +{ + float w = tex->precalc.hpat[htileid + 1] - tex->precalc.hpat[htileid] - tex->precalc.hgap; + float h = tex->precalc.vpat[vtileid + 1] - tex->precalc.vpat[vtileid] - tex->precalc.vgap; + float dim; + float intens = 0; + short htidl, htidr, vtida, vtidb; + float wr, wl, ha, hb; + float xi, yi, wi, hi; + short loop = 1; + short id = TILE_CURRENT; + + /* Width of tile to right */ + htidr = (htileid + 1) % tex->hcount; + wr = tex->precalc.hpat[htidr + 1] - tex->precalc.hpat[htidr] - tex->precalc.hgap; + /* Width of tile to left */ + htidl = (htileid - 1 + tex->hcount) % tex->hcount; + wl = tex->precalc.hpat[htidl + 1] - tex->precalc.hpat[htidl] - tex->precalc.hgap; + /* Height of tile above */ + vtida = (vtileid + 1) % tex->vcount; + ha = tex->precalc.vpat[vtida + 1] - tex->precalc.vpat[vtida] - tex->precalc.vgap; + /* Height of tile below */ + vtidb = (vtileid - 1 + tex->vcount) % tex->vcount; + hb = tex->precalc.vpat[vtidb + 1] - tex->precalc.vpat[vtidb] - tex->precalc.vgap; + + /* Offset by half-gap */ + x -= tex->precalc.hgap * 0.5; + y -= tex->precalc.vgap * 0.5; + + while (loop) { + if ((x < 0) || (x > w) || (y < 0) || (y > h)) break; + + /* Compute dimension for bevel */ + dim = tiles_bevel_dim(tex, MIN3(w, wl, wr), MIN3(h, ha, hb)) * 0.25; + + /* Horizontal Tiles */ + /* Bottom Center */ + xi = 0.125 * w; + yi = -0.125 * hb; + wi = 0.75 * w; + hi = 0.125 * (h + hb); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) { + id = TILE_BELOW; + break; + } + + /* Top Center */ + xi = 0.125 * w; + yi = 0.875 * h; + hi = 0.125 * (h + ha); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) { + id = TILE_ABOVE; + break; + } + + /* Middle Left */ + xi = -0.375 * wl; + yi = 0.375 * h; + wi = 0.375 * (w + wl); + hi = 0.25 * h; + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) { + id = TILE_LEFT; + break; + } + + /* Middle Right */ + xi = 0.625 * w; + yi = 0.375 * h; + wi = 0.375 * (w + wr); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) { + id = TILE_RIGHT; + break; + } + + + /* Vertical Tiles */ + /* Center */ + xi = 0.375 * w; + yi = 0.125 * h; + wi = 0.25 * w; + hi = 0.75 * h; + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) { + id = TILE_CURRENT; + break; + } + + /* Bottom Left */ + xi = -0.125 * wl; + yi = -0.375 * hb; + wi = 0.125 * (w + wl); + hi = 0.375 * (h + hb); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) { + id = TILE_LEFT_BELOW; + break; + } + + /* Bottom Right */ + xi = 0.875 * w; + yi = -0.375 * hb; + wi = 0.125 * (w + wr); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) { + id = TILE_RIGHT_BELOW; + break; + } + + /* Top Left */ + xi = -0.125 * wl; + yi = 0.625 * h; + wi = 0.125 * (w + wl); + hi = 0.375 * (h + ha); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) { + id = TILE_LEFT_ABOVE; + break; + } + + /* Top Right */ + xi = 0.875 * w; + yi = 0.625 * h; + wi = 0.125 * (w + wr); + intens = tiles_recthelper_int(tex, x - xi, y - yi, wi, hi, dim); + if (intens > 0) { + id = TILE_RIGHT_ABOVE; + break; + } + + loop = 0; + } + + /* Bevel function */ + intens = tiles_bevel_func(tex, intens); + + /* Compute colour */ + tiles_neighbour_col(tex, &intens, htileid, vtileid, id, -1, col); + + return intens; +} + +static void tiles_transform(Tex *tex, float *x, float *y, float *z) +{ + float angle, sinval, cosval, x1, y1, scale; + + /* Move origin to (0.5, 0.5) */ + *x -= 0.5; + *y -= 0.5; + + /* Apply texture coordinates rotation. */ + angle = tex->rotate * M_PI_OVER_180; + sinval = sin(angle); + cosval = cos(angle); + x1 = (*x) * cosval - (*y) * sinval; + y1 = (*y) * cosval + (*x) * sinval; + + /* Apply texture coordinates offset */ + x1 += tex->hoffset; + y1 += tex->voffset; + + /* Apply texture coordinates skew */ + *x = x1 + y1 * tex->hskew; + *y = y1 + x1 * tex->vskew; + + /* Apply texture coordinate scale */ + scale = 1.0 / tex->scale; + *x *= scale; + *y *= scale; + *z *= scale; + + /* Move origin back to (0, 0) */ + *x += 0.5; + *y += 0.5; +} + +static void tiles_calc(Tex *tex, float *x, float *y, float *z, short *htileid, short *vtileid) +{ + /* Given points (x, y, z) determines where in the tile pattern, tex->precalc.hpat[], + * the point belongs. It returns the index of the tile in htileid, vtileid and x, y, z + * will contain the relative offset for the tile. + * NOTE: currently z is ignored as this is a 2D texture. + */ + float wtot = tex->precalc.hpat[tex->hcount] - tex->precalc.hpat[0]; /* Width of tile pattern */ + float htot = tex->precalc.vpat[tex->vcount] - tex->precalc.vpat[0]; /* Height of tile pattern */ + float y1; + short i; + int row; + + /* Center the pattern */ + *x += (wtot * 0.5); + *y += (htot * 0.5); + + y1 = *y; + + /* Compute relative y offset for current tile */ + *y = mod(*y, htot); + + /* Determine vertical start of the tile */ + for (i = 0; i < tex->vcount; i++) { + if (*y <= tex->precalc.vpat[i + 1]) { + break; + } + } + *y -= tex->precalc.vpat[i]; + *vtileid = i; + + /* Calculate row number */ + row = (int)floor(y1 / htot) * tex->vcount + i; + + /* Shift rows */ + if ( tex->alternate > 0 ) { + *x += (mod(row, tex->alternate) * tex->shift); + } + else { + /* Shift every row */ + *x += (row * tex->shift); + } + + /* Compute relative x offset for current tile */ + *x = mod(*x, wtot); + + /* Determine horizontal start of the tile */ + for (i = 0; i < tex->hcount; i++) { + if (*x <= tex->precalc.hpat[i + 1]) { + break; + } + } + *x -= tex->precalc.hpat[i]; + *htileid = i; +} +static float tiles_int(Tex *tex, float x, float y, float z, float *col) +{ + short htileid, vtileid; + float intens; + + /* Compute coordinates in "tile-space"; i.e. relative to the tile containing + * the texture coordinates. + */ + tiles_transform(tex, &x, &y, &z); + tiles_calc(tex, &x, &y, &z, &htileid, &vtileid); + + /* Handle preset patterns and default tiling function */ + switch (tex->preset) { + case TEX_TILES_INTERLOCK1: + intens = tiles_interlock1_int(tex, x, y, z, htileid, vtileid, col); + break; + case TEX_TILES_INTERLOCK2: + intens = tiles_interlock2_int(tex, x, y, z, htileid, vtileid, 2, col); + break; + case TEX_TILES_INTERLOCK3: + intens = tiles_interlock2_int(tex, x, y, z, htileid, vtileid, 4, col); + break; + case TEX_TILES_HEX: + intens = tiles_hex_int(tex, x, y, z, htileid, vtileid, col); + break; + case TEX_TILES_HERRINGBONE1: + intens = tiles_herringbone_int(tex, x, y, z, htileid, vtileid, 2, col); + break; + case TEX_TILES_HERRINGBONE2: + intens = tiles_herringbone_int(tex, x, y, z, htileid, vtileid, 4, col); + break; + case TEX_TILES_HERRINGBONE3: + intens = tiles_herringbone_int(tex, x, y, z, htileid, vtileid, 5, col); + break; + case TEX_TILES_WEAVE: + intens = tiles_weave_int(tex, x, y, z, htileid, vtileid, col); + break; + default: + intens = tiles_default_int(tex, x, y, z, htileid, vtileid, col); + break; + } + + /* Clamp to [0, 1] range. The clamping prevents artifacts around the border + * in case negative numbers are generated by the tile functions. + */ + CLAMP(intens, 0, 1); + CLAMP(col[0], 0, 1); + CLAMP(col[1], 0, 1); + CLAMP(col[2], 0, 1); + + return intens; +} + +static int tiles(Tex *tex, float *texvec, TexResult *texres) +{ + int rv = TEX_INT; + float col[3]; + + texres->tin = tiles_int(tex, texvec[0], texvec[1], texvec[2], col); + + texres->tr = col[0]; + texres->tg = col[1]; + texres->tb = col[2]; + texres->ta = 1.0; + rv |= TEX_RGB; + + if (texres->nor!=NULL) { + /* calculate bumpnormal */ + texres->nor[0] = tiles_int(tex, texvec[0] + tex->nabla, texvec[1], texvec[2], col); + texres->nor[1] = tiles_int(tex, texvec[0], texvec[1] + tex->nabla, texvec[2], col); + texres->nor[2] = tiles_int(tex, texvec[0], texvec[1], texvec[2] + tex->nabla, col); + + tex_normal_derivate(tex, texres); + rv |= TEX_NOR; + } + + BRICONTRGB; + + BRICONT; + + return rv; +} + +/* ------------------------------------------------------------------------- */ + static int texnoise(Tex *tex, TexResult *texres) { float div=3.0; @@ -1186,6 +2719,9 @@ retval= mg_distNoiseTex(tex, tmpvec, texres); break; + case TEX_TILES: + retval = tiles(tex, texvec, texres); + break; } if (tex->flag & TEX_COLORBAND) { @@ -1202,7 +2738,7 @@ return retval; } -int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres) +int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres, ShadeInput *shi) { if(tex==NULL) { @@ -1211,11 +2747,12 @@ } /* Image requires 2d mapping conversion */ - if(tex->type==TEX_IMAGE) { + if(tex->type==TEX_IMAGE || tex->type==TEX_TILES) { MTex mtex; float texvec_l[3], dxt_l[3], dyt_l[3]; mtex.mapping= MTEX_FLAT; + if(shi) mtex.mapping= shi->wrap; mtex.tex= tex; mtex.object= NULL; mtex.texco= TEXCO_ORCO; @@ -1499,7 +3036,7 @@ co= tempvec; } - if(tex->type==TEX_IMAGE) { + if(tex->type==TEX_IMAGE || tex->type==TEX_TILES) { /* new: first swap coords, then map, then trans/scale */ @@ -1952,7 +3489,7 @@ } - if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, dxt, dyt); + if(mtex->tex->type==TEX_IMAGE || mtex->tex->type==TEX_TILES) do_2d_mapping(mtex, texvec, NULL, dxt, dyt); rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres); @@ -2123,7 +3660,7 @@ else texvec[2]= mtex->size[2]*(mtex->ofs[2]); /* texture */ - if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, dxt, dyt); + if(mtex->tex->type==TEX_IMAGE || mtex->tex->type==TEX_TILES) do_2d_mapping(mtex, texvec, NULL, dxt, dyt); rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres); @@ -2302,7 +3839,7 @@ } /* texture */ - if(tex->type==TEX_IMAGE) { + if(tex->type==TEX_IMAGE || tex->type==TEX_TILES) { do_2d_mapping(mtex, texvec, NULL, dxt, dyt); } @@ -2387,7 +3924,7 @@ else texvec[2]= mtex->size[2]*(mtex->ofs[2]); /* texture */ - if(tex->type==TEX_IMAGE) { + if(tex->type==TEX_IMAGE || tex->type==TEX_TILES) { do_2d_mapping(mtex, texvec, NULL, dxt, dyt); } Index: source/blender/render/intern/source/shadeinput.c =================================================================== --- source/blender/render/intern/source/shadeinput.c (revision 12209) +++ source/blender/render/intern/source/shadeinput.c (working copy) @@ -1001,7 +1001,7 @@ shade_samples_do_AO(ssamp); /* if shade (all shadepinputs have same passflag) */ - if(ssamp->shi[0].passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB)) { + if(ssamp->shi[0].passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB|SCE_PASS_INDEXMAT)) { for(samp=0; samptot; samp++, shi++, shr++) { shade_input_set_shade_texco(shi); Index: source/blender/render/intern/source/pipeline.c =================================================================== --- source/blender/render/intern/source/pipeline.c (revision 12209) +++ source/blender/render/intern/source/pipeline.c (working copy) @@ -330,6 +330,10 @@ if(channel==-1) return "IndexOB"; return "IndexOB.X"; } + if(passtype == SCE_PASS_INDEXMAT) { + if(channel==-1) return "IndexMat"; + return "IndexMat.X"; + } return "Unknown"; } @@ -378,6 +382,9 @@ if(strcmp(str, "IndexOB")==0) return SCE_PASS_INDEXOB; + if(strcmp(str, "IndexMat")==0) + return SCE_PASS_INDEXMAT; + return 0; } @@ -542,6 +549,8 @@ render_layer_add_pass(rr, rl, 3, SCE_PASS_RADIO); if(srl->passflag & SCE_PASS_INDEXOB) render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB); + if(srl->passflag & SCE_PASS_INDEXMAT) + render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMAT); } /* sss, previewrender and envmap don't do layers, so we make a default one */ Index: source/blender/render/intern/source/zbuf.c =================================================================== --- source/blender/render/intern/source/zbuf.c (revision 12209) +++ source/blender/render/intern/source/zbuf.c (working copy) @@ -2875,6 +2875,22 @@ } } +static void add_transp_matindex(RenderLayer *rl, int offset, int facenr) +{ + VlakRen *vlr= RE_findOrAddVlak(&R, (facenr-1) & RE_QUAD_MASK); + if(vlr && vlr->mat) { + RenderPass *rpass; + + for(rpass= rl->passes.first; rpass; rpass= rpass->next) { + if(rpass->passtype == SCE_PASS_INDEXMAT) { + float *fp= rpass->rect + offset; + *fp= (float)vlr->mat->index; + break; + } + } + } +} + /* ONLY OSA! merge all shaderesult samples to one */ /* target should have been cleared */ static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) @@ -3090,7 +3106,7 @@ shade_samples_do_AO(ssamp); /* if shade (all shadepinputs have same passflag) */ - if(shi->passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB)) { + if(shi->passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB|SCE_PASS_INDEXMAT)) { for(samp=0; samptot; samp++, shi++, shr++) { shade_input_set_shade_texco(shi); shade_input_do_shade(shi, shr); @@ -3319,7 +3335,9 @@ if(addpassflag & SCE_PASS_INDEXOB) add_transp_obindex(rl, od, zrow[totface-1][1]); - + if(addpassflag & SCE_PASS_INDEXMAT) + add_transp_matindex(rl, od, zrow[totface-1][1]); + if(R.osa==0) { while(totface>0) { totface--; Index: source/blender/render/intern/source/rendercore.c =================================================================== --- source/blender/render/intern/source/rendercore.c (revision 12209) +++ source/blender/render/intern/source/rendercore.c (working copy) @@ -400,6 +400,14 @@ *fp= (float)shi->vlr->ob->index; } break; + case SCE_PASS_INDEXMAT: + /* no filter */ + if(shi->vlr) { + fp= rpass->rect + offset; + if(*fp==0.0f) + *fp= (float)shi->vlr->mat->index; + } + break; case SCE_PASS_VECTOR: { /* add minimum speed in pixel, no filter */ @@ -478,6 +486,12 @@ *fp= (float)shi->vlr->ob->index; } break; + case SCE_PASS_INDEXMAT: + if(shi->vlr) { + fp= rpass->rect + offset; + *fp= (float)shi->vlr->mat->index; + } + break; } if(col) { fp= rpass->rect + pixsize*offset; Index: source/blender/render/intern/include/texture.h =================================================================== --- source/blender/render/intern/include/texture.h (revision 12209) +++ source/blender/render/intern/include/texture.h (working copy) @@ -49,6 +49,7 @@ struct HaloRen; struct ShadeInput; struct TexResult; +struct TexPreCalc; struct Tex; struct Image; struct ImBuf; Index: source/blender/render/extern/include/RE_shader_ext.h =================================================================== --- source/blender/render/extern/include/RE_shader_ext.h (revision 12209) +++ source/blender/render/extern/include/RE_shader_ext.h (working copy) @@ -132,6 +132,9 @@ ShadeInputCol col[8]; /* 8 = MAX_MCOL */ int totuv, totcol; + /* texture mapping type */ + int wrap, pad; + /* dx/dy OSA coordinates */ float dxco[3], dyco[3]; float dxlo[3], dylo[3], dxgl[3], dygl[3]; @@ -168,7 +171,7 @@ /* node shaders... */ struct Tex; -int multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres); +int multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres, ShadeInput *shi); /* shaded view and bake */ struct Render; Index: source/blender/python/api2_2x/windowTheme.c =================================================================== --- source/blender/python/api2_2x/windowTheme.c (revision 12209) +++ source/blender/python/api2_2x/windowTheme.c (working copy) @@ -195,6 +195,7 @@ ELSEIF_TSP_RGBA( plugin ) ELSEIF_TSP_RGBA( transition ) ELSEIF_TSP_RGBA( meta ) + ELSEIF_TSP_RGBA( layer_color_ne ) else if( !strcmp( name, "vertex_size" ) ) attrib = Py_BuildValue( "i", tsp->vertex_size ); else if( !strcmp( name, "facedot_size" ) ) @@ -274,6 +275,7 @@ ELSEIF_TSP_RGBA( plugin ) ELSEIF_TSP_RGBA( transition ) ELSEIF_TSP_RGBA( meta ) + ELSEIF_TSP_RGBA( layer_color_ne ) else if( !strcmp( name, "vertex_size" ) ) { int val; Index: source/blender/python/api2_2x/Material.c =================================================================== --- source/blender/python/api2_2x/Material.c (revision 12209) +++ source/blender/python/api2_2x/Material.c (working copy) @@ -123,6 +123,8 @@ #define EXPP_MAT_NRINGS_MIN 0 #define EXPP_MAT_NRINGS_MAX 24 +#define EXPP_MAT_PASSINDEX_MIN 0 +#define EXPP_MAT_PASSINDEX_MAX 1000 #define EXPP_MAT_RAYMIRR_MIN 0.0 #define EXPP_MAT_RAYMIRR_MAX 1.0 #define EXPP_MAT_MIRRDEPTH_MIN 0 @@ -454,6 +456,7 @@ static PyObject *Matr_oldsetNLines( BPy_Material * self, PyObject * args ); static PyObject *Matr_oldsetNRings( BPy_Material * self, PyObject * args ); static PyObject *Matr_oldsetNStars( BPy_Material * self, PyObject * args ); +static PyObject *Matr_oldsetPassIndex( BPy_Material * self, PyObject * args ); static PyObject *Matr_oldsetRayMirr( BPy_Material * self, PyObject * args ); static PyObject *Matr_oldsetMirrDepth( BPy_Material * self, PyObject * args ); static PyObject *Matr_oldsetRef( BPy_Material * self, PyObject * args ); @@ -509,6 +512,7 @@ static int Material_setNStars( BPy_Material * self, PyObject * value ); static int Material_setNLines( BPy_Material * self, PyObject * value ); static int Material_setNRings( BPy_Material * self, PyObject * value ); +static int Material_setPassIndex( BPy_Material * self, PyObject * value ); static int Material_setRayMirr( BPy_Material * self, PyObject * value ); static int Material_setMirrDepth( BPy_Material * self, PyObject * value ); static int Material_setFresnelMirr( BPy_Material * self, PyObject * value ); @@ -581,6 +585,7 @@ static PyObject *Material_getNStars( BPy_Material * self ); static PyObject *Material_getNLines( BPy_Material * self ); static PyObject *Material_getNRings( BPy_Material * self ); +static PyObject *Material_getPassIndex( BPy_Material * self ); /* Shader settings */ static PyObject *Material_getSpecShader( BPy_Material * self ); static PyObject *Material_getDiffuseShader( BPy_Material * self ); @@ -713,6 +718,8 @@ "() - Return Material's number of lines in halo"}, {"getNRings", ( PyCFunction ) Material_getNRings, METH_NOARGS, "() - Return Material's number of rings in halo"}, + {"getPassIndex", ( PyCFunction ) Material_getPassIndex, METH_NOARGS, + "() - Return pass index"}, {"getRayMirr", ( PyCFunction ) Material_getRayMirr, METH_NOARGS, "() - Return mount mirror"}, {"getMirrDepth", ( PyCFunction ) Material_getMirrDepth, METH_NOARGS, @@ -818,6 +825,8 @@ "(i) - Set Material's number of lines in halo - [0, 250]"}, {"setNRings", ( PyCFunction ) Matr_oldsetNRings, METH_VARARGS, "(i) - Set Material's number of rings in halo - [0, 24]"}, + {"setPassIndex", ( PyCFunction ) Matr_oldsetPassIndex, METH_VARARGS, + "() - Set pass index - [0, 1000]"}, {"setRayMirr", ( PyCFunction ) Matr_oldsetRayMirr, METH_VARARGS, "(f) - Set amount mirror - [0.0, 1.0]"}, {"setMirrDepth", ( PyCFunction ) Matr_oldsetMirrDepth, METH_VARARGS, @@ -1015,6 +1024,10 @@ (getter)Material_getNStars, (setter)Material_setNStars, "Number of star points with halo", NULL}, + {"passIndex", + (getter)Material_getPassIndex, (setter)Material_setPassIndex, + "Index # for the IndexMat render pass.", + NULL}, {"rayMirr", (getter)Material_getRayMirr, (setter)Material_setRayMirr, "Mirror reflection amount for raytrace", @@ -1529,6 +1542,11 @@ return PyInt_FromLong( ( long ) self->material->ringc ); } +static PyObject *Material_getPassIndex( BPy_Material * self ) +{ + return PyInt_FromLong( ( long ) self->material->index ); +} + static PyObject *Material_getRayMirr( BPy_Material * self ) { return PyFloat_FromDouble( ( double ) self->material->ray_mirror ); @@ -2003,6 +2021,13 @@ EXPP_MAT_NRINGS_MAX, 'h' ); } +static int Material_setPassIndex( BPy_Material * self, PyObject * value ) +{ + return EXPP_setIValueClamped ( value, &self->material->index, + EXPP_MAT_PASSINDEX_MIN, + EXPP_MAT_PASSINDEX_MAX, 'h' ); +} + static int Material_setRayMirr( BPy_Material * self, PyObject * value ) { return EXPP_setFloatClamped ( value, &self->material->ray_mirror, @@ -2815,6 +2840,11 @@ return EXPP_setterWrapper( (void *)self, args, (setter)Material_setNStars ); } +static PyObject *Matr_oldsetPassIndex( BPy_Material * self, PyObject * args ) +{ + return EXPP_setterWrapper( (void *)self, args, (setter)Material_setPassIndex ); +} + static PyObject *Matr_oldsetRayMirr( BPy_Material * self, PyObject * args ) { return EXPP_setterWrapper( (void *)self, args, (setter)Material_setRayMirr ); Index: source/blender/python/api2_2x/Texture.c =================================================================== --- source/blender/python/api2_2x/Texture.c (revision 12209) +++ source/blender/python/api2_2x/Texture.c (working copy) @@ -2483,7 +2483,7 @@ "expects a 3D vector object"); /* rgbnor = .. we don't need this now */ - multitex_ext(self->texture, vec_in->vec, NULL, NULL, 1, &texres); + multitex_ext(self->texture, vec_in->vec, NULL, NULL, 1, &texres, NULL); vec[0] = texres.tr; vec[1] = texres.tg; Index: source/blender/python/api2_2x/Ipocurve.c =================================================================== --- source/blender/python/api2_2x/Ipocurve.c (revision 12209) +++ source/blender/python/api2_2x/Ipocurve.c (working copy) @@ -89,10 +89,12 @@ static PyObject *IpoCurve_getDriverChannel( C_IpoCurve * self); static int IpoCurve_setDriverChannel( C_IpoCurve * self, PyObject * args ); static PyObject *IpoCurve_getDriverExpression( C_IpoCurve * self); +static PyObject *IpoCurve_getDriverFactor( C_IpoCurve * self); static PyObject *IpoCurve_getFlag( C_IpoCurve * self, void *type); static int IpoCurve_setFlag( C_IpoCurve * self, PyObject *value, void *type); static int IpoCurve_setDriverExpression( C_IpoCurve * self, PyObject * args ); +static int IpoCurve_setDriverFactor( C_IpoCurve * self, PyObject * args ); static PyObject *IpoCurve_getCurval( C_IpoCurve * self, PyObject * args ); static int IpoCurve_setCurval( C_IpoCurve * self, PyObject * key, PyObject * value ); @@ -160,6 +162,10 @@ (getter)IpoCurve_getDriverExpression, (setter)IpoCurve_setDriverExpression, "The python expression on the driver used to drive the IpoCurve", NULL}, + {"factor", + (getter)IpoCurve_getDriverFactor, (setter)IpoCurve_setDriverFactor, + "The factor on the driver object used to scale the driver of the IpoCurve", + NULL}, {"interpolation", (getter)IpoCurve_newgetInterp, (setter)IpoCurve_newsetInterp, "The interpolation mode of the curve", @@ -930,6 +936,36 @@ return 0; } +static PyObject *IpoCurve_getDriverFactor( C_IpoCurve * self ) +{ + IpoCurve *ipo = self->ipocurve; + + if( ipo->driver && ipo->driver->fac) + return PyFloat_FromDouble( ( double ) ipo->driver->fac ); + + Py_RETURN_NONE; +} + +static int IpoCurve_setDriverFactor( C_IpoCurve * self, PyObject * arg ) +{ + IpoCurve *ipo = self->ipocurve; + float value = PyFloat_AsDouble( arg ); + + if( !ipo->driver ) + return EXPP_ReturnIntError( PyExc_RuntimeError, + "This IpoCurve does not have an active driver" ); + + if( !PyNumber_Check( arg ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected float argument" ); + + ipo->driver->fac = EXPP_ClampFloat( value, -1000.0, 1000.0); + + DAG_scene_sort(G.scene); + + return 0; +} + static PyObject *M_IpoCurve_ExtendDict( void ) { PyObject *EM = PyConstant_New( ); Index: source/blender/blenkernel/BKE_blender.h =================================================================== --- source/blender/blenkernel/BKE_blender.h (revision 12209) +++ source/blender/blenkernel/BKE_blender.h (working copy) @@ -44,7 +44,7 @@ struct MemFile; #define BLENDER_VERSION 245 -#define BLENDER_SUBVERSION 3 +#define BLENDER_SUBVERSION 4 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 Index: source/blender/blenkernel/BKE_node.h =================================================================== --- source/blender/blenkernel/BKE_node.h (revision 12209) +++ source/blender/blenkernel/BKE_node.h (working copy) @@ -143,11 +143,13 @@ void nodeAddToPreview(struct bNode *, float *, int, int); +void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node); struct bNode *nodeAddNodeType(struct bNodeTree *ntree, int type, struct bNodeTree *ngroup); void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node); struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node); struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock); +struct bNodeLink *nodeAddLink2(struct bNodeTree *ntree, struct bNodeSocket *fromsock, struct bNodeSocket *tosock); void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link); struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to); @@ -209,6 +211,9 @@ #define SH_NODE_SEPRGB 120 #define SH_NODE_COMBRGB 121 #define SH_NODE_HUE_SAT 122 +#define SH_NODE_BRIGHTCONTRAST 123 +#define SH_NODE_GAMMA 124 +#define SH_NODE_BOOLEAN 125 /* custom defines options for Material node */ @@ -248,6 +253,7 @@ #define RRES_OUT_REFRACT 12 #define RRES_OUT_RADIO 13 #define RRES_OUT_INDEXOB 14 +#define RRES_OUT_INDEXMAT 15 /* note: types are needed to restore callbacks, don't change values */ #define CMP_NODE_VIEWER 201 @@ -302,6 +308,9 @@ #define CMP_NODE_GAMMA 250 #define CMP_NODE_INVERT 251 #define CMP_NODE_NORMALIZE 252 +#define CMP_NODE_CROP 253 +#define CMP_NODE_BOOLEAN 254 +#define CMP_NODE_BILATERALBLUR 255 /* channel toggles */ #define CMP_CHAN_RGB 1 Index: source/blender/blenkernel/bad_level_call_stubs/stubs.c =================================================================== --- source/blender/blenkernel/bad_level_call_stubs/stubs.c (revision 12209) +++ source/blender/blenkernel/bad_level_call_stubs/stubs.c (working copy) @@ -265,7 +265,7 @@ /* node_composite.c */ void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect) {} -int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres) +int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres, ShadeInput *shi) { return 1969; } Index: source/blender/blenkernel/intern/texture.c =================================================================== --- source/blender/blenkernel/intern/texture.c (revision 12209) +++ source/blender/blenkernel/intern/texture.c (working copy) @@ -213,6 +213,7 @@ texmap->size[0]= texmap->size[1]= texmap->size[2]= 1.0f; texmap->max[0]= texmap->max[1]= texmap->max[2]= 1.0f; + texmap->wrap= MTEX_FLAT; Mat4One(texmap->mat); return texmap; @@ -441,6 +442,44 @@ tex->vn_mexp = 2.5; tex->vn_distm = 0; tex->vn_coltype = 0; + /* tiles */ + tex->scale = 1; + tex->hcount = 3; + tex->minwidth = 0.2; + tex->maxwidth = 0.3; + tex->vcount = 3; + tex->minheight = 0.1; + tex->maxheight = 0.2; + tex->hgap = 0.05; + tex->vgap = 0.05; + tex->shift = 0.1; + tex->bevel = 0.2; + tex->corner = 0; + tex->hcorner = 0.25; + tex->vcorner = 0.25; + tex->rotate = 0; + tex->seed = 0; + tex->alternate = 2; + tex->hskew = 0; + tex->vskew = 0; + tex->curve = 0; + tex->smooth = 0; + tex->freq = 0; + tex->amp = 0; + tex->hoffset = 0; + tex->voffset = 0; + tex->strength = 1; + tex->preset = 0; + tex->bevoption = 0; + tex->colr1 = 1; + tex->colg1 = 1; + tex->colb1 = 1; + tex->colr2 = 0; + tex->colg2 = 0; + tex->colb2 = 0; + tex->minbump = 0; + tex->maxbump = 1; + tiles_precalc(tex); if (tex->env) { tex->env->stype=ENV_STATIC; Index: source/blender/blenkernel/intern/object.c =================================================================== --- source/blender/blenkernel/intern/object.c (revision 12209) +++ source/blender/blenkernel/intern/object.c (working copy) @@ -889,13 +889,15 @@ VECCOPY(ob->loc, G.scene->cursor); } - v3d->viewquat[0]= -v3d->viewquat[0]; - if (ob->transflag & OB_QUAT) { - QUATCOPY(ob->quat, v3d->viewquat); - } else { - QuatToEul(v3d->viewquat, ob->rot); + if (U.flag & USER_ADDOB_ALIGN_EDIT) { + v3d->viewquat[0]= -v3d->viewquat[0]; + if (ob->transflag & OB_QUAT) { + QUATCOPY(ob->quat, v3d->viewquat); + } else { + QuatToEul(v3d->viewquat, ob->rot); + } + v3d->viewquat[0]= -v3d->viewquat[0]; } - v3d->viewquat[0]= -v3d->viewquat[0]; } SoftBody *copy_softbody(SoftBody *sb) Index: source/blender/blenkernel/intern/brush.c =================================================================== --- source/blender/blenkernel/intern/brush.c (revision 12209) +++ source/blender/blenkernel/intern/brush.c (working copy) @@ -62,9 +62,9 @@ brush= alloc_libblock(&G.main->brush, ID_BR, name); - brush->rgb[0]= 1.0f; - brush->rgb[1]= 1.0f; - brush->rgb[2]= 1.0f; + brush->rgb[0]= 0.0f; + brush->rgb[1]= 0.0f; + brush->rgb[2]= 0.0f; brush->alpha= 0.2f; brush->size= 25; brush->spacing= 10.0f; Index: source/blender/blenkernel/intern/ipo.c =================================================================== --- source/blender/blenkernel/intern/ipo.c (revision 12209) +++ source/blender/blenkernel/intern/ipo.c (working copy) @@ -772,6 +772,8 @@ ob= ob->proxy_from; if(driver->blocktype==ID_OB) { + float retval; + /* depsgraph failure; ob ipos are calculated in where_is_object, this might get called too late */ if(ob->ipo && ob->ctime!=ipotime) { calc_ipo_spec(ob->ipo, driver->adrcode, &ipotime); @@ -780,31 +782,44 @@ switch(driver->adrcode) { case OB_LOC_X: - return ob->loc[0]; + retval= ob->loc[0]; + break; case OB_LOC_Y: - return ob->loc[1]; + retval= ob->loc[1]; + break; case OB_LOC_Z: - return ob->loc[2]; + retval= ob->loc[2]; + break; case OB_ROT_X: - return ob->rot[0]/(M_PI_2/9.0); + retval= ob->rot[0]/(M_PI_2/9.0); + break; case OB_ROT_Y: - return ob->rot[1]/(M_PI_2/9.0); + retval= ob->rot[1]/(M_PI_2/9.0); + break; case OB_ROT_Z: - return ob->rot[2]/(M_PI_2/9.0); + retval= ob->rot[2]/(M_PI_2/9.0); + break; case OB_SIZE_X: - return ob->size[0]; + retval= ob->size[0]; + break; case OB_SIZE_Y: - return ob->size[1]; + retval= ob->size[1]; + break; case OB_SIZE_Z: - return ob->size[2]; + retval= ob->size[2]; + break; } + + return retval*driver->fac; } else { /* ID_AR */ bPoseChannel *pchan= get_pose_channel(ob->pose, driver->name); + if(pchan && pchan->bone) { float pose_mat[3][3]; float diff_mat[3][3], par_mat[3][3], ipar_mat[3][3]; float eul[3], size[3]; + float retval; /* we need the local transform = current transform - (parent transform + bone transform) */ @@ -827,24 +842,35 @@ switch(driver->adrcode) { case OB_LOC_X: - return pchan->loc[0]; + retval= pchan->loc[0]; + break; case OB_LOC_Y: - return pchan->loc[1]; + retval= pchan->loc[1]; + break; case OB_LOC_Z: - return pchan->loc[2]; + retval= pchan->loc[2]; + break; case OB_ROT_X: - return eul[0]/(M_PI_2/9.0); + retval= eul[0]/(M_PI_2/9.0); + break; case OB_ROT_Y: - return eul[1]/(M_PI_2/9.0); + retval= eul[1]/(M_PI_2/9.0); + break; case OB_ROT_Z: - return eul[2]/(M_PI_2/9.0); + retval= eul[2]/(M_PI_2/9.0); + break; case OB_SIZE_X: - return size[0]; + retval= size[0]; + break; case OB_SIZE_Y: - return size[1]; + retval= size[1]; + break; case OB_SIZE_Z: - return size[2]; + retval= size[2]; + break; } + + return retval*driver->fac; } } } Index: source/blender/blenkernel/intern/modifier.c =================================================================== --- source/blender/blenkernel/intern/modifier.c (revision 12209) +++ source/blender/blenkernel/intern/modifier.c (working copy) @@ -96,6 +96,10 @@ /***/ +/* Since were using normals a bit */ +#define NORM_SHORT_TO_FLOAT(fln, shn) fln[0]=shn[0]/32767.0f; fln[1]=shn[1]/32767.0f; fln[2]=shn[2]/32767.0f; +#define NORM_FLOAT_TO_SHORT(shn, fln) shn[0]=(short)(fln[0]*32767.0f); shn[1]=(short)(fln[1]*32767.0f); shn[2]=(short)(fln[2]*32767.0f); + static int noneModifier_isDisabled(ModifierData *md) { return 1; @@ -552,6 +556,705 @@ return result; } +/* Lathe */ +/* Lathe modifier: revolves the edges about an axis +*/ + +/* used for gathering edge connectivity */ +typedef struct LatheVertConnect { + float dist; /* distance from the center axis */ + float co[3]; /* loaction relative to the transformed axis */ + float no[3]; /* calc normal of the vertex */ + int v[2]; /* 2 verts on either side of this one */ + MEdge *e[2]; /* edges on either side, a bit of a waste since each edge ref's 2 edges */ + char flag; +} LatheVertConnect; + +typedef struct LatheVertIter { + LatheVertConnect * v_array; + LatheVertConnect * v_poin; + int v; + int v_other; + MEdge *e; +} LatheVertIter; + +#define LatheVertIter_INIT(iter, array, v_init, dir)\ + iter.v_array = array;\ + iter.v = v_init;\ + if (v_init>=0) {\ + iter.v_poin = &array[v_init];\ + iter.v_other = iter.v_poin->v[dir];\ + if (dir)\ + iter.e = iter.v_poin->e[0];\ + else\ + iter.e = iter.v_poin->e[1];\ + } else {\ + iter.v_poin= NULL;\ + iter.e= NULL;\ + } + +/* GCC Warns of incompatible pointers here + * but its only when setting the edge and vert to NULL + * on line "iter.e = iter.v_poin = NULL;" + */ +#define LatheVertIter_NEXT(iter)\ + if (iter.v_poin->v[0] == iter.v_other) {\ + iter.v_other = iter.v;\ + iter.v = iter.v_poin->v[1];\ + } else if (iter.v_poin->v[1] == iter.v_other) {\ + iter.v_other = iter.v;\ + iter.v = iter.v_poin->v[0];\ + }\ + if (iter.v >=0) {\ + iter.v_poin = &iter.v_array[iter.v];\ + if ( iter.v_poin->e[0] != iter.e ) iter.e = iter.v_poin->e[0];\ + else iter.e = iter.v_poin->e[1];\ + } else {\ + iter.e = iter.v_poin = NULL;\ + } + +static void latheModifier_initData(ModifierData *md) +{ + LatheModifierData *ltmd = (LatheModifierData*) md; + ltmd->ob_axis = NULL; + ltmd->deg = 360.0f; + ltmd->axis = 2; + ltmd->flag = 0; + ltmd->steps = 16; + ltmd->renderSteps = 16; +} + +static void latheModifier_copyData(ModifierData *md, ModifierData *target) +{ + LatheModifierData *sltmd = (LatheModifierData*) md; + LatheModifierData *tltmd = (LatheModifierData*) target; + + tltmd->ob_axis = sltmd->ob_axis; + tltmd->deg = sltmd->deg; + tltmd->axis = sltmd->axis; + tltmd->flag = sltmd->flag; + tltmd->steps = sltmd->steps; + tltmd->renderSteps = sltmd->renderSteps; +} + +static DerivedMesh *latheModifier_applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + DerivedMesh *dm = derivedData; + DerivedMesh *result; + LatheModifierData *ltmd = (LatheModifierData*) md; + + int *origindex; + int mface_index=0; + int i, j; + int i1,i2; + int steps = ltmd->steps; + int maxVerts=0, maxEdges=0, maxFaces=0; + int totvert = dm->getNumVerts(dm); + int totedge = dm->getNumEdges(dm); + + char axis_char, close; + float angle, axis_vec[3] = {0.0f, 0.0f, 0.0f}; + float tmp_vec1[3], tmp_vec2[3]; + float mat3[3][3]; + float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */ + float mtx_tx_inv[4][4]; /* inverted */ + float mtx_tmp_a[4][4]; + + int vc_tot_linked = 0; + short other_axis_1, other_axis_2; + float *tmpf1, *tmpf2; + + MFace *mface_new, *mf_new; + MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new; + MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new; + + LatheVertConnect *vc, *vc_tmp, *vert_connect; + + + float mat[4][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}; + + /* dont do anything? */ + if (!totvert) + return CDDM_from_template(dm, 0, 0, 0); + + if (useRenderParams) + steps = ltmd->renderSteps; + else + steps = ltmd->steps; + + /* will the lathe be closed? */ + if (fabs(ltmd->deg) + 0.000001 > 360.0) { + close = 1; + + maxVerts = totvert * (steps); /* -1 because we're joining back up */ + maxEdges = (totvert * (steps)) + /* these are the edges between new verts */ + (totedge * (steps)); /* -1 because vert edges join */ + maxFaces = totedge * steps; + } else { + close = 0; + + maxVerts = totvert * (steps); /* -1 because we're joining back up */ + maxEdges = (totvert * (steps-1)) + /* these are the edges between new verts */ + (totedge * (steps)); /* -1 because vert edges join */ + maxFaces = totedge * (steps-1); + } + + axis_vec[ltmd->axis] = 1.0; + if (ltmd->ob_axis) { + /* calc the matrix relative to the axis object */ + Mat4Invert(mtx_tmp_a, ob->obmat); + Mat4CpyMat4(mtx_tx_inv, ltmd->ob_axis->obmat); + Mat4MulMat4(mtx_tx, mtx_tx_inv, mtx_tmp_a); + + /* calc the axis vec */ + Mat4Mul3Vecfl(mtx_tx, axis_vec); + Normalize(axis_vec); + } else { + /* exis char is used by i_rotate*/ + if (ltmd->axis==0) axis_char= 'x'; + else if (ltmd->axis==1) axis_char= 'y'; + else axis_char= 'z'; + } + + result = CDDM_from_template(dm, maxVerts, maxEdges, maxFaces); + + /* copy verts from mesh */ + mvert_orig = dm->getVertArray(dm); + medge_orig = dm->getEdgeArray(dm); + + mvert_new = result->getVertArray(result); + mface_new = result->getFaceArray(result); + medge_new = result->getEdgeArray(result); + + origindex = result->getFaceDataArray(result, CD_ORIGINDEX); + + /* Set the locations of the first set of verts */ + + mv_new= mvert_new; + mv_orig= mvert_orig; + + /* Copy the first set of edges */ + med_orig= medge_orig; + med_new= medge_new; + for (i=0; i < totedge; i++, med_orig++, med_new++) { + med_new->v1 = med_orig->v1; + med_new->v2 = med_orig->v2; + med_new->crease = med_orig->crease; + med_new->flag = med_orig->flag & ~ME_LOOSEEDGE; + } + + /* + * Normal Calculation (for face flipping) + * Sort edge verts for correct face flipping + * NOT REALLY NEEDED but face flipping is nice. + * + * */ + + + /* Notice! + * + * Since we are only ordering the edges here it can avoid mallocing the + * extra space by abusing the vert array berfore its filled with new verts. + * The new array for vert_connect must be at least sizeof(LatheVertConnect) * totvert + * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3 + * so its safe to use the second 2 thrids of MVert the array for vert_connect, + * just make sure LatheVertConnect struct is no more then twice as big as MVert, + * at the moment there is no chance of that being a problem, + * unless MVert becomes half its current size. + * + * once the edges are ordered, vert_connect is not needed and it can be used for verts + * + * This makes the modifier faster with one less alloc. + */ + + vert_connect = MEM_mallocN(sizeof(LatheVertConnect) * totvert, "LatheVertConnect"); + //vert_connect = (LatheVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */ + vc = vert_connect; + + /* Copy Vert Locations */ + /* - We can do this in a later loop - only do here if no normal calc */ + if (!totedge) { + for (i=0; i < totvert; i++, mv_orig++, mv_new++) { + VECCOPY(mv_new->co, mv_orig->co); + + VECCOPY(vc->no, mv_new->co); /* no edges- this is realy a dummy normal */ + Normalize(vc->no); + } + } else { + /*printf("\n\n\n\n\nStarting Modifier\n");*/ + /* set edge users */ + med_new= medge_new; + mv_new= mvert_new; + + if (ltmd->axis==0) { + other_axis_1=1; + other_axis_2=2; + } else if (ltmd->axis==1) { + other_axis_1=0; + other_axis_2=2; + } else { + other_axis_1=0; + other_axis_2=1; + } + + if (ltmd->ob_axis) { + /*mtx_tx is initialized early on */ + for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) { + vc->co[0] = mv_new->co[0] = mv_orig->co[0]; + vc->co[1] = mv_new->co[1] = mv_orig->co[1]; + vc->co[2] = mv_new->co[2] = mv_orig->co[2]; + + vc->flag= 0; + vc->e[0] = vc->e[1] = NULL; + vc->v[0] = vc->v[1] = -1; + + Mat4Mul3Vecfl(mtx_tx, vc->co); + /* length in 2d, dont sqrt because this is only for comparison */ + vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] + + vc->co[other_axis_2]*vc->co[other_axis_2]; + + /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ + } + } else { + for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) { + vc->co[0] = mv_new->co[0] = mv_orig->co[0]; + vc->co[1] = mv_new->co[1] = mv_orig->co[1]; + vc->co[2] = mv_new->co[2] = mv_orig->co[2]; + + vc->flag= 0; + vc->e[0] = vc->e[1] = NULL; + vc->v[0] = vc->v[1] = -1; + + /* length in 2d, dont sqrt because this is only for comparison */ + vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] + + vc->co[other_axis_2]*vc->co[other_axis_2]; + + /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ + } + } + + /* this loop builds connectivity info for verts */ + for (i=0; iv1]; + + if (vc->v[0]==-1) { /* unused */ + vc->v[0] = med_new->v2; + vc->e[0] = med_new; + } else if (vc->v[1]==-1) { + vc->v[1] = med_new->v2; + vc->e[1] = med_new; + } else { + vc->v[0] = vc->v[1] = -2; /* erro value - dont use, 3 edges on vert */ + } + + vc = &vert_connect[med_new->v2]; + + /* same as above but swap v1/2 */ + if (vc->v[0]==-1) { /* unused */ + vc->v[0] = med_new->v1; + vc->e[0] = med_new; + } else if (vc->v[1]==-1) { + vc->v[1] = med_new->v1; + vc->e[1] = med_new; + } else { + vc->v[0] = vc->v[1] = -2; /* erro value - dont use, 3 edges on vert */ + } + } + + /* find the first vert */ + vc = vert_connect; + for (i=0; i < totvert; i++, vc++) { + int VBEST=-1, ed_loop_closed=0; /* vert and vert new */ + int ed_loop_flip; + float fl = -1.0f; + LatheVertIter lt_iter; + + /* Now do search for connected verts, order all edges and flip them + * so resulting faces are flipped the right way */ + vc_tot_linked = 0; /* count the number of linked verts for this loop */ + if (vc->flag==0) { + /*printf("Loop on connected vert: %i\n", i);*/ + + for(j=0; j<2; j++) { + /*printf("\tSide: %i\n", j);*/ + LatheVertIter_INIT(lt_iter, vert_connect, i, j); + if (j==1) { + LatheVertIter_NEXT(lt_iter); + } + while (lt_iter.v_poin) { + /*printf("\t\tVERT: %i\n", lt_iter.v);*/ + if (lt_iter.v_poin->flag) { + /*printf("\t\t\tBreaking Found end\n");*/ + //endpoints[0] = endpoints[1] = -1; + ed_loop_closed = 1; /* circle */ + break; + } + lt_iter.v_poin->flag= 1; + vc_tot_linked++; + /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/ + if (fl <= lt_iter.v_poin->dist) { + fl = lt_iter.v_poin->dist; + VBEST = lt_iter.v; + /*printf("\t\t\tVERT BEST: %i\n", VBEST);*/ + } + LatheVertIter_NEXT(lt_iter); + if (!lt_iter.v_poin) { + /*printf("\t\t\tFound End Also Num %i\n", j);*/ + /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */ + break; + } + } + } + + /* now we have a collection of used edges. flip their edges the right way*/ + /*if (VBEST !=-1) - */ + + /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/ + + if (vc_tot_linked>1) { + float vf_1, vf_2, vf_best; + + vc_tmp = &vert_connect[VBEST]; + + tmpf1 = ((&vert_connect[vc_tmp->v[0]])->co); + tmpf2 = ((&vert_connect[vc_tmp->v[1]])->co); + + + /* edge connects on each side! */ + if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) { + /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/ + /* find out which is higher */ + + vf_1= tmpf1[ltmd->axis]; + vf_2= tmpf2[ltmd->axis]; + vf_best= vc_tmp->co[ltmd->axis]; + + if (vf_1 < vf_best && vf_best < vf_2) { + ed_loop_flip = 0; + } else if (vf_1 > vf_best && vf_best > vf_2) { + ed_loop_flip = 1; + } else { + /* not so simple to work out wich edge is higher */ + VECSUB(tmp_vec1, tmpf1, vc_tmp->co); + VECSUB(tmp_vec1, tmpf2, vc_tmp->co); + Normalize(tmp_vec1); + Normalize(tmp_vec2); + + if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) { + ed_loop_flip = 1; + } else { + ed_loop_flip = 0; + } + } + } else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */ + /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/ + if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */ + ed_loop_flip = 1; + } else { /* best is below or even... in even case we cant know whet to do. */ + ed_loop_flip = 0; + } + + }/* else { + printf("No Connected ___\n"); + }*/ + + /*printf("flip direction %i\n", ed_loop_flip);*/ + + + /* switch the flip option if set */ + if (ltmd->flag & MOD_LATHE_NORMAL_FLIP) { + if (ed_loop_flip) ed_loop_flip = 0; + else ed_loop_flip = 1; + } + if (ltmd->deg < 0.0f) { + if (ed_loop_flip) ed_loop_flip = 0; + else ed_loop_flip = 1; + } + + /* if its closed, we only need 1 loop */ + for(j=ed_loop_closed; j<2; j++) { + /*printf("Ordering Side J %i\n", j);*/ + + LatheVertIter_INIT(lt_iter, vert_connect, VBEST, j); + /*printf("\n\nStarting - Loop\n");*/ + lt_iter.v_poin->flag = 1; /* so a non loop will traverse the other side */ + + + /* If this is the vert off the best vert and + * the best vert has 2 edges connected too it + * then swap the flip direction */ + if (j==1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) { + if (ed_loop_flip) ed_loop_flip = 0; + else ed_loop_flip = 1; + } + + while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) { + /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/ + + lt_iter.v_poin->flag = 2; + if (lt_iter.e) { + if (lt_iter.v == lt_iter.e->v1) { + if (ed_loop_flip==0) { + /*printf("\t\t\tFlipping 0\n");*/ + SWAP( int, lt_iter.e->v1, lt_iter.e->v2 ); + }/* else { + printf("\t\t\tFlipping Not 0\n"); + }*/ + } else if (lt_iter.v == lt_iter.e->v2) { + if (ed_loop_flip==1) { + /*printf("\t\t\tFlipping 1\n");*/ + SWAP( int, lt_iter.e->v1, lt_iter.e->v2 ); + }/* else { + printf("\t\t\tFlipping Not 1\n"); + }*/ + }/* else { + printf("\t\tIncorrect edge topology"); + }*/ + }/* else { + printf("\t\tNo Edge at this point\n"); + }*/ + LatheVertIter_NEXT(lt_iter); + } + } + } + } + + /* *VERTEX NORMALS* + * we know the surrounding edges are ordered correctly now + * so its safe to create vertex normals. + * + * calculate vertex normals that can be propodated on lathing + * use edge connectivity work this out */ + if (vc->v[0]>=0) { + if (vc->v[1]>=0) { + /* 2 edges connedted */ + /* make 2 connecting vert locations relative to the middle vert */ + VECSUB(tmp_vec1, (&mvert_new[vc->v[0]])->co, (&mvert_new[i])->co); + VECSUB(tmp_vec2, (&mvert_new[vc->v[1]])->co, (&mvert_new[i])->co); + /* normalize so both edges have the same influence, no matter their length */ + Normalize(tmp_vec1); + Normalize(tmp_vec2); + + /* vc_no_tmp1 - this line is the average direction of both connecting edges + * + * Use the edge order to make the subtraction, flip the normal the right way + * edge should be there but check just in case... */ + if (vc->e && vc->e[0]->v1 == i) { + VECSUB(tmp_vec1, tmp_vec1, tmp_vec2); + } else { + VECSUB(tmp_vec1, tmp_vec2, tmp_vec1); + } + + } else { + /* only 1 edge connected - same as above except + * dont need to average edge direction */ + if (vc->e && vc->e[0]->v2 == i) { + VECSUB(tmp_vec1, (&mvert_new[i])->co, (&mvert_new[vc->v[0]])->co); + } else { + VECSUB(tmp_vec1, (&mvert_new[vc->v[0]])->co, (&mvert_new[i])->co); + } + } + + /* vc_no_tmp2 - is a line 90d from the pivot to the vec + * This is used so the resulting normal points directly away from the middle */ + Crossf(tmp_vec2, axis_vec, vc->co); + + /* edge average vector and right angle to the pivot make the normal */ + Crossf(vc->no, tmp_vec1, tmp_vec2); + + } else { + VECCOPY(vc->no, vc->co); + } + + /* we wont be looping on this data again so copy normals here */ + if (ltmd->deg < 0.0) + VecMulf(vc->no, -1.0f); + + Normalize(vc->no); + NORM_FLOAT_TO_SHORT((&mvert_new[i])->no, vc->no); + + /* Done with normals */ + } + } + /* done with edge connectivity based normal flipping */ + + + /* Add Faces */ + for (i=1; i < steps; i++) { + /* Rotation Matrix */ + if (close) angle = (ltmd->deg / steps) * i; + else angle = (ltmd->deg / (steps-1)) * i; + + if (ltmd->ob_axis) { + VecRotToMat3(axis_vec, angle * M_PI/180.0f, mat3); + Mat4CpyMat3(mat, mat3); + + } else { + Mat4One(mat); + i_rotate(angle, axis_char, mat); + } + + mv_orig= mvert_orig; + mv_new= &mvert_new[totvert*i]; /* advance to the next slice */ + + for (j=0; jno); + + /* set location */ + VECCOPY(mv_new->co, mv_orig->co); + + /* only need to set these if using non cleared memory */ + /*mv_new->mat_nr = mv_new->flag = 0;*/ + + if (ltmd->ob_axis) { + mv_new->co[0] -= mtx_tx[3][0]; + mv_new->co[1] -= mtx_tx[3][1]; + mv_new->co[2] -= mtx_tx[3][2]; + + Mat4MulVecfl(mat, mv_new->co); + Mat4MulVecfl(mat, tmp_vec1); + + mv_new->co[0] += mtx_tx[3][0]; + mv_new->co[1] += mtx_tx[3][1]; + mv_new->co[2] += mtx_tx[3][2]; + } else { + Mat4MulVecfl(mat, mv_new->co); + Mat4MulVecfl(mat, tmp_vec1); + } + + /* set the normal now its transformed */ + NORM_FLOAT_TO_SHORT(mv_new->no, tmp_vec1); + + /* add the new edge */ + med_new->v1 = j+(i*totvert); + med_new->v2 = med_new->v1 - totvert; + med_new->flag = ME_EDGEDRAW|ME_EDGERENDER; + med_new++; + } + } + + if (close) { + /* last loop of edges, previous loop dosnt account for the last set of edges */ + for (i=0; iv1 = i+((steps-1)*totvert); + med_new->v2 = i; + med_new->flag = ME_EDGEDRAW|ME_EDGERENDER; + med_new++; + } + } + + mf_new = mface_new; + med_new_firstloop= medge_new; + + for (i=0; i < totedge; i++, med_new_firstloop++) { + /* for each edge, make a cylinder of quads */ + i1= med_new_firstloop->v1; + i2= med_new_firstloop->v2; + + for (j=0; j < steps-1; j++) { + + /* new face */ + mf_new->v1 = i1; + mf_new->v2 = i2; + mf_new->v3 = i2 + totvert; + mf_new->v4 = i1 + totvert; + + if( !mf_new->v3 || !mf_new->v4 ) { + SWAP( int, mf_new->v1, mf_new->v3 ); + SWAP( int, mf_new->v2, mf_new->v4 ); + } + mf_new->flag = ME_SMOOTH; + origindex[mface_index] = ORIGINDEX_NONE; + mf_new++; + mface_index++; + + /* new vertical edge */ + if (j) { /* The first set is alredw dome */ + med_new->v1 = i1; + med_new->v2 = i2; + med_new->flag = med_new_firstloop->flag; + med_new->crease = med_new_firstloop->crease; + med_new++; + } + i1 += totvert; + i2 += totvert; + } + + /* close the loop*/ + if (close) { + mf_new->v1 = i1; + mf_new->v2 = i2; + mf_new->v3 = med_new_firstloop->v2; + mf_new->v4 = med_new_firstloop->v1; + + if( !mf_new->v3 || !mf_new->v4 ) { + SWAP( int, mf_new->v1, mf_new->v3 ); + SWAP( int, mf_new->v2, mf_new->v4 ); + } + mf_new->flag = ME_SMOOTH; + origindex[mface_index] = ORIGINDEX_NONE; + mf_new++; + mface_index++; + } + + /* new vertical edge */ + med_new->v1 = i1; + med_new->v2 = i2; + med_new->flag = med_new_firstloop->flag & ~ME_LOOSEEDGE; + med_new->crease = med_new_firstloop->crease; + med_new++; + } + + /* we can avoid if using vert alloc trick */ + MEM_freeN(vert_connect); + + return result; +} + + +static void latheModifier_updateDepgraph( + ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) +{ + LatheModifierData *ltmd = (LatheModifierData*) md; + + if(ltmd->ob_axis) { + DagNode *curNode = dag_get_node(forest, ltmd->ob_axis); + + dag_add_relation(forest, curNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + } +} + +static void latheModifier_foreachObjectLink( + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) +{ + LatheModifierData *ltmd = (LatheModifierData*) md; + + walk(userData, ob, <md->ob_axis); +} + +/* This dosnt work with material*/ +static DerivedMesh *latheModifier_applyModifierEM( + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) +{ + return latheModifier_applyModifier(md, ob, derivedData, 0, 1); +} + +static int latheModifier_dependsOnTime(ModifierData *md) +{ + return 0; +} + /* Array */ /* Array modifier: duplicates the object multiple times along an axis */ @@ -2785,7 +3488,7 @@ int result_type; result_type = multitex_ext(texture, tex_co, NULL, - NULL, 1, texres); + NULL, 1, texres, NULL); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, so calculate one (formula from do_material_tex). @@ -5000,6 +5703,20 @@ mti->dependsOnTime = buildModifier_dependsOnTime; mti->applyModifier = buildModifier_applyModifier; + mti = INIT_TYPE(Lathe); + mti->type = eModifierTypeType_Constructive; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; + + mti->initData = latheModifier_initData; + mti->copyData = latheModifier_copyData; + mti->foreachObjectLink = latheModifier_foreachObjectLink; + mti->dependsOnTime = latheModifier_dependsOnTime; + mti->updateDepgraph = latheModifier_updateDepgraph; + mti->applyModifier = latheModifier_applyModifier; + mti->applyModifierEM = latheModifier_applyModifierEM; + mti = INIT_TYPE(Array); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh Index: source/blender/blenkernel/intern/colortools.c =================================================================== --- source/blender/blenkernel/intern/colortools.c (revision 12209) +++ source/blender/blenkernel/intern/colortools.c (working copy) @@ -44,6 +44,7 @@ #include "BKE_global.h" #include "BKE_ipo.h" #include "BKE_image.h" +#include "DNA_material_types.h" /* for bool defines */ #include "BKE_main.h" #include "BKE_utildefines.h" @@ -167,18 +168,29 @@ void curvemap_insert(CurveMap *cuma, float x, float y) { CurveMapPoint *cmp= MEM_callocN((cuma->totpoint+1)*sizeof(CurveMapPoint), "curve points"); - int a; - - memcpy(cmp, cuma->curve, (cuma->totpoint)*sizeof(CurveMapPoint)); + int a, b, foundloc= 0; + + /* insert fragments of the old one and the new point to the new curve */ + cuma->totpoint++; + for(a=0, b=0; atotpoint; a++) { + if((x < cuma->curve[a].x) && !foundloc) { + cmp[a].x= x; + cmp[a].y= y; + cmp[a].flag= CUMA_SELECT; + foundloc= 1; + } + else { + cmp[a].x= cuma->curve[b].x; + cmp[a].y= cuma->curve[b].y; + cmp[a].flag= cuma->curve[b].flag; + cmp[a].shorty= cuma->curve[b].shorty; + b++; + } + } + + /* free old curve and replace it with new one */ MEM_freeN(cuma->curve); cuma->curve= cmp; - - cuma->curve[cuma->totpoint].x= x; - cuma->curve[cuma->totpoint].y= y; - cuma->curve[cuma->totpoint].flag = CUMA_SELECT; - for(a=0; atotpoint; a++, cmp++) - cmp->flag= 0; - cuma->totpoint++; } void curvemap_reset(CurveMap *cuma, rctf *clipr) @@ -717,3 +729,52 @@ curvemap_make_table(cumap->cm+a, &cumap->clipr); } } + +void boolean_operation(int type, float *out, float limit, float *in1, float *in2) +{ + char assign; + float in1delta, in2delta; + int i; + + for(i=0; i<4; i++) { + if(in1[i] && in2[i]) { + assign= 0; + in1delta= in1[i]-limit; + in2delta= in2[i]-limit; + + switch (type) { + case MA_BOOL_AND: + if((in1delta >= 0) && (in2delta >= 0)) + assign= 1; + break; + case MA_BOOL_OR: + if((in1delta >= 0) || (in2delta >= 0)) + assign= 1; + break; + case MA_BOOL_NAND: + if(!((in1delta >= 0) && (in2delta >= 0))) + assign= 1; + break; + case MA_BOOL_NOR: + if(!((in1delta >= 0) || (in2delta >= 0))) + assign= 1; + break; + case MA_BOOL_XNOR: + if(!((in1delta >= 0) ^ (in2delta >= 0))) + assign= 1; + break; + case MA_BOOL_XOR: + if((in1delta >= 0) ^ (in2delta >= 0)) + assign= 1; + break; + } + + if(assign == 1) + out[i]= (in1[i]+in2[i])/2; + else + out[i]= 0.0; + } + else + break; + } +} Index: source/blender/blenkernel/intern/node.c =================================================================== --- source/blender/blenkernel/intern/node.c (revision 12209) +++ source/blender/blenkernel/intern/node.c (working copy) @@ -843,6 +843,24 @@ return link; } +/* version without bNodes */ +bNodeLink *nodeAddLink2(bNodeTree *ntree, bNodeSocket *fromsock, bNodeSocket *tosock) +{ + bNode *fromnode, *tonode; + int index; /* just for find_node_with_socket */ + + /* figure out in which nodes sockets belong */ + find_node_with_socket(ntree, fromsock, &fromnode, &index); + printf("index: %d \n", index); + find_node_with_socket(ntree, tosock, &tonode, &index); + printf("index: %d \n", index); + + if(fromnode) printf("fromnode ok \n"); + if(tonode) printf("tonode ok \n"); + + return nodeAddLink(ntree, fromnode, fromsock, tonode, tosock); +} + void nodeRemLink(bNodeTree *ntree, bNodeLink *link) { BLI_remlink(&ntree->links, link); @@ -941,7 +959,7 @@ /* ************** Free stuff ********** */ /* goes over entire tree */ -static void node_unlink_node(bNodeTree *ntree, bNode *node) +void nodeUnlinkNode(bNodeTree *ntree, bNode *node) { bNodeLink *link, *next; bNodeSocket *sock; @@ -985,7 +1003,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) { - node_unlink_node(ntree, node); + nodeUnlinkNode(ntree, node); BLI_remlink(&ntree->nodes, node); /* since it is called while free database, node->id is undefined */ @@ -2172,7 +2190,9 @@ if(!(passflag & SCE_PASS_RADIO)) sock->flag |= SOCK_UNAVAIL; sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB); if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL; - + sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMAT); + if(!(passflag & SCE_PASS_INDEXMAT)) sock->flag |= SOCK_UNAVAIL; + } /* based on rules, force sockets hidden always */ @@ -2335,6 +2355,7 @@ nodeRegisterType(ntypelist, &cmp_node_filter); nodeRegisterType(ntypelist, &cmp_node_blur); + nodeRegisterType(ntypelist, &cmp_node_bilateralblur); nodeRegisterType(ntypelist, &cmp_node_vecblur); nodeRegisterType(ntypelist, &cmp_node_dilateerode); nodeRegisterType(ntypelist, &cmp_node_defocus); @@ -2344,6 +2365,7 @@ nodeRegisterType(ntypelist, &cmp_node_setalpha); nodeRegisterType(ntypelist, &cmp_node_idmask); nodeRegisterType(ntypelist, &cmp_node_math); + nodeRegisterType(ntypelist, &cmp_node_boolean); nodeRegisterType(ntypelist, &cmp_node_seprgba); nodeRegisterType(ntypelist, &cmp_node_combrgba); nodeRegisterType(ntypelist, &cmp_node_sephsva); @@ -2363,6 +2385,7 @@ nodeRegisterType(ntypelist, &cmp_node_rotate); nodeRegisterType(ntypelist, &cmp_node_scale); nodeRegisterType(ntypelist, &cmp_node_flip); + nodeRegisterType(ntypelist, &cmp_node_crop); nodeRegisterType(ntypelist, &cmp_node_displace); nodeRegisterType(ntypelist, &cmp_node_mapuv); } @@ -2380,6 +2403,7 @@ nodeRegisterType(ntypelist, &sh_node_curve_vec); nodeRegisterType(ntypelist, &sh_node_curve_rgb); nodeRegisterType(ntypelist, &sh_node_math); + nodeRegisterType(ntypelist, &sh_node_boolean); nodeRegisterType(ntypelist, &sh_node_vect_math); nodeRegisterType(ntypelist, &sh_node_squeeze); nodeRegisterType(ntypelist, &sh_node_camera); @@ -2392,6 +2416,8 @@ nodeRegisterType(ntypelist, &sh_node_seprgb); nodeRegisterType(ntypelist, &sh_node_combrgb); nodeRegisterType(ntypelist, &sh_node_hue_sat); + nodeRegisterType(ntypelist, &sh_node_brightcontrast); + nodeRegisterType(ntypelist, &sh_node_gamma); } void init_nodesystem(void) Index: source/blender/blenkernel/BKE_colortools.h =================================================================== --- source/blender/blenkernel/BKE_colortools.h (revision 12209) +++ source/blender/blenkernel/BKE_colortools.h (working copy) @@ -57,6 +57,7 @@ void curvemapping_premultiply(struct CurveMapping *cumap, int restore); int curvemapping_RGBA_does_something(struct CurveMapping *cumap); void curvemapping_initialize(struct CurveMapping *cumap); +void boolean_operation(int type, float *out, float limit, float *in1, float *in2); #endif Index: source/blender/makesdna/DNA_node_types.h =================================================================== --- source/blender/makesdna/DNA_node_types.h (revision 12209) +++ source/blender/makesdna/DNA_node_types.h (working copy) @@ -92,7 +92,8 @@ #define SOCK_IN_USE 4 /* unavailable is for dynamic sockets */ #define SOCK_UNAVAIL 8 - + /* flag for selection status */ +#define SOCK_SEL 16 # # typedef struct bNodePreview { @@ -167,6 +168,10 @@ ListBase alltypes; /* type definitions */ struct bNodeType *owntype; /* for groups or dynamic trees, no read/write */ + /* selected input/output socket */ + bNodeSocket *selin; + bNodeSocket *selout; + /* callbacks */ void (*timecursor)(int nr); void (*stats_draw)(char *str); @@ -192,12 +197,19 @@ typedef struct NodeBlurData { short sizex, sizey, samples, maxspeed, minspeed, pad1; - float fac; + float fac,percentx,percenty; short filtertype; char bokeh, gamma; - int pad2; + int relative; + /* need to relative data correlation*/ + int imageInputWidth,imageInputHeight; } NodeBlurData; +typedef struct NodeBilateralBlurData { + short iter,pad1; + float sigma_color,sigma_space; +} NodeBilateralBlurData; + typedef struct NodeHueSat { float hue, sat, val; } NodeHueSat; @@ -214,6 +226,10 @@ float key[4]; } NodeChroma; +typedef struct NodeTwoXYs { + short x1, x2, y1, y2; +} NodeTwoXYs; + typedef struct NodeGeometry { char uvname[32]; char colname[32]; Index: source/blender/makesdna/DNA_space_types.h =================================================================== --- source/blender/makesdna/DNA_space_types.h (revision 12209) +++ source/blender/makesdna/DNA_space_types.h (working copy) @@ -152,7 +152,8 @@ short chanshown; short pad2; int flag; - int pad; + short render; + short pad; } SpaceSeq; typedef struct SpaceFile { @@ -171,7 +172,7 @@ char file[80]; short type, ofs, flag, sort; - short maxnamelen, collums, f_fp, pad1; + short maxnamelen, collums, f_fp, wasfullscreen; int pad2; char fp_str[8]; @@ -342,6 +343,7 @@ /* snode->flag */ #define SNODE_DO_PREVIEW 1 #define SNODE_BACKDRAW 2 +#define SNODE_AUTOCONNECT 4 typedef struct SpaceImaSel { SpaceLink *next, *prev; Index: source/blender/makesdna/DNA_scene_types.h =================================================================== --- source/blender/makesdna/DNA_scene_types.h (revision 12209) +++ source/blender/makesdna/DNA_scene_types.h (working copy) @@ -153,6 +153,7 @@ #define SCE_PASS_INDEXOB 2048 #define SCE_PASS_UV 4096 #define SCE_PASS_RADIO 8192 +#define SCE_PASS_INDEXMAT 16384 /* note, srl->passflag is treestore element 'nr' in outliner, short still... */ @@ -333,7 +334,8 @@ short uvcalc_mapalign; short uvcalc_flag; - short pad2; + /* Mirror axis */ + short mirror; /* Image Paint (8 byte aligned please!) */ struct ImagePaintSettings imapaint; @@ -576,9 +578,13 @@ #define SCE_SNAP_TARGET_MEDIAN 2 /* sce->selectmode */ -#define SCE_SELECT_VERTEX 1 -#define SCE_SELECT_EDGE 2 -#define SCE_SELECT_FACE 4 +#define SCE_SELECT_VERTEX 1 +#define SCE_SELECT_EDGE 2 +#define SCE_SELECT_VERTEX_AND_EDGE 3 +#define SCE_SELECT_FACE 4 +#define SCE_SELECT_VERTEX_AND_FACE 5 +#define SCE_SELECT_EDGE_AND_FACE 6 +#define SCE_SELECT_VERTEX_AND_EDGE_AND_FACE 7 /* sce->recalc (now in use by previewrender) */ #define SCE_PRV_CHANGED 1 Index: source/blender/makesdna/DNA_userdef_types.h =================================================================== --- source/blender/makesdna/DNA_userdef_types.h (revision 12209) +++ source/blender/makesdna/DNA_userdef_types.h (working copy) @@ -94,7 +94,10 @@ char strip[4], strip_select[4]; char vertex_size, facedot_size; + + char layer_color_ne[4]; char bpad[2]; + char bpad2[4]; char syntaxl[4], syntaxn[4], syntaxb[4]; // syntax for textwindow and nodes char syntaxv[4], syntaxc[4]; @@ -206,6 +209,8 @@ #define USER_LMOUSESELECT 16384 #define USER_FILECOMPRESS 32768 #define USER_SAVE_PREVIEWS 65536 +#define USER_ADDOB_ALIGN_EDIT 131072 +#define USER_TWEAKMODE 262144 /* viewzom */ #define USER_ZOOM_CONT 0 @@ -226,14 +231,15 @@ #define USER_MENUOPENAUTO 512 #define USER_PANELPINNED 1024 #define USER_AUTOPERSP 2048 -#define USER_LOCKAROUND 4096 -#define USER_GLOBALUNDO 8192 -#define USER_ORBIT_SELECTION 16384 +#define USER_LOCKAROUND 4096 +#define USER_GLOBALUNDO 8192 +#define USER_ORBIT_SELECTION 16384 #define USER_KEYINSERTAVAI 32768 #define USER_HIDE_DOT 65536 -#define USER_SHOW_ROTVIEWICON 131072 -#define USER_SHOW_VIEWPORTNAME 262144 +#define USER_SHOW_ROTVIEWICON 131072 +#define USER_SHOW_VIEWPORTNAME 262144 #define USER_KEYINSERTNEED 524288 +#define USER_CYCLE_SELMODE 1048576 /* transopts */ Index: source/blender/makesdna/DNA_texture_types.h =================================================================== --- source/blender/makesdna/DNA_texture_types.h (revision 12209) +++ source/blender/makesdna/DNA_texture_types.h (working copy) @@ -128,6 +128,21 @@ short recalc, lastsize; } EnvMap; +/* --------------------------------------- Tiles Specific ---------------------------------------------- */ +typedef struct TexPreCalc { + float hpat[16]; /* Stores horizontal tile pattern */ + float vpat[16]; /* Stores vertical tile pattern */ + float bpat[16][16]; /* Stores the bump pattern */ + float minw, minh; /* Store overall min of width and height value */ + float maxw, maxh; /* Store overall max of width and height value */ + float r[16][16]; /* Store colour pattern */ + float g[16][16]; + float b[16][16]; + float rpat[16]; /* Stores the random numbers for anything else */ + float hgap, vgap; /* Stores gap values scaled by overall size of pattern */ +} TexPreCalc; +/* --------------------------------------- Tiles Specific ---------------------------------------------- */ + typedef struct Tex { ID id; @@ -152,7 +167,18 @@ short imaflag, flag; short type, stype; - + + short hcount, vcount, smooth; + short corner, preset, bevoption; + float scale, rotate, hskew, vskew, hoffset, voffset; + float minwidth, maxwidth, minheight, maxheight, minbump, maxbump; + float curve, freq, amp; + float hgap, vgap, shift, bevel, strength; + float colr1, colg1, colb1, colr2, colg2, colb2, fhue, fsat, fval; + float hcorner, vcorner; + unsigned int seed, alternate; + struct TexPreCalc precalc; + float cropxmin, cropymin, cropxmax, cropymax; short xrepeat, yrepeat; short extend; @@ -176,12 +202,16 @@ } Tex; +void tiles_precalc(Tex *tex); + /* used for mapping node. note: rot is in degrees */ typedef struct TexMapping { float loc[3], rot[3], size[3]; int flag; + int wrap, pad; + float mat[4][4]; float min[3], max[3]; struct Object *ob; @@ -209,6 +239,7 @@ #define TEX_MUSGRAVE 11 #define TEX_VORONOI 12 #define TEX_DISTNOISE 13 +#define TEX_TILES 14 /* musgrave stype */ #define TEX_MFRACTAL 0 @@ -307,6 +338,27 @@ #define TEX_HALO 5 #define TEX_RAD 6 +/* tex->stype in texture.c - corner types */ +#define TEX_CORNER_ROUND1 0 +#define TEX_CORNER_ROUND2 1 +#define TEX_CORNER_ELLIPSE1 2 +#define TEX_CORNER_ELLIPSE2 3 +#define TEX_CORNER_STRAIGHT 4 + +#define TEX_TILES_NONE 0 +#define TEX_TILES_INTERLOCK1 1 +#define TEX_TILES_HEX 2 +#define TEX_TILES_HERRINGBONE1 3 +#define TEX_TILES_HERRINGBONE2 4 +#define TEX_TILES_HERRINGBONE3 5 +#define TEX_TILES_WEAVE 6 +#define TEX_TILES_INTERLOCK2 7 +#define TEX_TILES_INTERLOCK3 8 + +#define TEX_BEVEL_DEFAULTMIN 0 +#define TEX_BEVEL_UNIFORMMIN 1 +#define TEX_BEVEL_UNIFORMMAX 2 + /* tex->stype in texture.c - stucci types */ #define TEX_PLASTIC 0 #define TEX_WALLIN 1 Index: source/blender/makesdna/DNA_curve_types.h =================================================================== --- source/blender/makesdna/DNA_curve_types.h (revision 12209) +++ source/blender/makesdna/DNA_curve_types.h (working copy) @@ -193,6 +193,7 @@ typedef struct IpoDriver { struct Object *ob; short blocktype, adrcode, type, flag; + float fac, pad; char name[128]; /* bone or constraint(?), or python expression here */ } IpoDriver; Index: source/blender/makesdna/DNA_modifier_types.h =================================================================== --- source/blender/makesdna/DNA_modifier_types.h (revision 12209) +++ source/blender/makesdna/DNA_modifier_types.h (working copy) @@ -28,6 +28,7 @@ eModifierType_UVProject, eModifierType_Smooth, eModifierType_Cast, + eModifierType_Lathe, NUM_MODIFIER_TYPES } ModifierType; @@ -96,6 +97,17 @@ int randomize, seed; } BuildModifierData; +typedef struct LatheModifierData { + ModifierData modifier; + struct Object *ob_axis; + int steps; + int renderSteps; + float deg; + short axis; + short flag; +} LatheModifierData; +#define MOD_LATHE_NORMAL_FLIP 1 + typedef struct ArrayModifierData { ModifierData modifier; Index: source/blender/makesdna/DNA_material_types.h =================================================================== --- source/blender/makesdna/DNA_material_types.h (revision 12209) +++ source/blender/makesdna/DNA_material_types.h (working copy) @@ -87,8 +87,10 @@ float strand_sta, strand_end, strand_ease; float sbias; /* shadow bias */ - float shad_alpha, padf; /* in use for irregular shadowbuffer */ + float shad_alpha; /* in use for irregular shadowbuffer */ + short index, pad; + /* for buttons and render*/ char rgbsel, texact, pr_type, use_nodes; short pr_back, pr_lamp, septex, ml_flag; /* ml_flag is for disable base material */ @@ -236,6 +238,14 @@ #define MA_RAMP_VAL 14 #define MA_RAMP_COLOR 15 +/* booleans */ +#define MA_BOOL_AND 0 +#define MA_BOOL_OR 1 +#define MA_BOOL_NAND 2 +#define MA_BOOL_NOR 3 +#define MA_BOOL_XNOR 4 +#define MA_BOOL_XOR 5 + /* texco */ #define TEXCO_ORCO 1 #define TEXCO_REFL 2 Index: source/blender/makesdna/DNA_view3d_types.h =================================================================== --- source/blender/makesdna/DNA_view3d_types.h (revision 12209) +++ source/blender/makesdna/DNA_view3d_types.h (working copy) @@ -170,6 +170,7 @@ #define V3D_FLYMODE 2 #define V3D_DEPRECATED 4 /* V3D_TRANSFORM_SNAP, moved to a scene setting */ #define V3D_SOLID_TEX 8 +#define V3D_LOCK_3DCURSOR 16 /* View3D->around */ #define V3D_CENTER 0 Index: source/blender/include/BIF_resources.h =================================================================== --- source/blender/include/BIF_resources.h (revision 12209) +++ source/blender/include/BIF_resources.h (working copy) @@ -482,6 +482,7 @@ TH_GROUP, TH_GROUP_ACTIVE, TH_TRANSFORM, + TH_LAYER_COLOR_NE, TH_VERTEX, TH_VERTEX_SELECT, TH_VERTEX_SIZE, @@ -534,6 +535,7 @@ #define TH_SHADED 1 #define TH_ROUNDED 2 #define TH_OLDSKOOL 3 +#define TH_ROUNDSHADED 4 /* specific defines per space should have higher define values */ Index: source/blender/include/blendef.h =================================================================== --- source/blender/include/blendef.h (revision 12209) +++ source/blender/include/blendef.h (working copy) @@ -428,7 +428,7 @@ #define B_AUTOFGON 32 #define B_KNIFE 0x80 #define B_PERCENTSUBD 0x40 -#define B_MESH_X_MIRROR 0x100 +#define B_MESH_MIRROR 0x100 #define B_JOINTRIA_UV 0x200 #define B_JOINTRIA_VCOL 0X400 #define B_JOINTRIA_SHARP 0X800 @@ -439,6 +439,11 @@ #define R_DISPLAYWIN 1 #define R_DISPLAYSCREEN 2 +/* mirror axes */ +#define MIRROR_X 0 +#define MIRROR_Y 1 +#define MIRROR_Z 2 + /* Gvp.flag and Gwp.flag */ #define VP_COLINDEX 1 #define VP_AREA 2 Index: source/blender/include/BSE_view.h =================================================================== --- source/blender/include/BSE_view.h (revision 12209) +++ source/blender/include/BSE_view.h (working copy) @@ -76,6 +76,7 @@ void calctrackballvecfirst(struct rcti *area, short *mval, float *vec); void calctrackballvec(struct rcti *area, short *mval, float *vec); void viewmove(int mode); +void view_zoom_mouseloc(float dfac, short *mouseloc); int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize); void setwinmatrixview3d(int winx, int winy, struct rctf *rect); Index: source/blender/include/butspace.h =================================================================== --- source/blender/include/butspace.h (revision 12209) +++ source/blender/include/butspace.h (working copy) @@ -213,6 +213,9 @@ /* world buttons: buttons-preview update, and redraw 3dview */ #define B_WORLDPRV2 1224 +#define B_MTEXUP 1225 +#define B_MTEXDOWN 1226 + /* *********************** */ #define B_TEXBUTS 1400 Index: source/blender/include/BIF_meshtools.h =================================================================== --- source/blender/include/BIF_meshtools.h (revision 12209) +++ source/blender/include/BIF_meshtools.h (working copy) @@ -44,7 +44,8 @@ extern long mesh_octree_table(struct Object *ob, float *co, char mode); extern int mesh_get_x_mirror_vert(struct Object *ob, int index); -extern struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, float *co); +extern void setmirroredcoords(float *vec, float *co, int mirror); +extern struct EditVert *editmesh_get_mirror_vert(struct Object *ob, float *co, int mirror); #endif Index: source/blender/include/BIF_editmesh.h =================================================================== --- source/blender/include/BIF_editmesh.h (revision 12209) +++ source/blender/include/BIF_editmesh.h (working copy) @@ -134,9 +134,9 @@ extern int EM_check_backbuf(unsigned int index); extern void EM_free_backbuf(void); +extern void EM_selectmode_cycle(unsigned int direction); extern void EM_selectmode_menu(void); - extern void vertexnoise(void); extern void vertexsmooth(void); extern void righthandfaces(int select); Index: source/blender/include/BIF_interface.h =================================================================== --- source/blender/include/BIF_interface.h (revision 12209) +++ source/blender/include/BIF_interface.h (working copy) @@ -79,6 +79,7 @@ #define UI_BLOCK_NOSHADOW 64 #define UI_BLOCK_FRONTBUFFER 128 #define UI_BLOCK_NO_HILITE 256 +#define UI_BLOCK_TRANSPARENT 512 /* block->flag bits 12-15 are identical to but->flag bits */ @@ -178,7 +179,10 @@ void uiRoundBoxEmboss(float minx, float miny, float maxx, float maxy, float rad, int active); void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad); void uiSetRoundBox(int type); +int uiGetRoundBox(void); void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad); +void uiRoundRectFakeAA(float minx, float miny, float maxx, float maxy, float rad, float asp); +void uiTriangleFakeAA(float x1, float y1, float x2, float y2, float x3, float y3, float asp); void uiDrawMenuBox(float minx, float miny, float maxx, float maxy, short flag); void uiTextBoundsBlock(uiBlock *block, int addval); @@ -282,6 +286,8 @@ int uiButGetRetVal (uiBut *but); +void uiButSetCol (uiBut *but, int col); + void uiButSetFlag (uiBut *but, int flag); void uiButClearFlag (uiBut *but, int flag); @@ -328,4 +334,3 @@ void autocomplete_end(AutoComplete *autocpl, char *autoname); #endif /* BIF_INTERFACE_H */ - Index: source/blender/src/header_info.c =================================================================== --- source/blender/src/header_info.c (revision 12209) +++ source/blender/src/header_info.c (working copy) @@ -2048,21 +2048,27 @@ uiDefPulldownBut(block, info_filemenu, NULL, "File", xco, -1, xmax-3, 22, ""); xco+= xmax; +/* xmax= GetButStringLength("Add"); uiDefPulldownBut(block, info_addmenu, NULL, "Add", xco, -1, xmax-3, 22, ""); xco+= xmax; +*/ xmax= GetButStringLength("Timeline"); uiDefPulldownBut(block, info_timelinemenu, NULL, "Timeline", xco, -1, xmax-3, 22, ""); xco+= xmax; +/* xmax= GetButStringLength("Game"); uiDefPulldownBut(block, info_gamemenu, NULL, "Game", xco, -1, xmax-3, 22, ""); xco+= xmax; +*/ +/* xmax= GetButStringLength("Render"); uiDefPulldownBut(block, info_rendermenu, NULL, "Render", xco, -1, xmax-3, 22, ""); xco+= xmax; +*/ xmax= GetButStringLength("Help"); uiDefPulldownBut(block, info_helpmenu, NULL, "Help", xco, -1, xmax-3, 22, ""); Index: source/blender/src/interface_draw.c =================================================================== --- source/blender/src/interface_draw.c (revision 12209) +++ source/blender/src/interface_draw.c (working copy) @@ -181,6 +181,12 @@ } else height= ICON_HEIGHT; + + /* stretch icon to fit large buttons */ + if (but->y2 - but->y1 > ICON_HEIGHT+6) { + aspect /= (but->y2 - but->y1 - ICON_HEIGHT)/10.0; + height= (but->y2 - but->y1)*0.8; + } if(but->flag & UI_ICON_LEFT) { if (but->type==BUT_TOGDUAL && but->drawstr[0]) { @@ -420,6 +426,84 @@ /* END OUTER OUTLINE */ } +/* shaded round button */ +static void round_button_shaded(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag, int rad) +{ + float shadefac; + + /* colour shading */ + if (flag & UI_SELECT) { + shadefac = -0.05; + if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -40); + else BIF_ThemeColorShade(colorid, -30); + } else { + shadefac = 0.05; + if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, +30); + else BIF_ThemeColorShade(colorid, +20); + } + /* end colour shading */ + + + /* the shaded base */ + gl_round_box_shade(GL_POLYGON, x1, y1, x2, y2, rad, shadefac, -shadefac); + + /* outline */ + BIF_ThemeColorBlendShade(TH_BUT_OUTLINE, TH_BACK, 0.1, -40); + + uiRoundRectFakeAA(x1, y1, x2, y2, rad, asp); + /* end outline */ +} + +/* base thin button */ +static void round_button_thin(int colorid, float asp, float x1, float y1, float x2, float y2, int flag, float rad) +{ + /* colour shading */ + if(flag & UI_SELECT) { + if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -35); + else BIF_ThemeColorShade(colorid, -25); + } else { + if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, +20); + else BIF_ThemeColorShade(colorid, 0); + } + /* end colour shading */ + + + /*the solid base */ + gl_round_box(GL_POLYGON, x1, y1, x2, y2, rad); + + /* outline */ + BIF_ThemeColorBlendShade(TH_BUT_OUTLINE, TH_BACK, 0.1, -26); + + uiRoundRectFakeAA(x1, y1, x2, y2, rad, asp); + /* end outline */ +} + + + +/* base round flat button */ +static void round_button_flat(int colorid, float asp, float x1, float y1, float x2, float y2, int flag, float rad) +{ + /* colour shading */ + if(flag & UI_SELECT) { + if (flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -20); + else BIF_ThemeColorShade(colorid, -45); + } + else { + if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, 35); + else BIF_ThemeColorShade(colorid, 25); + } + /* end colour shading */ + + /* the solid base */ + gl_round_box(GL_POLYGON, x1, y1, x2, y2, rad); + + /* outline */ + BIF_ThemeColorBlendShade(TH_BUT_OUTLINE, TH_BACK, 0.1, -32); + + uiRoundRectFakeAA(x1, y1, x2, y2, rad, asp); + /* end outline */ +} + /* small side double arrow for iconrow */ static void ui_default_iconrow_arrows(float x1, float y1, float x2, float y2) { @@ -444,88 +528,615 @@ } /* side double arrow for menu */ -static void ui_default_menu_arrows(float x1, float y1, float x2, float y2) +static void ui_default_menu_arrows(float x1, float y1, float x2, float y2, float asp) { - glEnable( GL_POLYGON_SMOOTH ); - glEnable( GL_BLEND ); + /* 'point' first, then two base vertices */ + uiTriangleFakeAA(x2-9, (y2-(y2-y1)/2)+6, + x2-6, (y2-(y2-y1)/2)+2, + x2-11, (y2-(y2-y1)/2)+2, + asp); - glShadeModel(GL_FLAT); - glBegin(GL_TRIANGLES); - glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+1); - glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2)+1); - glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2)+4); - glEnd(); - - glBegin(GL_TRIANGLES); - glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -1); - glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2) -1); - glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2) -4); - glEnd(); - - glDisable( GL_BLEND ); - glDisable( GL_POLYGON_SMOOTH ); + uiTriangleFakeAA(x2-8, (y2-(y2-y1)/2)-6, + x2-6, (y2-(y2-y1)/2)-2, + x2-11, (y2-(y2-y1)/2)-2, + asp); } /* left/right arrows for number fields */ -static void ui_default_num_arrows(float x1, float y1, float x2, float y2) +static void ui_default_num_arrows(float x1, float y1, float x2, float y2, float asp) { if( x2-x1 > 25) { // 25 is a bit arbitrary, but small buttons cant have arrows - glEnable( GL_POLYGON_SMOOTH ); - glEnable( GL_BLEND ); - - glShadeModel(GL_FLAT); - glBegin(GL_TRIANGLES); - - glVertex2f((short)x1+5,(short)(y2-(y2-y1)/2)); - glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)+4); - glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)-4); - glEnd(); + /* 'point' first, then two base vertices */ + uiTriangleFakeAA(x1+4, y2-(y2-y1)/2, + x1+9, y2-(y2-y1)/2+3, + x1+9, y2-(y2-y1)/2-3, + asp); + + uiTriangleFakeAA(x2-4, y2-(y2-y1)/2, + x2-9, y2-(y2-y1)/2+3, + x2-9, y2-(y2-y1)/2-3, + asp); + } +} - /* right */ - glShadeModel(GL_FLAT); - glBegin(GL_TRIANGLES); +/* changing +/- or black/white for TOG3 buts */ +static void ui_tog3_invert(float x1, float y1, float x2, float y2, int seltype, int theme) +{ + short alpha = 30; + + if (theme == TH_ROUNDSHADED) { + if (seltype == 0) { + BIF_ThemeColorShade(TH_BUT_SETTING, -120); + + glEnable( GL_LINE_SMOOTH ); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glLineWidth(1.0); + + fdrawline(x1+10, (y1+(y2-y1)/2+4), x1+10, (y1+(y2-y1)/2)-4); + + fdrawline(x1+6, (y1+(y2-y1)/2), x1+14, (y1+(y2-y1)/2)); + + glLineWidth(1.0); + glDisable( GL_BLEND ); + glDisable( GL_LINE_SMOOTH ); + } else { + BIF_ThemeColorShade(TH_BUT_SETTING, -120); + + glEnable( GL_LINE_SMOOTH ); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glLineWidth(1.0); + + fdrawline(x1+6, (y1+(y2-y1)/2), x1+14, (y1+(y2-y1)/2)); + + glLineWidth(1.0); + glDisable( GL_BLEND ); + glDisable( GL_LINE_SMOOTH ); + + } + } else { + if (seltype == 0) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, alpha); + glRectf(x2-6, y1, x2, (y1+(y2-y1)/2)); + + glColor4ub(255, 255, 255, alpha); + glRectf(x2-6, (y1+(y2-y1)/2), x2, y2); + + glDisable(GL_BLEND); + } else { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + glColor4ub(255, 255, 255, alpha); + glRectf(x2-6, y1, x2, (y1+(y2-y1)/2)); + + glColor4ub(0, 0, 0, alpha); + glRectf(x2-6, (y1+(y2-y1)/2), x2, y2); + + glDisable(GL_BLEND); + } + } +} - glVertex2f((short)x2-5,(short)(y2-(y2-y1)/2)); - glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)-4); - glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)+4); - glEnd(); - - glDisable( GL_BLEND ); - glDisable( GL_POLYGON_SMOOTH ); +/* roundshaded button/popup menu/iconrow drawing code */ +static void ui_roundshaded_button(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + float rad, maxrad; + int align= (flag & UI_BUT_ALIGN); + int round_align_fix= 0; + + /* rounded corners */ + if ((type == MENU) || (type == ICONROW) || (type == ICONTEXTROW)) maxrad = 4.0; + else maxrad= 10.0; + + rad= (y2-y1)/2.0; + if (rad>(x2-x1)/2) rad = (x2-x1)/2; + if (maxrad) { + if (rad > maxrad) rad = maxrad; } + /* end rounded corners */ + + /* alignment */ + if(align) { + switch(align) { + case UI_BUT_ALIGN_TOP: + uiSetRoundBox(12); + round_align_fix= 4; + break; + case UI_BUT_ALIGN_DOWN: + uiSetRoundBox(3); + round_align_fix= 2; + break; + case UI_BUT_ALIGN_LEFT: + uiSetRoundBox(6); + round_align_fix= 6; + break; + case UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(9); + round_align_fix= 9; + break; + + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(1); + round_align_fix= 0; + break; + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT: + uiSetRoundBox(2); + round_align_fix= 2; + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(8); + round_align_fix= 0; + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT: + uiSetRoundBox(4); + round_align_fix= 4; + break; + + default: + uiSetRoundBox(0); + round_align_fix= 0; + break; + } + } + else { + uiSetRoundBox(15); + if (x2 - x1 > 19) { + round_align_fix= 6; + } else { + round_align_fix= 15; + } + } + /* end alignment */ + + + /* draw the base button */ + round_button_shaded(type, colorid, asp, x1, y1, x2, y2, flag, rad); + + + /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */ + switch(type) { + case ICONROW: + case ICONTEXTROW: + /* iconrow darkened area */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, 30); + + uiSetRoundBox(6); + round_align_fix= 6; + gl_round_box(GL_POLYGON, x2-9, y1, x2, y2, rad); + + glDisable(GL_BLEND); + /* end iconrow darkened area */ + + /* iconrow double arrow */ + if(flag & UI_SELECT) { + BIF_ThemeColorShade(colorid, -80); + } else { + BIF_ThemeColorShade(colorid, -45); + } + ui_default_iconrow_arrows(x1, y1, x2, y2); + /* end iconrow double arrow */ + break; + case MENU: + /* menu darkened area */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, 25); + + uiSetRoundBox(round_align_fix); + gl_round_box(GL_POLYGON, x2-19, y1, x2, y2, rad); + + glDisable(GL_BLEND); + /* end menu darkened area */ + + /* menu double arrow */ + if(flag & UI_SELECT) { + BIF_ThemeColorShade(colorid, -90); + } else { + BIF_ThemeColorShade(colorid, -60); + } + ui_default_menu_arrows(x1, y1, x2, y2, asp); + /* end menu double arrow */ + break; + } } -/* changing black/white for TOG3 buts */ -static void ui_tog3_invert(float x1, float y1, float x2, float y2, int seltype) +/* toggle (checkbox) drawing code */ +static void ui_roundshaded_thin(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) { - short alpha = 30; + float rad, maxrad=10.0; + int align= (flag & UI_BUT_ALIGN); - if (seltype == 0) { - glEnable(GL_BLEND); + /* rounded corners */ + rad= (y2-y1)/2.0; + if (rad>(x2-x1)/2) rad = (x2-x1)/2; + if (maxrad) { + if (rad > maxrad) rad = maxrad; + } + /* end rounded corners */ + + /* alignment */ + if(align) { + switch(align) { + case UI_BUT_ALIGN_TOP: + uiSetRoundBox(12); + break; + case UI_BUT_ALIGN_DOWN: + uiSetRoundBox(3); + break; + case UI_BUT_ALIGN_LEFT: + uiSetRoundBox(6); + break; + case UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(9); + break; + + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(1); + break; + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT: + uiSetRoundBox(2); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(8); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT: + uiSetRoundBox(4); + break; + + default: + uiSetRoundBox(0); + break; + } + } + else { + uiSetRoundBox(15); + } + /* end alignment */ + + /* draw the base button */ + round_button_thin(colorid, asp, x1, y1, x2, y2, flag, rad); + + /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */ + switch(type) { + case TOG: + case TOGN: + case TOG3: + if (!(flag & UI_HAS_ICON)) { + /* check to see that there's room for the check mark + * draw a check mark, or if it's a TOG3, draw a + or - */ + if (x2 - x1 > 20) { + uiSetRoundBox(15); + BIF_ThemeColorShade(colorid, -5); + gl_round_box_shade(GL_POLYGON, x1+4, (y1+(y2-y1)/2)-5, x1+14, (y1+(y2-y1)/2)+4, 2, -0.04, 0.03); + + BIF_ThemeColorShade(colorid, -20); + gl_round_box(GL_LINE_LOOP, x1+4, (y1+(y2-y1)/2)-5, x1+14, (y1+(y2-y1)/2)+4, 2); + + /* TOG3 is handled with ui_tog3_invert() + * remember to update checkmark drawing there too*/ + if((flag & UI_SELECT) && (type != TOG3)) { + BIF_ThemeColorShade(colorid, -120); + + glEnable( GL_LINE_SMOOTH ); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glLineWidth(1.5); + + glBegin( GL_LINE_STRIP ); + glVertex2f(x1+5, (y1+(y2-y1)/2)-1); + glVertex2f(x1+8, (y1+(y2-y1)/2)-4); + glVertex2f(x1+13, (y1+(y2-y1)/2)+5); + glEnd(); + + glLineWidth(1.0); + glDisable( GL_BLEND ); + glDisable( GL_LINE_SMOOTH ); + } + /* draw a dot: alternate, for layers etc. */ + } else if(flag & UI_SELECT) { + uiSetRoundBox(15); + BIF_ThemeColorShade(colorid, -60); + + glPushMatrix(); + glTranslatef((x1+(x2-x1)/2), (y1+(y2-y1)/2), 0.0); + + /* circle */ + glutil_draw_filled_arc(0.0, M_PI*2.0, 2, 16); + + glEnable( GL_LINE_SMOOTH ); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + /* smooth outline */ + glutil_draw_lined_arc(0.0, M_PI*2.0, 2, 16); + + glDisable( GL_BLEND ); + glDisable( GL_LINE_SMOOTH ); + + glPopMatrix(); + } + } + break; + } +} + +/* roundshaded number/text field drawing code */ +static void ui_roundshaded_flat(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +{ + float rad, maxrad=10.0; + int align= (flag & UI_BUT_ALIGN); + + /* rounded corners */ + rad= (y2-y1)/2.0; + if(rad>(x2-x1)/2) rad = (x2-x1)/2; + if (maxrad) { + if (rad > maxrad) rad = maxrad; + } + /* end rounded corners */ + + /* alignment */ + if(align) { + switch(align) { + case UI_BUT_ALIGN_TOP: + uiSetRoundBox(12); + break; + case UI_BUT_ALIGN_DOWN: + uiSetRoundBox(3); + break; + case UI_BUT_ALIGN_LEFT: + uiSetRoundBox(6); + break; + case UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(9); + break; + + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(1); + break; + case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT: + uiSetRoundBox(2); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT: + uiSetRoundBox(8); + break; + case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT: + uiSetRoundBox(4); + break; + + default: + uiSetRoundBox(0); + break; + } + } + else { + uiSetRoundBox(15); + } + + round_button_flat(colorid, asp, x1, y1, x2, y2, flag, rad); + + /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */ + switch(type) { + case NUM: + /* side arrows */ + if(flag & UI_SELECT)