More compositing goodies.

- Texture Node
Allows to use any Blender Texture block as input for masks or color
blending. The texture node doesn't generate a real image, but adjusts to
the size as mapped with during an operation. So it won't work to use it
as Image input for Blur or Filter nodes.

Note; the Vector inputs for this node only work with manual input now!

- Translation Node
Give any image an offset in X or Y direction

For the Texture node to work, I needed to move the central 'pixel
processor' up one level... to allow differently sized images to merge
and allow 'procedural images' without size.

Temporal image of the day: http://www.blender.org/bf/rt.jpg
This commit is contained in:
2006-02-19 14:55:16 +00:00
parent f624730d26
commit 130c41c7ba
10 changed files with 365 additions and 293 deletions

View File

@@ -33,6 +33,7 @@
#ifndef BKE_NODE_H
#define BKE_NODE_H
struct ID;
struct bNodeTree;
struct bNode;
struct bNodeLink;
@@ -134,6 +135,7 @@ struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype);
void nodeClearActiveID(struct bNodeTree *ntree, short idtype);
void NodeTagChanged(struct bNodeTree *ntree, struct bNode *node);
void NodeTagIDChanged(struct bNodeTree *ntree, struct ID *id);
/* ************** Groups ****************** */
@@ -214,11 +216,12 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, str
#define CMP_NODE_SEPHSVA 217
#define CMP_NODE_SETALPHA 218
#define CMP_NODE_HUE_SAT 219
#define CMP_NODE_IMAGE 220
#define CMP_NODE_R_RESULT 221
#define CMP_NODE_COMPOSITE 222
#define CMP_NODE_OUTPUT_FILE 223
#define CMP_NODE_TEXTURE 224
#define CMP_NODE_TRANSLATE 225
/* filter types */

View File

@@ -1409,6 +1409,18 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node)
}
}
void NodeTagIDChanged(bNodeTree *ntree, ID *id)
{
if(ntree->type==NTREE_COMPOSIT) {
bNode *node;
for(node= ntree->nodes.first; node; node= node->next)
if(node->id==id)
NodeTagChanged(ntree, node);
}
}
#pragma mark /* *************** preview *********** */
/* if node->preview, then we assume the rect to exist */

View File

