Blender  V2.93
interface_eyedropper_gpencil_color.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009 Blender Foundation.
17  * All rights reserved.
18  */
19 
29 #include "MEM_guardedalloc.h"
30 
31 #include "BLI_listbase.h"
32 #include "BLI_string.h"
33 
34 #include "BLT_translation.h"
35 
36 #include "DNA_gpencil_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_space_types.h"
39 
40 #include "BKE_context.h"
41 #include "BKE_gpencil.h"
42 #include "BKE_lib_id.h"
43 #include "BKE_main.h"
44 #include "BKE_material.h"
45 #include "BKE_paint.h"
46 #include "BKE_report.h"
47 
48 #include "UI_interface.h"
49 
50 #include "IMB_colormanagement.h"
51 
52 #include "WM_api.h"
53 #include "WM_types.h"
54 
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57 
58 #include "ED_gpencil.h"
59 #include "ED_screen.h"
60 #include "ED_undo.h"
61 
62 #include "DEG_depsgraph.h"
63 #include "DEG_depsgraph_build.h"
64 
66 #include "interface_intern.h"
67 
68 typedef struct EyedropperGPencil {
71  float color[3];
73  int mode;
75 
76 /* Helper: Draw status message while the user is running the operator */
78 {
79  char msg_str[UI_MAX_DRAW_STR];
81  msg_str, TIP_("LMB: Stroke - Shift: Fill - Shift+Ctrl: Stroke + Fill"), UI_MAX_DRAW_STR);
82 
83  ED_workspace_status_text(C, msg_str);
84 }
85 
86 /* Initialize. */
88 {
89  EyedropperGPencil *eye = MEM_callocN(sizeof(EyedropperGPencil), __func__);
90 
91  op->customdata = eye;
93 
94  const char *display_device;
95  display_device = scene->display_settings.display_device;
96  eye->display = IMB_colormanagement_display_get_named(display_device);
97 
98  eye->mode = RNA_enum_get(op->ptr, "mode");
99  return true;
100 }
101 
102 /* Exit and free memory. */
104 {
105  /* Clear status message area. */
107 
109 }
110 
112  const float col_conv[4],
113  const bool only_stroke,
114  const bool only_fill,
115  const bool both)
116 {
117  Main *bmain = CTX_data_main(C);
119  Material *ma = NULL;
120 
121  bool found = false;
122 
123  /* Look for a similar material in grease pencil slots. */
124  short *totcol = BKE_object_material_len_p(ob);
125  for (short i = 0; i < *totcol; i++) {
126  ma = BKE_object_material_get(ob, i + 1);
127  if (ma == NULL) {
128  continue;
129  }
130 
131  MaterialGPencilStyle *gp_style = ma->gp_style;
132  if (gp_style != NULL) {
133  /* Check stroke color. */
134  bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) &&
135  (gp_style->flag & GP_MATERIAL_STROKE_SHOW);
136  /* Check fill color. */
137  bool found_fill = compare_v3v3(gp_style->fill_rgba, col_conv, 0.01f) &&
138  (gp_style->flag & GP_MATERIAL_FILL_SHOW);
139 
140  if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) {
141  found = true;
142  }
143  else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0)) {
144  found = true;
145  }
146  else if ((both) && (found_stroke) && (found_fill)) {
147  found = true;
148  }
149 
150  /* Found existing material. */
151  if (found) {
152  ob->actcol = i + 1;
155  return;
156  }
157  }
158  }
159 
160  /* If material was not found add a new material with stroke and/or fill color
161  * depending of the secondary key (LMB: Stroke, Shift: Fill, Shift+Ctrl: Stroke/Fill)
162  */
163  int idx;
164  Material *ma_new = BKE_gpencil_object_material_new(bmain, ob, "Material", &idx);
168 
169  BLI_assert(ma_new != NULL);
170 
171  MaterialGPencilStyle *gp_style_new = ma_new->gp_style;
172  BLI_assert(gp_style_new != NULL);
173 
174  /* Only create Stroke (default option). */
175  if (only_stroke) {
176  /* Stroke color. */
177  gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW;
178  gp_style_new->flag &= ~GP_MATERIAL_FILL_SHOW;
179  copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
180  zero_v4(gp_style_new->fill_rgba);
181  }
182  /* Fill Only. */
183  else if (only_fill) {
184  /* Fill color. */
185  gp_style_new->flag &= ~GP_MATERIAL_STROKE_SHOW;
186  gp_style_new->flag |= GP_MATERIAL_FILL_SHOW;
187  zero_v4(gp_style_new->stroke_rgba);
188  copy_v3_v3(gp_style_new->fill_rgba, col_conv);
189  }
190  /* Stroke and Fill. */
191  else if (both) {
193  copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
194  copy_v3_v3(gp_style_new->fill_rgba, col_conv);
195  }
196  /* Push undo for new created material. */
197  ED_undo_push(C, "Add Grease Pencil Material");
198 }
199 
200 /* Create a new palette color and palette if needed. */
201 static void eyedropper_add_palette_color(bContext *C, const float col_conv[4])
202 {
203  Main *bmain = CTX_data_main(C);
206  GpPaint *gp_paint = ts->gp_paint;
207  GpVertexPaint *gp_vertexpaint = ts->gp_vertexpaint;
208  Paint *paint = &gp_paint->paint;
209  Paint *vertexpaint = &gp_vertexpaint->paint;
210 
211  /* Check for Palette in Draw and Vertex Paint Mode. */
212  if (paint->palette == NULL) {
213  Palette *palette = BKE_palette_add(bmain, "Grease Pencil");
214  id_us_min(&palette->id);
215 
216  BKE_paint_palette_set(paint, palette);
217 
218  if (vertexpaint->palette == NULL) {
219  BKE_paint_palette_set(vertexpaint, palette);
220  }
221  }
222  /* Check if the color exist already. */
223  Palette *palette = paint->palette;
224  LISTBASE_FOREACH (PaletteColor *, palcolor, &palette->colors) {
225  if (compare_v3v3(palcolor->rgb, col_conv, 0.01f)) {
226  return;
227  }
228  }
229 
230  /* Create Colors. */
231  PaletteColor *palcol = BKE_palette_color_add(palette);
232  if (palcol) {
233  copy_v3_v3(palcol->rgb, col_conv);
234  }
235 }
236 
237 /* Set the material or the palette color. */
239 {
240 
241  const bool only_stroke = ((!event->ctrl) && (!event->shift));
242  const bool only_fill = ((!event->ctrl) && (event->shift));
243  const bool both = ((event->ctrl) && (event->shift));
244 
245  float col_conv[4];
246 
247  /* Convert from linear rgb space to display space because grease pencil colors are in display
248  * space, and this conversion is needed to undo the conversion to linear performed by
249  * eyedropper_color_sample_fl. */
250  if (eye->display) {
251  copy_v3_v3(col_conv, eye->color);
253  }
254  else {
255  copy_v3_v3(col_conv, eye->color);
256  }
257 
258  /* Add material or Palette color*/
259  if (eye->mode == 0) {
260  eyedropper_add_material(C, col_conv, only_stroke, only_fill, both);
261  }
262  else {
263  eyedropper_add_palette_color(C, col_conv);
264  }
265 }
266 
267 /* Sample the color below cursor. */
268 static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, int mx, int my)
269 {
270  eyedropper_color_sample_fl(C, mx, my, eye->color);
271 }
272 
273 /* Cancel operator. */
275 {
277 }
278 
279 /* Main modal status check. */
280 static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *event)
281 {
283  /* Handle modal keymap */
284  switch (event->type) {
285  case EVT_MODAL_MAP: {
286  switch (event->val) {
287  case EYE_MODAL_SAMPLE_BEGIN: {
288  return OPERATOR_RUNNING_MODAL;
289  }
290  case EYE_MODAL_CANCEL: {
292  return OPERATOR_CANCELLED;
293  }
295  eyedropper_gpencil_color_sample(C, eye, event->x, event->y);
296 
297  /* Create material. */
298  eyedropper_gpencil_color_set(C, event, eye);
300 
302  return OPERATOR_FINISHED;
303  }
304  default: {
305  break;
306  }
307  }
308  break;
309  }
310  case MOUSEMOVE:
311  case INBETWEEN_MOUSEMOVE: {
312  eyedropper_gpencil_color_sample(C, eye, event->x, event->y);
313  break;
314  }
315  default: {
316  break;
317  }
318  }
319 
320  return OPERATOR_RUNNING_MODAL;
321 }
322 
323 /* Modal Operator init */
325 {
326  /* Init. */
327  if (eyedropper_gpencil_init(C, op)) {
328  /* Add modal temp handler. */
330  /* Status message. */
332 
333  return OPERATOR_RUNNING_MODAL;
334  }
335  return OPERATOR_PASS_THROUGH;
336 }
337 
338 /* Repeat operator */
340 {
341  /* init */
342  if (eyedropper_gpencil_init(C, op)) {
343 
344  /* cleanup */
346 
347  return OPERATOR_FINISHED;
348  }
349  return OPERATOR_PASS_THROUGH;
350 }
351 
353 {
354  /* Only valid if the current active object is grease pencil. */
355  Object *obact = CTX_data_active_object(C);
356  if ((obact == NULL) || (obact->type != OB_GPENCIL)) {
357  return false;
358  }
359 
360  /* Test we have a window below. */
361  return (CTX_wm_window(C) != NULL);
362 }
363 
365 {
366  static const EnumPropertyItem items_mode[] = {
367  {0, "MATERIAL", 0, "Material", ""},
368  {1, "PALETTE", 0, "Palette", ""},
369  {0, NULL, 0, NULL, NULL},
370  };
371 
372  /* identifiers */
373  ot->name = "Grease Pencil Eyedropper";
374  ot->idname = "UI_OT_eyedropper_gpencil_color";
375  ot->description = "Sample a color from the Blender Window and create Grease Pencil material";
376 
377  /* api callbacks */
383 
384  /* flags */
386 
387  /* properties */
388  ot->prop = RNA_def_enum(ot->srna, "mode", items_mode, 0, "Mode", "");
389 }
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
struct Material * BKE_gpencil_object_material_new(struct Main *bmain, struct Object *ob, const char *name, int *r_index)
Definition: gpencil.c:1873
void id_us_min(struct ID *id)
Definition: lib_id.c:297
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:697
short * BKE_object_material_len_p(struct Object *ob)
Definition: material.c:356
struct Palette * BKE_palette_add(struct Main *bmain, const char *name)
Definition: paint.c:751
void BKE_paint_palette_set(struct Paint *p, struct Palette *palette)
Definition: paint.c:705
struct PaletteColor * BKE_palette_color_add(struct Palette *palette)
Definition: paint.c:757
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
MINLINE bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v4(float r[4])
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define UNUSED(x)
#define TIP_(msgid)
void DEG_relations_tag_update(struct Main *bmain)
@ GP_MATERIAL_STROKE_SHOW
@ GP_MATERIAL_FILL_SHOW
@ OB_GPENCIL
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_workspace_status_text(struct bContext *C, const char *str)
Definition: area.c:840
void ED_undo_push(struct bContext *C, const char *str)
Definition: ed_undo.c:117
void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], struct ColorManagedDisplay *display)
struct ColorManagedDisplay * IMB_colormanagement_display_get_named(const char *name)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition: RandGen.cpp:39
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:90
@ OPTYPE_BLOCKING
Definition: WM_types.h:157
@ OPTYPE_UNDO
Definition: WM_types.h:155
#define ND_DATA
Definition: WM_types.h:408
#define NA_EDITED
Definition: WM_types.h:462
#define NC_MATERIAL
Definition: WM_types.h:281
#define NC_GPENCIL
Definition: WM_types.h:300
#define ND_OB_SHADING
Definition: WM_types.h:358
#define ND_SPACE_VIEW3D
Definition: WM_types.h:423
#define NC_OBJECT
Definition: WM_types.h:280
#define ND_SHADING_LINKS
Definition: WM_types.h:379
#define NC_SPACE
Definition: WM_types.h:293
Scene scene
void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
get the color from the screen.
static void eyedropper_gpencil_status_indicators(bContext *C)
static void eyedropper_gpencil_cancel(bContext *C, wmOperator *op)
static void eyedropper_add_material(bContext *C, const float col_conv[4], const bool only_stroke, const bool only_fill, const bool both)
static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, int mx, int my)
static int eyedropper_gpencil_exec(bContext *C, wmOperator *op)
static bool eyedropper_gpencil_init(bContext *C, wmOperator *op)
static bool eyedropper_gpencil_poll(bContext *C)
void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot)
static void eyedropper_gpencil_exit(bContext *C, wmOperator *op)
static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye)
static void eyedropper_add_palette_color(bContext *C, const float col_conv[4])
struct EyedropperGPencil EyedropperGPencil
static int eyedropper_gpencil_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
@ EYE_MODAL_SAMPLE_BEGIN
@ EYE_MODAL_SAMPLE_CONFIRM
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
struct ColorManagedDisplay * display
Definition: BKE_main.h:116
struct MaterialGPencilStyle * gp_style
struct Palette * palette
ListBase colors
struct ToolSettings * toolsettings
ColorManagedDisplaySettings display_settings
GpPaint * gp_paint
GpVertexPaint * gp_vertexpaint
int y
Definition: WM_types.h:581
short shift
Definition: WM_types.h:618
short val
Definition: WM_types.h:579
int x
Definition: WM_types.h:581
short type
Definition: WM_types.h:577
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct PointerRNA * ptr
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_main_add_notifier(unsigned int type, void *reference)
@ EVT_MODAL_MAP
@ MOUSEMOVE
@ INBETWEEN_MOUSEMOVE
wmOperatorType * ot
Definition: wm_files.c:3156