forked from bartvdbraak/blender
ImagePaint Refactoring:
- ImagePaint now uses ImBuf directly, and the rect blending functions were moved into the imbuf module. - The brush spacing, timing and sampling was abstracted into brush.c, for later reuse in other paint modes. Float ImagePaint support. Textured Brushes: - Only the first texture channel is used now. - Options for size and offset should be added, but need to find some space in the panel, or add a second one ..
This commit is contained in:
parent
6bc2ada6fc
commit
e168d67b32
@ -36,22 +36,37 @@
|
|||||||
|
|
||||||
struct ID;
|
struct ID;
|
||||||
struct Brush;
|
struct Brush;
|
||||||
|
struct ImBuf;
|
||||||
|
|
||||||
|
/* datablock functions */
|
||||||
struct Brush *add_brush(char *name);
|
struct Brush *add_brush(char *name);
|
||||||
struct Brush *copy_brush(struct Brush *brush);
|
struct Brush *copy_brush(struct Brush *brush);
|
||||||
void make_local_brush(struct Brush *brush);
|
void make_local_brush(struct Brush *brush);
|
||||||
void free_brush(struct Brush *brush);
|
void free_brush(struct Brush *brush);
|
||||||
|
|
||||||
/* implementation of blending modes for use by different paint modes */
|
/* brush library operations used by different paint panels */
|
||||||
void brush_blend_rgb(char *outcol, char *col1, char *col2, int fac, short mode);
|
|
||||||
|
|
||||||
/* functions for brush datablock browsing used by different paint panels */
|
|
||||||
int brush_set_nr(struct Brush **current_brush, int nr);
|
int brush_set_nr(struct Brush **current_brush, int nr);
|
||||||
int brush_delete(struct Brush **current_brush);
|
int brush_delete(struct Brush **current_brush);
|
||||||
void brush_toggle_fake_user(struct Brush *brush);
|
|
||||||
int brush_clone_image_delete(struct Brush *brush);
|
|
||||||
int brush_clone_image_set_nr(struct Brush *brush, int nr);
|
|
||||||
void brush_check_exists(struct Brush **brush);
|
void brush_check_exists(struct Brush **brush);
|
||||||
|
void brush_toggle_fake_user(struct Brush *brush);
|
||||||
|
int brush_texture_set_nr(struct Brush *brush, int nr);
|
||||||
|
int brush_texture_delete(struct Brush *brush);
|
||||||
|
int brush_clone_image_set_nr(struct Brush *brush, int nr);
|
||||||
|
int brush_clone_image_delete(struct Brush *brush);
|
||||||
|
|
||||||
|
/* sampling */
|
||||||
|
void brush_sample(struct Brush *brush, float *xy, float dist, float *rgb, float *alpha, short texonly);
|
||||||
|
struct ImBuf *brush_imbuf_new(struct Brush *brush, short flt, short texonly, int size);
|
||||||
|
|
||||||
|
/* painting */
|
||||||
|
struct BrushPainter;
|
||||||
|
typedef struct BrushPainter BrushPainter;
|
||||||
|
typedef int (*BrushFunc)(void *user, struct ImBuf *ibuf, float *lastpos, float *pos);
|
||||||
|
|
||||||
|
BrushPainter *brush_painter_new(struct Brush *brush);
|
||||||
|
void brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size);
|
||||||
|
int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, void *user);
|
||||||
|
void brush_painter_free(BrushPainter *painter);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ void fluidsimSettingsFree(struct FluidsimSettings* sb) {}
|
|||||||
void fluidsimSettingsCopy(struct FluidsimSettings* sb) {}
|
void fluidsimSettingsCopy(struct FluidsimSettings* sb) {}
|
||||||
|
|
||||||
/*new render funcs */
|
/*new render funcs */
|
||||||
void externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta) {}
|
int externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta) { return 0; }
|
||||||
int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres) {return 0;}
|
int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres) {return 0;}
|
||||||
struct Render *RE_GetRender(const char *name) {return (struct Render *)NULL;}
|
struct Render *RE_GetRender(const char *name) {return (struct Render *)NULL;}
|
||||||
struct RenderResult *RE_GetResult(Render *re) {return (struct RenderResult *)NULL;}
|
struct RenderResult *RE_GetResult(Render *re) {return (struct RenderResult *)NULL;}
|
||||||
|
@ -30,18 +30,31 @@
|
|||||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "DNA_brush_types.h"
|
#include "DNA_brush_types.h"
|
||||||
#include "DNA_image_types.h"
|
#include "DNA_image_types.h"
|
||||||
|
#include "DNA_texture_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
|
|
||||||
|
#include "BLI_arithb.h"
|
||||||
#include "BLI_blenlib.h"
|
#include "BLI_blenlib.h"
|
||||||
|
|
||||||
#include "BKE_brush.h"
|
#include "BKE_brush.h"
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_library.h"
|
#include "BKE_library.h"
|
||||||
#include "BKE_main.h"
|
#include "BKE_main.h"
|
||||||
|
#include "BKE_texture.h"
|
||||||
|
#include "BKE_utildefines.h"
|
||||||
|
|
||||||
|
#include "IMB_imbuf.h"
|
||||||
|
#include "IMB_imbuf_types.h"
|
||||||
|
|
||||||
|
#include "RE_render_ext.h" /* externtex */
|
||||||
|
|
||||||
|
/* Datablock add/copy/free/make_local */
|
||||||
|
|
||||||
Brush *add_brush(char *name)
|
Brush *add_brush(char *name)
|
||||||
{
|
{
|
||||||
@ -68,9 +81,19 @@ Brush *add_brush(char *name)
|
|||||||
Brush *copy_brush(Brush *brush)
|
Brush *copy_brush(Brush *brush)
|
||||||
{
|
{
|
||||||
Brush *brushn;
|
Brush *brushn;
|
||||||
|
MTex *mtex;
|
||||||
|
int a;
|
||||||
|
|
||||||
brushn= copy_libblock(brush);
|
brushn= copy_libblock(brush);
|
||||||
|
|
||||||
|
for(a=0; a<MAX_MTEX; a++) {
|
||||||
|
mtex= brush->mtex[a];
|
||||||
|
if(mtex) {
|
||||||
|
brushn->mtex[a]= MEM_dupallocN(mtex);
|
||||||
|
if(mtex->tex) id_us_plus((ID*)mtex->tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* enable fake user by default */
|
/* enable fake user by default */
|
||||||
if (!(brushn->id.flag & LIB_FAKEUSER))
|
if (!(brushn->id.flag & LIB_FAKEUSER))
|
||||||
brush_toggle_fake_user(brushn);
|
brush_toggle_fake_user(brushn);
|
||||||
@ -81,12 +104,20 @@ Brush *copy_brush(Brush *brush)
|
|||||||
/* not brush itself */
|
/* not brush itself */
|
||||||
void free_brush(Brush *brush)
|
void free_brush(Brush *brush)
|
||||||
{
|
{
|
||||||
|
MTex *mtex;
|
||||||
|
int a;
|
||||||
|
|
||||||
|
for(a=0; a<MAX_MTEX; a++) {
|
||||||
|
mtex= brush->mtex[a];
|
||||||
|
if(mtex) {
|
||||||
|
if(mtex->tex) mtex->tex->id.us--;
|
||||||
|
MEM_freeN(mtex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void make_local_brush(Brush *brush)
|
void make_local_brush(Brush *brush)
|
||||||
{
|
{
|
||||||
/* don't forget: add stuff texture make local once texture bruses are added*/
|
|
||||||
|
|
||||||
/* - only lib users: do nothing
|
/* - only lib users: do nothing
|
||||||
* - only local users: set flag
|
* - only local users: set flag
|
||||||
* - mixed: make copy
|
* - mixed: make copy
|
||||||
@ -135,103 +166,7 @@ void make_local_brush(Brush *brush)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void brush_blend_mix(char *cp, char *cp1, char *cp2, int fac)
|
/* Library Operations */
|
||||||
{
|
|
||||||
/* this and other blending modes previously used >>8 instead of /255. both
|
|
||||||
are not equivalent (>>8 is /256), and the former results in rounding
|
|
||||||
errors that can turn colors black fast */
|
|
||||||
int mfac= 255-fac;
|
|
||||||
cp[0]= (mfac*cp1[0]+fac*cp2[0])/255;
|
|
||||||
cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
|
|
||||||
cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void brush_blend_add(char *cp, char *cp1, char *cp2, int fac)
|
|
||||||
{
|
|
||||||
int temp;
|
|
||||||
|
|
||||||
temp= cp1[0] + ((fac*cp2[0])/255);
|
|
||||||
if(temp>254) cp[0]= 255; else cp[0]= temp;
|
|
||||||
temp= cp1[1] + ((fac*cp2[1])/255);
|
|
||||||
if(temp>254) cp[1]= 255; else cp[1]= temp;
|
|
||||||
temp= cp1[2] + ((fac*cp2[2])/255);
|
|
||||||
if(temp>254) cp[2]= 255; else cp[2]= temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void brush_blend_sub(char *cp, char *cp1, char *cp2, int fac)
|
|
||||||
{
|
|
||||||
int temp;
|
|
||||||
|
|
||||||
temp= cp1[0] - ((fac*cp2[0])/255);
|
|
||||||
if(temp<0) cp[0]= 0; else cp[0]= temp;
|
|
||||||
temp= cp1[1] - ((fac*cp2[1])/255);
|
|
||||||
if(temp<0) cp[1]= 0; else cp[1]= temp;
|
|
||||||
temp= cp1[2] - ((fac*cp2[2])/255);
|
|
||||||
if(temp<0) cp[2]= 0; else cp[2]= temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void brush_blend_mul(char *cp, char *cp1, char *cp2, int fac)
|
|
||||||
{
|
|
||||||
int mfac= 255-fac;
|
|
||||||
|
|
||||||
/* first mul, then blend the fac */
|
|
||||||
cp[0]= (mfac*cp1[0] + fac*((cp2[0]*cp1[0])/255))/255;
|
|
||||||
cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255))/255;
|
|
||||||
cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255))/255;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void brush_blend_lighten(char *cp, char *cp1, char *cp2, int fac)
|
|
||||||
{
|
|
||||||
/* See if are lighter, if so mix, else dont do anything.
|
|
||||||
if the paint col is darker then the original, then ignore */
|
|
||||||
if (cp1[0]+cp1[1]+cp1[2] > cp2[0]+cp2[1]+cp2[2]) {
|
|
||||||
cp[0]= cp1[0];
|
|
||||||
cp[1]= cp1[1];
|
|
||||||
cp[2]= cp1[2];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
brush_blend_mix(cp, cp1, cp2, fac);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void brush_blend_darken(char *cp, char *cp1, char *cp2, int fac)
|
|
||||||
{
|
|
||||||
/* See if were darker, if so mix, else dont do anything.
|
|
||||||
if the paint col is brighter then the original, then ignore */
|
|
||||||
if (cp1[0]+cp1[1]+cp1[2] < cp2[0]+cp2[1]+cp2[2]) {
|
|
||||||
cp[0]= cp1[0];
|
|
||||||
cp[1]= cp1[1];
|
|
||||||
cp[2]= cp1[2];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
brush_blend_mix(cp, cp1, cp2, fac);
|
|
||||||
}
|
|
||||||
|
|
||||||
void brush_blend_rgb(char *outcol, char *col1, char *col2, int fac, short mode)
|
|
||||||
{
|
|
||||||
if (fac==0) {
|
|
||||||
outcol[0]= col1[0];
|
|
||||||
outcol[1]= col1[1];
|
|
||||||
outcol[2]= col1[2];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switch (mode) {
|
|
||||||
case BRUSH_BLEND_MIX:
|
|
||||||
brush_blend_mix(outcol, col1, col2, fac); break;
|
|
||||||
case BRUSH_BLEND_ADD:
|
|
||||||
brush_blend_add(outcol, col1, col2, fac); break;
|
|
||||||
case BRUSH_BLEND_SUB:
|
|
||||||
brush_blend_sub(outcol, col1, col2, fac); break;
|
|
||||||
case BRUSH_BLEND_MUL:
|
|
||||||
brush_blend_mul(outcol, col1, col2, fac); break;
|
|
||||||
case BRUSH_BLEND_LIGHTEN:
|
|
||||||
brush_blend_lighten(outcol, col1, col2, fac); break;
|
|
||||||
case BRUSH_BLEND_DARKEN:
|
|
||||||
brush_blend_darken(outcol, col1, col2, fac); break;
|
|
||||||
default:
|
|
||||||
brush_blend_mix(outcol, col1, col2, fac); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int brush_set_nr(Brush **current_brush, int nr)
|
int brush_set_nr(Brush **current_brush, int nr)
|
||||||
{
|
{
|
||||||
@ -261,6 +196,7 @@ int brush_delete(Brush **current_brush)
|
|||||||
if (*current_brush) {
|
if (*current_brush) {
|
||||||
(*current_brush)->id.us--;
|
(*current_brush)->id.us--;
|
||||||
*current_brush= NULL;
|
*current_brush= NULL;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,6 +217,51 @@ void brush_toggle_fake_user(Brush *brush)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int brush_texture_set_nr(Brush *brush, int nr)
|
||||||
|
{
|
||||||
|
ID *idtest, *id=NULL;
|
||||||
|
|
||||||
|
if(brush->mtex[brush->texact])
|
||||||
|
id= (ID *)brush->mtex[brush->texact]->tex;
|
||||||
|
|
||||||
|
idtest= (ID*)BLI_findlink(&G.main->tex, nr-1);
|
||||||
|
if(idtest==0) { /* new tex */
|
||||||
|
if(id) idtest= (ID *)copy_texture((Tex *)id);
|
||||||
|
else idtest= (ID *)add_texture("Tex");
|
||||||
|
idtest->us--;
|
||||||
|
}
|
||||||
|
if(idtest!=id) {
|
||||||
|
brush_texture_delete(brush);
|
||||||
|
|
||||||
|
if(brush->mtex[brush->texact]==NULL) {
|
||||||
|
brush->mtex[brush->texact]= add_mtex();
|
||||||
|
brush->mtex[brush->texact]->r = 1.0f;
|
||||||
|
brush->mtex[brush->texact]->g = 1.0f;
|
||||||
|
brush->mtex[brush->texact]->b = 1.0f;
|
||||||
|
}
|
||||||
|
brush->mtex[brush->texact]->tex= (Tex*)idtest;
|
||||||
|
id_us_plus(idtest);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int brush_texture_delete(Brush *brush)
|
||||||
|
{
|
||||||
|
if(brush->mtex[brush->texact]) {
|
||||||
|
if(brush->mtex[brush->texact]->tex)
|
||||||
|
brush->mtex[brush->texact]->tex->id.us--;
|
||||||
|
MEM_freeN(brush->mtex[brush->texact]);
|
||||||
|
brush->mtex[brush->texact]= NULL;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int brush_clone_image_set_nr(Brush *brush, int nr)
|
int brush_clone_image_set_nr(Brush *brush, int nr)
|
||||||
{
|
{
|
||||||
if(brush && nr > 0) {
|
if(brush && nr > 0) {
|
||||||
@ -316,3 +297,292 @@ void brush_check_exists(Brush **brush)
|
|||||||
brush_set_nr(brush, 1);
|
brush_set_nr(brush, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Brush Sampling */
|
||||||
|
|
||||||
|
static float brush_sample_falloff(Brush *brush, float dist)
|
||||||
|
{
|
||||||
|
float a, outer, inner;
|
||||||
|
|
||||||
|
outer = brush->size >> 1;
|
||||||
|
inner = outer*brush->innerradius;
|
||||||
|
|
||||||
|
if (dist <= inner) {
|
||||||
|
return brush->alpha;
|
||||||
|
}
|
||||||
|
else if ((dist < outer) && (inner < outer)) {
|
||||||
|
/* formula used by sculpt:
|
||||||
|
0.5f * (cos(3*(dist - inner)/(outer - inner)) + 1); */
|
||||||
|
a = sqrt((dist - inner)/(outer - inner));
|
||||||
|
return (1 - a)*brush->alpha;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void brush_sample(Brush *brush, float *xy, float dist, float *rgb, float *alpha, short texonly)
|
||||||
|
{
|
||||||
|
if (alpha) {
|
||||||
|
if (texonly) *alpha= 1.0;
|
||||||
|
else *alpha= brush_sample_falloff(brush, dist);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xy && brush->mtex[0] && brush->mtex[0]->tex) {
|
||||||
|
float co[3], tin, tr, tg, tb, ta;
|
||||||
|
int hasrgb;
|
||||||
|
|
||||||
|
co[0]= xy[0]/(brush->size >> 1);
|
||||||
|
co[1]= xy[1]/(brush->size >> 1);
|
||||||
|
co[2]= 0.0f;
|
||||||
|
|
||||||
|
hasrgb= externtex(brush->mtex[0], co, &tin, &tr, &tg, &tb, &ta);
|
||||||
|
|
||||||
|
if (rgb) {
|
||||||
|
if (hasrgb) {
|
||||||
|
rgb[0]= tr*brush->rgb[0];
|
||||||
|
rgb[1]= tg*brush->rgb[1];
|
||||||
|
rgb[2]= tb*brush->rgb[2];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rgb[0]= tin*brush->rgb[0];
|
||||||
|
rgb[1]= tin*brush->rgb[1];
|
||||||
|
rgb[2]= tin*brush->rgb[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (alpha && hasrgb)
|
||||||
|
*alpha *= ta;
|
||||||
|
}
|
||||||
|
else if (rgb)
|
||||||
|
VECCOPY(rgb, brush->rgb)
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
|
||||||
|
|
||||||
|
ImBuf *brush_imbuf_new(Brush *brush, short flt, short texonly, int size)
|
||||||
|
{
|
||||||
|
ImBuf *ibuf;
|
||||||
|
float w_2, h_2, xy[2], dist, rgba[3], *dstf;
|
||||||
|
unsigned int x, y, rowbytes;
|
||||||
|
char *dst;
|
||||||
|
|
||||||
|
if (texonly && !(brush->mtex[0] && brush->mtex[0]->tex))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
w_2 = size/2.0f;
|
||||||
|
h_2 = size/2.0f;
|
||||||
|
rowbytes= size*4;
|
||||||
|
|
||||||
|
if (flt) {
|
||||||
|
ibuf= IMB_allocImBuf(size, size, 32, IB_rectfloat, 0);
|
||||||
|
|
||||||
|
for (y=0; y < ibuf->y; y++) {
|
||||||
|
dstf = ibuf->rect_float + y*rowbytes;
|
||||||
|
|
||||||
|
for (x=0; x < ibuf->x; x++, dstf+=4) {
|
||||||
|
xy[0] = x + 0.5f - w_2;
|
||||||
|
xy[1] = y + 0.5f - h_2;
|
||||||
|
dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
|
||||||
|
|
||||||
|
brush_sample(brush, xy, dist, dstf, dstf+3, texonly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ibuf= IMB_allocImBuf(size, size, 32, IB_rect, 0);
|
||||||
|
|
||||||
|
for (y=0; y < ibuf->y; y++) {
|
||||||
|
dst = (char*)ibuf->rect + y*rowbytes;
|
||||||
|
|
||||||
|
for (x=0; x < ibuf->x; x++, dst+=4) {
|
||||||
|
xy[0] = x + 0.5f - w_2;
|
||||||
|
xy[1] = y + 0.5f - h_2;
|
||||||
|
dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
|
||||||
|
|
||||||
|
brush_sample(brush, xy, dist, rgba, rgba+3, texonly);
|
||||||
|
dst[0]= FTOCHAR(rgba[0]);
|
||||||
|
dst[1]= FTOCHAR(rgba[1]);
|
||||||
|
dst[2]= FTOCHAR(rgba[2]);
|
||||||
|
dst[3]= FTOCHAR(rgba[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ibuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Brush Painting */
|
||||||
|
|
||||||
|
struct BrushPainter {
|
||||||
|
Brush *brush;
|
||||||
|
|
||||||
|
float lastmousepos[2]; /* mouse position of last paint call */
|
||||||
|
|
||||||
|
float accumdistance; /* accumulated distance of brush since last paint op */
|
||||||
|
float lastpaintpos[2]; /* position of last paint op */
|
||||||
|
|
||||||
|
double accumtime; /* accumulated time since last paint op (airbrush) */
|
||||||
|
double lasttime; /* time of last update */
|
||||||
|
|
||||||
|
short firsttouch; /* first paint op */
|
||||||
|
|
||||||
|
struct BrushPainterImbufCache {
|
||||||
|
int size; /* size override, if 0 uses brush->size */
|
||||||
|
short flt; /* need float imbuf? */
|
||||||
|
short texonly; /* no alpha, color or fallof, only texture in imbuf */
|
||||||
|
short enabled;
|
||||||
|
|
||||||
|
int lastsize;
|
||||||
|
float lastalpha;
|
||||||
|
float lastinnerradius;
|
||||||
|
|
||||||
|
ImBuf *ibuf;
|
||||||
|
} cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
BrushPainter *brush_painter_new(Brush *brush)
|
||||||
|
{
|
||||||
|
BrushPainter *painter= MEM_callocN(sizeof(BrushPainter), "BrushPainter");
|
||||||
|
|
||||||
|
painter->brush= brush;
|
||||||
|
painter->firsttouch= 1;
|
||||||
|
|
||||||
|
return painter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
|
||||||
|
{
|
||||||
|
painter->cache.size = size;
|
||||||
|
painter->cache.flt = flt;
|
||||||
|
painter->cache.texonly = texonly;
|
||||||
|
painter->cache.enabled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void brush_painter_free(BrushPainter *painter)
|
||||||
|
{
|
||||||
|
if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
|
||||||
|
MEM_freeN(painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void brush_painter_refresh_cache(BrushPainter *painter)
|
||||||
|
{
|
||||||
|
Brush *brush= painter->brush;
|
||||||
|
|
||||||
|
if ((brush->size != painter->cache.lastsize)
|
||||||
|
|| (brush->alpha != painter->cache.lastalpha)
|
||||||
|
|| (brush->innerradius != painter->cache.lastinnerradius)) {
|
||||||
|
|
||||||
|
if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
|
||||||
|
|
||||||
|
painter->cache.ibuf= brush_imbuf_new(brush,
|
||||||
|
painter->cache.flt, painter->cache.texonly,
|
||||||
|
painter->cache.size? painter->cache.size: brush->size);
|
||||||
|
|
||||||
|
painter->cache.lastsize= brush->size;
|
||||||
|
painter->cache.lastalpha= brush->alpha;
|
||||||
|
painter->cache.lastinnerradius= brush->innerradius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, void *user)
|
||||||
|
{
|
||||||
|
Brush *brush= painter->brush;
|
||||||
|
int totpaintops= 0;
|
||||||
|
|
||||||
|
if (painter->firsttouch) {
|
||||||
|
/* paint exactly once on first touch */
|
||||||
|
if (painter->cache.enabled) brush_painter_refresh_cache(painter);
|
||||||
|
totpaintops += func(user, painter->cache.ibuf, pos, pos);
|
||||||
|
|
||||||
|
painter->lastpaintpos[0]= pos[0];
|
||||||
|
painter->lastpaintpos[1]= pos[1];
|
||||||
|
painter->lasttime= time;
|
||||||
|
|
||||||
|
painter->firsttouch= 0;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
else if (painter->brush->flag & BRUSH_AIRBRUSH) {
|
||||||
|
float spacing, step, paintpos[2], dmousepos[2], len;
|
||||||
|
double starttime, curtime= time;
|
||||||
|
|
||||||
|
/* compute brush spacing adapted to brush size */
|
||||||
|
spacing= brush->rate; //brush->size*brush->spacing*0.01f;
|
||||||
|
|
||||||
|
/* setup starting time, direction vector and accumulated time */
|
||||||
|
starttime= painter->accumtime;
|
||||||
|
Vec2Subf(dmousepos, pos, painter->lastmousepos);
|
||||||
|
len= Normalise2(dmousepos);
|
||||||
|
painter->accumtime += curtime - painter->lasttime;
|
||||||
|
|
||||||
|
/* do paint op over unpainted time distance */
|
||||||
|
while (painter->accumtime >= spacing) {
|
||||||
|
step= (spacing - starttime)*len;
|
||||||
|
paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
|
||||||
|
paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;
|
||||||
|
|
||||||
|
if (painter->cache.enabled) brush_painter_refresh_cache(painter);
|
||||||
|
totpaintops += func(user, painter->cache.ibuf, painter->lastpaintpos, paintpos);
|
||||||
|
|
||||||
|
painter->lastpaintpos[0]= paintpos[0];
|
||||||
|
painter->lastpaintpos[1]= paintpos[1];
|
||||||
|
painter->accumtime -= spacing;
|
||||||
|
starttime -= spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->lasttime= curtime;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else {
|
||||||
|
float startdistance, spacing, step, paintpos[2], dmousepos[2];
|
||||||
|
|
||||||
|
/* compute brush spacing adapted to brush size */
|
||||||
|
spacing= brush->size*brush->spacing*0.01f;
|
||||||
|
|
||||||
|
/* setup starting distance, direction vector and accumulated distance */
|
||||||
|
startdistance= painter->accumdistance;
|
||||||
|
Vec2Subf(dmousepos, pos, painter->lastmousepos);
|
||||||
|
painter->accumdistance += Normalise2(dmousepos);
|
||||||
|
|
||||||
|
/* do paint op over unpainted distance */
|
||||||
|
while (painter->accumdistance >= spacing) {
|
||||||
|
step= spacing - startdistance;
|
||||||
|
paintpos[0]= painter->lastmousepos[0] + dmousepos[0]*step;
|
||||||
|
paintpos[1]= painter->lastmousepos[1] + dmousepos[1]*step;
|
||||||
|
|
||||||
|
if (painter->cache.enabled) brush_painter_refresh_cache(painter);
|
||||||
|
totpaintops += func(user, painter->cache.ibuf, painter->lastpaintpos, paintpos);
|
||||||
|
|
||||||
|
painter->lastpaintpos[0]= paintpos[0];
|
||||||
|
painter->lastpaintpos[1]= paintpos[1];
|
||||||
|
painter->accumdistance -= spacing;
|
||||||
|
startdistance -= spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do airbrush paint ops, based on the number of paint ops left over
|
||||||
|
from regular painting. this is a temporary solution until we have
|
||||||
|
accurate time stamps for mouse move events */
|
||||||
|
if (brush->flag & BRUSH_AIRBRUSH) {
|
||||||
|
double curtime= time;
|
||||||
|
double painttime= brush->rate*totpaintops;
|
||||||
|
|
||||||
|
painter->accumtime += curtime - painter->lasttime;
|
||||||
|
if (painter->accumtime <= painttime)
|
||||||
|
painter->accumtime= 0.0;
|
||||||
|
else
|
||||||
|
painter->accumtime -= painttime;
|
||||||
|
|
||||||
|
while (painter->accumtime >= brush->rate) {
|
||||||
|
if (painter->cache.enabled) brush_painter_refresh_cache(painter);
|
||||||
|
totpaintops += func(user, painter->cache.ibuf, painter->lastmousepos, pos);
|
||||||
|
painter->accumtime -= brush->rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->lasttime= curtime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->lastmousepos[0]= pos[0];
|
||||||
|
painter->lastmousepos[1]= pos[1];
|
||||||
|
|
||||||
|
return totpaintops;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
#include "DNA_image_types.h"
|
#include "DNA_image_types.h"
|
||||||
#include "DNA_world_types.h"
|
#include "DNA_world_types.h"
|
||||||
|
#include "DNA_brush_types.h"
|
||||||
|
|
||||||
#include "IMB_imbuf_types.h"
|
#include "IMB_imbuf_types.h"
|
||||||
#include "IMB_imbuf.h"
|
#include "IMB_imbuf.h"
|
||||||
@ -77,6 +78,7 @@
|
|||||||
#include "BKE_key.h"
|
#include "BKE_key.h"
|
||||||
#include "BKE_icons.h"
|
#include "BKE_icons.h"
|
||||||
#include "BKE_ipo.h"
|
#include "BKE_ipo.h"
|
||||||
|
#include "BKE_brush.h"
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
@ -545,6 +547,7 @@ void make_local_texture(Tex *tex)
|
|||||||
Material *ma;
|
Material *ma;
|
||||||
World *wrld;
|
World *wrld;
|
||||||
Lamp *la;
|
Lamp *la;
|
||||||
|
Brush *br;
|
||||||
int a, local=0, lib=0;
|
int a, local=0, lib=0;
|
||||||
|
|
||||||
/* - only lib users: do nothing
|
/* - only lib users: do nothing
|
||||||
@ -599,6 +602,16 @@ void make_local_texture(Tex *tex)
|
|||||||
}
|
}
|
||||||
wrld= wrld->id.next;
|
wrld= wrld->id.next;
|
||||||
}
|
}
|
||||||
|
br= G.main->brush.first;
|
||||||
|
while(br) {
|
||||||
|
for(a=0; a<MAX_MTEX; a++) {
|
||||||
|
if(br->mtex[a] && br->mtex[a]->tex==tex) {
|
||||||
|
if(br->id.lib) lib= 1;
|
||||||
|
else local= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
br= br->id.next;
|
||||||
|
}
|
||||||
|
|
||||||
if(local && lib==0) {
|
if(local && lib==0) {
|
||||||
tex->id.lib= 0;
|
tex->id.lib= 0;
|
||||||
@ -648,7 +661,19 @@ void make_local_texture(Tex *tex)
|
|||||||
}
|
}
|
||||||
wrld= wrld->id.next;
|
wrld= wrld->id.next;
|
||||||
}
|
}
|
||||||
|
br= G.main->brush.first;
|
||||||
|
while(br) {
|
||||||
|
for(a=0; a<MAX_MTEX; a++) {
|
||||||
|
if(br->mtex[a] && br->mtex[a]->tex==tex) {
|
||||||
|
if(br->id.lib==0) {
|
||||||
|
br->mtex[a]->tex= texn;
|
||||||
|
texn->id.us++;
|
||||||
|
tex->id.us--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
br= br->id.next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1183,26 +1183,36 @@ static void test_pointer_array(FileData *fd, void **mat)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************ READ BRUSH *************** */
|
/* ************ READ Brush *************** */
|
||||||
|
|
||||||
/* library brush linking after fileread */
|
/* library brush linking after fileread */
|
||||||
static void lib_link_brush(FileData *fd, Main *main)
|
static void lib_link_brush(FileData *fd, Main *main)
|
||||||
{
|
{
|
||||||
Brush *brush;
|
Brush *brush;
|
||||||
|
MTex *mtex;
|
||||||
|
int a;
|
||||||
|
|
||||||
/* only link ID pointers */
|
/* only link ID pointers */
|
||||||
for(brush= main->brush.first; brush; brush= brush->id.next) {
|
for(brush= main->brush.first; brush; brush= brush->id.next) {
|
||||||
if(brush->id.flag & LIB_NEEDLINK) {
|
if(brush->id.flag & LIB_NEEDLINK) {
|
||||||
brush->id.flag -= LIB_NEEDLINK;
|
brush->id.flag -= LIB_NEEDLINK;
|
||||||
/* nothing to do yet - until brush gets textures */
|
|
||||||
|
for(a=0; a<MAX_MTEX; a++) {
|
||||||
|
mtex= brush->mtex[a];
|
||||||
|
if(mtex)
|
||||||
|
mtex->tex= newlibadr_us(fd, brush->id.lib, mtex->tex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* brush itself has been read! */
|
|
||||||
static void direct_link_brush(FileData *fd, Brush *brush)
|
static void direct_link_brush(FileData *fd, Brush *brush)
|
||||||
{
|
{
|
||||||
/* nothing to do yet - until brush gets textures */
|
/* brush itself has been read */
|
||||||
|
int a;
|
||||||
|
|
||||||
|
for(a=0; a<MAX_MTEX; a++)
|
||||||
|
brush->mtex[a]= newdataadr(fd, brush->mtex[a]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************ READ CurveMapping *************** */
|
/* ************ READ CurveMapping *************** */
|
||||||
@ -5802,7 +5812,12 @@ static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
|
|||||||
|
|
||||||
static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
|
static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
|
||||||
{
|
{
|
||||||
/* nothing to do yet - until brush gets texture */
|
int a;
|
||||||
|
|
||||||
|
for(a=0; a<MAX_MTEX; a++)
|
||||||
|
if(brush->mtex[a])
|
||||||
|
expand_doit(fd, mainvar, brush->mtex[a]->tex);
|
||||||
|
expand_doit(fd, mainvar, brush->clone.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
|
static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
|
||||||
|
@ -1596,10 +1596,16 @@ static void write_nodetrees(WriteData *wd, ListBase *idbase)
|
|||||||
static void write_brushes(WriteData *wd, ListBase *idbase)
|
static void write_brushes(WriteData *wd, ListBase *idbase)
|
||||||
{
|
{
|
||||||
Brush *brush;
|
Brush *brush;
|
||||||
|
int a;
|
||||||
|
|
||||||
for(brush=idbase->first; brush; brush= brush->id.next)
|
for(brush=idbase->first; brush; brush= brush->id.next) {
|
||||||
if (brush->id.us>0 || wd->current)
|
if(brush->id.us>0 || wd->current) {
|
||||||
writestruct(wd, ID_BR, "Brush", 1, brush);
|
writestruct(wd, ID_BR, "Brush", 1, brush);
|
||||||
|
for(a=0; a<MAX_MTEX; a++)
|
||||||
|
if(brush->mtex[a])
|
||||||
|
writestruct(wd, DATA, "MTex", 1, brush->mtex[a]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_global(WriteData *wd)
|
static void write_global(WriteData *wd)
|
||||||
|
@ -219,8 +219,33 @@ void IMB_freecmapImBuf(struct ImBuf * ibuf);
|
|||||||
*
|
*
|
||||||
* @attention Defined in rectop.c
|
* @attention Defined in rectop.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef enum IMB_BlendMode {
|
||||||
|
IMB_BLEND_MIX = 0,
|
||||||
|
IMB_BLEND_ADD = 1,
|
||||||
|
IMB_BLEND_SUB = 2,
|
||||||
|
IMB_BLEND_MUL = 3,
|
||||||
|
IMB_BLEND_LIGHTEN = 4,
|
||||||
|
IMB_BLEND_DARKEN = 5,
|
||||||
|
|
||||||
|
IMB_BLEND_COPY = 1000,
|
||||||
|
IMB_BLEND_COPY_RGB = 1001,
|
||||||
|
IMB_BLEND_COPY_ALPHA = 1002
|
||||||
|
} IMB_BlendMode;
|
||||||
|
|
||||||
|
unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac,
|
||||||
|
IMB_BlendMode mode);
|
||||||
|
void IMB_blend_color_float(float *dst, float *src1, float *src2, float fac,
|
||||||
|
IMB_BlendMode mode);
|
||||||
|
|
||||||
|
void IMB_rectclip(struct ImBuf *dbuf, struct ImBuf *sbuf, int *destx,
|
||||||
|
int *desty, int *srcx, int *srcy, int *width, int *height);
|
||||||
void IMB_rectcpy(struct ImBuf *drect, struct ImBuf *srect, int destx,
|
void IMB_rectcpy(struct ImBuf *drect, struct ImBuf *srect, int destx,
|
||||||
int desty, int srcx, int srcy, int width, int height);
|
int desty, int srcx, int srcy, int width, int height);
|
||||||
|
void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
|
||||||
|
int desty, int srcx, int srcy, int width, int height, IMB_BlendMode mode);
|
||||||
|
void IMB_rectblend_torus(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
|
||||||
|
int desty, int srcx, int srcy, int width, int height, IMB_BlendMode mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the length (in frames) of the given @a anim.
|
* Return the length (in frames) of the given @a anim.
|
||||||
|
@ -41,104 +41,433 @@
|
|||||||
|
|
||||||
#include "IMB_allocimbuf.h"
|
#include "IMB_allocimbuf.h"
|
||||||
|
|
||||||
void IMB_rectcpy(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
|
/* blend modes */
|
||||||
int desty, int srcx, int srcy, int width, int height)
|
|
||||||
|
static void blend_color_mix(char *cp, char *cp1, char *cp2, int fac)
|
||||||
{
|
{
|
||||||
unsigned int *drect, *srect;
|
/* this and other blending modes previously used >>8 instead of /255. both
|
||||||
float *drectf = NULL;
|
are not equivalent (>>8 is /256), and the former results in rounding
|
||||||
float *srectf = NULL;
|
errors that can turn colors black fast after repeated blending */
|
||||||
int tmp, do_float = 0;
|
int mfac= 255-fac;
|
||||||
|
cp[0]= (mfac*cp1[0]+fac*cp2[0])/255;
|
||||||
|
cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
|
||||||
|
cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_add(char *cp, char *cp1, char *cp2, int fac)
|
||||||
|
{
|
||||||
|
int temp;
|
||||||
|
|
||||||
|
temp= cp1[0] + ((fac*cp2[0])/255);
|
||||||
|
if(temp>254) cp[0]= 255; else cp[0]= temp;
|
||||||
|
temp= cp1[1] + ((fac*cp2[1])/255);
|
||||||
|
if(temp>254) cp[1]= 255; else cp[1]= temp;
|
||||||
|
temp= cp1[2] + ((fac*cp2[2])/255);
|
||||||
|
if(temp>254) cp[2]= 255; else cp[2]= temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_sub(char *cp, char *cp1, char *cp2, int fac)
|
||||||
|
{
|
||||||
|
int temp;
|
||||||
|
|
||||||
|
temp= cp1[0] - ((fac*cp2[0])/255);
|
||||||
|
if(temp<0) cp[0]= 0; else cp[0]= temp;
|
||||||
|
temp= cp1[1] - ((fac*cp2[1])/255);
|
||||||
|
if(temp<0) cp[1]= 0; else cp[1]= temp;
|
||||||
|
temp= cp1[2] - ((fac*cp2[2])/255);
|
||||||
|
if(temp<0) cp[2]= 0; else cp[2]= temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_mul(char *cp, char *cp1, char *cp2, int fac)
|
||||||
|
{
|
||||||
|
int mfac= 255-fac;
|
||||||
|
|
||||||
|
/* first mul, then blend the fac */
|
||||||
|
cp[0]= (mfac*cp1[0] + fac*((cp1[0]*cp2[0])/255))/255;
|
||||||
|
cp[1]= (mfac*cp1[1] + fac*((cp1[1]*cp2[1])/255))/255;
|
||||||
|
cp[2]= (mfac*cp1[2] + fac*((cp1[2]*cp2[2])/255))/255;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_lighten(char *cp, char *cp1, char *cp2, int fac)
|
||||||
|
{
|
||||||
|
/* See if are lighter, if so mix, else dont do anything.
|
||||||
|
if the paint col is darker then the original, then ignore */
|
||||||
|
if (cp1[0]+cp1[1]+cp1[2] > cp2[0]+cp2[1]+cp2[2]) {
|
||||||
|
cp[0]= cp1[0];
|
||||||
|
cp[1]= cp1[1];
|
||||||
|
cp[2]= cp1[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
blend_color_mix(cp, cp1, cp2, fac);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_darken(char *cp, char *cp1, char *cp2, int fac)
|
||||||
|
{
|
||||||
|
/* See if were darker, if so mix, else dont do anything.
|
||||||
|
if the paint col is brighter then the original, then ignore */
|
||||||
|
if (cp1[0]+cp1[1]+cp1[2] < cp2[0]+cp2[1]+cp2[2]) {
|
||||||
|
cp[0]= cp1[0];
|
||||||
|
cp[1]= cp1[1];
|
||||||
|
cp[2]= cp1[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
blend_color_mix(cp, cp1, cp2, fac);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_BlendMode mode)
|
||||||
|
{
|
||||||
|
unsigned int dst;
|
||||||
|
char *cp, *cp1, *cp2;
|
||||||
|
|
||||||
|
if (fac==0)
|
||||||
|
return src1;
|
||||||
|
|
||||||
|
cp = (char*)&dst;
|
||||||
|
cp1 = (char*)&src1;
|
||||||
|
cp2 = (char*)&src2;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case IMB_BLEND_MIX:
|
||||||
|
blend_color_mix(cp, cp1, cp2, fac); break;
|
||||||
|
case IMB_BLEND_ADD:
|
||||||
|
blend_color_add(cp, cp1, cp2, fac); break;
|
||||||
|
case IMB_BLEND_SUB:
|
||||||
|
blend_color_sub(cp, cp1, cp2, fac); break;
|
||||||
|
case IMB_BLEND_MUL:
|
||||||
|
blend_color_mul(cp, cp1, cp2, fac); break;
|
||||||
|
case IMB_BLEND_LIGHTEN:
|
||||||
|
blend_color_lighten(cp, cp1, cp2, fac); break;
|
||||||
|
case IMB_BLEND_DARKEN:
|
||||||
|
blend_color_darken(cp, cp1, cp2, fac); break;
|
||||||
|
default:
|
||||||
|
return src1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_mix_float(float *cp, float *cp1, float *cp2, float fac)
|
||||||
|
{
|
||||||
|
float mfac= 1.0-fac;
|
||||||
|
cp[0]= mfac*cp1[0] + fac*cp2[0];
|
||||||
|
cp[1]= mfac*cp1[1] + fac*cp2[1];
|
||||||
|
cp[2]= mfac*cp1[2] + fac*cp2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_add_float(float *cp, float *cp1, float *cp2, float fac)
|
||||||
|
{
|
||||||
|
cp[0] = cp1[0] + fac*cp2[0];
|
||||||
|
cp[1] = cp1[1] + fac*cp2[1];
|
||||||
|
cp[2] = cp1[2] + fac*cp2[2];
|
||||||
|
|
||||||
|
if (cp[0] > 1.0f) cp[0]= 1.0f;
|
||||||
|
if (cp[1] > 1.0f) cp[1]= 1.0f;
|
||||||
|
if (cp[2] > 1.0f) cp[2]= 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_sub_float(float *cp, float *cp1, float *cp2, float fac)
|
||||||
|
{
|
||||||
|
cp[0] = cp1[0] - fac*cp2[0];
|
||||||
|
cp[1] = cp1[1] - fac*cp2[1];
|
||||||
|
cp[2] = cp1[2] - fac*cp2[2];
|
||||||
|
|
||||||
|
if (cp[0] < 0.0f) cp[0]= 0.0f;
|
||||||
|
if (cp[1] < 0.0f) cp[1]= 0.0f;
|
||||||
|
if (cp[2] < 0.0f) cp[2]= 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_mul_float(float *cp, float *cp1, float *cp2, float fac)
|
||||||
|
{
|
||||||
|
float mfac= 1.0-fac;
|
||||||
|
|
||||||
|
cp[0]= mfac*cp1[0] + fac*(cp1[0]*cp2[0]);
|
||||||
|
cp[1]= mfac*cp1[1] + fac*(cp1[1]*cp2[1]);
|
||||||
|
cp[2]= mfac*cp1[2] + fac*(cp1[2]*cp2[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_lighten_float(float *cp, float *cp1, float *cp2, float fac)
|
||||||
|
{
|
||||||
|
/* See if are lighter, if so mix, else dont do anything.
|
||||||
|
if the pafloat col is darker then the original, then ignore */
|
||||||
|
if (cp1[0]+cp1[1]+cp1[2] > cp2[0]+cp2[1]+cp2[2]) {
|
||||||
|
cp[0]= cp1[0];
|
||||||
|
cp[1]= cp1[1];
|
||||||
|
cp[2]= cp1[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
blend_color_mix_float(cp, cp1, cp2, fac);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_color_darken_float(float *cp, float *cp1, float *cp2, float fac)
|
||||||
|
{
|
||||||
|
/* See if were darker, if so mix, else dont do anything.
|
||||||
|
if the pafloat col is brighter then the original, then ignore */
|
||||||
|
if (cp1[0]+cp1[1]+cp1[2] < cp2[0]+cp2[1]+cp2[2]) {
|
||||||
|
cp[0]= cp1[0];
|
||||||
|
cp[1]= cp1[1];
|
||||||
|
cp[2]= cp1[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
blend_color_mix_float(cp, cp1, cp2, fac);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMB_blend_color_float(float *dst, float *src1, float *src2, float fac, IMB_BlendMode mode)
|
||||||
|
{
|
||||||
|
if (fac==0) {
|
||||||
|
dst[0]= src1[0];
|
||||||
|
dst[1]= src1[1];
|
||||||
|
dst[2]= src1[2];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case IMB_BLEND_MIX:
|
||||||
|
blend_color_mix_float(dst, src1, src2, fac); break;
|
||||||
|
case IMB_BLEND_ADD:
|
||||||
|
blend_color_add_float(dst, src1, src2, fac); break;
|
||||||
|
case IMB_BLEND_SUB:
|
||||||
|
blend_color_sub_float(dst, src1, src2, fac); break;
|
||||||
|
case IMB_BLEND_MUL:
|
||||||
|
blend_color_mul_float(dst, src1, src2, fac); break;
|
||||||
|
case IMB_BLEND_LIGHTEN:
|
||||||
|
blend_color_lighten_float(dst, src1, src2, fac); break;
|
||||||
|
case IMB_BLEND_DARKEN:
|
||||||
|
blend_color_darken_float(dst, src1, src2, fac); break;
|
||||||
|
default:
|
||||||
|
dst[0]= src1[0];
|
||||||
|
dst[1]= src1[1];
|
||||||
|
dst[2]= src1[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clipping */
|
||||||
|
|
||||||
|
void IMB_rectclip(struct ImBuf *dbuf, struct ImBuf *sbuf, int *destx,
|
||||||
|
int *desty, int *srcx, int *srcy, int *width, int *height)
|
||||||
|
{
|
||||||
|
int tmp;
|
||||||
|
|
||||||
if (dbuf == NULL) return;
|
if (dbuf == NULL) return;
|
||||||
|
|
||||||
if (sbuf && sbuf->rect_float && dbuf->rect_float) do_float = 1;
|
if (*destx < 0) {
|
||||||
|
*srcx -= *destx ;
|
||||||
if (destx < 0){
|
*width += *destx ;
|
||||||
srcx -= destx ;
|
*destx = 0;
|
||||||
width += destx ;
|
|
||||||
destx = 0;
|
|
||||||
}
|
}
|
||||||
if (srcx < 0){
|
if (*srcx < 0) {
|
||||||
destx -= srcx ;
|
*destx -= *srcx ;
|
||||||
width += destx ;
|
*width += *destx ;
|
||||||
srcx = 0;
|
*srcx = 0;
|
||||||
}
|
}
|
||||||
if (desty < 0){
|
if (*desty < 0) {
|
||||||
srcy -= desty ;
|
*srcy -= *desty ;
|
||||||
height += desty ;
|
*height += *desty ;
|
||||||
desty = 0;
|
*desty = 0;
|
||||||
}
|
}
|
||||||
if (srcy < 0){
|
if (*srcy < 0) {
|
||||||
desty -= srcy ;
|
*desty -= *srcy ;
|
||||||
height += desty ;
|
*height += *desty ;
|
||||||
srcy = 0;
|
*srcy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = dbuf->x - destx;
|
tmp = dbuf->x - *destx;
|
||||||
if (width > tmp) width = tmp;
|
if (*width > tmp) *width = tmp;
|
||||||
tmp = dbuf->y - desty;
|
tmp = dbuf->y - *desty;
|
||||||
if (height > tmp) height = tmp;
|
if (*height > tmp) *height = tmp;
|
||||||
|
|
||||||
drect = dbuf->rect + desty * dbuf->x + destx;
|
|
||||||
if (do_float) drectf = dbuf->rect_float + desty * dbuf->x + destx;
|
|
||||||
destx = dbuf->x;
|
|
||||||
|
|
||||||
if (sbuf) {
|
if (sbuf) {
|
||||||
tmp = sbuf->x - srcx;
|
tmp = sbuf->x - *srcx;
|
||||||
if (width > tmp) width = tmp;
|
if (*width > tmp) *width = tmp;
|
||||||
tmp = sbuf->y - srcy;
|
tmp = sbuf->y - *srcy;
|
||||||
if (height > tmp) height = tmp;
|
if (*height > tmp) *height = tmp;
|
||||||
|
}
|
||||||
if (width <= 0) return;
|
|
||||||
if (height <= 0) return;
|
|
||||||
|
|
||||||
srect = sbuf->rect;
|
|
||||||
srect += srcy * sbuf->x;
|
|
||||||
srect += srcx;
|
|
||||||
if (do_float) {
|
|
||||||
srectf = sbuf->rect_float;
|
|
||||||
srectf += srcy * sbuf->x;
|
|
||||||
srectf += srcx;
|
|
||||||
}
|
}
|
||||||
srcx = sbuf->x;
|
|
||||||
} else{
|
|
||||||
if (width <= 0) return;
|
|
||||||
if (height <= 0) return;
|
|
||||||
|
|
||||||
|
/* copy and blend */
|
||||||
|
|
||||||
|
void IMB_rectcpy(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
|
||||||
|
int desty, int srcx, int srcy, int width, int height)
|
||||||
|
{
|
||||||
|
IMB_rectblend(dbuf, sbuf, destx, desty, srcx, srcy, width, height,
|
||||||
|
IMB_BLEND_COPY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
|
||||||
|
int desty, int srcx, int srcy, int width, int height, IMB_BlendMode mode)
|
||||||
|
{
|
||||||
|
unsigned int *drect = NULL, *srect = NULL, *dr, *sr;
|
||||||
|
float *drectf = NULL, *srectf = NULL, *drf, *srf;
|
||||||
|
int do_float, do_char, srcskip, destskip, x;
|
||||||
|
|
||||||
|
if (dbuf == NULL) return;
|
||||||
|
|
||||||
|
IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &width, &height);
|
||||||
|
|
||||||
|
if (width == 0 || height == 0) return;
|
||||||
|
|
||||||
|
do_char = (sbuf && sbuf->rect && dbuf->rect);
|
||||||
|
do_float = (sbuf && sbuf->rect_float && dbuf->rect_float);
|
||||||
|
|
||||||
|
if (do_char) drect = dbuf->rect + desty * dbuf->x + destx;
|
||||||
|
if (do_float) drectf = dbuf->rect_float + (desty * dbuf->x + destx)*4;
|
||||||
|
|
||||||
|
destskip = dbuf->x;
|
||||||
|
|
||||||
|
if (sbuf) {
|
||||||
|
if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx;
|
||||||
|
if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx)*4;
|
||||||
|
srcskip = sbuf->x;
|
||||||
|
} else {
|
||||||
srect = drect;
|
srect = drect;
|
||||||
srectf = drectf;
|
srectf = drectf;
|
||||||
srcx = destx;
|
srcskip = destskip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode == IMB_BLEND_COPY) {
|
||||||
|
/* copy */
|
||||||
for (;height > 0; height--) {
|
for (;height > 0; height--) {
|
||||||
|
if (do_char) {
|
||||||
memcpy(drect,srect, width * sizeof(int));
|
memcpy(drect,srect, width * sizeof(int));
|
||||||
drect += destx;
|
drect += destskip;
|
||||||
srect += srcx;
|
srect += srcskip;
|
||||||
|
}
|
||||||
|
|
||||||
if (do_float) {
|
if (do_float) {
|
||||||
memcpy(drectf,srectf, width * sizeof(float) * 4);
|
memcpy(drectf,srectf, width * sizeof(float) * 4);
|
||||||
drectf += destx;
|
drectf += destskip*4;
|
||||||
srectf += srcx;
|
srectf += srcskip*4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (mode == IMB_BLEND_COPY_RGB) {
|
||||||
|
/* copy rgb only */
|
||||||
|
for (;height > 0; height--) {
|
||||||
|
if (do_char) {
|
||||||
|
dr = drect;
|
||||||
|
sr = srect;
|
||||||
|
for (x=width; x > 0; x--, dr++, sr++) {
|
||||||
|
((char*)dr)[0]= ((char*)sr)[0];
|
||||||
|
((char*)dr)[1]= ((char*)sr)[1];
|
||||||
|
((char*)dr)[2]= ((char*)sr)[2];
|
||||||
|
}
|
||||||
|
drect += destskip;
|
||||||
|
srect += srcskip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_float) {
|
||||||
|
drf = drectf;
|
||||||
|
srf = srectf;
|
||||||
|
for (x=width; x > 0; x--, drf+=4, srf+=4) {
|
||||||
|
drf[0]= srf[0];
|
||||||
|
drf[1]= srf[1];
|
||||||
|
drf[2]= srf[2];
|
||||||
|
}
|
||||||
|
drectf += destskip*4;
|
||||||
|
srectf += srcskip*4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mode == IMB_BLEND_COPY_ALPHA) {
|
||||||
|
/* copy alpha only */
|
||||||
|
for (;height > 0; height--) {
|
||||||
|
if (do_char) {
|
||||||
|
dr = drect;
|
||||||
|
sr = srect;
|
||||||
|
for (x=width; x > 0; x--, dr++, sr++)
|
||||||
|
((char*)dr)[3]= ((char*)sr)[3];
|
||||||
|
drect += destskip;
|
||||||
|
srect += srcskip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_float) {
|
||||||
|
drf = drectf;
|
||||||
|
srf = srectf;
|
||||||
|
for (x=width; x > 0; x--, drf+=4, srf+=4)
|
||||||
|
drf[3]= srf[3];
|
||||||
|
drectf += destskip*4;
|
||||||
|
srectf += srcskip*4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* blend */
|
||||||
|
for (;height > 0; height--) {
|
||||||
|
if (do_char) {
|
||||||
|
dr = drect;
|
||||||
|
sr = srect;
|
||||||
|
for (x=width; x > 0; x--, dr++, sr++)
|
||||||
|
*dr = IMB_blend_color(*dr, *sr, ((char*)sr)[3], mode);
|
||||||
|
|
||||||
|
drect += destskip;
|
||||||
|
srect += srcskip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_float) {
|
||||||
|
drf = drectf;
|
||||||
|
srf = srectf;
|
||||||
|
for (x=width; x > 0; x--, drf+=4, srf+=4)
|
||||||
|
IMB_blend_color_float(drf, drf, srf, srf[3], mode);
|
||||||
|
|
||||||
|
drectf += destskip*4;
|
||||||
|
srectf += srcskip*4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMB_rectblend_torus(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
|
||||||
|
int desty, int srcx, int srcy, int width, int height, IMB_BlendMode mode)
|
||||||
|
{
|
||||||
|
int origw, origh, w, h;
|
||||||
|
|
||||||
|
/* convert destination and source coordinates too be withing image */
|
||||||
|
destx = destx % dbuf->x;
|
||||||
|
if (destx < 0) destx += dbuf->x;
|
||||||
|
desty = desty % dbuf->y;
|
||||||
|
if (desty < 0) desty += dbuf->y;
|
||||||
|
srcx = srcx % sbuf->x;
|
||||||
|
if (srcx < 0) srcx += sbuf->x;
|
||||||
|
srcy = srcy % sbuf->y;
|
||||||
|
if (srcy < 0) srcy += sbuf->y;
|
||||||
|
|
||||||
|
/* clip width of blending area to destination imbuf, to avoid writing the
|
||||||
|
same pixel twice */
|
||||||
|
origw = w = (width > dbuf->x)? dbuf->x: width;
|
||||||
|
origh = h = (height > dbuf->y)? dbuf->y: height;
|
||||||
|
|
||||||
|
/* clip and blend */
|
||||||
|
IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h);
|
||||||
|
IMB_rectblend(dbuf, sbuf, destx, desty, srcx, srcy, w, h, mode);
|
||||||
|
|
||||||
|
/* do 3 other rects if needed */
|
||||||
|
if (w < origw)
|
||||||
|
IMB_rectblend(dbuf, sbuf, (destx+w)%dbuf->x, desty, (srcx+w)%sbuf->x, srcy,
|
||||||
|
origw-w, h, mode);
|
||||||
|
if (h < origh)
|
||||||
|
IMB_rectblend(dbuf, sbuf, destx, (desty+h)%dbuf->y, srcx, (srcy+h)%sbuf->y,
|
||||||
|
w, origh-h, mode);
|
||||||
|
if ((w < origw) && (h < origh))
|
||||||
|
IMB_rectblend(dbuf, sbuf, (destx+w)%dbuf->x, (desty+h)%dbuf->y,
|
||||||
|
(srcx+w)%sbuf->x, (srcy+h)%sbuf->y, origw-w, origh-h, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill */
|
||||||
|
|
||||||
void IMB_rectfill(struct ImBuf *drect, float col[4])
|
void IMB_rectfill(struct ImBuf *drect, float col[4])
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
unsigned int *rrect = drect->rect;
|
unsigned int *rrect = drect->rect;
|
||||||
unsigned char *spot;
|
char ccol[4];
|
||||||
|
|
||||||
|
ccol[0]= (int)(col[0]*255);
|
||||||
|
ccol[1]= (int)(col[1]*255);
|
||||||
|
ccol[2]= (int)(col[2]*255);
|
||||||
|
ccol[3]= (int)(col[3]*255);
|
||||||
|
|
||||||
num = drect->x * drect->y;
|
num = drect->x * drect->y;
|
||||||
for (;num > 0; num--) {
|
for (;num > 0; num--)
|
||||||
spot = (unsigned char *)rrect;
|
*rrect++ = *((unsigned int*)ccol);
|
||||||
spot[0] = (int)(col[0]*255);
|
|
||||||
spot[1] = (int)(col[1]*255);
|
|
||||||
spot[2] = (int)(col[2]*255);
|
|
||||||
spot[3] = (int)(col[3]*255);
|
|
||||||
*rrect++;
|
|
||||||
}
|
|
||||||
if(drect->rect_float) {
|
if(drect->rect_float) {
|
||||||
float *rrectf = drect->rect_float;
|
float *rrectf = drect->rect_float;
|
||||||
|
|
||||||
|
@ -320,6 +320,8 @@
|
|||||||
#define B_SIMABRUSHDELETE 375
|
#define B_SIMABRUSHDELETE 375
|
||||||
#define B_SIMABRUSHLOCAL 376
|
#define B_SIMABRUSHLOCAL 376
|
||||||
#define B_SIMABRUSHCHANGE 377
|
#define B_SIMABRUSHCHANGE 377
|
||||||
|
#define B_SIMABTEXBROWSE 378
|
||||||
|
#define B_SIMABTEXDELETE 379
|
||||||
|
|
||||||
/* BUTS: 400 */
|
/* BUTS: 400 */
|
||||||
#define B_BUTSHOME 401
|
#define B_BUTSHOME 401
|
||||||
|
@ -541,6 +541,7 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
|
|||||||
#define B_BRUSHDELETE 2852
|
#define B_BRUSHDELETE 2852
|
||||||
#define B_BRUSHLOCAL 2853
|
#define B_BRUSHLOCAL 2853
|
||||||
#define B_BRUSHCHANGE 2854
|
#define B_BRUSHCHANGE 2854
|
||||||
|
#define B_BTEXBROWSE 2855
|
||||||
|
|
||||||
/* *********************** */
|
/* *********************** */
|
||||||
#define B_RADIOBUTS 3000
|
#define B_RADIOBUTS 3000
|
||||||
|
@ -32,6 +32,13 @@
|
|||||||
|
|
||||||
#include "DNA_ID.h"
|
#include "DNA_ID.h"
|
||||||
|
|
||||||
|
#ifndef MAX_MTEX
|
||||||
|
#define MAX_MTEX 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct MTex;
|
||||||
|
struct Image;
|
||||||
|
|
||||||
typedef struct Brush {
|
typedef struct Brush {
|
||||||
ID id;
|
ID id;
|
||||||
|
|
||||||
@ -44,6 +51,9 @@ typedef struct Brush {
|
|||||||
float rgb[3]; /* color */
|
float rgb[3]; /* color */
|
||||||
float alpha; /* opacity */
|
float alpha; /* opacity */
|
||||||
|
|
||||||
|
short texact, pad;
|
||||||
|
struct MTex *mtex[10];
|
||||||
|
|
||||||
struct Clone {
|
struct Clone {
|
||||||
struct Image *image; /* image for clone tool */
|
struct Image *image; /* image for clone tool */
|
||||||
float offset[2]; /* offset of clone image from canvas */
|
float offset[2]; /* offset of clone image from canvas */
|
||||||
|
@ -44,8 +44,8 @@ struct Render;
|
|||||||
struct MTex;
|
struct MTex;
|
||||||
void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem, struct Render *re);
|
void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem, struct Render *re);
|
||||||
|
|
||||||
/* effect.c and editmesh_modes. */
|
/* effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
|
||||||
void externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta);
|
int externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta);
|
||||||
|
|
||||||
#endif /* RE_RENDER_EXT_H */
|
#endif /* RE_RENDER_EXT_H */
|
||||||
|
|
||||||
|
@ -2362,7 +2362,7 @@ void do_lamp_tex(LampRen *la, float *lavec, ShadeInput *shi, float *colf)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void externtex(MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta)
|
int externtex(MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta)
|
||||||
{
|
{
|
||||||
Tex *tex;
|
Tex *tex;
|
||||||
TexResult texr;
|
TexResult texr;
|
||||||
@ -2404,6 +2404,8 @@ void externtex(MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *
|
|||||||
*tg= texr.tg;
|
*tg= texr.tg;
|
||||||
*tb= texr.tb;
|
*tb= texr.tb;
|
||||||
*ta= texr.ta;
|
*ta= texr.ta;
|
||||||
|
|
||||||
|
return (rgb != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3889,6 +3889,23 @@ void do_fpaintbuts(unsigned short event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case B_BTEXBROWSE:
|
||||||
|
if(G.scene->toolsettings->imapaint.brush==0) return;
|
||||||
|
if(G.buts->menunr==-2) {
|
||||||
|
MTex *mtex= G.scene->toolsettings->imapaint.brush->mtex[0];
|
||||||
|
ID *id= (ID*)((mtex)? mtex->tex: NULL);
|
||||||
|
activate_databrowse(id, ID_TE, 0, B_BTEXBROWSE, &G.buts->menunr, do_global_buttons);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(G.buts->menunr < 0) break;
|
||||||
|
|
||||||
|
if(brush_texture_set_nr(G.scene->toolsettings->imapaint.brush, G.buts->menunr)) {
|
||||||
|
BIF_undo_push("Browse Brush Texture");
|
||||||
|
allqueue(REDRAWBUTSSHADING, 0);
|
||||||
|
allqueue(REDRAWBUTSEDIT, 0);
|
||||||
|
allqueue(REDRAWIMAGE, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_brush_types.h"
|
||||||
#include "DNA_curve_types.h"
|
#include "DNA_curve_types.h"
|
||||||
#include "DNA_image_types.h"
|
#include "DNA_image_types.h"
|
||||||
#include "DNA_lamp_types.h"
|
#include "DNA_lamp_types.h"
|
||||||
@ -1215,7 +1216,7 @@ static void texture_panel_colors(Tex *tex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *la, bNode *node)
|
static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *la, bNode *node, Brush *br)
|
||||||
{
|
{
|
||||||
MTex *mt=NULL;
|
MTex *mt=NULL;
|
||||||
uiBlock *block;
|
uiBlock *block;
|
||||||
@ -1236,6 +1237,7 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l
|
|||||||
if(ma) idfrom= &ma->id;
|
if(ma) idfrom= &ma->id;
|
||||||
else if(wrld) idfrom= &wrld->id;
|
else if(wrld) idfrom= &wrld->id;
|
||||||
else if(la) idfrom= &la->id;
|
else if(la) idfrom= &la->id;
|
||||||
|
else if(br) idfrom= &br->id;
|
||||||
else idfrom= NULL;
|
else idfrom= NULL;
|
||||||
|
|
||||||
uiBlockSetCol(block, TH_BUT_SETTING2);
|
uiBlockSetCol(block, TH_BUT_SETTING2);
|
||||||
@ -1248,6 +1250,9 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l
|
|||||||
else if(la) {
|
else if(la) {
|
||||||
std_libbuttons(block, 10, 180, 0, NULL, B_LTEXBROWSE, ID_TE, 0, id, idfrom, &(G.buts->texnr), B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME, B_KEEPDATA);
|
std_libbuttons(block, 10, 180, 0, NULL, B_LTEXBROWSE, ID_TE, 0, id, idfrom, &(G.buts->texnr), B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME, B_KEEPDATA);
|
||||||
}
|
}
|
||||||
|
else if(br) {
|
||||||
|
std_libbuttons(block, 10, 180, 0, NULL, B_BTEXBROWSE, ID_TE, 0, id, idfrom, &(G.buts->texnr), B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME, B_KEEPDATA);
|
||||||
|
}
|
||||||
else if(node) {
|
else if(node) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1264,6 +1269,7 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l
|
|||||||
if(ma) mt= ma->mtex[a];
|
if(ma) mt= ma->mtex[a];
|
||||||
else if(wrld) mt= wrld->mtex[a];
|
else if(wrld) mt= wrld->mtex[a];
|
||||||
else if(la) mt= la->mtex[a];
|
else if(la) mt= la->mtex[a];
|
||||||
|
else if(br) mt= br->mtex[a];
|
||||||
|
|
||||||
if(mt && mt->tex) splitIDname(mt->tex->id.name+2, str, &loos);
|
if(mt && mt->tex) splitIDname(mt->tex->id.name+2, str, &loos);
|
||||||
else strcpy(str, "");
|
else strcpy(str, "");
|
||||||
@ -1281,6 +1287,10 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l
|
|||||||
uiDefButS(block, ROW, B_TEXCHANNEL, str, 10,yco,140,19, &(la->texact), 0.0, (float)a, 0, 0, "");
|
uiDefButS(block, ROW, B_TEXCHANNEL, str, 10,yco,140,19, &(la->texact), 0.0, (float)a, 0, 0, "");
|
||||||
yco-= 20;
|
yco-= 20;
|
||||||
}
|
}
|
||||||
|
else if(br) {
|
||||||
|
uiDefButS(block, ROW, B_TEXCHANNEL, str, 10,yco,140,19, &(br->texact), 0.0, (float)a, 0, 0, "");
|
||||||
|
yco-= 20;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uiBlockEndAlign(block);
|
uiBlockEndAlign(block);
|
||||||
}
|
}
|
||||||
@ -1323,6 +1333,7 @@ static void texture_panel_preview(MTex *mtex, int preview)
|
|||||||
uiDefButC(block, ROW, B_TEXREDR_PRV, "Mat", 200,175,80,25, &G.buts->texfrom, 3.0, 0.0, 0, 0, "Displays the textures of the active material");
|
uiDefButC(block, ROW, B_TEXREDR_PRV, "Mat", 200,175,80,25, &G.buts->texfrom, 3.0, 0.0, 0, 0, "Displays the textures of the active material");
|
||||||
uiDefButC(block, ROW, B_TEXREDR_PRV, "World", 200,150,80,25, &G.buts->texfrom, 3.0, 1.0, 0, 0, "Displays the textures of the world block");
|
uiDefButC(block, ROW, B_TEXREDR_PRV, "World", 200,150,80,25, &G.buts->texfrom, 3.0, 1.0, 0, 0, "Displays the textures of the world block");
|
||||||
uiDefButC(block, ROW, B_TEXREDR_PRV, "Lamp", 200,125,80,25, &G.buts->texfrom, 3.0, 2.0, 0, 0, "Displays the textures of the selected lamp");
|
uiDefButC(block, ROW, B_TEXREDR_PRV, "Lamp", 200,125,80,25, &G.buts->texfrom, 3.0, 2.0, 0, 0, "Displays the textures of the selected lamp");
|
||||||
|
uiDefButC(block, ROW, B_TEXREDR_PRV, "Brush", 200,100,80,25, &G.buts->texfrom, 3.0, 3.0, 0, 0, "Displays the textures of the selected lamp");
|
||||||
uiBlockEndAlign(block);
|
uiBlockEndAlign(block);
|
||||||
|
|
||||||
if(mtex && mtex->tex)
|
if(mtex && mtex->tex)
|
||||||
@ -3399,6 +3410,7 @@ void world_panels()
|
|||||||
void texture_panels()
|
void texture_panels()
|
||||||
{
|
{
|
||||||
Material *ma=NULL;
|
Material *ma=NULL;
|
||||||
|
Brush *br=NULL;
|
||||||
Lamp *la=NULL;
|
Lamp *la=NULL;
|
||||||
World *wrld=NULL;
|
World *wrld=NULL;
|
||||||
bNode *node=NULL;
|
bNode *node=NULL;
|
||||||
@ -3431,13 +3443,17 @@ void texture_panels()
|
|||||||
mtex= la->mtex[ la->texact ];
|
mtex= la->mtex[ la->texact ];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(G.buts->texfrom==3) {
|
||||||
|
br= G.scene->toolsettings->imapaint.brush;
|
||||||
|
if(br) mtex= br->mtex[br->texact];
|
||||||
|
}
|
||||||
|
|
||||||
texture_panel_preview(mtex, ma || wrld || la || node); // for 'from' buttons
|
texture_panel_preview(mtex, ma || wrld || la || br || node); // for 'from' buttons
|
||||||
|
|
||||||
if(ma || wrld || la || node) {
|
if(ma || wrld || la || br || node) {
|
||||||
Tex *tex= NULL;
|
Tex *tex= NULL;
|
||||||
|
|
||||||
texture_panel_texture(mtex, ma, wrld, la, node);
|
texture_panel_texture(mtex, ma, wrld, la, node, br);
|
||||||
|
|
||||||
if(mtex) tex= mtex->tex;
|
if(mtex) tex= mtex->tex;
|
||||||
else if(node) tex= (Tex *)node->id;
|
else if(node) tex= (Tex *)node->id;
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
#include "DNA_screen_types.h"
|
#include "DNA_screen_types.h"
|
||||||
#include "DNA_space_types.h"
|
#include "DNA_space_types.h"
|
||||||
|
#include "DNA_texture_types.h"
|
||||||
#include "DNA_userdef_types.h"
|
#include "DNA_userdef_types.h"
|
||||||
|
|
||||||
#include "BKE_brush.h"
|
#include "BKE_brush.h"
|
||||||
@ -944,6 +945,36 @@ void do_imagebuts(unsigned short event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case B_SIMABTEXBROWSE:
|
||||||
|
if(settings->imapaint.brush) {
|
||||||
|
Brush *brush= settings->imapaint.brush;
|
||||||
|
|
||||||
|
if(G.sima->menunr==-2) {
|
||||||
|
MTex *mtex= brush->mtex[brush->texact];
|
||||||
|
ID *id= (ID*)((mtex)? mtex->tex: NULL);
|
||||||
|
activate_databrowse(id, ID_TE, 0, B_SIMABTEXBROWSE, &G.sima->menunr, do_global_buttons);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(G.sima->menunr < 0) break;
|
||||||
|
|
||||||
|
if(brush_texture_set_nr(brush, G.sima->menunr)) {
|
||||||
|
BIF_undo_push("Browse Brush Texture");
|
||||||
|
allqueue(REDRAWBUTSSHADING, 0);
|
||||||
|
allqueue(REDRAWBUTSEDIT, 0);
|
||||||
|
allqueue(REDRAWIMAGE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case B_SIMABTEXDELETE:
|
||||||
|
if(settings->imapaint.brush) {
|
||||||
|
if (brush_texture_delete(settings->imapaint.brush)) {
|
||||||
|
BIF_undo_push("Unlink Brush Texture");
|
||||||
|
allqueue(REDRAWBUTSSHADING, 0);
|
||||||
|
allqueue(REDRAWBUTSEDIT, 0);
|
||||||
|
allqueue(REDRAWIMAGE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1062,6 +1093,12 @@ static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PROPERTIES
|
|||||||
uiDefButF(block, NUMSLI, B_SIMABRUSHCHANGE, "B ",xco+5,yco,butw,19, &brush->clone.alpha , 0.0, 1.0, 0, 0, "Opacity of clone image display");
|
uiDefButF(block, NUMSLI, B_SIMABRUSHCHANGE, "B ",xco+5,yco,butw,19, &brush->clone.alpha , 0.0, 1.0, 0, 0, "Opacity of clone image display");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
uiBlockSetCol(block, TH_BUT_SETTING2);
|
||||||
|
id= (brush->mtex[0])? (ID*)brush->mtex[0]->tex: NULL;
|
||||||
|
xco= std_libbuttons(block, 0, yco, 0, NULL, B_SIMABTEXBROWSE, ID_TE, 0, id, NULL, &(G.sima->menunr), 0, 0, B_SIMABTEXDELETE, 0, 0);
|
||||||
|
uiBlockSetCol(block, TH_AUTO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
#include "DNA_ID.h"
|
#include "DNA_ID.h"
|
||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
|
#include "DNA_brush_types.h"
|
||||||
#include "DNA_lamp_types.h"
|
#include "DNA_lamp_types.h"
|
||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
#include "DNA_node_types.h"
|
#include "DNA_node_types.h"
|
||||||
@ -321,6 +322,13 @@ void buttons_active_id(ID **id, ID **idfrom)
|
|||||||
if(mtex) *id= (ID *)mtex->tex;
|
if(mtex) *id= (ID *)mtex->tex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(G.buts->texfrom==3) {
|
||||||
|
Brush *brush= G.scene->toolsettings->imapaint.brush;
|
||||||
|
if (brush) {
|
||||||
|
mtex= brush->mtex[brush->texact];
|
||||||
|
if(mtex) *id= (ID*)mtex->tex;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(G.buts->mainb==CONTEXT_OBJECT || G.buts->mainb==CONTEXT_LOGIC) {
|
else if(G.buts->mainb==CONTEXT_OBJECT || G.buts->mainb==CONTEXT_LOGIC) {
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "DNA_ID.h"
|
#include "DNA_ID.h"
|
||||||
#include "DNA_action_types.h"
|
#include "DNA_action_types.h"
|
||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
|
#include "DNA_brush_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
#include "DNA_curve_types.h"
|
#include "DNA_curve_types.h"
|
||||||
#include "DNA_group_types.h"
|
#include "DNA_group_types.h"
|
||||||
@ -87,10 +88,11 @@
|
|||||||
|
|
||||||
#include "BKE_utildefines.h"
|
#include "BKE_utildefines.h"
|
||||||
|
|
||||||
#include "BKE_constraint.h"
|
|
||||||
#include "BKE_action.h"
|
#include "BKE_action.h"
|
||||||
#include "BKE_armature.h"
|
#include "BKE_armature.h"
|
||||||
#include "BKE_blender.h"
|
#include "BKE_blender.h"
|
||||||
|
#include "BKE_brush.h"
|
||||||
|
#include "BKE_constraint.h"
|
||||||
#include "BKE_curve.h"
|
#include "BKE_curve.h"
|
||||||
#include "BKE_depsgraph.h"
|
#include "BKE_depsgraph.h"
|
||||||
#include "BKE_exotic.h"
|
#include "BKE_exotic.h"
|
||||||
@ -550,6 +552,7 @@ void do_global_buttons(unsigned short event)
|
|||||||
bAction *act;
|
bAction *act;
|
||||||
ID *id, *idtest, *from=NULL;
|
ID *id, *idtest, *from=NULL;
|
||||||
ScrArea *sa;
|
ScrArea *sa;
|
||||||
|
Brush *br;
|
||||||
int nr= 1;
|
int nr= 1;
|
||||||
char buf[FILE_MAXDIR+FILE_MAXFILE];
|
char buf[FILE_MAXDIR+FILE_MAXFILE];
|
||||||
|
|
||||||
@ -767,7 +770,7 @@ void do_global_buttons(unsigned short event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { /* from lamp */
|
else if(G.buts->texfrom==2) { /* from lamp */
|
||||||
la= ob->data;
|
la= ob->data;
|
||||||
if(la && ob->type==OB_LAMP) { /* to be sure */
|
if(la && ob->type==OB_LAMP) { /* to be sure */
|
||||||
mtex= la->mtex[ la->texact ];
|
mtex= la->mtex[ la->texact ];
|
||||||
@ -781,6 +784,21 @@ void do_global_buttons(unsigned short event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else { /* from brush */
|
||||||
|
br= G.scene->toolsettings->imapaint.brush;
|
||||||
|
if(br) {
|
||||||
|
mtex= br->mtex[ br->texact ];
|
||||||
|
if(mtex) {
|
||||||
|
if(mtex->tex) mtex->tex->id.us--;
|
||||||
|
MEM_freeN(mtex);
|
||||||
|
br->mtex[ br->texact ]= NULL;
|
||||||
|
allqueue(REDRAWBUTSSHADING, 0);
|
||||||
|
allqueue(REDRAWIMAGE, 0);
|
||||||
|
allqueue(REDRAWIPO, 0);
|
||||||
|
/*BIF_preview_changed(ID_BR);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIF_undo_push("Unlink Texture");
|
BIF_undo_push("Unlink Texture");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1244,6 +1262,7 @@ void do_global_buttons(unsigned short event)
|
|||||||
BIF_undo_push("Auto name");
|
BIF_undo_push("Auto name");
|
||||||
allqueue(REDRAWBUTSSHADING, 0);
|
allqueue(REDRAWBUTSSHADING, 0);
|
||||||
allqueue(REDRAWOOPS, 0);
|
allqueue(REDRAWOOPS, 0);
|
||||||
|
allqueue(REDRAWIMAGE, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1501,6 +1520,7 @@ void do_global_buttons2(short event)
|
|||||||
World *wrld;
|
World *wrld;
|
||||||
ID *idfrom;
|
ID *idfrom;
|
||||||
bAction *act;
|
bAction *act;
|
||||||
|
Brush *br;
|
||||||
|
|
||||||
/* general: Single User is allowed when from==LOCAL
|
/* general: Single User is allowed when from==LOCAL
|
||||||
* Make Local is allowed when (from==LOCAL && id==LIB)
|
* Make Local is allowed when (from==LOCAL && id==LIB)
|
||||||
@ -1772,6 +1792,20 @@ void do_global_buttons2(short event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(G.buts->texfrom==3) { /* from brush */
|
||||||
|
br= G.scene->toolsettings->imapaint.brush;
|
||||||
|
if(br==0) return;
|
||||||
|
if(br->id.lib==0) {
|
||||||
|
mtex= br->mtex[ br->texact ];
|
||||||
|
if(mtex->tex && mtex->tex->id.us>1) {
|
||||||
|
if(okee("Single user")) {
|
||||||
|
mtex->tex->id.us--;
|
||||||
|
mtex->tex= copy_texture(mtex->tex);
|
||||||
|
allqueue(REDRAWIMAGE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case B_TEXLOCAL:
|
case B_TEXLOCAL:
|
||||||
if(G.buts->texfrom==0) { /* from mat */
|
if(G.buts->texfrom==0) { /* from mat */
|
||||||
@ -1810,6 +1844,19 @@ void do_global_buttons2(short event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(G.buts->texfrom==3) { /* from brush */
|
||||||
|
br= G.scene->toolsettings->imapaint.brush;
|
||||||
|
if(br==0) return;
|
||||||
|
if(br->id.lib==0) {
|
||||||
|
mtex= br->mtex[ br->texact ];
|
||||||
|
if(mtex->tex && mtex->tex->id.lib) {
|
||||||
|
if(okee("Make local")) {
|
||||||
|
make_local_texture(mtex->tex);
|
||||||
|
allqueue(REDRAWIMAGE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_IPOALONE:
|
case B_IPOALONE:
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user