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:
-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