2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-02-19 23:53:40 +00:00
|
|
|
* ***** 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.
|
|
|
|
*
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-02-19 23:53:40 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: some of this file.
|
|
|
|
*
|
|
|
|
* Contributor(s): Jens Ole Wund (bjornmose), Campbell Barton (ideasman42)
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-02-27 20:29:51 +00:00
|
|
|
/** \file blender/editors/sculpt_paint/paint_image.c
|
|
|
|
* \ingroup edsculpt
|
2012-04-30 14:24:11 +00:00
|
|
|
* \brief Functions to paint images in 2D and 3D.
|
2011-02-27 20:29:51 +00:00
|
|
|
*/
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
#include <float.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#ifdef WIN32
|
2012-04-15 07:54:07 +00:00
|
|
|
# include "BLI_winstuff.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
#endif
|
2012-04-15 07:54:07 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
#include "BLI_math.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_linklist.h"
|
|
|
|
#include "BLI_memarena.h"
|
|
|
|
#include "BLI_threads.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
|
|
#include "PIL_time.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
2011-03-03 18:53:07 +00:00
|
|
|
#include "DNA_brush_types.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
#include "DNA_mesh_types.h"
|
2011-09-05 21:01:50 +00:00
|
|
|
#include "DNA_node_types.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
#include "DNA_object_types.h"
|
|
|
|
|
2011-11-05 13:00:39 +00:00
|
|
|
#include "BKE_camera.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
#include "BKE_context.h"
|
2011-03-03 18:53:07 +00:00
|
|
|
#include "BKE_depsgraph.h"
|
|
|
|
#include "BKE_DerivedMesh.h"
|
2010-03-06 19:46:21 +00:00
|
|
|
#include "BKE_idprop.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
#include "BKE_brush.h"
|
|
|
|
#include "BKE_image.h"
|
2011-03-03 18:53:07 +00:00
|
|
|
#include "BKE_library.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
#include "BKE_main.h"
|
|
|
|
#include "BKE_mesh.h"
|
2011-03-03 18:53:07 +00:00
|
|
|
#include "BKE_node.h"
|
|
|
|
#include "BKE_object.h"
|
2009-08-17 04:40:59 +00:00
|
|
|
#include "BKE_paint.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
#include "BKE_report.h"
|
2011-11-08 13:07:16 +00:00
|
|
|
#include "BKE_scene.h"
|
2013-01-04 03:07:25 +00:00
|
|
|
#include "BKE_colortools.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-01-17 21:08:25 +00:00
|
|
|
#include "BKE_tessmesh.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
#include "BIF_gl.h"
|
|
|
|
#include "BIF_glutil.h"
|
|
|
|
|
|
|
|
#include "UI_view2d.h"
|
|
|
|
|
|
|
|
#include "ED_image.h"
|
|
|
|
#include "ED_screen.h"
|
2009-11-04 20:19:41 +00:00
|
|
|
#include "ED_sculpt.h"
|
2011-11-08 13:07:16 +00:00
|
|
|
#include "ED_uvedit.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
#include "ED_view3d.h"
|
2012-01-17 16:31:13 +00:00
|
|
|
#include "ED_mesh.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "RNA_define.h"
|
2010-03-05 18:19:32 +00:00
|
|
|
#include "RNA_enum_types.h"
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
#include "GPU_draw.h"
|
|
|
|
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
#include "IMB_colormanagement.h"
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
#include "paint_intern.h"
|
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
#define IMAPAINT_TILE_BITS 6
|
|
|
|
#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS)
|
2010-03-06 19:46:21 +00:00
|
|
|
|
2009-11-04 20:19:41 +00:00
|
|
|
typedef struct UndoImageTile {
|
|
|
|
struct UndoImageTile *next, *prev;
|
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
char idname[MAX_ID_NAME]; /* name instead of pointer*/
|
2011-10-03 11:04:05 +00:00
|
|
|
char ibufname[IB_FILENAME_SIZE];
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-08-25 19:43:15 +00:00
|
|
|
union {
|
|
|
|
float *fp;
|
|
|
|
unsigned int *uint;
|
|
|
|
void *pt;
|
|
|
|
} rect;
|
2009-02-19 23:53:40 +00:00
|
|
|
int x, y;
|
2011-10-03 13:01:24 +00:00
|
|
|
|
2011-12-15 08:01:49 +00:00
|
|
|
short source, use_float;
|
2011-10-03 13:01:24 +00:00
|
|
|
char gen_type;
|
2009-11-04 20:19:41 +00:00
|
|
|
} UndoImageTile;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-07 12:11:38 +00:00
|
|
|
/* this is a static resource for non-globality,
|
|
|
|
* Maybe it should be exposed as part of the
|
|
|
|
* paint operation, but for now just give a public interface */
|
2009-02-19 23:53:40 +00:00
|
|
|
static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
|
|
|
|
|
2013-03-08 04:00:06 +00:00
|
|
|
ImagePaintPartialRedraw *get_imapaintpartial(void)
|
|
|
|
{
|
2013-03-07 12:11:38 +00:00
|
|
|
return &imapaintpartial;
|
|
|
|
}
|
|
|
|
|
2013-03-08 04:00:06 +00:00
|
|
|
void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr)
|
|
|
|
{
|
2013-03-07 12:11:38 +00:00
|
|
|
imapaintpartial = *ippr;
|
|
|
|
}
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
/* UNDO */
|
|
|
|
|
2009-11-04 20:19:41 +00:00
|
|
|
static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
|
|
|
/* copy or swap contents of tile->rect and region in ibuf->rect */
|
2012-03-28 03:47:33 +00:00
|
|
|
IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
|
|
|
|
tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ibuf->rect_float) {
|
2012-08-25 19:43:15 +00:00
|
|
|
SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-08-25 19:43:15 +00:00
|
|
|
SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (restore)
|
2012-03-28 03:47:33 +00:00
|
|
|
IMB_rectcpy(ibuf, tmpibuf, tile->x * IMAPAINT_TILE_SIZE,
|
|
|
|
tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-07 12:11:38 +00:00
|
|
|
void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
|
2009-11-04 20:19:41 +00:00
|
|
|
UndoImageTile *tile;
|
2009-02-19 23:53:40 +00:00
|
|
|
int allocsize;
|
2011-12-15 08:01:49 +00:00
|
|
|
short use_float = ibuf->rect_float ? 1 : 0;
|
2009-11-04 20:19:41 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
for (tile = lb->first; tile; tile = tile->next)
|
2012-03-24 06:38:07 +00:00
|
|
|
if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type && ima->source == tile->source)
|
|
|
|
if (tile->use_float == use_float)
|
2012-03-28 03:47:33 +00:00
|
|
|
if (strcmp(tile->idname, ima->id.name) == 0 && strcmp(tile->ibufname, ibuf->name) == 0)
|
2012-08-25 19:43:15 +00:00
|
|
|
return tile->rect.pt;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
if (*tmpibuf == NULL)
|
|
|
|
*tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
tile = MEM_callocN(sizeof(UndoImageTile), "UndoImageTile");
|
2011-10-19 23:10:54 +00:00
|
|
|
BLI_strncpy(tile->idname, ima->id.name, sizeof(tile->idname));
|
2012-03-28 03:47:33 +00:00
|
|
|
tile->x = x_tile;
|
|
|
|
tile->y = y_tile;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
|
|
|
|
allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
|
2012-08-25 19:43:15 +00:00
|
|
|
tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2011-10-19 23:10:54 +00:00
|
|
|
BLI_strncpy(tile->ibufname, ibuf->name, sizeof(tile->ibufname));
|
2011-10-03 11:04:05 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
tile->gen_type = ima->gen_type;
|
|
|
|
tile->source = ima->source;
|
|
|
|
tile->use_float = use_float;
|
2011-10-03 13:01:24 +00:00
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
undo_copy_tile(tile, *tmpibuf, ibuf, 0);
|
2009-11-04 20:19:41 +00:00
|
|
|
undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2009-11-04 20:19:41 +00:00
|
|
|
BLI_addtail(lb, tile);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-08-25 19:43:15 +00:00
|
|
|
return tile->rect.pt;
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
void image_undo_restore(bContext *C, ListBase *lb)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Main *bmain = CTX_data_main(C);
|
2009-02-19 23:53:40 +00:00
|
|
|
Image *ima = NULL;
|
|
|
|
ImBuf *ibuf, *tmpibuf;
|
2009-11-04 20:19:41 +00:00
|
|
|
UndoImageTile *tile;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
|
|
|
|
IB_rectfloat | IB_rect);
|
2013-03-10 17:40:55 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
for (tile = lb->first; tile; tile = tile->next) {
|
2011-12-15 08:01:49 +00:00
|
|
|
short use_float;
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
/* find image based on name, pointer becomes invalid with global undo */
|
2012-03-28 03:47:33 +00:00
|
|
|
if (ima && strcmp(tile->idname, ima->id.name) == 0) {
|
2011-10-03 12:56:33 +00:00
|
|
|
/* ima is valid */
|
|
|
|
}
|
2009-02-19 23:53:40 +00:00
|
|
|
else {
|
2012-03-28 03:47:33 +00:00
|
|
|
ima = BLI_findstring(&bmain->image, tile->idname, offsetof(ID, name));
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2012-11-15 15:59:58 +00:00
|
|
|
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
if (ima && ibuf && strcmp(tile->ibufname, ibuf->name) != 0) {
|
2011-10-03 11:04:05 +00:00
|
|
|
/* current ImBuf filename was changed, probably current frame
|
2012-03-03 16:31:46 +00:00
|
|
|
* was changed when paiting on image sequence, rather than storing
|
|
|
|
* full image user (which isn't so obvious, btw) try to find ImBuf with
|
|
|
|
* matched file name in list of already loaded images */
|
2011-10-03 11:04:05 +00:00
|
|
|
|
2012-11-15 15:59:58 +00:00
|
|
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
ibuf = BLI_findstring(&ima->ibufs, tile->ibufname, offsetof(ImBuf, name));
|
2011-10-03 11:04:05 +00:00
|
|
|
}
|
|
|
|
|
2012-11-15 15:59:58 +00:00
|
|
|
if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
|
|
|
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
2009-02-19 23:53:40 +00:00
|
|
|
continue;
|
2012-11-15 15:59:58 +00:00
|
|
|
}
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-11-15 15:59:58 +00:00
|
|
|
if (ima->gen_type != tile->gen_type || ima->source != tile->source) {
|
|
|
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
2011-10-03 13:01:24 +00:00
|
|
|
continue;
|
2012-11-15 15:59:58 +00:00
|
|
|
}
|
2011-10-03 13:01:24 +00:00
|
|
|
|
2012-02-03 20:12:21 +00:00
|
|
|
use_float = ibuf->rect_float ? 1 : 0;
|
|
|
|
|
2012-11-15 15:59:58 +00:00
|
|
|
if (use_float != tile->use_float) {
|
|
|
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
2011-12-15 08:01:49 +00:00
|
|
|
continue;
|
2012-11-15 15:59:58 +00:00
|
|
|
}
|
2011-12-15 08:01:49 +00:00
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
undo_copy_tile(tile, tmpibuf, ibuf, 1);
|
|
|
|
|
|
|
|
GPU_free_image(ima); /* force OpenGL reload */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ibuf->rect_float)
|
2011-01-17 18:16:10 +00:00
|
|
|
ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ibuf->mipmap[0])
|
2012-03-28 03:47:33 +00:00
|
|
|
ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
2012-11-15 15:59:58 +00:00
|
|
|
|
|
|
|
BKE_image_release_ibuf(ima, ibuf, NULL);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IMB_freeImBuf(tmpibuf);
|
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
void image_undo_free(ListBase *lb)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2009-11-04 20:19:41 +00:00
|
|
|
UndoImageTile *tile;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
for (tile = lb->first; tile; tile = tile->next)
|
2012-08-25 19:43:15 +00:00
|
|
|
MEM_freeN(tile->rect.pt);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
/* Imagepaint Partial Redraw & Dirty Region */
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
void imapaint_clear_partial_redraw(void)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2013-03-10 17:40:55 +00:00
|
|
|
memset(&imapaintpartial, 0, sizeof(imapaintpartial));
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2013-03-10 17:40:55 +00:00
|
|
|
ImBuf *tmpibuf = NULL;
|
|
|
|
int srcx = 0, srcy = 0, origx;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
if (w == 0 || h == 0)
|
|
|
|
return;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
if (!imapaintpartial.enabled) {
|
|
|
|
imapaintpartial.x1 = x;
|
|
|
|
imapaintpartial.y1 = y;
|
|
|
|
imapaintpartial.x2 = x + w;
|
|
|
|
imapaintpartial.y2 = y + h;
|
|
|
|
imapaintpartial.enabled = 1;
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-03-10 17:40:55 +00:00
|
|
|
imapaintpartial.x1 = min_ii(imapaintpartial.x1, x);
|
|
|
|
imapaintpartial.y1 = min_ii(imapaintpartial.y1, y);
|
|
|
|
imapaintpartial.x2 = max_ii(imapaintpartial.x2, x + w);
|
|
|
|
imapaintpartial.y2 = max_ii(imapaintpartial.y2, y + h);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
w = ((x + w - 1) >> IMAPAINT_TILE_BITS);
|
|
|
|
h = ((y + h - 1) >> IMAPAINT_TILE_BITS);
|
|
|
|
origx = (x >> IMAPAINT_TILE_BITS);
|
|
|
|
y = (y >> IMAPAINT_TILE_BITS);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
for (; y <= h; y++)
|
|
|
|
for (x = origx; x <= w; x++)
|
|
|
|
image_undo_push_tile(ima, ibuf, &tmpibuf, x, y);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
ibuf->userflags |= IB_BITMAPDIRTY;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
if (tmpibuf)
|
|
|
|
IMB_freeImBuf(tmpibuf);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2013-02-11 13:24:35 +00:00
|
|
|
if (imapaintpartial.x1 != imapaintpartial.x2 &&
|
|
|
|
imapaintpartial.y1 != imapaintpartial.y2)
|
|
|
|
{
|
2013-03-10 17:40:55 +00:00
|
|
|
IMB_partial_display_buffer_update_delayed(ibuf, imapaintpartial.x1, imapaintpartial.y1,
|
|
|
|
imapaintpartial.x2, imapaintpartial.y2);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
2013-03-10 17:40:55 +00:00
|
|
|
|
|
|
|
if (ibuf->mipmap[0])
|
|
|
|
ibuf->userflags |= IB_MIPMAP_INVALID;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
/* todo: should set_tpage create ->rect? */
|
|
|
|
if (texpaint || (sima && sima->lock)) {
|
|
|
|
int w = imapaintpartial.x2 - imapaintpartial.x1;
|
|
|
|
int h = imapaintpartial.y2 - imapaintpartial.y1;
|
|
|
|
/* Testing with partial update in uv editor too */
|
|
|
|
GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint);
|
|
|
|
}
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************ image paint poll ************************/
|
|
|
|
|
|
|
|
static Brush *image_paint_brush(bContext *C)
|
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
ToolSettings *settings = scene->toolsettings;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2009-08-17 04:40:59 +00:00
|
|
|
return paint_brush(&settings->imapaint.paint);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int image_paint_poll(bContext *C)
|
|
|
|
{
|
2009-08-16 01:25:53 +00:00
|
|
|
Object *obact = CTX_data_active_object(C);
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!image_paint_brush(C))
|
2009-02-19 23:53:40 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if ((obact && obact->mode & OB_MODE_TEXTURE_PAINT) && CTX_wm_region_view3d(C)) {
|
2009-02-19 23:53:40 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else {
|
2012-03-28 03:47:33 +00:00
|
|
|
SpaceImage *sima = CTX_wm_space_image(C);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (sima) {
|
2012-03-28 03:47:33 +00:00
|
|
|
ARegion *ar = CTX_wm_region(C);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-07-25 11:25:10 +00:00
|
|
|
if ((sima->mode == SI_MODE_PAINT) && ar->regiontype == RGN_TYPE_WINDOW) {
|
2009-02-19 23:53:40 +00:00
|
|
|
return 1;
|
2012-07-25 11:25:10 +00:00
|
|
|
}
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int image_paint_2d_clone_poll(bContext *C)
|
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Brush *brush = image_paint_brush(C);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!CTX_wm_region_view3d(C) && image_paint_poll(C))
|
|
|
|
if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE))
|
|
|
|
if (brush->clone.image)
|
2009-02-19 23:53:40 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************ paint operator ************************/
|
2013-03-06 22:54:44 +00:00
|
|
|
typedef enum TexPaintMode {
|
2009-02-19 23:53:40 +00:00
|
|
|
PAINT_MODE_2D,
|
|
|
|
PAINT_MODE_3D_PROJECT
|
2013-03-06 22:54:44 +00:00
|
|
|
} TexPaintMode;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
typedef struct PaintOperation {
|
2013-03-06 22:54:44 +00:00
|
|
|
TexPaintMode mode;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
void *custom_paint;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
int prevmouse[2];
|
|
|
|
double starttime;
|
|
|
|
|
|
|
|
ViewContext vc;
|
|
|
|
wmTimer *timer;
|
|
|
|
} PaintOperation;
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
void paint_brush_init_tex(Brush *brush)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2013-03-10 17:40:55 +00:00
|
|
|
/* init mtex nodes */
|
|
|
|
if (brush) {
|
|
|
|
MTex *mtex = &brush->mtex;
|
|
|
|
if (mtex->tex && mtex->tex->nodetree)
|
|
|
|
ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
void paint_brush_exit_tex(Brush *brush)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2013-03-10 17:40:55 +00:00
|
|
|
if (brush) {
|
|
|
|
MTex *mtex = &brush->mtex;
|
|
|
|
if (mtex->tex && mtex->tex->nodetree)
|
|
|
|
ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
|
2013-02-14 01:30:13 +00:00
|
|
|
}
|
2013-03-10 17:40:55 +00:00
|
|
|
}
|
2010-03-14 22:43:44 +00:00
|
|
|
|
2010-03-05 10:26:23 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
static void paint_redraw(const bContext *C, PaintOperation *pop, int final)
|
|
|
|
{
|
|
|
|
if (pop->mode == PAINT_MODE_2D) {
|
|
|
|
paint_2d_redraw(C, pop->custom_paint, final);
|
2010-03-05 10:26:23 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-03-10 17:40:55 +00:00
|
|
|
if (final) {
|
|
|
|
/* compositor listener deals with updating */
|
|
|
|
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, NULL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ED_region_tag_redraw(CTX_wm_region(C));
|
|
|
|
}
|
2010-03-05 10:26:23 +00:00
|
|
|
}
|
2011-03-03 18:53:07 +00:00
|
|
|
}
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static PaintOperation * texture_paint_init(bContext *C, wmOperator *op, const wmEvent *event)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
ToolSettings *settings = scene->toolsettings;
|
|
|
|
PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
|
2013-03-17 03:08:46 +00:00
|
|
|
int mode = RNA_enum_get(op->ptr, "mode");
|
2013-03-10 17:40:55 +00:00
|
|
|
view3d_set_viewcontext(C, &pop->vc);
|
|
|
|
|
|
|
|
/* TODO Should avoid putting this here. Instead, last position should be requested
|
|
|
|
* from stroke system. */
|
|
|
|
pop->prevmouse[0] = event->mval[0];
|
|
|
|
pop->prevmouse[1] = event->mval[1];
|
|
|
|
|
2010-11-17 06:30:06 +00:00
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
/* initialize from context */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (CTX_wm_region_view3d(C)) {
|
2013-03-06 19:54:43 +00:00
|
|
|
pop->mode = PAINT_MODE_3D_PROJECT;
|
2013-03-17 03:08:46 +00:00
|
|
|
pop->custom_paint = paint_proj_new_stroke(C, OBACT, pop->prevmouse, mode);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-03-10 17:40:55 +00:00
|
|
|
pop->mode = PAINT_MODE_2D;
|
|
|
|
pop->custom_paint = paint_2d_new_stroke(C, op);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
if (!pop->custom_paint) {
|
|
|
|
MEM_freeN(pop);
|
|
|
|
return NULL;
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
2013-01-04 02:54:38 +00:00
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
|
2010-07-23 14:46:31 +00:00
|
|
|
undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
|
2012-03-28 03:47:33 +00:00
|
|
|
image_undo_restore, image_undo_free);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-01-17 04:24:22 +00:00
|
|
|
{
|
|
|
|
UnifiedPaintSettings *ups = &settings->unified_paint_settings;
|
|
|
|
ups->draw_pressure = true;
|
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
return pop;
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2013-03-10 17:40:55 +00:00
|
|
|
PaintOperation *pop = paint_stroke_mode_data(stroke);
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
Brush *brush = paint_brush(&scene->toolsettings->imapaint.paint);
|
|
|
|
|
|
|
|
/* initial brush values. Maybe it should be considered moving these to stroke system */
|
|
|
|
float startsize = BKE_brush_size_get(scene, brush);
|
|
|
|
float startalpha = BKE_brush_alpha_get(scene, brush);
|
|
|
|
|
|
|
|
float mousef[2];
|
2009-02-19 23:53:40 +00:00
|
|
|
float pressure;
|
2013-03-10 17:40:55 +00:00
|
|
|
int mouse[2], redraw, eraser;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2009-08-18 21:14:36 +00:00
|
|
|
RNA_float_get_array(itemptr, "mouse", mousef);
|
2010-07-14 14:11:03 +00:00
|
|
|
mouse[0] = (int)(mousef[0]);
|
|
|
|
mouse[1] = (int)(mousef[1]);
|
2012-03-28 03:47:33 +00:00
|
|
|
pressure = RNA_float_get(itemptr, "pressure");
|
2013-03-10 17:40:55 +00:00
|
|
|
eraser = RNA_boolean_get(itemptr, "pen_flip");
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
if (BKE_brush_use_alpha_pressure(scene, brush))
|
|
|
|
BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure));
|
|
|
|
if (BKE_brush_use_size_pressure(scene, brush))
|
|
|
|
BKE_brush_size_set(scene, brush, max_ff(1.0f, startsize * pressure));
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (pop->mode == PAINT_MODE_3D_PROJECT) {
|
2013-03-17 03:08:46 +00:00
|
|
|
redraw = paint_proj_stroke(C, pop->custom_paint, pop->prevmouse, mouse);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
2012-10-21 05:46:41 +00:00
|
|
|
else {
|
2013-03-10 17:40:55 +00:00
|
|
|
redraw = paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
pop->prevmouse[0] = mouse[0];
|
|
|
|
pop->prevmouse[1] = mouse[1];
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
/* restore brush values */
|
|
|
|
BKE_brush_alpha_set(scene, brush, startalpha);
|
|
|
|
BKE_brush_size_set(scene, brush, startsize);
|
|
|
|
|
|
|
|
|
|
|
|
if (redraw)
|
|
|
|
paint_redraw(C, pop, 0);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2011-03-03 18:53:07 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
ToolSettings *settings = scene->toolsettings;
|
2013-03-10 17:40:55 +00:00
|
|
|
PaintOperation *pop = paint_stroke_mode_data(stroke);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-17 16:53:35 +00:00
|
|
|
paint_redraw(C, pop, 1);
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (pop->timer)
|
2009-11-01 00:06:53 +00:00
|
|
|
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pop->timer);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (pop->mode == PAINT_MODE_3D_PROJECT) {
|
2013-03-10 17:40:55 +00:00
|
|
|
paint_proj_stroke_done(pop->custom_paint);
|
2008-10-31 05:51:16 +00:00
|
|
|
}
|
2012-03-28 01:06:43 +00:00
|
|
|
else {
|
2013-03-10 17:40:55 +00:00
|
|
|
paint_2d_stroke_done(pop->custom_paint);
|
2012-03-28 01:06:43 +00:00
|
|
|
}
|
2013-03-06 19:54:43 +00:00
|
|
|
|
2009-11-04 20:19:41 +00:00
|
|
|
undo_paint_push_end(UNDO_PAINT_IMAGE);
|
2013-03-06 19:54:43 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
/* duplicate warning, see texpaint_init
|
2012-03-24 06:38:07 +00:00
|
|
|
if (pop->s.warnmultifile)
|
2009-02-19 23:53:40 +00:00
|
|
|
BKE_reportf(op->reports, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (pop->s.warnpackedfile)
|
2009-02-19 23:53:40 +00:00
|
|
|
BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
|
2013-03-10 17:40:55 +00:00
|
|
|
*/
|
2009-02-19 23:53:40 +00:00
|
|
|
MEM_freeN(pop);
|
2013-01-17 04:24:22 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
|
|
|
ups->draw_pressure = false;
|
|
|
|
}
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
static int paint_stroke_test_start(bContext *UNUSED(C), wmOperator *UNUSED(op), const float UNUSED(mouse[2]))
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2013-03-10 17:40:55 +00:00
|
|
|
return true;
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
|
|
|
PaintOperation *pop;
|
2013-03-10 17:40:55 +00:00
|
|
|
struct PaintStroke *stroke;
|
|
|
|
int retval;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
if (!(pop = texture_paint_init(C, op, event))) {
|
2009-02-19 23:53:40 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2013-01-17 04:24:22 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
stroke = op->customdata = paint_stroke_new(C, NULL, paint_stroke_test_start,
|
|
|
|
paint_stroke_update_step,
|
|
|
|
paint_stroke_done, event->type);
|
|
|
|
paint_stroke_set_mode_data(stroke, pop);
|
|
|
|
/* add modal handler */
|
2009-10-22 23:22:05 +00:00
|
|
|
WM_event_add_modal_handler(C, op);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
retval = op->type->modal(C, op, event);
|
|
|
|
OPERATOR_RETVAL_CHECK(retval);
|
|
|
|
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PAINT_OT_image_paint(wmOperatorType *ot)
|
|
|
|
{
|
2013-03-17 03:08:46 +00:00
|
|
|
static EnumPropertyItem stroke_mode_items[] = {
|
|
|
|
{BRUSH_STROKE_NORMAL, "NORMAL", 0, "Normal", "Apply brush normally"},
|
|
|
|
{BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"},
|
|
|
|
{0}
|
|
|
|
};
|
2013-03-10 17:40:55 +00:00
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Image Paint";
|
|
|
|
ot->idname = "PAINT_OT_image_paint";
|
2012-05-05 17:10:51 +00:00
|
|
|
ot->description = "Paint a stroke into the image";
|
2013-03-10 17:40:55 +00:00
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
/* api callbacks */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->invoke = paint_invoke;
|
2013-03-10 17:40:55 +00:00
|
|
|
ot->modal = paint_stroke_modal;
|
|
|
|
/* ot->exec = paint_exec; <-- needs stroke property */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = image_paint_poll;
|
2013-03-10 17:40:55 +00:00
|
|
|
ot->cancel = paint_stroke_cancel;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
/* flags */
|
2013-03-10 17:40:55 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2013-03-17 03:08:46 +00:00
|
|
|
RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL,
|
|
|
|
"Paint Stroke Mode",
|
|
|
|
"Action taken when a paint stroke is made");
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
|
|
|
|
}
|
|
|
|
|
2013-03-10 17:40:55 +00:00
|
|
|
|
2013-03-10 18:46:31 +00:00
|
|
|
int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
|
2009-02-22 19:31:25 +00:00
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
2009-02-22 19:31:25 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!rv3d) {
|
2012-03-28 03:47:33 +00:00
|
|
|
SpaceImage *sima = CTX_wm_space_image(C);
|
|
|
|
ARegion *ar = CTX_wm_region(C);
|
2009-02-22 19:31:25 +00:00
|
|
|
|
2012-10-29 19:47:26 +00:00
|
|
|
if (sima->mode == SI_MODE_PAINT) {
|
|
|
|
ED_space_image_get_zoom(sima, ar, zoomx, zoomy);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2009-02-22 19:31:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*zoomx = *zoomy = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************ cursor drawing *******************************/
|
|
|
|
|
2013-03-03 16:33:39 +00:00
|
|
|
void brush_drawcursor_texpaint_uvsculpt(bContext *C, int x, int y, void *UNUSED(customdata))
|
2009-02-22 19:31:25 +00:00
|
|
|
{
|
2011-06-06 08:43:17 +00:00
|
|
|
#define PX_SIZE_FADE_MAX 12.0f
|
|
|
|
#define PX_SIZE_FADE_MIN 4.0f
|
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2012-10-23 03:38:26 +00:00
|
|
|
//Brush *brush = image_paint_brush(C);
|
2012-06-04 07:29:45 +00:00
|
|
|
Paint *paint = paint_get_active_from_context(C);
|
2012-03-28 03:47:33 +00:00
|
|
|
Brush *brush = paint_brush(paint);
|
2009-02-22 19:31:25 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (paint && brush && paint->flags & PAINT_SHOW_BRUSH) {
|
2009-02-22 19:31:25 +00:00
|
|
|
float zoomx, zoomy;
|
2012-05-05 00:58:22 +00:00
|
|
|
const float size = (float)BKE_brush_size_get(scene, brush);
|
2012-03-16 21:26:18 +00:00
|
|
|
short use_zoom;
|
2012-01-17 16:31:13 +00:00
|
|
|
float pixel_size;
|
2012-03-28 03:47:33 +00:00
|
|
|
float alpha = 0.5f;
|
2010-07-22 18:56:46 +00:00
|
|
|
|
2012-10-29 19:47:26 +00:00
|
|
|
use_zoom = get_imapaint_zoom(C, &zoomx, &zoomy);
|
2012-01-17 16:31:13 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (use_zoom) {
|
2012-10-23 13:28:22 +00:00
|
|
|
pixel_size = size * max_ff(zoomx, zoomy);
|
2012-01-17 16:31:13 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
pixel_size = size;
|
|
|
|
}
|
|
|
|
|
2012-07-18 11:01:23 +00:00
|
|
|
/* fade out the brush (cheap trick to work around brush interfering with sampling [#])*/
|
2012-03-24 06:38:07 +00:00
|
|
|
if (pixel_size < PX_SIZE_FADE_MIN) {
|
2010-07-22 18:56:46 +00:00
|
|
|
return;
|
2011-06-06 08:43:17 +00:00
|
|
|
}
|
|
|
|
else if (pixel_size < PX_SIZE_FADE_MAX) {
|
|
|
|
alpha *= (pixel_size - PX_SIZE_FADE_MIN) / (PX_SIZE_FADE_MAX - PX_SIZE_FADE_MIN);
|
|
|
|
}
|
2010-07-22 18:56:46 +00:00
|
|
|
|
2009-02-22 19:31:25 +00:00
|
|
|
glPushMatrix();
|
|
|
|
|
|
|
|
glTranslatef((float)x, (float)y, 0.0f);
|
|
|
|
|
2012-07-18 11:01:23 +00:00
|
|
|
/* No need to scale for uv sculpting, on the contrary it might be useful to keep un-scaled */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (use_zoom)
|
2009-02-22 19:31:25 +00:00
|
|
|
glScalef(zoomx, zoomy, 1.0f);
|
|
|
|
|
2011-06-06 08:43:17 +00:00
|
|
|
glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha);
|
2012-03-28 03:47:33 +00:00
|
|
|
glEnable(GL_LINE_SMOOTH);
|
2009-02-22 19:31:25 +00:00
|
|
|
glEnable(GL_BLEND);
|
2013-01-17 04:24:22 +00:00
|
|
|
{
|
|
|
|
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
|
|
|
/* hrmf, duplicate paint_draw_cursor logic here */
|
|
|
|
if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) {
|
|
|
|
/* inner at full alpha */
|
|
|
|
glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size * ups->pressure_value, 40);
|
|
|
|
/* outer at half alpha */
|
|
|
|
glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha * 0.5f);
|
|
|
|
}
|
|
|
|
}
|
2012-03-28 03:47:33 +00:00
|
|
|
glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size, 40);
|
2009-02-22 19:31:25 +00:00
|
|
|
glDisable(GL_BLEND);
|
2012-03-28 03:47:33 +00:00
|
|
|
glDisable(GL_LINE_SMOOTH);
|
2010-07-22 18:56:46 +00:00
|
|
|
|
2009-02-22 19:31:25 +00:00
|
|
|
glPopMatrix();
|
|
|
|
}
|
2011-06-06 08:43:17 +00:00
|
|
|
#undef PX_SIZE_FADE_MAX
|
|
|
|
#undef PX_SIZE_FADE_MIN
|
2009-02-22 19:31:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void toggle_paint_cursor(bContext *C, int enable)
|
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
wmWindowManager *wm = CTX_wm_manager(C);
|
2012-01-17 18:01:16 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2012-03-28 03:47:33 +00:00
|
|
|
ToolSettings *settings = scene->toolsettings;
|
2009-02-22 19:31:25 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (settings->imapaint.paintcursor && !enable) {
|
2012-01-17 18:01:16 +00:00
|
|
|
WM_paint_cursor_end(wm, settings->imapaint.paintcursor);
|
2009-02-22 19:31:25 +00:00
|
|
|
settings->imapaint.paintcursor = NULL;
|
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
else if (enable)
|
2013-03-03 16:33:39 +00:00
|
|
|
settings->imapaint.paintcursor =
|
|
|
|
WM_paint_cursor_activate(wm, image_paint_poll, brush_drawcursor_texpaint_uvsculpt, NULL);
|
2009-02-22 19:31:25 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 00:42:19 +00:00
|
|
|
/* enable the paint cursor if it isn't already.
|
2012-03-03 16:31:46 +00:00
|
|
|
*
|
|
|
|
* purpose is to make sure the paint cursor is shown if paint
|
|
|
|
* mode is enabled in the image editor. the paint poll will
|
|
|
|
* ensure that the cursor is hidden when not in paint mode */
|
2010-10-20 00:42:19 +00:00
|
|
|
void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
|
|
|
|
{
|
2012-08-31 13:04:03 +00:00
|
|
|
wmWindow *win;
|
|
|
|
ScrArea *sa;
|
2010-10-20 00:42:19 +00:00
|
|
|
ImagePaintSettings *imapaint = &settings->imapaint;
|
2012-08-31 13:04:03 +00:00
|
|
|
int enabled = FALSE;
|
2010-10-20 00:42:19 +00:00
|
|
|
|
2012-08-31 13:04:03 +00:00
|
|
|
for (win = wm->windows.first; win; win = win->next)
|
|
|
|
for (sa = win->screen->areabase.first; sa; sa = sa->next)
|
|
|
|
if (sa->spacetype == SPACE_IMAGE)
|
2012-09-30 06:12:47 +00:00
|
|
|
if (((SpaceImage *)sa->spacedata.first)->mode == SI_MODE_PAINT)
|
2012-08-31 13:04:03 +00:00
|
|
|
enabled = TRUE;
|
|
|
|
|
|
|
|
if (enabled) {
|
|
|
|
BKE_paint_init(&imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT);
|
|
|
|
|
|
|
|
if (!imapaint->paintcursor) {
|
|
|
|
imapaint->paintcursor =
|
2012-09-14 06:17:14 +00:00
|
|
|
WM_paint_cursor_activate(wm, image_paint_poll,
|
2013-03-03 16:33:39 +00:00
|
|
|
brush_drawcursor_texpaint_uvsculpt, NULL);
|
2012-08-31 13:04:03 +00:00
|
|
|
}
|
2010-10-20 00:42:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
/************************ grab clone operator ************************/
|
|
|
|
|
|
|
|
typedef struct GrabClone {
|
|
|
|
float startoffset[2];
|
|
|
|
int startx, starty;
|
|
|
|
} GrabClone;
|
|
|
|
|
|
|
|
static void grab_clone_apply(bContext *C, wmOperator *op)
|
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Brush *brush = image_paint_brush(C);
|
2009-02-19 23:53:40 +00:00
|
|
|
float delta[2];
|
|
|
|
|
|
|
|
RNA_float_get_array(op->ptr, "delta", delta);
|
2010-03-05 22:01:42 +00:00
|
|
|
add_v2_v2(brush->clone.offset, delta);
|
2009-02-19 23:53:40 +00:00
|
|
|
ED_region_tag_redraw(CTX_wm_region(C));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int grab_clone_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
grab_clone_apply(C, op);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static int grab_clone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Brush *brush = image_paint_brush(C);
|
2009-02-19 23:53:40 +00:00
|
|
|
GrabClone *cmv;
|
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
cmv = MEM_callocN(sizeof(GrabClone), "GrabClone");
|
2010-03-05 22:01:42 +00:00
|
|
|
copy_v2_v2(cmv->startoffset, brush->clone.offset);
|
2012-03-28 03:47:33 +00:00
|
|
|
cmv->startx = event->x;
|
|
|
|
cmv->starty = event->y;
|
|
|
|
op->customdata = cmv;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2009-10-22 23:22:05 +00:00
|
|
|
WM_event_add_modal_handler(C, op);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
}
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Brush *brush = image_paint_brush(C);
|
|
|
|
ARegion *ar = CTX_wm_region(C);
|
|
|
|
GrabClone *cmv = op->customdata;
|
2009-02-19 23:53:40 +00:00
|
|
|
float startfx, startfy, fx, fy, delta[2];
|
2012-03-28 03:47:33 +00:00
|
|
|
int xmin = ar->winrct.xmin, ymin = ar->winrct.ymin;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
switch (event->type) {
|
2009-02-19 23:53:40 +00:00
|
|
|
case LEFTMOUSE:
|
|
|
|
case MIDDLEMOUSE:
|
|
|
|
case RIGHTMOUSE: // XXX hardcoded
|
|
|
|
MEM_freeN(op->customdata);
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
case MOUSEMOVE:
|
|
|
|
/* mouse moved, so move the clone image */
|
|
|
|
UI_view2d_region_to_view(&ar->v2d, cmv->startx - xmin, cmv->starty - ymin, &startfx, &startfy);
|
|
|
|
UI_view2d_region_to_view(&ar->v2d, event->x - xmin, event->y - ymin, &fx, &fy);
|
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
delta[0] = fx - startfx;
|
|
|
|
delta[1] = fy - startfy;
|
2009-02-19 23:53:40 +00:00
|
|
|
RNA_float_set_array(op->ptr, "delta", delta);
|
|
|
|
|
2010-03-05 22:01:42 +00:00
|
|
|
copy_v2_v2(brush->clone.offset, cmv->startoffset);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
grab_clone_apply(C, op);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int grab_clone_cancel(bContext *UNUSED(C), wmOperator *op)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
|
|
|
MEM_freeN(op->customdata);
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PAINT_OT_grab_clone(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Grab Clone";
|
|
|
|
ot->idname = "PAINT_OT_grab_clone";
|
2012-05-05 17:10:51 +00:00
|
|
|
ot->description = "Move the clone source image";
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = grab_clone_exec;
|
|
|
|
ot->invoke = grab_clone_invoke;
|
|
|
|
ot->modal = grab_clone_modal;
|
|
|
|
ot->cancel = grab_clone_cancel;
|
|
|
|
ot->poll = image_paint_2d_clone_poll;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
/* flags */
|
2012-03-28 03:47:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
/* properties */
|
2011-09-19 12:26:20 +00:00
|
|
|
RNA_def_float_vector(ot->srna, "delta", 2, NULL, -FLT_MAX, FLT_MAX, "Delta", "Delta offset of clone image in 0.0..1.0 coordinates", -1.0f, 1.0f);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************** sample color operator ********************/
|
|
|
|
|
|
|
|
static int sample_color_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Brush *brush = image_paint_brush(C);
|
|
|
|
ARegion *ar = CTX_wm_region(C);
|
2009-02-19 23:53:40 +00:00
|
|
|
int location[2];
|
|
|
|
|
|
|
|
RNA_int_get_array(op->ptr, "location", location);
|
2012-06-04 07:29:45 +00:00
|
|
|
paint_sample_color(C, ar, location[0], location[1]);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
2009-02-19 23:53:40 +00:00
|
|
|
{
|
2011-05-20 07:40:05 +00:00
|
|
|
RNA_int_set_array(op->ptr, "location", event->mval);
|
|
|
|
sample_color_exec(C, op);
|
2010-09-16 21:03:07 +00:00
|
|
|
|
|
|
|
WM_event_add_modal_handler(C, op);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2010-09-16 21:03:07 +00:00
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
}
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
2010-09-16 21:03:07 +00:00
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
switch (event->type) {
|
2010-09-16 21:03:07 +00:00
|
|
|
case LEFTMOUSE:
|
|
|
|
case RIGHTMOUSE: // XXX hardcoded
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
case MOUSEMOVE:
|
2011-05-20 07:40:05 +00:00
|
|
|
RNA_int_set_array(op->ptr, "location", event->mval);
|
|
|
|
sample_color_exec(C, op);
|
2010-09-16 21:03:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2011-05-02 12:32:28 +00:00
|
|
|
/* same as image_paint_poll but fail when face mask mode is enabled */
|
|
|
|
static int image_paint_sample_color_poll(bContext *C)
|
|
|
|
{
|
2012-03-24 06:38:07 +00:00
|
|
|
if (image_paint_poll(C)) {
|
|
|
|
if (CTX_wm_view3d(C)) {
|
2011-05-02 12:32:28 +00:00
|
|
|
Object *obact = CTX_data_active_object(C);
|
|
|
|
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
|
2012-05-05 16:03:57 +00:00
|
|
|
Mesh *me = BKE_mesh_from_object(obact);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (me) {
|
2012-12-22 14:25:34 +00:00
|
|
|
return !(me->editflag & ME_EDIT_PAINT_FACE_SEL);
|
2011-05-02 12:32:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
void PAINT_OT_sample_color(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Sample Color";
|
|
|
|
ot->idname = "PAINT_OT_sample_color";
|
2012-05-05 17:10:51 +00:00
|
|
|
ot->description = "Use the mouse to sample a color in the image";
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sample_color_exec;
|
|
|
|
ot->invoke = sample_color_invoke;
|
|
|
|
ot->modal = sample_color_modal;
|
|
|
|
ot->poll = image_paint_sample_color_poll;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
/* flags */
|
2012-03-28 03:47:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
/* properties */
|
2011-09-19 12:26:20 +00:00
|
|
|
RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "Cursor location in region coordinates", 0, 16384);
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************** texture paint toggle operator ********************/
|
|
|
|
|
|
|
|
static int texture_paint_toggle_poll(bContext *C)
|
|
|
|
{
|
2012-03-24 06:38:07 +00:00
|
|
|
if (CTX_data_edit_object(C))
|
2009-02-19 23:53:40 +00:00
|
|
|
return 0;
|
2012-03-28 03:47:33 +00:00
|
|
|
if (CTX_data_active_object(C) == NULL)
|
2009-02-19 23:53:40 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2012-03-28 03:47:33 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
Mesh *me = NULL;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
if (ob == NULL)
|
2009-02-19 23:53:40 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2012-05-05 14:03:12 +00:00
|
|
|
if (BKE_object_obdata_is_libdata(ob)) {
|
2012-10-26 17:32:50 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata");
|
2009-02-19 23:53:40 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2012-05-05 16:03:57 +00:00
|
|
|
me = BKE_mesh_from_object(ob);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!(ob->mode & OB_MODE_TEXTURE_PAINT) && !me) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Can only enter texture paint mode for mesh objects");
|
2009-02-19 23:53:40 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ob->mode & OB_MODE_TEXTURE_PAINT) {
|
2009-08-16 01:25:53 +00:00
|
|
|
ob->mode &= ~OB_MODE_TEXTURE_PAINT;
|
2009-03-17 21:44:58 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (U.glreslimit != 0)
|
2009-03-17 21:44:58 +00:00
|
|
|
GPU_free_images();
|
2009-02-19 23:53:40 +00:00
|
|
|
GPU_paint_set_mipmap(1);
|
2009-03-17 21:44:58 +00:00
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
toggle_paint_cursor(C, 0);
|
|
|
|
}
|
|
|
|
else {
|
2009-08-16 01:25:53 +00:00
|
|
|
ob->mode |= OB_MODE_TEXTURE_PAINT;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-03-28 03:47:33 +00:00
|
|
|
if (me->mtface == NULL)
|
|
|
|
me->mtface = CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
|
|
|
|
NULL, me->totface);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
2012-07-25 13:44:59 +00:00
|
|
|
BKE_paint_init(&scene->toolsettings->imapaint.paint, PAINT_CURSOR_TEXTURE_PAINT);
|
2009-03-17 21:44:58 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (U.glreslimit != 0)
|
2009-03-17 21:44:58 +00:00
|
|
|
GPU_free_images();
|
2009-02-19 23:53:40 +00:00
|
|
|
GPU_paint_set_mipmap(0);
|
2009-03-17 21:44:58 +00:00
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
toggle_paint_cursor(C, 1);
|
|
|
|
}
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2012-03-28 03:47:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Texture Paint Toggle";
|
|
|
|
ot->idname = "PAINT_OT_texture_paint_toggle";
|
2012-05-05 17:10:51 +00:00
|
|
|
ot->description = "Toggle texture paint mode in 3D view";
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = texture_paint_toggle_exec;
|
|
|
|
ot->poll = texture_paint_toggle_poll;
|
2009-02-19 23:53:40 +00:00
|
|
|
|
|
|
|
/* flags */
|
2012-03-28 03:47:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-02-19 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2009-02-23 16:31:58 +00:00
|
|
|
static int texture_paint_poll(bContext *C)
|
|
|
|
{
|
2012-03-24 06:38:07 +00:00
|
|
|
if (texture_paint_toggle_poll(C))
|
|
|
|
if (CTX_data_active_object(C)->mode & OB_MODE_TEXTURE_PAINT)
|
2009-02-23 16:31:58 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-10-22 23:22:05 +00:00
|
|
|
int image_texture_paint_poll(bContext *C)
|
|
|
|
{
|
|
|
|
return (texture_paint_poll(C) || image_paint_poll(C));
|
|
|
|
}
|
|
|
|
|
2009-11-01 00:06:53 +00:00
|
|
|
int facemask_paint_poll(bContext *C)
|
|
|
|
{
|
|
|
|
return paint_facesel_test(CTX_data_active_object(C));
|
|
|
|
}
|
2009-11-04 20:19:41 +00:00
|
|
|
|
2011-07-12 19:06:06 +00:00
|
|
|
int vert_paint_poll(bContext *C)
|
|
|
|
{
|
|
|
|
return paint_vertsel_test(CTX_data_active_object(C));
|
|
|
|
}
|
2011-09-18 17:10:28 +00:00
|
|
|
|
2011-07-18 17:38:17 +00:00
|
|
|
int mask_paint_poll(bContext *C)
|
|
|
|
{
|
|
|
|
return paint_facesel_test(CTX_data_active_object(C)) || paint_vertsel_test(CTX_data_active_object(C));
|
|
|
|
}
|
2010-03-06 19:46:21 +00:00
|
|
|
|