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 bmesh
19  *
20  * BMesh inline operator functions.
21  */
22 
23 #pragma once
24 
25 /* tool flag API. never, ever ever should tool code put junk in
26  * header flags (element->head.flag), nor should they use
27  * element->head.eflag1/eflag2.  instead, use this api to set
28  * flags.
29  *
30  * if you need to store a value per element, use a
31  * ghash or a mapping slot to do it. */
32 
33 /* flags 15 and 16 (1 << 14 and 1 << 15) are reserved for bmesh api use */
34 ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE
_bmo_elem_flag_test(BMesh * bm,const BMFlagLayer * oflags,const short oflag)35     short _bmo_elem_flag_test(BMesh *bm, const BMFlagLayer *oflags, const short oflag)
36 {
37   BLI_assert(bm->use_toolflags);
38   return oflags[bm->toolflag_index].f & oflag;
39 }
40 
41 ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE
_bmo_elem_flag_test_bool(BMesh * bm,const BMFlagLayer * oflags,const short oflag)42     bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag)
43 {
44   BLI_assert(bm->use_toolflags);
45   return (oflags[bm->toolflag_index].f & oflag) != 0;
46 }
47 
48 ATTR_NONNULL(1, 2)
_bmo_elem_flag_enable(BMesh * bm,BMFlagLayer * oflags,const short oflag)49 BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const short oflag)
50 {
51   BLI_assert(bm->use_toolflags);
52   oflags[bm->toolflag_index].f |= oflag;
53 }
54 
55 ATTR_NONNULL(1, 2)
_bmo_elem_flag_disable(BMesh * bm,BMFlagLayer * oflags,const short oflag)56 BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag)
57 {
58   BLI_assert(bm->use_toolflags);
59   oflags[bm->toolflag_index].f &= (short)~oflag;
60 }
61 
62 ATTR_NONNULL(1, 2)
_bmo_elem_flag_set(BMesh * bm,BMFlagLayer * oflags,const short oflag,int val)63 BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val)
64 {
65   BLI_assert(bm->use_toolflags);
66   if (val) {
67     oflags[bm->toolflag_index].f |= oflag;
68   }
69   else {
70     oflags[bm->toolflag_index].f &= (short)~oflag;
71   }
72 }
73 
74 ATTR_NONNULL(1, 2)
_bmo_elem_flag_toggle(BMesh * bm,BMFlagLayer * oflags,const short oflag)75 BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag)
76 {
77   BLI_assert(bm->use_toolflags);
78   oflags[bm->toolflag_index].f ^= oflag;
79 }
80 
81 ATTR_NONNULL(1, 2)
BMO_slot_map_int_insert(BMOperator * op,BMOpSlot * slot,void * element,const int val)82 BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op,
83                                         BMOpSlot *slot,
84                                         void *element,
85                                         const int val)
86 {
87   union {
88     void *ptr;
89     int val;
90   } t = {NULL};
91   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
92   BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr));
93 }
94 
95 ATTR_NONNULL(1, 2)
BMO_slot_map_bool_insert(BMOperator * op,BMOpSlot * slot,void * element,const bool val)96 BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op,
97                                          BMOpSlot *slot,
98                                          void *element,
99                                          const bool val)
100 {
101   union {
102     void *ptr;
103     bool val;
104   } t = {NULL};
105   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
106   BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr));
107 }
108 
109 ATTR_NONNULL(1, 2)
BMO_slot_map_float_insert(BMOperator * op,BMOpSlot * slot,void * element,const float val)110 BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op,
111                                           BMOpSlot *slot,
112                                           void *element,
113                                           const float val)
114 {
115   union {
116     void *ptr;
117     float val;
118   } t = {NULL};
119   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
120   BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr));
121 }
122 
123 /* pointer versions of BMO_slot_map_float_get and BMO_slot_map_float_insert.
124  *
125  * do NOT use these for non-operator-api-allocated memory! instead
126  * use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */
127 
128 ATTR_NONNULL(1, 2)
BMO_slot_map_ptr_insert(BMOperator * op,BMOpSlot * slot,const void * element,void * val)129 BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op,
130                                         BMOpSlot *slot,
131                                         const void *element,
132                                         void *val)
133 {
134   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
135   BMO_slot_map_insert(op, slot, element, val);
136 }
137 
138 ATTR_NONNULL(1, 2)
BMO_slot_map_elem_insert(BMOperator * op,BMOpSlot * slot,const void * element,void * val)139 BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op,
140                                          BMOpSlot *slot,
141                                          const void *element,
142                                          void *val)
143 {
144   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM);
145   BMO_slot_map_insert(op, slot, element, val);
146 }
147 
148 /* no values */
149 ATTR_NONNULL(1, 2)
BMO_slot_map_empty_insert(BMOperator * op,BMOpSlot * slot,const void * element)150 BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, const void *element)
151 {
152   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY);
153   BMO_slot_map_insert(op, slot, element, NULL);
154 }
155 
156 ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
BMO_slot_map_contains(BMOpSlot * slot,const void * element)157     bool BMO_slot_map_contains(BMOpSlot *slot, const void *element)
158 {
159   BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
160   return BLI_ghash_haskey(slot->data.ghash, element);
161 }
162 
163 ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
BMO_slot_map_data_get(BMOpSlot * slot,const void * element)164     void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element)
165 {
166 
167   return BLI_ghash_lookup_p(slot->data.ghash, element);
168 }
169 
170 ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
BMO_slot_map_float_get(BMOpSlot * slot,const void * element)171     float BMO_slot_map_float_get(BMOpSlot *slot, const void *element)
172 {
173   void **data;
174   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
175 
176   data = BMO_slot_map_data_get(slot, element);
177   if (data) {
178     return *(float *)data;
179   }
180   else {
181     return 0.0f;
182   }
183 }
184 
185 ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
BMO_slot_map_int_get(BMOpSlot * slot,const void * element)186     int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
187 {
188   void **data;
189   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
190 
191   data = BMO_slot_map_data_get(slot, element);
192   if (data) {
193     return *(int *)data;
194   }
195   else {
196     return 0;
197   }
198 }
199 
200 ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
BMO_slot_map_bool_get(BMOpSlot * slot,const void * element)201     bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
202 {
203   void **data;
204   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
205 
206   data = BMO_slot_map_data_get(slot, element);
207   if (data) {
208     return *(bool *)data;
209   }
210   else {
211     return false;
212   }
213 }
214 
215 ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
BMO_slot_map_ptr_get(BMOpSlot * slot,const void * element)216     void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
217 {
218   void **val = BMO_slot_map_data_get(slot, element);
219   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
220   if (val) {
221     return *val;
222   }
223 
224   return NULL;
225 }
226 
227 ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
BMO_slot_map_elem_get(BMOpSlot * slot,const void * element)228     void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element)
229 {
230   void **val = (void **)BMO_slot_map_data_get(slot, element);
231   BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM);
232   if (val) {
233     return *val;
234   }
235 
236   return NULL;
237 }
238