Blender  V2.93
wm_operator_utils.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 
23 #include <math.h>
24 
25 #include "BLI_string.h"
26 #include "BLI_utildefines.h"
27 
28 #include "BKE_context.h"
29 #include "BKE_global.h"
30 #include "BKE_layer.h"
31 
32 #include "RNA_access.h"
33 #include "RNA_define.h"
34 
35 #include "WM_api.h" /* Own include. */
36 #include "WM_types.h"
37 
38 #include "MEM_guardedalloc.h"
39 
40 #include "ED_object.h"
41 #include "ED_screen.h"
42 
43 /* -------------------------------------------------------------------- */
52 typedef struct ValueInteraction {
53  struct {
54  float mval[2];
55  float prop_value;
56  } init;
57  struct {
58  float prop_value;
59  bool is_snap;
60  bool is_precise;
61  } prev;
62  float range[2];
63 
64  struct {
69 
71  ValueInteraction *inter,
72  const wmEvent *event,
73  const float value_final,
74  const float range[2])
75 {
76 
77  inter->context_vars.area = CTX_wm_area(C);
79 
80  inter->init.mval[0] = event->mval[0];
81  inter->init.mval[1] = event->mval[1];
82  inter->init.prop_value = value_final;
83  inter->prev.prop_value = value_final;
84  inter->range[0] = range[0];
85  inter->range[1] = range[1];
86 }
87 
89  bContext *C, ValueInteraction *inter, const wmEvent *event, PointerRNA *ptr, PropertyRNA *prop)
90 {
91  float range[2];
92  float step, precision;
93  RNA_property_float_ui_range(ptr, prop, &range[0], &range[1], &step, &precision);
94  const float value_final = RNA_property_float_get(ptr, prop);
95  interactive_value_init(C, inter, event, value_final, range);
96 }
97 
99 {
101 }
102 
104  const wmEvent *event,
105  float *r_value_final)
106 {
107  const int mval_axis = 0;
108 
109  const float value_scale = 4.0f; /* Could be option. */
110  const float value_range = inter->range[1] - inter->range[0];
111  const int mval_curr = event->mval[mval_axis];
112  const int mval_init = inter->init.mval[mval_axis];
113  float value_delta = (inter->init.prop_value +
114  (((float)(mval_curr - mval_init) / inter->context_vars.region->winx) *
115  value_range)) *
116  value_scale;
117  if (event->ctrl) {
118  const double snap = 0.1;
119  value_delta = (float)roundf((double)value_delta / snap) * snap;
120  }
121  if (event->shift) {
122  value_delta *= 0.1f;
123  }
124  const float value_final = inter->init.prop_value + value_delta;
125 
126  const bool changed = value_final != inter->prev.prop_value;
127  if (changed) {
128  /* set the property for the operator and call its modal function */
129  char str[64];
130  SNPRINTF(str, "%.4f", value_final);
132  }
133 
134  inter->prev.prop_value = value_final;
135  inter->prev.is_snap = event->ctrl;
136  inter->prev.is_precise = event->shift;
137 
138  *r_value_final = value_final;
139  return changed;
140 }
141 
144 /* -------------------------------------------------------------------- */
153  bool is_active;
154  bool is_first;
155 
157 
162 };
163 
164 /* Internal callback to free. */
166 {
167  struct ObCustomData_ForEditMode *cd = op->customdata;
168  if (cd) {
170 
171  for (uint ob_index = 0; ob_index < cd->objects_len; ob_index++) {
172  struct XFormObjectData *xod = cd->objects_xform[ob_index];
173  if (xod != NULL) {
175  }
176  }
177  MEM_freeN(cd->objects);
179  MEM_freeN(cd);
180  }
181 
182  G.moving &= ~G_TRANSFORM_EDIT;
183 }
184 
186 {
187  struct ObCustomData_ForEditMode *cd = op->customdata;
188  for (uint ob_index = 0; ob_index < cd->objects_len; ob_index++) {
191  }
192 }
193 
195 {
197 }
198 
199 static int op_generic_value_invoke(bContext *C, wmOperator *op, const wmEvent *event)
200 {
201  if (RNA_property_is_set(op->ptr, op->type->prop)) {
202  return WM_operator_call_notest(C, op);
203  }
204 
205  ViewLayer *view_layer = CTX_data_view_layer(C);
208  view_layer, CTX_wm_view3d(C), &objects_len);
209  if (objects_len == 0) {
211  return OPERATOR_CANCELLED;
212  }
213 
214  struct ObCustomData_ForEditMode *cd = MEM_callocN(sizeof(*cd), __func__);
216  cd->wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
217  cd->is_active = !cd->wait_for_input;
218  cd->is_first = true;
219  cd->objects = objects;
220  cd->objects_len = objects_len;
221 
222  if (cd->wait_for_input == false) {
223  interactive_value_init_from_property(C, &cd->inter, event, op->ptr, op->type->prop);
224  }
225 
226  cd->objects_xform = MEM_callocN(sizeof(*cd->objects_xform) * objects_len, __func__);
227 
228  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
229  Object *obedit = objects[ob_index];
231  }
232 
233  op->customdata = cd;
234 
236  G.moving |= G_TRANSFORM_EDIT;
237 
238  return OPERATOR_RUNNING_MODAL;
239 }
240 
241 static int op_generic_value_modal(bContext *C, wmOperator *op, const wmEvent *event)
242 {
243  struct ObCustomData_ForEditMode *cd = op->customdata;
244 
245  /* Special case, check if we release the event that activated this operator. */
246  if ((event->type == cd->launch_event) && (event->val == KM_RELEASE)) {
247  if (cd->wait_for_input == false) {
249  return OPERATOR_FINISHED;
250  }
251  }
252 
253  switch (event->type) {
254  case MOUSEMOVE:
255  case EVT_LEFTCTRLKEY:
256  case EVT_RIGHTCTRLKEY:
257  case EVT_LEFTSHIFTKEY:
258  case EVT_RIGHTSHIFTKEY: {
259  float value_final;
260  if (cd->is_active && interactive_value_update(&cd->inter, event, &value_final)) {
262 
263  RNA_property_float_set(op->ptr, op->type->prop, value_final);
264  if (cd->is_first == false) {
266  }
267 
268  wm->op_undo_depth++;
269  int retval = op->type->exec(C, op);
270  OPERATOR_RETVAL_CHECK(retval);
271  wm->op_undo_depth--;
272 
273  cd->is_first = false;
274 
275  if ((retval & OPERATOR_FINISHED) == 0) {
277  return OPERATOR_CANCELLED;
278  }
279  }
280  break;
281  }
282  case EVT_RETKEY:
283  case EVT_PADENTER:
284  case LEFTMOUSE: {
285  if (cd->wait_for_input) {
286  if (event->val == KM_PRESS) {
287  if (cd->is_active == false) {
288  cd->is_active = true;
289  interactive_value_init_from_property(C, &cd->inter, event, op->ptr, op->type->prop);
290  }
291  }
292  else if (event->val == KM_RELEASE) {
293  if (cd->is_active == true) {
295  return OPERATOR_FINISHED;
296  }
297  }
298  }
299  else {
300  if (event->val == KM_RELEASE) {
302  return OPERATOR_FINISHED;
303  }
304  }
305  break;
306  }
307  case EVT_ESCKEY:
308  case RIGHTMOUSE: {
309  if (event->val == KM_PRESS) {
310  if (cd->is_active == true) {
312  }
314  return OPERATOR_CANCELLED;
315  }
316  break;
317  }
318  }
319  return OPERATOR_RUNNING_MODAL;
320 }
321 
327 {
328  PropertyRNA *prop;
329 
330  BLI_assert(ot->modal == NULL);
331  BLI_assert(ot->invoke == NULL);
332  BLI_assert(ot->cancel == NULL);
333  BLI_assert(ot->prop != NULL);
334 
338 
339  prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
341 }
342 
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
@ G_TRANSFORM_EDIT
Definition: BKE_global.h:219
#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:426
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:165
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
#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:815
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
@ PROP_HIDDEN
Definition: RNA_types.h:202
#define C
Definition: RandGen.cpp:39
#define KM_PRESS
Definition: WM_types.h:242
#define KM_RELEASE
Definition: WM_types.h:243
#define str(s)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
vector snap(vector a, vector b)
Definition: node_math.h:72
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2941
void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision)
Definition: rna_access.c:1466
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:6655
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
Definition: rna_access.c:2964
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
struct XFormObjectData ** objects_xform
void * data
struct ValueInteraction::@1160 context_vars
struct ValueInteraction::@1159 prev
struct ValueInteraction::@1158 init
short shift
Definition: WM_types.h:618
short ctrl
Definition: WM_types.h:618
short val
Definition: WM_types.h:579
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
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct wmOperatorType * type
struct PointerRNA * ptr
#define G(x, y, z)
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:3157
wmOperatorType * ot
Definition: wm_files.c:3156
static void op_generic_value_restore(wmOperator *op)
static int op_generic_value_modal(bContext *C, wmOperator *op, const 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)