Bevel mod: cleanup flags and extra data.
[blender.git] / source / blender / python / intern / bpy_gizmo_wrap.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 pythonintern
19  *
20  * This file is so Python can define widget-group's that C can call into.
21  * The generic callback functions for Python widget-group are defines in
22  * 'rna_wm.c', some calling into functions here to do python specific
23  * functionality.
24  *
25  * \note This follows 'bpy_operator_wrap.c' very closely.
26  * Keep in sync unless there is good reason not to!
27  */
28
29 #include <Python.h>
30
31 #include "BLI_utildefines.h"
32
33 #include "WM_api.h"
34 #include "WM_types.h"
35
36 #include "RNA_access.h"
37 #include "RNA_define.h"
38 #include "RNA_enum_types.h"
39
40 #include "bpy_rna.h"
41 #include "bpy_intern_string.h"
42 #include "bpy_gizmo_wrap.h"  /* own include */
43
44 /* we may want to add, but not now */
45
46 /* -------------------------------------------------------------------- */
47 /** \name Gizmo
48  * \{ */
49
50
51 static bool bpy_gizmotype_target_property_def(
52         wmGizmoType *gzt, PyObject *item)
53 {
54         /* Note: names based on 'rna_rna.c' */
55         PyObject *empty_tuple = PyTuple_New(0);
56
57         struct {
58                 char *id;
59                 char *type_id; int type;
60                 int array_length;
61         } params = {
62                 .id = NULL, /* not optional */
63                 .type = PROP_FLOAT,
64                 .type_id = NULL,
65                 .array_length = 1,
66         };
67
68         static const char * const _keywords[] = {"id", "type", "array_length", NULL};
69         static _PyArg_Parser _parser = {"|$ssi:register_class", _keywords, 0};
70         if (!_PyArg_ParseTupleAndKeywordsFast(
71                 empty_tuple, item,
72                 &_parser,
73                 &params.id,
74                 &params.type_id,
75                 &params.array_length))
76         {
77                 goto fail;
78         }
79
80         if (params.id == NULL) {
81                 PyErr_SetString(PyExc_ValueError, "'id' argument not given");
82                 goto fail;
83         }
84
85         if ((params.type_id != NULL) &&
86             pyrna_enum_value_from_id(
87                 rna_enum_property_type_items, params.type_id, &params.type, "'type' enum value") == -1)
88         {
89                 goto fail;
90         }
91         else {
92                 params.type = rna_enum_property_type_items[params.type].value;
93         }
94
95         if ((params.array_length < 1 || params.array_length > RNA_MAX_ARRAY_LENGTH)) {
96                 PyErr_SetString(PyExc_ValueError, "'array_length' out of range");
97                 goto fail;
98         }
99
100         WM_gizmotype_target_property_def(gzt, params.id, params.type, params.array_length);
101         Py_DECREF(empty_tuple);
102         return true;
103
104 fail:
105         Py_DECREF(empty_tuple);
106         return false;
107 }
108
109 static void gizmo_properties_init(wmGizmoType *gzt)
110 {
111         PyTypeObject *py_class = gzt->ext.data;
112         RNA_struct_blender_type_set(gzt->ext.srna, gzt);
113
114         /* only call this so pyrna_deferred_register_class gives a useful error
115          * WM_operatortype_append_ptr will call RNA_def_struct_identifier
116          * later */
117         RNA_def_struct_identifier_no_struct_map(gzt->srna, gzt->idname);
118
119         if (pyrna_deferred_register_class(gzt->srna, py_class) != 0) {
120                 PyErr_Print(); /* failed to register operator props */
121                 PyErr_Clear();
122         }
123
124         /* Extract target property definitions from 'bl_target_properties' */
125         {
126                 /* picky developers will notice that 'bl_targets' won't work with inheritance
127                  * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */
128                 PyObject *py_class_dict = py_class->tp_dict;
129                 PyObject *bl_target_properties = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_target_properties);
130
131                 /* Some widgets may only exist to activate operators. */
132                 if (bl_target_properties != NULL) {
133                         PyObject *bl_target_properties_fast;
134                         if (!(bl_target_properties_fast = PySequence_Fast(
135                                   bl_target_properties, "bl_target_properties sequence")))
136                         {
137                                 /* PySequence_Fast sets the error */
138                                 PyErr_Print();
139                                 PyErr_Clear();
140                                 return;
141                         }
142
143                         const uint items_len = PySequence_Fast_GET_SIZE(bl_target_properties_fast);
144                         PyObject **items = PySequence_Fast_ITEMS(bl_target_properties_fast);
145
146                         for (uint i = 0; i < items_len; i++) {
147                                 if (!bpy_gizmotype_target_property_def(gzt, items[i])) {
148                                         PyErr_Print();
149                                         PyErr_Clear();
150                                         break;
151                                 }
152                         }
153
154                         Py_DECREF(bl_target_properties_fast);
155                 }
156         }
157 }
158
159 void BPY_RNA_gizmo_wrapper(wmGizmoType *gzt, void *userdata)
160 {
161         /* take care not to overwrite anything set in
162          * WM_gizmomaptype_group_link_ptr before opfunc() is called */
163         StructRNA *srna = gzt->srna;
164         *gzt = *((wmGizmoType *)userdata);
165         gzt->srna = srna; /* restore */
166
167         /* don't do translations here yet */
168 #if 0
169         /* Use i18n context from ext.srna if possible (py gizmogroups). */
170         if (gt->ext.srna) {
171                 RNA_def_struct_translation_context(gt->srna, RNA_struct_translation_context(gt->ext.srna));
172         }
173 #endif
174
175         gzt->struct_size = sizeof(wmGizmo);
176
177         gizmo_properties_init(gzt);
178 }
179
180 /** \} */
181
182
183 /* -------------------------------------------------------------------- */
184 /** \name Gizmo Group
185  * \{ */
186
187 static void gizmogroup_properties_init(wmGizmoGroupType *gzgt)
188 {
189         PyTypeObject *py_class = gzgt->ext.data;
190         RNA_struct_blender_type_set(gzgt->ext.srna, gzgt);
191
192         /* only call this so pyrna_deferred_register_class gives a useful error
193          * WM_operatortype_append_ptr will call RNA_def_struct_identifier
194          * later */
195         RNA_def_struct_identifier_no_struct_map(gzgt->srna, gzgt->idname);
196
197         if (pyrna_deferred_register_class(gzgt->srna, py_class) != 0) {
198                 PyErr_Print(); /* failed to register operator props */
199                 PyErr_Clear();
200         }
201 }
202
203 void BPY_RNA_gizmogroup_wrapper(wmGizmoGroupType *gzgt, void *userdata)
204 {
205         /* take care not to overwrite anything set in
206          * WM_gizmomaptype_group_link_ptr before opfunc() is called */
207         StructRNA *srna = gzgt->srna;
208         *gzgt = *((wmGizmoGroupType *)userdata);
209         gzgt->srna = srna; /* restore */
210
211         /* don't do translations here yet */
212 #if 0
213         /* Use i18n context from ext.srna if possible (py gizmogroups). */
214         if (gzgt->ext.srna) {
215                 RNA_def_struct_translation_context(gzgt->srna, RNA_struct_translation_context(gzgt->ext.srna));
216         }
217 #endif
218
219         gizmogroup_properties_init(gzgt);
220 }
221
222 /** \} */