Blender V4.5
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 "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
44 int event_xy_last[2] = {};
45 /* Alpha is currently fixed at 1.0, may support in future. */
47 bool sample_start = false;
51 PropertyRNA *prop = nullptr;
52 bool is_undo = false;
53 bool is_set = false;
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__);
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{
137 bContext *C = data->context;
138 EyedropperColorband *eye = data->eye;
139 const int cursor[2] = {mx, my};
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 */
195 wmOperator *op,
196 const wmEvent *event)
197{
198 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
199 /* handle modal keymap */
200 if (event->type == EVT_MODAL_MAP) {
201 switch (event->val) {
202 case EYE_MODAL_CANCEL:
204 return OPERATOR_CANCELLED;
206 const bool is_undo = eye->is_undo;
210 /* Could support finished & undo-skip. */
211 return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
212 }
214 /* Enable accumulate and make first sample. */
215 eye->sample_start = true;
218 copy_v2_v2_int(eye->event_xy_last, event->xy);
219 break;
221 break;
222 }
223 }
224 else if (event->type == MOUSEMOVE) {
225 if (eye->sample_start) {
228 }
229 }
231}
232
234 wmOperator *op,
235 const wmEvent *event)
236{
237 EyedropperColorband *eye = static_cast<EyedropperColorband *>(op->customdata);
238 /* handle modal keymap */
239 if (event->type == EVT_MODAL_MAP) {
240 switch (event->val) {
243 return OPERATOR_CANCELLED;
247 return OPERATOR_FINISHED;
249 if (!eye->color_buffer.is_empty()) {
250 eye->color_buffer.pop_last();
252 }
253 break;
257 if (eye->color_buffer.size() == MAXCOLORBAND) {
259 return OPERATOR_FINISHED;
260 }
261 break;
263 *eye->color_band = eye->init_color_band;
264 if (eye->prop) {
265 RNA_property_update(C, &eye->ptr, eye->prop);
266 }
267 eye->color_buffer.clear();
268 break;
269 }
270 }
272}
273
274/* Modal Operator init */
276 wmOperator *op,
277 const wmEvent * /*event*/)
278{
279 /* init */
280 if (eyedropper_colorband_init(C, op)) {
281 wmWindow *win = CTX_wm_window(C);
282 /* Workaround for de-activating the button clearing the cursor, see #76794 */
285
286 /* add temp handler */
288
290 }
291 return OPERATOR_CANCELLED;
292}
293
294/* Repeat operator */
296{
297 /* init */
298 if (eyedropper_colorband_init(C, op)) {
299
300 /* do something */
301
302 /* cleanup */
304
305 return OPERATOR_FINISHED;
306 }
307 return OPERATOR_CANCELLED;
308}
309
311{
313 if (but && but->type == UI_BTYPE_COLORBAND) {
314 return true;
315 }
316 const PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
317 if (ptr.data != nullptr) {
318 return true;
319 }
320 return false;
321}
322
324{
325 /* identifiers */
326 ot->name = "Eyedropper Colorband";
327 ot->idname = "UI_OT_eyedropper_colorramp";
328 ot->description = "Sample a color band";
329
330 /* API callbacks. */
336
337 /* flags */
339
340 /* properties */
341}
342
344{
345 /* identifiers */
346 ot->name = "Eyedropper Colorband (Points)";
347 ot->idname = "UI_OT_eyedropper_colorramp_point";
348 ot->description = "Point-sample a color band";
349
350 /* API callbacks. */
356
357 /* flags */
359
360 /* properties */
361}
362
363} // 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:278
#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
uiBut * UI_context_active_but_get(const bContext *C)
void UI_context_active_but_clear(bContext *C, wmWindow *win, ARegion *region)
@ UI_BTYPE_COLORBAND
@ UI_BUT_UNDO
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_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)
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
eButType type
PointerRNA rnapoin
wmEventType type
Definition WM_types.hh:754
short val
Definition WM_types.hh:756
int xy[2]
Definition WM_types.hh:758
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:4227
wmOperatorType * ot
Definition wm_files.cc:4226