- New UI element: the "Curve Button".

For mapping ranges (like 0 - 1) to another range, the curve button can be
used for proportional falloff, bone influences, painting density, etc.
Most evident use is of course to map RGB color with curves.

To be able to use it, you have to allocate a CurveMapping struct and pass
this on to the button. The CurveMapping API is in the new C file
blenkernel/intern/colortools.c
It's as simple as calling:

   curvemap= curvemapping_add(3, 0, 0, 1, 1)

Which will create 3 curves, and sets a default 0-1 range. The current code
only supports up to 4 curves maximum per mapping struct.
The CurveMap button in Blender than handles allmost all  editing.
Evaluating a single channel:

   float newvalue= curvemapping_evaluateF(curvemap, 0, oldval);

Where the second argument is the channel index, here 0-1-2 are possible.
Or mapping a vector:

   curvemapping_evaluate3F(curvemap, newvec, oldvec);

Optimized versions for byte or short mapping is possible too, not done yet.

In butspace.c I've added a template wrapper for buttons around the curve, to
reveil settings or show tools; check this screenie:

http://www.blender.org/bf/curves.jpg

- Buttons R, G, B: select channel
- icons + and -: zoom in, out
- icon 'wrench': menu with tools, like clear curve, set handle type
- icon 'clipping': menu with clip values, and to dis/enable clipping
- icon 'x': delete selection

In the curve button itself, only LMB clicks are handled (like all UI elements
in Blender).

- click on point: select
- shift+click on point: swap select
- click on point + drag: select point (if not selected) and move it
- click outside point + drag: translate view
- CTRL+click: add new point
- hold SHIFT while dragging to snap to grid
  (Yes I know... either one of these can be Blender compliant, not both!)
- if you drag a point exactly on top of another, it merges them

Other fixes:

- Icons now draw using "Safe RasterPos", so they align with pixel boundary.
  the old code made ints from the raster pos coordinate, which doesn't work
  well for zoom in/out situations

- bug in Node editing: buttons could not get freed, causing in memory error
  prints at end of a Blender session. That one was a very simple, but nasty
  error causing me all evening last night to find!
  (Hint; check diff of editnode.c, where uiDoButtons is called)

Last note: this adds 3 new files in our tree, I did scons, but not MSVC!
This commit is contained in:
Ton Roosendaal 2006-01-08 11:41:06 +00:00
parent 32e21f4524
commit 104ab9b103
22 changed files with 2811 additions and 1573 deletions

@ -0,0 +1,50 @@
/**
* $Id$
*
* ***** 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): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef BKE_COLORTOOLS_H
#define BKE_COLORTOOLS_H
struct CurveMapping;
struct CurveMap;
struct rctf;
struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
void curvemapping_free(struct CurveMapping *cumap);
struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap);
void curvemap_remove(struct CurveMap *cuma, int flag);
void curvemap_insert(struct CurveMap *cuma, float x, float y);
void curvemap_reset(struct CurveMap *cuma, struct rctf *clipr);
void curvemap_sethandle(struct CurveMap *cuma, int type);
void curvemapping_changed(struct CurveMapping *cumap, int rem_doubles);
float curvemapping_evaluateF(struct CurveMapping *cumap, int cur, float value);
void curvemapping_evaluate3F(struct CurveMapping *cumap, float *vecout, const float *vecin);
#endif

@ -159,6 +159,8 @@ struct ShadeResult;
#define SH_NODE_NORMAL 107
#define SH_NODE_GEOMETRY 108
#define SH_NODE_MAPPING 109
#define SH_NODE_CURVE_VEC 110
#define SH_NODE_CURVE_RGB 111
/* custom defines: options for Material node */
#define SH_NODE_MAT_DIFF 1

