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) { + if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -60); + else BIF_ThemeColorShade(colorid, -60); + } else { + if(flag & UI_ACTIVE) BIF_ThemeColorShade(colorid, -30); + else BIF_ThemeColorShade(colorid, -10); + } + + ui_default_num_arrows(x1, y1, x2, y2, asp); + /* end side arrows */ + } +} + +/* nice AA filled circle. borrowed from drawnode.c. there should be a generic function + for drawing circles */ +static void circle_draw(float x, float y, float size) +{ + /* 16 values of sin function */ + static float si[16] = { + 0.00000000, 0.39435585,0.72479278,0.93775213, + 0.99871650,0.89780453,0.65137248,0.29936312, + -0.10116832,-0.48530196,-0.79077573,-0.96807711, + -0.98846832,-0.84864425,-0.57126821,-0.20129852 + }; + /* 16 values of cos function */ + static float co[16] ={ + 1.00000000,0.91895781,0.68896691,0.34730525, + -0.05064916,-0.44039415,-0.75875812,-0.95413925, + -0.99486932,-0.87434661,-0.61210598,-0.25065253, + 0.15142777,0.52896401,0.82076344,0.97952994, + }; + int a; + + glColor3ub(160, 160, 160); /* should be a parameter */ + + glBegin(GL_POLYGON); + for(a=0; a<16; a++) + glVertex2f(x+size*si[a], y+size*co[a]); + glEnd(); +} + +/* roundshaded slider drawing */ +static void ui_roundshaded_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag) +{ + float rad, origrad; + float ofsy = 2.0, ofsy1, ofsy2; + float extx = 0; /* extension */ + float ymid; + int round, origround; + int origcol; + int i; + + ymid= (y1+y2)/2.0; + + /* correct the fac to use 'packed sliders */ + fac /= (x2 - x1); + x1 -= (x2-x1) + 5.0*aspect; + x2 += 5.0*aspect; + + ofsy *= aspect; + + fac *= (x2-x1); + + rad = ((y2 - y1)+(2*ofsy))/2; + + origround = round = uiGetRoundBox(); + origcol = colorid; + origrad = rad; + + /* nice background interior shadow */ + //if (!(flag & UI_SELECT)) gl_round_box_shade(GL_LINE_LOOP, x1, y1-ofsy, x2, y2+ofsy-1*aspect, rad, 0.05, 0); + + if (fac < 4) fac = 4; + + /* set up the movable slider */ + if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -95); + else BIF_ThemeColorShade(colorid, -35); + + if (fac < rad) { + /* if slider end is in the left end cap */ + round &= ~2; + round &= ~4; + uiSetRoundBox(round); - glColor4ub(0, 0, 0, alpha); - glRectf(x2-6, y1, x2, (y1+(y2-y1)/2)); + ofsy1 = ofsy2 = ofsy - ((rad - fac)/2.0*aspect); - glColor4ub(255, 255, 255, alpha); - glRectf(x2-6, (y1+(y2-y1)/2), x2, y2); + rad = fac; - glDisable(GL_BLEND); - } else { - glEnable(GL_BLEND); + /* for top and bottom button alignment */ + if (!(round & 1)) ofsy2 = 2.0*aspect; + if (!(round & 8)) ofsy1 = 2.0*aspect; - glColor4ub(255, 255, 255, alpha); - glRectf(x2-6, y1, x2, (y1+(y2-y1)/2)); + gl_round_box_shade(GL_POLYGON, x1, y1-ofsy1, x1+fac, y2+ofsy2, rad, 0.05, -0.05); - glColor4ub(0, 0, 0, alpha); - glRectf(x2-6, (y1+(y2-y1)/2), x2, y2); + } else if ( (fac >= rad) && (x1+fac < x2 - rad) ) { + /* if the slider is in the middle */ - glDisable(GL_BLEND); + round &= ~2; + round &= ~4; + uiSetRoundBox(round); + + gl_round_box_shade(GL_POLYGON, x1, y1-ofsy, x1+fac, y2+ofsy, rad, 0.05, -0.05); + + gl_round_box_shade(GL_LINE_LOOP, x1, y1-ofsy+1, x1+fac, y2+ofsy-1, rad, 0.11, 0.05); + + } else if (x1+fac >= x2-rad) { + /* if the slider is in the right end cap */ + + gl_round_box_shade(GL_POLYGON, x1, y1-ofsy, x2, y2+ofsy, rad, 0.05, -0.05); + + gl_round_box_shade(GL_LINE_LOOP, x1, y1-ofsy+1, x2, y2+ofsy-1, rad, 0.11, 0.05); + + /* tricky hack to trim off right end curve by drawing over it */ + extx = (x1 + fac) - (x2 - rad); /* width of extension bit */ + + //ofsy1 = ofsy2 = ofsy - (extx)/2.7; + + ofsy1 = ofsy2 = ofsy - ((x1 + fac) - (x2 - rad))/2.0*aspect; + + + rad -= extx+1; + + round &= ~1; + round &= ~8; + + /* for top and bottom button alignment */ + if (!(round & 2)) ofsy2 = 2.0*aspect; + if (!(round & 4)) ofsy1 = 2.0*aspect; + + uiSetRoundBox(round); + + if(flag & UI_SELECT) BIF_ThemeColorShade(origcol, -35); + else BIF_ThemeColorShade(origcol, -5); + + gl_round_box(GL_POLYGON, x1+fac, y1-ofsy1, x2, y2+ofsy2, rad); + } + + /* triangles */ + if(flag & UI_ACTIVE) { + + glShadeModel(GL_FLAT); + + /* left */ + if (fac > 6) { + if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -15); + else BIF_ThemeColorShade(colorid, 15); + + glBegin(GL_TRIANGLES); + + glVertex2f((short)x1+fac-7,(short)(y2-(y2-y1)/2)); + glVertex2f((short)x1+fac-4,(short)(y2-(y2-y1)/2)+4); + glVertex2f((short)x1+fac-4,(short)(y2-(y2-y1)/2)-4); + glEnd(); + } + + /* right */ + if(fac < (x2 - x1) - 6) { + if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -40); + else BIF_ThemeColorShade(colorid, -25); + + glBegin(GL_TRIANGLES); + + glVertex2f((short)x1+fac+8,(short)(y2-(y2-y1)/2)); + glVertex2f((short)x1+fac+3,(short)(y2-(y2-y1)/2)-4); + glVertex2f((short)x1+fac+3,(short)(y2-(y2-y1)/2)+4); + glEnd(); + } } + + /* circles */ + for(i=1; i<10; i++) + circle_draw(i*((x2-x1)/10)+x1, ymid, 3); /* it is safe to presume that x2 > x1? */ + + if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -55); + else BIF_ThemeColorShade(colorid, -25); + uiSetRoundBox(origround); + uiRoundRectFakeAA(x1, y1-2.0*aspect, x2, y2+2.0*aspect, origrad, aspect); + } +/* roundshaded theme callback */ +static void ui_draw_roundshaded(int type, int colorid, float aspect, float x1, float y1, float x2, float y2, int flag) +{ + + switch(type) { + case TOG: + case TOGN: + case TOG3: + case SLI: + case NUMSLI: + case HSVSLI: + ui_roundshaded_thin(type, colorid, aspect, x1, y1, x2, y2, flag); + break; + case TEX: + case IDPOIN: + case NUM: + ui_roundshaded_flat(type, colorid, aspect, x1, y1, x2, y2, flag); + break; + case ICONROW: + case ICONTEXTROW: + case MENU: + default: + ui_roundshaded_button(type, colorid, aspect, x1, y1, x2, y2, flag); + } + +} + /* button/popup menu/iconrow drawing code */ -static void ui_default_button(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +static void ui_shaded_button(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) { int align= (flag & UI_BUT_ALIGN); @@ -696,7 +1307,7 @@ /* MENU DOUBLE-ARROW */ M_DARK; - ui_default_menu_arrows(x1, y1, x2, y2); + ui_default_menu_arrows(x1, y1, x2, y2, asp); /* MENU DOUBLE-ARROW */ break; } @@ -704,7 +1315,7 @@ /* number/text field drawing code */ -static void ui_default_flat(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) +static void ui_shaded_flat(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag) { int align= (flag & UI_BUT_ALIGN); @@ -859,12 +1470,12 @@ else M_LGREY; } - ui_default_num_arrows(x1, y1, x2, y2); + ui_default_num_arrows(x1, y1, x2, y2, asp); /* END SIDE ARROWS */ } } -static void ui_default_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag) +static void ui_shaded_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag) { float ymid, yc; @@ -892,8 +1503,7 @@ if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, +15); else BIF_ThemeColorShade(TH_BUT_NUM, +45); fdrawline(x1+1, ymid-yc, x2, ymid-yc); - - + /* the movable slider */ if(flag & UI_SELECT) BIF_ThemeColorShade(TH_BUT_NUM, +80); else BIF_ThemeColorShade(TH_BUT_NUM, -45); @@ -939,20 +1549,20 @@ } /* default theme callback */ -static void ui_draw_default(int type, int colorid, float aspect, float x1, float y1, float x2, float y2, int flag) +static void ui_draw_shaded(int type, int colorid, float aspect, float x1, float y1, float x2, float y2, int flag) { switch(type) { case TEX: case IDPOIN: case NUM: - ui_default_flat(type, colorid, aspect, x1, y1, x2, y2, flag); + ui_shaded_flat(type, colorid, aspect, x1, y1, x2, y2, flag); break; case ICONROW: case ICONTEXTROW: case MENU: default: - ui_default_button(type, colorid, aspect, x1, y1, x2, y2, flag); + ui_shaded_button(type, colorid, aspect, x1, y1, x2, y2, flag); } } @@ -1031,7 +1641,7 @@ case NUM: if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60); else BIF_ThemeColorShade(colorid, -30); - ui_default_num_arrows(x1, y1, x2, y2); + ui_default_num_arrows(x1, y1, x2, y2, asp); break; case ICONROW: @@ -1050,7 +1660,7 @@ glRectf(x2-17, y1+asp, x2-asp, y2-asp); BIF_ThemeColorShade(colorid, -50); - ui_default_menu_arrows(x1, y1, x2, y2); + ui_default_menu_arrows(x1, y1, x2, y2, asp); break; } @@ -1180,7 +1790,7 @@ switch(type) { case NUM: BIF_ThemeColorShade(colorid, curshade-60); - ui_default_num_arrows(x1, y1, x2, y2); + ui_default_num_arrows(x1, y1, x2, y2, asp); break; case ICONROW: @@ -1192,7 +1802,7 @@ case MENU: case BLOCK: BIF_ThemeColorShade(colorid, curshade-60); - ui_default_menu_arrows(x1, y1, x2, y2); + ui_default_menu_arrows(x1, y1, x2, y2, asp); break; } } @@ -1290,7 +1900,7 @@ case NUM: if(flag & UI_SELECT) BIF_ThemeColorShade(colorid, -60); else BIF_ThemeColorShade(colorid, -30); - ui_default_num_arrows(x1, y1, x2, y2); + ui_default_num_arrows(x1, y1, x2, y2, asp); break; case ICONROW: @@ -1310,14 +1920,13 @@ glRectf(x2-17, y1+asp, x2-asp, y2-asp); BIF_ThemeColorShade(colorid, -50); - ui_default_menu_arrows(x1, y1, x2, y2); + ui_default_menu_arrows(x1, y1, x2, y2, asp); break; } } - /* fac is the slider handle position between x1 and x2 */ static void ui_draw_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag) { @@ -1403,6 +2012,8 @@ char col[4]; BIF_GetThemeColor4ubv(TH_MENU_BACK, col); + if (flag & UI_BLOCK_TRANSPARENT) return; + if( (flag & UI_BLOCK_NOSHADOW)==0) { /* accumulated outline boxes to make shade not linear, is more pleasant */ ui_shadowbox(minx, miny, maxx, maxy, 6.0, (30*col[3])>>8); @@ -1480,6 +2091,7 @@ char *cpoin; short t, pos, ch; short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw; + int theme= BIF_GetThemeValue(TH_BUT_DRAWTYPE); /* check for button text label */ if (but->type == ICONTEXTROW) { @@ -1562,8 +2174,13 @@ else x= (but->x1+but->x2-but->strwidth+1)/2.0; } else { - if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0; - else x= (but->x1+but->x2-but->strwidth+1)/2.0; + if(but->flag & UI_TEXT_LEFT) { + x= but->x1+4.0; + } else if ((theme == TH_ROUNDSHADED) && ELEM3(but->type, TOG, TOGN, TOG3)) { + x= but->x1+18.0; /* offset for checkmark */ + } else { + x= (but->x1+but->x2-but->strwidth+1)/2.0; + } } /* tog3 button exception; draws with glColor! */ @@ -1577,7 +2194,7 @@ if( BTST( sp[1], but->bitnr )) tog3= 1; } - ui_tog3_invert(but->x1,but->y1,but->x2,but->y2, tog3); + ui_tog3_invert(but->x1,but->y1,but->x2,but->y2, tog3, theme); if (tog3) glColor3ub(255, 255, 0); } @@ -1604,15 +2221,7 @@ ui_rasterpos_safe(x, (but->y1+but->y2- 9.0)/2.0, but->aspect); if(but->type==IDPOIN) transopts= 0; // no translation, of course! else transopts= (U.transopts & USER_TR_BUTTONS); - - #ifdef INTERNATIONAL - if (but->type == FTPREVIEW) - FTF_DrawNewFontString (but->drawstr+but->ofs, FTF_INPUT_UTF8); - else - BIF_DrawString(but->font, but->drawstr+but->ofs, transopts); - #else BIF_DrawString(but->font, but->drawstr+but->ofs, transopts); - #endif /* part text right aligned */ if(cpoin) { @@ -1629,6 +2238,25 @@ } } +static void ui_draw_but_SEPR(uiBut *but) +{ + float mid; + mid = but->y1 + (but->y2 - but->y1)/2; + + glEnable(GL_BLEND); + + BIF_ThemeColor4(TH_MENU_ITEM); + glRectf(but->x1, but->y1, but->x2, but->y2); + + glColor4ub(0, 0, 0, 20); + fdrawline(but->x1, mid, but->x2, mid); + glColor4ub(255, 255, 255, 20); + fdrawline(but->x1, mid-1, but->x2, mid-1); + + glDisable(GL_BLEND); + +} + static void ui_draw_but_COL(uiBut *but) { float *fp; @@ -1649,8 +2277,10 @@ /* exception... hrms, but can't simply use the emboss callback for this now. */ /* this button type needs review, and nice integration with rest of API here */ - if(but->embossfunc == ui_draw_round) { + if(ELEM(but->embossfunc, ui_draw_round, ui_draw_roundshaded)) { char *cp= BIF_ThemeGetColorPtr(U.themes.first, 0, TH_CUSTOM); + + but->embossfunc = ui_draw_round; cp[0]= colr; cp[1]= colg; cp[2]= colb; but->flag &= ~UI_SELECT; but->embossfunc(but->type, TH_CUSTOM, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag); @@ -2240,9 +2870,7 @@ } /* the curve */ - BIF_ThemeColorBlend(TH_TEXT, TH_BUT_NEUTRAL, 0.35); - glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); + BIF_ThemeColor(TH_TEXT); glBegin(GL_LINE_STRIP); if(cuma->table==NULL) @@ -2271,8 +2899,6 @@ glVertex2f(fx, fy); } glEnd(); - glDisable(GL_LINE_SMOOTH); - glDisable(GL_BLEND); /* the points, use aspect to make them visible on edges */ cmp= cuma->curve; @@ -2323,6 +2949,8 @@ void ui_set_embossfunc(uiBut *but, int drawtype) { + int theme= BIF_GetThemeValue(TH_BUT_DRAWTYPE); + // this aded for evaluating textcolor for example but->dt= drawtype; @@ -2337,10 +2965,13 @@ else if(drawtype==UI_EMBOSSP) but->embossfunc= ui_draw_pulldown_item; else if(drawtype==UI_EMBOSSR) but->embossfunc= ui_draw_round; else { - int theme= BIF_GetThemeValue(TH_BUT_DRAWTYPE); switch(theme) { + case TH_ROUNDSHADED: + but->embossfunc= ui_draw_roundshaded; + but->sliderfunc= ui_roundshaded_slider; + break; case TH_ROUNDED: but->embossfunc= ui_draw_round; break; @@ -2352,8 +2983,8 @@ break; case TH_SHADED: default: - but->embossfunc= ui_draw_default; - but->sliderfunc= ui_default_slider; + but->embossfunc= ui_draw_shaded; + but->sliderfunc= ui_shaded_slider; break; } } @@ -2375,9 +3006,7 @@ case NUMSLI: case HSVSLI: - but->embossfunc(but->type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag); - ui_draw_text_icon(but); x1= (but->x1+but->x2)/2; x2= but->x2 - 5.0*but->aspect; @@ -2388,9 +3017,12 @@ fac= (value-but->min)*(x2-x1)/(but->max - but->min); but->sliderfunc(but->themecol, fac, but->aspect, x1, y1, x2, y2, but->flag); + + ui_draw_text_icon(but); break; case SEPR: + ui_draw_but_SEPR(but); // only background break; Index: source/blender/src/editview.c =================================================================== --- source/blender/src/editview.c (revision 12209) +++ source/blender/src/editview.c (working copy) @@ -1090,6 +1090,7 @@ VECCOPY(fp, oldcurs); } + if(G.vd->flag2&V3D_LOCK_3DCURSOR) VECCOPY(fp, oldcurs); } void deselectall(void) /* is toggle */ Index: source/blender/src/editarmature.c =================================================================== --- source/blender/src/editarmature.c (revision 12209) +++ source/blender/src/editarmature.c (working copy) @@ -55,6 +55,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "DNA_userdef_types.h" #include "DNA_view3d_types.h" #include "DNA_modifier_types.h" @@ -1446,7 +1447,7 @@ return bone; } -static void add_primitive_bone(Object *ob) +static void add_primitive_bone(Object *ob, short newob) { float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3]; EditBone *bone; @@ -1457,7 +1458,9 @@ Mat4Invert(G.obedit->imat, G.obedit->obmat); Mat4MulVecfl(G.obedit->imat, curs); - Mat3CpyMat4(obmat, G.vd->viewmat); + if ( !(newob) || U.flag & USER_ADDOB_ALIGN_EDIT) Mat3CpyMat4(obmat, G.vd->viewmat); + else Mat3One(obmat); + Mat3CpyMat4(viewmat, G.obedit->obmat); Mat3MulMat3(totmat, obmat, viewmat); Mat3Inv(imat, totmat); @@ -1474,6 +1477,8 @@ void add_primitiveArmature(int type) { + short newob=0; + if(G.scene->id.lib) return; /* this function also comes from an info window */ @@ -1495,13 +1500,18 @@ make_editArmature(); setcursor_space(SPACE_VIEW3D, CURSOR_EDIT); + newob=1; } /* no primitive support yet */ - add_primitive_bone(G.obedit); + add_primitive_bone(G.obedit, newob); countall(); // flushes selection! + if ( (newob) && !(U.flag & USER_ADDOB_ALIGN_EDIT)) { + exit_editmode(2); + } + allqueue(REDRAWALL, 0); BIF_undo_push("Add primitive"); } Index: source/blender/src/editnode.c =================================================================== --- source/blender/src/editnode.c (revision 12209) +++ source/blender/src/editnode.c (working copy) @@ -504,6 +504,23 @@ } } +/* returns 1 if one was found */ +static int node_get_active_viewer(SpaceNode *snode, bNode **actnode) +{ + bNode *node; + + for(node= snode->nodetree->nodes.first; node; node= node->next) { + if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if(node->flag & NODE_DO_OUTPUT) { + *actnode= node; + return 1; + } + } + } + + return 0; +} + void snode_make_group_editable(SpaceNode *snode, bNode *gnode) { bNode *node; @@ -830,6 +847,23 @@ window_set_cursor(win, oldcursor); } +static void reset_sel_socket(SpaceNode *snode, int in_out) +{ + bNode *node; + bNodeSocket *sock; + + for(node= snode->edittree->nodes.first; node; node= node->next) { + if(in_out & SOCK_IN) { + for(sock= node->inputs.first; sock; sock= sock->next) + if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL; + } + if(in_out & SOCK_OUT) { + for(sock= node->outputs.first; sock; sock= sock->next) + if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL; + } + } +} + /* checks mouse position, and returns found node/socket */ /* type is SOCK_IN and/or SOCK_OUT */ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out) @@ -1351,6 +1385,43 @@ return 0; } +/* in_out can be used to limit socket type to input or output */ +static int mouse_over_socket(SpaceNode *snode, int in_out, bNode **socknode, bNodeSocket **sockover) { + bNode *node; + bNodeSocket *sock, *tsock, *sockinsel= NULL, *sockoutsel= NULL; + float mx, my; + short mval[2]; + + if(snode->edittree==NULL) return 0; + + getmouseco_areawin(mval); + areamouseco_to_ipoco(G.v2d, mval, &mx, &my); + + for(node= snode->edittree->nodes.first; node; node= node->next) { + for(sock= node->inputs.first; sock; sock= sock->next) { + if(sock->flag & SELECT) sockinsel= sock; + } + for(sock= node->outputs.first; sock; sock= sock->next) { + if(sock->flag & SELECT) sockoutsel= sock; + } + } + + if(find_indicated_socket(snode, &node, &tsock, in_out)) { + if(tsock==sockinsel) { + *socknode= node; + *sockover= tsock; + return SOCK_IN; + } + if(tsock==sockoutsel) { + *socknode= node; + *sockover= tsock; + return SOCK_OUT; + } + } + + return 0; +} + static int node_socket_hilights(SpaceNode *snode, int in_out) { bNode *node; @@ -2091,8 +2162,12 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt) { SpaceNode *snode= spacedata; + bNode *actnode, *socknode; + bNodeSocket *actsock; + bNodeLink *remlink; unsigned short event= evt->event; - short val= evt->val, doredraw=0, fromlib= 0; + short val= evt->val, doredraw=0, doendchecks=0, fromlib= 0; + char *undostr; if(sa->win==0) return; if(snode->nodetree==NULL) return; @@ -2118,7 +2193,29 @@ break; case RIGHTMOUSE: - if(!node_mouse_select(snode, event)) + if(find_indicated_socket(snode, &actnode, &actsock, SOCK_IN)) { + if(actsock->flag & SOCK_SEL) { + snode->edittree->selin= NULL; + actsock->flag&= ~SOCK_SEL; + } + else { + snode->edittree->selin= actsock; + reset_sel_socket(snode, SOCK_IN); + actsock->flag|= SOCK_SEL; + } + } + else if(find_indicated_socket(snode, &actnode, &actsock, SOCK_OUT)) { + if(actsock->flag & SOCK_SEL) { + snode->edittree->selout= NULL; + actsock->flag&= ~SOCK_SEL; + } + else { + snode->edittree->selout= actsock; + reset_sel_socket(snode, SOCK_OUT); + actsock->flag|= SOCK_SEL; + } + } + else if(!node_mouse_select(snode, event)) toolbox_n(); break; @@ -2194,6 +2291,17 @@ case EKEY: snode_handle_recalc(snode); break; + case FKEY: + if(snode->edittree->selin && snode->edittree->selout) { + remlink= nodeFindLink(snode->edittree, snode->edittree->selout, snode->edittree->selin); + + if(remlink) nodeRemLink(snode->edittree, remlink); + else nodeAddLink2(snode->edittree, snode->edittree->selout, snode->edittree->selin); + + undostr= "Toggle Link"; + doendchecks= 1; + } + break; case GKEY: if(fromlib) fromlib= -1; else { @@ -2225,6 +2333,20 @@ if(okee("Read saved Render Layers")) node_read_renderlayers(snode); break; + case VKEY: + if(mouse_over_socket(snode, SOCK_OUT, &socknode, &actsock)) { + if(node_get_active_viewer(snode, &actnode)) { + /* remove old connections of active viewer node. could handle better? */ + nodeUnlinkNode(snode->edittree, actnode); + + /* connect output socket to input of active viewer node */ + nodeAddLink(snode->edittree, socknode, actsock, actnode, actnode->inputs.first); + + undostr= "Connect to Active Viewer"; + doendchecks= 1; + } + } + break; case DELKEY: case XKEY: if(fromlib) fromlib= -1; @@ -2239,6 +2361,16 @@ scrarea_queue_winredraw(sa); if(doredraw==2) scrarea_queue_headredraw(sa); + if(doendchecks) { + node_get_active_viewer(snode, &actnode); + NodeTagChanged(snode->edittree, actnode); /* check for viewer */ + ntreeSolveOrder(snode->edittree); + snode_verify_groups(snode); + snode_handle_recalc(snode); + + allqueue(REDRAWNODE, 0); + BIF_undo_push(undostr); + } } Index: source/blender/src/buttons_editing.c =================================================================== --- source/blender/src/buttons_editing.c (revision 12209) +++ source/blender/src/buttons_editing.c (working copy) @@ -1603,6 +1603,8 @@ height = 26; } else if (md->type==eModifierType_Boolean) { height = 48; + } else if (md->type==eModifierType_Lathe) { + height = 105; } else if (md->type==eModifierType_Array) { height = 211; } @@ -1942,6 +1944,27 @@ BooleanModifierData *bmd = (BooleanModifierData*) md; uiDefButI(block, MENU, B_MODIFIER_RECALC, "Operation%t|Intersect%x0|Union%x1|Difference%x2", lx,(cy-=19),buttonWidth,19, &bmd->operation, 0.0, 1.0, 0, 0, "Boolean operation to perform"); uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation"); + } else if (md->type==eModifierType_Lathe) { + LatheModifierData *ltmd = (LatheModifierData*) md; + uiBlockBeginAlign(block); + uiDefButI(block, NUM, B_MODIFIER_RECALC, "Steps:", lx, (cy-=19), buttonWidth,19, <md->steps, 3, 1024, 100, 0, "Lathe steps."); + uiDefButI(block, NUM, B_MODIFIER_RECALC, "Render Steps:", lx, (cy-=19), buttonWidth,19, <md->renderSteps, 3, 1024, 100, 0, "Lathe steps when rendering."); + uiDefButF(block, NUM, B_MODIFIER_RECALC, "Degr:", lx, (cy-=19), buttonWidth,19, <md->deg, -360.0, 360.0, 10, 10, ""); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButS(block, ROW,B_MODIFIER_RECALC,"X", lx, (cy-=19), buttonWidth/6,19, <md->axis, 12.0, 0, 0, 0, "The axis that the slices face"); + uiDefButS(block, ROW,B_MODIFIER_RECALC,"Y", (lx+buttonWidth/6), cy, buttonWidth/6,19, <md->axis, 12.0, 1, 0, 0, "The axis that the slices face"); + uiDefButS(block, ROW,B_MODIFIER_RECALC,"Z", (lx+2*buttonWidth/6), cy, buttonWidth/6,19, <md->axis, 12.0, 2, 0, 0, "The axis that the slices face"); + uiBlockEndAlign(block); + + uiDefButBitS(block, TOG, MOD_LATHE_NORMAL_FLIP, B_MODIFIER_RECALC, "Flip Faces", (lx+buttonWidth/2),cy,buttonWidth/2,19, <md->flag, 0, 0, 0, 0, "Enable X axis mirror"); + + but = uiDefIDPoinBut(block, test_obpoin_but, ID_OB, + B_CHANGEDEP, "Ob: ", + lx,(cy-=19), buttonWidth, 19, + <md->ob_axis, + "Control object: slice the axis of this object"); } else if (md->type==eModifierType_Array) { ArrayModifierData *amd = (ArrayModifierData*) md; float range = 10000; @@ -4398,8 +4421,12 @@ uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, G_ALLEDGES, 0, "All Edges", 1125, 22,150,19, &G.f, 0, 0, 0, 0, "Displays all edges in object mode without optimization"); - uiDefButBitS(block, TOG, B_MESH_X_MIRROR, B_DIFF, "X-axis mirror",1125,0,150,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "While using transforms, mirrors the transformation"); + uiDefButBitI(block, TOG, G_ALLEDGES, 0, "All Edges", 1125, 44,150,19, &G.f, 0, 0, 0, 0, "Displays all edges in object mode without optimization"); + + uiDefButBitS(block, TOG, B_MESH_MIRROR, B_DIFF, "Mirror",1125,22,150,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Enable mirrored editing"); + uiDefButS(block, ROW, B_DIFF, "X", 1125, 0, 50, 19, &G.scene->toolsettings->mirror, 0, MIRROR_X, 0, 0, "Enable X-axis mirrored editing"); + uiDefButS(block, ROW, B_DIFF, "Y", 1175, 0, 50, 19, &G.scene->toolsettings->mirror, 0, MIRROR_Y, 0, 0, "Enable Y-axis mirrored editing"); + uiDefButS(block, ROW, B_DIFF, "Z", 1225, 0, 50, 19, &G.scene->toolsettings->mirror, 0, MIRROR_Z, 0, 0, "Enable Z-axis mirrored editing"); uiBlockEndAlign(block); } Index: source/blender/src/outliner.c =================================================================== --- source/blender/src/outliner.c (revision 12209) +++ source/blender/src/outliner.c (working copy) @@ -447,6 +447,10 @@ te->name= "Index Object"; te->directdata= &srl->passflag; + te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_INDEXMAT); + te->name= "Index Material"; + te->directdata= &srl->passflag; + te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_RGBA); te->name= "Color"; te->directdata= &srl->passflag; Index: source/blender/src/transform_conversions.c =================================================================== --- source/blender/src/transform_conversions.c (revision 12209) +++ source/blender/src/transform_conversions.c (working copy) @@ -1652,7 +1652,7 @@ float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; int count=0, countsel=0, a, totleft; int propmode = t->flag & T_PROP_EDIT; - int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR); + int mirror = G.scene->toolsettings->mirror, negmirror= 0; // transform now requires awareness for select mode, so we tag the f1 flags in verts if(G.scene->selectmode & SCE_SELECT_VERTEX) { @@ -1735,6 +1735,7 @@ /* find out which half we do */ if(mirror) { +/* for (eve=em->verts.first; eve; eve=eve->next) { if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) { if(eve->co[0]<0.0f) @@ -1742,8 +1743,18 @@ break; } } +*/ + for (eve=em->verts.first; eve; eve=eve->next) { + if(eve->h==0 && eve->f1 && eve->co[mirror]!=0.0f) { + if(eve->co[mirror]<0.0f) + negmirror= 1; + break; + } + } } + + for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) { if(eve->h==0) { if(propmode || eve->f1) { @@ -1791,9 +1802,11 @@ } /* Mirror? */ - if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) { - EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */ - if(vmir!=eve) tob->tdmir= vmir; + if(mirror >= 0) { + if((!negmirror && tob->iloc[mirror]>0.0f) || (negmirror && tob->iloc[mirror]<0.0f)) { + EditVert *vmir= editmesh_get_mirror_vert(G.obedit, tob->iloc, mirror); /* initializes octree on first call */ + if(vmir!=eve) tob->tdmir= vmir; + } } tob++; } Index: source/blender/src/meshtools.c =================================================================== --- source/blender/src/meshtools.c (revision 12209) +++ source/blender/src/meshtools.c (working copy) @@ -805,15 +805,23 @@ return mesh_octree_table(ob, vec, 'u'); } -EditVert *editmesh_get_x_mirror_vert(Object *ob, float *co) +void setmirroredcoords(float *vec, float *co, int mirror) { + int i; + + for(i=0; i<3; i++) { + if(i==mirror) vec[i]= -co[i]; + else vec[i]= co[i]; + } +} + +EditVert *editmesh_get_mirror_vert(Object *ob, float *co, int mirror) +{ float vec[3]; long poinval; - - vec[0]= -co[0]; - vec[1]= co[1]; - vec[2]= co[2]; - + + setmirroredcoords(vec, co, mirror); + poinval= mesh_octree_table(ob, vec, 'u'); if(poinval != -1) return (EditVert *)(poinval); Index: source/blender/src/drawview.c =================================================================== --- source/blender/src/drawview.c (revision 12209) +++ source/blender/src/drawview.c (working copy) @@ -774,8 +774,11 @@ my = co[1]; if(mx!=IS_CLIPPED) { - setlinestyle(0); - cpack(0xFF); + setlinestyle(0); + + if(G.vd->flag2&V3D_LOCK_3DCURSOR) cpack(0xFF); + else cpack(0x46CC46); + circ((float)mx, (float)my, 10.0); setlinestyle(4); cpack(0xFFFFFF); @@ -2464,9 +2467,10 @@ uiBlockBeginAlign(block); curs= give_cursor(); - uiDefButF(block, NUM, REDRAWVIEW3D, "X:", 160, 130, 150, 22, curs, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "X co-ordinate of the 3D cursor"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Y:", 160, 108, 150, 22, curs+1, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "Y co-ordinate of the 3D cursor"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Z:", 160, 86, 150, 22, curs+2, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "Z co-ordinate of the 3D cursor"); + uiDefButF(block, NUM, REDRAWVIEW3D, "X:", 160, 130, 150, 22, curs, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "X co-ordinate of the 3D cursor"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Y:", 160, 108, 150, 22, curs+1, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "Y co-ordinate of the 3D cursor"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Z:", 160, 86, 150, 22, curs+2, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "Z co-ordinate of the 3D cursor"); + uiDefButBitS(block, TOG, V3D_LOCK_3DCURSOR, REDRAWVIEW3D, "Lock", 160, 64, 150, 22, &vd->flag2, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "3D cursor lock (ctrl shift C)"); uiBlockEndAlign(block); uiDefBut(block, LABEL, 1, "Display:", 10, 50, 150, 19, NULL, 0.0, 0.0, 0, 0, ""); @@ -2478,11 +2482,12 @@ uiDefButBitS(block, TOG, V3D_SOLID_TEX, REDRAWVIEW3D, "Solid Tex", 10, -30, 140, 19, &vd->flag2, 0, 0, 0, 0, "Display textures in Solid draw type (Shift T)"); uiBlockEndAlign(block); - uiDefBut(block, LABEL, 1, "View Locking:", 160, 50, 150, 19, NULL, 0.0, 0.0, 0, 0, ""); - uiBlockBeginAlign(block); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, REDRAWVIEW3D, "Object:", 160, 30, 140, 19, &vd->ob_centre, "Lock view to center to this Object"); - uiDefBut(block, TEX, REDRAWVIEW3D, "Bone:", 160, 10, 140, 19, vd->ob_centre_bone, 1, 31, 0, 0, "If view locked to Object, use this Bone to lock to view to"); - + uiDefBut(block, LABEL, 1, "View Locking:", 160, 40, 150, 19, NULL, 0.0, 0.0, 0, 0, ""); + uiBlockBeginAlign(block); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, REDRAWVIEW3D, "Object:", 160, 20, 140, 19, &vd->ob_centre, "Lock view to center always on this Object"); + uiDefBut(block, TEX, REDRAWVIEW3D, "Bone:", 160, 0, 140, 19, vd->ob_centre_bone, 1, 31, 0, 0, "If view locked to Object, use this Bone to lock to view to"); + + handle_view3d_around(); /* needed to update 3d lock values in all 3d views */ } static void view3d_panel_preview(ScrArea *sa, short cntrl) // VIEW3D_HANDLER_PREVIEW @@ -3000,6 +3005,47 @@ } retopo_draw_paint_lines(); + /* Draw Texture Paint brush */ + /* TODO: draw while mouse is pressed down and moved */ + if(!G.obedit && (G.f & G_TEXTUREPAINT) && area_is_active_area(v3d->area)) { + ToolSettings *settings= G.scene->toolsettings; + Brush *brush= settings->imapaint.brush; + short csc[2], car[2]; + getmouseco_sc(csc); + getmouseco_areawin(car); + if(csc[0] > v3d->area->winrct.xmin && + csc[1] > v3d->area->winrct.ymin && + csc[0] < v3d->area->winrct.xmax && + csc[1] < v3d->area->winrct.ymax) + fdrawXORcirc((float)car[0], (float)car[1], brush->size); + } + + /* Draw Vertex Paint brush */ + if(!G.obedit && (G.f & G_VERTEXPAINT) && area_is_active_area(v3d->area)) { + extern VPaint Gvp; /* from vpaint */ + short csc[2], car[2]; + getmouseco_sc(csc); + getmouseco_areawin(car); + if(csc[0] > v3d->area->winrct.xmin && + csc[1] > v3d->area->winrct.ymin && + csc[0] < v3d->area->winrct.xmax && + csc[1] < v3d->area->winrct.ymax) + fdrawXORcirc((float)car[0], (float)car[1], Gvp.size); + } + + /* Draw Weight Paint brush */ + if(!G.obedit && (G.f & G_WEIGHTPAINT) && area_is_active_area(v3d->area)) { + extern VPaint Gwp; /* from vpaint */ + short csc[2], car[2]; + getmouseco_sc(csc); + getmouseco_areawin(car); + if(csc[0] > v3d->area->winrct.xmin && + csc[1] > v3d->area->winrct.ymin && + csc[0] < v3d->area->winrct.xmax && + csc[1] < v3d->area->winrct.ymax) + fdrawXORcirc((float)car[0], (float)car[1], Gwp.size); + } + if(v3d->persp>1) drawviewborder(); if(v3d->flag2 & V3D_FLYMODE) drawviewborder_flymode(); if(!(G.f & G_PLAYANIM)) drawcursor(v3d); Index: source/blender/src/editcurve.c =================================================================== --- source/blender/src/editcurve.c (revision 12209) +++ source/blender/src/editcurve.c (working copy) @@ -2514,6 +2514,10 @@ } +/* from what I can gather, the mode==0 magic number spins and bridges the nurbs based on the + * orientation of the global 3d view (yuck yuck!) mode==1 does the same, but doesn't bridge up + * up the new geometry, mode==2 now does the same as 0, but aligned to world axes, not the view. +*/ static void spin_nurb(float *dvec, short mode) { Nurb *nu; @@ -2525,7 +2529,8 @@ if(G.vd==0 || G.obedit==0 || G.obedit->type!=OB_SURF) return; if( (G.vd->lay & G.obedit->lay)==0 ) return; - Mat3CpyMat4(persmat, G.vd->viewmat); + if (mode != 2) Mat3CpyMat4(persmat, G.vd->viewmat); + else Mat3One(persmat); Mat3Inv(persinv, persmat); /* imat and center and size */ @@ -2537,7 +2542,7 @@ VecSubf(cent, cent, G.obedit->obmat[3]); Mat3MulVecfl(imat,cent); - if(dvec) { + if(dvec || mode==2) { n[0]=n[1]= 0.0; n[2]= 1.0; } else { @@ -2578,7 +2583,7 @@ ok= 1; for(a=0;a<7;a++) { - if(mode==0) ok= extrudeflagNurb(1); + if(mode==0 || mode==2) ok= extrudeflagNurb(1); else adduplicateflagNurb(1); if(ok==0) { error("Can't spin"); @@ -2586,7 +2591,7 @@ } rotateflagNurb(1,cent,rotmat); - if(mode==0) { + if(mode==0 || mode==2) { if( (a & 1)==0 ) { rotateflagNurb(1,cent,scalemat1); weightflagNurb(1, 0.25*sqrt(2.0), 1); @@ -3806,7 +3811,11 @@ cent[2]-= G.obedit->obmat[3][2]; if (G.vd) { - Mat3CpyMat4(imat, G.vd->viewmat); + if ( !(newname) || U.flag & USER_ADDOB_ALIGN_EDIT) + Mat3CpyMat4(imat, G.vd->viewmat); + else + Mat3One(imat); + Mat3MulVecfl(imat, cent); Mat3MulMat3(cmat, imat, mat); Mat3Inv(imat, cmat); @@ -4061,7 +4070,7 @@ rename_id((ID *)G.obedit->data, "SurfTube"); } - nu= addNurbprim(4, 1, 0); /* circle */ + nu= addNurbprim(4, 1, newname); /* circle */ nu->resolu= 32; nu->flag= CU_SMOOTH; BLI_addtail(&editNurb, nu); /* temporal for extrude and translate */ @@ -4116,7 +4125,8 @@ makeknots(nu, 1, nu->flagu>>1); BLI_addtail(&editNurb, nu); /* temporal for spin */ - spin_nurb(0, 0); + if(newname) spin_nurb(0, 2); + else spin_nurb(0, 0); makeknots(nu, 2, nu->flagv>>1); @@ -4137,13 +4147,14 @@ } xzproj= 1; - nu= addNurbprim(4, 1, 0); /* circle */ + nu= addNurbprim(4, 1, newname); /* circle */ xzproj= 0; nu->resolu= 24; nu->resolv= 32; nu->flag= CU_SMOOTH; BLI_addtail(&editNurb, nu); /* temporal for extrude and translate */ - spin_nurb(0, 0); + if(newname) spin_nurb(0, 2); + else spin_nurb(0, 0); BLI_remlink(&editNurb, nu); @@ -4256,11 +4267,17 @@ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); countall(); + + /* if a new object was created, it stores it in Curve, for reload original data and undo */ + if ( !(newname) || U.flag & USER_ADDOB_ALIGN_EDIT) { + if(newname) load_editNurb(); + } else { + exit_editmode(2); + } + allqueue(REDRAWALL, 0); - /* if a new object was created, it stores it in Curve, for reload original data and undo */ - if(newname) load_editNurb(); - BIF_undo_push("Add primitive"); + BIF_undo_push("Add Curve"); } void add_primitiveNurb(int type) @@ -4291,11 +4308,16 @@ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); countall(); + + /* if a new object was created, it stores it in Curve, for reload original data and undo */ + if ( !(newname) || U.flag & USER_ADDOB_ALIGN_EDIT) { + if(newname) load_editNurb(); + } else { + exit_editmode(2); + } allqueue(REDRAWALL, 0); - - /* if a new object was created, it stores it in Curve, for reload original data and undo */ - if(newname) load_editNurb(); - else BIF_undo_push("Add primitive"); + + BIF_undo_push("Add Surface"); } Index: source/blender/src/drawnode.c =================================================================== --- source/blender/src/drawnode.c (revision 12209) +++ source/blender/src/drawnode.c (working copy) @@ -372,6 +372,20 @@ return 40; } +static int node_buts_boolean(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +{ + if(block) { + uiBut *bt; + + /* boolean type */ + bt=uiDefButS(block, MENU, B_NODE_EXEC+node->nr, "AND %x0|OR %x1|NAND %x2|NOR %x3|XNOR %x4|XOR %x5", + butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, + &node->custom1, 0, 0, 0, 0, ""); + uiButSetFunc(bt, node_but_title_cb, node, bt); + } + return 20; +} + static int node_buts_curvevec(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) { if(block) { @@ -657,9 +671,14 @@ uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC+node->nr, "Min", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, ""); dy-= 19; uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC+node->nr, "Max", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, ""); + dy-= 25; + uiDefBut(block, LABEL, B_NOP, "Mapping Type", butr->xmin, dy, 3*dx, 19, NULL, 0.0f, 0.0f, 0, 0, ""); + uiDefButI(block, MENU, B_NODE_EXEC+node->nr, "Flat %x0|Cube %x1|Tube %x2|Sphere %x3", + butr->xmin+4*dx, dy, 3*dx, 19, + &texmap->wrap, 0, 0, 0, 0, "Set mapping type"); } - return 5*19 + 6; + return 6*19 + 12; } static int node_shader_buts_vect_math(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) @@ -732,6 +751,9 @@ case SH_NODE_VALTORGB: ntype->butfunc= node_buts_valtorgb; break; + case SH_NODE_BOOLEAN: + ntype->butfunc= node_buts_boolean; + break; case SH_NODE_MATH: ntype->butfunc= node_buts_math; break; @@ -1046,13 +1068,30 @@ } return 19; } +static void node_blur_relative_cb(void *node) +{ + bNode *nodev=node; + NodeBlurData *nbd= nodev->storage; + if(nbd->imageInputWidth!=0){ + if(nbd->relative){ + //we calcule the relative data + nbd->percentx=(float)(nbd->sizex)/nbd->imageInputWidth; + nbd->percenty=(float)(nbd->sizey)/nbd->imageInputHeight; + }else{ + nbd->sizex=(int)(nbd->percentx*nbd->imageInputWidth); + nbd->sizey=(int)(nbd->percenty*nbd->imageInputHeight); + } + } + allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWNODE, 0); +} static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) { if(block) { NodeBlurData *nbd= node->storage; uiBut *bt; - short dy= butr->ymin+38; + short dy= butr->ymin+58; short dx= (butr->xmax-butr->xmin)/2; char str[256]; @@ -1061,7 +1100,8 @@ uiDefButS(block, MENU, B_NODE_EXEC+node->nr,str, butr->xmin, dy, dx*2, 19, &nbd->filtertype, 0, 0, 0, 0, "Set sampling filter for blur"); - dy-=19; + dy-=19; + uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Bokeh", butr->xmin, dy, dx, 19, &nbd->bokeh, 0, 0, 0, 0, "Uses circular filter, warning it's slow!"); @@ -1070,16 +1110,53 @@ &nbd->gamma, 0, 0, 0, 0, "Applies filter on gamma corrected values"); dy-=19; - bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:", - butr->xmin, dy, dx, 19, - &nbd->sizex, 0, 256, 0, 0, ""); - bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:", - butr->xmin+dx, dy, dx, 19, - &nbd->sizey, 0, 256, 0, 0, ""); + bt= uiDefButC(block, TOG, B_NOP, "Relative", + butr->xmin, dy, dx*2, 19, + &nbd->relative, 0, 0, 0, 0, "Applies relative blurs"); + uiButSetFunc(bt, node_blur_relative_cb, node, NULL); + + dy-=19; + if(nbd->relative){ + bt=uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "X:", + butr->xmin, dy, dx, 19, + &nbd->percentx, 0.0f, 1.0f, 0, 0, ""); + bt=uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Y:", + butr->xmin+dx, dy, dx, 19, + &nbd->percenty, 0.0f, 1.0f, 0, 0, ""); + }else{ + bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:", + butr->xmin, dy, dx, 19, + &nbd->sizex, 0, 256, 0, 0, ""); + bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:", + butr->xmin+dx, dy, dx, 19, + &nbd->sizey, 0, 256, 0, 0, ""); + } } - return 57; + return 87; } +static int node_composit_buts_bilateralblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +{ + if(block) { + NodeBilateralBlurData *nbbd= node->storage; + short dy= butr->ymin; + short dx= (butr->xmax-butr->xmin); + + uiBlockBeginAlign(block); + uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Iterations:", + butr->xmin, dy+57, dx, 19, + &nbbd->iter, 1, 128, 0, 0, "Number of iterations"); + uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Color Sigma:", + butr->xmin, dy+38, dx, 19, + &nbbd->sigma_color, 0.01, 128, 10, 0, "Color sigma"); + uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Space sigma:", + butr->xmin, dy+19, dx, 19, + &nbbd->sigma_space ,0.01, 128, 10, 0, "Space sigma"); + + } + return 76; +} + /* qdn: defocus node */ static int node_composit_buts_defocus(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) { @@ -1227,6 +1304,46 @@ return 80; } +static int node_composit_buts_crop(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +{ + if(block) { + NodeTwoXYs *ntxy= node->storage; + uiBut *bt; + char elementheight = 19; + short dx= (butr->xmax-butr->xmin)/2; + short dy= butr->ymax - elementheight; + short xymin= 0, xymax= 10000; + + /* crop image size toggle */ + uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Crop Image Size", + butr->xmin, dy, dx*2, elementheight, + &node->custom1, 0, 0, 0, 0, "Crop the size of the input image."); + + dy-=elementheight; + + /* x1 */ + bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X1:", + butr->xmin, dy, dx, elementheight, + &ntxy->x1, xymin, xymax, 0, 0, ""); + /* y1 */ + bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y1:", + butr->xmin+dx, dy, dx, elementheight, + &ntxy->y1, xymin, xymax, 0, 0, ""); + + dy-=elementheight; + + /* x2 */ + bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X2:", + butr->xmin, dy, dx, elementheight, + &ntxy->x2, xymin, xymax, 0, 0, ""); + /* y2 */ + bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y2:", + butr->xmin+dx, dy, dx, elementheight, + &ntxy->y2, xymin, xymax, 0, 0, ""); + } + return 60; +} + static int node_composit_buts_alphaover(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) { if(block) { @@ -1614,9 +1731,18 @@ case CMP_NODE_VALTORGB: ntype->butfunc= node_buts_valtorgb; break; + case CMP_NODE_BOOLEAN: + ntype->butfunc= node_buts_boolean; + break; + case CMP_NODE_CROP: + ntype->butfunc= node_composit_buts_crop; + break; case CMP_NODE_BLUR: ntype->butfunc= node_composit_buts_blur; break; + case CMP_NODE_BILATERALBLUR: + ntype->butfunc= node_composit_buts_bilateralblur; + break; /* qdn: defocus node */ case CMP_NODE_DEFOCUS: ntype->butfunc = node_composit_buts_defocus; @@ -1746,31 +1872,46 @@ Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); if(ibuf) { - int x, y; - /* somehow the offset has to be calculated inverse */ + int x, y; + float zoom = 1.0; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); glaDefine2DArea(&sa->winrct); - /* ortho at pixel level curarea */ - myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375); - x = (sa->winx-ibuf->x)/2 + snode->xof; - y = (sa->winx-ibuf->y)/2 + snode->yof; + if(ibuf->x > sa->winx || ibuf->y > sa->winy) { + float zoomx, zoomy; + zoomx= (float)sa->winx/ibuf->x; + zoomy= (float)sa->winy/ibuf->y; + zoom = MIN2(zoomx, zoomy); + } + + x = (sa->winx-zoom*ibuf->x)/2 + snode->xof; + y = (sa->winy-zoom*ibuf->y)/2 + snode->yof; + glPixelZoom(zoom, zoom); + + glColor4f(1.0, 1.0, 1.0, 1.0); if(ibuf->rect) - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect); else if(ibuf->channels==4) - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float); - - /* sort this out, this should not be needed */ - myortho2(snode->v2d.cur.xmin, snode->v2d.cur.xmax, snode->v2d.cur.ymin, snode->v2d.cur.ymax); - bwin_clear_viewmat(sa->win); /* clear buttons view */ - glLoadIdentity(); + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float); + + glPixelZoom(1.0, 1.0); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } } } /* nice AA filled circle */ -static void socket_circle_draw(float x, float y, float size, int type, int select) +static void socket_circle_draw(float x, float y, float size, int type, int col[3]) { /* 16 values of sin function */ static float si[16] = { @@ -1788,28 +1929,7 @@ }; int a; - if(select==0) { - if(type==-1) - glColor3ub(0, 0, 0); - else if(type==SOCK_VALUE) - glColor3ub(160, 160, 160); - else if(type==SOCK_VECTOR) - glColor3ub(100, 100, 200); - else if(type==SOCK_RGBA) - glColor3ub(200, 200, 40); - else - glColor3ub(100, 200, 100); - } - else { - if(type==SOCK_VALUE) - glColor3ub(200, 200, 200); - else if(type==SOCK_VECTOR) - glColor3ub(140, 140, 240); - else if(type==SOCK_RGBA) - glColor3ub(240, 240, 100); - else - glColor3ub(140, 240, 140); - } + glColor3ub(col[0], col[1], col[2]); glBegin(GL_POLYGON); for(a=0; a<16; a++) @@ -1827,6 +1947,40 @@ glDisable(GL_BLEND); } +/* wrapper for socket_circle_draw */ +static void socket_circle_draw_wrapper(bNodeSocket *sock, float size) +{ + int col[3]; + + /* choose color based on sock flags */ + if(sock->flag & SELECT) { + if(sock->type==SOCK_VALUE) { + col[0]= 200; col[1]= 200; col[2]= 200;} + else if(sock->type==SOCK_VECTOR) { + col[0]= 140; col[1]= 140; col[2]= 240;} + else if(sock->type==SOCK_RGBA) { + col[0]= 240; col[1]= 240; col[2]= 100;} + else { + col[0]= 140; col[1]= 240; col[2]= 140;} + } + else if(sock->flag & SOCK_SEL) { + col[0]= 255; col[1]= 160; col[2]= 0;} + else { + if(sock->type==-1) { + col[0]= 0; col[1]= 0; col[2]= 0;} + else if(sock->type==SOCK_VALUE) { + col[0]= 160; col[1]= 160; col[2]= 160;} + else if(sock->type==SOCK_VECTOR) { + col[0]= 100; col[1]= 100; col[2]= 200;} + else if(sock->type==SOCK_RGBA) { + col[0]= 200; col[1]= 200; col[2]= 40;} + else { + col[0]= 100; col[1]= 200; col[2]= 100;} + } + + socket_circle_draw(sock->locx, sock->locy, size, sock->type, col); +} + /* not a callback */ static void node_draw_preview(bNodePreview *preview, rctf *prv) { @@ -2235,7 +2389,7 @@ /* socket inputs, buttons */ for(sock= node->inputs.first; sock; sock= sock->next) { if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); if(block && sock->link==NULL) { float *butpoin= sock->ns.vec; @@ -2277,7 +2431,7 @@ /* socket outputs */ for(sock= node->outputs.first; sock; sock= sock->next) { if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); BIF_ThemeColor(TH_TEXT); ofs= 0; @@ -2365,12 +2519,12 @@ /* sockets */ for(sock= node->inputs.first; sock; sock= sock->next) { if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); } for(sock= node->outputs.first; sock; sock= sock->next) { if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); } } @@ -2581,10 +2735,10 @@ /* group sockets */ for(sock= gnode->inputs.first; sock; sock= sock->next) if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); for(sock= gnode->outputs.first; sock; sock= sock->next) if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); /* and finally the whole tree */ node_draw_nodetree(sa, snode, ngroup); Index: source/blender/src/editmesh_add.c =================================================================== --- source/blender/src/editmesh_add.c (revision 12209) +++ source/blender/src/editmesh_add.c (working copy) @@ -48,6 +48,7 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" #include "DNA_screen_types.h" +#include "DNA_userdef_types.h" #include "DNA_view3d_types.h" #include "BLI_blenlib.h" @@ -1178,7 +1179,7 @@ char *name=NULL; if(G.scene->id.lib) return; - + /* this function also comes from an info window */ if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return; if(G.vd==0) return; @@ -1308,7 +1309,8 @@ cent[1]-= G.obedit->obmat[3][1]; cent[2]-= G.obedit->obmat[3][2]; - Mat3CpyMat4(imat, G.vd->viewmat); + if ( !(newob) || U.flag & USER_ADDOB_ALIGN_EDIT) Mat3CpyMat4(imat, G.vd->viewmat); + else Mat3One(imat); Mat3MulVecfl(imat, cent); Mat3MulMat3(cmat, imat, mat); Mat3Inv(imat,cmat); @@ -1320,8 +1322,7 @@ phid= 2*M_PI/tot; phi= .25*M_PI; - make_prim(type, imat, tot, seg, subdiv, dia, d, - ext, fill, cent); + make_prim(type, imat, tot, seg, subdiv, dia, d, ext, fill, cent); if(type<2) tot = totoud; @@ -1331,12 +1332,18 @@ if(type!=0 && type!=13) righthandfaces(1); /* otherwise monkey has eyes in wrong direction... */ countall(); + DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); + + /* if a new object was created, it stores it in Mesh, for reload original data and undo */ + if ( !(newob) || U.flag & USER_ADDOB_ALIGN_EDIT) { + if(newob) load_editMesh(); + } else { + exit_editmode(2); + } + allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */ allqueue(REDRAWALL, 0); - DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); - - /* if a new object was created, it stores it in Mesh, for reload original data and undo */ - if(newob) load_editMesh(); + BIF_undo_push(undostr); } Index: source/blender/src/interface_panel.c =================================================================== --- source/blender/src/interface_panel.c (revision 12209) +++ source/blender/src/interface_panel.c (working copy) @@ -119,6 +119,11 @@ } +int uiGetRoundBox() +{ + return roundboxtype; +} + void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad) { float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293}, @@ -303,7 +308,7 @@ int a; char alpha=255; - if(roundboxtype & UI_RB_ALPHA) alpha= 128; + if(roundboxtype & UI_RB_ALPHA) alpha= 72; /* mult */ for(a=0; a<7; a++) { @@ -371,14 +376,14 @@ gl_round_box_topshade(minx+1, miny+1, maxx-1, maxy-1, rad); /* total outline */ - if(roundboxtype & UI_RB_ALPHA) glColor4ub(0,0,0, 128); else glColor4ub(0,0,0, 200); + if(roundboxtype & UI_RB_ALPHA) glColor4ub(0,0,0, 128); else glColor4ub(0,0,0, 150); gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad); glDisable( GL_LINE_SMOOTH ); /* bottom shade for header down */ if((roundboxtype & 12)==12) { - glColor4ub(0,0,0, 80); + glColor4ub(0,0,0, 60); fdrawline(minx+rad-1.0, miny+1.0, maxx-rad+1.0, miny+1.0); } glDisable( GL_BLEND ); @@ -409,8 +414,31 @@ glDisable( GL_LINE_SMOOTH ); } +/* plain fake antialiased unfilled round rectangle */ +void uiRoundRectFakeAA(float minx, float miny, float maxx, float maxy, float rad, float asp) +{ + float color[4]; + float raddiff; + int i, passes=4; + + /* get the colour and divide up the alpha */ + glGetFloatv(GL_CURRENT_COLOR, color); + color[3]= 1/(float)passes; + glColor4fv(color); + + /* set the 'jitter amount' */ + raddiff = (1/(float)passes) * asp; + + glEnable( GL_BLEND ); + + /* draw lots of lines on top of each other */ + for (i=passes; i>=(-passes); i--) { + gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad+(i*raddiff)); + } + + glDisable( GL_BLEND ); +} - /* plain antialiased filled box */ void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad) { @@ -438,7 +466,39 @@ glDisable( GL_LINE_SMOOTH ); } +/* plain fake antialiased unfilled round rectangle */ +void uiTriangleFakeAA(float x1, float y1, float x2, float y2, float x3, float y3, float asp) +{ + float color[4]; + float jitter; + int i, passes=4; + + /* get the colour and divide up the alpha */ + glGetFloatv(GL_CURRENT_COLOR, color); + color[3]= 1/(float)passes; + glColor4fv(color); + + /* set the 'jitter amount' */ + jitter = 1/(float)passes; + //jitter = (1/(float)passes) * asp; + + glEnable( GL_BLEND ); + + /* draw lots of lines on top of each other */ + for (i=passes; i>=(-passes); i--) { + glBegin(GL_TRIANGLES); + + /* 'point' first, then two base vertices */ + glVertex2f(x1+(i*jitter), y1+(i*jitter)); + glVertex2f(x2, y2+(i*jitter)); + glVertex2f(x3, y3+(i*jitter)); + glEnd(); + } + + glDisable( GL_BLEND ); +} + /* ************** panels ************* */ static void copy_panel_offset(Panel *pa, Panel *papar) @@ -1103,9 +1163,13 @@ glEnable(GL_BLEND); BIF_ThemeColor4(TH_PANEL); + + uiSetRoundBox(12); glRectf(block->minx, block->miny, block->maxx, block->maxy); glDisable(GL_BLEND); + + } /* draw the title, tabs, etc in the header */ @@ -1810,59 +1874,6 @@ } -/* disabled /deprecated now, panels minimise in place */ -#if 0 -static void stow_unstow(uiBlock *block) -{ - SpaceLink *sl= curarea->spacedata.first; - Panel *pa; - int ok=0, x, y, width; - - if(block->panel->flag & PNL_CLOSEDY) { // flag has been set how it should become! - - width= (curarea->winx-320)/sl->blockscale; - if(width<5) width= 5; - - /* find empty spot in bottom */ - for(y=4; y<100; y+= PNL_HEADER+4) { - for(x=4; xpanels.first; pa; pa=pa->next) { - if(pa!=block->panel && pa->active && pa->paneltab==NULL) { - if( abs(pa->ofsx-x)<320 ) { - if( abs(pa->ofsy+pa->sizey-y)panel->old_ofsx= block->panel->ofsx; - block->panel->old_ofsy= block->panel->ofsy; - - block->panel->ofsx= x; - block->panel->ofsy= y-block->panel->sizey; - - } - else { - block->panel->ofsx= block->panel->old_ofsx; - block->panel->ofsy= block->panel->old_ofsy; - - } - /* copy locations */ - for(pa= curarea->panels.first; pa; pa= pa->next) { - if(pa->paneltab==block->panel) copy_panel_offset(pa, block->panel); - } - -} -#endif - - /* this function is supposed to call general window drawing too */ /* also it supposes a block has panel, and isnt a menu */ void ui_do_panel(uiBlock *block, uiEvent *uevent) @@ -1946,5 +1957,3 @@ ui_drag_panel(block, 1); } - - Index: source/blender/src/header_node.c =================================================================== --- source/blender/src/header_node.c (revision 12209) +++ source/blender/src/header_node.c (working copy) @@ -221,7 +221,7 @@ node= node_add_node(snode, event, locx, locy); /* uses test flag */ - snode_autoconnect(snode, node, NODE_TEST); + if(snode->flag & SNODE_AUTOCONNECT) snode_autoconnect(snode, node, NODE_TEST); addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); @@ -662,10 +662,13 @@ xco+= 80; uiDefButBitS(block, TOG, R_COMP_FREE, B_NOP, "Free Unused", xco+5,0,80,19, &G.scene->r.scemode, 0.0f, 0.0f, 0, 0, "Free Nodes that are not used while composite"); xco+= 80; - uiDefButBitS(block, TOG, SNODE_BACKDRAW, B_NOP, "Backdrop", xco+5,0,80,19, &snode->flag, 0.0f, 0.0f, 0, 0, "Use active Viewer Node output as backdrop"); + uiDefButBitS(block, TOG, SNODE_BACKDRAW, REDRAWNODE, "Backdrop", xco+5,0,80,19, &snode->flag, 0.0f, 0.0f, 0, 0, "Use active Viewer Node output as backdrop"); xco+= 80; } + uiDefButBitS(block, TOG, SNODE_AUTOCONNECT, REDRAWNODE, "Auto Connect", xco+5,0,100,19, &snode->flag, 0.0f, 0.0f, 0, 0, "Connect new nodes automatically to selected ones"); + xco+= 80; + /* always as last */ sa->headbutlen= xco+2*XIC; Index: source/blender/src/drawipo.c =================================================================== --- source/blender/src/drawipo.c (revision 12209) +++ source/blender/src/drawipo.c (working copy) @@ -1918,6 +1918,7 @@ } else { ei->icu->driver= MEM_callocN(sizeof(IpoDriver), "ipo driver"); + ei->icu->driver->fac= 1.0; ei->icu->driver->blocktype= ID_OB; ei->icu->driver->adrcode= OB_LOC_X; } @@ -2039,6 +2040,7 @@ { extern int totipo_curve; // editipo.c uiBlock *block; + uiBut *but; EditIpo *ei; char name[48]; @@ -2063,10 +2065,10 @@ uiDefBut(block, BUT, B_IPO_DRIVER, "Remove", 210,265,100,20, NULL, 0.0f, 0.0f, 0, 0, "Remove Driver for this Ipo Channel"); uiBlockBeginAlign(block); - uiDefIconButS(block, TOG, B_IPO_DRIVERTYPE, ICON_PYTHON, 10,240,25,20, &driver->type, (float)IPO_DRIVER_TYPE_NORMAL, (float)IPO_DRIVER_TYPE_PYTHON, 0, 0, "Use a one-line Python Expression as Driver"); + uiDefIconButS(block, TOG, B_IPO_DRIVERTYPE, ICON_PYTHON, 10,245,25,20, &driver->type, (float)IPO_DRIVER_TYPE_NORMAL, (float)IPO_DRIVER_TYPE_PYTHON, 0, 0, "Use a one-line Python Expression as Driver"); if(driver->type == IPO_DRIVER_TYPE_PYTHON) { - uiDefBut(block, TEX, B_IPO_REDR, "", 35,240,275,20, driver->name, 0, 127, 0, 0, "Python Expression"); + uiDefBut(block, TEX, B_IPO_REDR, "", 35,245,275,20, driver->name, 0, 127, 0, 0, "Python Expression"); uiBlockEndAlign(block); if(driver->flag & IPO_DRIVER_FLAG_INVALID) { uiDefBut(block, LABEL, 0, "Error: invalid Python expression", @@ -2074,22 +2076,24 @@ } } else { - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_IPO_DEPCHANGE, "OB:", 35, 240, 125, 20, &(driver->ob), "Driver Object"); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_IPO_DEPCHANGE, "OB:", 35, 245, 135, 20, &(driver->ob), "Driver Object"); if(driver->ob) { int icon=ICON_OBJECT; if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR) { icon = ICON_POSE_DEHLT; - uiDefBut(block, TEX, B_IPO_REDR, "BO:", 10,220,150,20, driver->name, 0, 31, 0, 0, "Bone name"); + but= uiDefBut(block, TEX, B_IPO_REDR, "BO:", 170,245,140,20, driver->name, 0, 31, 0, 0, "Bone name"); + uiButSetCompleteFunc(but, autocomplete_bone, (void *)driver->ob); } else driver->blocktype= ID_OB; /* safety when switching object button */ uiBlockBeginAlign(block); uiDefIconTextButS(block, MENU, B_IPO_DEPCHANGE, icon, - ipodriver_modeselect_pup(driver->ob), 165,240,145,20, &(driver->blocktype), 0, 0, 0, 0, "Driver type"); + ipodriver_modeselect_pup(driver->ob), 10,220,80,20, &(driver->blocktype), 0, 0, 0, 0, "Driver type"); uiDefButS(block, MENU, B_IPO_REDR, - ipodriver_channelselect_pup(), 165,220,145,20, &(driver->adrcode), 0, 0, 0, 0, "Driver channel"); + ipodriver_channelselect_pup(), 90,220,75,20, &(driver->adrcode), 0, 0, 0, 0, "Driver channel"); + uiDefButF(block, NUM, B_IPO_REDR, "Factor:", 175, 220, 135, 20, &(driver->fac), -1000.0, 1000.0, 100, 0, "Factor that is used to scale the driver value"); } uiBlockEndAlign(block); } Index: source/blender/src/sculptmode.c =================================================================== --- source/blender/src/sculptmode.c (revision 12209) +++ source/blender/src/sculptmode.c (working copy) @@ -1158,7 +1158,7 @@ co[2]= 0.0f; /* This is copied from displace modifier code */ - hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 1, &texres); + hasrgb = multitex_ext(mtex->tex, co, NULL, 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). Index: source/blender/src/header_buttonswin.c =================================================================== --- source/blender/src/header_buttonswin.c (revision 12209) +++ source/blender/src/header_buttonswin.c (working copy) @@ -668,7 +668,7 @@ // xco+=XIC; uiBlockBeginAlign(block); - uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_GAME, xco, 0, XIC, YIC, &(G.buts->mainb), 0.0, (float)CONTEXT_LOGIC, 0, 0, "Logic (F4) "); +// uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_GAME, xco, 0, XIC, YIC, &(G.buts->mainb), 0.0, (float)CONTEXT_LOGIC, 0, 0, "Logic (F4) "); uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_SCRIPT, xco+=XIC, 0, XIC, YIC, &(G.buts->mainb), 0.0, (float)CONTEXT_SCRIPT, 0, 0, "Script "); uiDefIconButS(block, ROW, B_BUTSPREVIEW, ICON_MATERIAL_DEHLT,xco+=XIC, 0, XIC, YIC, &(G.buts->mainb), 0.0, (float)CONTEXT_SHADING, 0, 0, "Shading (F5) "); uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_OBJECT, xco+=XIC, 0, XIC, YIC, &(G.buts->mainb), 0.0, (float)CONTEXT_OBJECT, 0, 0, "Object (F7) "); Index: source/blender/src/editscreen.c =================================================================== --- source/blender/src/editscreen.c (revision 12209) +++ source/blender/src/editscreen.c (working copy) @@ -474,15 +474,6 @@ winqueue_break= 1; } -static void headmenu(ScrArea *sa) -{ - short val= pupmenu("Header %t|Top%x2|Bottom %x1|No Header %x0"); - - if(val> -1) { - scrarea_change_headertype(sa, val); - } -} - static void addqueue_ext(short win, unsigned short event, short val, char ascii) { if (win<4 || !areawinar[win]) { @@ -546,9 +537,6 @@ case MIDDLEMOUSE: scrollheader(sa); break; - case RIGHTMOUSE: - headmenu(sa); - break; case REDRAW: do_redraw= 1; break; @@ -793,15 +781,32 @@ int edgeop; char str[64] = "Split Area%x1|"; - if(isjoinable(actarea, actedge)) strcat(str, "Join Areas%x2|"); - if (actarea->headertype) strcat(str, "No Header%x3"); - else strcat(str, "Add Header%x3"); + if (isjoinable(actarea, actedge)) strcat(str, "Join Areas%x2|"); + + if (actarea->headertype == HEADERDOWN) + strcat(str, "Set Header Up%x3"); + else if (actarea->headertype == HEADERTOP) + strcat(str, "Set Header Down%x3"); + else if (!actarea->headertype) + strcat(str, "Add Header%x3"); + if(actarea->headertype) strcat(str, "|Remove Header%x4"); + edgeop= pupmenu(str); if (edgeop==1) splitarea_interactive(actarea, actedge); else if (edgeop==2) joinarea_interactive(actarea, actedge); - else if (edgeop==3) scrarea_change_headertype(actarea, - actarea->headertype?0:HEADERDOWN); + else if (edgeop==3) { + if(actarea->headertype == HEADERDOWN) + scrarea_change_headertype(actarea, HEADERTOP); + else if(actarea->headertype == HEADERTOP) + scrarea_change_headertype(actarea, HEADERDOWN); + else if(scredge_is_horizontal(actedge) && actedge->v1->vec.y == actarea->v2->vec.y) + scrarea_change_headertype(actarea, HEADERTOP); + else + scrarea_change_headertype(actarea, HEADERDOWN); + } + else if (edgeop==4) + scrarea_change_headertype(actarea, 0); } else blenderqread(evt, val); // global hotkeys } Index: source/blender/src/space.c =================================================================== --- source/blender/src/space.c (revision 12209) +++ source/blender/src/space.c (working copy) @@ -335,6 +335,12 @@ vd->flag |= V3D_ALIGN; else vd->flag &= ~V3D_ALIGN; + + if (G.vd->flag2 & V3D_LOCK_3DCURSOR) + vd->flag2 |= V3D_LOCK_3DCURSOR; + else + vd->flag2 &= ~V3D_LOCK_3DCURSOR; + scrarea_queue_headredraw(sa); } } @@ -854,6 +860,25 @@ return changed; } +static short select_same_index_object(Object *ob) +{ + char changed = 0; + Base *base = FIRSTBASE; + + if (!ob) + return 0; + + while(base) { + if (BASE_SELECTABLE(base) && (base->object->index == ob->index) && !(base->flag & SELECT)) { + base->flag |= SELECT; + base->object->flag |= SELECT; + changed = 1; + } + base= base->next; + } + return changed; +} + void select_object_grouped(short nr) { short changed = 0; @@ -865,6 +890,7 @@ else if(nr==6) changed = select_same_layer(OBACT); else if(nr==7) changed = select_same_group(OBACT); else if(nr==8) changed = select_object_hooks(OBACT); + else if(nr==9) changed = select_same_index_object(OBACT); if (changed) { countall(); @@ -890,7 +916,7 @@ "Objects of Same Type%x5|" "Objects on Shared Layers%x6|" "Objects in Same Group%x7|" - "Object Hooks%x8|"); + "Object Hooks%x8|Index Object%x9"); /* here we go */ @@ -1171,6 +1197,30 @@ } } + if(!G.obedit && (G.f & G_TEXTUREPAINT)) { + /* TODO: build session for texture paint too? -> generic paint session is possible? */ + if(event!=LEFTMOUSE && event!=MIDDLEMOUSE && (event==MOUSEY || event==MOUSEX)) { + if(!bwin_qtest(sa->win)) + allqueue(REDRAWVIEW3D, 0); + } + } + + if(!G.obedit && (G.f & G_VERTEXPAINT)) { + /* TODO: build session for vertex paint too? */ + if(event!=LEFTMOUSE && event!=MIDDLEMOUSE && (event==MOUSEY || event==MOUSEX)) { + if(!bwin_qtest(sa->win)) + allqueue(REDRAWVIEW3D, 0); + } + } + + if(!G.obedit && (G.f & G_WEIGHTPAINT)) { + /* TODO: build session for weight paint too? */ + if(event!=LEFTMOUSE && event!=MIDDLEMOUSE && (event==MOUSEY || event==MOUSEX)) { + if(!bwin_qtest(sa->win)) + allqueue(REDRAWVIEW3D, 0); + } + } + /* Handle retopo painting */ if(retopo_mesh_paint_check()) { if(!retopo_paint(event)) @@ -1726,7 +1776,16 @@ borderselect(); break; case CKEY: - if(G.qual==LR_CTRLKEY) { + if(G.qual==(LR_CTRLKEY|LR_SHIFTKEY)) { + if(G.vd->flag2 & V3D_LOCK_3DCURSOR) + G.vd->flag2 &= ~V3D_LOCK_3DCURSOR; + else + G.vd->flag2 |= V3D_LOCK_3DCURSOR; + + allqueue(REDRAWVIEW3D, 0); + handle_view3d_around(); + } + else if(G.qual==LR_CTRLKEY) { if(ob && (ob->flag & OB_POSEMODE)) pose_copy_menu(); /* poseobject.c */ else @@ -2215,9 +2274,9 @@ } else if((G.qual==0) && (OBACT) && (OBACT->type==OB_ARMATURE) && (OBACT->flag & OB_POSEMODE)) select_bone_parent(); - else if((G.qual==0)) { + /*else if((G.qual==0)) { start_game(); - } + }*/ break; case RKEY: if((G.obedit==0) && G.qual==LR_ALTKEY) { @@ -2541,8 +2600,31 @@ nextkey_obipo(-1); break; - case PAD0: case PAD1: case PAD2: case PAD3: case PAD4: - case PAD5: case PAD6: case PAD7: case PAD8: case PAD9: + /* could reuse more perhaps */ + case PAD1: + if(G.qual==LR_ALTKEY) do_view3d_buttons(B_SEL_VERT); + else { + persptoetsen(event); + doredraw= 1; + } + break; + case PAD2: + if(G.qual==LR_ALTKEY) do_view3d_buttons(B_SEL_EDGE); + else { + persptoetsen(event); + doredraw= 1; + } + break; + + case PAD3: + if(G.qual==LR_ALTKEY) do_view3d_buttons(B_SEL_FACE); + else { + persptoetsen(event); + doredraw= 1; + } + break; + + case PAD0: case PAD4: case PAD5: case PAD6: case PAD7: case PAD8: case PAD9: case PADENTER: persptoetsen(event); doredraw= 1; @@ -2614,6 +2696,7 @@ vd->dist= 10.0; vd->lens= 35.0f; vd->near= 0.01f; + //vd->near= 0.001f; new one -> doesn't work vd->far= 500.0f; vd->grid= 1.0f; vd->gridlines= 16; @@ -3119,8 +3202,9 @@ uiBlockBeginAlign(block); uiDefButC(block, ROW, B_UPDATE_THEME, "Shaded", 465,y2,80,20, col, 2.0, (float) TH_SHADED, 0, 0, ""); uiDefButC(block, ROW, B_UPDATE_THEME, "Rounded", 545,y2,80,20, col, 2.0, (float) TH_ROUNDED, 0, 0, ""); - uiDefButC(block, ROW, B_UPDATE_THEME, "Minimal", 625,y2,80,20, col, 2.0, (float) TH_MINIMAL, 0, 0, ""); - uiDefButC(block, ROW, B_UPDATE_THEME, "OldSkool", 705,y2,80,20, col, 2.0, (float) TH_OLDSKOOL, 0, 0, ""); + uiDefButC(block, ROW, B_UPDATE_THEME, "Round Shaded", 625,y2,80,20, col, 2.0, (float) TH_ROUNDSHADED, 0, 0, ""); + uiDefButC(block, ROW, B_UPDATE_THEME, "Minimal", 705,y2,80,20, col, 2.0, (float) TH_MINIMAL, 0, 0, ""); + uiDefButC(block, ROW, B_UPDATE_THEME, "OldSkool", 785,y2,80,20, col, 2.0, (float) TH_OLDSKOOL, 0, 0, ""); uiBlockEndAlign(block); } else if(th_curcol==TH_ICONFILE) { @@ -3464,15 +3548,22 @@ if (U.flag & USER_LMOUSESELECT) U.flag &= ~USER_TWOBUTTONMOUSE; + uiBlockBeginAlign(block); uiDefButBitI(block, TOG, USER_TWOBUTTONMOUSE, B_DRAWINFO, "Emulate 3 Button Mouse", (xpos+edgsp+(3*mpref)+(4*midsp)),y3,mpref,buth, &(U.flag), 0, 0, 0, 0, "Emulates Middle Mouse with Alt+LeftMouse (doesnt work with Left Mouse Select option)"); + + uiDefButBitI(block, TOGN, USER_TWEAKMODE, B_DRAWINFO, "Tweak Mode", + (xpos+edgsp+(3*mpref)+(4*midsp)),y2,mpref,buth, + &(U.flag), 0, 0, 0, 0, "Drag operations no longer require a click to complete (Best for tablet users)"); + uiBlockEndAlign(block); uiDefBut(block, LABEL,0,"Middle Mouse Button:", (xpos+(2*edgsp)+(4*mpref)+(4*midsp)),y6label,mpref,buth, 0, 0, 0, 0, 0, ""); + uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); /* mutually exclusive toggles, start color */ uiDefButBitI(block, TOGN, USER_VIEWMOVE, B_DRAWINFO, "Rotate View", @@ -3519,6 +3610,11 @@ &(U.obcenter_dia), 4, 10, 0, 0, "Diameter in Pixels for Object/Lamp center display"); + uiDefButBitI(block, TOG, USER_CYCLE_SELMODE, B_DRAWINFO, "Cycle Selection Mode", + (xpos+edgsp+(5*mpref)+(6*midsp)),y1,mpref,buth, + &(U.uiflag), 0, 0, 0, 0, + "Cycle through selection modes by using ctrl-tab and ctrl-shift-tab"); + } else if (U.userpref == 1) { /* edit methods */ @@ -3534,6 +3630,11 @@ (xpos+edgsp+(mpref/2)),y2,(mpref/2),buth, &(U.flag), 0, 0, 0, 0, "Link new objects' material to the object block"); uiBlockEndAlign(block); + + uiDefButBitI(block, TOG, USER_ADDOB_ALIGN_EDIT, B_DRAWINFO, "Add Objects Aligned", + (xpos+edgsp),y1,mpref,buth, + &(U.flag), 0, 0, 0, 0, "Align newly added objects to the view and automatically enter Edit Mode"); + uiBlockEndAlign(block); uiDefBut(block, LABEL,0,"Undo:", Index: source/blender/src/interface.c =================================================================== --- source/blender/src/interface.c (revision 12209) +++ source/blender/src/interface.c (working copy) @@ -1961,28 +1961,46 @@ } break; - case BACKSPACEKEY: - if(len!=0) { - if ((but->selend - but->selsta) > 0) { - len -= ui_delete_selection_edittext(but); - - if (len < 0) len = 0; - dodraw=1; - } - else if(get_qual() & LR_SHIFTKEY) { - str[0]= 0; - but->pos= 0; - len= 0; - dodraw= 1; - } - else if(but->pos>0) { - for(x=but->pos; x<=strlen(str); x++) - str[x-1]= str[x]; - but->pos--; - str[--len]='\0'; - dodraw= 1; - } - } + case BACKSPACEKEY: + if(G.qual & LR_CTRLKEY) { + short foundword= 0, eraseamount= 0; + + for(x=strlen(str)-1; x>=0; x--) { + if(str[x] != ' ' && foundword == 0) + foundword= 1; + if(str[x] == ' ' && foundword == 1) + break; + eraseamount++; + } + + but->pos-=eraseamount; + len-=eraseamount; + str[len]='\0'; + dodraw= 1; + } + else { + if(len!=0) { + if (but->selend - but->selsta > 0) { + len -= ui_delete_selection_edittext(but); + + if (len < 0) len = 0; + dodraw=1; + } + else if(get_qual() & LR_SHIFTKEY) { + str[0]= 0; + but->pos= 0; + len= 0; + dodraw= 1; + } + else if(but->pos>0) { + for(x=but->pos; x<=strlen(str); x++) + str[x-1]= str[x]; + but->pos--; + str[--len]='\0'; + dodraw= 1; + } + } + } break; case TABKEY: @@ -4801,18 +4819,90 @@ return retval; } +/* Simpler than dynamic, do not write huge tips */ +#define TIPMAXLINES 10 +/* System will create lines of "this plus one word" each */ +#define PERLINE 50 + static uiOverDraw *ui_draw_but_tip(uiBut *but) { uiOverDraw *od; float x1, x2, y1, y2; - rctf tip_bbox; + rctf tip_bbox, temp_bbox; + char *lines[TIPMAXLINES]; + float sizes[TIPMAXLINES]; + char *cursor; + int total, done; + int slot, totlines; + float boxbase; - BIF_GetBoundingBox(but->font, but->tip, (U.transopts & USER_TR_TOOLTIPS), &tip_bbox); + /* Better safe than sorry, init cleanly */ + for (slot = 0; slot < TIPMAXLINES; slot++) { + lines[slot] = NULL; + sizes[slot] = 0.0f; + } + cursor = but->tip; + total = strlen(but->tip); + done = 0; + slot = 0; + totlines = 0; + while (done < total) { + /* Split in TIPMAXLINES lines, or less, each of just one word more than PERLINE chars */ + if ((*cursor != 0) && (strlen(cursor) > PERLINE) && (slot < TIPMAXLINES)) { + char *space; + + space = strchr(cursor+PERLINE, ' '); + if (space) { + lines[slot] = malloc(space-cursor+1); + memcpy(lines[slot], cursor, space-cursor+1); /* Include the space */ + *(lines[slot] + (space-cursor)) = 0; /* Replaces trailing space with \0 */ + done += (space-cursor); + cursor = space + 1; /* Jump the space so next line starts in letter */ + } else { + /* Line has no spaces after PERLINE chars, so last line */ + lines[slot] = strdup(cursor); + done = total; + } + } else { + /* Last line, could be huge, but then it is tooltip issue, do not write a book in them */ + lines[slot] = strdup(cursor); + done = total; + } + slot++; + totlines++; + } + + tip_bbox.xmax = 0.0f; + tip_bbox.xmin = 0.0f; + tip_bbox.ymax = 0.0f; + tip_bbox.ymin = 0.0f; + boxbase = 0.0f; + for (slot = 0; slot < TIPMAXLINES; slot++) { + if(lines[slot]) { + BIF_GetBoundingBox(but->font, lines[slot], (U.transopts & USER_TR_TOOLTIPS), &temp_bbox); + sizes[slot] = temp_bbox.ymax - temp_bbox.ymin; + /* Extend sides and bottom */ + if (tip_bbox.xmin > temp_bbox.xmin) tip_bbox.xmin = temp_bbox.xmin; + if (tip_bbox.xmax < temp_bbox.xmax) tip_bbox.xmax = temp_bbox.xmax; + if (tip_bbox.ymin > temp_bbox.ymin) tip_bbox.ymin = temp_bbox.ymin; + /* Accumulate heights */ + tip_bbox.ymax += (temp_bbox.ymax - temp_bbox.ymin); + /* Save to be eliminated later */ + if (slot == 0) boxbase = temp_bbox.ymin; + } + } + /* Eliminate the starting value */ + tip_bbox.ymax += boxbase; + x1= (but->x1+but->x2)/2; x2= x1+but->aspect*((tip_bbox.xmax-tip_bbox.xmin) + 8); y2= but->y1-10; - y1= y2-but->aspect*((tip_bbox.ymax+(tip_bbox.ymax-tip_bbox.ymin))); + if (totlines > 1) { + y1= y2-but->aspect*((tip_bbox.ymax+0.75f*(tip_bbox.ymax-tip_bbox.ymin))); + } else { + y1= y2-but->aspect*((tip_bbox.ymax+(tip_bbox.ymax-tip_bbox.ymin))); + } /* for pulldown menus it doesnt work */ @@ -4827,8 +4917,8 @@ x2= G.curscreen->sizex; } if(y1 < 0) { - y1 += 36; - y2 += 36; + y2 = 24+(y2-y1); + y1 = 24; } od= ui_begin_overdraw((int)(x1-1), (int)(y1-2), (int)(x2+4), (int)(y2+4)); @@ -4854,16 +4944,27 @@ glColor3ub(0,0,0); /* set the position for drawing text +4 in from the left edge, and leaving an equal gap between the top of the background box * and the top of the string's tip_bbox, and the bottom of the background box, and the bottom of the string's tip_bbox + * ui_rasterpos_safe(x1+4, ((y2-tip_bbox.ymax)+(y1+tip_bbox.ymin))/2 - tip_bbox.ymin, but->aspect); */ - ui_rasterpos_safe(x1+4, ((y2-tip_bbox.ymax)+(y1+tip_bbox.ymin))/2 - tip_bbox.ymin, but->aspect); BIF_SetScale(1.0); - BIF_DrawString(but->font, but->tip, (U.transopts & USER_TR_TOOLTIPS)); + for (slot = 0; slot < TIPMAXLINES; slot++){ + if (lines[slot]) { + /* +4 from left edge, and spread the lines evenly over the provided area, with 2 vert padding */ + ui_rasterpos_safe(x1+4, 2 + y1 - sizes[slot] + (y2-2-y1-2) * ((float)(totlines-slot) / (float)totlines), but->aspect); + BIF_DrawString(but->font, lines[slot], (U.transopts & USER_TR_TOOLTIPS)); + /* The should not be needed anymore */ + free(lines[slot]); + } + } ui_flush_overdraw(od); /* to show it in the frontbuffer */ return od; } +#undef TIPMAXLINES +#undef PERLINE + /* inside this function no global UIbuttip... qread is not safe */ static void ui_do_but_tip(uiBut *buttip) { @@ -5420,12 +5521,21 @@ } - /* safety is 4 to enable small number buttons (like 'users') */ + /* safety is 4 to enable small number buttons (like 'users') */ if(but->type==NUMSLI || but->type==HSVSLI) - okwidth= -4 + (but->x2 - but->x1)/2.0; + //okwidth= -4 + (but->x2 - but->x1)/2.0; + okwidth= -4 + (but->x2 - but->x1); + /* a bit more for round shaded theme tog button checkmarks */ + else if ((BIF_GetThemeValue(TH_BUT_DRAWTYPE) == TH_ROUNDSHADED) && (ELEM3(but->type, TOG, TOGN, TOG3))) + okwidth= -20 + (but->x2 - but->x1); + /* a bit less for labels */ + else if (but->type == LABEL) + okwidth= but->x2 - but->x1; else - okwidth= -4 + (but->x2 - but->x1); + okwidth= -4 + (but->x2 - but->x1); + if (okwidth < 0) okwidth= 0; + /* name: */ switch( but->type ) { @@ -5614,9 +5724,8 @@ { uiBut *prev, *but=NULL, *next; int flag= 0, cols=0, rows=0; - int theme= BIF_GetThemeValue(TH_BUT_DRAWTYPE); - if ( !(ELEM3(theme, TH_MINIMAL, TH_SHADED, TH_ROUNDED)) ) { + if ( !(ELEM4(BIF_GetThemeValue(TH_BUT_DRAWTYPE), TH_ROUNDSHADED, TH_ROUNDED, TH_SHADED, TH_MINIMAL)) ) { block->flag &= ~UI_BUT_ALIGN; // all 4 flags return; } @@ -6247,6 +6356,11 @@ return block->curfont; } +void uiButSetCol(uiBut *but, int col) +{ + but->themecol= col; +} + void uiButSetFlag(uiBut *but, int flag) { but->flag|= flag; @@ -6680,4 +6794,3 @@ return val; } - Index: source/blender/src/resources.c =================================================================== --- source/blender/src/resources.c (revision 12209) +++ source/blender/src/resources.c (working copy) @@ -238,6 +238,8 @@ cp= ts->group_active; break; case TH_TRANSFORM: cp= ts->transform; break; + case TH_LAYER_COLOR_NE: + cp= ts->layer_color_ne; break; case TH_VERTEX: cp= ts->vertex; break; case TH_VERTEX_SELECT: @@ -376,6 +378,8 @@ SETCOL(btheme->tv3d.header, 195, 195, 195, 255); SETCOL(btheme->tv3d.panel, 165, 165, 165, 127); + SETCOL(btheme->tv3d.layer_color_ne, 195, 195, 195, 255); + SETCOL(btheme->tv3d.shade1, 160, 160, 160, 100); SETCOL(btheme->tv3d.shade2, 0x7f, 0x70, 0x70, 100); @@ -589,7 +593,7 @@ str += sprintf(str, "Object Grouped %%x%d|", TH_GROUP); str += sprintf(str, "Object Grouped Active %%x%d|", TH_GROUP_ACTIVE); str += sprintf(str, "Transform %%x%d|", TH_TRANSFORM); - str += sprintf(str, "%%l|"); + str += sprintf(str, "Color of Not Empty Layers %%x%d|", TH_LAYER_COLOR_NE); str += sprintf(str, "Vertex %%x%d|", TH_VERTEX); str += sprintf(str, "Vertex Selected %%x%d|", TH_VERTEX_SELECT); str += sprintf(str, "Vertex Size %%x%d|", TH_VERTEX_SIZE); Index: source/blender/src/filesel.c =================================================================== --- source/blender/src/filesel.c (revision 12209) +++ source/blender/src/filesel.c (working copy) @@ -1189,6 +1189,9 @@ /* sfile->act is used for databrowse: double names of library objects */ sfile->act= -1; + if(curarea->full) sfile->wasfullscreen= 1; + else area_fullscreen(); /* set full screen */ + if(G.relbase_valid && BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) sfile->flag |= FILE_STRINGCODE; else @@ -1552,11 +1555,16 @@ else if(event== B_FS_PARDIR) parent(sfile); else if(event== B_FS_LOAD) { - if(sfile->type) + if(sfile->type) filesel_execute(sfile); + + area_fullscreen(); } - else if(event== B_FS_CANCEL) + else if(event== B_FS_CANCEL) { filesel_prevspace(); + + if(!sfile->wasfullscreen) area_fullscreen(); + } else if(event== B_FS_LIBNAME) { Library *lib= BLI_findlink(&G.main->library, sfile->menu); if(lib) { Index: source/blender/src/transform_generics.c =================================================================== --- source/blender/src/transform_generics.c (revision 12209) +++ source/blender/src/transform_generics.c (working copy) @@ -194,7 +194,7 @@ } /* assumes G.obedit set to mesh object */ -static void editmesh_apply_to_mirror(TransInfo *t) +static void editmesh_apply_to_mirror(TransInfo *t, int mirror) { TransData *td = t->data; EditVert *eve; @@ -207,12 +207,8 @@ break; eve= td->tdmir; - if(eve) { - eve->co[0]= -td->loc[0]; - eve->co[1]= td->loc[1]; - eve->co[2]= td->loc[2]; - } - } + if(eve) setmirroredcoords(eve->co, td->loc, mirror); + } } /* called for updating while transform acts, once per redraw */ @@ -336,9 +332,11 @@ if(t->state != TRANS_CANCEL) clipMirrorModifier(t, G.obedit); - if(G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR) - editmesh_apply_to_mirror(t); - + //if(G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR) + // editmesh_apply_to_mirror(t); + if(G.scene->toolsettings->editbutflag & B_MESH_MIRROR) + editmesh_apply_to_mirror(t, G.scene->toolsettings->mirror); + DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); /* sets recalc flags */ recalc_editnormals(); Index: source/blender/src/buttons_shading.c =================================================================== --- source/blender/src/buttons_shading.c (revision 12209) +++ source/blender/src/buttons_shading.c (working copy) @@ -720,7 +720,166 @@ uiDefButF(block, NUMSLI, B_TEXPRV, "W4: ", 10, 10, 150, 19, &tex->vn_w4, -2.0, 2.0, 10, 0, "Sets feature weight 4"); } +static void texture_tiles_precalc(void *tex, void *unused) +{ + tiles_precalc((Tex *)tex); +} +static void texture_tiles_preset(void *tex, void *unused) +{ + Tex *t = (Tex *)tex; + /* Setup parameters for preset patterns. */ + switch (t->preset) + { + case TEX_TILES_HEX: + t->hgap = 0; + t->vgap = 0; + t->alternate = 1; + break; + case TEX_TILES_HERRINGBONE1: + case TEX_TILES_HERRINGBONE2: + case TEX_TILES_HERRINGBONE3: + t->hgap = 0; + t->vgap = 0; + t->alternate = 1; + break; + case TEX_TILES_WEAVE: + t->hgap = 0; + t->vgap = 0; + t->alternate = 1; + break; + case TEX_TILES_INTERLOCK1: + case TEX_TILES_INTERLOCK2: + case TEX_TILES_INTERLOCK3: + break; + } + + texture_tiles_precalc(tex, unused); +} +static char* tiles_corner_menu() +{ + static char nbmenu[256]; + sprintf(nbmenu, "Corner Style %%t|Round 1 %%x%d|Round 2 %%x%d|Ellipse 1 %%x%d|Ellipse 2 %%x%d|Straight %%x%d", TEX_CORNER_ROUND1, TEX_CORNER_ROUND2, TEX_CORNER_ELLIPSE1, TEX_CORNER_ELLIPSE2, TEX_CORNER_STRAIGHT); + return nbmenu; +} +static char* tiles_preset_menu() +{ + static char nbmenu[256]; + sprintf(nbmenu, "Preset %%t|None %%x%d|Interlock 1 %%x%d|Interlock 2 %%x%d|Interlock 3 %%x%d|Honeycomb %%x%d|Herringbone 1 %%x%d|Herringbone 2 %%x%d|Herringbone 3 %%x%d|Weave %%x%d", TEX_TILES_NONE, TEX_TILES_INTERLOCK1, TEX_TILES_INTERLOCK2, TEX_TILES_INTERLOCK3, TEX_TILES_HEX, TEX_TILES_HERRINGBONE1, TEX_TILES_HERRINGBONE2, TEX_TILES_HERRINGBONE3, TEX_TILES_WEAVE); + return nbmenu; +} +static char* tiles_bevopt_menu() +{ + static char nbmenu[256]; + sprintf(nbmenu, "Bevel Option %%t|Default %%x%d|Uniform Min %%x%d|Uniform Max %%x%d", TEX_BEVEL_DEFAULTMIN, TEX_BEVEL_UNIFORMMIN, TEX_BEVEL_UNIFORMMAX); + return nbmenu; +} +static void texture_panel_tiles(Tex *tex) +{ + uiBut *bt; + uiBlock *block; + + block= uiNewBlock(&curarea->uiblocks, "texture_panel_tiles", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Tiles Basic", "Texture", 640, 0, 400, 204)==0) return; + + uiSetButLock(tex->id.lib!=NULL, ERROR_LIBDATA_MESSAGE); + + bt = uiDefBut(block, LABEL, 0, "Preset", -40, 180, 60, 19, 0, 0, 0, 0, 0, ""); + bt = uiDefButS(block, MENU, B_TEXPRV, tiles_preset_menu(), 10, 180, 100, 19, &tex->preset, 0, 0, 0, 0, "Tile preset"); + uiButSetFunc(bt, texture_tiles_preset, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Scale", 210, 180, 50, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "%:", 250, 180, 80, 19, &tex->scale, 0.0001, 10, 10, 0, "Scaling"); + + bt = uiDefBut(block, LABEL, 0, "Width", -40, 156, 60, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "Lo:", 10, 156, 80, 19, &tex->minwidth, 0.01, 10, 10, 0, "Minimum tile width"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, NUM, B_TEXPRV, "Hi:", 100, 156, 80, 19, &tex->maxwidth, 0.01, 10, 10, 0, "Maximum tile width"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButS(block, NUMSLI, B_TEXPRV, "N:", 190, 156, 80, 19, &tex->hcount, 1, 15, 10, 0, "Number of horizontal random tiles"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Height", -40, 132, 60, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "Lo:", 10, 132, 80, 19, &tex->minheight, 0.01, 10, 10, 0, "Minimum tile height"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, NUM, B_TEXPRV, "Hi:", 100, 132, 80, 19, &tex->maxheight, 0.01, 10, 10, 0, "Maximum tile height"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButS(block, NUMSLI, B_TEXPRV, "N:", 190, 132, 80, 19, &tex->vcount, 1, 15, 10, 0, "Number of vertical random tiles"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Bump", -40, 108, 60, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "Lo:", 10, 108, 80, 19, &tex->minbump, 0, 1, 10, 0, "Minimum bump height"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, NUM, B_TEXPRV, "Hi:", 100, 108, 80, 19, &tex->maxbump, 0, 1, 10, 0, "Maximum bump height"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Gap", -40, 84, 60, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "H:", 10, 84, 80, 19, &tex->hgap, 0, 10, 10, 0, "Horizontal gap"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, NUM, B_TEXPRV, "V:", 100, 84, 80, 19, &tex->vgap, 0, 10, 10, 0, "Vertical gap"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Shift", -40, 60, 60, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "D:", 10, 60, 80, 19, &tex->shift, -10, 10, 10, 0, "Tile shift amount"); + bt = uiDefButI(block, NUM, B_TEXPRV, "N:", 100, 60, 80, 19, &tex->alternate, 0, 0x8000, 0, 0, "Number of tiles after which shifting starts again"); + + bt = uiDefBut(block, LABEL, 0, "Color", -40, 36, 40, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, COL, B_TEXPRV, "", 10, 36, 19, 19, &tex->colr1, 0, 0, 0, 0, "Base color for brick"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, COL, B_TEXPRV, "", 40, 36, 19, 19, &tex->colr2, 0, 0, 0, 0, "Gap color"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefButF(block, NUM, B_TEXPRV, "H%:", 70, 36, 80, 19, &tex->fhue, 0, 1, 10, 0, "Hue variation"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, NUM, B_TEXPRV, "S%:", 160, 36, 80, 19, &tex->fsat, 0, 1, 10, 0, "Saturation variation"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + bt = uiDefButF(block, NUM, B_TEXPRV, "V%:", 250, 36, 80, 19, &tex->fval, 0, 1, 10, 0, "Value variation"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefButI(block, NUM, B_TEXPRV, "Seed:", -40, 12,150, 19, &tex->seed, 0, 0x80000000, 10, 0, "Seed for random number generator"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefButF(block, NUM, B_NOP, "Nabla:", 180, 12,150, 19, &tex->nabla, 0.001, 0.1, 1, 0, "Defines size of derivative offset used for calculating normal"); +} +static void texture_panel_tiles_advanced(Tex *tex) +{ + uiBut *bt; + uiBlock *block; + + block= uiNewBlock(&curarea->uiblocks, "texture_panel_tiles_advanced", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Tiles Basic", "Texture"); + if(uiNewPanel(curarea, block, "Tiles Advanced", "Texture", 1280, 0, 400, 204)==0) return; + + uiSetButLock(tex->id.lib!=NULL, ERROR_LIBDATA_MESSAGE); + + + bt = uiDefBut(block, LABEL, 0, "Bevel", 10, 180, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "%:", 90, 180, 80, 19, &tex->bevel, 0, 0.5, 10, 0, "Tile bevel factor"); + bt = uiDefButF(block, NUM, B_TEXPRV, "C:", 180, 180, 80, 19, &tex->curve, -1, 1, 10, 0, "Adjust the bevel profile"); + bt = uiDefButS(block, TOG, B_TEXPRV, "Smooth", 270, 180, 80, 19, &tex->smooth, 0, 1, 0, 0, "Smooth the bevel profile"); + bt = uiDefButF(block, NUM, B_TEXPRV, "Freq:", 90, 156, 80, 19, &tex->freq, 0, 100, 10, 0, "Frequency of wave function for bevel"); + bt = uiDefButF(block, NUM, B_TEXPRV, "Amp:", 180, 156, 80, 19, &tex->amp, 0, 100, 10, 0, "Amplitude of wave function for bevel"); + bt = uiDefButF(block, NUM, B_TEXPRV, "S:", 270, 156, 80, 19, &tex->strength, 0, 1, 10, 0, "Strength of bevel"); + bt = uiDefButS(block, MENU, B_TEXPRV, tiles_bevopt_menu(), 90, 132,170, 19, &tex->bevoption, 0, 0, 0, 0, "Controls uniformity of bevel across tiles"); + uiButSetFunc(bt, texture_tiles_precalc, tex, NULL); + + bt = uiDefBut(block, LABEL, 0, "Corner", 10, 108, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "H%:", 90, 108, 80, 19, &tex->hcorner, 0, 0.5, 10, 0, "Tile corner horizontal factor"); + bt = uiDefButF(block, NUM, B_TEXPRV, "V%:", 180, 108, 80, 19, &tex->vcorner, 0, 0.5, 10, 0, "Tile corner vertical factor"); + bt = uiDefButS(block, MENU, B_TEXPRV, tiles_corner_menu(), 270, 108, 80, 19, &tex->corner, 0, 0, 0, 0, "Tile corner type"); + + bt = uiDefBut(block, LABEL, 0, "Rotate", 10, 60, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "Deg:", 90, 60, 80, 19, &tex->rotate, 0, 360, 100, 0, "Texture rotation in degrees"); + + bt = uiDefBut(block, LABEL, 0, "Skew", 10, 36, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "H:", 90, 36, 80, 19, &tex->hskew, -100, 100, 10, 0, "Horizontal skew"); + bt = uiDefButF(block, NUM, B_TEXPRV, "V:", 180, 36, 80, 19, &tex->vskew, -100, 100, 10, 0, "Vertical skew"); + + bt = uiDefBut(block, LABEL, 0, "Offset", 10, 12, 80, 19, 0, 0.0, 0.0, 0, 0, ""); + bt = uiDefButF(block, NUM, B_TEXPRV, "H:", 90, 12, 80, 19, &tex->hoffset, -100, 100, 10, 0, "Horizontal offset"); + bt = uiDefButF(block, NUM, B_TEXPRV, "V:", 180, 12, 80, 19, &tex->voffset, -100, 100, 10, 0, "Vertical offset"); +} + static char *layer_menu(RenderResult *rr, short *curlay) { RenderLayer *rl; @@ -1525,7 +1684,22 @@ uiDefButF(block, NUMSLI, B_TEXPRV, "Contr", 160,10,150,20, &tex->contrast, 0.01, 5.0, 0, 0, "Changes the contrast of the color or intensity of a texture"); } - +static void texture_type_select(void *tex, void *unused) +{ + Tex *t = (Tex *)tex; + if (t->type == TEX_TILES) { + /* We have to do this because do_2d_mapping() will mess up the texture mapping + * for Tiles texture + */ + t->extend = TEX_REPEAT; + t->cropxmin = 0.0; + t->cropxmax = 1.0; + t->cropymin = 0.0; + t->cropymax = 1.0; + t->xrepeat = 1.0; + t->yrepeat = 1.0; + } +} static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *la, bNode *node, Brush *br, SculptData *sd) { MTex *mt=NULL; @@ -1619,16 +1793,17 @@ if(id) { char textypes[512]; Tex *tex= (Tex *)id; + uiBut *bt; uiSetButLock(tex->id.lib!=0, ERROR_LIBDATA_MESSAGE); /* newnoise: all texture types as menu, not enough room for more buttons. * Can widen panel, but looks ugly when other panels overlap it */ - sprintf(textypes, "Texture Type %%t|None %%x%d|Image %%x%d|EnvMap %%x%d|Clouds %%x%d|Marble %%x%d|Stucci %%x%d|Wood %%x%d|Magic %%x%d|Blend %%x%d|Noise %%x%d|Plugin %%x%d|Musgrave %%x%d|Voronoi %%x%d|DistortedNoise %%x%d", 0, TEX_IMAGE, TEX_ENVMAP, TEX_CLOUDS, TEX_MARBLE, TEX_STUCCI, TEX_WOOD, TEX_MAGIC, TEX_BLEND, TEX_NOISE, TEX_PLUGIN, TEX_MUSGRAVE, TEX_VORONOI, TEX_DISTNOISE); + sprintf(textypes, "Texture Type %%t|None %%x%d|Image %%x%d|EnvMap %%x%d|Clouds %%x%d|Marble %%x%d|Stucci %%x%d|Wood %%x%d|Magic %%x%d|Blend %%x%d|Noise %%x%d|Plugin %%x%d|Musgrave %%x%d|Voronoi %%x%d|DistortedNoise %%x%d|Tiles %%x%d", 0, TEX_IMAGE, TEX_ENVMAP, TEX_CLOUDS, TEX_MARBLE, TEX_STUCCI, TEX_WOOD, TEX_MAGIC, TEX_BLEND, TEX_NOISE, TEX_PLUGIN, TEX_MUSGRAVE, TEX_VORONOI, TEX_DISTNOISE, TEX_TILES); uiDefBut(block, LABEL, 0, "Texture Type", 160, 150, 140, 20, 0, 0.0, 0.0, 0, 0, ""); - uiDefButS(block, MENU, B_TEXTYPE, textypes, 160, 125, 140, 25, &tex->type, 0,0,0,0, "Select texture type"); - + bt = uiDefButS(block, MENU, B_TEXTYPE, textypes, 160, 125, 140, 25, &tex->type, 0,0,0,0, "Select texture type"); + uiButSetFunc(bt, texture_type_select, tex, NULL); } else { // label to avoid centering @@ -1954,8 +2129,8 @@ /* TEXTURE OUTPUT */ uiBlockBeginAlign(block); uiDefButBitS(block, TOG, MTEX_STENCIL, B_WORLDPRV, "Stencil", 10,125,45,19, &(mtex->texflag), 0, 0, 0, 0, "Sets the texture mapping to stencil mode"); - uiDefButBitS(block, TOG, MTEX_NEGATIVE, B_WORLDPRV, "Neg", 55,125,30,19, &(mtex->texflag), 0, 0, 0, 0, "Inverts the values of the texture to reverse its effect"); - uiDefButBitS(block, TOG, MTEX_RGBTOINT, B_WORLDPRV, "No RGB", 85,125,60,19, &(mtex->texflag), 0, 0, 0, 0, "Converts texture RGB values to intensity (gray) values"); + uiDefButBitS(block, TOG, MTEX_NEGATIVE, B_WORLDPRV, "Invert", 55,125,30,19, &(mtex->texflag), 0, 0, 0, 0, "Inverts the values of the texture to reverse its effect"); + uiDefButBitS(block, TOG, MTEX_RGBTOINT, B_WORLDPRV, "BW", 85,125,60,19, &(mtex->texflag), 0, 0, 0, 0, "Converts texture RGB values to intensity (gray) values"); uiBlockEndAlign(block); uiBlockBeginAlign(block); @@ -1969,9 +2144,9 @@ /* MAP TO */ uiBlockBeginAlign(block); uiDefButBitS(block, TOG, WOMAP_BLEND, B_WORLDPRV, "Blend", 10,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the color progression of the background"); - uiDefButBitS(block, TOG, WOMAP_HORIZ, B_WORLDPRV, "Hori", 85,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the color of the horizon"); - uiDefButBitS(block, TOG, WOMAP_ZENUP, B_WORLDPRV, "ZenUp", 160,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the color of the zenith above"); - uiDefButBitS(block, TOG, WOMAP_ZENDOWN, B_WORLDPRV, "ZenDo", 235,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the color of the zenith below"); + uiDefButBitS(block, TOG, WOMAP_HORIZ, B_WORLDPRV, "Horizon", 85,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the color of the horizon"); + uiDefButBitS(block, TOG, WOMAP_ZENUP, B_WORLDPRV, "Zenith Above", 160,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the color of the zenith above"); + uiDefButBitS(block, TOG, WOMAP_ZENDOWN, B_WORLDPRV, "Zenith Below", 235,180,75,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the color of the zenith below"); uiBlockEndAlign(block); uiBlockBeginAlign(block); @@ -1979,9 +2154,9 @@ uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_WORLDPRV, "Col ", 155,100,155,19, &(mtex->colfac), 0.0, 1.0, 0, 0, "Sets the amount the texture affects color values"); - uiDefButF(block, NUMSLI, B_WORLDPRV, "Nor ", 155,80,155,19, &(mtex->norfac), 0.0, 1.0, 0, 0, "Sets the amount the texture affects normal values"); - uiDefButF(block, NUMSLI, B_WORLDPRV, "Var ", 155,60,155,19, &(mtex->varfac), 0.0, 1.0, 0, 0, "Sets the amount the texture affects other values"); + uiDefButF(block, NUMSLI, B_WORLDPRV, "Color", 155,100,155,19, &(mtex->colfac), 0.0, 1.0, 0, 0, "Sets the amount the texture affects color values"); + uiDefButF(block, NUMSLI, B_WORLDPRV, "Normal", 155,80,155,19, &(mtex->norfac), 0.0, 1.0, 0, 0, "Sets the amount the texture affects normal values"); + uiDefButF(block, NUMSLI, B_WORLDPRV, "Other", 155,60,155,19, &(mtex->varfac), 0.0, 1.0, 0, 0, "Sets the amount the texture affects other values"); } @@ -2138,14 +2313,14 @@ /* aolight: samples */ uiDefButS(block, MENU, B_REDR, "Constant QMC %x2|Adaptive QMC %x1|Constant Jittered %x0", 10, 120, 145, 19, &wrld->ao_samp_method, 0, 0, 0, 0, "Method for generating shadow samples: Constant QMC: best quality, Adaptive QMC: fast in high contrast areas"); - uiDefButS(block, NUM, B_REDR, "Samples:", + uiDefButS(block, NUMSLI, B_REDR, "Samples:", 165, 120, 145, 19, &wrld->aosamp, 1.0, 32.0, 100, 0, "Sets the number of samples used for AO (actual number: squared)"); if (wrld->ao_samp_method == WO_AOSAMP_HALTON) { uiDefButF(block, NUM, B_REDR, "Threshold:", 10, 95, 145, 19, &wrld->ao_adapt_thresh, 0.0, 1.0, 100, 0, "Samples below this threshold will be considered fully shadowed/unshadowed and skipped"); } - uiDefButF(block, NUM, B_REDR, "Dist:", + uiDefButF(block, NUMSLI, B_REDR, "Distance:", 165, 95, 145, 19, &wrld->aodist, 0.001, 5000.0, 100, 0, "Sets length of AO rays, defines how far away other faces give occlusion effect"); uiBlockBeginAlign(block); @@ -2923,6 +3098,49 @@ BIF_preview_changed(ID_MA); } break; + + case B_MTEXUP: + case B_MTEXDOWN: + if(ma) + { + int i0 = ma->texact; + int i1 = ma->texact + (event==B_MTEXUP?-1:1); + + if( (event==B_MTEXUP)?(i0 == 0):(i0 == MAX_MTEX-1) ) break; + if( ma->mtex[i0] || ma->mtex[i1] ) + { + /* swap visibility settings */ + int sti0 = ma->septex & (1<septex & (1<septex |= (1<septex &= ~(1<septex |= (1<septex &= ~(1<mtex[i0]) + { + ma->mtex[i0] = ma->mtex[i1]; + ma->mtex[i1] = 0; + } + else if(!ma->mtex[i1]) + { + ma->mtex[i1] = ma->mtex[i0]; + ma->mtex[i0] = 0; + } + else + { + memcpy(&mtexcopybuf, ma->mtex[ i1 ], sizeof(MTex)); + memcpy(ma->mtex[ i1 ], ma->mtex[ i0 ], sizeof(MTex)); + memcpy(ma->mtex[ i0 ], &mtexcopybuf, sizeof(MTex)); + } + } + ma->texact += (event==B_MTEXUP)?-1:1; + + BIF_preview_changed(ID_MA); + scrarea_queue_winredraw(curarea); + } + break; + case B_MTEXCOPY: if(ma && ma->mtex[(int)ma->texact] ) { mtex= ma->mtex[(int)ma->texact]; @@ -3251,6 +3469,10 @@ uiDefIconBut(block, BUT, B_MTEXCOPY, ICON_COPYUP, 100,180,23,21, 0, 0, 0, 0, 0, "Copies the mapping settings to the buffer"); uiDefIconBut(block, BUT, B_MTEXPASTE, ICON_PASTEUP, 125,180,23,21, 0, 0, 0, 0, 0, "Pastes the mapping settings from the buffer"); uiBlockEndAlign(block); + uiBlockBeginAlign(block); + uiDefIconBut(block, BUT, B_MTEXUP, VICON_MOVE_UP, 175,180,23,21, 0, 0, 0, 0, 0, "Moves the texture up one place"); + uiDefIconBut(block, BUT, B_MTEXDOWN, VICON_MOVE_DOWN, 200,180,23,21, 0, 0, 0, 0, 0, "Moves the texture down one place"); + uiBlockEndAlign(block); uiBlockSetCol(block, TH_AUTO); mtex= ma->mtex[ ma->texact ]; @@ -3312,7 +3534,7 @@ X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->ray_mirror), 0.0, 1.0, 100, 2, "Sets the amount mirror reflection for raytrace"); uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel: ", X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->fresnel_mir), 0.0, 5.0, 10, 2, "Power of Fresnel for mirror reflection"); - uiDefButF(block, NUMSLI, B_MATPRV, "Fac: ", + uiDefButF(block, NUMSLI, B_MATPRV, "Factor: ", X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->fresnel_mir_i), 1.0, 5.0, 10, 2, "Blending factor for Fresnel"); uiBlockEndAlign(block); @@ -3425,7 +3647,7 @@ // parameters only used in ray_transp mode if(ma->mode & MA_RAYTRANSP) { // Filter - uiDefButF(block, NUM, B_MATPRV, "Filt:", 160,115,150,20, &(ma->filter), 0.0, 1.0, 10, 0, "Amount of filtering for transparent raytrace"); + uiDefButF(block, NUM, B_MATPRV, "Filter:", 160,115,150,20, &(ma->filter), 0.0, 1.0, 10, 0, "Amount of filtering for transparent raytrace"); /* absorption color */ uiDefBut(block, LABEL, 0, "Absorption Color", 10, 98, 150, 18, 0, 0.0, 0.0, 0, 0, ""); @@ -3497,29 +3719,31 @@ 200,180,110,20, &ma->sss_preset, 0, 0, 0, 0, ""); uiButSetFunc(bt, material_sss_preset_cb, ma, NULL); + uiDefButF(block, NUMSLI, B_MATPRV, "Scale:", 10,150,145,20, + &ma->sss_scale, 0.001, 1000, 1, 3, "Object scale"); + + uiDefBut(block, LABEL, B_DIFF, "Radius", 10,130,145,20, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_MATPRV, "Scale:", 10,150,145,20, - &ma->sss_scale, 0.001, 1000, 1, 3, "Object scale"); - bt=uiDefButF(block, NUM, B_MATPRV, "Radius R", 10,130,145,20, + bt=uiDefButF(block, NUMSLI, B_MATPRV, "R ", 10,110,145,20, &ma->sss_radius[0], 0.0001, 10000, 1, 3, "Mean red scattering path length"); uiButSetFunc(bt, material_sss_custom_set_cb, ma, NULL); - bt=uiDefButF(block, NUM, B_MATPRV, "Radius G", 10,110,145,20, + bt=uiDefButF(block, NUMSLI, B_MATPRV, "G ", 10,90,145,20, &ma->sss_radius[1], 0.0001, 10000, 1, 3, "Mean green scattering path length"); uiButSetFunc(bt, material_sss_custom_set_cb, ma, NULL); - bt=uiDefButF(block, NUM, B_MATPRV, "Radius B", 10,90,145,20, + bt=uiDefButF(block, NUMSLI, B_MATPRV, "B ", 10,70,145,20, &ma->sss_radius[2], 0.0001, 10000, 1, 3, "Mean blue scattering path length"); uiButSetFunc(bt, material_sss_custom_set_cb, ma, NULL); uiBlockEndAlign(block); - bt=uiDefButF(block, NUM, B_MATPRV, "IOR:", 10,60,145,20, + bt=uiDefButF(block, NUMSLI, B_MATPRV, "IOR:", 10,40,145,20, &ma->sss_ior, 0.1, 2, 1, 3, "Index of refraction (higher values are denser)"); uiButSetFunc(bt, material_sss_custom_set_cb, ma, NULL); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_MATPRV, "Error:", 10,30,145,20, + uiDefButF(block, NUMSLI, B_MATPRV, "Error:", 10,10,145,20, &ma->sss_error, 0.0001, 10, 1, 3, "Error tolerance (low values are slower and higher quality)"); uiBlockEndAlign(block); @@ -3592,7 +3816,7 @@ uiDefButS(block, MENU, B_MATPRV, str1, 9, 180,78,19, &(ma->diff_shader), 0.0, 0.0, 0, 0, "Creates a diffuse shader"); uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_MATPRV, "Ref ", 90,180,150,19, &(ma->ref), 0.0, 1.0, 0, 0, "Sets the amount of reflection"); + uiDefButF(block, NUMSLI, B_MATPRV, "Reflectivity:", 90,180,150,19, &(ma->ref), 0.0, 1.0, 0, 0, "Sets the amount of reflection"); if(ma->diff_shader==MA_DIFF_ORENNAYAR) uiDefButF(block, NUMSLI, B_MATPRV, "Rough:",90,160, 150,19, &(ma->roughness), 0.0, 3.14, 0, 0, "Sets Oren Nayar Roughness"); else if(ma->diff_shader==MA_DIFF_TOON) { @@ -3603,7 +3827,7 @@ uiDefButF(block, NUMSLI, B_MATPRV, "Dark:",90,160, 150,19, &(ma->darkness), 0.0, 2.0, 0, 0, "Sets Minnaert darkness"); else if(ma->diff_shader==MA_DIFF_FRESNEL) { uiDefButF(block, NUMSLI, B_MATPRV, "Fresnel:", 90, 160,150,19, &(ma->param[1]), 0.0, 5.0, 0, 0, "Power of Fresnel"); - uiDefButF(block, NUMSLI, B_MATPRV, "Fac:",90,140,150,19, &(ma->param[0]), 1.0, 5.0, 0, 0, "Blending factor"); + uiDefButF(block, NUMSLI, B_MATPRV, "Factor:",90,140,150,19, &(ma->param[0]), 1.0, 5.0, 0, 0, "Blending factor"); } uiBlockEndAlign(block); @@ -3611,24 +3835,24 @@ uiDefButS(block, MENU, B_MATPRV, str2, 9,120,77,19, &(ma->spec_shader), 0.0, 0.0, 0, 0, "Creates a specular shader"); uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_MATPRV, "Spec ", 90,120,150,19, &(ma->spec), 0.0, 2.0, 0, 0, "Sets the degree of specularity"); + uiDefButF(block, NUMSLI, B_MATPRV, "Specularity:", 90,120,150,19, &(ma->spec), 0.0, 2.0, 0, 0, "Sets the degree of specularity"); if ELEM3(ma->spec_shader, MA_SPEC_COOKTORR, MA_SPEC_PHONG, MA_SPEC_BLINN) { - uiDefButS(block, NUMSLI, B_MATPRV, "Hard:", 90, 100, 150,19, &(ma->har), 1.0, 511, 0, 0, "Sets the hardness of the specularity"); + uiDefButS(block, NUMSLI, B_MATPRV, "Hardness:", 90, 100, 150,19, &(ma->har), 1.0, 511, 0, 0, "Sets the hardness of the specularity"); } if(ma->spec_shader==MA_SPEC_BLINN) - uiDefButF(block, NUMSLI, B_MATPRV, "Refr:", 90, 80,150,19, &(ma->refrac), 1.0, 10.0, 0, 0, "Sets the material's Index of Refraction"); + uiDefButF(block, NUMSLI, B_MATPRV, "IOR:", 90, 80,150,19, &(ma->refrac), 1.0, 10.0, 0, 0, "Sets the material's Index of Refraction"); if(ma->spec_shader==MA_SPEC_TOON) { uiDefButF(block, NUMSLI, B_MATPRV, "Size:", 90, 100,150,19, &(ma->param[2]), 0.0, 1.53, 0, 0, "Sets the size of specular toon area"); - uiDefButF(block, NUMSLI, B_MATPRV, "Smooth:",90, 80,150,19, &(ma->param[3]), 0.0, 1.0, 0, 0, "Sets the smoothness of specular toon area"); + uiDefButF(block, NUMSLI, B_MATPRV, "Smoothness:",90, 80,150,19, &(ma->param[3]), 0.0, 1.0, 0, 0, "Sets the smoothness of specular toon area"); } if(ma->spec_shader==MA_SPEC_WARDISO) uiDefButF(block, NUMSLI, B_MATPRV, "rms:", 90, 100,150,19, &(ma->rms), 0.0, 0.4, 0, 0, "Sets the standard deviation of surface slope"); /* default shading variables */ uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_MATPRV, "Tralu ", 9,30,150,19, &(ma->translucency), 0.0, 1.0, 100, 2, "Translucency, amount of diffuse shading of the back side"); - uiDefButF(block, NUMSLI, B_MATPRV, "SBias ", 159,30,151,19, &(ma->sbias), 0.0, 0.25, 10, 2, "Shadow bias, to prevent terminator problems on shadow boundary"); - uiDefButF(block, NUMSLI, B_MATPRV, "Amb ", 9,10,150,19, &(ma->amb), 0.0, 1.0, 0, 0, "Sets the amount of global ambient color the material receives"); - uiDefButF(block, NUMSLI, B_MATPRV, "Emit ", 159,10,151,19, &(ma->emit), 0.0, 2.0, 0, 0, "Sets the amount of light the material emits"); + uiDefButF(block, NUMSLI, B_MATPRV, "Translucency:", 9,30,150,19, &(ma->translucency), 0.0, 1.0, 100, 2, "Translucency, amount of diffuse shading of the back side"); + uiDefButF(block, NUMSLI, B_MATPRV, "Shadow Bias:", 159,30,151,19, &(ma->sbias), 0.0, 0.25, 10, 2, "Shadow bias, to prevent terminator problems on shadow boundary"); + uiDefButF(block, NUMSLI, B_MATPRV, "Ambience:", 9,10,150,19, &(ma->amb), 0.0, 1.0, 0, 0, "Sets the amount of global ambient color the material receives"); + uiDefButF(block, NUMSLI, B_MATPRV, "Emit:", 159,10,151,19, &(ma->emit), 0.0, 2.0, 0, 0, "Sets the amount of light the material emits"); uiBlockEndAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); @@ -3730,6 +3954,10 @@ block= uiNewBlock(&curarea->uiblocks, "material_panel_material", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Material", "Material", 320, 0, 318, 204)==0) return; + /* TODO, check for ob->id.lib */ + /*but = */ + uiDefButS(block, NUM, B_NOP, "PassIndex:", 8, 200, 148, YIC, &ma->index, 0.0, 1000.0, 0, 0, "Index # for the IndexMat render pass."); + uiSetButLock(ma->id.lib!=NULL, ERROR_LIBDATA_MESSAGE); uiBlockBeginAlign(block); uiDefIconBut(block, BUT, B_MATCOPY, ICON_COPYUP, 262,200,XIC,YIC, 0, 0, 0, 0, 0, "Copies Material to the buffer"); @@ -3756,7 +3984,7 @@ uiDefButBitI(block, TOG, MA_NOMIST, B_NOP, "No Mist", 8,146,74,20, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); uiDefButBitI(block, TOG, MA_ENV, B_MATPRV, "Env", 82,146,74,20, &(ma->mode), 0, 0, 0, 0, "Causes faces to render with alpha zero: allows sky/backdrop to show through (only for solid faces)"); - uiDefButF(block, NUM, B_NOP, "Shad A ", 156,146,147,19, &ma->shad_alpha, 0.001, 1.0f, 100, 0, "Shadow casting alpha, only in use for Irregular Shadowbuffer"); + uiDefButF(block, NUMSLI, B_NOP, "Shadow Alpha", 156,146,147,19, &ma->shad_alpha, 0.001, 1.0f, 100, 0, "Shadow casting alpha, only in use for Irregular Shadowbuffer"); } uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); @@ -4174,6 +4402,10 @@ case TEX_VORONOI: texture_panel_voronoi(tex); break; + case TEX_TILES: + texture_panel_tiles(tex); + texture_panel_tiles_advanced(tex); + break; } } } Index: source/blender/src/usiblender.c =================================================================== --- source/blender/src/usiblender.c (revision 12209) +++ source/blender/src/usiblender.c (working copy) @@ -364,6 +364,10 @@ bTheme *btheme; for(btheme= U.themes.first; btheme; btheme= btheme->next) { SETCOL(btheme->tv3d.editmesh_active, 255, 255, 255, 128); + + if(btheme->tv3d.layer_color_ne[3]==0) { + SETCOL(btheme->tv3d.layer_color_ne, 195, 195, 195, 255); + } } } Index: source/blender/src/toets.c =================================================================== --- source/blender/src/toets.c (revision 12209) +++ source/blender/src/toets.c (working copy) @@ -109,6 +109,9 @@ #include "BIF_poseobject.h" +#define VIEW_ZOOM_OUT_FACTOR (1.15f) +#define VIEW_ZOOM_IN_FACTOR (1.0f/VIEW_ZOOM_OUT_FACTOR) + /* ------------------------------------------------------------------------- */ static int is_an_active_object(void *ob) { @@ -156,6 +159,7 @@ float phi, si, q1[4], vec[3]; static int perspo=1; int preview3d_event= 1; + short mouseloc[2]; float new_dist, orig_ofs[3]; @@ -244,14 +248,20 @@ if(G.vd->persp==2) { G.vd->camzoom= MAX2(-30, G.vd->camzoom-5); } - else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f; + else if(G.vd->dist<10.0*G.vd->far) { + getmouseco_areawin(mouseloc); + view_zoom_mouseloc(VIEW_ZOOM_OUT_FACTOR, mouseloc); + } if(G.vd->persp!=1) preview3d_event= 0; } else if(event==PADPLUSKEY) { if(G.vd->persp==2) { G.vd->camzoom= MIN2(300, G.vd->camzoom+5); } - else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f; + else if(G.vd->dist> 0.001*G.vd->grid) { + getmouseco_areawin(mouseloc); + view_zoom_mouseloc(VIEW_ZOOM_IN_FACTOR, mouseloc); + } if(G.vd->persp!=1) preview3d_event= 0; } else if(event==PAD5) { @@ -723,13 +733,29 @@ else enter_posemode(); } else if(ob->type==OB_MESH) { - if(ob==G.obedit) EM_selectmode_menu(); + //if(ob==G.obedit) EM_selectmode_menu(); + if(ob==G.obedit) { + if (U.uiflag & USER_CYCLE_SELMODE) + EM_selectmode_cycle(1); + else EM_selectmode_menu(); + } else if(G.f & G_SCULPTMODE) sculptmode_selectbrush_menu(); else set_wpaint(); } } } + else if(G.qual == (LR_SHIFTKEY | LR_CTRLKEY)) { + Object *ob= OBACT; + if(ob) { + if(ob->type==OB_MESH) { + if(ob==G.obedit) { + if (U.uiflag & USER_CYCLE_SELMODE) + EM_selectmode_cycle(0); + } + } + } + } break; case BACKSPACEKEY: @@ -738,11 +764,11 @@ case AKEY: if(textediting==0 && textspace==0) { if(G.qual==(LR_SHIFTKEY|LR_ALTKEY)){ - play_anim(1); + play_anim(0); return 0; } else if(G.qual==LR_ALTKEY) { - play_anim(0); + play_anim(1); return 0; } } Index: source/blender/src/editsima.c =================================================================== --- source/blender/src/editsima.c (revision 12209) +++ source/blender/src/editsima.c (working copy) @@ -2078,7 +2078,7 @@ { static int width= 256, height= 256; static short uvtestgrid= 0; - static float color[] = {0, 0, 0, 1}; + static float color[] = {1, 1, 1, 1}; char name[22]; Image *ima; Index: source/blender/src/header_seq.c =================================================================== --- source/blender/src/header_seq.c (revision 12209) +++ source/blender/src/header_seq.c (working copy) @@ -614,10 +614,15 @@ xco+= 8 + XIC*3.5; } - - /* ZOOM and BORDER */ + /* RENDER */ xco+= 8; uiBlockBeginAlign(block); + uiDefIconButS(block, ICONTOG, 1, ICON_VIEWZOOM, xco,0,XIC,YIC, &(sseq->render), 0, 0, 0, 0, "Toggles rendering"); /* fix icon */ + uiBlockEndAlign(block); + + /* ZOOM and BORDER */ + xco+= 8 + XIC+10; + uiBlockBeginAlign(block); uiDefIconButI(block, TOG, B_VIEW2DZOOM, ICON_VIEWZOOM, xco,0,XIC,YIC, &viewmovetemp, 0, 0, 0, 0, "Zooms view in and out (Ctrl MiddleMouse)"); uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to fit area"); uiBlockEndAlign(block); Index: source/blender/src/buttons_scene.c =================================================================== --- source/blender/src/buttons_scene.c (revision 12209) +++ source/blender/src/buttons_scene.c (working copy) @@ -1317,11 +1317,12 @@ uiDefButBitI(block, TOG, R_RADIO, B_REDR,"Radio", 647,142,40,29, &G.scene->r.mode, 0, 0, 0, 0, "Enable radiosity rendering"); uiBlockEndAlign(block); - uiBlockBeginAlign(block); + uiBlockBeginAlign(block);/* uiDefButS(block, ROW,B_DIFF,"100%", 565,109,122,20,&G.scene->r.size,1.0,100.0, 0, 0, "Set render size to defined size"); uiDefButS(block, ROW,B_DIFF,"75%", 565,88,40,20,&G.scene->r.size,1.0,75.0, 0, 0, "Set render size to 3/4 of defined size"); uiDefButS(block, ROW,B_DIFF,"50%", 606,88,40,20,&G.scene->r.size,1.0,50.0, 0, 0, "Set render size to 1/2 of defined size"); - uiDefButS(block, ROW,B_DIFF,"25%", 647,88,40,20,&G.scene->r.size,1.0,25.0, 0, 0, "Set render size to 1/4 of defined size"); + uiDefButS(block, ROW,B_DIFF,"25%", 647,88,40,20,&G.scene->r.size,1.0,25.0, 0, 0, "Set render size to 1/4 of defined size"); */ + uiDefButS(block, NUM,B_DIFF,"Size (%):",565,88,122,20,&G.scene->r.size,1.0, 200.0, 0, 0, "Render size"); uiBlockEndAlign(block); uiBlockBeginAlign(block); @@ -1905,7 +1906,8 @@ uiDefButBitI(block, TOG, SCE_PASS_VECTOR, B_SET_PASS,"Vec", 120, 30, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Speed Vector pass"); uiDefButBitI(block, TOG, SCE_PASS_NORMAL, B_SET_PASS,"Nor", 160, 30, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Normal pass"); uiDefButBitI(block, TOG, SCE_PASS_UV, B_SET_PASS,"UV", 200, 30, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Texture UV pass"); - uiDefButBitI(block, TOG, SCE_PASS_INDEXOB, B_SET_PASS,"IndexOb",240, 30, 70, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Object Index pass"); + uiDefButBitI(block, TOG, SCE_PASS_INDEXOB, B_SET_PASS,"IndexOb",240, 30, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Object Index pass"); + uiDefButBitI(block, TOG, SCE_PASS_INDEXMAT, B_SET_PASS,"IndexMat",275, 30, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Material Index pass"); uiDefButBitI(block, TOG, SCE_PASS_RGBA, B_SET_PASS,"Col", 10, 10, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver shade-less Color pass"); uiDefButBitI(block, TOG, SCE_PASS_DIFFUSE, B_SET_PASS,"Diff", 45, 10, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass"); Index: source/blender/src/drawseq.c =================================================================== --- source/blender/src/drawseq.c (revision 12209) +++ source/blender/src/drawseq.c (working copy) @@ -789,10 +789,12 @@ return; else { recursive= 1; - if (!U.prefetchframes || (G.f & G_PLAYANIM) == 0) { - ibuf= (ImBuf *)give_ibuf_seq(rectx, recty, (G.scene->r.cfra), sseq->chanshown); - } else { - ibuf= (ImBuf *)give_ibuf_threaded(rectx, recty, (G.scene->r.cfra), sseq->chanshown); + if(sseq->render) { + if (!U.prefetchframes || (G.f & G_PLAYANIM) == 0) { + ibuf= (ImBuf *)give_ibuf_seq(rectx, recty, (G.scene->r.cfra), sseq->chanshown); + } else { + ibuf= (ImBuf *)give_ibuf_threaded(rectx, recty, (G.scene->r.cfra), sseq->chanshown); + } } recursive= 0; Index: source/blender/src/header_view3d.c =================================================================== --- source/blender/src/header_view3d.c (revision 12209) +++ source/blender/src/header_view3d.c (working copy) @@ -862,6 +862,7 @@ case 6: /* Objects on Shared Layers */ case 7: /* Objects in Same Group */ case 8: /* Object Hooks*/ + case 9: /* Index Object */ select_object_grouped((short)event); break; } @@ -884,7 +885,8 @@ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Objects on Shared Layers|Shift G, 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Objects in Same Group|Shift G, 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Object Hooks|Shift G, 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, ""); - + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Index Object|Shift G, 9", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, ""); + uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); return block; @@ -2090,6 +2092,7 @@ case 25: case 26: case 29: + case 30: copy_attr((short)event); break; } @@ -2153,6 +2156,8 @@ if( give_parteff(ob) ) { uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Particle Settings|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); } + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Index Object|Ctrl C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 30, ""); } uiBlockSetDirection(block, UI_RIGHT); @@ -4956,9 +4961,37 @@ *xcoord= xco; } +/* layer is given in 0-19. */ +/* returns 1 if the given layer has an object, else 0 */ +static int nonvisiblelayerhasobject(int layer) +{ + Base *base; + int baselayer, i; + + base= FIRSTBASE; + while(base) { + if(!(base->lay & G.scene->lay) && base->object) { + i= 0; + baselayer= base->lay; + + while(baselayer>0) { + baselayer>>= 1; + i++; + } + + if(i == layer+1) + return 1; + } + base= base->next; + } + + return 0; +} + void view3d_buttons(void) { uiBlock *block; + uiBut *but; Object *ob= OBACT; int a; short xco = 0; @@ -5095,18 +5128,32 @@ /* LAYERS */ if(G.obedit==NULL && G.vd->localview==0) { uiBlockBeginAlign(block); - for(a=0; a<5; a++) - uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); - for(a=0; a<5; a++) - uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - + for(a=0; a<5; a++) { + but= uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); + + if(nonvisiblelayerhasobject(a)) + uiButSetCol(but, TH_LAYER_COLOR_NE); + } + for(a=0; a<5; a++) { + but= uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + + if(nonvisiblelayerhasobject(a+10)) + uiButSetCol(but, TH_LAYER_COLOR_NE); + } xco+= 5; uiBlockBeginAlign(block); - for(a=5; a<10; a++) - uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); - for(a=5; a<10; a++) - uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - + for(a=5; a<10; a++) { + but= uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); + + if(nonvisiblelayerhasobject(a)) + uiButSetCol(but, TH_LAYER_COLOR_NE); + } + for(a=5; a<10; a++) { + but= uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + + if(nonvisiblelayerhasobject(a+10)) + uiButSetCol(but, TH_LAYER_COLOR_NE); + } uiBlockEndAlign(block); xco+= (a-2)*(XIC/2)+3; @@ -5152,11 +5199,11 @@ /* selection modus */ if(G.obedit && (G.obedit->type == OB_MESH)) { uiBlockBeginAlign(block); - uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode (Ctrl Tab 1)"); + uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode (Alt 1)"); xco+= XIC; - uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode (Ctrl Tab 2)"); + uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode (Alt 2)"); xco+= XIC; - uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode (Ctrl Tab 3)"); + uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode (Alt 3)"); xco+= XIC; uiBlockEndAlign(block); if(G.vd->drawtype > OB_WIRE) { Index: source/blender/src/toolbox.c =================================================================== --- source/blender/src/toolbox.c (revision 12209) +++ source/blender/src/toolbox.c (working copy) @@ -893,6 +893,7 @@ { 0, "Objects on Shared Layers|Shift G, 6", 6, NULL}, { 0, "Objects in Same Group|Shift G, 7", 7, NULL}, { 0, "Object Hooks|Shift G, 8", 8, NULL}, +{ 0, "Index Object|Shift G, 9", 9, NULL}, { -1, "", 0, do_view3d_select_object_groupedmenu}}; static TBitem tb_object_select[]= { Index: source/blender/src/view.c =================================================================== --- source/blender/src/view.c (revision 12209) +++ source/blender/src/view.c (working copy) @@ -543,7 +543,7 @@ float reverse, oldquat[4], q1[4], si, phi, dist0; float ofs[3], obofs[3]= {0.0f, 0.0f, 0.0f}; int firsttime=1; - short mvalball[2], mval[2], mvalo[2]; + short mvalball[2], mval[2], mvalo[2], mval_area[2]; short use_sel = 0; short preview3d_event= 1; @@ -561,6 +561,7 @@ QUATCOPY(oldquat, G.vd->viewquat); + getmouseco_areawin(mval_area); /* for zoom to mouse loc */ getmouseco_sc(mvalo); /* work with screen coordinates because of trackball function */ mvalball[0]= mvalo[0]; /* needed for turntable to work */ mvalball[1]= mvalo[1]; @@ -733,9 +734,10 @@ } } else if(mode==2) { + float zfac=1.0; if(U.viewzoom==USER_ZOOM_CONT) { // oldstyle zoom - G.vd->dist*= 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/1000.0; + zfac = 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/1000.0; } else if(U.viewzoom==USER_ZOOM_SCALE) { int ctr[2], len1, len2; @@ -747,14 +749,17 @@ len1 = (int)sqrt((ctr[0] - mval[0])*(ctr[0] - mval[0]) + (ctr[1] - mval[1])*(ctr[1] - mval[1])) + 5; len2 = (int)sqrt((ctr[0] - mvalo[0])*(ctr[0] - mvalo[0]) + (ctr[1] - mvalo[1])*(ctr[1] - mvalo[1])) + 5; - G.vd->dist= dist0 * ((float)len2/len1); + zfac = dist0 * ((float)len2/len1) / G.vd->dist; } else { /* USER_ZOOM_DOLLY */ float len1 = (curarea->winrct.ymax - mval[1]) + 5; float len2 = (curarea->winrct.ymax - mvalo[1]) + 5; - - G.vd->dist= dist0 * (2.0*((len2/len1)-1.0) + 1.0); + zfac = dist0 * (2.0*((len2/len1)-1.0) + 1.0) / G.vd->dist; } + + if(zfac != 1.0 && zfac*G.vd->dist > 0.001*G.vd->grid && + zfac*G.vd->dist < 10.0*G.vd->far) + view_zoom_mouseloc(zfac, mval_area); /* these limits are in toets.c too */ if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid; @@ -804,7 +809,51 @@ BIF_view3d_previewrender_signal(curarea, PR_PROJECTED); } + +void view_zoom_mouseloc(float dfac, short *mouseloc) +{ + //if(U.uiflag & USER_MOUSEPOSDOLLY) { + if (1) { + short vb[2]; + float dvec[3]; + float tvec[3]; + float tpos[3]; + float new_dist; + /* find the current window width and height */ + vb[0] = G.vd->area->winx; + vb[1] = G.vd->area->winy; + + tpos[0] = -G.vd->ofs[0]; + tpos[1] = -G.vd->ofs[1]; + tpos[2] = -G.vd->ofs[2]; + + /* Project cursor position into 3D space */ + initgrabz(tpos[0], tpos[1], tpos[2]); + window_to_3d(dvec, mouseloc[0]-vb[0]/2, mouseloc[1]-vb[1]/2); + + /* Calculate view target position for dolly */ + tvec[0] = -(tpos[0] + dvec[0]); + tvec[1] = -(tpos[1] + dvec[1]); + tvec[2] = -(tpos[2] + dvec[2]); + + /* Offset to target position and dolly */ + new_dist = G.vd->dist * dfac; + + VECCOPY(G.vd->ofs, tvec); + G.vd->dist = new_dist; + + /* Calculate final offset */ + dvec[0] = tvec[0] + dvec[0] * dfac; + dvec[1] = tvec[1] + dvec[1] * dfac; + dvec[2] = tvec[2] + dvec[2] * dfac; + + VECCOPY(G.vd->ofs, dvec); + } else { + G.vd->dist *= dfac; + } +} + /* Gets the lens and clipping values from a camera of lamp type object */ void object_view_settings(Object *ob, float *lens, float *clipsta, float *clipend) { @@ -1315,6 +1364,8 @@ if (G.vd->persp>1) G.vd->persp= 1; if (G.vd->near> 0.1) G.vd->near= 0.1; + //if (G.vd->near> 0.01) G.vd->near= 0.01; + /* changed this to smaller value (0.1 before). */ /* it's possibly a bit slower but at least it doesn't have to be tweaked anymore. not working atm */ G.vd->cursor[0]= -G.vd->ofs[0]; G.vd->cursor[1]= -G.vd->ofs[1]; Index: source/blender/src/editobject.c =================================================================== --- source/blender/src/editobject.c (revision 12209) +++ source/blender/src/editobject.c (working copy) @@ -2191,8 +2191,8 @@ { static short numcuts= 2; Object *ob= OBACT; - float fac; - int nr,ret; + float fac, doublimit; + int count,nr,ret; short randfac; if(ob==NULL) return; @@ -2429,8 +2429,19 @@ mergemenu(); break; case 5: - notice("Removed %d Vertices", removedoublesflag(1, G.scene->toolsettings->doublimit)); - BIF_undo_push("Remove Doubles"); + doublimit= G.scene->toolsettings->doublimit; + if(fbutton(&doublimit, 0.0f, 1.0f, 10,10, "Limit:")==0) return; + waitcursor(1); + + G.scene->toolsettings->doublimit= doublimit; + count= removedoublesflag(1, G.scene->toolsettings->doublimit); + notice("Removed: %d", count); + if (count) { /* only undo and redraw if an action is taken */ + countall (); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 0); + BIF_undo_push("Rem Doubles"); + } break; case 6: hide_mesh(0); @@ -3382,6 +3393,9 @@ else if(event==29) { /* protected bits */ base->object->protectflag= ob->protectflag; } + else if(event==30) { /* index object */ + base->object->index= ob->index; + } } } base= base->next; @@ -3444,6 +3458,8 @@ if(ob->soft) strcat(str, "|Soft Body Settings%x23"); + strcat(str, "|Index Object%x30"); + if(ob->type==OB_MESH || ob->type==OB_CURVE || ob->type==OB_LATTICE || ob->type==OB_SURF){ strcat(str, "|Modifiers ...%x24"); } @@ -3951,11 +3967,14 @@ getmouseco_areawin(mval); if(abs(mval[0]-xo)+abs(mval[1]-yo) > 10) { if(curarea->spacetype==SPACE_VIEW3D) { -#ifdef TWEAK_MODE - initTransform(TFM_TRANSLATION, CTX_TWEAK); -#else - initTransform(TFM_TRANSLATION, CTX_NONE); -#endif + if(!(U.flag & USER_TWEAKMODE)) + { + initTransform(TFM_TRANSLATION, CTX_TWEAK); + } + else + { + initTransform(TFM_TRANSLATION, CTX_NONE); + } Transform(); } else if(curarea->spacetype==SPACE_IMAGE) { Index: source/blender/src/editmesh_mods.c =================================================================== --- source/blender/src/editmesh_mods.c (revision 12209) +++ source/blender/src/editmesh_mods.c (working copy) @@ -118,10 +118,11 @@ if(G.scene->selectmode & SCE_SELECT_VERTEX) { EditMesh *em = G.editMesh; EditVert *eve, *v1; + int mirror = G.scene->toolsettings->mirror; for(eve= em->verts.first; eve; eve= eve->next) { if(eve->f & SELECT) { - v1= editmesh_get_x_mirror_vert(G.obedit, eve->co); + v1= editmesh_get_mirror_vert(G.obedit, eve->co, mirror); if(v1) { eve->f &= ~SELECT; v1->f |= SELECT; @@ -3194,8 +3195,66 @@ EM_selectmode_flush(); } +void EM_selectmode_cycle(unsigned int direction) +{ + int selectModes[] = {SCE_SELECT_VERTEX, SCE_SELECT_VERTEX_AND_EDGE, SCE_SELECT_EDGE, SCE_SELECT_EDGE_AND_FACE, SCE_SELECT_FACE, SCE_SELECT_VERTEX_AND_FACE}; + const char *undoStrings[] = {"Vertex","Vertex\\Edge","Edge","Edge\\Face","Face","Vertex\\Face"}; + int amountOfSelectModes = 6; + + static char undoBegin[] = "Selectmode Set: "; + static char undoEnd[] = " "; + + int i = 0; + + /*the user can select all selection modes at once which is not in the + sequence. this exceptional case is handled here*/ + if (G.scene->selectmode == SCE_SELECT_VERTEX_AND_EDGE_AND_FACE) { + G.scene->selectmode= SCE_SELECT_VERTEX; + EM_selectmode_set(); + countall(); + BIF_undo_push("Selectmode Set: Vertex "); + } + else { + for(i; iselectmode == selectModes[i]) { + G.scene->selectmode= selectModes[j]; + EM_selectmode_set(); + countall(); + char *undoText = strcat(undoBegin, undoStrings[j]); + BIF_undo_push(strcat(undoText, undoEnd)); + break; + } + } + //backwards + else { + if (G.scene->selectmode == selectModes[i]) { + int j = i-1; + /*special case in which we have to "jump" to end*/ + if (i == 0) { + j = amountOfSelectModes-1; + } + G.scene->selectmode= selectModes[j]; + EM_selectmode_set(); + countall(); + char *undoText = strcat(undoBegin, undoStrings[j]); + BIF_undo_push(strcat(undoText, undoEnd)); + break; + } + } + } + } + allqueue(REDRAWVIEW3D, 1); +} + void EM_selectmode_menu(void) -{ +{ int val; if(G.scene->selectmode & SCE_SELECT_VERTEX) pupmenu_set_active(1); @@ -4112,4 +4171,3 @@ #endif BIF_undo_push("To Sphere"); } - Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 12209) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -5644,7 +5644,7 @@ } } } - } + } } @@ -6729,6 +6729,53 @@ } } + if(main->versionfile != 245 || main->subversionfile < 4) { + /* Initialize Tiles texture */ + Tex *tex; + for(tex= main->tex.first; tex; tex= tex->id.next) { + 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->fhue = 0; + tex->fsat = 0; + tex->fval = 0; + tex->minbump = 0; + tex->maxbump = 1; + tiles_precalc(tex); + } + } + for(ma=main->mat.first; ma; ma= ma->id.next) { if (ma->samp_gloss_mir == 0) { ma->gloss_mir = ma->gloss_tra= 1.0; @@ -6743,11 +6790,47 @@ } if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) { - Image *ima; + Image *ima; + Ipo *ipo; + bScreen *sc; + /* initialize 1:1 Aspect */ for(ima= main->image.first; ima; ima= ima->id.next) { ima->aspx = ima->aspy = 1.0f; } + + /* set clip start values of the 3d views */ + /* + sc = main->screen.first; + while(sc) { + ScrArea *sa= sc->areabase.first; + while(sa) { + SpaceLink *sl= sa->spacedata.first; + while (sl) { + if (sl->spacetype==SPACE_VIEW3D) { + View3D *v3d= (View3D*) sl; + + v3d->near= 0.001f; + } + sl= sl->next; + } + sa= sa->next; + } + sc= sc->id.next; + } + */ + + /* update ipo driver factors */ + ipo= main->ipo.first; + while(ipo) { + IpoCurve *icu; + for(icu= ipo->curve.first; icu; icu= icu->next) { + if(icu->driver) { + icu->driver->fac= 1.0; + } + } + ipo= ipo->id.next; + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ Index: source/blender/nodes/intern/SHD_nodes/SHD_texture.c =================================================================== --- source/blender/nodes/intern/SHD_nodes/SHD_texture.c (revision 12209) +++ source/blender/nodes/intern/SHD_nodes/SHD_texture.c (working copy) @@ -59,7 +59,7 @@ if(in[0]->datatype==NS_OSA_VECTORS) { float *fp= in[0]->data; - retval= multitex_ext((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres); + retval= multitex_ext((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres, shi); } else if(in[0]->datatype==NS_OSA_VALUES) { float *fp= in[0]->data; @@ -67,14 +67,14 @@ dxt[0]= fp[0]; dxt[1]= dxt[2]= 0.0f; dyt[0]= fp[1]; dyt[1]= dyt[2]= 0.0f; - retval= multitex_ext((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres); + retval= multitex_ext((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, shi); } else - retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres); + retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres, shi); } else { /* only for previewrender, so we see stuff */ VECCOPY(vec, shi->lo); - retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres); + retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres, shi); } /* stupid exception */ Index: source/blender/nodes/intern/SHD_nodes/SHD_brightness.c =================================================================== --- source/blender/nodes/intern/SHD_nodes/SHD_brightness.c (revision 0) +++ source/blender/nodes/intern/SHD_nodes/SHD_brightness.c (revision 0) @@ -0,0 +1,98 @@ +/** + * + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../SHD_util.h" + +/* **************** BRIGHTNESS AND CONTRAST ******************** */ +static bNodeSocketType sh_node_brightcontrast_in[]= { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 1, "bright", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f}, + { SOCK_VALUE, 1, "contrast", 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f}, + { -1, 0, "" } +}; + +static bNodeSocketType sh_node_brightcontrast_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_exec_brightcontrast(void *data, bNode *node, bNodeStack **in, +bNodeStack **out) +{ + float i; + int c; + float a, b, contrast, brightness, delta, v; + float *incol = in[0]->vec; + float outcol[3]; + contrast = in[2]->vec[0]; + brightness = (float)(in[1]->vec[0]); + brightness = (brightness) / 100.0f; + delta = contrast / 200.0f; + a = 1.0f - delta * 2.0f; + /* + * The algorithm is by Werner D. Streidt + * (http://visca.com/ffactory/archives/5-99/msg00021.html) + * Extracted of OpenCV demhist.c + */ + if( contrast > 0 ) +{ + a = 1.0f / a; + b = a * (brightness - delta); + } + else + { + delta *= -1; + b = a * (brightness + delta); + } + + for(c=0; c<3; c++){ + i = incol[c] ; + v = a*i + b; + outcol[c] = v; + } + + VECCOPY(out[0]->vec, outcol); +} + +bNodeType sh_node_brightcontrast= { + /* *next,*prev */ NULL, NULL, + /* type code */ SH_NODE_BRIGHTCONTRAST, + /* name */ "Bright/Contrast", + /* width+range */ 140, 100, 320, + /* class+opts */ NODE_CLASS_OP_COLOR, NODE_OPTIONS, + /* input sock */ sh_node_brightcontrast_in, + /* output sock */ sh_node_brightcontrast_out, + /* storage */ "", + /* execfunc */ node_shader_exec_brightcontrast, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copysotragefunc */ NULL, + /* id */ NULL +}; Index: source/blender/nodes/intern/SHD_nodes/SHD_boolean.c =================================================================== --- source/blender/nodes/intern/SHD_nodes/SHD_boolean.c (revision 0) +++ source/blender/nodes/intern/SHD_nodes/SHD_boolean.c (revision 0) @@ -0,0 +1,77 @@ +/** + * + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Juho Vepsäläinen + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../SHD_util.h" + +/* **************** Boolean ******************** */ + +static bNodeSocketType sh_node_boolean_in[]= { + { SOCK_VALUE, 1, "Limit", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "Color1", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "Color2", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketType sh_node_boolean_out[]= { + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_exec_boolean(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + /* stack order in: fac, col1, col2 */ + float fac;; + float col1[3], col2[3]; + + nodestack_get_vec(&fac, SOCK_VALUE, in[0]); + CLAMP(fac, 0.0f, 1.0f); + + nodestack_get_vec(col1, SOCK_VECTOR, in[1]); + nodestack_get_vec(col2, SOCK_VECTOR, in[2]); + + boolean_operation(node->custom1, out[0]->vec, fac, col1, col2); +} + +bNodeType sh_node_boolean= { + /* *next,*prev */ NULL, NULL, + /* type code */ SH_NODE_BOOLEAN, + /* name */ "Boolean", + /* width+range */ 80, 40, 120, + /* class+opts */ NODE_CLASS_CONVERTOR, NODE_OPTIONS, + /* input sock */ sh_node_boolean_in, + /* output sock */ sh_node_boolean_out, + /* storage */ "", + /* execfunc */ node_shader_exec_boolean, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL + +}; Index: source/blender/nodes/intern/SHD_nodes/SHD_gamma.c =================================================================== --- source/blender/nodes/intern/SHD_nodes/SHD_gamma.c (revision 0) +++ source/blender/nodes/intern/SHD_nodes/SHD_gamma.c (revision 0) @@ -0,0 +1,76 @@ +/** + * + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../SHD_util.h" + + + +/* **************** GAMMA ******************** */ +static bNodeSocketType sh_node_gamma_in[]= { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 1, "Gamma", 1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 2.0f}, + { -1, 0, "" } +}; + +static bNodeSocketType sh_node_gamma_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_exec_gamma(void *data, bNode *node, bNodeStack **in, +bNodeStack **out) +{ + float *incol= in[0]->vec; + float fac= in[1]->vec[0]; + float outcol[3]; + int i= 0; + + for(i= 0; i<3; i++) { + outcol[i]= pow(incol[i], fac); + } + + VECCOPY(out[0]->vec, outcol); +} + +bNodeType sh_node_gamma= { + /* *next,*prev */ NULL, NULL, + /* type code */ SH_NODE_GAMMA, + /* name */ "Gamma", + /* width+range */ 140, 100, 320, + /* class+opts */ NODE_CLASS_OP_COLOR, NODE_OPTIONS, + /* input sock */ sh_node_gamma_in, + /* output sock */ sh_node_gamma_out, + /* storage */ "", + /* execfunc */ node_shader_exec_gamma, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copysotragefunc */ NULL, + /* id */ NULL +}; Index: source/blender/nodes/intern/SHD_nodes/SHD_mapping.c =================================================================== --- source/blender/nodes/intern/SHD_nodes/SHD_mapping.c (revision 12209) +++ source/blender/nodes/intern/SHD_nodes/SHD_mapping.c (working copy) @@ -61,6 +61,12 @@ if(vec[1]>texmap->max[1]) vec[1]= texmap->max[1]; if(vec[2]>texmap->max[2]) vec[2]= texmap->max[2]; } + + /* nasty hack to pass texmap wrap to shi. there might be a better way to handle wrap */ + if(data) { + ShadeInput *shi= ((ShaderCallData *)data)->shi; + shi->wrap= texmap->wrap; + } } Index: source/blender/nodes/intern/CMP_nodes/CMP_texture.c =================================================================== --- source/blender/nodes/intern/CMP_nodes/CMP_texture.c (revision 12209) +++ source/blender/nodes/intern/CMP_nodes/CMP_texture.c (working copy) @@ -56,7 +56,7 @@ vec[1]= size[1]*(yco + sock->ns.vec[1]); vec[2]= size[2]*sock->ns.vec[2]; - retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres); + retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres, NULL); if(type==CB_VAL) { if(texres.talpha) Index: source/blender/nodes/intern/CMP_nodes/CMP_blur.c =================================================================== --- source/blender/nodes/intern/CMP_nodes/CMP_blur.c (revision 12209) +++ source/blender/nodes/intern/CMP_nodes/CMP_blur.c (working copy) @@ -99,7 +99,11 @@ work= alloc_compbuf(imgx, imgy, img->type, 1); /* allocs */ /* horizontal */ - rad = scale*(float)nbd->sizex; + if(nbd->relative) + rad = scale*((float)nbd->percentx)*imgx; + else + rad = scale*(float)nbd->sizex; + if(rad>imgx/2) rad= imgx/2; else if(rad<1) @@ -145,7 +149,11 @@ /* vertical */ MEM_freeN(gausstab); - rad = scale*(float)nbd->sizey; + if(nbd->relative) + rad = scale*((float)nbd->percenty)*imgy; + else + rad = scale*(float)nbd->sizey; + if(rad>imgy/2) rad= imgy/2; else if(rad<1) @@ -212,14 +220,20 @@ wbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1); /* horizontal */ - radx = (float)nbd->sizex; + if(nbd->relative) + radx = ((float)nbd->percentx)*imgx; + else + radx = (float)nbd->sizex; if(radx>imgx/2) radx= imgx/2; else if(radx<1) radx= 1; /* vertical */ - rady = (float)nbd->sizey; + if(nbd->relative) + rady = ((float)nbd->percenty)*imgy; + else + rady = (float)nbd->sizey; if(rady>imgy/2) rady= imgy/2; else if(rady<1) @@ -344,14 +358,20 @@ float *src= NULL, *dest, *srcd= NULL; /* horizontal */ - radxf = fac*(float)nbd->sizex; + if(nbd->relative) + radxf = fac*((float)nbd->percentx)*imgx; + else + radxf = fac*(float)nbd->sizex; if(radxf>imgx/2.0f) radxf= imgx/2.0f; else if(radxf<1.0f) radxf= 1.0f; /* vertical */ - radyf = fac*(float)nbd->sizey; + if(nbd->relative) + radyf = fac*((float)nbd->percenty)*imgy; + else + radyf = fac*(float)nbd->sizey; if(radyf>imgy/2.0f) radyf= imgy/2.0f; else if(radyf<1.0f) @@ -462,14 +482,20 @@ blur_single_image(node, blurbuf, blurbuf, 1.0f); /* horizontal */ - radx = (float)nbd->sizex; + if(nbd->relative) + radx = ((float)nbd->percentx)*imgx; + else + radx = (float)nbd->sizex; if(radx>imgx/2) radx= imgx/2; else if(radx<1) radx= 1; /* vertical */ - rady = (float)nbd->sizey; + if(nbd->relative) + rady = ((float)nbd->percenty)*imgy; + else + rady = (float)nbd->sizey; if(rady>imgy/2) rady= imgy/2; else if(rady<1) @@ -573,7 +599,7 @@ /* make output size of input image */ new= alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */ - + /* accept image offsets from other nodes */ new->xof = img->xof; new->yof = img->yof; @@ -596,7 +622,9 @@ /* make output size of input image */ new= alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */ - + /* need to calculate the relative/pixel data */ + nbd->imageInputWidth=img->x; + nbd->imageInputHeight=img->y; /* accept image offsets from other nodes */ new->xof = img->xof; new->yof = img->yof; Index: source/blender/nodes/intern/CMP_nodes/CMP_image.c =================================================================== --- source/blender/nodes/intern/CMP_nodes/CMP_image.c (revision 12209) +++ source/blender/nodes/intern/CMP_nodes/CMP_image.c (working copy) @@ -48,6 +48,7 @@ { SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_RGBA, 0, "Radio", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 0, "IndexMat", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; @@ -149,6 +150,8 @@ out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO); if(out[RRES_OUT_INDEXOB]->hasoutput) out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB); + if(out[RRES_OUT_INDEXMAT]->hasoutput) + out[RRES_OUT_INDEXMAT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXMAT); }; @@ -236,7 +239,7 @@ CompBuf *buf; int buftype= CB_VEC3; - if(ELEM(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB)) + if(ELEM3(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_INDEXMAT)) buftype= CB_VAL; else if(passcode==SCE_PASS_VECTOR) buftype= CB_VEC4; @@ -283,6 +286,8 @@ out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO); if(out[RRES_OUT_INDEXOB]->hasoutput) out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB); + if(out[RRES_OUT_INDEXMAT]->hasoutput) + out[RRES_OUT_INDEXMAT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXMAT); }; Index: source/blender/nodes/intern/CMP_nodes/CMP_crop.c =================================================================== --- source/blender/nodes/intern/CMP_nodes/CMP_crop.c (revision 0) +++ source/blender/nodes/intern/CMP_nodes/CMP_crop.c (revision 0) @@ -0,0 +1,119 @@ +/** + * + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Juho Vepsäläinen + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../CMP_util.h" + +/* **************** Crop ******************** */ + +static bNodeSocketType cmp_node_crop_in[]= { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketType cmp_node_crop_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_composit_exec_crop(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + if(in[0]->data) { + NodeTwoXYs *ntxy= node->storage; + CompBuf *cbuf= in[0]->data; + CompBuf *stackbuf; + int x, y; + float *srcfp, *outfp; + rcti outputrect; + + /* check input image size */ + if(cbuf->x <= ntxy->x1 + 1) + ntxy->x1= cbuf->x - 1; + + if(cbuf->y <= ntxy->y1 + 1) + ntxy->y1= cbuf->y - 1; + + if(cbuf->x <= ntxy->x2 + 1) + ntxy->x2= cbuf->x - 1; + + if(cbuf->y <= ntxy->y2 + 1) + ntxy->y2= cbuf->y - 1; + + /* figure out the minimums and maximums */ + outputrect.xmax=MAX2(ntxy->x1, ntxy->x2) + 1; + outputrect.xmin=MIN2(ntxy->x1, ntxy->x1); + outputrect.ymax=MAX2(ntxy->y1, ntxy->y2) + 1; + outputrect.ymin=MIN2(ntxy->y1, ntxy->y2); + + if(node->custom1) { + /* this option crops the image size too */ + stackbuf= get_cropped_compbuf(&outputrect, cbuf->rect, cbuf->x, cbuf->y, cbuf->type); + } + else { + /* this option won't crop the size of the image as well */ + /* allocate memory for the output image */ + stackbuf = alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); + + /* select the cropped part of the image and set it to the output */ + for(y=outputrect.ymin; yrect + (y * cbuf->x + outputrect.xmin) * cbuf->type; + outfp= stackbuf->rect + (y * stackbuf->x + outputrect.xmin) * stackbuf->type; + for(x=outputrect.xmin; xtype, srcfp+= cbuf->type) + memcpy(outfp, srcfp, sizeof(float)*stackbuf->type); + } + } + + out[0]->data= stackbuf; + } +} + +static void node_composit_init_crop(bNode* node) +{ + NodeTwoXYs *nxy= MEM_callocN(sizeof(NodeTwoXYs), "node xy data"); + node->storage= nxy; + nxy->x1= 0; + nxy->x2= 0; + nxy->y1= 0; + nxy->y2= 0; +} + +bNodeType cmp_node_crop= { + /* *next,*prev */ NULL, NULL, + /* type code */ CMP_NODE_CROP, + /* name */ "Crop", + /* width+range */ 140, 100, 320, + /* class+opts */ NODE_CLASS_DISTORT, NODE_OPTIONS, + /* input sock */ cmp_node_crop_in, + /* output sock */ cmp_node_crop_out, + /* storage */ "NodeTwoXYs", + /* execfunc */ node_composit_exec_crop, + /* butfunc */ NULL, + /* initfunc */ node_composit_init_crop, + /* freestoragefunc */ node_free_standard_storage, + /* copystoragefunc */ node_copy_standard_storage, + /* id */ NULL +}; Index: source/blender/nodes/intern/CMP_nodes/CMP_boolean.c =================================================================== --- source/blender/nodes/intern/CMP_nodes/CMP_boolean.c (revision 0) +++ source/blender/nodes/intern/CMP_nodes/CMP_boolean.c (revision 0) @@ -0,0 +1,107 @@ +/** + * + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Juho Vepsäläinen + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../CMP_util.h" + +/* **************** Boolean ******************** */ + +static bNodeSocketType cmp_node_boolean_in[]= { + { SOCK_VALUE, 1, "Limit", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "A", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, "B", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketType cmp_node_boolean_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void do_boolean(bNode *node, float *out, float *limit, float *in1, float *in2) +{ + boolean_operation(node->custom1, out, *limit, in1, in2); +} + +static void node_composit_exec_boolean(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + if(out[0]->hasoutput==0) return; + + /* input no image? then only color operation */ + if(in[1]->data==NULL && in[2]->data==NULL) + do_boolean(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec); + else { + int stackbufheight, stackbufwidth, stackbuftype; + CompBuf *limit = in[0]->data; + CompBuf *cbuf1 = in[1]->data; + CompBuf *cbuf2 = in[2]->data; + CompBuf *stackbuf; + + /* set stackbuftype */ + if(cbuf1==NULL && cbuf2==NULL) + stackbuftype= CB_VAL; + else + stackbuftype= CB_RGBA; + + /* make output size the smallest possible */ + if(cbuf1==NULL) { + stackbufheight= cbuf2->y; + stackbufwidth= cbuf2->x; + } + else if(cbuf2==NULL) { + stackbufheight= cbuf1->y; + stackbufwidth= cbuf1->x; + } + else { + stackbufheight= MIN2(cbuf1->y,cbuf2->y); + stackbufwidth= MIN2(cbuf1->x,cbuf2->x); + } + + stackbuf = alloc_compbuf(stackbufwidth, stackbufheight, stackbuftype, 1); // allocs + + composit3_pixel_processor(node, stackbuf, limit, in[0]->vec, cbuf1, in[1]->vec, cbuf2, in[2]->vec, do_boolean, CB_VAL, CB_RGBA, CB_RGBA); + + out[0]->data= stackbuf; + } +} + +bNodeType cmp_node_boolean= { + /* *next,*prev */ NULL, NULL, + /* type code */ CMP_NODE_BOOLEAN, + /* name */ "Boolean", + /* width+range */ 80, 40, 120, + /* class+opts */ NODE_CLASS_CONVERTOR, NODE_OPTIONS, + /* input sock */ cmp_node_boolean_in, + /* output sock */ cmp_node_boolean_out, + /* storage */ "", + /* execfunc */ node_composit_exec_boolean, + /* butfunc */ NULL, + /* initfunc */ NULL, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, + /* id */ NULL +}; Index: source/blender/nodes/SHD_node.h =================================================================== --- source/blender/nodes/SHD_node.h (revision 12209) +++ source/blender/nodes/SHD_node.h (working copy) @@ -54,6 +54,7 @@ extern bNodeType sh_node_curve_vec; extern bNodeType sh_node_curve_rgb; extern bNodeType sh_node_math; +extern bNodeType sh_node_boolean; extern bNodeType sh_node_vect_math; extern bNodeType sh_node_squeeze; extern bNodeType sh_node_material_ext; @@ -61,8 +62,9 @@ extern bNodeType sh_node_seprgb; extern bNodeType sh_node_combrgb; extern bNodeType sh_node_hue_sat; +extern bNodeType sh_node_brightcontrast; +extern bNodeType sh_node_gamma; - #endif Index: source/blender/nodes/CMP_node.h =================================================================== --- source/blender/nodes/CMP_node.h (revision 12209) +++ source/blender/nodes/CMP_node.h (working copy) @@ -66,6 +66,7 @@ extern bNodeType cmp_node_filter; extern bNodeType cmp_node_blur; +extern bNodeType cmp_node_bilateralblur; extern bNodeType cmp_node_vecblur; extern bNodeType cmp_node_dilateerode; extern bNodeType cmp_node_defocus; @@ -75,6 +76,7 @@ extern bNodeType cmp_node_setalpha; extern bNodeType cmp_node_idmask; extern bNodeType cmp_node_math; +extern bNodeType cmp_node_boolean; extern bNodeType cmp_node_seprgba; extern bNodeType cmp_node_combrgba; extern bNodeType cmp_node_sephsva; @@ -94,6 +96,7 @@ extern bNodeType cmp_node_rotate; extern bNodeType cmp_node_scale; extern bNodeType cmp_node_flip; +extern bNodeType cmp_node_crop; extern bNodeType cmp_node_displace; extern bNodeType cmp_node_mapuv;