Blender  V3.3
wm_operator_utils.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include <math.h>
10 
11 #include "BLI_string.h"
12 #include "BLI_utildefines.h"
13 
14 #include "BKE_context.h"
15 #include "BKE_global.h"
16 #include "BKE_layer.h"
17 
18 #include "RNA_access.h"
19 #include "RNA_define.h"
20 
21 #include "WM_api.h" /* Own include. */
22 #include "WM_types.h"
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "ED_object.h"
27 #include "ED_screen.h"
28 
29 /* -------------------------------------------------------------------- */
33 int WM_operator_flag_only_pass_through_on_press(int retval, const struct wmEvent *event)
34 {
35  if (event->val != KM_PRESS) {
36  if (retval & OPERATOR_PASS_THROUGH) {
37  /* Operators that use this function should either finish or cancel,
38  * otherwise non-press events will be passed through to other key-map items. */
39  BLI_assert((retval & ~OPERATOR_PASS_THROUGH) != 0);
40  if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) {
41  retval &= ~OPERATOR_PASS_THROUGH;
42  }
43  }
44  }
45  return retval;
46 }
47 
50 /* -------------------------------------------------------------------- */
59 typedef struct ValueInteraction {
60  struct {
61  float mval[2];
62  float prop_value;
63  } init;
64  struct {
65  float prop_value;
66  bool is_snap;
67  bool is_precise;
68  } prev;
69  float range[2];
70 
71  struct {
76 
78  ValueInteraction *inter,
79  const wmEvent *event,
80  const float value_final,
81  const float range[2])
82 {
83 
84  inter->context_vars.area = CTX_wm_area(C);
86 
87  inter->init.mval[0] = event->mval[0];
88  inter->init.mval[1] = event->mval[1];
89  inter->init.prop_value = value_final;
90  inter->prev.prop_value = value_final;
91  inter->range[0] = range[0];
92  inter->range[1] = range[1];
93 }
94 
96  bContext *C, ValueInteraction *inter, const wmEvent *event, PointerRNA *ptr, PropertyRNA *prop)
97 {
98  float range[2];
99  float step, precision;
100  RNA_property_float_ui_range(ptr, prop, &range[0], &range[1], &step, &precision);
101  const float value_final = RNA_property_float_get(ptr, prop);
102  interactive_value_init(C, inter, event, value_final, range);
103 }
104 
106 {
108 }
109 
111  const wmEvent *event,
112  float *r_value_final)
113 {
114  const int mval_axis = 0;
115 
116  const float value_scale = 4.0f; /* Could be option. */
117  const float value_range = inter->range[1] - inter->range[0];
118  const int mval_curr = event->mval[mval_axis];
119  const int mval_init = inter->init.mval[mval_axis];
120  float value_delta = (inter->init.prop_value +
121  (((float)(mval_curr - mval_init) / inter->context_vars.region->winx) *
122  value_range)) *
123  value_scale;
124  if (event->modifier & KM_CTRL) {
125  const double snap = 0.1;
126  value_delta = (float)roundf((double)value_delta / snap) * snap;
127  }
128  if (event->modifier & KM_SHIFT) {
129  value_delta *= 0.1f;
130  }
131  const float value_final = inter->init.prop_value + value_delta;
132 
133  const bool changed = value_final != inter->prev.prop_value;
134  if (changed) {
135  /* set the property for the operator and call its modal function */
136  char str[64];
137  SNPRINTF(str, "%.4f", value_final);
139  }
140 
141  inter->prev.prop_value = value_final;
142  inter->prev.is_snap = (event->modifier & KM_CTRL) != 0;
143  inter->prev.is_precise = (event->modifier & KM_SHIFT) != 0;
144 
145  *r_value_final = value_final;
146  return changed;
147 }
148 
151 /* -------------------------------------------------------------------- */
160  bool is_active;
161  bool is_first;
162 
164 
169 };
170 
171 /* Internal callback to free. */
173 {
174  struct ObCustomData_ForEditMode *cd = op->customdata;
175  if (cd) {
177 
178  for (uint ob_index = 0; ob_index < cd->objects_len; ob_index++) {
179  struct XFormObjectData *xod = cd->objects_xform[ob_index];
180  if (xod != NULL) {
182  }
183  }
184  MEM_freeN(cd->objects);
186  MEM_freeN(cd);
187  }
188 
189  G.moving &= ~G_TRANSFORM_EDIT;
190 }
191 
193 {
194  struct ObCustomData_ForEditMode *cd = op->customdata;
195  for (uint ob_index = 0; ob_index < cd->objects_len; ob_index++) {
198  }
199 }
200 
202 {
204 }
205 
206 static int op_generic_value_invoke(bContext *C, wmOperator *op, const wmEvent *event)
207 {
208  if (RNA_property_is_set(op->ptr, op->type->prop)) {
209  return WM_operator_call_notest(C, op);
210  }
211 
212  ViewLayer *view_layer = CTX_data_view_layer(C);
215  view_layer, CTX_wm_view3d(C), &objects_len);
216  if (objects_len == 0) {
218  return OPERATOR_CANCELLED;
219  }
220 
221  struct ObCustomData_ForEditMode *cd = MEM_callocN(sizeof(*cd), __func__);
223  cd->wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
224  cd->is_active = !cd->wait_for_input;
225  cd->is_first = true;
226  cd->objects = objects;
227  cd->objects_len = objects_len;
228 
229  if (cd->wait_for_input == false) {
230  interactive_value_init_from_property(C, &cd->inter, event, op->ptr, op->type->prop);
231  }
232 
233  cd->objects_xform = MEM_callocN(sizeof(*cd->objects_xform) * objects_len, __func__);
234 
235  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
236  Object *obedit = objects[ob_index];
238  }
239 
240  op->customdata = cd;
241 
243  G.moving |= G_TRANSFORM_EDIT;
244 
245  return OPERATOR_RUNNING_MODAL;
246 }
247 
248 static int op_generic_value_modal(bContext *C, wmOperator *op, const wmEvent *event)
249 {
250  struct ObCustomData_ForEditMode *cd = op->customdata;
251 
252  /* Special case, check if we release the event that activated this operator. */
253  if ((event->type == cd->launch_event) && (event->val == KM_RELEASE)) {
254  if (cd->wait_for_input == false) {
256  return OPERATOR_FINISHED;
257  }
258  }
259 
260  switch (event->type) {
261  case MOUSEMOVE:
262  case EVT_LEFTCTRLKEY:
263  case EVT_RIGHTCTRLKEY:
264  case EVT_LEFTSHIFTKEY:
265  case EVT_RIGHTSHIFTKEY: {
266  float value_final;
267  if (cd->is_active && interactive_value_update(&cd->inter, event, &value_final)) {
269 
270  RNA_property_float_set(op->ptr, op->type->prop, value_final);
271  if (cd->is_first == false) {
273  }
274 
275  wm->op_undo_depth++;
276  int retval = op->type->exec(C, op);
277  OPERATOR_RETVAL_CHECK(retval);
278  wm->op_undo_depth--;
279 
280  cd->is_first = false;
281 
282  if ((retval & OPERATOR_FINISHED) == 0) {
284  return OPERATOR_CANCELLED;
285  }
286  }
287  break;
288  }
289  case EVT_RETKEY:
290  case EVT_PADENTER:
291  case LEFTMOUSE: {
292  if (cd->wait_for_input) {
293  if (event->val == KM_PRESS) {
294  if (cd->is_active == false) {
295  cd->is_active = true;
296  interactive_value_init_from_property(C, &cd->inter, event, op->ptr, op->type->prop);
297  }
298  }
299  else if (event->val == KM_RELEASE) {
300  if (cd->is_active == true) {
302  return OPERATOR_FINISHED;
303  }
304  }
305  }
306  else {
307  if (event->val == KM_RELEASE) {
309  return OPERATOR_FINISHED;
310  }
311  }
312  break;
313  }
314  case EVT_ESCKEY:
315  case RIGHTMOUSE: {
316  if (event->val == KM_PRESS) {
317  if (cd->is_active == true) {
319  }
321  return OPERATOR_CANCELLED;
322  }
323  break;
324  }
325  }
326  return OPERATOR_RUNNING_MODAL;
327 }
328 
330 {
331  PropertyRNA *prop;
332 
333  BLI_assert(ot->modal == NULL);
334  BLI_assert(ot->invoke == NULL);
335  BLI_assert(ot->cancel == NULL);
336  BLI_assert(ot->prop != NULL);
337 
341 
342  prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
344 }
345 
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
@ G_TRANSFORM_EDIT
Definition: BKE_global.h:248
#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:542
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:485
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
#define OPERATOR_RETVAL_CHECK(ret)
void ED_object_data_xform_restore(struct XFormObjectData *xod)
struct XFormObjectData * ED_object_data_xform_create_from_edit_mode(ID *id)
void ED_object_data_xform_destroy(struct XFormObjectData *xod_base)
void ED_object_data_xform_tag_update(struct XFormObjectData *xod)
void ED_area_status_text(ScrArea *area, const char *str)
Definition: area.c:792
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
@ PROP_HIDDEN
Definition: RNA_types.h:216
#define C
Definition: RandGen.cpp:25
@ KM_PRESS
Definition: WM_types.h:267
@ KM_RELEASE
Definition: WM_types.h:268
@ KM_CTRL
Definition: WM_types.h:239
@ KM_SHIFT
Definition: WM_types.h:238
#define str(s)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define G(x, y, z)
vector snap(vector a, vector b)
Definition: node_math.h:59
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2767
void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision)
Definition: rna_access.c:1311
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
Definition: rna_access.c:2790
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
struct XFormObjectData ** objects_xform
void * data
struct ValueInteraction::@1196 context_vars
struct ValueInteraction::@1194 init
struct ValueInteraction::@1195 prev
short val
Definition: WM_types.h:680
uint8_t modifier
Definition: WM_types.h:693
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
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct wmOperatorType * type
struct PointerRNA * ptr
int WM_userdef_event_type_from_keymap_type(int kmitype)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
int WM_operator_call_notest(bContext *C, wmOperator *op)
@ RIGHTMOUSE
@ EVT_RIGHTCTRLKEY
@ EVT_LEFTCTRLKEY
@ EVT_PADENTER
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
@ EVT_RIGHTSHIFTKEY
@ EVT_LEFTSHIFTKEY
@ EVT_RETKEY
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
static void op_generic_value_restore(wmOperator *op)
static int op_generic_value_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_operator_flag_only_pass_through_on_press(int retval, const struct wmEvent *event)
static void interactive_value_init_from_property(bContext *C, ValueInteraction *inter, const wmEvent *event, PointerRNA *ptr, PropertyRNA *prop)
struct ValueInteraction ValueInteraction
static void op_generic_value_cancel(bContext *UNUSED(C), wmOperator *op)
static int op_generic_value_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void interactive_value_exit(ValueInteraction *inter)
static void interactive_value_init(bContext *C, ValueInteraction *inter, const wmEvent *event, const float value_final, const float range[2])
static void op_generic_value_exit(wmOperator *op)
void WM_operator_type_modal_from_exec_for_object_edit_coords(wmOperatorType *ot)
static bool interactive_value_update(ValueInteraction *inter, const wmEvent *event, float *r_value_final)