Blender  V3.3
eyedropper_gpencil_color.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2009 Blender Foundation. All rights reserved. */
3 
13 #include "MEM_guardedalloc.h"
14 
15 #include "BLI_listbase.h"
16 #include "BLI_string.h"
17 
18 #include "BLT_translation.h"
19 
20 #include "DNA_gpencil_types.h"
21 #include "DNA_material_types.h"
22 #include "DNA_space_types.h"
23 
24 #include "BKE_context.h"
25 #include "BKE_gpencil.h"
26 #include "BKE_lib_id.h"
27 #include "BKE_main.h"
28 #include "BKE_material.h"
29 #include "BKE_paint.h"
30 #include "BKE_report.h"
31 
32 #include "UI_interface.h"
33 
34 #include "IMB_colormanagement.h"
35 
36 #include "WM_api.h"
37 #include "WM_types.h"
38 
39 #include "RNA_access.h"
40 #include "RNA_define.h"
41 
42 #include "ED_gpencil.h"
43 #include "ED_screen.h"
44 #include "ED_undo.h"
45 
46 #include "DEG_depsgraph.h"
47 #include "DEG_depsgraph_build.h"
48 
49 #include "eyedropper_intern.h"
50 #include "interface_intern.h"
51 
52 typedef enum eGP_EyeMode {
56 
57 typedef struct EyedropperGPencil {
60  float color[3];
64 
65 /* Helper: Draw status message while the user is running the operator */
67 {
68  char msg_str[UI_MAX_DRAW_STR];
70  msg_str, TIP_("LMB: Stroke - Shift: Fill - Shift+Ctrl: Stroke + Fill"), UI_MAX_DRAW_STR);
71 
72  ED_workspace_status_text(C, msg_str);
73 }
74 
75 /* Initialize. */
77 {
78  EyedropperGPencil *eye = MEM_callocN(sizeof(EyedropperGPencil), __func__);
79 
80  op->customdata = eye;
82 
83  const char *display_device;
84  display_device = scene->display_settings.display_device;
85  eye->display = IMB_colormanagement_display_get_named(display_device);
86 
87  eye->mode = (eGP_EyeMode)RNA_enum_get(op->ptr, "mode");
88  return true;
89 }
90 
91 /* Exit and free memory. */
93 {
94  /* Clear status message area. */
96 
98 }
99 
101  const float col_conv[4],
102  const bool only_stroke,
103  const bool only_fill,
104  const bool both)
105 {
106  Main *bmain = CTX_data_main(C);
108  Material *ma = NULL;
109 
110  bool found = false;
111 
112  /* Look for a similar material in grease pencil slots. */
113  short *totcol = BKE_object_material_len_p(ob);
114  for (short i = 0; i < *totcol; i++) {
115  ma = BKE_object_material_get(ob, i + 1);
116  if (ma == NULL) {
117  continue;
118  }
119 
120  MaterialGPencilStyle *gp_style = ma->gp_style;
121  if (gp_style != NULL) {
122  /* Check stroke color. */
123  bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) &&
124  (gp_style->flag & GP_MATERIAL_STROKE_SHOW);
125  /* Check fill color. */
126  bool found_fill = compare_v3v3(gp_style->fill_rgba, col_conv, 0.01f) &&
127  (gp_style->flag & GP_MATERIAL_FILL_SHOW);
128 
129  if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) {
130  found = true;
131  }
132  else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0)) {
133  found = true;
134  }
135  else if ((both) && (found_stroke) && (found_fill)) {
136  found = true;
137  }
138 
139  /* Found existing material. */
140  if (found) {
141  ob->actcol = i + 1;
144  return;
145  }
146  }
147  }
148 
149  /* If material was not found add a new material with stroke and/or fill color
150  * depending of the secondary key (LMB: Stroke, Shift: Fill, Shift+Ctrl: Stroke/Fill)
151  */
152  int idx;
153  Material *ma_new = BKE_gpencil_object_material_new(bmain, ob, "Material", &idx);
157 
158  BLI_assert(ma_new != NULL);
159 
160  MaterialGPencilStyle *gp_style_new = ma_new->gp_style;
161  BLI_assert(gp_style_new != NULL);
162 
163  /* Only create Stroke (default option). */
164  if (only_stroke) {
165  /* Stroke color. */
166  gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW;
167  gp_style_new->flag &= ~GP_MATERIAL_FILL_SHOW;
168  copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
169  zero_v4(gp_style_new->fill_rgba);
170  }
171  /* Fill Only. */
172  else if (only_fill) {
173  /* Fill color. */
174  gp_style_new->flag &= ~GP_MATERIAL_STROKE_SHOW;
175  gp_style_new->flag |= GP_MATERIAL_FILL_SHOW;
176  zero_v4(gp_style_new->stroke_rgba);
177  copy_v3_v3(gp_style_new->fill_rgba, col_conv);
178  }
179  /* Stroke and Fill. */
180  else if (both) {
182  copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
183  copy_v3_v3(gp_style_new->fill_rgba, col_conv);
184  }
185  /* Push undo for new created material. */
186  ED_undo_push(C, "Add Grease Pencil Material");
187 }
188 
189 /* Create a new palette color and palette if needed. */
190 static void eyedropper_add_palette_color(bContext *C, const float col_conv[4])
191 {
192  Main *bmain = CTX_data_main(C);
195  GpPaint *gp_paint = ts->gp_paint;
196  GpVertexPaint *gp_vertexpaint = ts->gp_vertexpaint;
197  Paint *paint = &gp_paint->paint;
198  Paint *vertexpaint = &gp_vertexpaint->paint;
199 
200  /* Check for Palette in Draw and Vertex Paint Mode. */
201  if (paint->palette == NULL) {
202  Palette *palette = BKE_palette_add(bmain, "Grease Pencil");
203  id_us_min(&palette->id);
204 
205  BKE_paint_palette_set(paint, palette);
206 
207  if (vertexpaint->palette == NULL) {
208  BKE_paint_palette_set(vertexpaint, palette);
209  }
210  }
211  /* Check if the color exist already. */
212  Palette *palette = paint->palette;
213  LISTBASE_FOREACH (PaletteColor *, palcolor, &palette->colors) {
214  if (compare_v3v3(palcolor->rgb, col_conv, 0.01f)) {
215  return;
216  }
217  }
218 
219  /* Create Colors. */
220  PaletteColor *palcol = BKE_palette_color_add(palette);
221  if (palcol) {
222  copy_v3_v3(palcol->rgb, col_conv);
223  }
224 }
225 
226 /* Set the material or the palette color. */
228 {
229 
230  const bool only_stroke = (event->modifier & (KM_CTRL | KM_SHIFT)) == 0;
231  const bool only_fill = ((event->modifier & KM_CTRL) == 0 && (event->modifier & KM_SHIFT));
232  const bool both = ((event->modifier & KM_CTRL) && (event->modifier & KM_SHIFT));
233 
234  float col_conv[4];
235 
236  /* Convert from linear rgb space to display space because palette colors are in display
237  * space, and this conversion is needed to undo the conversion to linear performed by
238  * eyedropper_color_sample_fl. */
239  if ((eye->display) && (eye->mode == GP_EYE_PALETTE)) {
240  copy_v3_v3(col_conv, eye->color);
242  }
243  else {
244  copy_v3_v3(col_conv, eye->color);
245  }
246 
247  /* Add material or Palette color. */
248  if (eye->mode == 0) {
249  eyedropper_add_material(C, col_conv, only_stroke, only_fill, both);
250  }
251  else {
252  eyedropper_add_palette_color(C, col_conv);
253  }
254 }
255 
256 /* Sample the color below cursor. */
257 static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, const int m_xy[2])
258 {
259  eyedropper_color_sample_fl(C, m_xy, eye->color);
260 }
261 
262 /* Cancel operator. */
264 {
266 }
267 
268 /* Main modal status check. */
269 static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *event)
270 {
272  /* Handle modal keymap */
273  switch (event->type) {
274  case EVT_MODAL_MAP: {
275  switch (event->val) {
276  case EYE_MODAL_SAMPLE_BEGIN: {
277  return OPERATOR_RUNNING_MODAL;
278  }
279  case EYE_MODAL_CANCEL: {
281  return OPERATOR_CANCELLED;
282  }
284  eyedropper_gpencil_color_sample(C, eye, event->xy);
285 
286  /* Create material. */
287  eyedropper_gpencil_color_set(C, event, eye);
289 
291  return OPERATOR_FINISHED;
292  }
293  default: {
294  break;
295  }
296  }
297  break;
298  }
299  case MOUSEMOVE:
300  case INBETWEEN_MOUSEMOVE: {
301  eyedropper_gpencil_color_sample(C, eye, event->xy);
302  break;
303  }
304  default: {
305  break;
306  }
307  }
308 
309  return OPERATOR_RUNNING_MODAL;
310 }
311 
312 /* Modal Operator init */
314 {
315  /* Init. */
316  if (eyedropper_gpencil_init(C, op)) {
317  /* Add modal temp handler. */
319  /* Status message. */
321 
322  return OPERATOR_RUNNING_MODAL;
323  }
324  return OPERATOR_PASS_THROUGH;
325 }
326 
327 /* Repeat operator */
329 {
330  /* init */
331  if (eyedropper_gpencil_init(C, op)) {
332 
333  /* cleanup */
335 
336  return OPERATOR_FINISHED;
337  }
338  return OPERATOR_PASS_THROUGH;
339 }
340 
342 {
343  /* Only valid if the current active object is grease pencil. */
344  Object *obact = CTX_data_active_object(C);
345  if ((obact == NULL) || (obact->type != OB_GPENCIL)) {
346  return false;
347  }
348 
349  /* Test we have a window below. */
350  return (CTX_wm_window(C) != NULL);
351 }
352 
354 {
355  static const EnumPropertyItem items_mode[] = {
356  {GP_EYE_MATERIAL, "MATERIAL", 0, "Material", ""},
357  {GP_EYE_PALETTE, "PALETTE", 0, "Palette", ""},
358  {0, NULL, 0, NULL, NULL},
359  };
360 
361  /* identifiers */
362  ot->name = "Grease Pencil Eyedropper";
363  ot->idname = "UI_OT_eyedropper_gpencil_color";
364  ot->description = "Sample a color from the Blender Window and create Grease Pencil material";
365 
366  /* api callbacks */
372 
373  /* flags */
375 
376  /* properties */
377  ot->prop = RNA_def_enum(ot->srna, "mode", items_mode, GP_EYE_MATERIAL, "Mode", "");
378 }
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
struct Material * BKE_gpencil_object_material_new(struct Main *bmain, struct Object *ob, const char *name, int *r_index)
Definition: gpencil.c:1734
void id_us_min(struct ID *id)
Definition: lib_id.c:313
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
short * BKE_object_material_len_p(struct Object *ob)
Definition: material.c:344
struct Palette * BKE_palette_add(struct Main *bmain, const char *name)
Definition: paint.c:764
void BKE_paint_palette_set(struct Paint *p, struct Palette *palette)
Definition: paint.c:719
struct PaletteColor * BKE_palette_color_add(struct Palette *palette)
Definition: paint.c:770
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE bool compare_v3v3(const float a[3], const float b[3], 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, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#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:816
void ED_undo_push(struct bContext *C, const char *str)
Definition: ed_undo.c:100
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:25
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:91
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
@ OPTYPE_UNDO
Definition: WM_types.h:148
#define ND_DATA
Definition: WM_types.h:456
#define NA_EDITED
Definition: WM_types.h:523
#define NC_MATERIAL
Definition: WM_types.h:330
#define NC_GPENCIL
Definition: WM_types.h:349
@ KM_CTRL
Definition: WM_types.h:239
@ KM_SHIFT
Definition: WM_types.h:238
#define ND_OB_SHADING
Definition: WM_types.h:406
#define ND_SPACE_VIEW3D
Definition: WM_types.h:471
#define NC_OBJECT
Definition: WM_types.h:329
#define ND_SHADING_LINKS
Definition: WM_types.h:427
#define NC_SPACE
Definition: WM_types.h:342
Scene scene
void eyedropper_color_sample_fl(bContext *C, const int m_xy[2], float r_col[3])
get the color from the screen.
static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, const int m_xy[2])
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 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_CANCEL
@ EYE_MODAL_SAMPLE_CONFIRM
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
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:3783
struct ColorManagedDisplay * display
Definition: BKE_main.h:121
struct MaterialGPencilStyle * gp_style
struct Palette * palette
ListBase colors
struct ToolSettings * toolsettings
ColorManagedDisplaySettings display_settings
GpPaint * gp_paint
GpVertexPaint * gp_vertexpaint
short val
Definition: WM_types.h:680
int xy[2]
Definition: WM_types.h:682
uint8_t modifier
Definition: WM_types.h:693
short type
Definition: WM_types.h:678
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
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:3479