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:
authorJeroen Bakker <jeroen@blender.org>2022-02-22 11:57:11 +0300
committerJeroen Bakker <jeroen@blender.org>2022-02-22 12:00:03 +0300
commit1d4ed6ba2964eb6ec9bf0e0648f8bb60ab7a914a (patch)
tree42a08f5efaaf685894e51109203aca146b422b03 /source/blender/editors/sculpt_paint/paint_image.c
parent1ec02b869587cf31414f8c2146614bc65a21725b (diff)
Convert paint_image to cc.
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_image.c')
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c1381
1 files changed, 0 insertions, 1381 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
deleted file mode 100644
index 2df42e6f532..00000000000
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ /dev/null
@@ -1,1381 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later
- * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
-
-/** \file
- * \ingroup edsculpt
- * \brief Functions to paint images in 2D and 3D.
- */
-
-#include <float.h>
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-
-#include "BLT_translation.h"
-
-#include "IMB_imbuf.h"
-#include "IMB_imbuf_types.h"
-
-#include "DNA_brush_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-
-#include "BKE_brush.h"
-#include "BKE_colorband.h"
-#include "BKE_context.h"
-#include "BKE_image.h"
-#include "BKE_main.h"
-#include "BKE_material.h"
-#include "BKE_mesh.h"
-#include "BKE_node.h"
-#include "BKE_paint.h"
-#include "BKE_undo_system.h"
-
-#include "NOD_texture.h"
-
-#include "DEG_depsgraph.h"
-
-#include "UI_interface.h"
-#include "UI_view2d.h"
-
-#include "ED_image.h"
-#include "ED_object.h"
-#include "ED_paint.h"
-#include "ED_screen.h"
-#include "ED_view3d.h"
-
-#include "WM_api.h"
-#include "WM_message.h"
-#include "WM_toolsystem.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "GPU_immediate.h"
-#include "GPU_state.h"
-
-#include "IMB_colormanagement.h"
-
-#include "paint_intern.h"
-
-/**
- * This is a static resource for non-global access.
- * Maybe it should be exposed as part of the paint operation,
- * but for now just give a public interface.
- */
-static ImagePaintPartialRedraw imapaintpartial = {{0}};
-
-ImagePaintPartialRedraw *get_imapaintpartial(void)
-{
- return &imapaintpartial;
-}
-
-void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr)
-{
- imapaintpartial = *ippr;
-}
-
-/* Imagepaint Partial Redraw & Dirty Region */
-
-void ED_imapaint_clear_partial_redraw(void)
-{
- BLI_rcti_init_minmax(&imapaintpartial.dirty_region);
-}
-
-void imapaint_region_tiles(
- ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th)
-{
- int srcx = 0, srcy = 0;
-
- IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
-
- *tw = ((x + w - 1) >> ED_IMAGE_UNDO_TILE_BITS);
- *th = ((y + h - 1) >> ED_IMAGE_UNDO_TILE_BITS);
- *tx = (x >> ED_IMAGE_UNDO_TILE_BITS);
- *ty = (y >> ED_IMAGE_UNDO_TILE_BITS);
-}
-
-void ED_imapaint_dirty_region(
- Image *ima, ImBuf *ibuf, ImageUser *iuser, int x, int y, int w, int h, bool find_old)
-{
- ImBuf *tmpibuf = NULL;
- int tilex, tiley, tilew, tileh, tx, ty;
- int srcx = 0, srcy = 0;
-
- IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
-
- if (w == 0 || h == 0) {
- return;
- }
-
- rcti rect_to_merge;
- BLI_rcti_init(&rect_to_merge, x, x + w, y, y + h);
- BLI_rcti_do_minmax_rcti(&imapaintpartial.dirty_region, &rect_to_merge);
-
- imapaint_region_tiles(ibuf, x, y, w, h, &tilex, &tiley, &tilew, &tileh);
-
- ListBase *undo_tiles = ED_image_paint_tile_list_get();
-
- for (ty = tiley; ty <= tileh; ty++) {
- for (tx = tilex; tx <= tilew; tx++) {
- ED_image_paint_tile_push(
- undo_tiles, ima, ibuf, &tmpibuf, iuser, tx, ty, NULL, NULL, false, find_old);
- }
- }
-
- BKE_image_mark_dirty(ima, ibuf);
-
- if (tmpibuf) {
- IMB_freeImBuf(tmpibuf);
- }
-}
-
-void imapaint_image_update(
- SpaceImage *sima, Image *image, ImBuf *ibuf, ImageUser *iuser, short texpaint)
-{
- if (BLI_rcti_is_empty(&imapaintpartial.dirty_region)) {
- return;
- }
-
- if (ibuf->mipmap[0]) {
- ibuf->userflags |= IB_MIPMAP_INVALID;
- }
-
- IMB_partial_display_buffer_update_delayed(ibuf,
- imapaintpartial.dirty_region.xmin,
- imapaintpartial.dirty_region.ymin,
- imapaintpartial.dirty_region.xmax,
- imapaintpartial.dirty_region.ymax);
-
- /* TODO: should set_tpage create ->rect? */
- if (texpaint || (sima && sima->lock)) {
- const int w = BLI_rcti_size_x(&imapaintpartial.dirty_region);
- const int h = BLI_rcti_size_y(&imapaintpartial.dirty_region);
- /* Testing with partial update in uv editor too */
- BKE_image_update_gputexture(
- image, iuser, imapaintpartial.dirty_region.xmin, imapaintpartial.dirty_region.ymin, w, h);
- }
-}
-
-BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
-{
- int i, j;
- BlurKernel *kernel = MEM_mallocN(sizeof(BlurKernel), "blur kernel");
- float radius;
- int side;
- eBlurKernelType type = br->blur_mode;
-
- if (proj) {
- radius = 0.5f;
-
- side = kernel->side = 2;
- kernel->side_squared = kernel->side * kernel->side;
- kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
- kernel->pixel_len = radius;
- }
- else {
- if (br->blur_kernel_radius <= 0) {
- br->blur_kernel_radius = 1;
- }
-
- radius = br->blur_kernel_radius;
-
- side = kernel->side = radius * 2 + 1;
- kernel->side_squared = kernel->side * kernel->side;
- kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
- kernel->pixel_len = br->blur_kernel_radius;
- }
-
- switch (type) {
- case KERNEL_BOX:
- for (i = 0; i < kernel->side_squared; i++) {
- kernel->wdata[i] = 1.0;
- }
- break;
-
- case KERNEL_GAUSSIAN: {
- /* at 3.0 standard deviations distance, kernel is about zero */
- float standard_dev = radius / 3.0f;
-
- /* make the necessary adjustment to the value for use in the normal distribution formula */
- standard_dev = -standard_dev * standard_dev * 2;
-
- for (i = 0; i < side; i++) {
- for (j = 0; j < side; j++) {
- float idist = radius - i;
- float jdist = radius - j;
- float value = exp((idist * idist + jdist * jdist) / standard_dev);
-
- kernel->wdata[i + j * side] = value;
- }
- }
-
- break;
- }
-
- default:
- printf("unidentified kernel type, aborting\n");
- MEM_freeN(kernel->wdata);
- MEM_freeN(kernel);
- return NULL;
- }
-
- return kernel;
-}
-
-void paint_delete_blur_kernel(BlurKernel *kernel)
-{
- if (kernel->wdata) {
- MEM_freeN(kernel->wdata);
- }
-}
-
-/************************ image paint poll ************************/
-
-static Brush *image_paint_brush(bContext *C)
-{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
-
- return BKE_paint_brush(&settings->imapaint.paint);
-}
-
-static bool image_paint_poll_ex(bContext *C, bool check_tool)
-{
- Object *obact;
-
- if (!image_paint_brush(C)) {
- return false;
- }
-
- obact = CTX_data_active_object(C);
- if ((obact && obact->mode & OB_MODE_TEXTURE_PAINT) && CTX_wm_region_view3d(C)) {
- if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
- return true;
- }
- }
- else {
- SpaceImage *sima = CTX_wm_space_image(C);
-
- if (sima) {
- if (sima->image != NULL && ID_IS_LINKED(sima->image)) {
- return false;
- }
- ARegion *region = CTX_wm_region(C);
-
- if ((sima->mode == SI_MODE_PAINT) && region->regiontype == RGN_TYPE_WINDOW) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-static bool image_paint_poll(bContext *C)
-{
- return image_paint_poll_ex(C, true);
-}
-
-static bool image_paint_poll_ignore_tool(bContext *C)
-{
- return image_paint_poll_ex(C, false);
-}
-
-static bool image_paint_2d_clone_poll(bContext *C)
-{
- Brush *brush = image_paint_brush(C);
-
- if (!CTX_wm_region_view3d(C) && image_paint_poll(C)) {
- if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) {
- if (brush->clone.image) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-/************************ paint operator ************************/
-typedef enum eTexPaintMode {
- PAINT_MODE_2D,
- PAINT_MODE_3D_PROJECT,
-} eTexPaintMode;
-
-typedef struct PaintOperation {
- eTexPaintMode mode;
-
- void *stroke_handle;
-
- float prevmouse[2];
- float startmouse[2];
- double starttime;
-
- void *cursor;
- ViewContext vc;
-} PaintOperation;
-
-bool paint_use_opacity_masking(Brush *brush)
-{
- return ((brush->flag & BRUSH_AIRBRUSH) || (brush->flag & BRUSH_DRAG_DOT) ||
- (brush->flag & BRUSH_ANCHORED) ||
- (ELEM(brush->imagepaint_tool, PAINT_TOOL_SMEAR, PAINT_TOOL_SOFTEN)) ||
- (brush->imagepaint_tool == PAINT_TOOL_FILL) ||
- (brush->flag & BRUSH_USE_GRADIENT) ||
- (brush->mtex.tex && !ELEM(brush->mtex.brush_map_mode,
- MTEX_MAP_MODE_TILED,
- MTEX_MAP_MODE_STENCIL,
- MTEX_MAP_MODE_3D)) ?
- false :
- true);
-}
-
-void paint_brush_color_get(struct Scene *scene,
- struct Brush *br,
- bool color_correction,
- bool invert,
- float distance,
- float pressure,
- float color[3],
- struct ColorManagedDisplay *display)
-{
- if (invert) {
- copy_v3_v3(color, BKE_brush_secondary_color_get(scene, br));
- }
- else {
- if (br->flag & BRUSH_USE_GRADIENT) {
- float color_gr[4];
- switch (br->gradient_stroke_mode) {
- case BRUSH_GRADIENT_PRESSURE:
- BKE_colorband_evaluate(br->gradient, pressure, color_gr);
- break;
- case BRUSH_GRADIENT_SPACING_REPEAT: {
- float coord = fmod(distance / br->gradient_spacing, 1.0);
- BKE_colorband_evaluate(br->gradient, coord, color_gr);
- break;
- }
- case BRUSH_GRADIENT_SPACING_CLAMP: {
- BKE_colorband_evaluate(br->gradient, distance / br->gradient_spacing, color_gr);
- break;
- }
- }
- /* Gradient / Colorband colors are not considered PROP_COLOR_GAMMA.
- * Brush colors are expected to be in sRGB though. */
- IMB_colormanagement_scene_linear_to_srgb_v3(color_gr);
-
- copy_v3_v3(color, color_gr);
- }
- else {
- copy_v3_v3(color, BKE_brush_color_get(scene, br));
- }
- }
- if (color_correction) {
- IMB_colormanagement_display_to_scene_linear_v3(color, display);
- }
-}
-
-void paint_brush_init_tex(Brush *brush)
-{
- /* init mtex nodes */
- if (brush) {
- MTex *mtex = &brush->mtex;
- if (mtex->tex && mtex->tex->nodetree) {
- /* has internal flag to detect it only does it once */
- ntreeTexBeginExecTree(mtex->tex->nodetree);
- }
- mtex = &brush->mask_mtex;
- if (mtex->tex && mtex->tex->nodetree) {
- ntreeTexBeginExecTree(mtex->tex->nodetree);
- }
- }
-}
-
-void paint_brush_exit_tex(Brush *brush)
-{
- if (brush) {
- MTex *mtex = &brush->mtex;
- if (mtex->tex && mtex->tex->nodetree) {
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
- }
- mtex = &brush->mask_mtex;
- if (mtex->tex && mtex->tex->nodetree) {
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
- }
- }
-}
-
-static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customdata)
-{
- PaintOperation *pop = (PaintOperation *)customdata;
-
- if (pop) {
- GPU_line_smooth(true);
- GPU_blend(GPU_BLEND_ALPHA);
-
- GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
-
- ARegion *region = pop->vc.region;
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- GPU_line_width(4.0);
- immUniformColor4ub(0, 0, 0, 255);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2i(pos, x, y);
- immVertex2i(
- pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin);
- immEnd();
-
- GPU_line_width(2.0);
- immUniformColor4ub(255, 255, 255, 255);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2i(pos, x, y);
- immVertex2i(
- pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin);
- immEnd();
-
- immUnbindProgram();
-
- GPU_blend(GPU_BLEND_NONE);
- GPU_line_smooth(false);
- }
-}
-
-static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const float mouse[2])
-{
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
- PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
- Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
- int mode = RNA_enum_get(op->ptr, "mode");
- ED_view3d_viewcontext_init(C, &pop->vc, depsgraph);
-
- copy_v2_v2(pop->prevmouse, mouse);
- copy_v2_v2(pop->startmouse, mouse);
-
- /* initialize from context */
- if (CTX_wm_region_view3d(C)) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- bool uvs, mat, tex, stencil;
- if (!ED_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) {
- ED_paint_data_warning(op->reports, uvs, mat, tex, stencil);
- MEM_freeN(pop);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
- return NULL;
- }
- pop->mode = PAINT_MODE_3D_PROJECT;
- pop->stroke_handle = paint_proj_new_stroke(C, ob, mouse, mode);
- }
- else {
- pop->mode = PAINT_MODE_2D;
- pop->stroke_handle = paint_2d_new_stroke(C, op, mode);
- }
-
- if (!pop->stroke_handle) {
- MEM_freeN(pop);
- return NULL;
- }
-
- if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
- pop->cursor = WM_paint_cursor_activate(
- SPACE_TYPE_ANY, RGN_TYPE_ANY, image_paint_poll, gradient_draw_line, pop);
- }
-
- settings->imapaint.flag |= IMAGEPAINT_DRAWING;
- ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
-
- return pop;
-}
-
-static void paint_stroke_update_step(bContext *C,
- wmOperator *UNUSED(op),
- struct PaintStroke *stroke,
- PointerRNA *itemptr)
-{
- PaintOperation *pop = paint_stroke_mode_data(stroke);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *toolsettings = CTX_data_tool_settings(C);
- UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
- Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
-
- float alphafac = (brush->flag & BRUSH_ACCUMULATE) ? ups->overlap_factor : 1.0f;
-
- /* initial brush values. Maybe it should be considered moving these to stroke system */
- float startalpha = BKE_brush_alpha_get(scene, brush);
-
- float mouse[2];
- float pressure;
- float size;
- float distance = paint_stroke_distance_get(stroke);
- int eraser;
-
- RNA_float_get_array(itemptr, "mouse", mouse);
- pressure = RNA_float_get(itemptr, "pressure");
- eraser = RNA_boolean_get(itemptr, "pen_flip");
- size = RNA_float_get(itemptr, "size");
-
- /* stroking with fill tool only acts on stroke end */
- if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
- copy_v2_v2(pop->prevmouse, mouse);
- return;
- }
-
- if (BKE_brush_use_alpha_pressure(brush)) {
- BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac));
- }
- else {
- BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac));
- }
-
- if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) {
- UndoStack *ustack = CTX_wm_manager(C)->undo_stack;
- ED_image_undo_restore(ustack->step_init);
- }
-
- switch (pop->mode) {
- case PAINT_MODE_2D:
- paint_2d_stroke(pop->stroke_handle, pop->prevmouse, mouse, eraser, pressure, distance, size);
- break;
-
- case PAINT_MODE_3D_PROJECT:
- paint_proj_stroke(
- C, pop->stroke_handle, pop->prevmouse, mouse, eraser, pressure, distance, size);
- break;
- }
-
- copy_v2_v2(pop->prevmouse, mouse);
-
- /* restore brush values */
- BKE_brush_alpha_set(scene, brush, startalpha);
-}
-
-static void paint_stroke_redraw(const bContext *C, struct PaintStroke *stroke, bool final)
-{
- PaintOperation *pop = paint_stroke_mode_data(stroke);
-
- switch (pop->mode) {
- case PAINT_MODE_2D:
- paint_2d_redraw(C, pop->stroke_handle, final);
- break;
-
- case PAINT_MODE_3D_PROJECT:
- paint_proj_redraw(C, pop->stroke_handle, final);
- break;
- }
-}
-
-static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
-{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *toolsettings = scene->toolsettings;
- PaintOperation *pop = paint_stroke_mode_data(stroke);
- Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
-
- toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
-
- if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
- if (brush->flag & BRUSH_USE_GRADIENT) {
- switch (pop->mode) {
- case PAINT_MODE_2D:
- paint_2d_gradient_fill(C, brush, pop->startmouse, pop->prevmouse, pop->stroke_handle);
- break;
-
- case PAINT_MODE_3D_PROJECT:
- paint_proj_stroke(C,
- pop->stroke_handle,
- pop->startmouse,
- pop->prevmouse,
- paint_stroke_flipped(stroke),
- 1.0,
- 0.0,
- BKE_brush_size_get(scene, brush));
- /* two redraws, one for GPU update, one for notification */
- paint_proj_redraw(C, pop->stroke_handle, false);
- paint_proj_redraw(C, pop->stroke_handle, true);
- break;
- }
- }
- else {
- switch (pop->mode) {
- case PAINT_MODE_2D:
- float color[3];
- if (paint_stroke_inverted(stroke)) {
- srgb_to_linearrgb_v3_v3(color, BKE_brush_secondary_color_get(scene, brush));
- }
- else {
- srgb_to_linearrgb_v3_v3(color, BKE_brush_color_get(scene, brush));
- }
- paint_2d_bucket_fill(
- C, color, brush, pop->startmouse, pop->prevmouse, pop->stroke_handle);
- break;
-
- case PAINT_MODE_3D_PROJECT:
- paint_proj_stroke(C,
- pop->stroke_handle,
- pop->startmouse,
- pop->prevmouse,
- paint_stroke_flipped(stroke),
- 1.0,
- 0.0,
- BKE_brush_size_get(scene, brush));
- /* two redraws, one for GPU update, one for notification */
- paint_proj_redraw(C, pop->stroke_handle, false);
- paint_proj_redraw(C, pop->stroke_handle, true);
- break;
- }
- }
- }
-
- switch (pop->mode) {
- case PAINT_MODE_2D:
- paint_2d_stroke_done(pop->stroke_handle);
- break;
-
- case PAINT_MODE_3D_PROJECT:
- paint_proj_stroke_done(pop->stroke_handle);
- break;
- }
-
- if (pop->cursor) {
- WM_paint_cursor_end(pop->cursor);
- }
-
- ED_image_undo_push_end();
-
- /* duplicate warning, see texpaint_init */
-#if 0
- if (pop->s.warnmultifile) {
- BKE_reportf(op->reports,
- RPT_WARNING,
- "Image requires 4 color channels to paint: %s",
- pop->s.warnmultifile);
- }
- if (pop->s.warnpackedfile) {
- BKE_reportf(op->reports,
- RPT_WARNING,
- "Packed MultiLayer files cannot be painted: %s",
- pop->s.warnpackedfile);
- }
-#endif
- MEM_freeN(pop);
-}
-
-static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
-{
- PaintOperation *pop;
-
- /* TODO: Should avoid putting this here. Instead, last position should be requested
- * from stroke system. */
-
- if (!(pop = texture_paint_init(C, op, mouse))) {
- return false;
- }
-
- paint_stroke_set_mode_data(op->customdata, pop);
-
- return true;
-}
-
-static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- int retval;
-
- op->customdata = paint_stroke_new(C,
- op,
- NULL,
- paint_stroke_test_start,
- paint_stroke_update_step,
- paint_stroke_redraw,
- paint_stroke_done,
- event->type);
-
- if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
- paint_stroke_free(C, op, op->customdata);
- return OPERATOR_FINISHED;
- }
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
-
- OPERATOR_RETVAL_CHECK(retval);
- BLI_assert(retval == OPERATOR_RUNNING_MODAL);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int paint_exec(bContext *C, wmOperator *op)
-{
- PropertyRNA *strokeprop;
- PointerRNA firstpoint;
- float mouse[2];
-
- strokeprop = RNA_struct_find_property(op->ptr, "stroke");
-
- if (!RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint)) {
- return OPERATOR_CANCELLED;
- }
-
- RNA_float_get_array(&firstpoint, "mouse", mouse);
-
- op->customdata = paint_stroke_new(C,
- op,
- NULL,
- paint_stroke_test_start,
- paint_stroke_update_step,
- paint_stroke_redraw,
- paint_stroke_done,
- 0);
- /* frees op->customdata */
- return paint_stroke_exec(C, op, op->customdata);
-}
-
-static int paint_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- return paint_stroke_modal(C, op, event, op->customdata);
-}
-
-static void paint_cancel(bContext *C, wmOperator *op)
-{
- paint_stroke_cancel(C, op, op->customdata);
-}
-
-void PAINT_OT_image_paint(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Image Paint";
- ot->idname = "PAINT_OT_image_paint";
- ot->description = "Paint a stroke into the image";
-
- /* api callbacks */
- ot->invoke = paint_invoke;
- ot->modal = paint_modal;
- ot->exec = paint_exec;
- ot->poll = image_paint_poll;
- ot->cancel = paint_cancel;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
-
- paint_stroke_operator_properties(ot);
-}
-
-bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
-{
- ScrArea *area = CTX_wm_area(C);
- if (area && area->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = area->spacedata.first;
- if (sima->mode == SI_MODE_PAINT) {
- ARegion *region = CTX_wm_region(C);
- ED_space_image_get_zoom(sima, region, zoomx, zoomy);
- return true;
- }
- }
-
- *zoomx = *zoomy = 1;
-
- return false;
-}
-
-/************************ cursor drawing *******************************/
-
-static void toggle_paint_cursor(Scene *scene, bool enable)
-{
- ToolSettings *settings = scene->toolsettings;
- Paint *p = &settings->imapaint.paint;
-
- if (p->paint_cursor && !enable) {
- WM_paint_cursor_end(p->paint_cursor);
- p->paint_cursor = NULL;
- paint_cursor_delete_textures();
- }
- else if (enable) {
- paint_cursor_start(p, image_paint_poll);
- }
-}
-
-void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene)
-{
- ToolSettings *settings = scene->toolsettings;
- ImagePaintSettings *imapaint = &settings->imapaint;
- bool enabled = false;
-
- LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
- bScreen *screen = WM_window_get_active_screen(win);
-
- LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- if (area->spacetype == SPACE_IMAGE) {
- if (((SpaceImage *)area->spacedata.first)->mode == SI_MODE_PAINT) {
- enabled = true;
- }
- }
- }
- }
-
- if (enabled) {
- BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_2D, PAINT_CURSOR_TEXTURE_PAINT);
-
- paint_cursor_start(&imapaint->paint, image_paint_poll);
- }
- else {
- paint_cursor_delete_textures();
- }
-}
-
-/************************ grab clone operator ************************/
-
-typedef struct GrabClone {
- float startoffset[2];
- int startx, starty;
-} GrabClone;
-
-static void grab_clone_apply(bContext *C, wmOperator *op)
-{
- Brush *brush = image_paint_brush(C);
- float delta[2];
-
- RNA_float_get_array(op->ptr, "delta", delta);
- add_v2_v2(brush->clone.offset, delta);
- 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;
-}
-
-static int grab_clone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Brush *brush = image_paint_brush(C);
- GrabClone *cmv;
-
- cmv = MEM_callocN(sizeof(GrabClone), "GrabClone");
- copy_v2_v2(cmv->startoffset, brush->clone.offset);
- cmv->startx = event->xy[0];
- cmv->starty = event->xy[1];
- op->customdata = cmv;
-
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Brush *brush = image_paint_brush(C);
- ARegion *region = CTX_wm_region(C);
- GrabClone *cmv = op->customdata;
- float startfx, startfy, fx, fy, delta[2];
- int xmin = region->winrct.xmin, ymin = region->winrct.ymin;
-
- switch (event->type) {
- 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(
- &region->v2d, cmv->startx - xmin, cmv->starty - ymin, &startfx, &startfy);
- UI_view2d_region_to_view(&region->v2d, event->xy[0] - xmin, event->xy[1] - ymin, &fx, &fy);
-
- delta[0] = fx - startfx;
- delta[1] = fy - startfy;
- RNA_float_set_array(op->ptr, "delta", delta);
-
- copy_v2_v2(brush->clone.offset, cmv->startoffset);
-
- grab_clone_apply(C, op);
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void grab_clone_cancel(bContext *UNUSED(C), wmOperator *op)
-{
- MEM_freeN(op->customdata);
-}
-
-void PAINT_OT_grab_clone(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Grab Clone";
- ot->idname = "PAINT_OT_grab_clone";
- ot->description = "Move the clone source image";
-
- /* api callbacks */
- 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;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* properties */
- RNA_def_float_vector(ot->srna,
- "delta",
- 2,
- NULL,
- -FLT_MAX,
- FLT_MAX,
- "Delta",
- "Delta offset of clone image in 0.0 to 1.0 coordinates",
- -1.0f,
- 1.0f);
-}
-
-/******************** sample color operator ********************/
-typedef struct {
- bool show_cursor;
- short launch_event;
- float initcolor[3];
- bool sample_palette;
-} SampleColorData;
-
-static void sample_color_update_header(SampleColorData *data, bContext *C)
-{
- char msg[UI_MAX_DRAW_STR];
- ScrArea *area = CTX_wm_area(C);
-
- if (area) {
- BLI_snprintf(msg,
- sizeof(msg),
- TIP_("Sample color for %s"),
- !data->sample_palette ?
- TIP_("Brush. Use Left Click to sample for palette instead") :
- TIP_("Palette. Use Left Click to sample more colors"));
- ED_workspace_status_text(C, msg);
- }
-}
-
-static int sample_color_exec(bContext *C, wmOperator *op)
-{
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- ARegion *region = CTX_wm_region(C);
- wmWindow *win = CTX_wm_window(C);
- const bool show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
- int location[2];
- paint->flags &= ~PAINT_SHOW_BRUSH;
-
- /* force redraw without cursor */
- WM_paint_cursor_tag_redraw(win, region);
- WM_redraw_windows(C);
-
- RNA_int_get_array(op->ptr, "location", location);
- const bool use_palette = RNA_boolean_get(op->ptr, "palette");
- const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) &&
- !RNA_boolean_get(op->ptr, "merged");
-
- paint_sample_color(C, region, location[0], location[1], use_sample_texture, use_palette);
-
- if (show_cursor) {
- paint->flags |= PAINT_SHOW_BRUSH;
- }
-
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
-
- return OPERATOR_FINISHED;
-}
-
-static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Scene *scene = CTX_data_scene(C);
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
- SampleColorData *data = MEM_mallocN(sizeof(SampleColorData), "sample color custom data");
- ARegion *region = CTX_wm_region(C);
- wmWindow *win = CTX_wm_window(C);
-
- data->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
- data->show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
- copy_v3_v3(data->initcolor, BKE_brush_color_get(scene, brush));
- data->sample_palette = false;
- op->customdata = data;
- paint->flags &= ~PAINT_SHOW_BRUSH;
-
- sample_color_update_header(data, C);
-
- WM_event_add_modal_handler(C, op);
-
- /* force redraw without cursor */
- WM_paint_cursor_tag_redraw(win, region);
- WM_redraw_windows(C);
-
- RNA_int_set_array(op->ptr, "location", event->mval);
-
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) &&
- !RNA_boolean_get(op->ptr, "merged");
-
- paint_sample_color(C, region, event->mval[0], event->mval[1], use_sample_texture, false);
- WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER);
-
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Scene *scene = CTX_data_scene(C);
- SampleColorData *data = op->customdata;
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *brush = BKE_paint_brush(paint);
-
- if ((event->type == data->launch_event) && (event->val == KM_RELEASE)) {
- if (data->show_cursor) {
- paint->flags |= PAINT_SHOW_BRUSH;
- }
-
- if (data->sample_palette) {
- BKE_brush_color_set(scene, brush, data->initcolor);
- RNA_boolean_set(op->ptr, "palette", true);
- }
- WM_cursor_modal_restore(CTX_wm_window(C));
- MEM_freeN(data);
- ED_workspace_status_text(C, NULL);
-
- return OPERATOR_FINISHED;
- }
-
- ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) &&
- !RNA_boolean_get(op->ptr, "merged");
-
- switch (event->type) {
- case MOUSEMOVE: {
- ARegion *region = CTX_wm_region(C);
- RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, region, event->mval[0], event->mval[1], use_sample_texture, false);
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
- break;
- }
-
- case LEFTMOUSE:
- if (event->val == KM_PRESS) {
- ARegion *region = CTX_wm_region(C);
- RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, region, event->mval[0], event->mval[1], use_sample_texture, true);
- if (!data->sample_palette) {
- data->sample_palette = true;
- sample_color_update_header(data, C);
- }
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
- }
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static bool sample_color_poll(bContext *C)
-{
- return (image_paint_poll_ignore_tool(C) || vertex_paint_poll_ignore_tool(C));
-}
-
-void PAINT_OT_sample_color(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Sample Color";
- ot->idname = "PAINT_OT_sample_color";
- ot->description = "Use the mouse to sample a color in the image";
-
- /* api callbacks */
- ot->exec = sample_color_exec;
- ot->invoke = sample_color_invoke;
- ot->modal = sample_color_modal;
- ot->poll = sample_color_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- PropertyRNA *prop;
-
- prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
-
- RNA_def_boolean(ot->srna, "merged", 0, "Sample Merged", "Sample the output display color");
- RNA_def_boolean(ot->srna, "palette", 0, "Add to Palette", "");
-}
-
-/******************** texture paint toggle operator ********************/
-
-void ED_object_texture_paint_mode_enter_ex(Main *bmain, Scene *scene, Object *ob)
-{
- Image *ima = NULL;
- ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
-
- /* This has to stay here to regenerate the texture paint
- * cache in case we are loading a file */
- BKE_texpaint_slots_refresh_object(scene, ob);
-
- ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
-
- /* entering paint mode also sets image to editors */
- if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
- /* set the current material active paint slot on image editor */
- Material *ma = BKE_object_material_get(ob, ob->actcol);
-
- if (ma && ma->texpaintslot) {
- ima = ma->texpaintslot[ma->paint_active_slot].ima;
- }
- }
- else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
- ima = imapaint->canvas;
- }
-
- if (ima) {
- wmWindowManager *wm = bmain->wm.first;
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- const bScreen *screen = WM_window_get_active_screen(win);
- for (ScrArea *area = screen->areabase.first; area; area = area->next) {
- SpaceLink *sl = area->spacedata.first;
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- if (!sima->pin) {
- ED_space_image_set(bmain, sima, ima, true);
- }
- }
- }
- }
- }
-
- ob->mode |= OB_MODE_TEXTURE_PAINT;
-
- BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_3D, PAINT_CURSOR_TEXTURE_PAINT);
-
- BKE_paint_toolslots_brush_validate(bmain, &imapaint->paint);
-
- if (U.glreslimit != 0) {
- BKE_image_free_all_gputextures(bmain);
- }
- BKE_image_paint_set_mipmap(bmain, 0);
-
- toggle_paint_cursor(scene, true);
-
- Mesh *me = BKE_mesh_from_object(ob);
- BLI_assert(me != NULL);
- DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE);
- WM_main_add_notifier(NC_SCENE | ND_MODE, scene);
-}
-
-void ED_object_texture_paint_mode_enter(bContext *C)
-{
- Main *bmain = CTX_data_main(C);
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
- ED_object_texture_paint_mode_enter_ex(bmain, scene, ob);
-}
-
-void ED_object_texture_paint_mode_exit_ex(Main *bmain, Scene *scene, Object *ob)
-{
- ob->mode &= ~OB_MODE_TEXTURE_PAINT;
-
- if (U.glreslimit != 0) {
- BKE_image_free_all_gputextures(bmain);
- }
- BKE_image_paint_set_mipmap(bmain, 1);
- toggle_paint_cursor(scene, false);
-
- Mesh *me = BKE_mesh_from_object(ob);
- BLI_assert(me != NULL);
- DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE);
- WM_main_add_notifier(NC_SCENE | ND_MODE, scene);
-}
-
-void ED_object_texture_paint_mode_exit(bContext *C)
-{
- Main *bmain = CTX_data_main(C);
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
- ED_object_texture_paint_mode_exit_ex(bmain, scene, ob);
-}
-
-static bool texture_paint_toggle_poll(bContext *C)
-{
- Object *ob = CTX_data_active_object(C);
- if (ob == NULL || ob->type != OB_MESH) {
- return false;
- }
- if (!ob->data || ID_IS_LINKED(ob->data)) {
- return false;
- }
-
- return true;
-}
-
-static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
-{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- const int mode_flag = OB_MODE_TEXTURE_PAINT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
-
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- if (ob->mode & mode_flag) {
- ED_object_texture_paint_mode_exit_ex(bmain, scene, ob);
- }
- else {
- ED_object_texture_paint_mode_enter_ex(bmain, scene, ob);
- }
-
- WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
-
- WM_toolsystem_update_from_context_view3d(C);
-
- return OPERATOR_FINISHED;
-}
-
-void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Texture Paint Toggle";
- ot->idname = "PAINT_OT_texture_paint_toggle";
- ot->description = "Toggle texture paint mode in 3D view";
-
- /* api callbacks */
- ot->exec = texture_paint_toggle_exec;
- ot->poll = texture_paint_toggle_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Scene *scene = CTX_data_scene(C);
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
-
- Paint *paint = BKE_paint_get_active_from_context(C);
- Brush *br = BKE_paint_brush(paint);
-
- if (ups->flag & UNIFIED_PAINT_COLOR) {
- swap_v3_v3(ups->rgb, ups->secondary_rgb);
- }
- else if (br) {
- swap_v3_v3(br->rgb, br->secondary_rgb);
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
- WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, br);
-
- return OPERATOR_FINISHED;
-}
-
-static bool brush_colors_flip_poll(bContext *C)
-{
- if (image_paint_poll(C)) {
- Brush *br = image_paint_brush(C);
- if (ELEM(br->imagepaint_tool, PAINT_TOOL_DRAW, PAINT_TOOL_FILL)) {
- return true;
- }
- }
- else {
- Object *ob = CTX_data_active_object(C);
- if (ob != NULL) {
- if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT | OB_MODE_SCULPT)) {
- return true;
- }
- }
- }
- return false;
-}
-
-void PAINT_OT_brush_colors_flip(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Swap Colors";
- ot->idname = "PAINT_OT_brush_colors_flip";
- ot->description = "Swap primary and secondary brush colors";
-
- /* api callbacks */
- ot->exec = brush_colors_flip_exec;
- ot->poll = brush_colors_flip_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-void ED_imapaint_bucket_fill(struct bContext *C,
- float color[3],
- wmOperator *op,
- const int mouse[2])
-{
- SpaceImage *sima = CTX_wm_space_image(C);
-
- if (sima && sima->image) {
- Image *ima = sima->image;
-
- ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
-
- const float mouse_init[2] = {mouse[0], mouse[1]};
- paint_2d_bucket_fill(C, color, NULL, mouse_init, NULL, NULL);
-
- ED_image_undo_push_end();
-
- DEG_id_tag_update(&ima->id, 0);
- }
-}
-
-static bool texture_paint_poll(bContext *C)
-{
- if (texture_paint_toggle_poll(C)) {
- if (CTX_data_active_object(C)->mode & OB_MODE_TEXTURE_PAINT) {
- return true;
- }
- }
-
- return false;
-}
-
-bool image_texture_paint_poll(bContext *C)
-{
- return (texture_paint_poll(C) || image_paint_poll(C));
-}
-
-bool facemask_paint_poll(bContext *C)
-{
- return BKE_paint_select_face_test(CTX_data_active_object(C));
-}
-
-bool vert_paint_poll(bContext *C)
-{
- return BKE_paint_select_vert_test(CTX_data_active_object(C));
-}
-
-bool mask_paint_poll(bContext *C)
-{
- return BKE_paint_select_elem_test(CTX_data_active_object(C));
-}