Blender V5.0
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
18
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 "WM_api.hh"
33#include "WM_types.hh"
34
35#include "interface_intern.hh"
36
37#include "eyedropper_intern.hh"
38
39namespace blender::ui {
40
42 int event_xy_last[2] = {};
43 /* Alpha is currently fixed at 1.0, may support in future. */
45 bool sample_start = false;
49 PropertyRNA *prop = nullptr;
50 bool is_undo = false;
51 bool is_set = false;
52};
53
54/* For user-data only. */
59
61{
62 ColorBand *band = nullptr;
63
65
66 PointerRNA rna_update_ptr = PointerRNA_NULL;
67 PropertyRNA *rna_update_prop = nullptr;
68 bool is_undo = true;
69
70 if (but == nullptr) {
71 /* pass */
72 }
73 else {
74 if (but->type == ButType::ColorBand) {
75 /* When invoked with a hotkey, we can find the band in 'but->poin'. */
76 band = (ColorBand *)but->poin;
77 }
78 else {
79 /* When invoked from a button it's in custom_data field. */
80 band = (ColorBand *)but->custom_data;
81 }
82
83 if (band) {
84 rna_update_ptr = but->rnapoin;
85 rna_update_prop = but->rnaprop;
86 is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
87 }
88 }
89
90 if (!band) {
91 const PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
92 if (ptr.data != nullptr) {
93 band = static_cast<ColorBand *>(ptr.data);
94
95 /* Set this to a sub-member of the property to trigger an update. */
96 rna_update_ptr = ptr;
97 rna_update_prop = &rna_ColorRamp_color_mode;
98 is_undo = RNA_struct_undo_check(ptr.type);
99 }
100 }
101
102 if (!band) {
103 return false;
104 }
105
106 EyedropperColorband *eye = MEM_new<EyedropperColorband>(__func__);
107 eye->color_band = band;
108 eye->init_color_band = *eye->color_band;
109 eye->ptr = rna_update_ptr;
110 eye->prop = rna_update_prop;
111 eye->is_undo = is_undo;
112
113 op->customdata = eye;
114
115 return true;
116}
117
120 const int m_xy[2])
121{
122 if (eye->event_xy_last[0] != m_xy[0] || eye->event_xy_last[1] != m_xy[1]) {
123 float4 col;
124 col[3] = 1.0f; /* TODO: sample alpha */
125 eyedropper_color_sample_fl(C, nullptr, m_xy, col);
126 eye->color_buffer.append(col);
127 copy_v2_v2_int(eye->event_xy_last, m_xy);
128 eye->is_set = true;
129 }
130}
131
132static bool eyedropper_colorband_sample_callback(int mx, int my, void *userdata)
133{
135 bContext *C = data->context;
136 EyedropperColorband *eye = data->eye;
137 const int cursor[2] = {mx, my};
139 return true;
140}
141
144 const int m_xy[2])
145{
146 /* Since the mouse tends to move rather rapidly we use #BLI_bitmap_draw_2d_line_v2v2i
147 * to interpolate between the reported coordinates */
148 EyedropperColorband_Context userdata = {C, eye};
151}
152
154{
156
157 if (op->customdata) {
158 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
159 MEM_delete(eye);
160 op->customdata = nullptr;
161 }
162}
163
165{
166 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
167 /* Always filter, avoids noise in resulting color-band. */
168 const bool filter_samples = true;
170 eye->color_band,
171 reinterpret_cast<const float (*)[4]>(eye->color_buffer.data()),
172 eye->color_buffer.size(),
173 filter_samples);
174 eye->is_set = true;
175 if (eye->prop) {
176 RNA_property_update(C, &eye->ptr, eye->prop);
177 }
178}
179
181{
182 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
183 if (eye->is_set) {
184 *eye->color_band = eye->init_color_band;
185 if (eye->prop) {
186 RNA_property_update(C, &eye->ptr, eye->prop);
187 }
188 }
190}
191
192/* main modal status check */
194 wmOperator *op,
195 const wmEvent *event)
196{
197 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
198 /* handle modal keymap */
199 if (event->type == EVT_MODAL_MAP) {
200 switch (event->val) {
201 case EYE_MODAL_CANCEL:
203 return OPERATOR_CANCELLED;
205 const bool is_undo = eye->is_undo;
209 /* Could support finished & undo-skip. */
210 return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
211 }
213 /* Enable accumulate and make first sample. */
214 eye->sample_start = true;
217 copy_v2_v2_int(eye->event_xy_last, event->xy);
218 break;
220 break;
221 }
222 }
223 else if (event->type == MOUSEMOVE) {
224 if (eye->sample_start) {
227 }
228 }
230}
231
233 wmOperator *op,
234 const wmEvent *event)
235{
236 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
237 /* handle modal keymap */
238 if (event->type == EVT_MODAL_MAP) {
239 switch (event->val) {
242 return OPERATOR_CANCELLED;
246 return OPERATOR_FINISHED;
248 if (!eye->color_buffer.is_empty()) {
249 eye->color_buffer.pop_last();
251 }
252 break;
256 if (eye->color_buffer.size() == MAXCOLORBAND) {
258 return OPERATOR_FINISHED;
259 }
260 break;
262 *eye->color_band = eye->init_color_band;
263 if (eye->prop) {
264 RNA_property_update(C, &eye->ptr, eye->prop);
265 }
266 eye->color_buffer.clear();
267 break;
268 }
269 }
271}
272
273/* Modal Operator init */
275 wmOperator *op,
276 const wmEvent * /*event*/)
277{
278 /* init */
279 if (eyedropper_colorband_init(C, op)) {
280 wmWindow *win = CTX_wm_window(C);
281 /* Workaround for de-activating the button clearing the cursor, see #76794 */
284
285 /* add temp handler */
287
289 }
290 return OPERATOR_CANCELLED;
291}
292
293/* Repeat operator */
295{
296 /* init */
297 if (eyedropper_colorband_init(C, op)) {
298
299 /* do something */
300
301 /* cleanup */
303
304 return OPERATOR_FINISHED;
305 }
306 return OPERATOR_CANCELLED;
307}
308
310{
312 if (but && but->type == ButType::ColorBand) {
313 return true;
314 }
315 const PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
316 if (ptr.data != nullptr) {
317 return true;
318 }
319 return false;
320}
321
323{
324 /* identifiers */
325 ot->name = "Eyedropper Colorband";
326 ot->idname = "UI_OT_eyedropper_colorramp";
327 ot->description = "Sample a color band";
328
329 /* API callbacks. */
335
336 /* flags */
338
339 /* properties */
340}
341
343{
344 /* identifiers */
345 ot->name = "Eyedropper Colorband (Points)";
346 ot->idname = "UI_OT_eyedropper_colorramp_point";
347 ot->description = "Point-sample a color band";
348
349 /* API callbacks. */
355
356 /* flags */
358
359 /* properties */
360}
361
362} // 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_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
@ UI_BUT_UNDO
uiBut * UI_context_active_but_get(const bContext *C)
void UI_context_active_but_clear(bContext *C, wmWindow *win, ARegion *region)
bool UI_but_flag_is_set(uiBut *but, int flag)
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_BLOCKING
Definition WM_types.hh:184
@ OPTYPE_UNDO
Definition WM_types.hh:182
BMesh const char void * data
bool eyedropper_color_sample_fl(bContext *C, Eyedropper *eye, const int event_xy[2], float r_col[3])
@ 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
static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
static void eyedropper_colorband_cancel(bContext *C, wmOperator *op)
static wmOperatorStatus eyedropper_colorband_modal(bContext *C, wmOperator *op, const wmEvent *event)
void UI_OT_eyedropper_colorramp(wmOperatorType *ot)
void UI_OT_eyedropper_colorramp_point(wmOperatorType *ot)
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 wmOperatorStatus eyedropper_colorband_invoke(bContext *C, wmOperator *op, const wmEvent *)
static bool eyedropper_colorband_sample_callback(int mx, int my, void *userdata)
static wmOperatorStatus eyedropper_colorband_exec(bContext *C, wmOperator *op)
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 wmOperatorStatus eyedropper_colorband_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool eyedropper_colorband_poll(bContext *C)
VecBase< float, 4 > float4
const PointerRNA PointerRNA_NULL
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
bool RNA_struct_undo_check(const StructRNA *type)
void * custom_data
PropertyRNA * rnaprop
ButType type
PointerRNA rnapoin
wmEventType type
Definition WM_types.hh:757
short val
Definition WM_types.hh:759
int xy[2]
Definition WM_types.hh:761
void WM_cursor_modal_set(wmWindow *win, int val)
void WM_cursor_modal_restore(wmWindow *win)
@ WM_CURSOR_EYEDROPPER
Definition wm_cursors.hh:36
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ EVT_MODAL_MAP
@ MOUSEMOVE
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237