63caf6126cce6f5c4f7cb7552d9fe242eedd796c
[blender.git] / source / blender / windowmanager / intern / wm_operator_type.c
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
17 /** \file
18  * \ingroup wm
19  *
20  * Operator Registry.
21  */
22
23 #include "MEM_guardedalloc.h"
24
25 #include "CLG_log.h"
26
27 #include "DNA_ID.h"
28 #include "DNA_screen_types.h"
29 #include "DNA_scene_types.h"
30 #include "DNA_userdef_types.h"
31 #include "DNA_windowmanager_types.h"
32
33 #include "BLT_translation.h"
34
35 #include "BLI_blenlib.h"
36 #include "BLI_utildefines.h"
37 #include "BLI_ghash.h"
38
39 #include "BKE_context.h"
40 #include "BKE_idprop.h"
41
42 #include "RNA_access.h"
43 #include "RNA_define.h"
44 #include "RNA_enum_types.h"
45
46 #include "WM_api.h"
47 #include "WM_types.h"
48
49 #include "wm.h"
50 #include "wm_event_system.h"
51
52 #define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
53
54 static void wm_operatortype_free_macro(wmOperatorType *ot);
55
56 /* -------------------------------------------------------------------- */
57 /** \name Operator Type Registry
58  * \{ */
59
60 static GHash *global_ops_hash = NULL;
61 /** Counter for operator-properties that should not be tagged with #OP_PROP_TAG_ADVANCED. */
62 static int ot_prop_basic_count = -1;
63
64 wmOperatorType *WM_operatortype_find(const char *idname, bool quiet)
65 {
66   if (idname[0]) {
67     wmOperatorType *ot;
68
69     /* needed to support python style names without the _OT_ syntax */
70     char idname_bl[OP_MAX_TYPENAME];
71     WM_operator_bl_idname(idname_bl, idname);
72
73     ot = BLI_ghash_lookup(global_ops_hash, idname_bl);
74     if (ot) {
75       return ot;
76     }
77
78     if (!quiet) {
79       CLOG_INFO(
80           WM_LOG_OPERATORS, 0, "search for unknown operator '%s', '%s'\n", idname_bl, idname);
81     }
82   }
83   else {
84     if (!quiet) {
85       CLOG_INFO(WM_LOG_OPERATORS, 0, "search for empty operator");
86     }
87   }
88
89   return NULL;
90 }
91
92 /* caller must free */
93 void WM_operatortype_iter(GHashIterator *ghi)
94 {
95   BLI_ghashIterator_init(ghi, global_ops_hash);
96 }
97
98 /** \name Operator Type Append
99  * \{ */
100
101 static wmOperatorType *wm_operatortype_append__begin(void)
102 {
103   wmOperatorType *ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
104
105   BLI_assert(ot_prop_basic_count == -1);
106
107   ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
108   RNA_def_struct_property_tags(ot->srna, rna_enum_operator_property_tags);
109   /* Set the default i18n context now, so that opfunc can redefine it if needed! */
110   RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
111   ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
112
113   return ot;
114 }
115 static void wm_operatortype_append__end(wmOperatorType *ot)
116 {
117   if (ot->name == NULL) {
118     CLOG_ERROR(WM_LOG_OPERATORS, "Operator '%s' has no name property", ot->idname);
119   }
120   BLI_assert((ot->description == NULL) || (ot->description[0]));
121
122   /* Allow calling _begin without _end in operatortype creation. */
123   WM_operatortype_props_advanced_end(ot);
124
125   /* XXX All ops should have a description but for now allow them not to. */
126   RNA_def_struct_ui_text(
127       ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
128   RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
129
130   BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
131 }
132
133 /* all ops in 1 list (for time being... needs evaluation later) */
134 void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
135 {
136   wmOperatorType *ot = wm_operatortype_append__begin();
137   opfunc(ot);
138   wm_operatortype_append__end(ot);
139 }
140
141 void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata)
142 {
143   wmOperatorType *ot = wm_operatortype_append__begin();
144   opfunc(ot, userdata);
145   wm_operatortype_append__end(ot);
146 }
147
148 /** \} */
149
150 /* called on initialize WM_exit() */
151 void WM_operatortype_remove_ptr(wmOperatorType *ot)
152 {
153   BLI_assert(ot == WM_operatortype_find(ot->idname, false));
154
155   RNA_struct_free(&BLENDER_RNA, ot->srna);
156
157   if (ot->last_properties) {
158     IDP_FreeProperty(ot->last_properties);
159     MEM_freeN(ot->last_properties);
160   }
161
162   if (ot->macro.first) {
163     wm_operatortype_free_macro(ot);
164   }
165
166   BLI_ghash_remove(global_ops_hash, ot->idname, NULL, NULL);
167
168   WM_keyconfig_update_operatortype();
169
170   MEM_freeN(ot);
171 }
172
173 bool WM_operatortype_remove(const char *idname)
174 {
175   wmOperatorType *ot = WM_operatortype_find(idname, 0);
176
177   if (ot == NULL) {
178     return false;
179   }
180
181   WM_operatortype_remove_ptr(ot);
182
183   return true;
184 }
185
186 /* called on initialize WM_init() */
187 void wm_operatortype_init(void)
188 {
189   /* reserve size is set based on blender default setup */
190   global_ops_hash = BLI_ghash_str_new_ex("wm_operatortype_init gh", 2048);
191 }
192
193 static void operatortype_ghash_free_cb(wmOperatorType *ot)
194 {
195   if (ot->last_properties) {
196     IDP_FreeProperty(ot->last_properties);
197     MEM_freeN(ot->last_properties);
198   }
199
200   if (ot->macro.first) {
201     wm_operatortype_free_macro(ot);
202   }
203
204   if (ot->ext.srna) {
205     /* python operator, allocs own string */
206     MEM_freeN((void *)ot->idname);
207   }
208
209   MEM_freeN(ot);
210 }
211
212 void wm_operatortype_free(void)
213 {
214   BLI_ghash_free(global_ops_hash, NULL, (GHashValFreeFP)operatortype_ghash_free_cb);
215   global_ops_hash = NULL;
216 }
217
218 /**
219  * Tag all operator-properties of \a ot defined after calling this, until
220  * the next #WM_operatortype_props_advanced_end call (if available), with
221  * #OP_PROP_TAG_ADVANCED. Previously defined ones properties not touched.
222  *
223  * Calling this multiple times without a call to #WM_operatortype_props_advanced_end,
224  * all calls after the first one are ignored. Meaning all propereties defined after the
225  * first call are tagged as advanced.
226  *
227  * This doesn't do the actual tagging, #WM_operatortype_props_advanced_end does which is
228  * called for all operators during registration (see #wm_operatortype_append__end).
229  */
230 void WM_operatortype_props_advanced_begin(wmOperatorType *ot)
231 {
232   if (ot_prop_basic_count ==
233       -1) { /* Don't do anything if _begin was called before, but not _end  */
234     ot_prop_basic_count = RNA_struct_count_properties(ot->srna);
235   }
236 }
237
238 /**
239  * Tags all operator-properties of \ot defined since the first #WM_operatortype_props_advanced_begin
240  * call, or the last #WM_operatortype_props_advanced_end call, with #OP_PROP_TAG_ADVANCED.
241  * Note that this is called for all operators during registration (see #wm_operatortype_append__end).
242  * So it does not need to be explicitly called in operator-type definition.
243  */
244 void WM_operatortype_props_advanced_end(wmOperatorType *ot)
245 {
246   PointerRNA struct_ptr;
247   int counter = 0;
248
249   if (ot_prop_basic_count == -1) {
250     /* WM_operatortype_props_advanced_begin was not called. Don't do anything. */
251     return;
252   }
253
254   RNA_pointer_create(NULL, ot->srna, NULL, &struct_ptr);
255
256   RNA_STRUCT_BEGIN (&struct_ptr, prop) {
257     counter++;
258     if (counter > ot_prop_basic_count) {
259       WM_operatortype_prop_tag(prop, OP_PROP_TAG_ADVANCED);
260     }
261   }
262   RNA_STRUCT_END;
263
264   ot_prop_basic_count = -1;
265 }
266
267 /**
268  * Remove memory of all previously executed tools.
269  */
270 void WM_operatortype_last_properties_clear_all(void)
271 {
272   GHashIterator iter;
273
274   for (WM_operatortype_iter(&iter); (!BLI_ghashIterator_done(&iter));
275        (BLI_ghashIterator_step(&iter))) {
276     wmOperatorType *ot = BLI_ghashIterator_getValue(&iter);
277
278     if (ot->last_properties) {
279       IDP_FreeProperty(ot->last_properties);
280       MEM_freeN(ot->last_properties);
281       ot->last_properties = NULL;
282     }
283   }
284 }
285
286 /** \} */
287
288 /* -------------------------------------------------------------------- */
289 /** \name Operator Macro Type
290  * \{ */
291
292 typedef struct {
293   int retval;
294 } MacroData;
295
296 static void wm_macro_start(wmOperator *op)
297 {
298   if (op->customdata == NULL) {
299     op->customdata = MEM_callocN(sizeof(MacroData), "MacroData");
300   }
301 }
302
303 static int wm_macro_end(wmOperator *op, int retval)
304 {
305   if (retval & OPERATOR_CANCELLED) {
306     MacroData *md = op->customdata;
307
308     if (md->retval & OPERATOR_FINISHED) {
309       retval |= OPERATOR_FINISHED;
310       retval &= ~OPERATOR_CANCELLED;
311     }
312   }
313
314   /* if modal is ending, free custom data */
315   if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) {
316     if (op->customdata) {
317       MEM_freeN(op->customdata);
318       op->customdata = NULL;
319     }
320   }
321
322   return retval;
323 }
324
325 /* macro exec only runs exec calls */
326 static int wm_macro_exec(bContext *C, wmOperator *op)
327 {
328   wmOperator *opm;
329   int retval = OPERATOR_FINISHED;
330
331   wm_macro_start(op);
332
333   for (opm = op->macro.first; opm; opm = opm->next) {
334
335     if (opm->type->exec) {
336       retval = opm->type->exec(C, opm);
337       OPERATOR_RETVAL_CHECK(retval);
338
339       if (retval & OPERATOR_FINISHED) {
340         MacroData *md = op->customdata;
341         md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */
342       }
343       else {
344         break; /* operator didn't finish, end macro */
345       }
346     }
347     else {
348       CLOG_WARN(WM_LOG_OPERATORS, "'%s' cant exec macro", opm->type->idname);
349     }
350   }
351
352   return wm_macro_end(op, retval);
353 }
354
355 static int wm_macro_invoke_internal(bContext *C,
356                                     wmOperator *op,
357                                     const wmEvent *event,
358                                     wmOperator *opm)
359 {
360   int retval = OPERATOR_FINISHED;
361
362   /* start from operator received as argument */
363   for (; opm; opm = opm->next) {
364     if (opm->type->invoke) {
365       retval = opm->type->invoke(C, opm, event);
366     }
367     else if (opm->type->exec) {
368       retval = opm->type->exec(C, opm);
369     }
370
371     OPERATOR_RETVAL_CHECK(retval);
372
373     BLI_movelisttolist(&op->reports->list, &opm->reports->list);
374
375     if (retval & OPERATOR_FINISHED) {
376       MacroData *md = op->customdata;
377       md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */
378     }
379     else {
380       break; /* operator didn't finish, end macro */
381     }
382   }
383
384   return wm_macro_end(op, retval);
385 }
386
387 static int wm_macro_invoke(bContext *C, wmOperator *op, const wmEvent *event)
388 {
389   wm_macro_start(op);
390   return wm_macro_invoke_internal(C, op, event, op->macro.first);
391 }
392
393 static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event)
394 {
395   wmOperator *opm = op->opm;
396   int retval = OPERATOR_FINISHED;
397
398   if (opm == NULL) {
399     CLOG_ERROR(WM_LOG_OPERATORS, "macro error, calling NULL modal()");
400   }
401   else {
402     retval = opm->type->modal(C, opm, event);
403     OPERATOR_RETVAL_CHECK(retval);
404
405     /* if we're halfway through using a tool and cancel it, clear the options [#37149] */
406     if (retval & OPERATOR_CANCELLED) {
407       WM_operator_properties_clear(opm->ptr);
408     }
409
410     /* if this one is done but it's not the last operator in the macro */
411     if ((retval & OPERATOR_FINISHED) && opm->next) {
412       MacroData *md = op->customdata;
413
414       md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */
415
416       retval = wm_macro_invoke_internal(C, op, event, opm->next);
417
418       /* if new operator is modal and also added its own handler */
419       if (retval & OPERATOR_RUNNING_MODAL && op->opm != opm) {
420         wmWindow *win = CTX_wm_window(C);
421         wmEventHandler_Op *handler;
422
423         handler = BLI_findptr(&win->modalhandlers, op, offsetof(wmEventHandler_Op, op));
424         if (handler) {
425           BLI_remlink(&win->modalhandlers, handler);
426           wm_event_free_handler(&handler->head);
427         }
428
429         /* if operator is blocking, grab cursor
430          * This may end up grabbing twice, but we don't care.
431          * */
432         if (op->opm->type->flag & OPTYPE_BLOCKING) {
433           int bounds[4] = {-1, -1, -1, -1};
434           const bool wrap = ((U.uiflag & USER_CONTINUOUS_MOUSE) &&
435                              ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) ||
436                               (op->opm->type->flag & OPTYPE_GRAB_CURSOR)));
437
438           if (wrap) {
439             ARegion *ar = CTX_wm_region(C);
440             if (ar) {
441               bounds[0] = ar->winrct.xmin;
442               bounds[1] = ar->winrct.ymax;
443               bounds[2] = ar->winrct.xmax;
444               bounds[3] = ar->winrct.ymin;
445             }
446           }
447
448           WM_cursor_grab_enable(win, wrap, false, bounds);
449         }
450       }
451     }
452   }
453
454   return wm_macro_end(op, retval);
455 }
456
457 static void wm_macro_cancel(bContext *C, wmOperator *op)
458 {
459   /* call cancel on the current modal operator, if any */
460   if (op->opm && op->opm->type->cancel) {
461     op->opm->type->cancel(C, op->opm);
462   }
463
464   wm_macro_end(op, OPERATOR_CANCELLED);
465 }
466
467 /* Names have to be static for now */
468 wmOperatorType *WM_operatortype_append_macro(const char *idname,
469                                              const char *name,
470                                              const char *description,
471                                              int flag)
472 {
473   wmOperatorType *ot;
474   const char *i18n_context;
475
476   if (WM_operatortype_find(idname, true)) {
477     CLOG_ERROR(WM_LOG_OPERATORS, "operator %s exists, cannot create macro", idname);
478     return NULL;
479   }
480
481   ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
482   ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
483
484   ot->idname = idname;
485   ot->name = name;
486   ot->description = description;
487   ot->flag = OPTYPE_MACRO | flag;
488
489   ot->exec = wm_macro_exec;
490   ot->invoke = wm_macro_invoke;
491   ot->modal = wm_macro_modal;
492   ot->cancel = wm_macro_cancel;
493   ot->poll = NULL;
494
495   if (!ot->description) {
496     /* XXX All ops should have a description but for now allow them not to. */
497     ot->description = UNDOCUMENTED_OPERATOR_TIP;
498   }
499
500   RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
501   RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
502   /* Use i18n context from ext.srna if possible (py operators). */
503   i18n_context = ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) :
504                                 BLT_I18NCONTEXT_OPERATOR_DEFAULT;
505   RNA_def_struct_translation_context(ot->srna, i18n_context);
506   ot->translation_context = i18n_context;
507
508   BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
509
510   return ot;
511 }
512
513 void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata)
514 {
515   wmOperatorType *ot;
516
517   ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
518   ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
519
520   ot->flag = OPTYPE_MACRO;
521   ot->exec = wm_macro_exec;
522   ot->invoke = wm_macro_invoke;
523   ot->modal = wm_macro_modal;
524   ot->cancel = wm_macro_cancel;
525   ot->poll = NULL;
526
527   if (!ot->description) {
528     ot->description = UNDOCUMENTED_OPERATOR_TIP;
529   }
530
531   /* Set the default i18n context now, so that opfunc can redefine it if needed! */
532   RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
533   ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
534   opfunc(ot, userdata);
535
536   RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
537   RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
538
539   BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
540 }
541
542 wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char *idname)
543 {
544   wmOperatorTypeMacro *otmacro = MEM_callocN(sizeof(wmOperatorTypeMacro), "wmOperatorTypeMacro");
545
546   BLI_strncpy(otmacro->idname, idname, OP_MAX_TYPENAME);
547
548   /* do this on first use, since operatordefinitions might have been not done yet */
549   WM_operator_properties_alloc(&(otmacro->ptr), &(otmacro->properties), idname);
550   WM_operator_properties_sanitize(otmacro->ptr, 1);
551
552   BLI_addtail(&ot->macro, otmacro);
553
554   {
555     /* operator should always be found but in the event its not. don't segfault */
556     wmOperatorType *otsub = WM_operatortype_find(idname, 0);
557     if (otsub) {
558       RNA_def_pointer_runtime(
559           ot->srna, otsub->idname, otsub->srna, otsub->name, otsub->description);
560     }
561   }
562
563   return otmacro;
564 }
565
566 static void wm_operatortype_free_macro(wmOperatorType *ot)
567 {
568   wmOperatorTypeMacro *otmacro;
569
570   for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) {
571     if (otmacro->ptr) {
572       WM_operator_properties_free(otmacro->ptr);
573       MEM_freeN(otmacro->ptr);
574     }
575   }
576   BLI_freelistN(&ot->macro);
577 }
578
579 /** \} */