@@ -56,16 +56,20 @@
#include "IMB_imbuf_types.h"
#include "RE_pipeline.h"
#include "RE_shader_ext.h" /* <- TexResult */
/* *************************** operations support *************************** */
/* general signal that's in output sockets, and goes over the wires */
typedef struct CompBuf {
float *rect;
int x, y;
int x, y, xrad, yrad;
short type, malloc;
rcti disprect; /* cropped part of image */
int xof, yof; /* relative to center of target image */
void (*rect_procedural)(struct CompBuf *, float *, float, float);
bNode *node;
} CompBuf;
/* defines also used for pixel size */
@@ -87,6 +91,9 @@ static CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc)
cbuf->x= sizex;
cbuf->y= sizey;
cbuf->xrad= sizex/2;
cbuf->yrad= sizey/2;
cbuf->type= type;
if(alloc) {
if(cbuf->type==CB_RGBA)
@@ -190,84 +197,45 @@ static CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy)
return outbuf;
}
float *compbuf_get_pixel(CompBuf *cbuf, float *rectf, int x, int y, int xrad, int yrad)
{
if(cbuf) {
if(cbuf->rect_procedural) {
cbuf->rect_procedural(cbuf, rectf, (float)x/(float)xrad, (float)y/(float)yrad);
return rectf;
}
else {
static float col[4]= {0.0f, 0.0f, 0.0f, 0.0f};
/* map coords */
x-= cbuf->xof;
y-= cbuf->yof;
if(y<-cbuf->yrad || y>= -cbuf->yrad+cbuf->y) return col;
if(x<-cbuf->xrad || x>= -cbuf->xrad+cbuf->x) return col;
return cbuf->rect + cbuf->type*( (cbuf->yrad+y)*cbuf->x + (cbuf->xrad+x) );
}
}
else return rectf;
}
/* **************************************************** */
#if 0
/* on first call, disprect should be initialized to 'out', then you can call this on all 'src' images */
static void get_overlap_rct(CompBuf *out, CompBuf *src, rcti *disprect)
{
rcti rect;
/* output center is considered (0,0) */
if(src==NULL) return;
/* translate src into output space */
rect= src->disprect;
BLI_translate_rcti(&rect, out->xof-src->xof, out->xof-src->xof);
/* intersect rect with current disprect */
BLI_isect_rcti(&rect, disprect, disprect);
}
static void get_scanline_rcti(CompBuf *out, rcti *disprect, CompBuf *src, rcti *srcrect)
{
int xof, yof;
/* translate src into output space */
xof= out->xof-src->xof;
yof= out->xof-src->xof;
srcrect->xmin= disprect->xmin + xof;
srcrect->ymin= disprect->ymin + yof;
srcrect->xmax= disprect->xmax + xof;
srcrect->ymax= disprect->ymax + yof;
}
#endif
/* Pixel-to-Pixel operation, 1 Image in, 1 out */
static void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
void (*func)(bNode *, float *, float *))
{
float *outfp, *srcfp, *out_data, *src_data;
int outx, outy;
int srcx, srcy;
int out_pix, out_stride, src_stride, src_pix, x, y;
float *outfp=out->rect, *srcfp;
int xrad, yrad, x, y;
outx= out->x;
outy= out->y;
out_pix= out->type;
out_stride= out->x;
out_data= out->rect;
xrad= out->xrad;
yrad= out->yrad;
/* handle case when input is constant color */
if(src_buf==NULL) {
srcx= outx; srcy= outy;
src_stride= 0;
src_pix= 0;
src_data= src_col;
}
else {
srcx= src_buf->x;
srcy= src_buf->y;
src_stride= srcx;
src_pix= src_buf->type;
src_data= src_buf->rect;
}
outx= MIN2(outx, srcx);
outy= MIN2(outy, srcy);
for(y=0; y<outy; y++) {
/* set scanlines on right location */
srcfp= src_data + src_pix*y*src_stride;
outfp= out_data + out_pix*y*out_stride;
for(x=0; x<outx; x++) {
for(y= -yrad; y<-yrad+out->y; y++) {
for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
srcfp= compbuf_get_pixel(src_buf, src_col, x, y, xrad, yrad);
func(node, outfp, srcfp);
srcfp += src_pix;
outfp += out_pix;
}
}
}
@@ -276,100 +244,18 @@ static void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_bu
static void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *))
{
float *outfp, *srcfp, *src_data, *facfp, *fac_data;
int outx= out->x, outy= out->y;
int srcx, srcy, facx, facy;
int out_pix, src_stride, src_pix, fac_stride, fac_pix, x, y;
float *outfp=out->rect, *srcfp, *facfp;
int xrad, yrad, x, y;
out_pix= out->type;
xrad= out->xrad;
yrad= out->yrad;
/* handle case when input is constant color */
if(src_buf==NULL) {
srcx= outx; srcy= outy;
src_stride= 0;
src_pix= 0;
src_data= src_col;
}
else {
srcx= src_buf->x;
srcy= src_buf->y;
src_stride= srcx;
src_pix= src_buf->type;
src_data= src_buf->rect;
}
/* factor buf or constant? */
if(fac_buf==NULL) {
facx= outx; facy= outy;
fac_stride= 0;
fac_pix= 0;
fac_data= fac;
}
else {
facx= fac_buf->x;
facy= fac_buf->y;
fac_stride= facx;
fac_pix= fac_buf->type;
fac_data= fac_buf->rect;
}
if(fac_data==NULL) {
printf("fac buffer error, node %s\n", node->name);
return;
}
facx= MIN2(facx, srcx);
facy= MIN2(facy, srcy);
#if 0
if(src_buf) {
rcti disprect;
disprect= out->disprect;
get_overlap_rct(out, src_buf, &disprect);
printf("%s\n", node->name);
printf("union %d %d %d %d\n", disprect.xmin,disprect.ymin,disprect.xmax,disprect.ymax);
}
/* new approach */
outfp= out->rect_float + src.ymin*outx + ;
for(y=src.ymin; y<src.ymax; y++) {
/* all operators available */
if(y>=disp.ymin && y<disp.ymax) {
srcfp= src_data + (src_stride*(y+scrc.ymin) + src.xmin);
facfp= fac_data + (fac_stride*(y+fac.ymin) + fac.xmin);
for(y= -yrad; y<-yrad+out->y; y++) {
for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
srcfp= compbuf_get_pixel(src_buf, src_col, x, y, xrad, yrad);
facfp= compbuf_get_pixel(fac_buf, fac, x, y, xrad, yrad);
for(x= src.xmin; x<src.xmax; x++) {
if(x>=disp.xmin && x<disp.xmax) {
srcfp+= src_pix;
facfp+= fac_pix;
}
else {
/* copy src1 */
}
}
}
else {
/* copy src1 */
srcfp= src_data + (src_stride*(y+scrc.ymin) + src.xmin);
QUATCOPY(outfp, srcfp);
}
}
#endif
outfp= out->rect;
for(y=0; y<outy; y++) {
/* set source scanline on right location */
srcfp= src_data + src_pix*y*src_stride;
facfp= fac_data + fac_pix*y*fac_stride;
for(x=0; x<outx; x++, outfp+=out_pix) {
if(x<facx && y<facy)
func(node, outfp, srcfp, facfp);
srcfp += src_pix;
facfp += fac_pix;
func(node, outfp, srcfp, facfp);
}
}
}
@@ -378,72 +264,19 @@ static void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_bu
static void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col,
CompBuf *fac_buf, float fac, void (*func)(bNode *, float *, float *, float *, float))
{
float *outfp, *src1fp, *src2fp, *facfp, *src1_data, *src2_data, *fac_data;
int outx= out->x, outy= out->y;
int src1x, src1y, src2x, src2y, facx, facy;
int src1_stride, src1_pix, src2_stride, src2_pix, fac_stride, fac_pix, x, y;
/* handle case when input has constant color */
if(src1_buf==NULL) {
src1x= outx; src1y= outy;
src1_stride= 0;
src1_pix= 0;
src1_data= src1_col;
}
else {
src1x= src1_buf->x;
src1y= src1_buf->y;
src1_stride= src1x;
src1_pix= src1_buf->type;
src1_data= src1_buf->rect;
}
float *outfp=out->rect, *src1fp, *src2fp, *facfp;
int xrad, yrad, x, y;
if(src2_buf==NULL) {
src2x= outx; src2y= outy;
src2_stride= 0;
src2_pix= 0;
src2_data= src2_col;
}
else {
src2x= src2_buf->x;
src2y= src2_buf->y;
src2_stride= src2x;
src2_pix= src2_buf->type;
src2_data= src2_buf->rect;
}
xrad= out->xrad;
yrad= out->yrad;
/* factor buf or constant? */
if(fac_buf==NULL) {
facx= outx; facy= outy;
fac_stride= 0;
fac_pix= 0;
fac_data= &fac;
}
else {
facx= fac_buf->x;
facy= fac_buf->y;
fac_stride= facx;
fac_pix= 1;
fac_data= fac_buf->rect;
}
facx= MIN3(facx, src1x, src2x);
facy= MIN3(facy, src1y, src2y);
outfp= out->rect;
for(y=0; y<outy; y++) {
/* set source scanlines on right location */
src1fp= src1_data + src1_pix*y*src1_stride;
src2fp= src2_data + src2_pix*y*src2_stride;
facfp= fac_data + y*fac_stride;
for(x=0; x<outx; x++, outfp+=4) {
if(x<facx && y<facy)
func(node, outfp, src1fp, src2fp, *facfp);
src1fp+= src1_pix;
src2fp+= src2_pix;
facfp+= fac_pix;
for(y= -yrad; y<-yrad+out->y; y++) {
for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
src1fp= compbuf_get_pixel(src1_buf, src1_col, x, y, xrad, yrad);
src2fp= compbuf_get_pixel(src2_buf, src2_col, x, y, xrad, yrad);
facfp= compbuf_get_pixel(fac_buf, &fac, x, y, xrad, yrad);
func(node, outfp, src1fp, src2fp, *facfp);
}
}
}
@@ -474,6 +307,8 @@ static void generate_preview(bNode *node, CompBuf *stackbuf)
if(preview && stackbuf) {
CompBuf *cbuf;
if(stackbuf->rect==NULL) return;
if(stackbuf->x > stackbuf->y) {
preview->xsize= 140;
preview->ysize= (140*stackbuf->y)/stackbuf->x;
@@ -1044,6 +879,107 @@ static bNodeType cmp_node_rresult= {
};
/* **************** TEXTURE ******************** */
static bNodeSocketType cmp_node_texture_in[]= {
{ SOCK_VECTOR, 0, "Offset", 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f},
{ SOCK_VECTOR, 0, "Scale", 1.0f, 1.0f, 1.0f, 1.0f, -10.0f, 10.0f},
{ -1, 0, "" }
};
static bNodeSocketType cmp_node_texture_out[]= {
{ SOCK_VALUE, 0, "Value", 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_RGBA , 0, "Color", 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
/* called without rect allocated */
static void texture_procedural(CompBuf *cbuf, float *col, float xco, float yco)
{
bNode *node= cbuf->node;
bNodeSocket *sock= node->inputs.first;
TexResult texres;
float vec[3], *size, nor[3]={0.0f, 0.0f, 0.0f};
int retval, type= cbuf->type;
texres.nor= NULL;
size= sock->next->ns.vec;
vec[0]= size[0]*(xco + sock->ns.vec[0]);
vec[1]= size[1]*(yco + sock->ns.vec[1]);
vec[2]= size[2]*sock->ns.vec[2];
retval= multitex((Tex *)node->id, vec, NULL, NULL, 0, &texres);
if(type==1) {
if(texres.talpha)
col[0]= texres.ta;
else
col[0]= texres.tin;
}
else if(type==4) {
if(texres.talpha)
col[3]= texres.ta;
else
col[3]= texres.tin;
if((retval & TEX_RGB)) {
col[0]= texres.tr;
col[1]= texres.tg;
col[2]= texres.tb;
}
else col[0]= col[1]= col[2]= col[3];
}
else {
VECCOPY(col, nor);
}
}
/* texture node outputs get a small rect, to make sure all other nodes accept it */
/* only the pixel-processor nodes do something with it though */
static void node_composit_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
/* outputs: value, color, normal */
if(node->id) {
/* first make the preview image */
CompBuf *prevbuf= alloc_compbuf(140, 140, CB_RGBA, 1); // alloc
prevbuf->rect_procedural= texture_procedural;
prevbuf->node= node;
composit1_pixel_processor(node, prevbuf, prevbuf, out[0]->vec, do_copy_rgba);
generate_preview(node, prevbuf);
free_compbuf(prevbuf);
if(out[0]->hasoutput) {
CompBuf *stackbuf= alloc_compbuf(140, 140, CB_VAL, 1); // alloc
stackbuf->rect_procedural= texture_procedural;
stackbuf->node= node;
out[0]->data= stackbuf;
}
if(out[1]->hasoutput) {
CompBuf *stackbuf= alloc_compbuf(140, 140, CB_RGBA, 1); // alloc
stackbuf->rect_procedural= texture_procedural;
stackbuf->node= node;
out[1]->data= stackbuf;
}
}
}
static bNodeType cmp_node_texture= {
/* type code */ CMP_NODE_TEXTURE,
/* name */ "Texture",
/* width+range */ 120, 80, 240,
/* class+opts */ NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW,
/* input sock */ cmp_node_texture_in,
/* output sock */ cmp_node_texture_out,
/* storage */ "",
/* execfunc */ node_composit_exec_texture
};
/* **************** NORMAL ******************** */
static bNodeSocketType cmp_node_normal_in[]= {
{ SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
@@ -1083,7 +1019,7 @@ static void node_composit_exec_normal(void *data, bNode *node, bNodeStack **in,
CompBuf *cbuf= in[0]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocs
composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_normal);
composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_normal);
out[1]->data= stackbuf;
}
@@ -1220,7 +1156,7 @@ static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **i
if(in[0]->data)
composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_curves_fac);
else
composit1_pixel_processor(node, stackbuf, in[1]->data, NULL, do_curves);
composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves);
out[0]->data= stackbuf;
}
@@ -1328,6 +1264,7 @@ static void node_composit_exec_hue_sat(void *data, bNode *node, bNodeStack **in,
{
/* stack order in: Fac, Image */
/* stack order out: Image */
if(out[0]->hasoutput==0) return;
/* input no image? then only color operation */
if(in[1]->data==NULL) {
@@ -1386,6 +1323,8 @@ static void node_composit_exec_mix_rgb(void *data, bNode *node, bNodeStack **in,
/* stack order out: Image */
float fac= in[0]->vec[0];
if(out[0]->hasoutput==0) return;
CLAMP(fac, 0.0f, 1.0f);
/* input no image? then only color operation */
@@ -1487,10 +1426,10 @@ static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
}
}
static float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f};
static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
static float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f};
float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1};
float laplace[9]= {1/8.0f, -1/8.0f, 1/8.0f, -1/8.0f, 1.0f, -1/8.0f, 1/8.0f, -1/8.0f, 1/8.0f};
float sobel[9]= {1,2,1,0,0,0,-1,-2,-1};
@@ -1498,6 +1437,8 @@ static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in,
float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2};
float shadow[9]= {1,2,1,0,1,0,-1,-2,-1};
if(out[0]->hasoutput==0) return;
/* stack order in: Image */
/* stack order out: Image */
@@ -1569,6 +1510,9 @@ static void node_composit_exec_valtorgb(void *data, bNode *node, bNodeStack **in
/* stack order in: fac */
/* stack order out: col, alpha */
if(out[0]->hasoutput==0 || out[1]->hasoutput==0)
return;
if(node->storage) {
/* input no image? then only color operation */
if(in[0]->data==NULL) {
@@ -1579,7 +1523,7 @@ static void node_composit_exec_valtorgb(void *data, bNode *node, bNodeStack **in
CompBuf *cbuf= in[0]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_colorband_composit);
composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_colorband_composit);
out[0]->data= stackbuf;
@@ -1623,6 +1567,9 @@ static void node_composit_exec_rgbtobw(void *data, bNode *node, bNodeStack **in,
/* stack order out: bw */
/* stack order in: col */
if(out[0]->hasoutput==0)
return;
/* input no image? then only color operation */
if(in[0]->data==NULL) {
do_rgbtobw(node, out[0]->vec, in[0]->vec);
@@ -1632,7 +1579,7 @@ static void node_composit_exec_rgbtobw(void *data, bNode *node, bNodeStack **in,
CompBuf *cbuf= in[0]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocs
composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_rgbtobw);
composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_rgbtobw);
out[0]->data= stackbuf;
}
@@ -1751,7 +1698,7 @@ static void node_composit_exec_sephsva(void *data, bNode *node, bNodeStack **in,
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
/* convert the RGB stackbuf to an HSV representation */
composit1_pixel_processor(node, stackbuf, in[0]->data, NULL, do_sephsva);
composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_sephsva);
/* separate each of those channels */
if(out[0]->hasoutput)
@@ -1854,20 +1801,11 @@ static void do_alphaover_premul(bNode *node, float *out, float *src, float *over
}
else {
float mul= 1.0f - over[3];
/* handle case where backdrop has no alpha, but still color */
if(src[0]==0.0f) {
out[0]= over[0];
out[1]= (mul*src[1]) + over[1];
out[2]= (mul*src[2]) + over[2];
out[3]= (mul*src[3]) + over[3];
}
else {
out[0]= (mul*src[0]) + over[0];
out[1]= (mul*src[1]) + over[1];
out[2]= (mul*src[2]) + over[2];
out[3]= (mul*src[3]) + over[3];
}
out[0]= (mul*src[0]) + over[0];
out[1]= (mul*src[1]) + over[1];
out[2]= (mul*src[2]) + over[2];
out[3]= (mul*src[3]) + over[3];
}
}
@@ -1884,20 +1822,11 @@ static void do_alphaover_key(bNode *node, float *out, float *src, float *over)
else {
float premul= over[3];
float mul= 1.0f - premul;
/* handle case where backdrop has no alpha, but still color */
if(src[0]==0.0f) {
out[0]= over[0];
out[1]= (mul*src[1]) + premul*over[1];
out[2]= (mul*src[2]) + premul*over[2];
out[3]= (mul*src[3]) + premul*over[3];
}
else {
out[0]= (mul*src[0]) + premul*over[0];
out[1]= (mul*src[1]) + premul*over[1];
out[2]= (mul*src[2]) + premul*over[2];
out[3]= (mul*src[3]) + premul*over[3];
}
out[0]= (mul*src[0]) + premul*over[0];
out[1]= (mul*src[1]) + premul*over[1];
out[2]= (mul*src[2]) + premul*over[2];
out[3]= (mul*src[3]) + premul*over[3];
}
}
@@ -1906,6 +1835,8 @@ static void node_composit_exec_alphaover(void *data, bNode *node, bNodeStack **i
{
/* stack order in: col col */
/* stack order out: col */
if(out[0]->hasoutput==0)
return;
/* input no image? then only color operation */
if(in[0]->data==NULL) {
@@ -1965,6 +1896,7 @@ static void node_composit_exec_map_value(void *data, bNode *node, bNodeStack **i
{
/* stack order in: col col */
/* stack order out: col */
if(out[0]->hasoutput==0) return;
/* input no image? then only value operation */
if(in[0]->data==NULL) {
@@ -2635,6 +2567,44 @@ static bNodeType cmp_node_vecblur= {
};
/* **************** Translate ******************** */
static bNodeSocketType cmp_node_translate_in[]= {
{ SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 0, "X", 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
{ SOCK_VALUE, 0, "Y", 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
{ -1, 0, "" }
};
static bNodeSocketType cmp_node_translate_out[]= {
{ SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
static void node_composit_exec_translate(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
if(in[0]->data) {
CompBuf *cbuf= in[0]->data;
CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 0); // no alloc
stackbuf->xof= (int)floor(in[1]->vec[0]);
stackbuf->yof= (int)floor(in[2]->vec[0]);
stackbuf->rect= cbuf->rect;
out[0]->data= stackbuf;
}
}
static bNodeType cmp_node_translate= {
/* type code */ CMP_NODE_TRANSLATE,
/* name */ "Translate",
/* width+range */ 140, 100, 320,
/* class+opts */ NODE_CLASS_CONVERTOR, NODE_OPTIONS,
/* input sock */ cmp_node_translate_in,
/* output sock */ cmp_node_translate_out,
/* storage */ "",
/* execfunc */ node_composit_exec_translate
};
/* ****************** types array for all shaders ****************** */
@@ -2663,6 +2633,8 @@ bNodeType *node_all_composit[]= {
&cmp_node_seprgba,
&cmp_node_sephsva,
&cmp_node_setalpha,
&cmp_node_texture,
&cmp_node_translate,
NULL
};

View File

@@ -579,6 +579,7 @@ void *add_lamp(void)
la->soft= 3.0;
la->ray_samp= la->ray_sampy= la->ray_sampz= 1;
la->area_size=la->area_sizey=la->area_sizez= 1.0;
la->buffers= 1;
return la;
}

View File

@@ -176,7 +176,6 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
#define B_MATPRV 1206
#define B_LAMPPRV 1207
#define B_WORLDPRV 1208
#define B_TEXPRV 1209
#define B_MTEXCOL 1210
#define B_TEXCLEAR 1211
#define B_MTEXPASTE 1212
@@ -215,6 +214,7 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
#define B_REDRAWCBAND 1318
#define B_BANDCOL 1319
#define B_LOADTEXIMA1 1320
#define B_TEXPRV 1321
#define B_PLUGBUT 1325
/* B_PLUGBUT reserves 24 buttons at least! */

View File

@@ -252,6 +252,7 @@
#define SCREEN_HANDLER 0x4036
#define REDRAWANIM 0x4037
#define REDRAWNODE 0x4038
#define RECALC_COMPOSITE 0x4039
#endif /* !__MYDEVICE_H__ */

View File

@@ -277,6 +277,15 @@ void do_texbuts(unsigned short event)
tex= G.buts->lockpoin;
switch(event) {
case B_TEXPRV:
BIF_preview_changed(ID_TE);
allqueue(REDRAWBUTSSHADING, 0);
if(tex && G.scene->nodetree) {
NodeTagIDChanged(G.scene->nodetree, &tex->id);
allqueue(RECALC_COMPOSITE, 0);
}
break;
case B_TEXCHANNEL:
scrarea_queue_headredraw(curarea);
BIF_preview_changed(ID_TE);
@@ -287,6 +296,11 @@ void do_texbuts(unsigned short event)
tex->stype= 0;
allqueue(REDRAWBUTSSHADING, 0);
BIF_preview_changed(ID_TE);
if(tex && G.scene->nodetree) {
NodeTagIDChanged(G.scene->nodetree, &tex->id);
allqueue(RECALC_COMPOSITE, 0);
}
break;
case B_DEFTEXVAR:
if(tex==0) return;
@@ -2450,10 +2464,6 @@ void do_matbuts(unsigned short event)
allqueue(REDRAWBUTSSHADING, 0);
shade_buttons_change_3d();
break;
case B_TEXPRV:
BIF_preview_changed(ID_TE);
allqueue(REDRAWBUTSSHADING, 0);
break;
case B_LAMPPRV:
BIF_preview_changed(ID_LA);
allqueue(REDRAWBUTSSHADING, 0);

View File

@@ -111,22 +111,44 @@ static void snode_drawstring(SpaceNode *snode, char *str, int okwidth)
/* ************** Socket callbacks *********** */
/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
/* also: butpoin is to the first element of socket nodestack struct */
static uiBlock *socket_vector_menu(void *butpoin_v)
static void socket_vector_menu_cb(void *node_v, void *ntree_v)
{
bNodeStack *ns= butpoin_v;
NodeTagChanged(ntree_v, node_v);
addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+((bNode *)node_v)->nr);
}
/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
static uiBlock *socket_vector_menu(void *socket_v)
{
SpaceNode *snode= curarea->spacedata.first;
bNode *node;
bNodeSocket *sock= socket_v;
bNodeStack *ns= &sock->ns;
uiBlock *block;
uiBut *bt;
/* a bit ugly... retrieve the node the socket comes from */
for(node= snode->nodetree->nodes.first; node; node= node->next) {
bNodeSocket *sockt;
for(sockt= node->inputs.first; sockt; sockt= sockt->next)
if(sockt==sock)
break;
if(sockt)
break;
}
block= uiNewBlock(&curarea->uiblocks, "socket menu", UI_EMBOSS, UI_HELV, curarea->win);
/* use this for a fake extra empy space around the buttons */
uiDefBut(block, LABEL, 0, "", -4, -4, 188, 68, NULL, 0, 0, 0, 0, "");
uiBlockBeginAlign(block);
uiDefButF(block, NUMSLI, 0, "X ", 0,40,180,20, ns->vec, ns->min, ns->max, 10, 0, "");
uiDefButF(block, NUMSLI, 0, "Y ", 0,20,180,20, ns->vec+1, ns->min, ns->max, 10, 0, "");
uiDefButF(block, NUMSLI, 0, "Z ", 0,0,180,20, ns->vec+2, ns->min, ns->max, 10, 0, "");
bt= uiDefButF(block, NUMSLI, 0, "X ", 0,40,180,20, ns->vec, ns->min, ns->max, 10, 0, "");
uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
bt= uiDefButF(block, NUMSLI, 0, "Y ", 0,20,180,20, ns->vec+1, ns->min, ns->max, 10, 0, "");
uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
bt= uiDefButF(block, NUMSLI, 0, "Z ", 0,0,180,20, ns->vec+2, ns->min, ns->max, 10, 0, "");
uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
uiBlockSetDirection(block, UI_TOP);
@@ -295,6 +317,59 @@ static int node_buts_normal(uiBlock *block, bNodeTree *ntree, bNode *node, rctf
return (int)(node->width-NODE_DY);
}
static void node_browse_tex_cb(void *ntree_v, void *node_v)
{
bNodeTree *ntree= ntree_v;
bNode *node= node_v;
Tex *tex;
if(node->menunr<1) return;
if(node->id) {
node->id->us--;
node->id= NULL;
}
tex= BLI_findlink(&G.main->tex, node->menunr-1);
node->id= &tex->id;
id_us_plus(node->id);
BLI_strncpy(node->name, node->id->name+2, 21);
nodeSetActive(ntree, node);
allqueue(REDRAWBUTSSHADING, 0);
allqueue(REDRAWNODE, 0);
NodeTagChanged(ntree, node);
node->menunr= 0;
}
static int node_buts_texture(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
{
if(block) {
uiBut *bt;
char *strp;
/* browse button texture */
uiBlockBeginAlign(block);
IDnames_to_pupstring(&strp, NULL, "", &(G.main->tex), NULL, NULL);
node->menunr= 0;
bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp,
butr->xmin, butr->ymin, 20, 19,
&node->menunr, 0, 0, 0, 0, "Browse texture");
uiButSetFunc(bt, node_browse_tex_cb, ntree, node);
if(strp) MEM_freeN(strp);
if(node->id) {
bt= uiDefBut(block, TEX, B_NOP, "TE:",
butr->xmin+19, butr->ymin, butr->xmax-butr->xmin-19, 19,
node->id->name+2, 0.0, 19.0, 0, 0, "Texture name");
uiButSetFunc(bt, node_ID_title_cb, node, NULL);
}
}
return 19;
}
/* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
@@ -443,21 +518,6 @@ static int node_shader_buts_material(uiBlock *block, bNodeTree *ntree, bNode *no
return 38;
}
static int node_shader_buts_texture(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
{
if(block) {
uiBut *bt;
bt= uiDefIDPoinBut(block, test_texpoin_but, ID_TE, B_NODE_EXEC+node->nr, "",
butr->xmin, butr->ymin, butr->xmax-butr->xmin, 19,
&node->id, "");
uiButSetFunc(bt, node_ID_title_cb, node, NULL);
}
return 19;
}
static int node_shader_buts_mapping(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
{
if(block) {
@@ -519,7 +579,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
ntype->butfunc= node_shader_buts_material;
break;
case SH_NODE_TEXTURE:
ntype->butfunc= node_shader_buts_texture;
ntype->butfunc= node_buts_texture;
break;
case SH_NODE_NORMAL:
ntype->butfunc= node_buts_normal;
@@ -970,6 +1030,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_HUE_SAT:
ntype->butfunc= node_composit_buts_hue_sat;
break;
case CMP_NODE_TEXTURE:
ntype->butfunc= node_buts_texture;
break;
default:
ntype->butfunc= NULL;
}
@@ -1504,7 +1567,7 @@ static void node_draw_basis(ScrArea *sa, SpaceNode *snode, bNode *node)
uiButSetFunc(bt, node_sync_cb, snode, node);
}
else if(sock->type==SOCK_VECTOR) {
uiDefBlockBut(node->block, socket_vector_menu, butpoin, sock->name,
uiDefBlockBut(node->block, socket_vector_menu, sock, sock->name,
(short)sock->locx+NODE_DYS, (short)sock->locy-9, (short)node->width-NODE_DY, 17,
"");
}

View File

@@ -2336,7 +2336,6 @@ static int ui_do_but_SLI(uiBut *but)
float f, fstart, tempf = 0.0, deler, value;
int sx, h, temp, pos=0, lvalue, redraw;
short mval[2], qual;
float curmatrix[4][4];
value= ui_get_but_val(but);
uiGetMouse(mywinget(), mval);
@@ -2420,9 +2419,13 @@ static int ui_do_but_SLI(uiBut *but)
because button callback function MIGHT change it
- which has until now occured through the Python API
*/
Mat4CpyMat4(curmatrix, UIwinmat);
/* This is really not possible atm... nothing in Blender
supports such functionality even now. Calling function
callbacks while using a button screws up the UI (ton)
*/
/* Mat4CpyMat4(curmatrix, UIwinmat);
uibut_do_func(but);
Mat4CpyMat4(UIwinmat, curmatrix);
Mat4CpyMat4(UIwinmat, curmatrix); */
}
else BIF_wait_for_statechange();
}
@@ -2451,11 +2454,12 @@ static int ui_do_but_SLI(uiBut *but)
ui_set_but_val(but, tempf);
}
uibut_do_func(but);
}
ui_check_but(but);
ui_draw_but(but);
ui_block_flush_back(but->block);
uibut_do_func(but);
return but->retval;
}

View File

@@ -147,6 +147,7 @@
#include "BPY_extern.h"
#include "butspace.h"
#include "mydevice.h"
#include "blendef.h"
#include "datatoc.h"
@@ -5075,6 +5076,11 @@ void allqueue(unsigned short event, short val)
scrarea_queue_winredraw(sa);
}
break;
case RECALC_COMPOSITE:
if(sa->spacetype==SPACE_NODE) {
addqueue(sa->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
}
break;
case REDRAWANIM:
if ELEM6(sa->spacetype, SPACE_IPO, SPACE_SOUND, SPACE_TIME, SPACE_NLA, SPACE_ACTION, SPACE_SEQ) {
scrarea_queue_winredraw(sa);