Blender  V3.3
eyedropper_colorband.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 
18 #include "MEM_guardedalloc.h"
19 
20 #include "DNA_screen_types.h"
21 
22 #include "BLI_bitmap_draw_2d.h"
23 #include "BLI_math_vector.h"
24 
25 #include "BKE_colorband.h"
26 #include "BKE_context.h"
27 
28 #include "RNA_access.h"
29 #include "RNA_prototypes.h"
30 
31 #include "UI_interface.h"
32 
33 #include "WM_api.h"
34 #include "WM_types.h"
35 
36 #include "interface_intern.h"
37 
38 #include "eyedropper_intern.h"
39 
40 typedef struct Colorband_RNAUpdateCb {
44 
45 typedef struct EyedropperColorband {
46  int event_xy_last[2];
47  /* Alpha is currently fixed at 1.0, may support in future. */
56  bool is_undo;
57  bool is_set;
59 
60 /* For user-data only. */
64 };
65 
67 {
68  ColorBand *band = NULL;
69 
71 
72  PointerRNA rna_update_ptr = PointerRNA_NULL;
73  PropertyRNA *rna_update_prop = NULL;
74  bool is_undo = true;
75 
76  if (but == NULL) {
77  /* pass */
78  }
79  else {
80  if (but->type == UI_BTYPE_COLORBAND) {
81  /* When invoked with a hotkey, we can find the band in 'but->poin'. */
82  band = (ColorBand *)but->poin;
83  }
84  else {
85  /* When invoked from a button it's in custom_data field. */
86  band = (ColorBand *)but->custom_data;
87  }
88 
89  if (band) {
90  rna_update_ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
91  rna_update_prop = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
92  is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
93  }
94  }
95 
96  if (!band) {
97  const PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
98  if (ptr.data != NULL) {
99  band = ptr.data;
100 
101  /* Set this to a sub-member of the property to trigger an update. */
102  rna_update_ptr = ptr;
103  rna_update_prop = &rna_ColorRamp_color_mode;
104  is_undo = RNA_struct_undo_check(ptr.type);
105  }
106  }
107 
108  if (!band) {
109  return false;
110  }
111 
112  EyedropperColorband *eye = MEM_callocN(sizeof(EyedropperColorband), __func__);
113  eye->color_buffer_alloc = 16;
114  eye->color_buffer = MEM_mallocN(sizeof(*eye->color_buffer) * eye->color_buffer_alloc, __func__);
115  eye->color_buffer_len = 0;
116  eye->color_band = band;
117  eye->init_color_band = *eye->color_band;
118  eye->ptr = rna_update_ptr;
119  eye->prop = rna_update_prop;
120  eye->is_undo = is_undo;
121 
122  op->customdata = eye;
123 
124  return true;
125 }
126 
128  EyedropperColorband *eye,
129  const int m_xy[2])
130 {
131  if (eye->event_xy_last[0] != m_xy[0] || eye->event_xy_last[1] != m_xy[1]) {
132  float col[4];
133  col[3] = 1.0f; /* TODO: sample alpha */
135  if (eye->color_buffer_len + 1 == eye->color_buffer_alloc) {
136  eye->color_buffer_alloc *= 2;
138  sizeof(*eye->color_buffer) * eye->color_buffer_alloc);
139  }
141  eye->color_buffer_len += 1;
142  copy_v2_v2_int(eye->event_xy_last, m_xy);
143  eye->is_set = true;
144  }
145 }
146 
147 static bool eyedropper_colorband_sample_callback(int mx, int my, void *userdata)
148 {
149  struct EyedropperColorband_Context *data = userdata;
150  bContext *C = data->context;
151  EyedropperColorband *eye = data->eye;
152  const int cursor[2] = {mx, my};
154  return true;
155 }
156 
159  const int m_xy[2])
160 {
161  /* Since the mouse tends to move rather rapidly we use #BLI_bitmap_draw_2d_line_v2v2i
162  * to interpolate between the reported coordinates */
163  struct EyedropperColorband_Context userdata = {C, eye};
166 }
167 
169 {
171 
172  if (op->customdata) {
175  MEM_freeN(eye);
176  op->customdata = NULL;
177  }
178 }
179 
181 {
183  /* Always filter, avoids noise in resulting color-band. */
184  const bool filter_samples = true;
186  eye->color_band, eye->color_buffer, eye->color_buffer_len, filter_samples);
187  eye->is_set = true;
188  if (eye->prop) {
190  }
191 }
192 
194 {
196  if (eye->is_set) {
198  if (eye->prop) {
200  }
201  }
203 }
204 
205 /* main modal status check */
206 static int eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent *event)
207 {
209  /* handle modal keymap */
210  if (event->type == EVT_MODAL_MAP) {
211  switch (event->val) {
212  case EYE_MODAL_CANCEL:
214  return OPERATOR_CANCELLED;
216  const bool is_undo = eye->is_undo;
220  /* Could support finished & undo-skip. */
221  return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
222  }
224  /* enable accum and make first sample */
225  eye->sample_start = true;
229  break;
231  break;
232  }
233  }
234  else if (event->type == MOUSEMOVE) {
235  if (eye->sample_start) {
238  }
239  }
240  return OPERATOR_RUNNING_MODAL;
241 }
242 
244 {
246  /* handle modal keymap */
247  if (event->type == EVT_MODAL_MAP) {
248  switch (event->val) {
251  return OPERATOR_CANCELLED;
255  return OPERATOR_FINISHED;
257  if (eye->color_buffer_len > 0) {
258  eye->color_buffer_len -= 1;
260  }
261  break;
267  return OPERATOR_FINISHED;
268  }
269  break;
272  if (eye->prop) {
274  }
275  eye->color_buffer_len = 0;
276  break;
277  }
278  }
279  return OPERATOR_RUNNING_MODAL;
280 }
281 
282 /* Modal Operator init */
284 {
285  /* init */
286  if (eyedropper_colorband_init(C, op)) {
287  wmWindow *win = CTX_wm_window(C);
288  /* Workaround for de-activating the button clearing the cursor, see T76794 */
291 
292  /* add temp handler */
294 
295  return OPERATOR_RUNNING_MODAL;
296  }
297  return OPERATOR_CANCELLED;
298 }
299 
300 /* Repeat operator */
302 {
303  /* init */
304  if (eyedropper_colorband_init(C, op)) {
305 
306  /* do something */
307 
308  /* cleanup */
310 
311  return OPERATOR_FINISHED;
312  }
313  return OPERATOR_CANCELLED;
314 }
315 
317 {
319  if (but && but->type == UI_BTYPE_COLORBAND) {
320  return true;
321  }
322  const PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
323  if (ptr.data != NULL) {
324  return true;
325  }
326  return false;
327 }
328 
330 {
331  /* identifiers */
332  ot->name = "Eyedropper Colorband";
333  ot->idname = "UI_OT_eyedropper_colorramp";
334  ot->description = "Sample a color band";
335 
336  /* api callbacks */
342 
343  /* flags */
345 
346  /* properties */
347 }
348 
350 {
351  /* identifiers */
352  ot->name = "Eyedropper Colorband (Points)";
353  ot->idname = "UI_OT_eyedropper_colorramp_point";
354  ot->description = "Point-sample a color band";
355 
356  /* api callbacks */
362 
363  /* flags */
365 
366  /* properties */
367 }
typedef float(TangentPoint)[2]
#define MAXCOLORBAND
Definition: BKE_colorband.h:16
void BKE_colorband_init_from_table_rgba(struct ColorBand *coba, const float(*array)[4], int array_len, bool filter_sample)
Definition: colorband.c:277
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:473
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
void BLI_bitmap_draw_2d_line_v2v2i(const int p1[2], const int p2[2], bool(*callback)(int, int, void *), void *user_data)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
#define UNUSED(x)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
#define C
Definition: RandGen.cpp:25
@ UI_BUT_UNDO
Definition: UI_interface.h:205
uiBut * UI_context_active_but_get(const struct bContext *C)
void UI_context_active_but_clear(struct bContext *C, struct wmWindow *win, struct ARegion *region)
@ UI_BTYPE_COLORBAND
Definition: UI_interface.h:360
bool UI_but_flag_is_set(uiBut *but, int flag)
Definition: interface.cc:5868
@ OPTYPE_INTERNAL
Definition: WM_types.h:168
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
@ OPTYPE_UNDO
Definition: WM_types.h:148
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_colorband_sample_point(bContext *C, EyedropperColorband *eye, const int m_xy[2])
static bool eyedropper_colorband_poll(bContext *C)
void UI_OT_eyedropper_colorramp_point(wmOperatorType *ot)
static int eyedropper_colorband_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
void UI_OT_eyedropper_colorramp(wmOperatorType *ot)
static void eyedropper_colorband_apply(bContext *C, wmOperator *op)
static bool eyedropper_colorband_sample_callback(int mx, int my, void *userdata)
static void eyedropper_colorband_exit(bContext *C, wmOperator *op)
static int eyedropper_colorband_exec(bContext *C, wmOperator *op)
struct EyedropperColorband EyedropperColorband
static void eyedropper_colorband_cancel(bContext *C, wmOperator *op)
static void eyedropper_colorband_sample_segment(bContext *C, EyedropperColorband *eye, const int m_xy[2])
static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
struct Colorband_RNAUpdateCb Colorband_RNAUpdateCb
static int eyedropper_colorband_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent *event)
@ EYE_MODAL_SAMPLE_BEGIN
@ EYE_MODAL_SAMPLE_RESET
@ EYE_MODAL_CANCEL
@ EYE_MODAL_SAMPLE_CONFIRM
@ EYE_MODAL_POINT_CANCEL
@ EYE_MODAL_POINT_SAMPLE
@ EYE_MODAL_POINT_CONFIRM
@ EYE_MODAL_POINT_REMOVE_LAST
uint col
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
const PointerRNA PointerRNA_NULL
Definition: rna_access.c:61
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2138
bool RNA_struct_undo_check(const StructRNA *type)
Definition: rna_access.c:660
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
void * custom_data
eButType type
char * poin
void * func_argN
short val
Definition: WM_types.h:680
int xy[2]
Definition: WM_types.h:682
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
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
void WM_cursor_modal_set(wmWindow *win, int val)
Definition: wm_cursors.c:191
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:200
@ WM_CURSOR_EYEDROPPER
Definition: wm_cursors.h:35
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ EVT_MODAL_MAP
@ MOUSEMOVE
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479