Blender  V2.93
interface_eyedropper_colorband.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 
34 #include "MEM_guardedalloc.h"
35 
36 #include "DNA_screen_types.h"
37 
38 #include "BLI_bitmap_draw_2d.h"
39 #include "BLI_math_vector.h"
40 
41 #include "BKE_colorband.h"
42 #include "BKE_context.h"
43 
44 #include "RNA_access.h"
45 
46 #include "UI_interface.h"
47 
48 #include "WM_api.h"
49 #include "WM_types.h"
50 
51 #include "interface_intern.h"
52 
54 
55 typedef struct Colorband_RNAUpdateCb {
59 
60 typedef struct EyedropperColorband {
61  int last_x, last_y;
62  /* Alpha is currently fixed at 1.0, may support in future. */
71  bool is_undo;
72  bool is_set;
74 
75 /* For user-data only. */
79 };
80 
82 {
83  ColorBand *band = NULL;
84 
86 
87  PointerRNA rna_update_ptr = PointerRNA_NULL;
88  PropertyRNA *rna_update_prop = NULL;
89  bool is_undo = true;
90 
91  if (but == NULL) {
92  /* pass */
93  }
94  else {
95  if (but->type == UI_BTYPE_COLORBAND) {
96  /* When invoked with a hotkey, we can find the band in 'but->poin'. */
97  band = (ColorBand *)but->poin;
98  }
99  else {
100  /* When invoked from a button it's in custom_data field. */
101  band = (ColorBand *)but->custom_data;
102  }
103 
104  if (band) {
105  rna_update_ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
106  rna_update_prop = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
107  is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
108  }
109  }
110 
111  if (!band) {
112  const PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
113  if (ptr.data != NULL) {
114  band = ptr.data;
115 
116  /* Set this to a sub-member of the property to trigger an update. */
117  extern PropertyRNA rna_ColorRamp_color_mode;
118  rna_update_ptr = ptr;
119  rna_update_prop = &rna_ColorRamp_color_mode;
120  is_undo = RNA_struct_undo_check(ptr.type);
121  }
122  }
123 
124  if (!band) {
125  return false;
126  }
127 
128  EyedropperColorband *eye = MEM_callocN(sizeof(EyedropperColorband), __func__);
129  eye->color_buffer_alloc = 16;
130  eye->color_buffer = MEM_mallocN(sizeof(*eye->color_buffer) * eye->color_buffer_alloc, __func__);
131  eye->color_buffer_len = 0;
132  eye->color_band = band;
133  eye->init_color_band = *eye->color_band;
134  eye->ptr = rna_update_ptr;
135  eye->prop = rna_update_prop;
136  eye->is_undo = is_undo;
137 
138  op->customdata = eye;
139 
140  return true;
141 }
142 
144  EyedropperColorband *eye,
145  int mx,
146  int my)
147 {
148  if (eye->last_x != mx || eye->last_y != my) {
149  float col[4];
150  col[3] = 1.0f; /* TODO: sample alpha */
151  eyedropper_color_sample_fl(C, mx, my, col);
152  if (eye->color_buffer_len + 1 == eye->color_buffer_alloc) {
153  eye->color_buffer_alloc *= 2;
155  sizeof(*eye->color_buffer) * eye->color_buffer_alloc);
156  }
158  eye->color_buffer_len += 1;
159  eye->last_x = mx;
160  eye->last_y = my;
161  eye->is_set = true;
162  }
163 }
164 
165 static bool eyedropper_colorband_sample_callback(int mx, int my, void *userdata)
166 {
167  struct EyedropperColorband_Context *data = userdata;
168  bContext *C = data->context;
169  EyedropperColorband *eye = data->eye;
171  return true;
172 }
173 
176  int mx,
177  int my)
178 {
179  /* Since the mouse tends to move rather rapidly we use #BLI_bitmap_draw_2d_line_v2v2i
180  * to interpolate between the reported coordinates */
181  struct EyedropperColorband_Context userdata = {C, eye};
182  const int p1[2] = {eye->last_x, eye->last_y};
183  const int p2[2] = {mx, my};
185 }
186 
188 {
190 
191  if (op->customdata) {
194  MEM_freeN(eye);
195  op->customdata = NULL;
196  }
197 }
198 
200 {
202  /* Always filter, avoids noise in resulting color-band. */
203  const bool filter_samples = true;
205  eye->color_band, eye->color_buffer, eye->color_buffer_len, filter_samples);
206  eye->is_set = true;
207  if (eye->prop) {
209  }
210 }
211 
213 {
215  if (eye->is_set) {
217  if (eye->prop) {
219  }
220  }
222 }
223 
224 /* main modal status check */
225 static int eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent *event)
226 {
228  /* handle modal keymap */
229  if (event->type == EVT_MODAL_MAP) {
230  switch (event->val) {
231  case EYE_MODAL_CANCEL:
233  return OPERATOR_CANCELLED;
235  const bool is_undo = eye->is_undo;
236  eyedropper_colorband_sample_segment(C, eye, event->x, event->y);
239  /* Could support finished & undo-skip. */
240  return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
241  }
243  /* enable accum and make first sample */
244  eye->sample_start = true;
245  eyedropper_colorband_sample_point(C, eye, event->x, event->y);
247  eye->last_x = event->x;
248  eye->last_y = event->y;
249  break;
251  break;
252  }
253  }
254  else if (event->type == MOUSEMOVE) {
255  if (eye->sample_start) {
256  eyedropper_colorband_sample_segment(C, eye, event->x, event->y);
258  }
259  }
260  return OPERATOR_RUNNING_MODAL;
261 }
262 
264 {
266  /* handle modal keymap */
267  if (event->type == EVT_MODAL_MAP) {
268  switch (event->val) {
271  return OPERATOR_CANCELLED;
275  return OPERATOR_FINISHED;
277  if (eye->color_buffer_len > 0) {
278  eye->color_buffer_len -= 1;
280  }
281  break;
283  eyedropper_colorband_sample_point(C, eye, event->x, event->y);
287  return OPERATOR_FINISHED;
288  }
289  break;
292  if (eye->prop) {
294  }
295  eye->color_buffer_len = 0;
296  break;
297  }
298  }
299  return OPERATOR_RUNNING_MODAL;
300 }
301 
302 /* Modal Operator init */
304 {
305  /* init */
306  if (eyedropper_colorband_init(C, op)) {
307  wmWindow *win = CTX_wm_window(C);
308  /* Workaround for de-activating the button clearing the cursor, see T76794 */
311 
312  /* add temp handler */
314 
315  return OPERATOR_RUNNING_MODAL;
316  }
317  return OPERATOR_CANCELLED;
318 }
319 
320 /* Repeat operator */
322 {
323  /* init */
324  if (eyedropper_colorband_init(C, op)) {
325 
326  /* do something */
327 
328  /* cleanup */
330 
331  return OPERATOR_FINISHED;
332  }
333  return OPERATOR_CANCELLED;
334 }
335 
337 {
339  if (but && but->type == UI_BTYPE_COLORBAND) {
340  return true;
341  }
342  const PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
343  if (ptr.data != NULL) {
344  return true;
345  }
346  return false;
347 }
348 
350 {
351  /* identifiers */
352  ot->name = "Eyedropper Colorband";
353  ot->idname = "UI_OT_eyedropper_colorramp";
354  ot->description = "Sample a color band";
355 
356  /* api callbacks */
362 
363  /* flags */
365 
366  /* properties */
367 }
368 
370 {
371  /* identifiers */
372  ot->name = "Eyedropper Colorband (Points)";
373  ot->idname = "UI_OT_eyedropper_colorramp_point";
374  ot->description = "Point-sample a color band";
375 
376  /* api callbacks */
382 
383  /* flags */
385 
386  /* properties */
387 }
typedef float(TangentPoint)[2]
#define MAXCOLORBAND
Definition: BKE_colorband.h:32
void BKE_colorband_init_from_table_rgba(struct ColorBand *coba, const float(*array)[4], const int array_len, bool filter_sample)
Definition: colorband.c:293
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:456
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
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])
#define UNUSED(x)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
StructRNA RNA_ColorRamp
#define C
Definition: RandGen.cpp:39
@ UI_BUT_UNDO
Definition: UI_interface.h:208
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:364
bool UI_but_flag_is_set(uiBut *but, int flag)
Definition: interface.c:6087
@ OPTYPE_INTERNAL
Definition: WM_types.h:175
@ OPTYPE_BLOCKING
Definition: WM_types.h:157
@ OPTYPE_UNDO
Definition: WM_types.h:155
uint col
void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
get the color from the screen.
static void eyedropper_colorband_sample_point(bContext *C, EyedropperColorband *eye, int mx, int my)
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))
static void eyedropper_colorband_sample_segment(bContext *C, EyedropperColorband *eye, int mx, int my)
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 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_POINT_CANCEL
@ EYE_MODAL_POINT_SAMPLE
@ EYE_MODAL_POINT_CONFIRM
@ EYE_MODAL_POINT_REMOVE_LAST
@ EYE_MODAL_SAMPLE_BEGIN
@ EYE_MODAL_SAMPLE_RESET
@ EYE_MODAL_SAMPLE_CONFIRM
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
const PointerRNA PointerRNA_NULL
Definition: rna_access.c:71
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2317
bool RNA_struct_undo_check(const StructRNA *type)
Definition: rna_access.c:802
struct StructRNA * type
Definition: RNA_types.h:51
void * data
Definition: RNA_types.h:52
void * custom_data
eButType type
char * poin
void * func_argN
int y
Definition: WM_types.h:581
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
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
void WM_cursor_modal_set(wmWindow *win, int val)
Definition: wm_cursors.c:207
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:216
@ WM_CURSOR_EYEDROPPER
Definition: wm_cursors.h:51
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ EVT_MODAL_MAP
@ MOUSEMOVE
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156