@ -46,6 +46,7 @@ source_files = ['intern/constraint.c',
'intern/softbody.c',
'intern/node.c',
'intern/node_shaders.c',
'intern/colortools.c',
'intern/texture.c']
blenkernel_env.Append (CPPPATH = ['.',

@ -0,0 +1,469 @@
/*
* $Id$
*
* ***** 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/BL DUAL LICENSE BLOCK *****
*/
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include "MEM_guardedalloc.h"
#include "DNA_color_types.h"
#include "DNA_curve_types.h"
#include "DNA_texture_types.h"
#include "BKE_colortools.h"
#include "BKE_curve.h"
#include "BKE_global.h"
#include "BKE_ipo.h"
#include "BKE_main.h"
#include "BKE_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
/* ********************************* color curve ********************* */
/* ***************** operations on full struct ************* */
CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
{
CurveMapping *cumap;
int a;
cumap= MEM_callocN(sizeof(CurveMapping), "new curvemap");
cumap->flag= CUMA_DO_CLIP;
BLI_init_rctf(&cumap->curr, minx, maxx, miny, maxy);
cumap->clipr= cumap->curr;
for(a=0; a<tot; a++) {
cumap->cm[a].totpoint= 2;
cumap->cm[a].curve= MEM_callocN(2*sizeof(CurveMapPoint), "curve points");
cumap->cm[a].curve[0].x= minx;
cumap->cm[a].curve[0].y= miny;
cumap->cm[a].curve[1].x= maxx;
cumap->cm[a].curve[1].y= maxy;
}
return cumap;
}
void curvemapping_free(CurveMapping *cumap)
{
int a;
if(cumap) {
for(a=0; a<CM_TOT; a++) {
if(cumap->cm[a].curve) MEM_freeN(cumap->cm[a].curve);
if(cumap->cm[a].table) MEM_freeN(cumap->cm[a].table);
}
MEM_freeN(cumap);
}
}
CurveMapping *curvemapping_copy(CurveMapping *cumap)
{
int a;
if(cumap) {
CurveMapping *cumapn= MEM_dupallocN(cumap);
for(a=0; a<CM_TOT; a++) {
if(cumap->cm[a].curve)
cumapn->cm[a].curve= MEM_dupallocN(cumap->cm[a].curve);
if(cumap->cm[a].table)
cumapn->cm[a].table= MEM_dupallocN(cumap->cm[a].table);
}
return cumapn;
}
return NULL;
}
/* ***************** operations on single curve ************* */
/* ********** NOTE: requires curvemapping_changed() call after ******** */
/* removes with flag set */
void curvemap_remove(CurveMap *cuma, int flag)
{
CurveMapPoint *cmp= MEM_mallocN((cuma->totpoint)*sizeof(CurveMapPoint), "curve points");
int a, b, removed=0;
/* well, lets keep the two outer points! */
cmp[0]= cuma->curve[0];
for(a=1, b=1; a<cuma->totpoint-1; a++) {
if(!(cuma->curve[a].flag & flag)) {
cmp[b]= cuma->curve[a];
b++;
}
else removed++;
}
cmp[b]= cuma->curve[a];
MEM_freeN(cuma->curve);
cuma->curve= cmp;
cuma->totpoint -= removed;
}
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));
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; a<cuma->totpoint; a++, cmp++)
cmp->flag= 0;
cuma->totpoint++;
}
void curvemap_reset(CurveMap *cuma, rctf *clipr)
{
cuma->totpoint= 2;
cuma->curve[0].x= clipr->xmin;
cuma->curve[0].y= clipr->ymin;
cuma->curve[0].flag= 0;
cuma->curve[1].x= clipr->xmax;
cuma->curve[1].y= clipr->ymax;
cuma->curve[1].flag= 0;
}
/* if type==1: vector, else auto */
void curvemap_sethandle(CurveMap *cuma, int type)
{
int a;
for(a=0; a<cuma->totpoint; a++) {
if(cuma->curve[a].flag & CUMA_SELECT) {
if(type) cuma->curve[a].flag |= CUMA_VECTOR;
else cuma->curve[a].flag &= ~CUMA_VECTOR;
}
}
}
/* *********************** Making the tables and display ************** */
/* reduced copy of garbled calchandleNurb() code in curve.c */
static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
{
float *p1,*p2,*p3,pt[3];
float dx1,dy1, dx,dy, vx,vy, len,len1,len2;
if(bezt->h1==0 && bezt->h2==0) return;
p2= bezt->vec[1];
if(prev==NULL) {
p3= next->vec[1];
pt[0]= 2*p2[0]- p3[0];
pt[1]= 2*p2[1]- p3[1];
p1= pt;
}
else p1= prev->vec[1];
if(next==NULL) {
p1= prev->vec[1];
pt[0]= 2*p2[0]- p1[0];
pt[1]= 2*p2[1]- p1[1];
p3= pt;
}
else p3= next->vec[1];
dx= p2[0]- p1[0];
dy= p2[1]- p1[1];
len1= (float)sqrt(dx*dx+dy*dy);
dx1= p3[0]- p2[0];
dy1= p3[1]- p2[1];
len2= (float)sqrt(dx1*dx1+dy1*dy1);
if(len1==0.0f) len1=1.0f;
if(len2==0.0f) len2=1.0f;
if(bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) { /* auto */
vx= dx1/len2 + dx/len1;
vy= dy1/len2 + dy/len1;
len= 2.5614f*(float)sqrt(vx*vx + vy*vy);
if(len!=0.0f) {
if(bezt->h1==HD_AUTO) {
len1/=len;
*(p2-3)= *p2-vx*len1;
*(p2-2)= *(p2+1)-vy*len1;
}
if(bezt->h2==HD_AUTO) {
len2/=len;
*(p2+3)= *p2+vx*len2;
*(p2+4)= *(p2+1)+vy*len2;
}
}
}
if(bezt->h1==HD_VECT) { /* vector */
dx/=3.0;
dy/=3.0;
*(p2-3)= *p2-dx;
*(p2-2)= *(p2+1)-dy;
}
if(bezt->h2==HD_VECT) {
dx1/=3.0;
dy1/=3.0;
*(p2+3)= *p2+dx1;
*(p2+4)= *(p2+1)+dy1;
}
}
static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
{
CurveMapPoint *cmp= cuma->curve;
BezTriple *bezt;
float *fp, *allpoints, curf, range;
int a, totpoint;
if(cuma->curve==NULL) return;
/* default rect also is table range */
cuma->mintable= clipr->xmin;
cuma->maxtable= clipr->xmax;
/* hrmf... we now rely on blender ipo beziers, these are more advanced */
bezt= MEM_callocN(cuma->totpoint*sizeof(BezTriple), "beztarr");
for(a=0; a<cuma->totpoint; a++) {
cuma->mintable= MIN2(cuma->mintable, cmp[a].x);
cuma->maxtable= MAX2(cuma->maxtable, cmp[a].x);
bezt[a].vec[1][0]= cmp[a].x;
bezt[a].vec[1][1]= cmp[a].y;
if(cmp[a].flag & CUMA_VECTOR)
bezt[a].h1= bezt[a].h2= HD_VECT;
else
bezt[a].h1= bezt[a].h2= HD_AUTO;
}
for(a=0; a<cuma->totpoint; a++) {
if(a==0)
calchandle_curvemap(bezt, NULL, bezt+1, 0);
else if(a==cuma->totpoint-1)
calchandle_curvemap(bezt+a, bezt+a-1, NULL, 0);
else
calchandle_curvemap(bezt+a, bezt+a-1, bezt+a+1, 0);
}
/* first and last handle need correction, instead of pointing to center of next/prev,
we let it point to the closest handle */
if(cuma->totpoint>2) {
float hlen, nlen, vec[3];
if(bezt[0].h2==HD_AUTO) {
hlen= VecLenf(bezt[0].vec[1], bezt[0].vec[2]); /* original handle length */
/* clip handle point */
VECCOPY(vec, bezt[1].vec[0]);
if(vec[0] < bezt[0].vec[1][0])
vec[0]= bezt[0].vec[1][0];
VecSubf(vec, vec, bezt[0].vec[1]);
nlen= VecLength(vec);
if(nlen>FLT_EPSILON) {
VecMulf(vec, hlen/nlen);
VecAddf(bezt[0].vec[2], vec, bezt[0].vec[1]);
}
}
a= cuma->totpoint-1;
if(bezt[a].h2==HD_AUTO) {
hlen= VecLenf(bezt[a].vec[1], bezt[a].vec[0]); /* original handle length */
/* clip handle point */
VECCOPY(vec, bezt[a-1].vec[2]);
if(vec[0] > bezt[a].vec[1][0])
vec[0]= bezt[a].vec[1][0];
VecSubf(vec, vec, bezt[a].vec[1]);
nlen= VecLength(vec);
if(nlen>FLT_EPSILON) {
VecMulf(vec, hlen/nlen);
VecAddf(bezt[a].vec[0], vec, bezt[a].vec[1]);
}
}
}
/* make the bezier curve */
if(cuma->table)
MEM_freeN(cuma->table);
totpoint= (cuma->totpoint-1)*CM_RESOL;
fp= allpoints= MEM_mallocN(totpoint*2*sizeof(float), "table");
for(a=0; a<cuma->totpoint-1; a++, fp += 2*CM_RESOL) {
correct_bezpart(bezt[a].vec[1], bezt[a].vec[2], bezt[a+1].vec[0], bezt[a+1].vec[1]);
forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a+1].vec[0][0], bezt[a+1].vec[1][0], fp, CM_RESOL-1, 2);
forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2);
}
MEM_freeN(bezt);
range= CM_TABLEDIV*(cuma->maxtable - cuma->mintable);
cuma->range= 1.0f/range;
/* now make a table with CM_TABLE equal x distances */
fp= allpoints;
cmp= MEM_callocN((CM_TABLE+1)*sizeof(CurveMapPoint), "dist table");
cmp[0].x= cuma->mintable;
cmp[0].y= allpoints[1];
for(a=1; a<CM_TABLE; a++) {
curf= cuma->mintable + range*(float)a;
cmp[a].x= curf;
/* get the first x coordinate larger than curf */
while(curf >= fp[0] && fp!=allpoints-2) {
fp+=2;
}
if(fp==allpoints-2)
cmp[a].y= fp[1];
else {
float fac1= fp[0] - fp[-2];
float fac2= fp[0] - curf;
if(fac1 > FLT_EPSILON)
fac1= fac2/fac1;
else
fac1= 0.0f;
cmp[a].y= fac1*fp[-1] + (1.0f-fac1)*fp[1];
}
}
cmp[CM_TABLE].x= cuma->maxtable;
cmp[CM_TABLE].y= allpoints[2*totpoint-1];
MEM_freeN(allpoints);
cuma->table= cmp;
}
static int sort_curvepoints(const void *a1, const void *a2)
{
const struct CurveMapPoint *x1=a1, *x2=a2;
if( x1->x > x2->x ) return 1;
else if( x1->x < x2->x) return -1;
return 0;
}
/* ************************ more CurveMapping calls *************** */
/* note; only does current curvemap! */
void curvemapping_changed(CurveMapping *cumap, int rem_doubles)
{
CurveMap *cuma= cumap->cm+cumap->cur;
CurveMapPoint *cmp= cuma->curve;
rctf *clipr= &cumap->clipr;
float thresh= 0.01f*(clipr->xmax - clipr->xmin);
float dx, dy;
int a;
/* clamp with clip */
if(cumap->flag & CUMA_DO_CLIP) {
for(a=0; a<cuma->totpoint; a++) {
if(cmp[a].x < clipr->xmin)
cmp[a].x= clipr->xmin;
else if(cmp[a].x > clipr->xmax)
cmp[a].x= clipr->xmax;
if(cmp[a].y < clipr->ymin)
cmp[a].y= clipr->ymin;
else if(cmp[a].y > clipr->ymax)
cmp[a].y= clipr->ymax;
}
}
qsort(cmp, cuma->totpoint, sizeof(CurveMapPoint), sort_curvepoints);
/* remove doubles, threshold set on 1% of default range */
if(rem_doubles && cuma->totpoint>2) {
for(a=0; a<cuma->totpoint-1; a++) {
dx= cmp[a].x - cmp[a+1].x;
dy= cmp[a].y - cmp[a+1].y;
if( sqrt(dx*dx + dy*dy) < thresh ) {
if(a==0) {
cmp[a+1].flag|= 2;
if(cmp[a+1].flag & CUMA_SELECT)
cmp[a].flag |= CUMA_SELECT;
}
else {
cmp[a].flag|= 2;
if(cmp[a].flag & CUMA_SELECT)
cmp[a+1].flag |= CUMA_SELECT;
}
break; /* we assume 1 deletion per edit is ok */
}
}
if(a != cuma->totpoint-1)
curvemap_remove(cuma, 2);
}
curvemap_make_table(cuma, clipr);
}
/* works with curve 'cur' */
float curvemapping_evaluateF(CurveMapping *cumap, int cur, float value)
{
CurveMap *cuma= cumap->cm+cur;
float fi;
int i;
/* allocate or bail out */
if(cuma->table==NULL) {
curvemap_make_table(cuma, &cumap->clipr);
if(cuma->table==NULL)
return value;
}
/* index in table */
fi= (value-cuma->mintable)*cuma->range;
i= (int)fi;
if(i<0) return cuma->table[0].y;
if(i>=CM_TABLE) return cuma->table[CM_TABLE].y;
fi= fi-(float)i;
return (1.0f-fi)*cuma->table[i].y + (fi)*cuma->table[i+1].y;
}
void curvemapping_evaluate3F(CurveMapping *cumap, float *vecout, const float *vecin)
{
vecout[0]= curvemapping_evaluateF(cumap, 0, vecin[0]);
vecout[1]= curvemapping_evaluateF(cumap, 1, vecin[1]);
vecout[2]= curvemapping_evaluateF(cumap, 2, vecin[2]);
}

