Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2006-07-27 02:29:23 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2006-07-27 02:29:23 +0400
commit4ee3515bf1751f7f89168f3c5c1fd907ad138ffd (patch)
treeacc86233c0d49317c74a239a6280dfe9e0a266cc
parent6a087fcb8b817d53f9689c300dc4002de8150a19 (diff)
Brush Datablock:
- Added a new Brush datablock, only used by image paint, but intended to be used in texture paint, vertex paint, weight paint and sculpt mode also. - Being a datablock, these brushes can be saved, appended and linked. They have a fake user by default, to make sure they are saved even if not selected. Image Painting: - Replaced the img module with C code in imagepaint.c - Airbrush is no longer a separate tool, but rather an option that can be used for soften, smear and clone also. - Blend modes mix, add, subtract, multiply, darken and lighten have been added, code taken directly from vertex paint. Note to project files maintainers: - The img module was removed from SCons and Makefiles, and this should be done in other build systems also. I'll wait to remove the module from cvs, to not break compilation.
-rw-r--r--source/Makefile1
-rw-r--r--source/blender/Makefile2
-rw-r--r--source/blender/blenkernel/BKE_brush.h57
-rw-r--r--source/blender/blenkernel/BKE_main.h1
-rw-r--r--source/blender/blenkernel/intern/brush.c317
-rw-r--r--source/blender/blenkernel/intern/library.c21
-rw-r--r--source/blender/blenloader/intern/readblenentry.c1
-rw-r--r--source/blender/blenloader/intern/readfile.c39
-rw-r--r--source/blender/blenloader/intern/writefile.c11
-rw-r--r--source/blender/include/BDR_editface.h1
-rw-r--r--source/blender/include/BDR_imagepaint.h40
-rw-r--r--source/blender/include/blendef.h3
-rw-r--r--source/blender/makesdna/DNA_ID.h1
-rw-r--r--source/blender/makesdna/DNA_brush_types.h70
-rw-r--r--source/blender/makesdna/DNA_scene_types.h13
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/src/Makefile1
-rw-r--r--source/blender/src/SConscript2
-rw-r--r--source/blender/src/drawimage.c200
-rw-r--r--source/blender/src/editface.c184
-rw-r--r--source/blender/src/filesel.c3
-rw-r--r--source/blender/src/header_image.c5
-rw-r--r--source/blender/src/headerbuttons.c4
-rw-r--r--source/blender/src/imagepaint.c820
-rw-r--r--source/blender/src/space.c3
-rw-r--r--source/nan_definitions.mk1
26 files changed, 1409 insertions, 394 deletions
diff --git a/source/Makefile b/source/Makefile
index f0273954440..ec78763506a 100644
--- a/source/Makefile
+++ b/source/Makefile
@@ -83,7 +83,6 @@ PYPLAYERLIB ?= $(PYLIB)
GRPLIB += $(NAN_SOUNDSYSTEM)/lib/$(DEBUG_DIR)libSoundSystem.a
GRPLIB += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
GRPLIB += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
- GRPLIB += $(OCGDIR)/blender/img/$(DEBUG_DIR)libimg.a
GRPLIB += $(OCGDIR)/blender/render/$(DEBUG_DIR)librender.a
GRPLIB += $(OCGDIR)/blender/radiosity/$(DEBUG_DIR)libradiosity.a
GRPLIB += $(NAN_OPENNL)/lib/$(DEBUG_DIR)libopennl.a
diff --git a/source/blender/Makefile b/source/blender/Makefile
index ebae59ef0de..5888186fcfc 100644
--- a/source/blender/Makefile
+++ b/source/blender/Makefile
@@ -34,7 +34,7 @@
include nan_definitions.mk
DIRS = blenloader readblenfile
-DIRS += avi imbuf img render radiosity blenlib blenkernel blenpluginapi
+DIRS += avi imbuf render radiosity blenlib blenkernel blenpluginapi
DIRS += makesdna src yafray
DIRS += python
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
new file mode 100644
index 00000000000..89c6a3adf2a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -0,0 +1,57 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * General operations for brushes.
+ */
+
+#ifndef BKE_BRUSH_H
+#define BKE_BRUSH_H
+
+struct ID;
+struct Brush;
+
+struct Brush *add_brush(char *name);
+struct Brush *copy_brush(struct Brush *brush);
+void make_local_brush(struct Brush *brush);
+void free_brush(struct Brush *brush);
+
+/* implementation of blending modes for use by different paint modes */
+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_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);
+
+#endif
+
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 1512ea28d4a..d385e357365 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -75,6 +75,7 @@ typedef struct Main {
ListBase armature;
ListBase action;
ListBase nodetree;
+ ListBase brush;
} Main;
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
new file mode 100644
index 00000000000..ca9d1154024
--- /dev/null
+++ b/source/blender/blenkernel/intern/brush.c
@@ -0,0 +1,317 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_image_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_brush.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+
+Brush *add_brush(char *name)
+{
+ Brush *brush;
+
+ brush= alloc_libblock(&G.main->brush, ID_BR, name);
+
+ brush->rgb[0]= 1.0f;
+ brush->rgb[1]= 1.0f;
+ brush->rgb[2]= 1.0f;
+ brush->alpha= 0.2f;
+ brush->size= 25;
+ brush->timing= 100.0f;
+ brush->innerradius= 0.5f;
+ brush->clone.alpha= 0.5;
+
+ /* enable fake user by default */
+ brush_toggle_fake_user(brush);
+
+ return brush;
+}
+
+Brush *copy_brush(Brush *brush)
+{
+ Brush *brushn;
+
+ brushn= copy_libblock(brush);
+
+ /* enable fake user by default */
+ if (!(brushn->id.flag & LIB_FAKEUSER))
+ brush_toggle_fake_user(brushn);
+
+ return brushn;
+}
+
+/* not brush itself */
+void free_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 local users: set flag
+ * - mixed: make copy
+ */
+
+ Brush *brushn;
+ Scene *scene;
+ int local= 0, lib= 0;
+
+ if(brush->id.lib==0) return;
+
+ if(brush->clone.image) {
+ /* special case: ima always local immediately */
+ brush->clone.image->id.lib= 0;
+ brush->clone.image->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)brush->clone.image, 0);
+ }
+
+ for(scene= G.main->scene.first; scene; scene=scene->id.next)
+ if(scene->toolsettings->imapaint.brush==brush) {
+ if(scene->id.lib) lib= 1;
+ else local= 1;
+ }
+
+ if(local && lib==0) {
+ brush->id.lib= 0;
+ brush->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)brush, 0);
+
+ /* enable fake user by default */
+ if (!(brush->id.flag & LIB_FAKEUSER))
+ brush_toggle_fake_user(brush);
+ }
+ else if(local && lib) {
+ brushn= copy_brush(brush);
+ brushn->id.us= 1; /* only keep fake user */
+ brushn->id.flag |= LIB_FAKEUSER;
+
+ for(scene= G.main->scene.first; scene; scene=scene->id.next)
+ if(scene->toolsettings->imapaint.brush==brush)
+ if(scene->id.lib==0) {
+ scene->toolsettings->imapaint.brush= brushn;
+ brushn->id.us++;
+ brush->id.us--;
+ }
+ }
+}
+
+static void brush_blend_mix(char *cp, char *cp1, char *cp2, int fac)
+{
+ /* 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)
+{
+ ID *idtest, *id;
+
+ id= (ID*)(*current_brush);
+ idtest= (ID*)BLI_findlink(&G.main->brush, nr-1);
+
+ if(idtest==0) { /* new brush */
+ if(id) idtest= (ID *)copy_brush((Brush *)id);
+ else idtest= (ID *)add_brush("Brush");
+ idtest->us--;
+ }
+ if(idtest!=id) {
+ brush_delete(current_brush);
+ *current_brush= (Brush *)idtest;
+ id_us_plus(idtest);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int brush_delete(Brush **current_brush)
+{
+ if (*current_brush) {
+ (*current_brush)->id.us--;
+ *current_brush= NULL;
+ return 1;
+ }
+
+ return 0;
+}
+
+void brush_toggle_fake_user(Brush *brush)
+{
+ ID *id= (ID*)brush;
+ if(id) {
+ if(id->flag & LIB_FAKEUSER) {
+ id->flag -= LIB_FAKEUSER;
+ id->us--;
+ } else {
+ id->flag |= LIB_FAKEUSER;
+ id_us_plus(id);
+ }
+ }
+}
+
+int brush_clone_image_set_nr(Brush *brush, int nr)
+{
+ if(brush && nr > 0) {
+ Image *ima= (Image*)BLI_findlink(&G.main->image, nr-1);
+
+ if(ima) {
+ brush_clone_image_delete(brush);
+ brush->clone.image= ima;
+ id_us_plus(&ima->id);
+ brush->clone.offset[0]= brush->clone.offset[1]= 0.0f;
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int brush_clone_image_delete(Brush *brush)
+{
+ if (brush && brush->clone.image) {
+ brush->clone.image->id.us--;
+ brush->clone.image= NULL;
+ return 1;
+ }
+
+ return 0;
+}
+
+void brush_check_exists(Brush **brush)
+{
+ if(*brush==NULL)
+ brush_set_nr(brush, 1);
+}
+
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 6992f2b2918..5628e4bc491 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -77,6 +77,7 @@
#include "DNA_node_types.h"
#include "DNA_nla_types.h"
#include "DNA_effect_types.h"
+#include "DNA_brush_types.h"
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
@@ -108,6 +109,7 @@
#include "BKE_action.h"
#include "BKE_node.h"
#include "BKE_effect.h"
+#include "BKE_brush.h"
#include "BPI_script.h"
@@ -193,6 +195,8 @@ ListBase *wich_libbase(Main *mainlib, short type)
return &(mainlib->action);
case ID_NT:
return &(mainlib->nodetree);
+ case ID_BR:
+ return &(mainlib->brush);
}
return 0;
}
@@ -233,12 +237,13 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[21]= &(main->sound);
lb[22]= &(main->group);
lb[23]= &(main->nodetree);
+ lb[24]= &(main->brush);
- lb[24]= samples;
- lb[25]= &(main->script);
- lb[26]= NULL;
+ lb[25]= samples;
+ lb[26]= &(main->script);
+ lb[27]= NULL;
- return 26;
+ return 27;
}
/* *********** ALLOC AND FREE *****************
@@ -332,7 +337,10 @@ static ID *alloc_libblock_notest(short type)
id = MEM_callocN(sizeof(bAction), "action");
break;
case ID_NT:
- id = MEM_callocN(sizeof(bNodeTree), "action");
+ id = MEM_callocN(sizeof(bNodeTree), "nodetree");
+ break;
+ case ID_BR:
+ id = MEM_callocN(sizeof(Brush), "brush");
break;
}
return id;
@@ -477,6 +485,9 @@ void free_libblock(ListBase *lb, void *idv)
case ID_NT:
ntreeFreeTree((bNodeTree *)id);
break;
+ case ID_BR:
+ free_brush((Brush *)id);
+ break;
}
BLI_remlink(lb, id);
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index 2da43013318..a16bd5a3972 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -81,6 +81,7 @@ typedef struct {
static IDType idtypes[]= {
{ ID_AC, "Action", IDTYPE_FLAGS_ISLINKABLE},
{ ID_AR, "Armature", IDTYPE_FLAGS_ISLINKABLE},
+ { ID_BR, "Brush", IDTYPE_FLAGS_ISLINKABLE},
{ ID_CA, "Camera", IDTYPE_FLAGS_ISLINKABLE},
{ ID_CU, "Curve", IDTYPE_FLAGS_ISLINKABLE},
{ ID_GR, "Group", IDTYPE_FLAGS_ISLINKABLE},
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 51dfc927251..17bf34f6f45 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -58,6 +58,7 @@
#include "DNA_armature_types.h"
#include "DNA_ID.h"
#include "DNA_actuator_types.h"
+#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_color_types.h"
#include "DNA_controller_types.h"
@@ -1182,6 +1183,28 @@ static void test_pointer_array(FileData *fd, void **mat)
}
}
+/* ************ READ BRUSH *************** */
+
+/* library brush linking after fileread */
+static void lib_link_brush(FileData *fd, Main *main)
+{
+ Brush *brush;
+
+ /* only link ID pointers */
+ for(brush= main->brush.first; brush; brush= brush->id.next) {
+ if(brush->id.flag & LIB_NEEDLINK) {
+ brush->id.flag -= LIB_NEEDLINK;
+ /* nothing to do yet - until brush gets textures */
+ }
+ }
+}
+
+/* brush itself has been read! */
+static void direct_link_brush(FileData *fd, Brush *brush)
+{
+ /* nothing to do yet - until brush gets textures */
+}
+
/* ************ READ CurveMapping *************** */
/* cuma itself has been read! */
@@ -2639,6 +2662,8 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->world= newlibadr_us(fd, sce->id.lib, sce->world);
sce->set= newlibadr(fd, sce->id.lib, sce->set);
sce->ima= newlibadr_us(fd, sce->id.lib, sce->ima);
+ sce->toolsettings->imapaint.brush=
+ newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.brush);
base= sce->base.first;
while(base) {
@@ -3471,6 +3496,8 @@ static char *dataname(short id_code)
case ID_TXT : return "Data from TXT";
case ID_SO: return "Data from SO";
case ID_SAMPLE: return "Data from SAMPLE";
+ case ID_NT: return "Data from NT";
+ case ID_BR: return "Data from BR";
}
return "Data from Lib Block";
@@ -3604,6 +3631,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
case ID_NT:
direct_link_nodetree(fd, (bNodeTree*)id);
break;
+ case ID_BR:
+ direct_link_brush(fd, (Brush*)id);
+ break;
}
oldnewmap_free_unused(fd->datamap);
@@ -5555,6 +5585,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_vfont(fd, main);
lib_link_screen_sequence_ipos(main);
lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
+ lib_link_brush(fd, main);
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
@@ -5769,6 +5800,11 @@ static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
expand_doit(fd, mainvar, tex->ipo);
}
+static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
+{
+ /* nothing to do yet - until brush gets texture */
+}
+
static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
{
bNode *node;
@@ -6232,6 +6268,9 @@ static void expand_main(FileData *fd, Main *mainvar)
case ID_NT:
expand_nodetree(fd, mainvar, (bNodeTree *)id);
break;
+ case ID_BR:
+ expand_brush(fd, mainvar, (Brush *)id);
+ break;
case ID_IP:
expand_ipo(fd, mainvar, (Ipo *)id);
break;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index ca7f75526dc..e3a67da94c3 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -105,6 +105,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
#include "DNA_armature_types.h"
#include "DNA_action_types.h"
#include "DNA_actuator_types.h"
+#include "DNA_brush_types.h"
#include "DNA_controller_types.h"
#include "DNA_curve_types.h"
#include "DNA_constraint_types.h"
@@ -1592,6 +1593,15 @@ static void write_nodetrees(WriteData *wd, ListBase *idbase)
}
}
+static void write_brushes(WriteData *wd, ListBase *idbase)
+{
+ Brush *brush;
+
+ for(brush=idbase->first; brush; brush= brush->id.next)
+ if (brush->id.us>0 || wd->current)
+ writestruct(wd, ID_BR, "Brush", 1, brush);
+}
+
static void write_global(WriteData *wd)
{
FileGlobal fg;
@@ -1650,6 +1660,7 @@ static int write_file_handle(int handle, MemFile *compare, MemFile *current, int
write_textures (wd, &G.main->tex);
write_meshs (wd, &G.main->mesh);
write_nodetrees(wd, &G.main->nodetree);
+ write_brushes (wd, &G.main->brush);
write_libraries(wd, G.main->next);
write_global(wd);
diff --git a/source/blender/include/BDR_editface.h b/source/blender/include/BDR_editface.h
index abce31796db..d46f05667ba 100644
--- a/source/blender/include/BDR_editface.h
+++ b/source/blender/include/BDR_editface.h
@@ -54,7 +54,6 @@ void face_borderselect(void);
void uv_autocalc_tface(void);
void set_faceselect(void);
void set_texturepaint(void);
-void face_draw(void);
void get_same_uv(void);
void seam_mark_clear_tface(short mode);
diff --git a/source/blender/include/BDR_imagepaint.h b/source/blender/include/BDR_imagepaint.h
index 5fd725ba934..8824c63071d 100644
--- a/source/blender/include/BDR_imagepaint.h
+++ b/source/blender/include/BDR_imagepaint.h
@@ -33,47 +33,11 @@
#ifndef BDR_IMAGEPAINT_H
#define BDR_IMAGEPAINT_H
-/* ImagePaint.current */
-#define IMAGEPAINT_BRUSH 0
-#define IMAGEPAINT_AIRBRUSH 1
-#define IMAGEPAINT_SOFTEN 2
-#define IMAGEPAINT_AUX1 3
-#define IMAGEPAINT_AUX2 4
-#define IMAGEPAINT_SMEAR 5
-#define IMAGEPAINT_CLONE 6
-#define IMAGEPAINT_TOOL_SIZE 7
-
-/* ImagePaint.flag */
-#define IMAGEPAINT_DRAW_TOOL 1
-#define IMAGEPAINT_DRAW_TOOL_DRAWING 2
-#define IMAGEPAINT_DRAWING 4
-#define IMAGEPAINT_TORUS 8
-#define IMAGEPAINT_TIMED 16
-
-typedef struct ImagePaintTool {
- float rgba[4];
- int size;
- float innerradius;
- float timing;
-} ImagePaintTool;
-
-typedef struct ImagePaint {
- struct Clone {
- Image *image;
- float offset[2];
- float alpha;
- } clone;
-
- ImagePaintTool tool[IMAGEPAINT_TOOL_SIZE];
-
- short flag, current;
-} ImagePaint;
-
-extern struct ImagePaint Gip;
-
void imagepaint_redraw_tool(void);
void imagepaint_paint(short mousebutton);
void imagepaint_pick(short mousebutton);
+void texturepaint_paint();
+
#endif /* BDR_IMAGEPAINT_H */
diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h
index 3dd0dda31d3..49873674917 100644
--- a/source/blender/include/blendef.h
+++ b/source/blender/include/blendef.h
@@ -317,6 +317,9 @@
#define B_SIMA_USE_ALPHA 371
#define B_SIMA_SHOW_ALPHA 372
#define B_SIMA_SHOW_ZBUF 373
+#define B_BRUSHBROWSE 374
+#define B_BRUSHDELETE 375
+#define B_BRUSHLOCAL 376
/* BUTS: 400 */
#define B_BUTSHOME 401
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 7e71da6df76..f9a824eec27 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -129,6 +129,7 @@ typedef struct Library {
#define ID_SCRIPT MAKE_ID2('P', 'Y')
#define ID_FLUIDSIM MAKE_ID2('F', 'S')
#define ID_NT MAKE_ID2('N', 'T')
+#define ID_BR MAKE_ID2('B', 'R')
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
#define ID_SEQ MAKE_ID2('S', 'Q')
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
new file mode 100644
index 00000000000..ff578494339
--- /dev/null
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -0,0 +1,70 @@
+/**
+ * $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 LICENSE BLOCK *****
+ */
+
+#ifndef DNA_BRUSH_TYPES_H
+#define DNA_BRUSH_TYPES_H
+
+#include "DNA_ID.h"
+
+typedef struct Brush {
+ ID id;
+
+ short flag, blend;
+ int size;
+ float innerradius;
+ float timing;
+
+ float rgb[3]; /* color */
+ float alpha; /* opacity */
+
+ struct Clone {
+ struct Image *image; /* image for clone tool */
+ float offset[2]; /* offset of clone image from canvas */
+ float alpha; /* transparency for drawing of clone image */
+ } clone;
+} Brush;
+
+/* Brush.flag */
+#define BRUSH_AIRBRUSH 1
+
+/* Brush.blend */
+#define BRUSH_BLEND_MIX 0
+#define BRUSH_BLEND_ADD 1
+#define BRUSH_BLEND_SUB 2
+#define BRUSH_BLEND_MUL 3
+#define BRUSH_BLEND_LIGHTEN 4
+#define BRUSH_BLEND_DARKEN 5
+
+#define PAINT_TOOL_DRAW 0
+#define PAINT_TOOL_SOFTEN 1
+#define PAINT_TOOL_SMEAR 2
+#define PAINT_TOOL_CLONE 3
+
+#endif
+
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 33edf65454e..fe2b0cfa015 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -344,6 +344,12 @@ typedef struct ToolSettings {
/* Select Group Threshold */
float select_thresh;
+ /* Image Paint */
+ struct ImagePaintSettings {
+ struct Brush *brush;
+ short flag, tool;
+ int pad3;
+ } imapaint;
} ToolSettings;
typedef struct Scene {
@@ -537,6 +543,13 @@ typedef struct Scene {
#define FFMPEG_MULTIPLEX_AUDIO 1
#define FFMPEG_AUTOSPLIT_OUTPUT 2
+/* toolsettings->imagepaint_flag */
+#define IMAGEPAINT_TORUS 1
+#define IMAGEPAINT_DRAWING 2
+#define IMAGEPAINT_TIMED 4
+#define IMAGEPAINT_DRAW_TOOL 8
+#define IMAGEPAINT_DRAW_TOOL_DRAWING 16
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 87174abab38..e7abcb1508e 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -125,6 +125,7 @@ char *includefiles[] = {
"DNA_nla_types.h",
"DNA_node_types.h",
"DNA_color_types.h",
+ "DNA_brush_types.h",
// if you add files here, please add them at the end
// of makesdna.c (this file) as well
@@ -1133,4 +1134,5 @@ int main(int argc, char ** argv)
#include "DNA_nla_types.h"
#include "DNA_node_types.h"
#include "DNA_color_types.h"
+#include "DNA_brush_types.h"
/* end of list */
diff --git a/source/blender/src/Makefile b/source/blender/src/Makefile
index dc7acc3d0d2..3bfb17dc586 100644
--- a/source/blender/src/Makefile
+++ b/source/blender/src/Makefile
@@ -69,7 +69,6 @@ CPPFLAGS += -I../blenlib
CPPFLAGS += -I../python
CPPFLAGS += -I../makesdna
CPPFLAGS += -I../imbuf
-CPPFLAGS += -I../img
CPPFLAGS += -I../blenloader
CPPFLAGS += -I..
CPPFLAGS += -I../../kernel/gen_system
diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript
index 8c3de925450..fdd920e2713 100644
--- a/source/blender/src/SConscript
+++ b/source/blender/src/SConscript
@@ -11,7 +11,7 @@ incs += ' ../include #/intern/bmfont ../imbuf ../render/extern/include'
incs += ' #/intern/bsp/extern ../radiosity/extern/include'
incs += ' #/intern/decimation/extern ../blenloader ../python'
incs += ' ../../kernel/gen_system #/intern/SoundSystem ../readstreamglue'
-incs += ' ../img ../quicktime #/intern/elbeem/extern'
+incs += ' ../quicktime #/intern/elbeem/extern'
incs += ' #/intern/ghost #/intern/opennl/extern'
incs += ' ' + env['BF_PYTHON_INC']
diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c
index 5486c093bcf..94d7ddd0b23 100644
--- a/source/blender/src/drawimage.c
+++ b/source/blender/src/drawimage.c
@@ -50,6 +50,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_color_types.h"
#include "DNA_image_types.h"
@@ -62,6 +63,7 @@
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
+#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
@@ -92,9 +94,11 @@
#include "BIF_renderwin.h"
#include "BIF_space.h"
#include "BIF_screen.h"
+#include "BIF_toolbox.h"
#include "BIF_transform.h"
#include "BSE_drawipo.h"
+#include "BSE_filesel.h"
#include "BSE_headerbuttons.h"
#include "BSE_trans_types.h"
#include "BSE_view.h"
@@ -112,28 +116,30 @@
static unsigned char *alloc_alpha_clone_image(int *width, int *height)
{
+ Brush *brush = G.scene->toolsettings->imapaint.brush;
+ Image *image;
unsigned int size, alpha;
unsigned char *rect, *cp;
- if(!Gip.clone.image)
+ if(!brush || !brush->clone.image)
return NULL;
+
+ image= brush->clone.image;
+ if(!image->ibuf)
+ load_image(image, IB_rect, G.sce, G.scene->r.cfra);
- if(!Gip.clone.image->ibuf)
- load_image(Gip.clone.image, IB_rect, G.sce, G.scene->r.cfra);
-
- if(!Gip.clone.image->ibuf || !Gip.clone.image->ibuf->rect)
+ if(!image->ibuf || !image->ibuf->rect)
return NULL;
- rect= MEM_dupallocN(Gip.clone.image->ibuf->rect);
-
+ rect= MEM_dupallocN(image->ibuf->rect);
if(!rect)
return NULL;
- *width= Gip.clone.image->ibuf->x;
- *height= Gip.clone.image->ibuf->y;
+ *width= image->ibuf->x;
+ *height= image->ibuf->y;
size= (*width)*(*height);
- alpha= (unsigned char)255*Gip.clone.alpha;
+ alpha= (unsigned char)255*brush->clone.alpha;
cp= rect;
while(size-- > 0) {
@@ -144,18 +150,6 @@ static unsigned char *alloc_alpha_clone_image(int *width, int *height)
return rect;
}
-static void setcloneimage()
-{
- if(G.sima->menunr > 0) {
- Image *ima= (Image*)BLI_findlink(&G.main->image, G.sima->menunr-1);
-
- if(ima) {
- Gip.clone.image= ima;
- Gip.clone.offset[0]= Gip.clone.offset[0]= 0.0;
- }
- }
-}
-
static int image_preview_active(ScrArea *sa, float *xim, float *yim)
{
SpaceImage *sima= sa->spacedata.first;
@@ -692,27 +686,30 @@ static void draw_image_view_icon(void)
static void draw_image_view_tool(void)
{
- ImagePaintTool *tool = &Gip.tool[Gip.current];
+ ToolSettings *settings= G.scene->toolsettings;
+ Brush *brush= settings->imapaint.brush;
short mval[2];
float radius;
int draw= 0;
- if(Gip.flag & IMAGEPAINT_DRAWING) {
- if(Gip.flag & IMAGEPAINT_DRAW_TOOL_DRAWING)
+ if(brush) {
+ if(settings->imapaint.flag & IMAGEPAINT_DRAWING) {
+ if(settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL_DRAWING)
+ draw= 1;
+ }
+ else if(settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL)
draw= 1;
- }
- else if(Gip.flag & IMAGEPAINT_DRAW_TOOL)
- draw= 1;
-
- if(draw) {
- getmouseco_areawin(mval);
-
- radius= tool->size*G.sima->zoom/2;
- fdrawXORcirc(mval[0], mval[1], radius);
+
+ if(draw) {
+ getmouseco_areawin(mval);
- if (tool->innerradius != 1.0) {
- radius *= tool->innerradius;
+ radius= brush->size*G.sima->zoom/2;
fdrawXORcirc(mval[0], mval[1], radius);
+
+ if (brush->innerradius != 1.0) {
+ radius *= brush->innerradius;
+ fdrawXORcirc(mval[0], mval[1], radius);
+ }
}
}
}
@@ -845,6 +842,8 @@ static void image_editvertex_buts(uiBlock *block)
void do_imagebuts(unsigned short event)
{
+ ToolSettings *settings= G.scene->toolsettings;
+
switch(event) {
case B_TRANS_IMAGE:
image_editvertex_buts(NULL);
@@ -884,13 +883,15 @@ void do_imagebuts(unsigned short event)
break;
case B_SIMACLONEBROWSE:
- setcloneimage();
- allqueue(REDRAWIMAGE, 0);
+ if (settings->imapaint.brush)
+ if (brush_clone_image_set_nr(settings->imapaint.brush, G.sima->menunr))
+ allqueue(REDRAWIMAGE, 0);
break;
case B_SIMACLONEDELETE:
- Gip.clone.image= NULL;
- allqueue(REDRAWIMAGE, 0);
+ if (settings->imapaint.brush)
+ if (brush_clone_image_delete(settings->imapaint.brush))
+ allqueue(REDRAWIMAGE, 0);
break;
case B_SIMABRUSHCHANGE:
@@ -907,6 +908,37 @@ void do_imagebuts(unsigned short event)
curvemapping_do_image(G.sima->cumap, G.sima->image);
allqueue(REDRAWIMAGE, 0);
break;
+
+ case B_BRUSHBROWSE:
+ if(G.sima->menunr==-2) {
+ activate_databrowse((ID*)settings->imapaint.brush, ID_BR, 0, B_BRUSHBROWSE, &G.sima->menunr, do_global_buttons);
+ break;
+ }
+ else if(G.sima->menunr < 0) break;
+
+ if(brush_set_nr(&settings->imapaint.brush, G.sima->menunr)) {
+ BIF_undo_push("Browse Brush");
+ allqueue(REDRAWIMAGE, 0);
+ }
+ break;
+ case B_BRUSHDELETE:
+ if(brush_delete(&settings->imapaint.brush)) {
+ BIF_undo_push("Unlink Brush");
+ allqueue(REDRAWIMAGE, 0);
+ }
+ break;
+ case B_KEEPDATA:
+ brush_toggle_fake_user(settings->imapaint.brush);
+ allqueue(REDRAWIMAGE, 0);
+ break;
+ case B_BRUSHLOCAL:
+ if(settings->imapaint.brush && settings->imapaint.brush->id.lib) {
+ if(okee("Make local")) {
+ make_local_brush(settings->imapaint.brush);
+ allqueue(REDRAWIMAGE, 0);
+ }
+ }
+ break;
}
}
@@ -964,9 +996,11 @@ static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PROPERTIES
/* B_SIMABRUSHCHANGE only redraws and eats the mouse messages */
/* so that LEFTMOUSE does not 'punch' through the floating panel */
/* B_SIMANOTHING */
- ImagePaintTool *tool= &Gip.tool[Gip.current];
+ ToolSettings *settings= G.scene->toolsettings;
+ Brush *brush= settings->imapaint.brush;
uiBlock *block;
ID *id;
+ int yco, xco, butw;
block= uiNewBlock(&curarea->uiblocks, "image_panel_paint", UI_EMBOSS, UI_HELV, curarea->win);
uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
@@ -974,39 +1008,63 @@ static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PROPERTIES
if(uiNewPanel(curarea, block, "Image Paint", "Image", 10, 230, 318, 204)==0)
return;
- uiBlockBeginAlign(block);
- uiDefButF(block, COL, B_VPCOLSLI, "", 979,160,230,19, tool->rgba, 0, 0, 0, 0, "");
- uiDefButF(block, NUMSLI, B_SIMANOTHING , "Opacity ", 979,140,230,19, tool->rgba+3, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
- uiDefButI(block, NUMSLI, B_SIMANOTHING , "Size ", 979,120,230,19, &tool->size, 2, 64, 0, 0, "The size of the brush");
- uiDefButF(block, NUMSLI, B_SIMANOTHING , "Fall ", 979,100,230,19, &tool->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush");
-
- if(Gip.current == IMAGEPAINT_BRUSH || Gip.current == IMAGEPAINT_SMEAR)
- uiDefButF(block, NUMSLI, B_SIMANOTHING , "Stepsize ",979,80,230,19, &tool->timing, 1.0, 100.0, 0, 0, "Repeating Paint On %of Brush diameter");
- else
- uiDefButF(block, NUMSLI, B_SIMANOTHING , "Flow ", 979,80,230,19, &tool->timing, 1.0, 100.0, 0, 0, "Paint Flow for Air Brush");
- uiBlockEndAlign(block);
+ yco= 160;
uiBlockBeginAlign(block);
- uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Brush", 890,160,80,19, &Gip.current, 7.0, IMAGEPAINT_BRUSH, 0, 0, "Brush");
- uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "AirBrush", 890,140,80,19, &Gip.current, 7.0, IMAGEPAINT_AIRBRUSH, 0, 0, "AirBrush");
- uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Soften", 890,120,80,19, &Gip.current, 7.0, IMAGEPAINT_SOFTEN, 0, 0, "Soften");
- uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Aux AB1", 890,100,80,19, &Gip.current, 7.0, IMAGEPAINT_AUX1, 0, 0, "Auxiliary Air Brush1");
- uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Aux AB2", 890,80,80,19, &Gip.current, 7.0, IMAGEPAINT_AUX2, 0, 0, "Auxiliary Air Brush2");
- uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Smear", 890,60,80,19, &Gip.current, 7.0, IMAGEPAINT_SMEAR, 0, 0, "Smear");
- uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Clone", 890,40,80,19, &Gip.current, 7.0, IMAGEPAINT_CLONE, 0, 0, "Clone Brush / use RMB to drag source image");
+ uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Draw", 0 ,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush");
+ uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Soften", 80 ,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
+ uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Smear", 160,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");
+ uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Clone", 240,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image");
uiBlockEndAlign(block);
+ yco -= 30;
- uiBlockBeginAlign(block);
- id= (ID*)Gip.clone.image;
- std_libbuttons(block, 979, 40, 0, NULL, B_SIMACLONEBROWSE, ID_IM, 0, id, 0, &G.sima->menunr, 0, 0, B_SIMACLONEDELETE, 0, 0);
- uiDefButF(block, NUMSLI, B_SIMABRUSHCHANGE, "B ",979,20,230,19, &Gip.clone.alpha , 0.0, 1.0, 0, 0, "Blend clone image");
- uiBlockEndAlign(block);
+ uiBlockSetCol(block, TH_BUT_SETTING2);
+ id= (ID*)settings->imapaint.brush;
+ xco= std_libbuttons(block, 0, yco, 0, NULL, B_BRUSHBROWSE, ID_BR, 0, id, NULL, &(G.sima->menunr), 0, B_BRUSHLOCAL, B_BRUSHDELETE, 0, B_KEEPDATA);
+ uiBlockSetCol(block, TH_AUTO);
+
+ if(brush && !brush->id.lib) {
+ butw= 320-(xco+10);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, B_SIMABRUSHCHANGE, "Airbrush", xco+10,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)");
+ uiDefButBitS(block, TOG|BIT, IMAGEPAINT_TORUS, B_SIMABRUSHCHANGE, "Wrap", xco+10,yco-20,butw,19, &settings->imapaint.flag, 0, 0, 0, 0, "Enables torus wrapping");
+ uiBlockEndAlign(block);
+
+ uiDefButS(block, MENU, B_SIMANOTHING, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5", xco+10,yco-45,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes");
+
+ yco -= 25;
+
+ uiBlockBeginAlign(block);
+ uiDefButF(block, COL, B_VPCOLSLI, "", 0,yco,200,19, brush->rgb, 0, 0, 0, 0, "");
+ uiDefButF(block, NUMSLI, B_SIMANOTHING, "Opacity ", 0,yco-20,200,19, &brush->alpha, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
+ uiDefButI(block, NUMSLI, B_SIMANOTHING, "Size ", 0,yco-40,200,19, &brush->size, 1, 200, 0, 0, "The size of the brush");
+ uiDefButF(block, NUMSLI, B_SIMANOTHING, "Falloff ", 0,yco-60,200,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush");
+
+ if(brush->flag & BRUSH_AIRBRUSH)
+ uiDefButF(block, NUMSLI, B_SIMANOTHING, "Flow ", 0,yco-80,200,19, &brush->timing, 1.0, 100.0, 0, 0, "Paint Flow for Air Brush");
+ else
+ uiDefButF(block, NUMSLI, B_SIMANOTHING, "Stepsize ",0,yco-80,200,19, &brush->timing, 1.0, 100.0, 0, 0, "Repeating Paint On %% of Brush diameter");
+ uiBlockEndAlign(block);
+
+ yco -= 110;
+
+ if(settings->imapaint.tool == PAINT_TOOL_CLONE) {
+ id= (ID*)brush->clone.image;
+ uiBlockSetCol(block, TH_BUT_SETTING2);
+ xco= std_libbuttons(block, 0, yco, 0, NULL, B_SIMACLONEBROWSE, ID_IM, 0, id, 0, &G.sima->menunr, 0, 0, B_SIMACLONEDELETE, 0, 0);
+ uiBlockSetCol(block, TH_AUTO);
+ if(id) {
+ butw= 320-(xco+5);
+ 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");
+ }
+ }
+ }
#if 0
- uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL_DRAWING, B_SIMABRUSHCHANGE, "TD", 890,1,50,19, &Gip.flag, 0, 0, 0, 0, "Enables tool shape while drawing");
- uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL, B_SIMABRUSHCHANGE, "TP", 940,1,50,19, &Gip.flag, 0, 0, 0, 0, "Enables tool shape while not drawing");
+ uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL_DRAWING, B_SIMABRUSHCHANGE, "TD", 0,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while drawing");
+ uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL, B_SIMABRUSHCHANGE, "TP", 50,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while not drawing");
#endif
- uiDefButBitS(block, TOG|BIT, IMAGEPAINT_TORUS, B_SIMABRUSHCHANGE, "Wrap", 890,1,50,19, &Gip.flag, 0, 0, 0, 0, "Enables torus wrapping");
}
static void image_panel_curves_reset(void *cumap_v, void *unused)
@@ -1444,6 +1502,7 @@ void drawimagespace(ScrArea *sa, void *spacedata)
{
SpaceImage *sima= spacedata;
ImBuf *ibuf= NULL;
+ Brush *brush;
float col[3];
unsigned int *rect;
float x1, y1;
@@ -1617,7 +1676,8 @@ void drawimagespace(ScrArea *sa, void *spacedata)
}
}
- if(Gip.current == IMAGEPAINT_CLONE) {
+ brush= G.scene->toolsettings->imapaint.brush;
+ if(brush && (G.scene->toolsettings->imapaint.tool == PAINT_TOOL_CLONE)) {
int w, h;
unsigned char *clonerect;
@@ -1627,8 +1687,8 @@ void drawimagespace(ScrArea *sa, void *spacedata)
if(clonerect) {
int offx, offy;
- offx = sima->zoom*ibuf->x * + Gip.clone.offset[0];
- offy = sima->zoom*ibuf->y * + Gip.clone.offset[1];
+ offx = sima->zoom*ibuf->x * + brush->clone.offset[0];
+ offy = sima->zoom*ibuf->y * + brush->clone.offset[1];
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c
index a906cc275fd..9c6e244e549 100644
--- a/source/blender/src/editface.c
+++ b/source/blender/src/editface.c
@@ -54,7 +54,6 @@
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_userdef_types.h"
#include "BKE_utildefines.h"
#include "BKE_depsgraph.h"
@@ -88,7 +87,6 @@
#include "blendef.h"
#include "butspace.h"
-#include "../img/IMG_Api.h"
#include "BSE_trans_types.h"
#include "BDR_unwrapper.h"
@@ -121,7 +119,7 @@
/* returns 0 if not found, otherwise 1 */
-static int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect)
+int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect)
{
if (!me->tface || me->totface==0)
return 0;
@@ -1506,7 +1504,7 @@ void set_texturepaint() /* toggle */
* @param org origin of the view ray.
* @param dir direction of the view ray.
*/
-static void get_pick_ray(short x, short y, float org[3], float dir[3])
+static void get_pick_ray(short *xy, float org[3], float dir[3])
{
double mvmatrix[16];
double projmatrix[16];
@@ -1525,10 +1523,10 @@ static void get_pick_ray(short x, short y, float org[3], float dir[3])
/* printf("viewport = (%4d, %4d, %4d, %4d)\n", viewport[0], viewport[1], viewport[2], viewport[3]); */
/* printf("cursor = (%4d, %4d)\n", x, y); */
- gluUnProject((GLdouble) x, (GLdouble) y, 0.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
+ gluUnProject((GLdouble) xy[0], (GLdouble) xy[1], 0.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
org[0] = (float)px; org[1] = (float)py; org[2] = (float)pz;
/* printf("world point at z=0.0 is (%f, %f, %f)\n", org[0], org[1], org[2]); */
- gluUnProject((GLdouble) x, (GLdouble) y, 1.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
+ gluUnProject((GLdouble) xy[0], (GLdouble) xy[1], 1.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
/* printf("world point at z=1.0 is (%f, %f, %f)\n", px, py, pz); */
dir[0] = ((float)px) - org[0];
dir[1] = ((float)py) - org[1];
@@ -1668,7 +1666,7 @@ static int face_get_vertex_coordinates(Mesh* mesh, TFace* face, float v1[3], flo
* @param u (u,v) coordinate.
* @param v (u,v) coordinate.
*/
-static void face_get_uv(TFace* face, int v1, int v2, int v3, float a, float b, float* u, float* v)
+static void face_get_uv(TFace* face, int v1, int v2, int v3, float a, float b, float *uv)
{
float uv01[2], uv21[2];
@@ -1692,8 +1690,8 @@ static void face_get_uv(TFace* face, int v1, int v2, int v3, float a, float b, f
uv01[1] *= a;
uv21[0] *= b;
uv21[1] *= b;
- *u = face->uv[v1][0] + (uv01[0] + uv21[0]);
- *v = face->uv[v1][1] + (uv01[1] + uv21[1]);
+ uv[0] = face->uv[v1][0] + (uv01[0] + uv21[0]);
+ uv[1] = face->uv[v1][1] + (uv01[1] + uv21[1]);
}
/**
@@ -1711,7 +1709,7 @@ static void face_get_uv(TFace* face, int v1, int v2, int v3, float a, float b, f
* 0 == no intersection, (u,v) invalid
* 1 == intersection, (u,v) valid
*/
-static int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short x, short y, float* u, float* v)
+int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short *xy, float *uv)
{
float org[3], dir[3];
float ab[2];
@@ -1720,7 +1718,7 @@ static int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short x, short
int num_verts;
/* Get a view ray to intersect with the face */
- get_pick_ray(x, y, org, dir);
+ get_pick_ray(xy, org, dir);
/* Convert local vertex coordinates to world */
num_verts = face_get_vertex_coordinates(mesh, face, v1, v2, v3, v4);
@@ -1738,178 +1736,18 @@ static int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short x, short
result = triangle_ray_intersect(v2, v1, v3, org, dir, ab);
if ( (num_verts == 3) || ((num_verts == 4) && (result > 1)) ) {
/* Face is a triangle or a quad with a hit on the first triangle */
- face_get_uv(face, 1, 0, 2, ab[0], ab[1], u, v);
+ face_get_uv(face, 1, 0, 2, ab[0], ab[1], uv);
/* printf("triangle 1, texture (u,v)=(%f, %f)\n", *u, *v); */
}
else {
/* Face is a quad and no intersection with first triangle */
result = triangle_ray_intersect(v4, v3, v1, org, dir, ab);
- face_get_uv(face, 3, 2, 0, ab[0], ab[1], u, v);
+ face_get_uv(face, 3, 2, 0, ab[0], ab[1], uv);
/* printf("triangle 2, texture (u,v)=(%f, %f)\n", *u, *v); */
}
return result > 0;
}
-/**
- * First attempt at drawing in the texture of a face.
- * @author Maarten Gribnau
- */
-void face_draw()
-{
- Object *ob;
- Mesh *me;
- TFace *face, *face_old = 0;
- short xy[2], xy_old[2];
- //int a, index;
- Image *img=NULL, *img_old = NULL;
- IMG_BrushPtr brush;
- IMG_CanvasPtr canvas = 0;
- unsigned int rowBytes, face_index;
- char *warn_packed_file = 0;
- float uv[2], uv_old[2];
- extern VPaint Gvp;
- short mousebut;
-
- ob = OBACT;
- if (!ob) {
- error("No active object"); return;
- }
- if (!(ob->lay & G.vd->lay)) {
- error("The active object is not in this layer"); return;
- }
- me = get_mesh(ob);
- if (!me) {
- error("The active object does not have a mesh obData"); return;
- }
-
- brush = IMG_BrushCreate(Gvp.size, Gvp.size, &Gvp.r);
- if (!brush) {
- error("Can't create brush"); return;
- }
-
- if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
- else mousebut = L_MOUSE;
-
- persp(PERSP_VIEW);
-
- getmouseco_areawin(xy_old);
- while (get_mbut() & mousebut) {
- getmouseco_areawin(xy);
- /* Check if cursor has moved */
- if ((xy[0] != xy_old[0]) || (xy[1] != xy_old[1])) {
-
- /* Get face to draw on */
- if (!facesel_face_pick(me, xy, &face_index, 0)) face = NULL;
- else face = (((TFace*)me->tface)+face_index);
-
- /* Check if this is another face. */
- if (face != face_old) {
- /* The active face changed, check the texture */
- if (face) {
- img = face->tpage;
- }
- else {
- img = 0;
- }
-
- if (img != img_old) {
- /* Faces have different textures. Finish drawing in the old face. */
- if (face_old && canvas) {
- face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
- IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
- img_old->ibuf->userflags |= IB_BITMAPDIRTY;
- /* Delete old canvas */
- IMG_CanvasDispose(canvas);
- canvas = 0;
- }
-
- /* Create new canvas and start drawing in the new face. */
- if (img) {
- if (img->ibuf && img->packedfile == 0) {
- /* MAART: skipx is not set most of the times. Make a guess. */
- rowBytes = img->ibuf->skipx ? img->ibuf->skipx : img->ibuf->x * 4;
- canvas = IMG_CanvasCreateFromPtr(img->ibuf->rect, img->ibuf->x, img->ibuf->y, rowBytes);
- if (canvas) {
- face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
- face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
- IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
- img->ibuf->userflags |= IB_BITMAPDIRTY;
- }
- }
- else {
- /* TODO: should issue warning that no texture is assigned */
- if (img->packedfile) {
- warn_packed_file = img->id.name + 2;
- img = 0;
- }
- }
- }
- }
- else {
- /* Face changed and faces have the same texture. */
- if (canvas) {
- /* Finish drawing in the old face. */
- if (face_old) {
- face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
- IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
- img_old->ibuf->userflags |= IB_BITMAPDIRTY;
- }
-
- /* Start drawing in the new face. */
- if (face) {
- face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
- face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
- IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
- img->ibuf->userflags |= IB_BITMAPDIRTY;
- }
- }
- }
- }
- else {
- /* Same face, continue drawing */
- if (face && canvas) {
- /* Get the new (u,v) coordinates */
- face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
- IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
- img->ibuf->userflags |= IB_BITMAPDIRTY;
- }
- }
-
- if (face && img) {
- /* Make OpenGL aware of a change in the texture */
- free_realtime_image(img);
- /* Redraw the view */
- scrarea_do_windraw(curarea);
- screen_swapbuffers();
- }
-
- xy_old[0] = xy[0];
- xy_old[1] = xy[1];
- uv_old[0] = uv[0];
- uv_old[1] = uv[1];
- face_old = face;
- img_old = img;
- }
- }
-
- IMG_BrushDispose(brush);
- if (canvas) {
- IMG_CanvasDispose(canvas);
- canvas = 0;
- }
-
- if (warn_packed_file) {
- error("Painting in packed images is not supported: %s", warn_packed_file);
- }
-
- persp(PERSP_WIN);
-
- BIF_undo_push("UV face draw");
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWIMAGE, 0);
- allqueue(REDRAWHEADERS, 0);
-}
-
/* Selects all faces which have the same uv-texture as the active face
* @author Roel Spruit
* @return Void
diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c
index cb478bf9f59..bc1bfba9161 100644
--- a/source/blender/src/filesel.c
+++ b/source/blender/src/filesel.c
@@ -2464,7 +2464,7 @@ void main_to_filelist(SpaceFile *sfile)
if( sfile->dir[0]==0) {
/* make directories */
- sfile->totfile= 23;
+ sfile->totfile= 24;
sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
for(a=0; a<sfile->totfile; a++) {
@@ -2495,6 +2495,7 @@ void main_to_filelist(SpaceFile *sfile)
sfile->filelist[20].relname= BLI_strdup("Armature");
sfile->filelist[21].relname= BLI_strdup("Action");
sfile->filelist[22].relname= BLI_strdup("NodeTree");
+ sfile->filelist[23].relname= BLI_strdup("Brush");
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
}
diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c
index 4d87f3c9c56..a21518c17e1 100644
--- a/source/blender/src/header_image.c
+++ b/source/blender/src/header_image.c
@@ -54,6 +54,7 @@
#include "BDR_drawmesh.h"
#include "BDR_unwrapper.h"
+#include "BKE_brush.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_library.h"
@@ -315,7 +316,9 @@ void do_image_buttons(unsigned short event)
break;
case B_SIMAGEPAINTTOOL:
- // check for packed file here
+ if(G.sima->flag & SI_DRAWTOOL)
+ /* add new brush if none exists */
+ brush_check_exists(&G.scene->toolsettings->imapaint.brush);
allqueue(REDRAWIMAGE, 0);
allqueue(REDRAWVIEW3D, 0);
break;
diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c
index 3440b5b0c18..3ec3a58f9b3 100644
--- a/source/blender/src/headerbuttons.c
+++ b/source/blender/src/headerbuttons.c
@@ -251,7 +251,7 @@ int std_libbuttons(uiBlock *block, short xco, short yco,
if(browse) {
char *extrastr= NULL;
- if(ELEM(id_code, ID_MA, ID_TE)) add_addbutton= 1;
+ if(ELEM3(id_code, ID_MA, ID_TE, ID_BR)) add_addbutton= 1;
lb= wich_libbase(G.main, id_code);
@@ -261,7 +261,7 @@ int std_libbuttons(uiBlock *block, short xco, short yco,
uiBlockSetCol(block, TH_BUT_SETTING2);
}
- if ELEM7( id_code, ID_SCE, ID_SCR, ID_MA, ID_TE, ID_WO, ID_IP, ID_AC) extrastr= "ADD NEW %x 32767";
+ if ELEM8( id_code, ID_SCE, ID_SCR, ID_MA, ID_TE, ID_WO, ID_IP, ID_AC, ID_BR) extrastr= "ADD NEW %x 32767";
else if (id_code==ID_TXT) extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
else if (id_code==ID_SO) extrastr= "OPEN NEW %x 32766";
diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c
index 3aed860442f..627d3aaf18f 100644
--- a/source/blender/src/imagepaint.c
+++ b/source/blender/src/imagepaint.c
@@ -43,17 +43,29 @@
#include <config.h>
#endif
+#include "MEM_guardedalloc.h"
+
#ifdef WIN32
#include "BLI_winstuff.h"
#endif
#include "IMB_imbuf_types.h"
+#include "DNA_brush_types.h"
#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "BKE_brush.h"
#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
#include "BIF_mywindow.h"
#include "BIF_screen.h"
@@ -62,15 +74,450 @@
#include "BSE_drawipo.h"
#include "BSE_trans_types.h"
+#include "BSE_view.h"
#include "BDR_drawmesh.h"
#include "BDR_imagepaint.h"
#include "BDR_vpaint.h"
-#include "IMG_Api.h"
-
+#include "blendef.h"
#include "mydevice.h"
+/* ImagePaintPixmap */
+
+#define IMAPAINT_FLOAT_TO_CHAR(f) ((char)(f*255))
+#define IMAPAINT_CHAR_TO_FLOAT(c) (c/255.0f)
+#define IMAPAINT_FLOAT_CLAMP(f) ((f < 0.0)? 0.0: (f > 1.0)? 1.0: f)
+
+#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { c[0]=IMAPAINT_FLOAT_TO_CHAR(f[0]); \
+ c[1]=IMAPAINT_FLOAT_TO_CHAR(f[1]); c[2]=IMAPAINT_FLOAT_TO_CHAR(f[2]); }
+#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \
+ c[0]=IMAPAINT_FLOAT_TO_CHAR(f[0]); c[1]=IMAPAINT_FLOAT_TO_CHAR(f[1]); \
+ c[2]=IMAPAINT_FLOAT_TO_CHAR(f[2]); c[2]=IMAPAINT_FLOAT_TO_CHAR(f[3]);}
+#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { f[0]=IMAPAINT_CHAR_TO_FLOAT(c[0]); \
+ f[1]=IMAPAINT_CHAR_TO_FLOAT(c[1]); f[2]=IMAPAINT_CHAR_TO_FLOAT(c[2]); }
+#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { \
+ f[0]=IMAPAINT_CHAR_TO_FLOAT(c[0]); f[1]=IMAPAINT_CHAR_TO_FLOAT(c[1]); \
+ f[2]=IMAPAINT_CHAR_TO_FLOAT(c[2]); f[3]=IMAPAINT_CHAR_TO_FLOAT(c[3]); }
+
+#define IMAPAINT_FLOAT_RGB_COPY(a, b) VECCOPY(a, b)
+#define IMAPAINT_FLOAT_RGB_ADD(a, b) VECADD(a, a, b)
+
+#define IMAPAINT_RGB_COPY(a, b) { a[0]=b[0]; a[1]=b[1]; a[2]=b[2]; }
+#define IMAPAINT_RGBA_COPY(a, b) { *((int*)a)=*((int*)b); }
+
+typedef struct ImagePaintPixmap {
+ unsigned int width, height, rowbytes, shared;
+ char *rect;
+} ImagePaintPixmap;
+
+static ImagePaintPixmap *imapaint_pixmap_new(unsigned int w, unsigned int h, char *rect)
+{
+ ImagePaintPixmap *pm = MEM_callocN(sizeof(ImagePaintPixmap), "ImagePaintPixmap");
+
+ pm->width = w;
+ pm->height = h;
+ pm->rowbytes = sizeof(char)*w*4;
+
+ if (rect) {
+ pm->rect = rect;
+ pm->shared = 1;
+ }
+ else
+ pm->rect = MEM_mallocN(pm->rowbytes*h, "ImagePaintPixmapRect");
+
+ return pm;
+}
+
+static void imapaint_pixmap_free(ImagePaintPixmap *pm)
+{
+ if (!pm->shared)
+ MEM_freeN(pm->rect);
+ MEM_freeN(pm);
+}
+
+/* ImagePaintBrush */
+
+typedef struct ImagePaintBrush {
+ ImagePaintPixmap *pixmap;
+ float rgb[3], alpha;
+ unsigned int inner_radius, outer_radius;
+ short torus, blend;
+} ImagePaintBrush;
+
+static void imapaint_brush_pixmap_refresh(ImagePaintBrush *brush)
+{
+ ImagePaintPixmap *pm = brush->pixmap;
+ char *dst, src[4], src_alpha[4];
+ unsigned int y, x, outer, inner;
+ float w_2, h_2, dX, dY, d, a;
+
+ w_2 = pm->width/2.0f;
+ h_2 = pm->height/2.0f;
+
+ outer = brush->outer_radius;
+ inner = brush->inner_radius;
+
+ IMAPAINT_FLOAT_RGB_TO_CHAR(src, brush->rgb);
+ src[3] = 0;
+ IMAPAINT_RGB_COPY(src_alpha, src);
+ src_alpha[3] = IMAPAINT_FLOAT_TO_CHAR(brush->alpha);
+
+ for (y=0; y < pm->height; y++) {
+ dst = pm->rect + y*pm->rowbytes;
+
+ for (x=0; x < pm->width; x++, dst+=4) {
+ dX = x + 0.5f - w_2;
+ dY = y + 0.5f - h_2;
+ d = sqrt(dX*dX + dY*dY);
+
+ if (d <= inner) {
+ IMAPAINT_RGBA_COPY(dst, src_alpha);
+ }
+ else if ((d < outer) && (inner < outer)) {
+ a = sqrt((d - inner)/(outer - inner));
+ a = (1 - a)*brush->alpha;
+
+ IMAPAINT_RGB_COPY(dst, src);
+ dst[3] = IMAPAINT_FLOAT_TO_CHAR(a);
+ }
+ else {
+ IMAPAINT_RGBA_COPY(dst, src);
+ }
+ }
+ }
+}
+
+static void imapaint_brush_set_radius_ratio(ImagePaintBrush *brush, float ratio)
+{
+ ImagePaintPixmap *pm = brush->pixmap;
+ unsigned int si, w_2 = pm->width/2, h_2 = pm->height/2;
+
+ si = (pm->width < pm->height)? pm->width: pm->height;
+ brush->inner_radius = (int)((ratio*si)/2);
+ brush->outer_radius = si/2;
+
+ if (brush->outer_radius > w_2)
+ brush->outer_radius = w_2;
+ if (brush->outer_radius > h_2)
+ brush->outer_radius = h_2;
+ if (brush->inner_radius > brush->outer_radius)
+ brush->inner_radius = brush->outer_radius;
+}
+
+static ImagePaintBrush *imapaint_brush_new(unsigned int w, unsigned int h, float *rgb, float alpha, float radius_ratio)
+{
+ ImagePaintBrush *brush = MEM_callocN(sizeof(ImagePaintBrush), "ImagePaintBrush");
+
+ IMAPAINT_FLOAT_RGB_COPY(brush->rgb, rgb);
+ brush->alpha = alpha;
+ brush->pixmap = imapaint_pixmap_new(w, h, NULL);
+
+ imapaint_brush_set_radius_ratio(brush, radius_ratio);
+ imapaint_brush_pixmap_refresh(brush);
+
+ return brush;
+}
+
+static void imapaint_brush_free(ImagePaintBrush *brush)
+{
+ imapaint_pixmap_free(brush->pixmap);
+ MEM_freeN(brush);
+}
+
+/* ImagePaintPixmap Utilities */
+
+static char *imapaint_pixmap_get_rgba(ImagePaintPixmap *pm, unsigned int x, unsigned int y)
+{
+ return &pm->rect[pm->rowbytes*y + x*4];
+}
+
+static char *imapaint_pixmap_get_rgba_torus(ImagePaintPixmap *pm, unsigned int x, unsigned int y)
+{
+ x %= pm->width;
+ y %= pm->height;
+
+ return &pm->rect[pm->rowbytes*y + x*4];
+}
+
+static void imapaint_pixmap_clip(ImagePaintPixmap *pm, ImagePaintPixmap *bpm, float *pos, unsigned int *off, unsigned int *boff, unsigned int *dim)
+{
+ int x = (int)(pos[0]*pm->width - bpm->width/2);
+ int y = (int)(pos[1]*pm->height - bpm->height/2);
+
+ dim[0] = bpm->width;
+ dim[1] = bpm->height;
+
+ if (((x + (int)dim[0]) <= 0) || (x >= (int)pm->width) ||
+ ((y + (int)dim[1]) <= 0) || (y >= (int)pm->height)) {
+ dim[0] = 0;
+ dim[1] = 0;
+ return;
+ }
+
+ if (x < 0) {
+ dim[0] += x;
+ off[0] = 0;
+ boff[0] = -x;
+ }
+ else {
+ off[0] = x;
+ boff[0] = 0;
+ }
+
+ if (y < 0) {
+ dim[1] += y;
+ off[1] = 0;
+ boff[1] = -y;
+ }
+ else {
+ off[1] = y;
+ boff[1] = 0;
+ }
+
+ if (off[0] + dim[0] > pm->width)
+ dim[0] -= (off[0] + dim[0]) - pm->width;
+ if (off[1] + dim[1] > pm->height)
+ dim[1] -= (off[1] + dim[1]) - pm->height;
+}
+
+static void imapaint_pixmap_blend(ImagePaintPixmap *pm, ImagePaintPixmap *bpm, float *pos, short mode)
+{
+ unsigned int x, y, dim[2], out_off[2], in_off[2];
+ char *out, *in;
+
+ imapaint_pixmap_clip(pm, bpm, pos, out_off, in_off, dim);
+
+ if ((dim[0] == 0) || (dim[1] == 0))
+ return;
+
+ for (y=0; y < dim[1]; y++) {
+ out = imapaint_pixmap_get_rgba(pm, out_off[0], out_off[1]+y);
+ in = imapaint_pixmap_get_rgba(bpm, in_off[0], in_off[1]+y);
+
+ for (x=0; x < dim[0]; x++, out+=4, in+=4)
+ brush_blend_rgb(out, out, in, in[3], mode);
+ }
+}
+
+static void imapaint_pixmap_blend_torus(ImagePaintPixmap *pm, ImagePaintPixmap *bpm, float *pos, short mode)
+{
+ unsigned int x, y, out_off[2], mx, my;
+ char *out, *in;
+
+ out_off[0] = (int)(pos[0]*pm->width - bpm->width/2);
+ out_off[1] = (int)(pos[1]*pm->height - bpm->height/2);
+
+ for (y=0; y < bpm->height; y++) {
+ in = imapaint_pixmap_get_rgba(bpm, 0, y);
+
+ for (x=0; x < bpm->width; x++, out+=4, in+=4) {
+ mx = (out_off[0]+x) % pm->width;
+ my = (out_off[1]+y) % pm->height;
+ out = imapaint_pixmap_get_rgba(pm, mx, my);
+
+ brush_blend_rgb(out, out, in, in[3], mode);
+ }
+ }
+}
+
+static int imapaint_pixmap_add_if(ImagePaintPixmap *pm, unsigned int x, unsigned int y, float *outrgb, short torus)
+{
+ char *inrgb;
+ float finrgb[3];
+
+ if ((x >= pm->width) || (y >= pm->height)) {
+ if (torus)
+ inrgb = imapaint_pixmap_get_rgba_torus(pm, x, y);
+ else
+ return 0;
+ }
+ else
+ inrgb = imapaint_pixmap_get_rgba(pm, x, y);
+
+ IMAPAINT_CHAR_RGB_TO_FLOAT(finrgb, inrgb);
+ IMAPAINT_FLOAT_RGB_ADD(outrgb, finrgb);
+
+ return 1;
+}
+
+/* ImagePaintPixmap Tools */
+
+static void imapaint_blend_line(ImagePaintPixmap *pm, ImagePaintBrush *brush, float *start, float *end)
+{
+ float numsteps, t, pos[2];
+ int step, d[2];
+
+ d[0] = (int)((end[0] - start[0])*pm->width);
+ d[1] = (int)((end[1] - start[1])*pm->height);
+ numsteps = sqrt(d[0]*d[0] + d[1]*d[1])/(brush->pixmap->width/4.0f);
+
+ if(numsteps < 1.0)
+ numsteps = 1.0f;
+
+ for (step=0; step < numsteps; step++) {
+ t = (step+1)/numsteps;
+ pos[0] = start[0] + d[0]*t/pm->width;
+ pos[1] = start[1] + d[1]*t/pm->height;
+
+ if (brush->torus)
+ imapaint_pixmap_blend_torus(pm, brush->pixmap, pos, brush->blend);
+ else
+ imapaint_pixmap_blend(pm, brush->pixmap, pos, brush->blend);
+ }
+}
+
+static void imapaint_soften_sharpen(ImagePaintPixmap *pm, ImagePaintBrush *brush, float *pos, short sharpen)
+{
+ ImagePaintPixmap *bpm = brush->pixmap;
+ unsigned int x, y, count, xi, yi, xo, yo;
+ unsigned int out_off[2], in_off[2], dim[2];
+ float outrgb[3], finrgb[3];
+ short torus= brush->torus;
+ char *inrgb, *out;
+
+ if (torus) {
+ dim[0] = bpm->width;
+ dim[1] = bpm->width;
+ in_off[0] = (int)(pos[0]*pm->width - bpm->width/2);
+ in_off[1] = (int)(pos[1]*pm->height - bpm->width/2);
+ out_off[0] = out_off[1] = 0;
+ }
+ else {
+ imapaint_pixmap_clip(pm, bpm, pos, in_off, out_off, dim);
+ if ((dim[0] == 0) || (dim[1] == 0))
+ return;
+ }
+
+ for (y=0; y < dim[1]; y++) {
+ for (x=0; x < dim[0]; x++) {
+ /* get input pixel */
+ xi = in_off[0] + x;
+ yi = in_off[1] + y;
+ if (torus)
+ inrgb = imapaint_pixmap_get_rgba_torus(pm, xi, yi);
+ else
+ inrgb = imapaint_pixmap_get_rgba(pm, xi, yi);
+
+ /* sum and average surrounding pixels */
+ count = 1;
+ IMAPAINT_CHAR_RGB_TO_FLOAT(outrgb, inrgb);
+ if (sharpen)
+ IMAPAINT_FLOAT_RGB_COPY(finrgb, outrgb);
+
+ count += imapaint_pixmap_add_if(pm, xi-1, yi-1, outrgb, torus);
+ count += imapaint_pixmap_add_if(pm, xi-1, yi , outrgb, torus);
+ count += imapaint_pixmap_add_if(pm, xi-1, yi+1, outrgb, torus);
+
+ count += imapaint_pixmap_add_if(pm, xi , yi-1, outrgb, torus);
+ count += imapaint_pixmap_add_if(pm, xi , yi+1, outrgb, torus);
+
+ count += imapaint_pixmap_add_if(pm, xi+1, yi-1, outrgb, torus);
+ count += imapaint_pixmap_add_if(pm, xi+1, yi , outrgb, torus);
+ count += imapaint_pixmap_add_if(pm, xi+1, yi+1, outrgb, torus);
+
+ outrgb[0] /= count;
+ outrgb[1] /= count;
+ outrgb[2] /= count;
+
+ if (sharpen) {
+ /* unsharp masking - creates ugly artifacts and is disabled
+ for now, needs some sort of clamping to reduce artifacts */
+ outrgb[0] = 2*finrgb[0] - outrgb[0];
+ outrgb[1] = 2*finrgb[1] - outrgb[1];
+ outrgb[2] = 2*finrgb[2] - outrgb[2];
+
+ outrgb[0] = IMAPAINT_FLOAT_CLAMP(outrgb[0]);
+ outrgb[1] = IMAPAINT_FLOAT_CLAMP(outrgb[1]);
+ outrgb[2] = IMAPAINT_FLOAT_CLAMP(outrgb[2]);
+ }
+
+ /* write into brush buffer */
+ xo = out_off[0] + x;
+ yo = out_off[1] + y;
+ out = imapaint_pixmap_get_rgba(bpm, xo, yo);
+ IMAPAINT_FLOAT_RGB_TO_CHAR(out, outrgb);
+ }
+ }
+
+ if (torus)
+ imapaint_pixmap_blend_torus(pm, bpm, pos, brush->blend);
+ else
+ imapaint_pixmap_blend(pm, bpm, pos, brush->blend);
+}
+
+static void imapaint_lift_smear(ImagePaintPixmap *pm, ImagePaintBrush *brush, float *pos)
+{
+ ImagePaintPixmap *bpm = brush->pixmap;
+ int in_off[2], x, y;
+ char *out, *in;
+
+ in_off[0] = (int)(pos[0]*pm->width - bpm->width/2);
+ in_off[1] = (int)(pos[1]*pm->height - bpm->height/2);
+
+ for (y=0; y < bpm->height; y++) {
+ out = imapaint_pixmap_get_rgba(bpm, 0, y);
+ for (x=0; x < bpm->width; x++, out+=4) {
+ in = imapaint_pixmap_get_rgba_torus(pm, in_off[0]+x, in_off[1]+y);
+ IMAPAINT_RGB_COPY(out, in);
+ }
+ }
+}
+
+static void imapaint_smear(ImagePaintPixmap *pm, ImagePaintBrush *brush, float *start, float *end)
+{
+ float pos[2];
+
+ pos[0]= 2*start[0] - end[0];
+ pos[1]= 2*start[1] - end[1];
+
+ imapaint_lift_smear(pm, brush, pos);
+ imapaint_blend_line(pm, brush, start, end);
+}
+
+static void imapaint_lift_clone(ImagePaintPixmap *pm, ImagePaintBrush *brush, float *pos)
+{
+ ImagePaintPixmap *bpm = brush->pixmap;
+ int in_off[2], x, y, xi, yi;
+ char *out, *in;
+
+ /* we overwrite alphas for pixels outside clone, so need to reload them */
+ imapaint_brush_pixmap_refresh(brush);
+
+ in_off[0] = (int)(pos[0]*pm->width - bpm->width/2);
+ in_off[1] = (int)(pos[1]*pm->height - bpm->height/2);
+
+ for (y=0; y < bpm->height; y++) {
+ out = imapaint_pixmap_get_rgba(bpm, 0, y);
+ for (x=0; x < bpm->width; x++, out+=4) {
+ xi = in_off[0] + x;
+ yi = in_off[1] + y;
+
+ if ((xi < 0) || (yi < 0) || (xi >= pm->width) || (yi >= pm->height)) {
+ out[0] = out[1] = out[2] = out[3] = 0;
+ }
+ else {
+ in = imapaint_pixmap_get_rgba(pm, xi, yi);
+ IMAPAINT_RGB_COPY(out, in);
+ }
+ }
+ }
+}
+
+static void imapaint_clone(ImagePaintPixmap *pm, ImagePaintPixmap *cpm, ImagePaintBrush *brush, float *start, float *off)
+{
+ float pos[2];
+
+ pos[0]= start[0] - off[0];
+ pos[1]= start[1] - off[1];
+
+ imapaint_lift_clone(cpm, brush, pos);
+ imapaint_pixmap_blend(pm, brush->pixmap, start, brush->blend);
+}
+
+/* 2D image paint */
+
+#if 0
struct ImagePaint Gip = {
{NULL, {0.0f, 0.0f}, 0.5f},
{{{1.0f, 1.0f, 1.0f, 0.2f}, 25, 0.5f, 100.0f}, /* brush */
@@ -82,73 +529,83 @@ struct ImagePaint Gip = {
{{1.0f, 1.0f, 1.0f, 0.5f}, 25, 0.1f, 20.0f}}, /* clone */
0, IMAGEPAINT_BRUSH
};
+#endif
-static int imagepaint_init(IMG_BrushPtr **brush, IMG_CanvasPtr **canvas, IMG_CanvasPtr **clonecanvas)
+static ImagePaintBrush *imapaint_init_brush()
{
- ImBuf *ibuf= NULL, *cloneibuf= NULL;
- ImagePaintTool *tool= &Gip.tool[Gip.current];
+ ToolSettings *settings= G.scene->toolsettings;
+ Brush *brush= settings->imapaint.brush;
- /* verify that we can paint */
- if(!G.sima->image || !G.sima->image->ibuf || !G.sima->image->ibuf->rect)
- return 0;
- else if(G.sima->image->packedfile) {
- error("Painting in packed images not supported");
- return 0;
- }
+ if (!brush)
+ return NULL;
- ibuf= G.sima->image->ibuf;
+ /* initialize paint settings */
+ if(brush->flag & BRUSH_AIRBRUSH)
+ settings->imapaint.flag |= IMAGEPAINT_TIMED;
+ else
+ settings->imapaint.flag &= ~IMAGEPAINT_TIMED;
- if(Gip.current == IMAGEPAINT_CLONE) {
- if(!Gip.clone.image || !Gip.clone.image->ibuf)
- return 0;
+ /* create brush */
+ return imapaint_brush_new(brush->size, brush->size, brush->rgb, brush->alpha, brush->innerradius);
+}
- cloneibuf= Gip.clone.image->ibuf;
- }
+static void imapaint_free_brush(ImagePaintBrush *brush)
+{
+ imapaint_brush_free(brush);
+}
- /* create brush */
- *brush= IMG_BrushCreate(tool->size, tool->size, tool->rgba);
- IMG_BrushSetInnerRaduisRatio(*brush, tool->innerradius);
+static ImagePaintPixmap *imapaint_init_canvas(ImagePaintPixmap **clonecanvas)
+{
+ ImBuf *ibuf= NULL, *cloneibuf= NULL;
+ ImagePaintPixmap *canvas;
+ ToolSettings *settings= G.scene->toolsettings;
+ Brush *brush= settings->imapaint.brush;
- /* create canvas */
- *canvas= IMG_CanvasCreateFromPtr(ibuf->rect, ibuf->x, ibuf->y, ibuf->x*4);
+ /* verify that we can paint and create canvas */
+ if(!G.sima->image || !G.sima->image->ibuf || !G.sima->image->ibuf->rect)
+ return NULL;
+ else if(G.sima->image->packedfile)
+ return NULL;
- if(Gip.current == IMAGEPAINT_CLONE) {
- int w= cloneibuf->x, h= cloneibuf->y;
- *clonecanvas= IMG_CanvasCreateFromPtr(cloneibuf->rect, w, h, cloneibuf->x*4);
+ ibuf= G.sima->image->ibuf;
+ canvas= imapaint_pixmap_new(ibuf->x, ibuf->y, (char*)ibuf->rect);
+
+ if (clonecanvas) {
+ /* create clone canvas */
+ if(brush && (settings->imapaint.tool == PAINT_TOOL_CLONE)) {
+ int w, h;
+ if(!brush->clone.image || !brush->clone.image->ibuf)
+ return 0;
+
+ cloneibuf= brush->clone.image->ibuf;
+ w = cloneibuf->x;
+ h = cloneibuf->y;
+ *clonecanvas= imapaint_pixmap_new(w, h, (char*)cloneibuf->rect);
+ }
+ else
+ *clonecanvas= NULL;
}
- else
- *clonecanvas= NULL;
-
- /* initialize paint settings */
- if((Gip.current == IMAGEPAINT_AIRBRUSH) ||
- (Gip.current == IMAGEPAINT_AUX1) ||
- (Gip.current == IMAGEPAINT_AUX2))
- Gip.flag |= IMAGEPAINT_TIMED;
- else
- Gip.flag &= ~IMAGEPAINT_TIMED;
-
- return 1;
+
+ return canvas;
}
-static void imagepaint_free(IMG_BrushPtr *brush, IMG_CanvasPtr *canvas, IMG_CanvasPtr *clonecanvas)
+static void imapaint_free_canvas(ImagePaintPixmap *canvas, ImagePaintPixmap *clonecanvas)
{
- IMG_BrushDispose(brush);
- IMG_CanvasDispose(canvas);
-
- if(Gip.current == IMAGEPAINT_CLONE)
- IMG_CanvasDispose(clonecanvas);
+ imapaint_pixmap_free(canvas);
+ if(clonecanvas)
+ imapaint_pixmap_free(clonecanvas);
}
-void imagepaint_redraw_tool(void)
+void imapaint_redraw_tool(void)
{
- if(Gip.flag & IMAGEPAINT_DRAW_TOOL_DRAWING)
+ if(G.scene->toolsettings->imapaint.flag & IMAGEPAINT_DRAW_TOOL_DRAWING)
force_draw(0);
}
-static void imagepaint_redraw(int final, int painted)
+static void imapaint_redraw(int final, int painted)
{
if(!final && !painted) {
- imagepaint_redraw_tool();
+ imapaint_redraw_tool();
return;
}
@@ -166,66 +623,76 @@ static void imagepaint_redraw(int final, int painted)
allqueue(REDRAWHEADERS, 0);
}
-static void imagepaint_compute_uvco(short *mval, float *uv)
+static void imapaint_compute_uvco(short *mval, float *uv)
{
areamouseco_to_ipoco(G.v2d, mval, &uv[0], &uv[1]);
}
-static void imagepaint_paint_tool(IMG_BrushPtr *brush, IMG_CanvasPtr *canvas, IMG_CanvasPtr *clonecanvas, float *prevuv, float *uv)
+static void imapaint_paint_tool(ImagePaintBrush *brush, ImagePaintPixmap *canvas, ImagePaintPixmap *clonecanvas, float *prevuv, float *uv)
{
- int torus = Gip.flag & IMAGEPAINT_TORUS;
- ImagePaintTool *tool= &Gip.tool[Gip.current];
-
- if(Gip.current == IMAGEPAINT_SOFTEN)
- IMG_CanvasSoftenAt(canvas, prevuv[0], prevuv[1], tool->size, tool->rgba[3], tool->innerradius, torus);
- else if(Gip.current == IMAGEPAINT_SMEAR)
- IMG_CanvasSmear(canvas, prevuv[0], prevuv[1], uv[0], uv[1], tool->size, tool->rgba[3], tool->innerradius, torus);
- else if(Gip.current == IMAGEPAINT_CLONE) {
- float offx= Gip.clone.offset[0];
- float offy= Gip.clone.offset[1];
-
- IMG_CanvasCloneAt(canvas, clonecanvas, prevuv[0], prevuv[1], offx, offy, tool->size, tool->rgba[3], tool->innerradius);
- }
- else if(Gip.flag & IMAGEPAINT_TIMED)
- IMG_CanvasDrawLineUVEX(canvas, brush, uv[0], uv[1],uv[0], uv[1], torus);
+ ToolSettings *settings= G.scene->toolsettings;
+ Brush *curbrush= settings->imapaint.brush;
+
+ brush->torus= (settings->imapaint.flag & IMAGEPAINT_TORUS)? 1: 0;
+ brush->blend= curbrush->blend;
+
+ if(settings->imapaint.tool == PAINT_TOOL_SOFTEN)
+ imapaint_soften_sharpen(canvas, brush, prevuv, 0);
+ else if(settings->imapaint.tool == PAINT_TOOL_SMEAR)
+ imapaint_smear(canvas, brush, prevuv, uv);
+ else if(settings->imapaint.tool == PAINT_TOOL_CLONE)
+ imapaint_clone(canvas, clonecanvas, brush, prevuv, curbrush->clone.offset);
+ else if(curbrush->flag & BRUSH_AIRBRUSH)
+ imapaint_blend_line(canvas, brush, uv, uv);
else
- IMG_CanvasDrawLineUVEX(canvas, brush, prevuv[0], prevuv[1], uv[0], uv[1], torus);
+ imapaint_blend_line(canvas, brush, prevuv, uv);
}
void imagepaint_paint(short mousebutton)
{
- IMG_BrushPtr *brush;
- IMG_CanvasPtr *canvas, *clonecanvas;
+ ImagePaintBrush *brush;
+ ImagePaintPixmap *canvas, *clonecanvas=NULL;
short prevmval[2], mval[2];
double prevtime, curtime;
float prevuv[2], uv[2];
int paint= 0, moved= 0, firsttouch=1 ;
- ImagePaintTool *tool= &Gip.tool[Gip.current];
+ ToolSettings *settings= G.scene->toolsettings;
+ Brush *curbrush= settings->imapaint.brush;
- if(!imagepaint_init(&brush, &canvas, &clonecanvas))
+ if (!(canvas = imapaint_init_canvas(&clonecanvas))) {
+ if(G.sima->image && G.sima->image->packedfile)
+ error("Painting in packed images not supported");
+ return;
+ }
+ else if (!(brush = imapaint_init_brush())) {
+ imapaint_free_canvas(canvas, clonecanvas);
return;
+ }
getmouseco_areawin(prevmval);
prevtime = PIL_check_seconds_timer();
- Gip.flag |= IMAGEPAINT_DRAWING;
+ settings->imapaint.flag |= IMAGEPAINT_DRAWING;
while(get_mbut() & mousebutton) {
getmouseco_areawin(mval);
- moved= paint= (prevmval[0] != mval[0]) || (prevmval[1] != mval[1]);
+ if(firsttouch)
+ moved= paint= 1;
+ else
+ moved= paint= (prevmval[0] != mval[0]) || (prevmval[1] != mval[1]);
- if(Gip.flag & IMAGEPAINT_TIMED) {
+ if(settings->imapaint.flag & IMAGEPAINT_TIMED) {
/* see if need to draw because of timer */
curtime = PIL_check_seconds_timer();
- if(((curtime - prevtime) > (5.0/tool->timing)) || firsttouch) {
+ if(((curtime - prevtime) > (5.0/curbrush->timing)) || firsttouch) {
prevtime= curtime;
paint= 1;
}
else paint= 0;
}
- else if(paint) {
+ else if(paint && !firsttouch) {
/* check if we moved enough to draw */
float dmval[2], d, dlimit;
@@ -233,7 +700,7 @@ void imagepaint_paint(short mousebutton)
dmval[1]= prevmval[1] - mval[1];
d= sqrt(dmval[0]*dmval[0] + dmval[1]*dmval[1]);
- dlimit= tool->size*G.sima->zoom*tool->timing/200.0;
+ dlimit= curbrush->size*G.sima->zoom*curbrush->timing/200.0;
if (d < dlimit)
paint= 0;
@@ -241,10 +708,10 @@ void imagepaint_paint(short mousebutton)
if(paint) {
/* do the actual painting */
- imagepaint_compute_uvco(prevmval, prevuv);
- imagepaint_compute_uvco(mval, uv);
+ imapaint_compute_uvco(prevmval, prevuv);
+ imapaint_compute_uvco(mval, uv);
- imagepaint_paint_tool(brush, canvas, clonecanvas, prevuv, uv);
+ imapaint_paint_tool(brush, canvas, clonecanvas, prevuv, uv);
prevmval[0]= mval[0];
prevmval[1]= mval[1];
@@ -252,25 +719,27 @@ void imagepaint_paint(short mousebutton)
firsttouch = 0;
if(paint)
- imagepaint_redraw(0, paint);
- else if(moved && (Gip.flag & IMAGEPAINT_DRAW_TOOL))
- imagepaint_redraw(0, paint);
+ imapaint_redraw(0, paint);
+ else if(moved && (settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL))
+ imapaint_redraw(0, paint);
}
- Gip.flag &= ~IMAGEPAINT_DRAWING;
+ settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
- imagepaint_free(brush, canvas, clonecanvas);
+ imapaint_free_brush(brush);
+ imapaint_free_canvas(canvas, clonecanvas);
G.sima->image->ibuf->userflags |= IB_BITMAPDIRTY;
- imagepaint_redraw(1, 0);
+ imapaint_redraw(1, 0);
}
void imagepaint_pick(short mousebutton)
{
- ImagePaintTool *tool= &Gip.tool[Gip.current];
+ ToolSettings *settings= G.scene->toolsettings;
+ Brush *brush= settings->imapaint.brush;
- if(Gip.current == IMAGEPAINT_CLONE) {
- if(Gip.clone.image && Gip.clone.image->ibuf) {
+ if(brush && (settings->imapaint.tool == PAINT_TOOL_CLONE)) {
+ if(brush->clone.image && brush->clone.image->ibuf) {
short prevmval[2], mval[2];
float prevuv[2], uv[2];
@@ -281,11 +750,11 @@ void imagepaint_pick(short mousebutton)
if((prevmval[0] != mval[0]) || (prevmval[1] != mval[1]) ) {
/* mouse moved, so move the clone image */
- imagepaint_compute_uvco(prevmval, prevuv);
- imagepaint_compute_uvco(mval, uv);
+ imapaint_compute_uvco(prevmval, prevuv);
+ imapaint_compute_uvco(mval, uv);
- Gip.clone.offset[0] += uv[0] - prevuv[0];
- Gip.clone.offset[1] += uv[1] - prevuv[1];
+ brush->clone.offset[0] += uv[0] - prevuv[0];
+ brush->clone.offset[1] += uv[1] - prevuv[1];
force_draw(0);
@@ -295,13 +764,172 @@ void imagepaint_pick(short mousebutton)
}
}
}
- else {
+ else if(brush) {
extern VPaint Gvp;
sample_vpaint();
- tool->rgba[0]= Gvp.r;
- tool->rgba[1]= Gvp.g;
- tool->rgba[2]= Gvp.b;
+ brush->rgb[0]= Gvp.r;
+ brush->rgb[1]= Gvp.g;
+ brush->rgb[2]= Gvp.b;
+ }
+}
+
+/* these will be moved */
+int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect);
+int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short *xy, float *uv);
+
+void texturepaint_paint()
+{
+ Object *ob;
+ Mesh *me;
+ TFace *face, *face_old = 0;
+ short xy[2], xy_old[2];
+ //int a, index;
+ Image *img=NULL, *img_old = NULL;
+ ImagePaintBrush *brush;
+ ImagePaintPixmap *canvas = 0;
+ unsigned int face_index, mousebutton;
+ char *warn_packed_file = 0;
+ float uv[2], uv_old[2];
+ extern VPaint Gvp;
+ ImBuf *ibuf= NULL;
+
+ ob = OBACT;
+ if (!ob) {
+ error("No active object"); return;
+ }
+ if (!(ob->lay & G.vd->lay)) {
+ error("The active object is not in this layer"); return;
}
+ me = get_mesh(ob);
+ if (!me) {
+ error("The active object does not have a mesh obData"); return;
+ }
+
+ brush = imapaint_brush_new(Gvp.size, Gvp.size, &Gvp.r, Gvp.a, 0.5);
+ if (!brush) {
+ error("Can't create brush"); return;
+ }
+
+ persp(PERSP_VIEW);
+
+ if (U.flag & USER_LMOUSESELECT) mousebutton = R_MOUSE;
+ else mousebutton = L_MOUSE;
+
+ getmouseco_areawin(xy_old);
+ while (get_mbut() & mousebutton) {
+ getmouseco_areawin(xy);
+ /* Check if cursor has moved */
+ if ((xy[0] != xy_old[0]) || (xy[1] != xy_old[1])) {
+
+ /* Get face to draw on */
+ if (!facesel_face_pick(me, xy, &face_index, 0)) face = NULL;
+ else face = (((TFace*)me->tface)+face_index);
+
+ /* Check if this is another face. */
+ if (face != face_old) {
+ /* The active face changed, check the texture */
+ if (face) {
+ img = face->tpage;
+ ibuf = (img)? img->ibuf: NULL;
+ }
+ else {
+ img = 0;
+ }
+
+ if (img != img_old) {
+ /* Faces have different textures. Finish drawing in the old face. */
+ if (face_old && canvas) {
+ face_pick_uv(ob, me, face_old, xy, uv);
+ imapaint_blend_line(canvas, brush, uv_old, uv);
+ img_old->ibuf->userflags |= IB_BITMAPDIRTY;
+ /* Delete old canvas */
+ imapaint_pixmap_free(canvas);
+ canvas = 0;
+ }
+
+ /* Create new canvas and start drawing in the new face. */
+ if (img) {
+ if (ibuf && img->packedfile == 0) {
+ /* MAART: skipx is not set most of the times. Make a guess. */
+ canvas = imapaint_pixmap_new(ibuf->x, ibuf->y, (char*)ibuf->rect);
+ if (canvas) {
+ face_pick_uv(ob, me, face, xy_old, uv_old);
+ face_pick_uv(ob, me, face, xy, uv);
+ imapaint_blend_line(canvas, brush, uv_old, uv);
+ ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+ }
+ else {
+ if (img->packedfile) {
+ warn_packed_file = img->id.name + 2;
+ img = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Face changed and faces have the same texture. */
+ if (canvas) {
+ /* Finish drawing in the old face. */
+ if (face_old) {
+ face_pick_uv(ob, me, face_old, xy, uv);
+ imapaint_blend_line(canvas, brush, uv_old, uv);
+ img_old->ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+
+ /* Start drawing in the new face. */
+ if (face) {
+ face_pick_uv(ob, me, face, xy_old, uv_old);
+ face_pick_uv(ob, me, face, xy, uv);
+ imapaint_blend_line(canvas, brush, uv_old, uv);
+ ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+ }
+ }
+ }
+ else {
+ /* Same face, continue drawing */
+ if (face && canvas) {
+ /* Get the new (u,v) coordinates */
+ face_pick_uv(ob, me, face, xy, uv);
+ imapaint_blend_line(canvas, brush, uv_old, uv);
+ ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+ }
+
+ if (face && img) {
+ /* Make OpenGL aware of a change in the texture */
+ free_realtime_image(img);
+ /* Redraw the view */
+ scrarea_do_windraw(curarea);
+ screen_swapbuffers();
+ }
+
+ xy_old[0] = xy[0];
+ xy_old[1] = xy[1];
+ uv_old[0] = uv[0];
+ uv_old[1] = uv[1];
+ face_old = face;
+ img_old = img;
+ }
+ }
+
+ imapaint_brush_free(brush);
+ if (canvas) {
+ imapaint_pixmap_free(canvas);
+ canvas = 0;
+ }
+
+ if (warn_packed_file) {
+ error("Painting in packed images is not supported: %s", warn_packed_file);
+ }
+
+ persp(PERSP_WIN);
+
+ BIF_undo_push("UV face draw");
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWHEADERS, 0);
}
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index 235c9bcea4b..538f664663d 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -157,7 +157,6 @@
#include "BKE_depsgraph.h"
#include "BSE_trans_types.h"
-#include "IMG_Api.h"
#include "SYS_System.h" /* for the user def menu ... should move elsewhere. */
@@ -1012,7 +1011,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
vertex_paint();
}
else if (G.f & G_TEXTUREPAINT) {
- face_draw();
+ texturepaint_paint();
}
break;
case MIDDLEMOUSE:
diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk
index 70ec992917c..9920c2a509b 100644
--- a/source/nan_definitions.mk
+++ b/source/nan_definitions.mk
@@ -80,7 +80,6 @@ endif
export NAN_MEMUTIL ?= $(LCGDIR)/memutil
export NAN_CONTAINER ?= $(LCGDIR)/container
export NAN_ACTION ?= $(LCGDIR)/action
- export NAN_IMG ?= $(LCGDIR)/img
export NAN_GHOST ?= $(LCGDIR)/ghost
export NAN_TEST_VERBOSITY ?= 1
export NAN_BMFONT ?= $(LCGDIR)/bmfont