Blender V4.3
eyedropper_colorband.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
19#include "MEM_guardedalloc.h"
20
21#include "DNA_screen_types.h"
22
23#include "BLI_bitmap_draw_2d.h"
24#include "BLI_math_vector.h"
25
26#include "BKE_colorband.hh"
27#include "BKE_context.hh"
28
29#include "RNA_access.hh"
30#include "RNA_prototypes.hh"
31
32#include "UI_interface.hh"
33
34#include "WM_api.hh"
35#include "WM_types.hh"
36
37#include "interface_intern.hh"
38
39#include "eyedropper_intern.hh"
40
41namespace blender::ui {
42
45 /* Alpha is currently fixed at 1.0, may support in future. */
52 bool is_undo;
53 bool is_set;
54};
55
56/* For user-data only. */
61
63{
64 ColorBand *band = nullptr;
65
67
68 PointerRNA rna_update_ptr = PointerRNA_NULL;
69 PropertyRNA *rna_update_prop = nullptr;
70 bool is_undo = true;
71
72 if (but == nullptr) {
73 /* pass */
74 }
75 else {
76 if (but->type == UI_BTYPE_COLORBAND) {
77 /* When invoked with a hotkey, we can find the band in 'but->poin'. */
78 band = (ColorBand *)but->poin;
79 }
80 else {
81 /* When invoked from a button it's in custom_data field. */
82 band = (ColorBand *)but->custom_data;
83 }
84
85 if (band) {
86 rna_update_ptr = but->rnapoin;
87 rna_update_prop = but->rnaprop;
88 is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
89 }
90 }
91
92 if (!band) {
93 const PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
94 if (ptr.data != nullptr) {
95 band = static_cast<ColorBand *>(ptr.data);
96
97 /* Set this to a sub-member of the property to trigger an update. */
98 rna_update_ptr = ptr;
99 rna_update_prop = &rna_ColorRamp_color_mode;
100 is_undo = RNA_struct_undo_check(ptr.type);
101 }
102 }
103
104 if (!band) {
105 return false;
106 }
107
108 EyedropperColorband *eye = MEM_new<EyedropperColorband>(__func__, EyedropperColorband{});
109 eye->color_band = band;
110 eye->init_color_band = *eye->color_band;
111 eye->ptr = rna_update_ptr;
112 eye->prop = rna_update_prop;
113 eye->is_undo = is_undo;
114
115 op->customdata = eye;
116
117 return true;
118}
119
122 const int m_xy[2])
123{
124 if (eye->event_xy_last[0] != m_xy[0] || eye->event_xy_last[1] != m_xy[1]) {
125 float4 col;
126 col[3] = 1.0f; /* TODO: sample alpha */
127 eyedropper_color_sample_fl(C, nullptr, m_xy, col);
128 eye->color_buffer.append(col);
129 copy_v2_v2_int(eye->event_xy_last, m_xy);
130 eye->is_set = true;
131 }
132}
133
134static bool eyedropper_colorband_sample_callback(int mx, int my, void *userdata)
135{
136 EyedropperColorband_Context *data = static_cast<EyedropperColorband_Context *>(userdata);
137 bContext *C = data->context;
138 EyedropperColorband *eye = data->eye;
139 const int cursor[2] = {mx, my};
140 eyedropper_colorband_sample_point(C, eye, cursor);
141 return true;
142}
143
146 const int m_xy[2])
147{
148 /* Since the mouse tends to move rather rapidly we use #BLI_bitmap_draw_2d_line_v2v2i
149 * to interpolate between the reported coordinates */
150 EyedropperColorband_Context userdata = {C, eye};
153}
154
156{
158
159 if (op->customdata) {
160 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
161 MEM_delete(eye);
162 op->customdata = nullptr;
163 }
164}
165
167{
168 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
169 /* Always filter, avoids noise in resulting color-band. */
170 const bool filter_samples = true;
172 reinterpret_cast<const float(*)[4]>(eye->color_buffer.data()),
173 eye->color_buffer.size(),
174 filter_samples);
175 eye->is_set = true;
176 if (eye->prop) {
177 RNA_property_update(C, &eye->ptr, eye->prop);
178 }
179}
180
182{
183 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
184 if (eye->is_set) {
185 *eye->color_band = eye->init_color_band;
186 if (eye->prop) {
187 RNA_property_update(C, &eye->ptr, eye->prop);
188 }
189 }
191}
192
193/* main modal status check */
194static int eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent *event)
195{
196 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
197 /* handle modal keymap */
198 if (event->type == EVT_MODAL_MAP) {
199 switch (event->val) {
200 case EYE_MODAL_CANCEL:
202 return OPERATOR_CANCELLED;
204 const bool is_undo = eye->is_undo;
208 /* Could support finished & undo-skip. */
209 return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
210 }
212 /* Enable accumulate and make first sample. */
213 eye->sample_start = true;
216 copy_v2_v2_int(eye->event_xy_last, event->xy);
217 break;
219 break;
220 }
221 }
222 else if (event->type == MOUSEMOVE) {
223 if (eye->sample_start) {
226 }
227 }
229}
230
232{
233 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
234 /* handle modal keymap */
235 if (event->type == EVT_MODAL_MAP) {
236 switch (event->val) {
239 return OPERATOR_CANCELLED;
243 return OPERATOR_FINISHED;
245 if (!eye->color_buffer.is_empty()) {
246 eye->color_buffer.pop_last();
248 }
249 break;
253 if (eye->color_buffer.size() == MAXCOLORBAND) {
255 return OPERATOR_FINISHED;
256 }
257 break;
259 *eye->color_band = eye->init_color_band;
260 if (eye->prop) {
261 RNA_property_update(C, &eye->ptr, eye->prop);
262 }
263 eye->color_buffer.clear();
264 break;
265 }
266 }
268}
269
270/* Modal Operator init */
271static int eyedropper_colorband_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
272{
273 /* init */
274 if (eyedropper_colorband_init(C, op)) {
275 wmWindow *win = CTX_wm_window(C);
276 /* Workaround for de-activating the button clearing the cursor, see #76794 */
279
280 /* add temp handler */
282
284 }
285 return OPERATOR_CANCELLED;
286}
287
288/* Repeat operator */
290{
291 /* init */
292 if (eyedropper_colorband_init(C, op)) {
293
294 /* do something */
295
296 /* cleanup */
298
299 return OPERATOR_FINISHED;
300 }
301 return OPERATOR_CANCELLED;
302}
303
305{
307 if (but && but->type == UI_BTYPE_COLORBAND) {
308 return true;
309 }
310 const PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
311 if (ptr.data != nullptr) {
312 return true;
313 }
314 return false;
315}
316
318{
319 /* identifiers */
320 ot->name = "Eyedropper Colorband";
321 ot->idname = "UI_OT_eyedropper_colorramp";
322 ot->description = "Sample a color band";
323
324 /* api callbacks */
330
331 /* flags */
333
334 /* properties */
335}
336
338{
339 /* identifiers */
340 ot->name = "Eyedropper Colorband (Points)";
341 ot->idname = "UI_OT_eyedropper_colorramp_point";
342 ot->description = "Point-sample a color band";
343
344 /* api callbacks */
350
351 /* flags */
353
354 /* properties */
355}
356
357} // namespace blender::ui
void BKE_colorband_init_from_table_rgba(ColorBand *coba, const float(*array)[4], int array_len, bool filter_samples)
Definition colorband.cc:279
#define MAXCOLORBAND
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
wmWindow * CTX_wm_window(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
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_v2_v2_int(int r[2], const int a[2])
@ OPERATOR_RUNNING_MODAL
Read Guarded memory(de)allocation.
constexpr PointerRNA PointerRNA_NULL
Definition RNA_types.hh:45
#define C
Definition RandGen.cpp:29
uiBut * UI_context_active_but_get(const bContext *C)
void UI_context_active_but_clear(bContext *C, wmWindow *win, ARegion *region)
@ UI_BTYPE_COLORBAND
bool UI_but_flag_is_set(uiBut *but, int flag)
@ UI_BUT_UNDO
@ OPTYPE_INTERNAL
Definition WM_types.hh:182
@ OPTYPE_BLOCKING
Definition WM_types.hh:164
@ OPTYPE_UNDO
Definition WM_types.hh:162
void eyedropper_color_sample_fl(bContext *C, Eyedropper *eye, const int event_xy[2], float r_col[3])
@ 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_CANCEL
@ EYE_MODAL_SAMPLE_CONFIRM
uint col
static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
static void eyedropper_colorband_cancel(bContext *C, wmOperator *op)
void UI_OT_eyedropper_colorramp(wmOperatorType *ot)
void UI_OT_eyedropper_colorramp_point(wmOperatorType *ot)
static int eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int eyedropper_colorband_invoke(bContext *C, wmOperator *op, const wmEvent *)
static int eyedropper_colorband_exec(bContext *C, wmOperator *op)
static void eyedropper_colorband_sample_segment(bContext *C, EyedropperColorband *eye, const int m_xy[2])
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 void eyedropper_colorband_sample_point(bContext *C, EyedropperColorband *eye, const int m_xy[2])
static int eyedropper_colorband_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool eyedropper_colorband_poll(bContext *C)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
bool RNA_struct_undo_check(const StructRNA *type)
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
void * custom_data
PropertyRNA * rnaprop
eButType type
PointerRNA rnapoin
short val
Definition WM_types.hh:724
int xy[2]
Definition WM_types.hh:726
short type
Definition WM_types.hh:722
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
void WM_cursor_modal_set(wmWindow *win, int val)
void WM_cursor_modal_restore(wmWindow *win)
@ WM_CURSOR_EYEDROPPER
Definition wm_cursors.hh:35
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ EVT_MODAL_MAP
@ MOUSEMOVE
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125