@ -35,6 +35,7 @@
#include "DNA_material_types.h"
#include "BKE_blender.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
@ -696,6 +697,10 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup)
node->storage= add_colorband(1);
else if(type==SH_NODE_MAPPING)
node->storage= add_mapping();
else if(type==SH_NODE_CURVE_VEC)
node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
else if(type==SH_NODE_CURVE_RGB)
node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
}
return node;
@ -722,8 +727,17 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
if(nnode->id)
nnode->id->us++;
if(nnode->storage)
nnode->storage= MEM_dupallocN(nnode->storage);
if(nnode->storage) {
/* another candidate for handlerizing! */
if(ntree->type==NTREE_SHADER) {
if(node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB)
nnode->storage= curvemapping_copy(node->storage);
else
nnode->storage= MEM_dupallocN(nnode->storage);
}
else
nnode->storage= MEM_dupallocN(nnode->storage);
}
node->new= nnode;
nnode->new= NULL;
@ -796,10 +810,9 @@ static void node_unlink_node(bNodeTree *ntree, bNode *node)
void nodeFreeNode(bNodeTree *ntree, bNode *node)
{
if(ntree) {
node_unlink_node(ntree, node);
BLI_remlink(&ntree->nodes, node);
}
node_unlink_node(ntree, node);
BLI_remlink(&ntree->nodes, node);
if(node->id)
node->id->us--;
@ -811,9 +824,17 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
MEM_freeN(node->preview->rect);
MEM_freeN(node->preview);
}
if(node->storage)
MEM_freeN(node->storage);
if(node->storage) {
/* could be handlerized at some point, now only 1 exception still */
if(ntree->type==NTREE_SHADER) {
if(node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB)
curvemapping_free(node->storage);
else
MEM_freeN(node->storage);
}
else
MEM_freeN(node->storage);
}
MEM_freeN(node);
}
@ -822,11 +843,12 @@ void ntreeFreeTree(bNodeTree *ntree)
{
bNode *node, *next;
BLI_freelistN(&ntree->links); /* do first, then unlink_node goes fast */
for(node= ntree->nodes.first; node; node= next) {
next= node->next;
nodeFreeNode(NULL, node); /* NULL -> no unlinking needed */
nodeFreeNode(ntree, node);
}
BLI_freelistN(&ntree->links);
if(ntree->owntype) {
if(ntree->owntype->inputs)

@ -36,6 +36,7 @@
#include "DNA_texture_types.h"
#include "BKE_blender.h"
#include "BKE_colortools.h"
#include "BKE_node.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
@ -240,8 +241,10 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
shi->mat->ref= in[MAT_IN_REFL]->vec[0];
/* retrieve normal */
if(in[MAT_IN_NORMAL]->hasinput)
if(in[MAT_IN_NORMAL]->hasinput) {
nor= in[MAT_IN_NORMAL]->vec;
Normalise(nor);
}
else
nor= shi->vno;
@ -476,6 +479,61 @@ static bNodeType sh_node_normal= {
};
/* **************** CURVE VEC ******************** */
static bNodeSocketType sh_node_curve_vec_in[]= {
{ SOCK_VECTOR, 1, "Vector", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ -1, 0, "" }
};
static bNodeSocketType sh_node_curve_vec_out[]= {
{ SOCK_VECTOR, 0, "Vector", 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
{ -1, 0, "" }
};
/* generates normal, does dot product */
static void node_shader_exec_curve(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
/* stack order input: vec */
/* stack order output: vec */
curvemapping_evaluate3F(node->storage, out[0]->vec, in[0]->vec);
}
static bNodeType sh_node_curve_vec= {
/* type code */ SH_NODE_CURVE_VEC,
/* name */ "Vector Curves",
/* width+range */ 200, 140, 320,
/* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS,
/* input sock */ sh_node_curve_vec_in,
/* output sock */ sh_node_curve_vec_out,
/* storage */ "CurveMapping",
/* execfunc */ node_shader_exec_curve
};
/* **************** CURVE RGB ******************** */
static bNodeSocketType sh_node_curve_rgb_in[]= {
{ SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
{ -1, 0, "" }
};
static bNodeSocketType sh_node_curve_rgb_out[]= {
{ SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
{ -1, 0, "" }
};
static bNodeType sh_node_curve_rgb= {
/* type code */ SH_NODE_CURVE_RGB,
/* name */ "RGB Curves",
/* width+range */ 200, 140, 320,
/* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS,
/* input sock */ sh_node_curve_rgb_in,
/* output sock */ sh_node_curve_rgb_out,
/* storage */ "CurveMapping",
/* execfunc */ node_shader_exec_curve
};
/* **************** VALUE ******************** */
static bNodeSocketType sh_node_value_out[]= {
{ SOCK_VALUE, 0, "Value", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
@ -647,6 +705,8 @@ bNodeType *node_all_shaders[]= {
&sh_node_normal,
&sh_node_geom,
&sh_node_mapping,
&sh_node_curve_vec,
&sh_node_curve_rgb,
NULL
};

@ -59,6 +59,7 @@
#include "DNA_ID.h"
#include "DNA_actuator_types.h"
#include "DNA_camera_types.h"
#include "DNA_color_types.h"
#include "DNA_controller_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
@ -119,6 +120,7 @@
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
#include "BKE_modifier.h"
#include "BKE_node.h" // for tree type defines
#include "BKE_object.h"
#include "BKE_sca.h" // for init_actuator
#include "BKE_scene.h"
@ -1186,6 +1188,19 @@ static void test_pointer_array(FileData *fd, void **mat)
}
}
/* ************ READ CurveMapping *************** */
/* cuma itself has been read! */
static void direct_link_curvemapping(FileData *fd, CurveMapping *cumap)
{
int a;
for(a=0; a<CM_TOT; a++) {
cumap->cm[a].curve= newdataadr(fd, cumap->cm[a].curve);
cumap->cm[a].table= NULL;
}
}
/* ************ READ NODE TREE *************** */
/* singe node tree, ntree is not NULL */
@ -1243,6 +1258,11 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
link_list(fd, &ntree->nodes);
for(node= ntree->nodes.first; node; node= node->next) {
node->storage= newdataadr(fd, node->storage);
if(node->storage) {
/* could be handlerized at some point, now only 1 exception still */
if(ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
direct_link_curvemapping(fd, node->storage);
}
link_list(fd, &node->inputs);
link_list(fd, &node->outputs);
}

@ -109,6 +109,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
#include "DNA_curve_types.h"
#include "DNA_constraint_types.h"
#include "DNA_camera_types.h"
#include "DNA_color_types.h"
#include "DNA_effect_types.h"
#include "DNA_group_types.h"
#include "DNA_image_types.h"
@ -362,6 +363,17 @@ static void writedata(WriteData *wd, int filecode, int len, void *adr) /* do not
if(len) mywrite(wd, adr, len);
}
/* *************** writing some direct data structs used in more code parts **************** */
static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
{
int a;
writestruct(wd, DATA, "CurveMapping", 1, cumap);
for(a=0; a<CM_TOT; a++)
writestruct(wd, DATA, "CurveMapPoint", cumap->cm[a].totpoint, cumap->cm[a].curve);
}
/* this is only direct data, tree itself should have been written */
static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
@ -375,8 +387,13 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
writestruct(wd, DATA, "bNode", 1, node);
for(node= ntree->nodes.first; node; node= node->next) {
if(node->storage)
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
if(node->storage) {
/* could be handlerized at some point, now only 1 exception still */
if(ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
write_curvemapping(wd, node->storage);
else
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
for(sock= node->inputs.first; sock; sock= sock->next)
writestruct(wd, DATA, "bNodeSocket", 1, sock);
for(sock= node->outputs.first; sock; sock= sock->next)

@ -161,6 +161,7 @@ struct ScrArea;
#define CHARTAB (29<<9)
#define BUT_COLORBAND (30<<9)
#define BUT_NORMAL (31<<9)
#define BUT_CURVE (32<<9)
#define BUTTYPE (63<<9)
@ -251,6 +252,7 @@ uiBut *uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *func_arg1, char *
uiBut *uiDefPulldownBut(uiBlock *block, uiBlockFuncFP func, void *func_arg1, char *str, short x1, short y1, short x2, short y2, char *tip);
uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip);
uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip);
void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip);

@ -182,8 +182,8 @@ typedef enum {
ICON_CHECKBOX_HLT,
ICON_LINK,
ICON_INLINK,
ICON_BLANK12,
ICON_BLANK13,
ICON_ZOOMIN,
ICON_ZOOMOUT,
ICON_PASTEDOWN,
ICON_COPYDOWN,
ICON_CONSTANT,

@ -40,6 +40,7 @@ struct ID;
struct ColorBand;
struct uiBlock;
struct rctf;
struct CurveMap;
/* buts->scaflag */
#define BUTS_SENS_SEL 1
@ -129,6 +130,8 @@ void test_texpoin_but(char *name, ID **idpp);
void test_idbutton_cb(void *namev, void *arg2_unused);
void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char labeltype, short event, short redraw, struct rctf *rect);
/* -------------- internal event defines ------------ */

@ -90,7 +90,7 @@ typedef struct uiLinkLine { /* only for draw/edit */
short flag, pad;
uiBut *from, *to;
struct uiBut *from, *to;
} uiLinkLine;
typedef struct {
@ -105,7 +105,7 @@ typedef struct {
} uiLink;
struct uiBut {
uiBut *next, *prev;
struct uiBut *next, *prev;
short type, pointype, bit, bitnr, retval, strwidth, ofs, pos, selsta, selend;
int flag;

@ -0,0 +1,74 @@
/**
*
* $Id$
*
* ***** 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): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef DNA_COLOR_TYPES_H
#define DNA_COLOR_TYPES_H
#include "DNA_vec_types.h"
/* general defines for kernel functions */
#define CM_RESOL 32
#define CM_TABLE 256
#define CM_TABLEDIV (1.0f/256.0f)
#define CM_TOT 4
typedef struct CurveMapPoint {
float x, y;
short flag, shorty; /* shorty for result lookup */
} CurveMapPoint;
/* curvepoint->flag */
#define CUMA_SELECT 1
#define CUMA_VECTOR 2
typedef struct CurveMap {
short totpoint, pad;
float range; /* quick multiply value for reading table */
float mintable, maxtable; /* the x-axis range for the table */
CurveMapPoint *curve; /* actual curve */
CurveMapPoint *table; /* display and evaluate table */
} CurveMap;
typedef struct CurveMapping {
int flag, cur; /* cur; for buttons, to show active curve */
rctf curr, clipr; /* current rect, clip rect (is default rect too) */
CurveMap cm[4]; /* max 4 builtin curves per mapping struct now */
} CurveMapping;
/* cuma->flag */
#define CUMA_DO_CLIP 1
#endif

@ -124,6 +124,7 @@ char *includefiles[] = {
"DNA_constraint_types.h",
"DNA_nla_types.h",
"DNA_node_types.h",
"DNA_color_types.h",
// if you add files here, please add them at the end
// of makesdna.c (this file) as well
@ -1131,4 +1132,5 @@ int main(int argc, char ** argv)
#include "DNA_constraint_types.h"
#include "DNA_nla_types.h"
#include "DNA_node_types.h"
#include "DNA_color_types.h"
/* end of list */

File diff suppressed because it is too large Load Diff

@ -41,6 +41,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_color_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@ -48,6 +49,7 @@
#include "DNA_space_types.h"
#include "DNA_texture_types.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_library.h"
@ -239,6 +241,195 @@ void test_texpoin_but(char *name, ID **idpp)
*idpp= NULL;
}
/* ----------- custom button group ---------------------- */
static void curvemap_buttons_zoom_in(void *cumap_v, void *unused)
{
CurveMapping *cumap = cumap_v;
float d;
/* we allow 5 times zoom */
if( (cumap->curr.xmax - cumap->curr.xmin) > 0.2f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
cumap->curr.xmin+= d;
cumap->curr.xmax-= d;
d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
cumap->curr.ymin+= d;
cumap->curr.ymax-= d;
}
}
static void curvemap_buttons_zoom_out(void *cumap_v, void *unused)
{
CurveMapping *cumap = cumap_v;
float d;
/* we allow 5 times zoom */
if( (cumap->curr.xmax - cumap->curr.xmin) < 5.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
d= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
cumap->curr.xmin-= d;
cumap->curr.xmax+= d;
d= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
cumap->curr.ymin-= d;
cumap->curr.ymax+= d;
}
}
static void curvemap_buttons_setclip(void *cumap_v, void *unused)
{
CurveMapping *cumap = cumap_v;
curvemapping_changed(cumap, 0);
}
static void curvemap_buttons_delete(void *cumap_v, void *unused)
{
CurveMapping *cumap = cumap_v;
curvemap_remove(cumap->cm+cumap->cur, SELECT);
curvemapping_changed(cumap, 0);
}
/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
static uiBlock *curvemap_clipping_func(void *cumap_v)
{
CurveMapping *cumap = cumap_v;
uiBlock *block;
uiBut *bt;
block= uiNewBlock(&curarea->uiblocks, "curvemap_clipping_func", UI_EMBOSS, UI_HELV, curarea->win);
/* use this for a fake extra empy space around the buttons */
uiDefBut(block, LABEL, 0, "", -4, 16, 128, 106, NULL, 0, 0, 0, 0, "");
bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",
0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, "");
uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
uiBlockBeginAlign(block);
uiDefButF(block, NUM, 0, "Min X ", 0,74,120,18, &cumap->clipr.xmin, -10.0, cumap->clipr.xmax, 10, 0, "");
uiDefButF(block, NUM, 0, "Min Y ", 0,56,120,18, &cumap->clipr.ymin, -10.0, cumap->clipr.ymax, 10, 0, "");
uiDefButF(block, NUM, 0, "Max X ", 0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 10.0, 10, 0, "");
uiDefButF(block, NUM, 0, "Max Y ", 0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 10.0, 10, 0, "");
uiBlockSetDirection(block, UI_RIGHT);
return block;
}
static void curvemap_tools_dofunc(void *cumap_v, int event)
{
CurveMapping *cumap = cumap_v;
CurveMap *cuma= cumap->cm+cumap->cur;
switch(event) {
case 0:
curvemap_reset(cuma, &cumap->clipr);
curvemapping_changed(cumap, 0);
break;
case 1:
cumap->curr= cumap->clipr;
break;
case 2: /* set vector */
curvemap_sethandle(cuma, 1);
curvemapping_changed(cumap, 0);
break;
case 3: /* set auto */
curvemap_sethandle(cuma, 0);
curvemapping_changed(cumap, 0);
break;
}
addqueue(curarea->win, REDRAW, 1);
}
static uiBlock *curvemap_tools_func(void *cumap_v)
{
uiBlock *block;
short yco= 0, menuwidth=120;
block= uiNewBlock(&curarea->uiblocks, "curvemap_tools_func", UI_EMBOSSP, UI_HELV, curarea->win);
uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
uiBlockSetDirection(block, UI_RIGHT);
uiTextBoundsBlock(block, 50);
return block;
}
/* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
void curvemap_buttons(uiBlock *block, CurveMapping *cumap, char labeltype, short event, short redraw, rctf *rect)
{
uiBut *bt;
float dx, fy= rect->ymax-18.0f;
int icon;
short xco, yco;
yco= (short)(rect->ymax-18.0f);
/* curve choice options + tools/settings, 8 icons */
dx= (rect->xmax-rect->xmin)/(8.0f);
uiBlockBeginAlign(block);
if(labeltype=='v') { /* vector */
xco= (short)rect->xmin;
if(cumap->cm[0].curve)
uiDefButI(block, ROW, redraw, "X", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
xco= (short)(rect->xmin+1.0f*dx);
if(cumap->cm[1].curve)
uiDefButI(block, ROW, redraw, "Y", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
xco= (short)(rect->xmin+2.0f*dx);
if(cumap->cm[2].curve)
uiDefButI(block, ROW, redraw, "Z", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
}
else if(labeltype=='c') { /* color */
xco= (short)rect->xmin;
if(cumap->cm[0].curve)
uiDefButI(block, ROW, redraw, "R", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
xco= (short)(rect->xmin+1.0f*dx);
if(cumap->cm[1].curve)
uiDefButI(block, ROW, redraw, "G", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
xco= (short)(rect->xmin+2.0f*dx);
if(cumap->cm[2].curve)
uiDefButI(block, ROW, redraw, "B", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
}
/* else no channels ! */
uiBlockEndAlign(block);
xco= (short)(rect->xmin+3.5f*dx);
uiBlockSetEmboss(block, UI_EMBOSSN);
bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMIN, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
xco= (short)(rect->xmin+4.25f*dx);
bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMOUT, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
xco= (short)(rect->xmin+5.0f*dx);
bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, event, ICON_MODIFIER, xco, yco, dx, 18, "Tools");
xco= (short)(rect->xmin+6.0f*dx);
if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, event, icon, xco, yco, dx, 18, "Clipping Options");
xco= (short)(rect->xmin+7.0f*dx);
bt= uiDefIconBut(block, BUT, redraw, ICON_X, xco, yco, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
uiButSetFunc(bt, curvemap_buttons_delete, cumap, NULL);
uiBlockSetEmboss(block, UI_EMBOSS);
uiDefBut(block, BUT_CURVE, event, "",
rect->xmin, rect->ymin, rect->xmax-rect->xmin, fy-rect->ymin,
cumap, 0.0f, 1.0f, 0, 0, "");
}
/* --------------------------------- */

@ -49,11 +49,11 @@
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_color_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
#include "DNA_effect_types.h"
#include "DNA_group_types.h"
#include "DNA_image_types.h"
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
@ -76,6 +76,7 @@
#include "BKE_blender.h"
#include "BKE_curve.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_key.h"
@ -1479,7 +1480,7 @@ static void editing_panel_shapes(Object *ob)
}
if(key->type && ob->shapenr!=1)
uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 10, 90, 150,19, &kb->vgroup, 0.0, 31.0, 0, 0, "Vertex Weight Group name, to blend with Basis Shape");
}
/* *************************** FONT ******************************** */

@ -361,9 +361,20 @@ static int node_shader_buts_normal(uiBlock *block, bNodeTree *ntree, bNode *node
return (int)(node->width-NODE_DY);
}
static int node_shader_buts_curve(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
{
if(block) {
if(node->type==SH_NODE_CURVE_VEC)
curvemap_buttons(block, node->storage, 'v', B_NODE_EXEC, B_REDR, butr);
else
curvemap_buttons(block, node->storage, 'c', B_NODE_EXEC, B_REDR, butr);
}
return (int)(node->width-NODE_DY);
}
static int node_shader_buts_mapping(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
{
if(block && (node->flag & NODE_OPTIONS)) {
if(block) {
TexMapping *texmap= node->storage;
short dx= (short)((butr->xmax-butr->xmin)/7.0f);
short dy= (short)(butr->ymax-19);
@ -472,7 +483,7 @@ static int node_shader_buts_mix_rgb(uiBlock *block, bNodeTree *ntree, bNode *nod
static int node_shader_buts_valtorgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
{
if(block && (node->flag & NODE_OPTIONS)) {
if(block) {
if(node->storage) {
draw_colorband_buts_small(block, node->storage, butr, B_NODE_EXEC);
}
@ -496,6 +507,10 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_NORMAL:
ntype->butfunc= node_shader_buts_normal;
break;
case SH_NODE_CURVE_VEC:
case SH_NODE_CURVE_RGB:
ntype->butfunc= node_shader_buts_curve;
break;
case SH_NODE_MAPPING:
ntype->butfunc= node_shader_buts_mapping;
break;

@ -143,9 +143,12 @@ static void shader_node_event(SpaceNode *snode, short event)
// bNode *node;
switch(event) {
case B_NODE_EXEC:
snode_handle_recalc(snode);
break;
case B_NODE_EXEC:
snode_handle_recalc(snode);
break;
case B_REDR:
allqueue(REDRAWNODE, 1);
break;
}
}
@ -1020,7 +1023,7 @@ static void node_add_menu(SpaceNode *snode)
short event, mval[2];
/* shader menu, still hardcoded defines... solve */
event= pupmenu("Add Node%t|Output%x1|Geometry%x108|Material%x100|Texture%x106|Mapping%x109|Normal%x107|Value %x102|Color %x101|Mix Color %x103|ColorRamp %x104|Color to BW %x105");
event= pupmenu("Add Node%t|Output%x1|Geometry%x108|Material%x100|Texture%x106|Mapping%x109|Normal%x107|RGB Curves%x111|Vector Curves%x110|Value %x102|Color %x101|Mix Color %x103|ColorRamp %x104|Color to BW %x105");
if(event<1) return;
getmouseco_areawin(mval);
@ -1416,12 +1419,13 @@ void node_make_group(SpaceNode *snode)
/* ******************** main event loop ****************** */
/* special version to prevent overlapping buttons */
/* special version to prevent overlapping buttons, has a bit of hack... */
int node_uiDoBlocks(SpaceNode *snode, ListBase *lb, short event)
{
bNode *node;
rctf rect;
ListBase listb= *lb;
void *prev;
int retval= UI_NOTHING;
short mval[2];
@ -1437,12 +1441,19 @@ int node_uiDoBlocks(SpaceNode *snode, ListBase *lb, short event)
if(node->block) {
if(node == visible_node(snode, &rect)) {
/* when there's menus, the prev pointer becomes zero! */
prev= ((struct Link *)node->block)->prev;
lb->first= lb->last= node->block;
retval= uiDoBlocks(lb, event);
((struct Link *)node->block)->prev= prev;
break;
}
}
}
*lb= listb;
return retval;
@ -1506,6 +1517,9 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
dx= (float)(0.1154*(G.v2d->cur.xmax-G.v2d->cur.xmin));
G.v2d->cur.xmin+= dx;
G.v2d->cur.xmax-= dx;
dx= (float)(0.1154*(G.v2d->cur.ymax-G.v2d->cur.ymin));
G.v2d->cur.ymin+= dx;
G.v2d->cur.ymax-= dx;
test_view2d(G.v2d, sa->winx, sa->winy);
doredraw= 1;
break;
@ -1513,6 +1527,9 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
dx= (float)(0.15*(G.v2d->cur.xmax-G.v2d->cur.xmin));
G.v2d->cur.xmin-= dx;
G.v2d->cur.xmax+= dx;
dx= (float)(0.15*(G.v2d->cur.ymax-G.v2d->cur.ymin));
G.v2d->cur.ymin-= dx;
G.v2d->cur.ymax+= dx;
test_view2d(G.v2d, sa->winx, sa->winy);
doredraw= 1;
break;

@ -64,6 +64,7 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "DNA_color_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
@ -73,6 +74,7 @@
#include "DNA_vfont_types.h"
#include "BKE_blender.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_texture.h"
@ -2502,6 +2504,9 @@ static uiBlock *ui_do_but_BLOCK(uiBut *but, int event)
but->flag &= ~UI_SELECT;
uibut_do_func(but);
if(but->retval)
addqueue(curarea->win, UI_BUT_EVENT, (short)but->retval);
return block;
}
@ -3324,6 +3329,142 @@ static int ui_do_but_NORMAL(uiBut *but)
return but->retval;
}
static int ui_do_but_CURVE(uiBut *but)
{
CurveMapping *cumap= (CurveMapping *)but->poin;
CurveMap *cuma= cumap->cm+cumap->cur;
CurveMapPoint *cmp= cuma->curve;
float fx, fy, zoomx, zoomy, offsx, offsy;
short mval[2], mvalo[2];
uiGetMouse(mywinget(), mval);
/* calculate offset and zoom */
zoomx= (but->x2-but->x1)/(cumap->curr.xmax-cumap->curr.xmin);
zoomy= (but->y2-but->y1)/(cumap->curr.ymax-cumap->curr.ymin);
offsx= cumap->curr.xmin;
offsy= cumap->curr.ymin;
if(G.qual & LR_CTRLKEY) {
fx= ((float)mval[0] - but->x1)/zoomx + offsx;
fy= ((float)mval[1] - but->y1)/zoomy + offsy;
curvemap_insert(cuma, fx, fy);
curvemapping_changed(cumap, 0);
ui_draw_but(but);
ui_block_flush_back(but->block);
}
else {
float dist, mindist= 200.0f; // 14 pixels radius
int a, sel= -1;
/* check for selecting of a point */
for(a=0; a<cuma->totpoint; a++) {
fx= but->x1 + zoomx*(cmp[a].x-offsx);
fy= but->y1 + zoomy*(cmp[a].y-offsy);
dist= (fx-mval[0])*(fx-mval[0]) + (fy-mval[1])*(fy-mval[1]);
if(dist < mindist) {
sel= a;
mindist= dist;
}
}
/* ok, we move a point */
if(sel!= -1) {
int moved_point;
int moved_mouse= 0;
/* deselect all if this one is deselect. except if we hold shift */
if((G.qual & LR_SHIFTKEY)==0 && (cmp[sel].flag & SELECT)==0)
for(a=0; a<cuma->totpoint; a++)
cmp[a].flag &= ~SELECT;
cmp[sel].flag |= SELECT;
/* draw to show select updates */
ui_draw_but(but);
ui_block_flush_back(but->block);
/* while move mouse, do move points around */
while(get_mbut() & L_MOUSE) {
uiGetMouse(mywinget(), mvalo);
if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
moved_mouse= 1; /* for selection */
moved_point= 0; /* for ctrl grid, can't use orig coords because of sorting */
fx= (mvalo[0]-mval[0])/zoomx;
fy= (mvalo[1]-mval[1])/zoomy;
for(a=0; a<cuma->totpoint; a++) {
if(cmp[a].flag & SELECT) {
float origx= cmp[a].x, origy= cmp[a].y;
cmp[a].x+= fx;
cmp[a].y+= fy;
if( (get_qual() & LR_SHIFTKEY) ) {
cmp[a].x= 0.125f*floor(0.5f + 8.0f*cmp[a].x);
cmp[a].y= 0.125f*floor(0.5f + 8.0f*cmp[a].y);
}
if(cmp[a].x!=origx || cmp[a].y!=origy)
moved_point= 1;
}
}
curvemapping_changed(cumap, 0); /* no remove doubles */
ui_draw_but(but);
ui_block_flush_back(but->block);
if(moved_point) {
mval[0]= mvalo[0];
mval[1]= mvalo[1];
}
}
BIF_wait_for_statechange();
}
if(moved_mouse==0) {
/* deselect all, select one */
if((G.qual & LR_SHIFTKEY)==0) {
for(a=0; a<cuma->totpoint; a++)
cmp[a].flag &= ~SELECT;
cmp[sel].flag |= SELECT;
}
}
else
curvemapping_changed(cumap, 1); /* remove doubles */
ui_draw_but(but);
ui_block_flush_back(but->block);
}
else {
/* we move the view */
while(get_mbut() & L_MOUSE) {
uiGetMouse(mywinget(), mvalo);
if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
fx= (mvalo[0]-mval[0])/zoomx;
fy= (mvalo[1]-mval[1])/zoomy;
cumap->curr.xmin-=fx;
cumap->curr.ymin-=fy;
cumap->curr.xmax-=fx;
cumap->curr.ymax-=fy;
ui_draw_but(but);
ui_block_flush_back(but->block);
mval[0]= mvalo[0];
mval[1]= mvalo[1];
}
}
BIF_wait_for_statechange();
}
}
return but->retval;
}
/* ************************************************ */
void uiSetButLock(int val, char *lockstr)
@ -3524,6 +3665,9 @@ static int ui_do_button(uiBlock *block, uiBut *but, uiEvent *uevent)
case BUT_NORMAL:
retval= ui_do_but_NORMAL(but);
break;
case BUT_CURVE:
retval= ui_do_but_CURVE(but);
break;
#ifdef INTERNATIONAL
case CHARTAB:
@ -5807,6 +5951,23 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int
return but;
}
/* Block button containing icon */
uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip)
{
uiBut *but= ui_def_but(block, BLOCK, retval, "", x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
but->icon= (BIFIconID) icon;
but->flag|= UI_HAS_ICON;
but->flag|= UI_ICON_LEFT;
but->flag|= UI_ICON_RIGHT;
but->block_func= func;
ui_check_but(but);
return but;
}
void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip)
{
uiBut *but= ui_def_but(block, KEYEVT|SHO, retval, str, x1, y1, x2, y2, spoin, 0.0, 0.0, 0.0, 0.0, tip);

@ -55,6 +55,8 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "DNA_color_types.h"
#include "DNA_key_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@ -64,8 +66,10 @@
#include "DNA_vfont_types.h"
#include "BKE_blender.h"
#include "BKE_colortools.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_utildefines.h"
#include "datatoc.h" /* std font */
@ -211,7 +215,7 @@ static void ui_draw_icon(uiBut *but, BIFIconID icon)
else if(but->flag & UI_ACTIVE);
else blend= -60;
}
BIF_icon_draw_blended((int)(xs+0.5f), (int)(ys+0.5f), icon, but->themecol, blend);
BIF_icon_draw_blended(xs, ys, icon, but->themecol, blend);
glDisable(GL_BLEND);
@ -2050,6 +2054,126 @@ static void ui_draw_but_NORMAL(uiBut *but)
if(old[a])
glEnable(GL_LIGHT0+a);
}
}
static void ui_draw_but_curve_grid(uiBut *but, float zoomx, float zoomy, float offsx, float offsy, float step)
{
float dx, dy, fx, fy;
glBegin(GL_LINES);
dx= step*zoomx;
fx= but->x1 + zoomx*(-offsx);
if(fx > but->x1) fx -= dx*( floor(fx-but->x1));
while(fx < but->x2) {
glVertex2f(fx, but->y1);
glVertex2f(fx, but->y2);
fx+= dx;
}
dy= step*zoomy;
fy= but->y1 + zoomy*(-offsy);
if(fy > but->y1) fy -= dy*( floor(fy-but->y1));
while(fy < but->y2) {
glVertex2f(but->x1, fy);
glVertex2f(but->x2, fy);
fy+= dy;
}
glEnd();
}
static void ui_draw_but_CURVE(uiBut *but)
{
CurveMapping *cumap= (CurveMapping *)but->poin;
CurveMap *cuma= cumap->cm+cumap->cur;
CurveMapPoint *cmp;
float fx, fy, dx, dy, fac[2], zoomx, zoomy, offsx, offsy;
GLint scissor[4];
int a;
/* need scissor test, curve can draw outside of boundary */
glGetIntegerv(GL_VIEWPORT, scissor);
fx= but->x1; fy= but->y1;
ui_graphics_to_window(but->win, &fx, &fy);
dx= but->x2; dy= but->y2;
ui_graphics_to_window(but->win, &dx, &dy);
glScissor((int)floor(fx), (int)floor(fy), (int)ceil(dx-fx), (int)ceil(dy-fy));
/* calculate offset and zoom */
zoomx= (but->x2-but->x1-2.0*but->aspect)/(cumap->curr.xmax - cumap->curr.xmin);
zoomy= (but->y2-but->y1-2.0*but->aspect)/(cumap->curr.ymax - cumap->curr.ymin);
offsx= cumap->curr.xmin-but->aspect/zoomx;
offsy= cumap->curr.ymin-but->aspect/zoomy;
/* backdrop */
if(cumap->flag & CUMA_DO_CLIP) {
BIF_ThemeColorShade(TH_BUT_NEUTRAL, -20);
glRectf(but->x1, but->y1, but->x2, but->y2);
BIF_ThemeColor(TH_BUT_NEUTRAL);
glRectf(but->x1 + zoomx*(cumap->clipr.xmin-offsx),
but->y1 + zoomy*(cumap->clipr.ymin-offsy),
but->x1 + zoomx*(cumap->clipr.xmax-offsx),
but->y1 + zoomy*(cumap->clipr.ymax-offsy));
}
else {
BIF_ThemeColor(TH_BUT_NEUTRAL);
glRectf(but->x1, but->y1, but->x2, but->y2);
}
/* grid, every .25 step */
BIF_ThemeColorBlend(TH_BUT_NEUTRAL, TH_BUT_OUTLINE, 0.06f);
ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 0.25f);
/* grid, every 1.0 step */
BIF_ThemeColorBlend(TH_BUT_NEUTRAL, TH_BUT_OUTLINE, 0.12f);
ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 1.0f);
/* axes */
BIF_ThemeColorBlend(TH_BUT_NEUTRAL, TH_BUT_OUTLINE, 0.25f);
glBegin(GL_LINES);
glVertex2f(but->x1, but->y1 + zoomy*(-offsy));
glVertex2f(but->x2, but->y1 + zoomy*(-offsy));
glVertex2f(but->x1 + zoomx*(-offsx), but->y1);
glVertex2f(but->x1 + zoomx*(-offsx), but->y2);
glEnd();
/* the curve */
BIF_ThemeColor(TH_TEXT);
glBegin(GL_LINE_STRIP);
if(cuma->table==NULL)
curvemapping_changed(cumap, 0); /* 0 = no remove doubles */
cmp= cuma->table;
glVertex2f(but->x1, but->y1 + zoomy*(cmp[0].y-offsy)); /* first point */
for(a=0; a<=CM_TABLE; a++) {
fx= but->x1 + zoomx*(cmp[a].x-offsx);
fy= but->y1 + zoomy*(cmp[a].y-offsy);
glVertex2f(fx, fy);
}
glVertex2f(but->x2, but->y1 + zoomy*(cmp[a-1].y-offsy)); /* last point */
glEnd();
/* the points, use aspect to make them visible on edges */
cmp= cuma->curve;
glPointSize(3.0f);
bglBegin(GL_POINTS);
for(a=0; a<cuma->totpoint; a++) {
if(cmp[a].flag & SELECT)
BIF_ThemeColor(TH_TEXT_HI);
else
BIF_ThemeColor(TH_TEXT);
fac[0]= but->x1 + zoomx*(cmp[a].x-offsx);
fac[1]= but->y1 + zoomy*(cmp[a].y-offsy);
bglVertex2fv(fac);
}
bglEnd();
glPointSize(1.0f);
/* restore scissortest */
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
/* outline */
BIF_ThemeColor(TH_BUT_OUTLINE);
fdrawbox(but->x1, but->y1, but->x2, but->y2);
}
@ -2175,6 +2299,9 @@ void ui_draw_but(uiBut *but)
case BUT_NORMAL:
ui_draw_but_NORMAL(but);
break;
case BUT_CURVE:
ui_draw_but_CURVE(but);
break;
default:
but->embossfunc(but->type, but->themecol, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);

@ -57,6 +57,7 @@
#include "DNA_camera_types.h"
#include "DNA_image_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "BKE_global.h"
@ -73,10 +74,13 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BIF_interface.h"
#include "BIF_interface_icons.h"
#include "BIF_previewrender.h"
#include "BIF_resources.h" /* elubie: should be removed once the enum for the ICONS is in BIF_preview_icons.h */
#include "interface.h"
#include "PIL_time.h"
#include "RE_renderconverter.h"
@ -727,7 +731,7 @@ void BIF_icon_draw(float x, float y, int icon_id)
if (!di->rect) return; /* something has gone wrong! */
glRasterPos2f(x, y);
ui_rasterpos_safe(x, y, di->aspect);
/* di->rect contains image in 'rendersize', we only scale if needed */
if(di->rw!=di->w && di->rh!=di->h) {