1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
23 "author": "Pixivore, Cedric LEPILLER, Ted Milker",
25 "blender": (2, 79, 2),
26 "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
27 "Scripts/Modeling/Carver",
28 "description": "Multiple tools to carve or to create objects",
38 from mathutils
import (
46 from bpy
.props
import (
52 from bpy_extras
import view3d_utils
53 from bpy_extras
.view3d_utils
import (
54 region_2d_to_vector_3d
,
55 region_2d_to_location_3d
,
61 Vector((2.61824, -5.56469, 0)),
62 [(-1.156501, 0.799282, 0.032334),
63 (-0.967583, 0.838861, 0.032334),
64 (-1.10386, 0.846403, 0.032334),
65 (-1.034712, 0.86089, 0.032334),
66 (-1.88472, -0.564419, 0.032334),
67 (-1.924299, -0.375502, 0.032334),
68 (-1.93184, -0.511778, 0.032334),
69 (-1.946327, -0.44263, 0.032334),
70 (-0.219065, -0.869195, 0.032334),
71 (-0.149916, -0.854708, 0.032334),
72 (-0.286193, -0.847167, 0.032334),
73 (-0.097275, -0.807588, 0.032334),
74 (0.692551, 0.434324, 0.032334),
75 (0.678064, 0.503472, 0.032334),
76 (0.670523, 0.367196, 0.032334),
77 (0.630943, 0.556113, 0.032334),
78 (-0.780424, -0.44263, 0.032334),
79 (-0.765937, -0.511778, 0.032334),
80 (-0.758396, -0.375502, 0.032334),
81 (-0.718817, -0.564419, 0.032334),
82 (-0.53496, 0.556113, 0.032334),
83 (-0.49538, 0.367196, 0.032334),
84 (-0.487839, 0.503472, 0.032334),
85 (-0.473352, 0.434324, 0.032334),
86 (-1.263178, -0.807588, 0.032334),
87 (-1.452096, -0.847167, 0.032334),
88 (-1.315819, -0.854708, 0.032334),
89 (-1.384968, -0.869195, 0.032334),
90 (0.131191, 0.86089, 0.032334),
91 (0.062043, 0.846403, 0.032334),
92 (0.19832, 0.838861, 0.032334),
93 (0.009402, 0.799282, 0.032334),
94 (0.946838, -0.869195, 0.032334),
95 (1.015987, -0.854708, 0.032334),
96 (0.87971, -0.847167, 0.032334),
97 (1.068628, -0.807588, 0.032334),
98 (1.858454, 0.434324, 0.032334),
99 (1.843967, 0.503472, 0.032334),
100 (1.836426, 0.367196, 0.032334),
101 (1.796846, 0.556113, 0.032334),
102 (0.385479, -0.44263, 0.032334),
103 (0.399966, -0.511778, 0.032334),
104 (0.407507, -0.375502, 0.032334),
105 (0.447086, -0.564419, 0.032334),
106 (1.297095, 0.86089, 0.032334),
107 (1.227946, 0.846403, 0.032334),
108 (1.364223, 0.838861, 0.032334),
109 (1.175305, 0.799282, 0.032334),
111 [[16, 17, 19], [5, 4, 24], [14, 12, 15], [14, 15, 31], [10, 8, 11], [15, 30, 31], [19, 10, 11],
112 [11, 14, 31], [31, 18, 11], [8, 9, 11], [18, 16, 19], [12, 13, 15], [18, 19, 11], [28, 29, 31],
113 [30, 28, 31], [24, 21, 0], [23, 22, 20], [20, 1, 0], [3, 2, 0], [0, 5, 24], [7, 6, 4], [4, 25, 24],
114 [27, 26, 24], [21, 23, 20], [1, 3, 0], [5, 7, 4], [25, 27, 24], [21, 20, 0], [40, 41, 43], [38, 36, 39],
115 [38, 39, 47], [34, 32, 35], [39, 46, 47], [43, 34, 35], [35, 38, 47], [47, 42, 35], [32, 33, 35],
116 [42, 40, 43], [36, 37, 39], [42, 43, 35], [44, 45, 47], [46, 44, 47]]),
118 Vector((-0.06267, -2.43829, -0.0)),
119 [(-0.534254, -1.0, 0.032334),
120 (-1.0, -0.534254, 0.032334),
121 (-0.654798, -0.98413, 0.032334),
122 (-0.767127, -0.937602, 0.032334),
123 (-0.863586, -0.863586, 0.032334),
124 (-0.937602, -0.767127, 0.032334),
125 (-0.98413, -0.654798, 0.032334),
126 (1.0, -0.534254, 0.032334),
127 (0.534254, -1.0, 0.032334),
128 (0.98413, -0.654798, 0.032334),
129 (0.937602, -0.767127, 0.032334),
130 (0.863586, -0.863586, 0.032334),
131 (0.767127, -0.937602, 0.032334),
132 (0.654798, -0.98413, 0.032334),
133 (-1.0, 0.534254, 0.032334),
134 (-0.534254, 1.0, 0.032334),
135 (-0.98413, 0.654798, 0.032334),
136 (-0.937602, 0.767127, 0.032334),
137 (-0.863586, 0.863586, 0.032334),
138 (-0.767127, 0.937602, 0.032334),
139 (-0.654798, 0.98413, 0.032334),
140 (0.534254, 1.0, 0.032334),
141 (1.0, 0.534254, 0.032334),
142 (0.654798, 0.98413, 0.032334),
143 (0.767127, 0.937602, 0.032334),
144 (0.863586, 0.863586, 0.032334),
145 (0.937602, 0.767127, 0.032334),
146 (0.98413, 0.654798, 0.032334),
147 (-0.763998, 0.518786, 0.032334),
148 (-0.763998, -0.518786, 0.032334),
149 (-0.754202, -0.593189, 0.032334),
150 (-0.731454, -0.648108, 0.032334),
151 (-0.695267, -0.695267, 0.032334),
152 (-0.648108, -0.731454, 0.032334),
153 (-0.593189, -0.754202, 0.032334),
154 (-0.518786, -0.763998, 0.032334),
155 (0.518786, -0.763998, 0.032334),
156 (0.593189, -0.754202, 0.032334),
157 (0.648108, -0.731454, 0.032334),
158 (0.695267, -0.695267, 0.032334),
159 (0.731454, -0.648108, 0.032334),
160 (0.754202, -0.593189, 0.032334),
161 (0.763998, -0.518786, 0.032334),
162 (0.763998, 0.518786, 0.032334),
163 (0.754202, 0.593189, 0.032334),
164 (0.731454, 0.648108, 0.032334),
165 (0.695267, 0.695267, 0.032334),
166 (0.648108, 0.731454, 0.032334),
167 (0.593189, 0.754202, 0.032334),
168 (0.518786, 0.763998, 0.032334),
169 (-0.518786, 0.763998, 0.032334),
170 (-0.593189, 0.754202, 0.032334),
171 (-0.648108, 0.731454, 0.032334),
172 (-0.695267, 0.695267, 0.032334),
173 (-0.731454, 0.648108, 0.032334),
174 (-0.754202, 0.593189, 0.032334),
175 (0.518786, 0.518786, 0.032334),
176 (-0.518786, 0.518786, 0.032334),
177 (0.518786, -0.518786, 0.032334),
178 (-0.518786, -0.518786, 0.032334),
179 (-0.593189, 0.518786, 0.032334),
180 (-0.593189, -0.518786, 0.032334),
181 (0.518786, -0.593189, 0.032334),
182 (-0.518786, -0.593189, 0.032334),
183 (-0.593189, -0.593189, 0.032334),
184 (0.593189, 0.518786, 0.032334),
185 (0.593189, -0.518786, 0.032334),
186 (0.593189, -0.593189, 0.032334),
187 (-0.593189, 0.593189, 0.032334),
188 (-0.518786, 0.593189, 0.032334),
189 (0.518786, 0.593189, 0.032334),
190 (0.593189, 0.593189, 0.032334),
191 (-0.648108, 0.593189, 0.032334),
192 (-0.648108, 0.518786, 0.032334),
193 (-0.648108, -0.518786, 0.032334),
194 (-0.648108, -0.593189, 0.032334),
195 (-0.695267, 0.593189, 0.032334),
196 (-0.695267, 0.518786, 0.032334),
197 (-0.695267, -0.518786, 0.032334),
198 (-0.695267, -0.593189, 0.032334),
199 (0.648108, 0.593189, 0.032334),
200 (0.648108, 0.518786, 0.032334),
201 (0.648108, -0.518786, 0.032334),
202 (0.648108, -0.593189, 0.032334),
203 (0.695267, 0.593189, 0.032334),
204 (0.695267, 0.518786, 0.032334),
205 (0.695267, -0.518786, 0.032334),
206 (0.695267, -0.593189, 0.032334),
208 [[87, 39, 40, 41], [29, 28, 14, 1], [30, 29, 1, 6], [31, 30, 6, 5], [32, 31, 5, 4], [33, 32, 4, 3],
209 [34, 33, 3, 2], [35, 34, 2, 0], [36, 35, 0, 8], [37, 36, 8, 13], [38, 37, 13, 12], [39, 38, 12, 11],
210 [40, 39, 11, 10], [41, 40, 10, 9], [42, 41, 9, 7], [43, 42, 7, 22], [44, 43, 22, 27], [45, 44, 27, 26],
211 [46, 45, 26, 25], [47, 46, 25, 24], [48, 47, 24, 23], [49, 48, 23, 21], [50, 49, 21, 15], [51, 50, 15, 20],
212 [52, 51, 20, 19], [53, 52, 19, 18], [54, 53, 18, 17], [55, 54, 17, 16], [28, 55, 16, 14], [68, 69, 50, 51],
213 [63, 35, 36, 62], [69, 57, 56, 70], [84, 85, 43, 44], [64, 34, 35, 63], [57, 59, 58, 56], [85, 86, 42, 43],
214 [60, 61, 59, 57], [73, 74, 61, 60], [72, 68, 51, 52], [75, 33, 34, 64], [61, 64, 63, 59], [59, 63, 62, 58],
215 [86, 87, 41, 42], [74, 75, 64, 61], [58, 62, 67, 66], [56, 58, 66, 65], [70, 56, 65, 71], [62, 36, 37, 67],
216 [49, 70, 71, 48], [50, 69, 70, 49], [60, 57, 69, 68], [73, 60, 68, 72], [46, 84, 44, 45], [78, 79, 75, 74],
217 [77, 78, 74, 73], [77, 73, 72, 76], [76, 72, 52, 53], [79, 32, 33, 75], [29, 30, 79, 78], [28, 29, 78, 77],
218 [28, 77, 76, 55], [55, 76, 53, 54], [30, 31, 32, 79], [66, 67, 83, 82], [65, 66, 82, 81], [71, 65, 81, 80],
219 [48, 71, 80, 47], [67, 37, 38, 83], [82, 83, 87, 86], [81, 82, 86, 85], [80, 81, 85, 84], [47, 80, 84, 46],
222 Vector((5.0114, -2.4281, 0.0)),
223 [(-0.490711, -1.0, 0.032334),
224 (-1.0, -0.490711, 0.032334),
225 (1.0, -0.490711, 0.032334),
226 (0.490711, -1.0, 0.032334),
227 (-1.0, 0.490711, 0.032334),
228 (-0.490711, 1.0, 0.032334),
229 (0.490711, 1.0, 0.032334),
230 (1.0, 0.490711, 0.032334),
231 (-0.51852, 0.291276, 0.032334),
232 (-0.51852, -0.291276, 0.032334),
233 (-0.291276, -0.51852, 0.032334),
234 (0.291276, -0.51852, 0.032334),
235 (0.51852, -0.291276, 0.032334),
236 (0.51852, 0.291276, 0.032334),
237 (0.291276, 0.51852, 0.032334),
238 (-0.291276, 0.51852, 0.032334),
240 [[11, 12, 13, 14], [9, 8, 4, 1], [10, 9, 1, 0], [11, 10, 0, 3], [12, 11, 3, 2], [13, 12, 2, 7],
241 [14, 13, 7, 6], [15, 14, 6, 5], [8, 15, 5, 4], [9, 10, 15, 8], [10, 11, 14, 15]]),
243 Vector((-0.11417, 2.48371, -0.0)),
244 [(0.0, 1.0, 0.016827),
245 (-0.382683, 0.92388, 0.016827),
246 (-0.707107, 0.707107, 0.016827),
247 (-0.92388, 0.382683, 0.016827),
248 (-1.0, -0.0, 0.016827),
249 (-0.92388, -0.382684, 0.016827),
250 (-0.707107, -0.707107, 0.016827),
251 (-0.382683, -0.92388, 0.016827),
252 (-0.0, -1.0, 0.016827),
253 (0.382683, -0.92388, 0.016827),
254 (0.707107, -0.707107, 0.016827),
255 (0.92388, -0.382684, 0.016827),
256 (1.0, 0.0, 0.016827),
257 (0.923879, 0.382684, 0.016827),
258 (0.707107, 0.707107, 0.016827),
259 (0.382683, 0.92388, 0.016827),
260 (-0.0, 0.546859, 0.016827),
261 (-0.209274, 0.505231, 0.016827),
262 (-0.386687, 0.386687, 0.016827),
263 (-0.505231, 0.209274, 0.016827),
264 (-0.546859, -0.0, 0.016827),
265 (-0.505231, -0.209274, 0.016827),
266 (-0.386687, -0.386687, 0.016827),
267 (-0.209274, -0.505231, 0.016827),
268 (-0.0, -0.546859, 0.016827),
269 (0.209274, -0.505231, 0.016827),
270 (0.386687, -0.386688, 0.016827),
271 (0.505231, -0.209274, 0.016827),
272 (0.546858, 0.0, 0.016827),
273 (0.505231, 0.209274, 0.016827),
274 (0.386687, 0.386688, 0.016827),
275 (0.209273, 0.505232, 0.016827),
277 [[3, 19, 18, 2], [11, 27, 26, 10], [4, 20, 19, 3], [12, 28, 27, 11], [5, 21, 20, 4], [13, 29, 28, 12],
278 [6, 22, 21, 5], [14, 30, 29, 13], [7, 23, 22, 6], [15, 31, 30, 14], [8, 24, 23, 7], [1, 17, 16, 0],
279 [0, 16, 31, 15], [9, 25, 24, 8], [2, 18, 17, 1], [10, 26, 25, 9]]),
281 Vector((5.50446, 2.41669, -0.0)),
282 [(0.0, 0.714247, 0.023261),
283 (-0.382683, 0.659879, 0.023261),
284 (-0.707107, 0.505049, 0.023261),
285 (-0.92388, 0.273331, 0.023261),
286 (-1.0, -0.0, 0.023261),
287 (-0.92388, -0.273331, 0.023261),
288 (-0.707107, -0.505049, 0.023261),
289 (-0.382683, -0.659879, 0.023261),
290 (-0.0, -0.714247, 0.023261),
291 (0.382683, -0.659879, 0.023261),
292 (0.707107, -0.505049, 0.023261),
293 (0.92388, -0.273331, 0.023261),
294 (1.0, 0.0, 0.023261),
295 (0.923879, 0.273331, 0.023261),
296 (0.707107, 0.505049, 0.023261),
297 (0.382683, 0.659879, 0.023261),
298 (-0.0, 0.303676, 0.023261),
299 (-0.162705, 0.28056, 0.023261),
300 (-0.30064, 0.214731, 0.023261),
301 (-0.392805, 0.116212, 0.023261),
302 (-0.425169, -0.0, 0.023261),
303 (-0.392805, -0.116212, 0.023261),
304 (-0.30064, -0.214731, 0.023261),
305 (-0.162705, -0.28056, 0.023261),
306 (-0.0, -0.303676, 0.023261),
307 (0.162705, -0.28056, 0.023261),
308 (0.30064, -0.214731, 0.023261),
309 (0.392805, -0.116212, 0.023261),
310 (0.425169, 0.0, 0.023261),
311 (0.392805, 0.116212, 0.023261),
312 (0.30064, 0.214731, 0.023261),
313 (0.162705, 0.28056, 0.023261),
315 [[3, 19, 18, 2], [11, 27, 26, 10], [4, 20, 19, 3], [12, 28, 27, 11], [5, 21, 20, 4], [13, 29, 28, 12],
316 [6, 22, 21, 5], [14, 30, 29, 13], [7, 23, 22, 6], [15, 31, 30, 14], [8, 24, 23, 7], [1, 17, 16, 0],
317 [0, 16, 31, 15], [9, 25, 24, 8], [2, 18, 17, 1], [10, 26, 25, 9]]),
319 Vector((2.61824, 2.34147, 0.0)),
320 [(1.0, -1.0, 0.032334),
321 (-1.0, 1.0, 0.032334),
322 (1.0, 1.0, 0.032334),
323 (0.783867, -0.259989, 0.032334),
324 (-0.393641, 0.857073, 0.032334),
325 (0.73142, -0.116299, 0.032334),
326 (0.657754, 0.02916, 0.032334),
327 (0.564682, 0.172804, 0.032334),
328 (0.454497, 0.311098, 0.032334),
329 (0.329912, 0.440635, 0.032334),
330 (0.193995, 0.558227, 0.032334),
331 (0.050092, 0.660978, 0.032334),
332 (-0.098254, 0.746358, 0.032334),
333 (-0.247389, 0.812263, 0.032334),
335 [[3, 0, 2], [10, 9, 2], [2, 1, 4], [2, 4, 13], [5, 3, 2], [6, 5, 2], [2, 13, 12], [2, 12, 11], [7, 6, 2],
336 [8, 7, 2], [2, 11, 10], [9, 8, 2]]),
338 Vector((2.61824, -2.52425, 0.0)),
339 [(1.0, 0.0, 0.020045),
340 (-1.0, 0.0, 0.020045),
341 (0.31903, -0.664947, 0.020045),
342 (-0.31903, -0.664947, 0.020045),
343 (-0.31903, 1.0, 0.020045),
344 (0.31903, 1.0, 0.020045),
345 (0.31903, 0.0, 0.020045),
346 (-0.31903, 0.0, 0.020045),
347 (-1.0, 0.614333, 0.020045),
348 (-0.614333, 1.0, 0.020045),
349 (-0.970643, 0.761921, 0.020045),
350 (-0.887041, 0.887041, 0.020045),
351 (-0.761921, 0.970643, 0.020045),
352 (0.614333, 1.0, 0.020045),
353 (1.0, 0.614333, 0.020045),
354 (0.761921, 0.970643, 0.020045),
355 (0.887041, 0.887041, 0.020045),
356 (0.970643, 0.761921, 0.020045),
357 (-0.31903, 0.614333, 0.020045),
358 (0.31903, 0.614333, 0.020045),
359 (0.31903, 0.761921, 0.020045),
360 (-0.31903, 0.761921, 0.020045),
361 (0.31903, 0.887041, 0.020045),
362 (-0.31903, 0.887041, 0.020045),
363 (0.614333, 0.614333, 0.020045),
364 (0.614333, 0.0, 0.020045),
365 (0.614333, 0.761921, 0.020045),
366 (0.614333, 0.887041, 0.020045),
367 (-0.614333, 0.761921, 0.020045),
368 (-0.614333, 0.0, 0.020045),
369 (-0.614333, 0.887041, 0.020045),
370 (-0.614333, 0.614333, 0.020045),
372 [[6, 25, 24, 19], [6, 19, 18, 7], [2, 6, 7, 3], [1, 29, 31, 8], [8, 31, 28, 10], [19, 24, 26, 20],
373 [18, 19, 20, 21], [21, 20, 22, 23], [10, 28, 30, 11], [20, 26, 27, 22], [22, 27, 13, 5], [23, 22, 5, 4],
374 [11, 30, 9, 12], [17, 16, 27, 26], [14, 17, 26, 24], [24, 25, 0, 14], [15, 13, 27, 16], [9, 30, 23, 4],
375 [31, 29, 7, 18], [28, 31, 18, 21], [30, 28, 21, 23]]),
377 Vector((7.31539, 0.0, 0.0)),
378 [(0.24549, -1.0, 0.022454),
379 (-0.24549, -1.0, 0.022454),
380 (-0.24549, 1.0, 0.022454),
381 (0.24549, 1.0, 0.022454),
382 (1.0, 0.267452, 0.022454),
383 (1.0, -0.267452, 0.022454),
384 (-1.0, -0.267452, 0.022454),
385 (-1.0, 0.267452, 0.022454),
386 (0.24549, 0.267452, 0.022454),
387 (0.24549, -0.267452, 0.022454),
388 (-0.24549, 0.267452, 0.022454),
389 (-0.24549, -0.267452, 0.022454),
391 [[8, 3, 2, 10], [0, 9, 11, 1], [4, 8, 9, 5], [8, 10, 11, 9], [10, 7, 6, 11]]),
393 Vector((4.91276, 0.0, 0.0)),
394 [(-1.0, -1.0, 0.026945),
395 (1.0, -1.0, 0.026945),
396 (-1.0, 1.0, 0.026945),
397 (-0.026763, -1.0, 0.026945),
398 (-0.026763, 1.0, 0.026945),
399 (1.0, -0.026763, 0.026945),
400 (0.238983, 0.965014, 0.026945),
401 (0.486619, 0.86244, 0.026945),
402 (0.699268, 0.699268, 0.026945),
403 (0.86244, 0.486619, 0.026945),
404 (0.965014, 0.238983, 0.026945),
405 (0.238983, -1.0, 0.026945),
406 (0.486619, -1.0, 0.026945),
407 (0.699268, -1.0, 0.026945),
408 (0.86244, -1.0, 0.026945),
409 (-0.026763, 0.479676, 0.026945),
410 (0.486619, 0.479676, 0.026945),
411 (0.699268, 0.479676, 0.026945),
412 (0.238983, 0.479676, 0.026945),
413 (0.865316, 0.479676, 0.026945),
414 (-1.0, 0.479676, 0.026945),
415 (0.86244, 0.479676, 0.026945),
416 (-0.026763, 0.238983, 0.026945),
417 (0.486619, 0.238983, 0.026945),
418 (0.699268, 0.238983, 0.026945),
419 (0.238983, 0.238983, 0.026945),
420 (-1.0, 0.238983, 0.026945),
421 (0.86244, 0.238983, 0.026945),
422 (-0.026763, -0.026763, 0.026945),
423 (0.486619, -0.026763, 0.026945),
424 (0.699268, -0.026763, 0.026945),
425 (0.238983, -0.026763, 0.026945),
426 (-1.0, -0.026763, 0.026945),
427 (0.86244, -0.026763, 0.026945),
429 [[0, 3, 28, 32], [4, 15, 18, 6], [6, 18, 16, 7], [7, 16, 17, 8], [8, 17, 21, 9], [9, 21, 19], [18, 15, 22, 25],
430 [19, 21, 27, 10], [16, 18, 25, 23], [17, 16, 23, 24], [20, 15, 4, 2], [21, 17, 24, 27], [27, 24, 30, 33],
431 [23, 25, 31, 29], [24, 23, 29, 30], [25, 22, 28, 31], [26, 22, 15, 20], [10, 27, 33, 5], [31, 28, 3, 11],
432 [33, 30, 13, 14], [29, 31, 11, 12], [5, 33, 14, 1], [30, 29, 12, 13], [32, 28, 22, 26]]),
434 Vector((2.61824, 0.0, 0.0)),
435 [(-1.0, -1.0, 0.032334),
436 (1.0, -1.0, 0.032334),
437 (-1.0, 1.0, 0.032334),
438 (1.0, 1.0, 0.032334),
442 Vector((0.0, 0.0, 0.0)),
443 [(-1.0, -1.0, 0.032334),
444 (1.0, -1.0, 0.032334),
445 (-1.0, 1.0, 0.032334),
446 (1.0, 1.0, 0.032334),
447 (0.0, 0.0, 0.032334),
448 (0.0, 0.0, 0.032334),
449 (0.0, 0.0, 0.032334),
450 (0.0, 0.0, 0.032334),
451 (0.0, 0.0, 0.032334),
452 (-0.636126, 0.636126, 0.032334),
453 (-0.636126, -0.636126, 0.032334),
454 (0.636126, -0.636126, 0.032334),
455 (0.636126, 0.636126, 0.032334),
457 [[10, 9, 2, 0], [11, 10, 0, 1], [12, 11, 1, 3], [9, 12, 3, 2]]),
470 class CarverPrefs(bpy
.types
.AddonPreferences
):
473 Enable_Tab_01
= BoolProperty(
475 description
="Some general information and settings about the add-on",
478 Enable_Tab_02
= BoolProperty(
480 description
="List of the shortcuts used during carving",
483 bpy
.types
.Scene
.Key_Create
= StringProperty(
484 name
="Object creation",
485 description
="Object creation",
489 bpy
.types
.Scene
.Key_Update
= StringProperty(
490 name
="Auto Bevel Update",
491 description
="Auto Bevel Update",
495 bpy
.types
.Scene
.Key_Bool
= StringProperty(
497 description
="Boolean operation type",
501 bpy
.types
.Scene
.Key_Brush
= StringProperty(
503 description
="Brush Mode",
507 bpy
.types
.Scene
.Key_Help
= StringProperty(
509 description
="Help display",
513 bpy
.types
.Scene
.Key_Instant
= StringProperty(
515 description
="Instantiate object",
519 bpy
.types
.Scene
.Key_Close
= StringProperty(
520 name
="Close polygonal shape",
521 description
="Close polygonal shape",
525 bpy
.types
.Scene
.Key_Apply
= StringProperty(
526 name
="Apply operation",
527 description
="Apply operation",
531 bpy
.types
.Scene
.Key_Scale
= StringProperty(
533 description
="Scale object",
537 bpy
.types
.Scene
.Key_Gapy
= StringProperty(
539 description
="Scale gap between columns",
543 bpy
.types
.Scene
.Key_Gapx
= StringProperty(
545 description
="Scale gap between columns",
549 bpy
.types
.Scene
.Key_Depth
= StringProperty(
551 description
="Cursor depth or solidify pattern",
555 bpy
.types
.Scene
.Key_BrushDepth
= StringProperty(
557 description
="Brush depth",
561 bpy
.types
.Scene
.Key_Subadd
= StringProperty(
562 name
="Add subdivision",
563 description
="Add subdivision",
567 bpy
.types
.Scene
.Key_Subrem
= StringProperty(
568 name
="Remove subdivision",
569 description
="Remove subdivision",
573 bpy
.types
.Scene
.Key_Randrot
= StringProperty(
574 name
="Random rotation",
575 description
="Random rotation",
579 bpy
.types
.Scene
.ProfilePrefix
= StringProperty(
580 name
="Profile prefix",
581 description
="Prefix to look for profiles with",
582 default
="Carver_Profile-"
585 def draw(self
, context
):
586 scene
= context
.scene
589 icon_1
= "TRIA_RIGHT" if not self
.Enable_Tab_01
else "TRIA_DOWN"
591 box
.prop(self
, "Enable_Tab_01", text
="Info and Settings", emboss
=False, icon
=icon_1
)
592 if self
.Enable_Tab_01
:
593 box
.label(text
="Carver Operator:", icon
="LAYER_ACTIVE")
594 box
.label(text
="Select a Mesh Object and press [CTRL]+[SHIFT]+[X] to carve",
596 box
.label(text
="To finish carving press [ESC] or [RIGHT CLICK]",
598 box
.prop(scene
, "ProfilePrefix", text
="Profile prefix")
600 icon_2
= "TRIA_RIGHT" if not self
.Enable_Tab_02
else "TRIA_DOWN"
602 box
.prop(self
, "Enable_Tab_02", text
="Keys", emboss
=False, icon
=icon_2
)
603 if self
.Enable_Tab_02
:
604 split
= box
.split(align
=True)
606 col
= box
.column(align
=True)
607 col
.label("Object Creation:")
608 col
.prop(scene
, "Key_Create", text
="")
609 col
.label("Auto bevel update:")
610 col
.prop(scene
, "Key_Update", text
="")
611 col
.label("Boolean operation type:")
612 col
.prop(scene
, "Key_Bool", text
="")
613 col
.label("Brush Depth:")
614 col
.prop(scene
, "Key_BrushDepth", text
="")
617 col
= box
.column(align
=True)
618 col
.label("Brush Mode:")
619 col
.prop(scene
, "Key_Brush", text
="")
620 col
.label("Help display:")
621 col
.prop(scene
, "Key_Help", text
="")
622 col
.label("Instantiate object:")
623 col
.prop(scene
, "Key_Instant", text
="")
624 col
.label("Random rotation:")
625 col
.prop(scene
, "Key_Randrot", text
="")
628 col
= box
.column(align
=True)
629 col
.label("Close polygonal shape:")
630 col
.prop(scene
, "Key_Close", text
="")
631 col
.label("Apply operation:")
632 col
.prop(scene
, "Key_Apply", text
="")
633 col
.label("Scale object:")
634 col
.prop(scene
, "Key_Scale", text
="")
635 col
.label("Subdiv add:")
636 col
.prop(scene
, "Key_Subadd", text
="")
639 col
= box
.column(align
=True)
640 col
.label("Gap rows:")
641 col
.prop(scene
, "Key_Gapy", text
="")
642 col
.label("Gap columns:")
643 col
.prop(scene
, "Key_Gapx", text
="")
644 col
.label("Depth / Solidify:")
645 col
.prop(scene
, "Key_Depth", text
="")
646 col
.label("Subdiv Remove:")
647 col
.prop(scene
, "Key_Subrem", text
="")
650 # Draw Text (Center position)
651 def DrawCenterText(text
, xt
, yt
, Size
, colors
, self
):
657 blf
.size(font_id
, Size
, 72)
658 blf
.position(font_id
, xt
+ Sshadow_x
- blf
.dimensions(font_id
, text
)[0] / 2, yt
+ Sshadow_y
, 0)
659 bgl
.glColor4f(0.0, 0.0, 0.0, 1.0)
661 blf
.draw(font_id
, text
)
662 blf
.position(font_id
, xt
- blf
.dimensions(font_id
, text
)[0] / 2, yt
, 0)
663 if colors
is not None:
664 mcolor
= Color((colors
[0], colors
[1], colors
[2]))
665 bgl
.glColor4f(mcolor
.r
, mcolor
.g
, mcolor
.b
, 1.0)
667 bgl
.glColor4f(1.0, 1.0, 1.0, 1.0)
668 blf
.draw(font_id
, text
)
671 # Draw text (Left position)
672 def DrawLeftText(text
, xt
, yt
, Size
, colors
, self
):
678 blf
.size(font_id
, Size
, 72)
679 blf
.position(font_id
, xt
+ Sshadow_x
, yt
+ Sshadow_y
, 0)
680 bgl
.glColor4f(0.0, 0.0, 0.0, 1.0)
681 blf
.draw(font_id
, text
)
682 blf
.position(font_id
, xt
, yt
, 0)
683 if colors
is not None:
684 mcolor
= Color((colors
[0], colors
[1], colors
[2]))
685 bgl
.glColor4f(mcolor
.r
, mcolor
.g
, mcolor
.b
, 1.0)
687 bgl
.glColor4f(1.0, 1.0, 1.0, 1.0)
688 blf
.draw(font_id
, text
)
691 # Draw text (Right position)
692 def DrawRightText(text
, xt
, yt
, Size
, colors
, self
):
698 blf
.size(font_id
, Size
, 72)
699 blf
.position(font_id
, xt
+ Sshadow_x
- blf
.dimensions(font_id
, text
)[0], yt
+ Sshadow_y
, 0)
700 bgl
.glColor4f(0.0, 0.0, 0.0, 1.0)
701 blf
.draw(font_id
, text
)
702 blf
.position(font_id
, xt
- blf
.dimensions(font_id
, text
)[0], yt
, 0)
703 if colors
is not None:
704 mcolor
= Color((colors
[0], colors
[1], colors
[2]))
705 bgl
.glColor4f(mcolor
.r
, mcolor
.g
, mcolor
.b
, 1.0)
707 bgl
.glColor4f(1.0, 1.0, 1.0, 1.0)
708 blf
.draw(font_id
, text
)
712 def draw_callback_px(self
, context
):
714 region
= context
.region
717 overlap
= context
.user_preferences
.system
.use_region_overlap
720 for region
in context
.area
.regions
:
721 if region
.type == 'TOOLS':
722 t_panel_width
= region
.width
725 xt
= int(region
.width
/ 2.0)
727 if region
.width
>= 850:
728 xt
= int(region
.width
/ 2.0)
732 if self
.CreateMode
and ((self
.ObjectMode
is False) and (self
.ProfileMode
is False)):
733 BooleanMode
= "Create"
735 if self
.ObjectMode
or self
.ProfileMode
:
736 BooleanType
= "Difference) [T]" if self
.BoolOps
== DIFFERENCE
else "Union) [T]"
738 "Object Brush (" + BooleanType
if self
.ObjectMode
else "Profil Brush (" + BooleanType
741 "Difference" if (self
.shift
is False) and (self
.ForceRebool
is False) else "Rebool"
743 UIColor
= (0.992, 0.5518, 0.0, 1.0)
745 # Display boolean mode
746 text_size
= 40 if region
.width
>= 850 else 20
747 DrawCenterText(BooleanMode
, xt
, yt
, text_size
, UIColor
, self
)
751 if region
.width
>= 850:
754 bgl
.glColor4f(1.0, 1.0, 1.0, 1.0)
755 bgl
.glBegin(bgl
.GL_LINE_STRIP
)
756 bgl
.glVertex2i(int(xt
- LineWidth
), yt
- 8)
757 bgl
.glVertex2i(int(xt
+ LineWidth
), yt
- 8)
761 xt
= xt
- blf
.dimensions(font_id
, "Difference")[0] / 2 + 80
764 PrimitiveType
= "Rectangle "
765 if self
.CutMode
== CIRCLE
:
766 PrimitiveType
= "Circle "
767 if self
.CutMode
== LINE
:
768 PrimitiveType
= "Line "
770 # Variables according to screen size
775 if region
.width
>= 850:
784 if (self
.ObjectMode
is False) and (self
.ProfileMode
is False):
785 TypeStr
= "Cut Type [Space] : "
787 TypeStr
= "Type [Space] : "
788 blf
.size(font_id
, IFontSize
, 72)
789 OpsStr
= TypeStr
+ PrimitiveType
790 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
791 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
792 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
793 DrawLeftText(TypeStr
, xLeft
, yCmd
, IFontSize
, Color0
, self
)
794 DrawLeftText(PrimitiveType
, xLeftP
, yCmd
, IFontSize
, Color1
, self
)
797 TypeStr
= "Cursor Depth [" + context
.scene
.Key_Depth
+ "] : "
798 BoolStr
= "(ON)" if self
.snapCursor
else "(OFF)"
799 OpsStr
= TypeStr
+ BoolStr
801 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
802 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
803 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
804 DrawLeftText(TypeStr
, xLeft
, yCmd
- yInterval
, IFontSize
, Color0
, self
)
805 DrawLeftText(BoolStr
, xLeftP
, yCmd
- yInterval
, IFontSize
, Color1
, self
)
807 if self
.CreateMode
is False:
809 TypeStr
= "Apply Operations [" + context
.scene
.Key_Apply
+ "] : "
810 BoolStr
= "(OFF)" if self
.DontApply
else "(ON)"
811 OpsStr
= TypeStr
+ BoolStr
813 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
814 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
815 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
816 DrawLeftText(TypeStr
, xLeft
, yCmd
- yInterval
* 2, IFontSize
, Color0
, self
)
817 DrawLeftText(BoolStr
, xLeftP
, yCmd
- yInterval
* 2, IFontSize
, Color1
, self
)
819 # Auto update for bevel
820 TypeStr
= "Bevel Update [" + context
.scene
.Key_Update
+ "] : "
821 BoolStr
= "(ON)" if self
.Auto_BevelUpdate
else "(OFF)"
822 OpsStr
= TypeStr
+ BoolStr
824 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
825 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
826 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
827 DrawLeftText(TypeStr
, xLeft
, yCmd
- yInterval
* 3, IFontSize
, Color0
, self
)
828 DrawLeftText(BoolStr
, xLeftP
, yCmd
- yInterval
* 3, IFontSize
, Color1
, self
)
831 if self
.CutMode
== CIRCLE
:
832 y
= yCmd
- yInterval
* 4 if self
.CreateMode
is False else yCmd
- yInterval
* 2
833 TypeStr
= "Subdivisions [" + context
.scene
.Key_Subrem
+ "][" + context
.scene
.Key_Subadd
+ "] : "
834 BoolStr
= str((int(360 / self
.stepAngle
[self
.step
])))
835 OpsStr
= TypeStr
+ BoolStr
836 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
837 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
838 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
839 DrawLeftText(TypeStr
, xLeft
, y
, IFontSize
, Color0
, self
)
840 DrawLeftText(BoolStr
, xLeftP
, y
, IFontSize
, Color1
, self
)
844 TypeStr
= "Instantiate [" + context
.scene
.Key_Instant
+ "] : "
845 BoolStr
= "(ON)" if self
.Instantiate
else "(OFF)"
846 OpsStr
= TypeStr
+ BoolStr
848 blf
.size(font_id
, IFontSize
, 72)
849 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
850 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
851 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
852 DrawLeftText(TypeStr
, xLeft
, yCmd
, IFontSize
, Color0
, self
)
853 DrawLeftText(BoolStr
, xLeftP
, yCmd
, IFontSize
, Color1
, self
)
857 TypeStr
= "Random Rotation [" + context
.scene
.Key_Randrot
+ "] : "
858 BoolStr
= "(ON)" if self
.RandomRotation
else "(OFF)"
859 OpsStr
= TypeStr
+ BoolStr
861 blf
.size(font_id
, IFontSize
, 72)
862 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
863 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
864 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
865 DrawLeftText(TypeStr
, xLeft
, yCmd
- yInterval
, IFontSize
, Color0
, self
)
866 DrawLeftText(BoolStr
, xLeftP
, yCmd
- yInterval
, IFontSize
, Color1
, self
)
869 if self
.BrushSolidify
:
870 TypeStr
= "Thickness [" + context
.scene
.Key_Depth
+ "] : "
872 BoolStr
= str(round(self
.ProfileBrush
.modifiers
["CT_SOLIDIFY"].thickness
, 2))
874 BoolStr
= str(round(self
.ObjectBrush
.modifiers
["CT_SOLIDIFY"].thickness
, 2))
875 OpsStr
= TypeStr
+ BoolStr
876 blf
.size(font_id
, IFontSize
, 72)
877 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
878 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
879 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
881 self_alt_y
= 2 if self
.alt
else 1
882 DrawLeftText(TypeStr
, xLeft
, yCmd
- yInterval
* self_alt_y
, IFontSize
, Color0
, self
)
883 DrawLeftText(BoolStr
, xLeftP
, yCmd
- yInterval
* self_alt_y
, IFontSize
, Color1
, self
)
886 if (self
.ObjectMode
):
887 TypeStr
= "Carve Depth [" + context
.scene
.Key_Depth
+ "] : "
888 BoolStr
= str(round(self
.ObjectBrush
.data
.vertices
[0].co
.z
, 2))
889 OpsStr
= TypeStr
+ BoolStr
891 blf
.size(font_id
, IFontSize
, 72)
892 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
893 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
894 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
896 self_alt_y
= 2 if self
.alt
else 1
897 DrawLeftText(TypeStr
, xLeft
, yCmd
- yInterval
* self_alt_y
, IFontSize
, Color0
, self
)
898 DrawLeftText(BoolStr
, xLeftP
, yCmd
- yInterval
* self_alt_y
, IFontSize
, Color1
, self
)
900 TypeStr
= "Brush Depth [" + context
.scene
.Key_BrushDepth
+ "] : "
901 BoolStr
= str(round(self
.BrushDepthOffset
, 2))
902 OpsStr
= TypeStr
+ BoolStr
904 blf
.size(font_id
, IFontSize
, 72)
905 TotalWidth
= blf
.dimensions(font_id
, OpsStr
)[0]
906 xLeft
= region
.width
/ 2 - TotalWidth
/ 2
907 xLeftP
= xLeft
+ blf
.dimensions(font_id
, TypeStr
)[0]
909 self_alt_y
= 3 if self
.alt
else 2
910 DrawLeftText(TypeStr
, xLeft
, yCmd
- yInterval
* self_alt_y
, IFontSize
, Color0
, self
)
911 DrawLeftText(BoolStr
, xLeftP
, yCmd
- yInterval
* self_alt_y
, IFontSize
, Color1
, self
)
913 bgl
.glEnable(bgl
.GL_BLEND
)
914 if region
.width
>= 850:
915 if self
.AskHelp
is False:
918 bgl
.glColor4f(0.0, 0.0, 0.0, 0.3)
919 bgl
.glRecti(xrect
, yrect
, xrect
+ 90, yrect
+ 25)
920 DrawLeftText("[" + context
.scene
.Key_Help
+ "] for help", xrect
+ 10, yrect
+ 8, 13, None, self
)
922 xHelp
= 30 + t_panel_width
926 if region
.width
>= 850:
931 if self
.ObjectMode
or self
.ProfileMode
:
933 DrawLeftText("[" + context
.scene
.Key_Brush
+ "]", xHelp
, yHelp
+
934 Help_Interval
* 2, Help_FontSize
, UIColor
, self
)
935 DrawLeftText(": Object Mode", 150 + t_panel_width
, yHelp
+
936 Help_Interval
* 2, Help_FontSize
, None, self
)
938 DrawLeftText("[" + context
.scene
.Key_Brush
+ "]", xHelp
, yHelp
+
939 Help_Interval
* 2, Help_FontSize
, UIColor
, self
)
940 DrawLeftText(": Return", 150 + t_panel_width
, yHelp
+
941 Help_Interval
* 2, Help_FontSize
, None, self
)
943 DrawLeftText("[" + context
.scene
.Key_Brush
+ "]", xHelp
, yHelp
+
944 Help_Interval
* 2, Help_FontSize
, UIColor
, self
)
945 DrawLeftText(": Profil Brush", 150 + t_panel_width
, yHelp
+
946 Help_Interval
* 2, Help_FontSize
, None, self
)
947 DrawLeftText("[Ctrl + LMB]", xHelp
, yHelp
- Help_Interval
* 6,
948 Help_FontSize
, UIColor
, self
)
949 DrawLeftText(": Move Cursor", 150 + t_panel_width
, yHelp
-
950 Help_Interval
* 6, Help_FontSize
, None, self
)
952 if (self
.ObjectMode
is False) and (self
.ProfileMode
is False):
953 if self
.CreateMode
is False:
954 DrawLeftText("[" + context
.scene
.Key_Create
+ "]", xHelp
,
955 yHelp
+ Help_Interval
, Help_FontSize
, UIColor
, self
)
956 DrawLeftText(": Create geometry", 150 + t_panel_width
,
957 yHelp
+ Help_Interval
, Help_FontSize
, None, self
)
959 DrawLeftText("[" + context
.scene
.Key_Create
+ "]", xHelp
,
960 yHelp
+ Help_Interval
, Help_FontSize
, UIColor
, self
)
961 DrawLeftText(": Cut", 150 + t_panel_width
, yHelp
+ Help_Interval
,
962 Help_FontSize
, None, self
)
964 if self
.CutMode
== RECTANGLE
:
965 DrawLeftText("MouseMove", xHelp
, yHelp
, Help_FontSize
, UIColor
, self
)
966 DrawLeftText("[Alt]", xHelp
, yHelp
- Help_Interval
, Help_FontSize
, UIColor
, self
)
967 DrawLeftText(": Dimension", 150 + t_panel_width
, yHelp
, Help_FontSize
, None, self
)
968 DrawLeftText(": Move all", 150 + t_panel_width
, yHelp
- Help_Interval
,
969 Help_FontSize
, None, self
)
971 if self
.CutMode
== CIRCLE
:
972 DrawLeftText("MouseMove", xHelp
, yHelp
, Help_FontSize
, UIColor
, self
)
973 DrawLeftText("[Alt]", xHelp
, yHelp
- Help_Interval
, Help_FontSize
, UIColor
, self
)
974 DrawLeftText("[" + context
.scene
.Key_Subrem
+ "] [" + context
.scene
.Key_Subadd
+ "]",
975 xHelp
, yHelp
- Help_Interval
* 2, Help_FontSize
, UIColor
, self
)
976 DrawLeftText("[Ctrl]", xHelp
, yHelp
- Help_Interval
* 3, Help_FontSize
, UIColor
, self
)
977 DrawLeftText(": Rotation and Radius", 150 + t_panel_width
, yHelp
, Help_FontSize
, None, self
)
978 DrawLeftText(": Move all", 150 + t_panel_width
, yHelp
- Help_Interval
,
979 Help_FontSize
, None, self
)
980 DrawLeftText(": Subdivision", 150 + t_panel_width
, yHelp
-
981 Help_Interval
* 2, Help_FontSize
, None, self
)
982 DrawLeftText(": Incremental rotation", 150 + t_panel_width
,
983 yHelp
- Help_Interval
* 3, Help_FontSize
, None, self
)
985 if self
.CutMode
== LINE
:
986 DrawLeftText("MouseMove", xHelp
, yHelp
, Help_FontSize
, UIColor
, self
)
987 DrawLeftText("[Alt]", xHelp
, yHelp
- Help_Interval
, Help_FontSize
, UIColor
, self
)
988 DrawLeftText("[Space]", xHelp
, yHelp
- Help_Interval
* 2, Help_FontSize
, UIColor
, self
)
989 DrawLeftText("[Ctrl]", xHelp
, yHelp
- Help_Interval
* 3, Help_FontSize
, UIColor
, self
)
990 DrawLeftText(": Dimension", 150 + t_panel_width
, yHelp
, Help_FontSize
, None, self
)
991 DrawLeftText(": Move all", 150 + t_panel_width
, yHelp
- Help_Interval
,
992 Help_FontSize
, None, self
)
993 DrawLeftText(": Validate", 150 + t_panel_width
, yHelp
-
994 Help_Interval
* 2, Help_FontSize
, None, self
)
995 DrawLeftText(": Incremental", 150 + t_panel_width
, yHelp
-
996 Help_Interval
* 3, Help_FontSize
, None, self
)
998 DrawLeftText("[" + context
.scene
.Key_Subadd
+ "]", xHelp
, yHelp
-
999 Help_Interval
* 4, Help_FontSize
, UIColor
, self
)
1000 DrawLeftText(": Close geometry", 150 + t_panel_width
, yHelp
-
1001 Help_Interval
* 4, Help_FontSize
, None, self
)
1003 DrawLeftText("[Space]", xHelp
, yHelp
+ Help_Interval
, Help_FontSize
, UIColor
, self
)
1004 DrawLeftText(": Difference", 150 + t_panel_width
, yHelp
+ Help_Interval
,
1005 Help_FontSize
, None, self
)
1006 DrawLeftText("[Shift][Space]", xHelp
, yHelp
, Help_FontSize
, UIColor
, self
)
1007 DrawLeftText(": Rebool", 150 + t_panel_width
, yHelp
, Help_FontSize
, None, self
)
1008 DrawLeftText("[Alt][Space]", xHelp
, yHelp
- Help_Interval
, Help_FontSize
, UIColor
, self
)
1009 DrawLeftText(": Duplicate", 150 + t_panel_width
, yHelp
- Help_Interval
,
1010 Help_FontSize
, None, self
)
1011 DrawLeftText("[" + context
.scene
.Key_Scale
+ "]", xHelp
, yHelp
-
1012 Help_Interval
* 2, Help_FontSize
, UIColor
, self
)
1013 DrawLeftText(": Scale", 150 + t_panel_width
, yHelp
- Help_Interval
* 2,
1014 Help_FontSize
, None, self
)
1015 DrawLeftText("[LMB][Move]", xHelp
, yHelp
- Help_Interval
* 3, Help_FontSize
, UIColor
, self
)
1016 DrawLeftText(": Rotation", 150 + t_panel_width
, yHelp
- Help_Interval
* 3,
1017 Help_FontSize
, None, self
)
1018 DrawLeftText("[Ctrl][LMB][Move]", xHelp
, yHelp
- Help_Interval
* 4,
1019 Help_FontSize
, UIColor
, self
)
1020 DrawLeftText(": Step Angle", 150 + t_panel_width
, yHelp
- Help_Interval
* 4,
1021 Help_FontSize
, None, self
)
1022 if self
.ProfileMode
:
1023 DrawLeftText("[" + context
.scene
.Key_Subadd
+ "][" + context
.scene
.Key_Subrem
+ "]",
1024 xHelp
, yHelp
- Help_Interval
* 5, Help_FontSize
, UIColor
, self
)
1025 DrawLeftText(": Previous or Next Profile", 150 + t_panel_width
,
1026 yHelp
- Help_Interval
* 5, Help_FontSize
, None, self
)
1027 DrawLeftText("[ARROWS]", xHelp
, yHelp
- Help_Interval
* 6, Help_FontSize
, UIColor
, self
)
1028 DrawLeftText(": Create / Delete rows or columns", 150 + t_panel_width
,
1029 yHelp
- Help_Interval
* 6, Help_FontSize
, None, self
)
1030 DrawLeftText("[" + context
.scene
.Key_Gapy
+ "][" + context
.scene
.Key_Gapx
+ "]",
1031 xHelp
, yHelp
- Help_Interval
* 7, Help_FontSize
, UIColor
, self
)
1032 DrawLeftText(": Gap between rows or columns", 150 + t_panel_width
,
1033 yHelp
- Help_Interval
* 7, Help_FontSize
, None, self
)
1036 bgl
.glEnable(bgl
.GL_BLEND
)
1037 bgl
.glColor4f(0.512, 0.919, 0.04, 1.0)
1040 bgl
.glEnable(bgl
.GL_POINT_SMOOTH
)
1043 if self
.ProfileMode
:
1044 xrect
= region
.width
- t_panel_width
- 80
1046 bgl
.glColor4f(0.0, 0.0, 0.0, 0.3)
1047 bgl
.glRecti(xrect
, yrect
, xrect
+ 60, yrect
- 60)
1049 faces
= self
.Profils
[self
.nProfil
][3]
1050 vertices
= self
.Profils
[self
.nProfil
][2]
1052 location
= Vector((region
.width
- t_panel_width
- WidthProfil
, 50, 0))
1054 bgl
.glColor4f(UIColor
[0], UIColor
[1], UIColor
[2], 0.7)
1057 bgl
.glBegin(bgl
.GL_QUADS
)
1058 bgl
.glVertex3f(vertices
[f
[0]][0] * ProfilScale
+ location
.x
, vertices
[f
[0]][1] *
1059 ProfilScale
+ location
.y
, vertices
[f
[0]][2] * ProfilScale
+ location
.z
)
1060 bgl
.glVertex3f(vertices
[f
[1]][0] * ProfilScale
+ location
.x
, vertices
[f
[1]][1] *
1061 ProfilScale
+ location
.y
, vertices
[f
[1]][2] * ProfilScale
+ location
.z
)
1062 bgl
.glVertex3f(vertices
[f
[2]][0] * ProfilScale
+ location
.x
, vertices
[f
[2]][1] *
1063 ProfilScale
+ location
.y
, vertices
[f
[2]][2] * ProfilScale
+ location
.z
)
1064 bgl
.glVertex3f(vertices
[f
[3]][0] * ProfilScale
+ location
.x
, vertices
[f
[3]][1] *
1065 ProfilScale
+ location
.y
, vertices
[f
[3]][2] * ProfilScale
+ location
.z
)
1068 bgl
.glBegin(bgl
.GL_TRIANGLES
)
1069 bgl
.glVertex3f(vertices
[f
[0]][0] * ProfilScale
+ location
.x
, vertices
[f
[0]][1] *
1070 ProfilScale
+ location
.y
, vertices
[f
[0]][2] * ProfilScale
+ location
.z
)
1071 bgl
.glVertex3f(vertices
[f
[1]][0] * ProfilScale
+ location
.x
, vertices
[f
[1]][1] *
1072 ProfilScale
+ location
.y
, vertices
[f
[1]][2] * ProfilScale
+ location
.z
)
1073 bgl
.glVertex3f(vertices
[f
[2]][0] * ProfilScale
+ location
.x
, vertices
[f
[2]][1] *
1074 ProfilScale
+ location
.y
, vertices
[f
[2]][2] * ProfilScale
+ location
.z
)
1078 if len(self
.mouse_path
) > 1:
1079 x0
= self
.mouse_path
[0][0]
1080 y0
= self
.mouse_path
[0][1]
1081 x1
= self
.mouse_path
[1][0]
1082 y1
= self
.mouse_path
[1][1]
1085 if self
.CutMode
== LINE
:
1086 if (self
.shift
) or (self
.CreateMode
and self
.Closed
):
1087 bgl
.glColor4f(UIColor
[0], UIColor
[1], UIColor
[2], 0.5)
1089 bgl
.glBegin(bgl
.GL_POLYGON
)
1090 for x
, y
in self
.mouse_path
:
1091 bgl
.glVertex2i(x
+ self
.xpos
, y
+ self
.ypos
)
1094 bgl
.glColor4f(UIColor
[0], UIColor
[1], UIColor
[2], 1.0)
1095 bgl
.glBegin(bgl
.GL_LINE_STRIP
)
1096 for x
, y
in self
.mouse_path
:
1097 bgl
.glVertex2i(x
+ self
.xpos
, y
+ self
.ypos
)
1099 if (self
.CreateMode
is False) or (self
.CreateMode
and self
.Closed
):
1100 bgl
.glBegin(bgl
.GL_LINE_STRIP
)
1101 bgl
.glVertex2i(self
.mouse_path
[len(self
.mouse_path
) - 1][0] + self
.xpos
,
1102 self
.mouse_path
[len(self
.mouse_path
) - 1][1] + self
.ypos
)
1103 bgl
.glVertex2i(self
.mouse_path
[0][0] + self
.xpos
, self
.mouse_path
[0][1] + self
.ypos
)
1107 bgl
.glBegin(bgl
.GL_POINTS
)
1108 for x
, y
in self
.mouse_path
:
1109 bgl
.glVertex2i(x
+ self
.xpos
, y
+ self
.ypos
)
1113 if self
.CutMode
== RECTANGLE
:
1114 bgl
.glColor4f(UIColor
[0], UIColor
[1], UIColor
[2], 0.5)
1116 # if SHIFT, fill primitive
1117 if self
.shift
or self
.CreateMode
:
1118 bgl
.glBegin(bgl
.GL_QUADS
)
1119 bgl
.glVertex2i(x0
+ self
.xpos
, y0
+ self
.ypos
)
1120 bgl
.glVertex2i(x1
+ self
.xpos
, y0
+ self
.ypos
)
1121 bgl
.glVertex2i(x1
+ self
.xpos
, y1
+ self
.ypos
)
1122 bgl
.glVertex2i(x0
+ self
.xpos
, y1
+ self
.ypos
)
1125 bgl
.glBegin(bgl
.GL_LINE_STRIP
)
1126 bgl
.glVertex2i(x0
+ self
.xpos
, y0
+ self
.ypos
)
1127 bgl
.glVertex2i(x1
+ self
.xpos
, y0
+ self
.ypos
)
1128 bgl
.glVertex2i(x1
+ self
.xpos
, y1
+ self
.ypos
)
1129 bgl
.glVertex2i(x0
+ self
.xpos
, y1
+ self
.ypos
)
1130 bgl
.glVertex2i(x0
+ self
.xpos
, y0
+ self
.ypos
)
1134 bgl
.glColor4f(UIColor
[0], UIColor
[1], UIColor
[2], 1.0)
1135 bgl
.glBegin(bgl
.GL_POINTS
)
1136 bgl
.glVertex2i(x0
+ self
.xpos
, y0
+ self
.ypos
)
1137 bgl
.glVertex2i(x1
+ self
.xpos
, y0
+ self
.ypos
)
1138 bgl
.glVertex2i(x1
+ self
.xpos
, y1
+ self
.ypos
)
1139 bgl
.glVertex2i(x0
+ self
.xpos
, y1
+ self
.ypos
)
1143 if self
.CutMode
== CIRCLE
:
1144 DEG2RAD
= 3.14159 / 180
1145 v0
= Vector((self
.mouse_path
[0][0], self
.mouse_path
[0][1], 0))
1146 v1
= Vector((self
.mouse_path
[1][0], self
.mouse_path
[1][1], 0))
1148 radius
= self
.mouse_path
[1][0] - self
.mouse_path
[0][0]
1149 DEG2RAD
= 3.14159 / (180.0 / self
.stepAngle
[self
.step
])
1151 self
.stepR
= (self
.mouse_path
[1][1] - self
.mouse_path
[0][1]) / 25
1152 shift
= (3.14159 / (360.0 / 60.0)) * int(self
.stepR
)
1154 shift
= (self
.mouse_path
[1][1] - self
.mouse_path
[0][1]) / 50
1156 if self
.shift
or self
.CreateMode
:
1157 bgl
.glColor4f(UIColor
[0], UIColor
[1], UIColor
[2], 0.5)
1158 bgl
.glBegin(bgl
.GL_TRIANGLE_FAN
)
1159 bgl
.glVertex2f(x0
+ self
.xpos
, y0
+ self
.ypos
)
1160 for i
in range(0, int(360 / self
.stepAngle
[self
.step
])):
1161 degInRad
= i
* DEG2RAD
1162 bgl
.glVertex2f(x0
+ self
.xpos
+ math
.cos(degInRad
+ shift
) * radius
,
1163 y0
+ self
.ypos
+ math
.sin(degInRad
+ shift
) * radius
)
1164 bgl
.glVertex2f(x0
+ self
.xpos
+ math
.cos(0 + shift
) * radius
,
1165 y0
+ self
.ypos
+ math
.sin(0 + shift
) * radius
)
1168 bgl
.glColor4f(UIColor
[0], UIColor
[1], UIColor
[2], 1.0)
1169 bgl
.glBegin(bgl
.GL_LINE_LOOP
)
1170 for i
in range(0, int(360 / self
.stepAngle
[self
.step
])):
1171 degInRad
= i
* DEG2RAD
1172 bgl
.glVertex2f(x0
+ self
.xpos
+ math
.cos(degInRad
+ shift
) * radius
,
1173 y0
+ self
.ypos
+ math
.sin(degInRad
+ shift
) * radius
)
1176 if self
.ObjectMode
or self
.ProfileMode
:
1178 region
= context
.region
1179 rv3d
= context
.space_data
.region_3d
1182 ob
= self
.ObjectBrush
1183 if self
.ProfileMode
:
1184 ob
= self
.ProfileBrush
1185 mat
= ob
.matrix_world
1187 # 50% alpha, 2 pixel width line
1188 bgl
.glEnable(bgl
.GL_BLEND
)
1190 bbox
= [mat
* Vector(b
) for b
in ob
.bound_box
]
1194 bgl
.glColor4f(0.5, 1.0, 0.0, 1.0)
1197 bgl
.glColor4f(1.0, 0.8, 0.0, 1.0)
1198 bgl
.glBegin(bgl
.GL_LINE_STRIP
)
1200 CRadius
= ((bbox
[7] - bbox
[0]).length
) / 2
1201 for i
in range(int(len(self
.CLR_C
) / 3)):
1202 vector3d
= (self
.CLR_C
[idx
* 3] * CRadius
+ self
.CurLoc
.x
, self
.CLR_C
[idx
* 3 + 1] *
1203 CRadius
+ self
.CurLoc
.y
, self
.CLR_C
[idx
* 3 + 2] * CRadius
+ self
.CurLoc
.z
)
1204 vector2d
= bpy_extras
.view3d_utils
.location_3d_to_region_2d(region
, rv3d
, vector3d
)
1205 if vector2d
is not None:
1206 bgl
.glVertex2f(*vector2d
)
1211 bgl
.glDisable(bgl
.GL_BLEND
)
1212 bgl
.glColor4f(0.0, 0.0, 0.0, 1.0)
1215 if self
.qRot
is not None:
1216 ob
.location
= self
.CurLoc
1219 v
.z
= self
.BrushDepthOffset
1220 ob
.location
+= self
.qRot
* v
1225 e
.z
= self
.aRotZ
/ 25.0
1227 qe
= e
.to_quaternion()
1228 qRot
= self
.qRot
* qe
1229 ob
.rotation_mode
= 'QUATERNION'
1230 ob
.rotation_quaternion
= qRot
1231 ob
.rotation_mode
= 'XYZ'
1233 if self
.ProfileMode
:
1234 if self
.ProfileBrush
is not None:
1235 self
.ProfileBrush
.location
= self
.CurLoc
1236 self
.ProfileBrush
.rotation_mode
= 'QUATERNION'
1237 self
.ProfileBrush
.rotation_quaternion
= qRot
1238 self
.ProfileBrush
.rotation_mode
= 'XYZ'
1242 bgl
.glDisable(bgl
.GL_BLEND
)
1243 bgl
.glColor4f(0.0, 0.0, 0.0, 1.0)
1244 bgl
.glDisable(bgl
.GL_POINT_SMOOTH
)
1248 # intersection function (ideasman42)
1249 def isect_line_plane_v3(p0
, p1
, p_co
, p_no
, epsilon
=1e-6):
1251 p0, p1: define the line
1252 p_co, p_no: define the plane:
1253 p_co is a point on the plane (plane coordinate).
1254 p_no is a normal vector defining the plane direction; does not need to be normalized.
1256 return a Vector or None (when the intersection can't be found).
1259 u
= sub_v3v3(p1
, p0
)
1260 dot
= dot_v3v3(p_no
, u
)
1262 if abs(dot
) > epsilon
:
1263 # the factor of the point between p0 -> p1 (0 - 1)
1264 # if 'fac' is between (0 - 1) the point intersects with the segment.
1267 # > 1.0: infront of p1.
1268 w
= sub_v3v3(p0
, p_co
)
1269 fac
= -dot_v3v3(p_no
, w
) / dot
1270 u
= mul_v3_fl(u
, fac
)
1271 return add_v3v3(p0
, u
)
1273 # The segment is parallel to plane
1277 # ----------------------
1278 # generic math functions
1280 def add_v3v3(v0
, v1
):
1288 def sub_v3v3(v0
, v1
):
1296 def dot_v3v3(v0
, v1
):
1304 def len_squared_v3(v0
):
1305 return dot_v3v3(v0
, v0
)
1308 def mul_v3_fl(v0
, f
):
1317 def CreateCutSquare(self
, context
):
1321 me
= bpy
.data
.meshes
.new('CMT_Square')
1323 ob
= bpy
.data
.objects
.new('CMT_Square', me
)
1325 self
.CurrentObj
= ob
1328 region
= context
.region
1329 rv3d
= context
.region_data
1330 coord
= self
.mouse_path
[0][0], self
.mouse_path
[0][1]
1332 depthLocation
= region_2d_to_vector_3d(region
, rv3d
, coord
)
1333 self
.ViewVector
= depthLocation
1335 PlanePoint
= context
.scene
.cursor_location
1337 PlanePoint
= self
.OpsObj
.location
if self
.OpsObj
is not None else Vector((0.0, 0.0, 0.0))
1339 PlaneNormal
= depthLocation
1340 PlaneNormalised
= PlaneNormal
.normalized()
1342 # Link object to scene
1343 context
.scene
.objects
.link(ob
)
1348 # Convert in 3d space
1349 v0
= self
.mouse_path
[0][0] + self
.xpos
, self
.mouse_path
[0][1] + self
.ypos
1350 v1
= self
.mouse_path
[1][0] + self
.xpos
, self
.mouse_path
[1][1] + self
.ypos
1351 v2
= self
.mouse_path
[1][0] + self
.xpos
, self
.mouse_path
[0][1] + self
.ypos
1352 v3
= self
.mouse_path
[0][0] + self
.xpos
, self
.mouse_path
[1][1] + self
.ypos
1353 vec
= region_2d_to_vector_3d(region
, rv3d
, v0
)
1354 loc0
= region_2d_to_location_3d(region
, rv3d
, v0
, vec
)
1356 vec
= region_2d_to_vector_3d(region
, rv3d
, v1
)
1357 loc1
= region_2d_to_location_3d(region
, rv3d
, v1
, vec
)
1359 vec
= region_2d_to_vector_3d(region
, rv3d
, v2
)
1360 loc2
= region_2d_to_location_3d(region
, rv3d
, v2
, vec
)
1362 vec
= region_2d_to_vector_3d(region
, rv3d
, v3
)
1363 loc3
= region_2d_to_location_3d(region
, rv3d
, v3
, vec
)
1365 p1
= loc0
+ PlaneNormalised
* FAR_LIMIT
1366 loc0
= isect_line_plane_v3(p0
, p1
, PlanePoint
, PlaneNormalised
)
1368 p1
= loc1
+ PlaneNormalised
* FAR_LIMIT
1369 loc1
= isect_line_plane_v3(p0
, p1
, PlanePoint
, PlaneNormalised
)
1371 p1
= loc2
+ PlaneNormalised
* FAR_LIMIT
1372 loc2
= isect_line_plane_v3(p0
, p1
, PlanePoint
, PlaneNormalised
)
1374 p1
= loc3
+ PlaneNormalised
* FAR_LIMIT
1375 loc3
= isect_line_plane_v3(p0
, p1
, PlanePoint
, PlaneNormalised
)
1377 t_v0
= t_bm
.verts
.new(loc0
)
1378 t_v1
= t_bm
.verts
.new(loc2
)
1379 t_v2
= t_bm
.verts
.new(loc1
)
1380 t_v3
= t_bm
.verts
.new(loc3
)
1382 # Update vertices index
1383 t_bm
.verts
.index_update()
1385 t_face
= t_bm
.faces
.new([t_v0
, t_v1
, t_v2
, t_v3
])
1391 def CreateCutLine(self
, context
):
1394 me
= bpy
.data
.meshes
.new('CMT_Line')
1396 ob
= bpy
.data
.objects
.new('CMT_Line', me
)
1397 self
.CurrentObj
= ob
1399 region
= context
.region
1400 rv3d
= context
.region_data
1401 coord
= self
.mouse_path
[0][0], self
.mouse_path
[0][1]
1402 depthLocation
= region_2d_to_vector_3d(region
, rv3d
, coord
)
1403 self
.ViewVector
= depthLocation
1405 PlanePoint
= context
.scene
.cursor_location
if self
.snapCursor
else Vector((0.0, 0.0, 0.0))
1406 PlaneNormal
= depthLocation
1407 PlaneNormalised
= PlaneNormal
.normalized()
1409 context
.scene
.objects
.link(ob
)
1419 if (len(self
.mouse_path
) == 2) or ((len(self
.mouse_path
) <= 3) and
1420 (self
.mouse_path
[1] == self
.mouse_path
[2])):
1421 PlanePoint
= Vector((0.0, 0.0, 0.0))
1422 PlaneNormal
= depthLocation
1423 PlaneNormalised
= PlaneNormal
.normalized()
1425 self
.ForceRebool
= True
1429 for x
, y
in self
.mouse_path
:
1431 v0
= x
+ self
.xpos
, y
+ self
.ypos
1432 vec
= region_2d_to_vector_3d(region
, rv3d
, v0
)
1433 loc0
= region_2d_to_location_3d(region
, rv3d
, v0
, vec
)
1436 p1
= loc0
+ PlaneNormalised
* FAR_LIMIT
1437 loc0
= isect_line_plane_v3(p0
, p1
, PlanePoint
, PlaneNormalised
)
1442 t_v0
= t_bm
.verts
.new(loc0
)
1444 t_bm
.verts
.index_update()
1446 t_v1
= t_bm
.verts
.new(loc0
)
1447 t_edges
= t_bm
.edges
.new([t_v0
, t_v1
])
1451 for x
, y
in self
.mouse_path
:
1452 v0
= x
+ self
.xpos
, y
+ self
.ypos
1453 vec
= region_2d_to_vector_3d(region
, rv3d
, v0
)
1454 loc0
= region_2d_to_location_3d(region
, rv3d
, v0
, vec
)
1457 p1
= loc0
+ PlaneNormalised
* FAR_LIMIT
1458 loc0
= isect_line_plane_v3(p0
, p1
, PlanePoint
, PlaneNormalised
)
1462 t_v0
= t_bm
.verts
.new(loc0
)
1464 t_bm
.verts
.index_update()
1465 FacesList
.append(t_v0
)
1467 t_v1
= t_bm
.verts
.new(loc0
)
1468 t_edges
= t_bm
.edges
.new([t_v0
, t_v1
])
1469 FacesList
.append(t_v1
)
1474 if self
.Closed
and (bLine
is False):
1475 t_v1
= t_bm
.verts
.new(LocInit
)
1476 t_edges
= t_bm
.edges
.new([t_v0
, t_v1
])
1477 FacesList
.append(t_v1
)
1478 t_face
= t_bm
.faces
.new(FacesList
)
1481 t_v1
= t_bm
.verts
.new(LocInit
)
1482 t_edges
= t_bm
.edges
.new([t_v0
, t_v1
])
1483 FacesList
.append(t_v1
)
1484 t_face
= t_bm
.faces
.new(FacesList
)
1490 def CreateCutCircle(self
, context
):
1493 me
= bpy
.data
.meshes
.new('CMT_Circle')
1495 ob
= bpy
.data
.objects
.new('CMT_Circle', me
)
1496 self
.CurrentObj
= ob
1498 region
= context
.region
1499 rv3d
= context
.region_data
1500 coord
= self
.mouse_path
[0][0], self
.mouse_path
[0][1]
1501 depthLocation
= region_2d_to_vector_3d(region
, rv3d
, coord
)
1502 self
.ViewVector
= depthLocation
1504 PlanePoint
= context
.scene
.cursor_location
if self
.snapCursor
else Vector((0.0, 0.0, 0.0))
1505 PlaneNormal
= depthLocation
1506 PlaneNormalised
= PlaneNormal
.normalized()
1508 context
.scene
.objects
.link(ob
)
1513 x0
= self
.mouse_path
[0][0]
1514 y0
= self
.mouse_path
[0][1]
1516 v0
= Vector((self
.mouse_path
[0][0], self
.mouse_path
[0][1], 0))
1517 v1
= Vector((self
.mouse_path
[1][0], self
.mouse_path
[1][1], 0))
1519 radius
= self
.mouse_path
[1][0] - self
.mouse_path
[0][0]
1520 DEG2RAD
= math
.pi
/ (180.0 / self
.stepAngle
[self
.step
])
1522 self
.stepR
= (self
.mouse_path
[1][1] - self
.mouse_path
[0][1]) / 25
1523 shift
= (math
.pi
/ (360.0 / self
.stepAngle
[self
.step
])) * (self
.stepR
)
1525 shift
= (self
.mouse_path
[1][1] - self
.mouse_path
[0][1]) / 50
1527 # Convert point in 3D Space
1529 for i
in range(0, int(360.0 / self
.stepAngle
[self
.step
])):
1530 degInRad
= i
* DEG2RAD
1531 v0
= x0
+ self
.xpos
+ math
.cos(degInRad
+ shift
) * radius
, \
1532 y0
+ self
.ypos
+ math
.sin(degInRad
+ shift
) * radius
1533 vec
= region_2d_to_vector_3d(region
, rv3d
, v0
)
1534 loc0
= region_2d_to_location_3d(region
, rv3d
, v0
, vec
)
1537 p1
= loc0
+ PlaneNormalised
* FAR_LIMIT
1538 loc0
= isect_line_plane_v3(p0
, p1
, PlanePoint
, PlaneNormalised
)
1540 t_v0
= t_bm
.verts
.new(loc0
)
1542 FacesList
.append(t_v0
)
1544 t_bm
.verts
.index_update()
1545 t_face
= t_bm
.faces
.new(FacesList
)
1550 # Object dimensions (SCULPT Tools tips)
1551 def objDiagonal(obj
):
1552 return ((obj
.dimensions
[0]**2) + (obj
.dimensions
[1]**2) + (obj
.dimensions
[2]**2))**0.5
1556 def update_bevel(context
):
1557 selection
= context
.selected_objects
.copy()
1558 active
= context
.active_object
1560 if len(selection
) > 0:
1561 for obj
in selection
:
1562 bpy
.ops
.object.select_all(action
='DESELECT')
1564 context
.scene
.objects
.active
= obj
1567 if obj
.data
.name
.startswith("S_") or obj
.data
.name
.startswith("S "):
1568 bpy
.ops
.object.mode_set(mode
='EDIT')
1569 bpy
.ops
.mesh
.region_to_loop()
1570 bpy
.ops
.transform
.edge_bevelweight(value
=1)
1571 bpy
.ops
.object.mode_set(mode
='OBJECT')
1574 for mod
in obj
.modifiers
:
1575 if mod
.type == 'BEVEL':
1578 context
.scene
.objects
.active
= bpy
.data
.objects
[obj
.name
]
1581 bpy
.ops
.object.mode_set(mode
='EDIT')
1584 bpy
.ops
.mesh
.select_mode(use_extend
=False, use_expand
=False, type='EDGE')
1587 bpy
.ops
.mesh
.select_all(action
='SELECT')
1588 bpy
.ops
.mesh
.mark_sharp(clear
=True)
1589 bpy
.ops
.transform
.edge_crease(value
=-1)
1591 bpy
.ops
.transform
.edge_bevelweight(value
=-1)
1592 bpy
.ops
.mesh
.select_all(action
='DESELECT')
1593 bpy
.ops
.mesh
.edges_select_sharp(sharpness
=0.523599)
1594 bpy
.ops
.mesh
.mark_sharp()
1595 bpy
.ops
.transform
.edge_crease(value
=1)
1596 bpy
.ops
.mesh
.select_all(action
='DESELECT')
1597 bpy
.ops
.mesh
.edges_select_sharp(sharpness
=0.523599)
1598 bpy
.ops
.transform
.edge_bevelweight(value
=1)
1599 bpy
.ops
.mesh
.select_all(action
='DESELECT')
1601 bpy
.ops
.object.mode_set(mode
="OBJECT")
1603 active
.data
.use_customdata_edge_bevel
= True
1605 for i
in range(len(active
.data
.edges
)):
1606 if active
.data
.edges
[i
].select
is True:
1607 active
.data
.edges
[i
].bevel_weight
= 1.0
1608 active
.data
.edges
[i
].use_edge_sharp
= True
1611 for m
in active
.modifiers
:
1612 if m
.name
== 'Bevel':
1615 if Already
is False:
1616 bpy
.ops
.object.modifier_add(type='BEVEL')
1617 mod
= context
.object.modifiers
[-1]
1618 mod
.limit_method
= 'WEIGHT'
1620 mod
.profile
= 0.699099
1621 mod
.use_clight_overlap
= False
1623 mod
.loop_slide
= False
1625 bpy
.ops
.object.shade_smooth()
1627 context
.object.data
.use_auto_smooth
= True
1628 context
.object.data
.auto_smooth_angle
= 1.0472
1630 bpy
.ops
.object.select_all(action
='DESELECT')
1632 for obj
in selection
:
1634 context
.scene
.objects
.active
= active
1638 def CreateBevel(context
, CurrentObject
):
1639 # Save active object
1640 SavActive
= context
.active_object
1641 # Active "CurrentObject"
1642 context
.scene
.objects
.active
= CurrentObject
1644 bpy
.ops
.object.mode_set(mode
='EDIT')
1647 bpy
.ops
.mesh
.select_mode(use_extend
=False, use_expand
=False, type='EDGE')
1650 bpy
.ops
.mesh
.select_all(action
='SELECT')
1651 bpy
.ops
.mesh
.mark_sharp(clear
=True)
1652 bpy
.ops
.transform
.edge_crease(value
=-1)
1654 bpy
.ops
.transform
.edge_bevelweight(value
=-1)
1655 bpy
.ops
.mesh
.select_all(action
='DESELECT')
1656 bpy
.ops
.mesh
.edges_select_sharp(sharpness
=0.523599)
1657 bpy
.ops
.mesh
.mark_sharp()
1658 bpy
.ops
.transform
.edge_crease(value
=1)
1659 bpy
.ops
.mesh
.select_all(action
='DESELECT')
1660 bpy
.ops
.mesh
.edges_select_sharp(sharpness
=0.523599)
1661 bpy
.ops
.transform
.edge_bevelweight(value
=1)
1662 bpy
.ops
.mesh
.select_all(action
='DESELECT')
1664 bpy
.ops
.object.mode_set(mode
="OBJECT")
1666 bpy
.ops
.object.mode_set(mode
='OBJECT')
1669 for m
in CurrentObject
.modifiers
:
1670 if m
.name
== 'Bevel':
1673 if Already
is False:
1674 bpy
.ops
.object.modifier_add(type='BEVEL')
1675 mod
= context
.object.modifiers
[-1]
1676 mod
.limit_method
= 'WEIGHT'
1678 mod
.profile
= 0.699099
1679 mod
.use_clight_overlap
= False
1681 mod
.loop_slide
= False
1683 bpy
.ops
.object.shade_smooth()
1685 context
.object.data
.use_auto_smooth
= True
1686 context
.object.data
.auto_smooth_angle
= 1.0471975
1688 # Restore the active object
1689 context
.scene
.objects
.active
= SavActive
1692 # Picking (template)
1693 def Picking(context
, event
):
1694 # get the context arguments
1695 scene
= context
.scene
1696 region
= context
.region
1697 rv3d
= context
.region_data
1698 coord
= event
.mouse_region_x
, event
.mouse_region_y
1700 # get the ray from the viewport and mouse
1701 view_vector
= view3d_utils
.region_2d_to_vector_3d(region
, rv3d
, coord
)
1702 ray_origin
= view3d_utils
.region_2d_to_origin_3d(region
, rv3d
, coord
)
1703 ray_target
= ray_origin
+ view_vector
1705 def visible_objects_and_duplis():
1706 for obj
in context
.visible_objects
:
1707 if obj
.type == 'MESH':
1708 yield (obj
, obj
.matrix_world
.copy())
1710 if obj
.instance_type
!= 'NONE':
1711 obj
.dupli_list_create(scene
)
1712 for dob
in obj
.dupli_list
:
1713 obj_dupli
= dob
.object
1714 if obj_dupli
.type == 'MESH':
1715 yield (obj_dupli
, dob
.matrix
.copy())
1717 obj
.dupli_list_clear()
1719 def obj_ray_cast(obj
, matrix
):
1720 # get the ray relative to the object
1721 matrix_inv
= matrix
.inverted()
1722 ray_origin_obj
= matrix_inv
* ray_origin
1723 ray_target_obj
= matrix_inv
* ray_target
1724 ray_direction_obj
= ray_target_obj
- ray_origin_obj
1726 success
, location
, normal
, face_index
= obj
.ray_cast(ray_origin_obj
, ray_direction_obj
)
1728 return location
, normal
, face_index
1729 return None, None, None
1731 # cast rays and find the closest object
1732 best_length_squared
= -1.0
1735 # cast rays and find the closest object
1736 for obj
, matrix
in visible_objects_and_duplis():
1737 if obj
.type == 'MESH':
1738 hit
, normal
, face_index
= obj_ray_cast(obj
, matrix
)
1740 hit_world
= matrix
* hit
1741 length_squared
= (hit_world
- ray_origin
).length_squared
1742 if best_obj
is None or length_squared
< best_length_squared
:
1743 scene
.cursor_location
= hit_world
1744 best_length_squared
= length_squared
1747 if best_obj
is None:
1748 depthLocation
= region_2d_to_vector_3d(region
, rv3d
, coord
)
1749 loc
= region_2d_to_location_3d(region
, rv3d
, coord
, depthLocation
)
1750 scene
.cursor_location
= loc
1753 def CreatePrimitive(self
, _AngleStep
, _radius
):
1755 self
.NbPointsInPrimitive
= 0
1756 while(Angle
< 360.0):
1757 self
.CircleListRaw
.append(math
.cos(math
.radians(Angle
)) * _radius
)
1758 self
.CircleListRaw
.append(math
.sin(math
.radians(Angle
)) * _radius
)
1759 self
.CircleListRaw
.append(0.0)
1761 self
.NbPointsInPrimitive
+= 1
1762 self
.CircleListRaw
.append(math
.cos(math
.radians(0.0)) * _radius
)
1763 self
.CircleListRaw
.append(math
.sin(math
.radians(0.0)) * _radius
)
1764 self
.CircleListRaw
.append(0.0)
1765 self
.NbPointsInPrimitive
+= 1
1768 def MoveCursor(qRot
, location
, self
):
1769 if qRot
is not None:
1773 for i
in range(int(len(self
.CircleListRaw
) / 3)):
1774 vc
.x
= self
.CircleListRaw
[idx
* 3] * self
.CRadius
1775 vc
.y
= self
.CircleListRaw
[idx
* 3 + 1] * self
.CRadius
1776 vc
.z
= self
.CircleListRaw
[idx
* 3 + 2] * self
.CRadius
1778 self
.CLR_C
.append(vc
.x
)
1779 self
.CLR_C
.append(vc
.y
)
1780 self
.CLR_C
.append(vc
.z
)
1784 def RBenVe(Object
, Dir
):
1785 ObjectV
= Object
.normalized()
1786 DirV
= Dir
.normalized()
1787 cosTheta
= ObjectV
.dot(DirV
)
1788 rotationAxis
= Vector((0.0, 0.0, 0.0))
1789 if (cosTheta
< -1 + 0.001):
1790 v
= Vector((0.0, 1.0, 0.0))
1791 rotationAxis
= ObjectV
.cross(v
)
1792 rotationAxis
= rotationAxis
.normalized()
1795 q
.x
= rotationAxis
.x
1796 q
.y
= rotationAxis
.y
1797 q
.z
= rotationAxis
.z
1799 rotationAxis
= ObjectV
.cross(DirV
)
1800 s
= math
.sqrt((1.0 + cosTheta
) * 2.0)
1804 q
.x
= rotationAxis
.x
* invs
1805 q
.y
= rotationAxis
.y
* invs
1806 q
.z
= rotationAxis
.z
* invs
1810 def Pick(context
, event
, self
, ray_max
=10000.0):
1811 region
= context
.region
1812 rv3d
= context
.region_data
1813 coord
= event
.mouse_region_x
, event
.mouse_region_y
1814 view_vector
= view3d_utils
.region_2d_to_vector_3d(region
, rv3d
, coord
)
1815 ray_origin
= view3d_utils
.region_2d_to_origin_3d(region
, rv3d
, coord
)
1816 ray_target
= ray_origin
+ (view_vector
* ray_max
)
1818 def obj_ray_cast(obj
, matrix
):
1819 matrix_inv
= matrix
.inverted()
1820 ray_origin_obj
= matrix_inv
* ray_origin
1821 ray_target_obj
= matrix_inv
* ray_target
1822 success
, hit
, normal
, face_index
= obj
.ray_cast(ray_origin_obj
, ray_target_obj
)
1824 return hit
, normal
, face_index
1825 return None, None, None
1827 best_length_squared
= ray_max
* ray_max
1829 for obj
in self
.CList
:
1830 matrix
= obj
.matrix_world
1831 hit
, normal
, face_index
= obj_ray_cast(obj
, matrix
)
1832 rotation
= obj
.rotation_euler
.to_quaternion()
1834 hit_world
= matrix
* hit
1835 length_squared
= (hit_world
- ray_origin
).length_squared
1836 if length_squared
< best_length_squared
:
1837 best_length_squared
= length_squared
1843 if best_obj
is not None:
1844 return hits
, ns
, fs
, rotation
1846 return None, None, None
1849 def SelectObject(self
, copyobj
):
1850 copyobj
.select
= True
1852 for child
in copyobj
.children
:
1853 SelectObject(self
, child
)
1855 if copyobj
.parent
is None:
1856 bpy
.context
.scene
.objects
.active
= copyobj
1860 def printUndo(self
):
1861 for l
in self
.UList
:
1865 def UndoAdd(self
, type, OpsObj
):
1868 if type != "DUPLICATE":
1870 # Create the 'backup' mesh
1872 bm
.from_mesh(ob
.data
)
1874 self
.UndoOps
.append((OpsObj
, type, bm
))
1876 self
.UndoOps
.append((OpsObj
, type, None))
1879 def UndoListUpdate(self
):
1880 self
.UList
.append((self
.UndoOps
.copy()))
1881 self
.UList_Index
+= 1
1882 self
.UndoOps
.clear()
1886 if self
.UList_Index
< 0:
1889 for o
in self
.UList
[self
.UList_Index
]:
1892 bm
.to_mesh(o
[0].data
)
1894 SelectObjList
= bpy
.context
.selected_objects
.copy()
1895 Active_Obj
= bpy
.context
.active_object
1896 bpy
.ops
.object.select_all(action
='TOGGLE')
1898 for o
in self
.UList
[self
.UList_Index
]:
1899 if o
[1] == "REBOOL":
1903 if o
[1] == "DUPLICATE":
1907 bpy
.ops
.object.delete(use_global
=False)
1909 for so
in SelectObjList
:
1910 bpy
.data
.objects
[so
.name
].select
= True
1911 bpy
.context
.scene
.objects
.active
= Active_Obj
1913 self
.UList_Index
-= 1
1914 self
.UList
[self
.UList_Index
+ 1:] = []
1917 def duplicateObject(self
):
1918 if self
.Instantiate
:
1919 bpy
.ops
.object.duplicate_move_linked(
1920 OBJECT_OT_duplicate
={
1922 "mode": 'TRANSLATION',
1924 TRANSFORM_OT_translate
={
1929 bpy
.ops
.object.duplicate_move(
1930 OBJECT_OT_duplicate
={
1932 "mode": 'TRANSLATION',
1934 TRANSFORM_OT_translate
={
1939 ob_new
= bpy
.context
.active_object
1941 ob_new
.location
= self
.CurLoc
1944 v
.z
= self
.BrushDepthOffset
1945 ob_new
.location
+= self
.qRot
* v
1948 ob_new
.scale
= self
.ObjectBrush
.scale
1949 if self
.ProfileMode
:
1950 ob_new
.scale
= self
.ProfileBrush
.scale
1954 e
.z
= self
.aRotZ
/ 25.0
1956 # If duplicate with a grid, no random rotation (each mesh in the grid is already rotated randomly)
1957 if (self
.alt
is True) and ((self
.nbcol
+ self
.nbrow
) < 3):
1958 if self
.RandomRotation
:
1959 e
.z
+= random
.random()
1961 qe
= e
.to_quaternion()
1962 qRot
= self
.qRot
* qe
1963 ob_new
.rotation_mode
= 'QUATERNION'
1964 ob_new
.rotation_quaternion
= qRot
1965 ob_new
.rotation_mode
= 'XYZ'
1967 if (ob_new
.display_type
== "WIRE") and (self
.BrushSolidify
is False):
1970 if self
.BrushSolidify
:
1971 ob_new
.display_type
= "SOLID"
1972 ob_new
.show_in_front
= False
1974 for o
in bpy
.context
.selected_objects
:
1975 UndoAdd(self
, "DUPLICATE", o
)
1977 if len(bpy
.context
.selected_objects
) > 0:
1978 bpy
.ops
.object.select_all(action
='TOGGLE')
1979 for o
in self
.SavSel
:
1982 bpy
.context
.scene
.objects
.active
= self
.OpsObj
1985 def update_grid(self
, context
):
1987 Thanks to batFINGER for his help :
1988 source : http://blender.stackexchange.com/questions/55864/multiple-meshes-not-welded-with-pydata
2004 # Get the data from the profils or the object
2005 if self
.ProfileMode
:
2006 brush
= bpy
.data
.objects
.new(
2007 self
.Profils
[self
.nProfil
][0],
2008 bpy
.data
.meshes
[self
.Profils
[self
.nProfil
][0]]
2010 obj
= bpy
.data
.objects
["CT_Profil"]
2011 obfaces
= brush
.data
.polygons
2012 obverts
= brush
.data
.vertices
2013 lenverts
= len(obverts
)
2015 brush
= bpy
.data
.objects
["CarverBrushCopy"]
2016 obj
= context
.selected_objects
[0]
2017 obverts
= brush
.data
.vertices
2018 obfaces
= brush
.data
.polygons
2019 lenverts
= len(brush
.data
.vertices
)
2021 # Gap between each row / column
2025 # Width of each row / column
2026 widthx
= brush
.dimensions
.x
* self
.scale_x
2027 widthy
= brush
.dimensions
.y
* self
.scale_y
2029 # Compute the corners so the new object will be always at the center
2030 left
= -((self
.nbcol
- 1) * (widthx
+ gapx
)) / 2
2031 start
= -((self
.nbrow
- 1) * (widthy
+ gapy
)) / 2
2033 for i
in range(self
.nbrow
* self
.nbcol
):
2034 row
= i
% self
.nbrow
2035 col
= i
// self
.nbrow
2036 startx
= left
+ ((widthx
+ gapx
) * col
)
2037 starty
= start
+ ((widthy
+ gapy
) * row
)
2039 # Add random rotation
2040 if (self
.RandomRotation
) and not (self
.GridScaleX
or self
.GridScaleY
):
2041 rotmat
= Matrix
.Rotation(math
.radians(360 * random
.random()), 4, 'Z')
2043 v
.co
= v
.co
* rotmat
2045 verts
.extend([((v
.co
.x
- startx
, v
.co
.y
- starty
, v
.co
.z
)) for v
in obverts
])
2046 faces
.extend([[v
+ numface
* lenverts
for v
in p
.vertices
] for p
in obfaces
])
2051 mymesh
= bpy
.data
.meshes
.new("CT_Profil")
2052 # Generate mesh data
2053 mymesh
.from_pydata(verts
, edges
, faces
)
2054 # Calculate the edges
2055 mymesh
.update(calc_edges
=True)
2058 # Make the object active to remove doubles
2059 context
.scene
.objects
.active
= obj
2062 def boolean_operation(bool_type
="DIFFERENCE"):
2063 ActiveObj
= bpy
.context
.active_object
2064 sel_index
= 0 if bpy
.context
.selected_objects
[0] != bpy
.context
.active_object
else 1
2066 bpy
.ops
.object.modifier_apply(apply_as
='DATA', modifier
="CT_SOLIDIFY")
2067 BoolMod
= ActiveObj
.modifiers
.new(
2068 "CT_" + bpy
.context
.selected_objects
[sel_index
].name
,
2071 BoolMod
.object = bpy
.context
.selected_objects
[sel_index
]
2072 BoolMod
.operation
= bool_type
2073 bpy
.context
.selected_objects
[sel_index
].display_type
= 'WIRE'
2076 def Rebool(context
, self
):
2077 LastObj
= context
.active_object
2079 Brush
= context
.selected_objects
[0]
2080 Brush
.display_type
= "WIRE"
2081 obj
= context
.selected_objects
[1]
2083 bpy
.ops
.object.select_all(action
='TOGGLE')
2085 context
.scene
.objects
.active
= obj
2086 obj
.display_type
= "SOLID"
2088 bpy
.ops
.object.duplicate_move(
2089 OBJECT_OT_duplicate
={
2091 "mode": 'TRANSLATION',
2093 TRANSFORM_OT_translate
={
2095 "constraint_axis": (False, False, False),
2096 "constraint_orientation": 'GLOBAL',
2098 "proportional": 'DISABLED',
2099 "proportional_edit_falloff": 'SMOOTH',
2100 "proportional_size": 1,
2102 "snap_target": 'CLOSEST',
2103 "snap_point": (0, 0, 0),
2104 "snap_align": False,
2105 "snap_normal": (0, 0, 0),
2106 "gpencil_strokes": False,
2107 "texture_space": False,
2108 "remove_on_cancel": False,
2109 "release_confirm": False,
2112 LastObjectCreated
= context
.active_object
2114 m
= LastObjectCreated
.modifiers
.new("CT_INTERSECT", "BOOLEAN")
2115 m
.operation
= "INTERSECT"
2118 m
= obj
.modifiers
.new("CT_DIFFERENCE", "BOOLEAN")
2119 m
.operation
= "DIFFERENCE"
2122 for mb
in LastObj
.modifiers
:
2123 if mb
.type == 'BEVEL':
2124 mb
.show_viewport
= False
2126 if self
.ObjectBrush
or self
.ProfileBrush
:
2127 LastObjectCreated
.show_in_front
= False
2129 bpy
.ops
.object.modifier_apply(apply_as
='DATA', modifier
="CT_SOLIDIFY")
2131 exc_type
, exc_value
, exc_traceback
= sys
.exc_info()
2132 self
.report({'ERROR'}, str(exc_value
))
2134 if self
.DontApply
is False:
2136 bpy
.ops
.object.modifier_apply(apply_as
='DATA', modifier
="CT_INTERSECT")
2138 exc_type
, exc_value
, exc_traceback
= sys
.exc_info()
2139 self
.report({'ERROR'}, str(exc_value
))
2141 bpy
.ops
.object.select_all(action
='TOGGLE')
2143 for mb
in LastObj
.modifiers
:
2144 if mb
.type == 'BEVEL':
2145 mb
.show_viewport
= True
2147 context
.scene
.objects
.active
= obj
2149 if self
.DontApply
is False:
2151 bpy
.ops
.object.modifier_apply(apply_as
='DATA', modifier
="CT_DIFFERENCE")
2153 exc_type
, exc_value
, exc_traceback
= sys
.exc_info()
2154 self
.report({'ERROR'}, str(exc_value
))
2156 bpy
.ops
.object.select_all(action
='TOGGLE')
2158 LastObjectCreated
.select
= True
2161 def createMeshFromData(self
):
2162 if self
.Profils
[self
.nProfil
][0] not in bpy
.data
.meshes
:
2163 # Create mesh and object
2164 me
= bpy
.data
.meshes
.new(self
.Profils
[self
.nProfil
][0])
2165 # Create mesh from given verts, faces.
2166 me
.from_pydata(self
.Profils
[self
.nProfil
][2], [], self
.Profils
[self
.nProfil
][3])
2167 # Update mesh with new data
2170 if "CT_Profil" not in bpy
.data
.objects
:
2171 ob
= bpy
.data
.objects
.new("CT_Profil", bpy
.data
.meshes
[self
.Profils
[self
.nProfil
][0]])
2172 ob
.location
= Vector((0.0, 0.0, 0.0))
2174 # Link object to scene and make active
2175 scn
= bpy
.context
.scene
2176 scn
.objects
.link(ob
)
2177 scn
.objects
.active
= ob
2179 ob
.location
= Vector((10000.0, 0.0, 0.0))
2180 ob
.display_type
= "WIRE"
2182 self
.SolidifyPossible
= True
2184 bpy
.data
.objects
["CT_Profil"].data
= bpy
.data
.meshes
[self
.Profils
[self
.nProfil
][0]]
2187 def Selection_Save_Restore(self
):
2188 if "CT_Profil" in bpy
.data
.objects
:
2189 Selection_Save(self
)
2190 bpy
.ops
.object.select_all(action
='DESELECT')
2191 bpy
.data
.objects
["CT_Profil"].select
= True
2192 bpy
.context
.scene
.objects
.active
= bpy
.data
.objects
["CT_Profil"]
2193 if bpy
.data
.objects
["CT_Profil"] in self
.SavSel
:
2194 self
.SavSel
.remove(bpy
.data
.objects
["CT_Profil"])
2195 bpy
.ops
.object.delete(use_global
=False)
2196 Selection_Restore(self
)
2199 def Selection_Save(self
):
2200 obj_name
= getattr(bpy
.context
.active_object
, "name", None)
2201 self
.SavSel
= bpy
.context
.selected_objects
.copy()
2202 self
.Sav_ac
= obj_name
2205 def Selection_Restore(self
):
2206 for o
in self
.SavSel
:
2209 bpy
.context
.scene
.objects
.active
= bpy
.data
.objects
.get(self
.Sav_ac
, None)
2213 class Carver(bpy
.types
.Operator
):
2214 bl_idname
= "object.carver"
2216 bl_description
= "Cut or create Meshes in Object mode"
2217 bl_options
= {'REGISTER', 'UNDO'}
2220 def poll(cls
, context
):
2222 if len(context
.selected_objects
) > 0:
2223 ob
= context
.selected_objects
[0]
2224 # Test if selected object or none (for create mode)
2226 (ob
and ob
.type == 'MESH' and context
.mode
== 'OBJECT') or
2227 (context
.mode
== 'OBJECT' and ob
is None) or
2228 (context
.mode
== 'EDIT_MESH'))
2230 def modal(self
, context
, event
):
2232 region_types
= {'WINDOW', 'UI'}
2233 win
= context
.window
2235 for area
in win
.screen
.areas
:
2236 if area
.type in ('VIEW_3D'):
2237 for region
in area
.regions
:
2238 if not region_types
or region
.type in region_types
:
2242 'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE',
2243 'NUMPAD_1', 'NUMPAD_2', 'NUMPAD_3', 'NUMPAD_4', 'NUMPAD_6',
2244 'NUMPAD_7', 'NUMPAD_8', 'NUMPAD_9', 'NUMPAD_5'}:
2245 return {'PASS_THROUGH'}
2248 self
.shift
= True if event
.shift
else False
2251 self
.ctrl
= True if event
.ctrl
else False
2256 if self
.InitPosition
is False:
2257 # Initialise position variable for start position
2260 self
.last_mouse_region_x
= event
.mouse_region_x
2261 self
.last_mouse_region_y
= event
.mouse_region_y
2262 self
.InitPosition
= True
2265 if self
.InitPosition
and self
.alt
is False:
2266 # Update coordinates
2267 for i
in range(0, len(self
.mouse_path
)):
2268 l
= list(self
.mouse_path
[i
])
2271 self
.mouse_path
[i
] = tuple(l
)
2273 self
.xpos
= self
.ypos
= 0
2274 self
.InitPosition
= False
2276 # Mode change (cut type)
2277 if event
.type == 'SPACE' and event
.value
== 'PRESS':
2278 if self
.ObjectMode
or self
.ProfileMode
:
2279 # If grid, remove double with intersect meshes
2280 if ((self
.nbcol
+ self
.nbrow
) > 3):
2281 # Go in edit mode mode
2282 bpy
.ops
.object.mode_set(mode
='EDIT')
2283 # Remove duplicate vertices
2284 bpy
.ops
.mesh
.remove_doubles()
2285 # Return in object mode
2286 bpy
.ops
.object.mode_set(mode
='OBJECT')
2289 # Save selected objects
2290 self
.SavSel
= context
.selected_objects
.copy()
2291 if len(context
.selected_objects
) > 0:
2292 bpy
.ops
.object.select_all(action
='TOGGLE')
2295 SelectObject(self
, self
.ObjectBrush
)
2297 SelectObject(self
, self
.ProfileBrush
)
2298 duplicateObject(self
)
2302 # Save selected objects
2304 if len(self
.ObjectBrush
.children
) > 0:
2305 self
.SavSel
= context
.selected_objects
.copy()
2306 if len(context
.selected_objects
) > 0:
2307 bpy
.ops
.object.select_all(action
='TOGGLE')
2310 SelectObject(self
, self
.ObjectBrush
)
2312 SelectObject(self
, self
.ProfileBrush
)
2313 duplicateObject(self
)
2315 UndoListUpdate(self
)
2317 # Save cursor position
2318 self
.SavMousePos
= self
.CurLoc
2320 if self
.bDone
is False:
2323 if self
.CutMode
> 2:
2326 if self
.CutMode
== LINE
:
2328 CreateCutLine(self
, context
)
2331 self
.CreateGeometry()
2332 bpy
.types
.SpaceView3D
.draw_handler_remove(self
._handle
, 'WINDOW')
2334 context
.scene
.mesh_carver
.DepthCursor
= self
.snapCursor
2335 # Object Instantiate
2336 context
.scene
.mesh_carver
.OInstanciate
= self
.Instantiate
2338 context
.scene
.mesh_carver
.ORandom
= self
.RandomRotation
2343 UndoListUpdate(self
)
2346 if event
.type == context
.scene
.Key_Create
and event
.value
== 'PRESS':
2347 if self
.ExclusiveCreateMode
is False:
2348 self
.CreateMode
= not self
.CreateMode
2351 if event
.type == context
.scene
.Key_Update
and event
.value
== 'PRESS':
2352 self
.Auto_BevelUpdate
= not self
.Auto_BevelUpdate
2354 # Boolean operation type
2355 if event
.type == context
.scene
.Key_Bool
and event
.value
== 'PRESS':
2356 if (self
.ProfileMode
is True) or (self
.ObjectMode
is True):
2357 if self
.BoolOps
== DIFFERENCE
:
2358 self
.BoolOps
= UNION
2360 self
.BoolOps
= DIFFERENCE
2363 if event
.type == context
.scene
.Key_Brush
and event
.value
== 'PRESS':
2364 self
.DontApply
= False
2365 if (self
.ProfileMode
is False) and (self
.ObjectMode
is False):
2366 self
.ProfileMode
= True
2368 self
.ProfileMode
= False
2369 if self
.ObjectBrush
is not None:
2370 if self
.ObjectMode
is False:
2371 self
.ObjectMode
= True
2372 self
.BrushSolidify
= False
2373 self
.CList
= self
.OB_List
2375 Selection_Save_Restore(self
)
2376 context
.scene
.mesh_carver
.nProfile
= self
.nProfil
2378 self
.ObjectMode
= False
2380 self
.BrushSolidify
= False
2381 Selection_Save_Restore(self
)
2383 if self
.ProfileMode
:
2384 createMeshFromData(self
)
2385 self
.ProfileBrush
= bpy
.data
.objects
["CT_Profil"]
2386 Selection_Save(self
)
2387 self
.BrushSolidify
= True
2389 bpy
.ops
.object.select_all(action
='TOGGLE')
2390 self
.ProfileBrush
.select
= True
2391 context
.scene
.objects
.active
= self
.ProfileBrush
2393 self
.ProfileBrush
.show_in_front
= True
2395 bpy
.ops
.object.modifier_add(type='SOLIDIFY')
2396 context
.object.modifiers
["Solidify"].name
= "CT_SOLIDIFY"
2397 context
.object.modifiers
["CT_SOLIDIFY"].thickness
= 0.1
2399 Selection_Restore(self
)
2401 self
.CList
= self
.CurrentSelection
2403 if self
.ObjectBrush
is not None:
2404 if self
.ObjectMode
is False:
2405 if self
.ObjectBrush
is not None:
2406 self
.ObjectBrush
.location
= self
.InitBrushPosition
2407 self
.ObjectBrush
.scale
= self
.InitBrushScale
2408 self
.ObjectBrush
.rotation_quaternion
= self
.InitBrushQRotation
2409 self
.ObjectBrush
.rotation_euler
= self
.InitBrushERotation
2410 self
.ObjectBrush
.display_type
= self
.ObjectBrush_DT
2411 self
.ObjectBrush
.show_in_front
= self
.XRay
2413 # Remove solidify modifier
2414 Selection_Save(self
)
2415 self
.BrushSolidify
= False
2417 bpy
.ops
.object.select_all(action
='TOGGLE')
2418 self
.ObjectBrush
.select
= True
2419 context
.scene
.objects
.active
= self
.ObjectBrush
2421 bpy
.ops
.object.modifier_remove(modifier
="CT_SOLIDIFY")
2423 Selection_Restore(self
)
2425 if self
.Solidify_Active_Start
:
2426 Selection_Save(self
)
2427 self
.BrushSolidify
= True
2428 self
.SolidifyPossible
= True
2429 bpy
.ops
.object.select_all(action
='TOGGLE')
2430 self
.ObjectBrush
.select
= True
2431 context
.scene
.objects
.active
= self
.ObjectBrush
2433 self
.ObjectBrush
.show_in_front
= True
2434 bpy
.ops
.object.modifier_add(type='SOLIDIFY')
2435 context
.object.modifiers
["Solidify"].name
= "CT_SOLIDIFY"
2436 context
.object.modifiers
["CT_SOLIDIFY"].thickness
= 0.1
2437 Selection_Restore(self
)
2440 if event
.type == context
.scene
.Key_Help
and event
.value
== 'PRESS':
2441 self
.AskHelp
= not self
.AskHelp
2443 # Instantiate object
2444 if event
.type == context
.scene
.Key_Instant
and event
.value
== 'PRESS':
2445 self
.Instantiate
= not self
.Instantiate
2447 # Close polygonal shape
2448 if event
.type == context
.scene
.Key_Close
and event
.value
== 'PRESS':
2450 self
.Closed
= not self
.Closed
2452 if event
.type == context
.scene
.Key_Apply
and event
.value
== 'PRESS':
2453 self
.DontApply
= not self
.DontApply
2456 if event
.type == context
.scene
.Key_Scale
and event
.value
== 'PRESS':
2457 if self
.ObjectScale
is False:
2458 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2459 self
.ObjectScale
= True
2462 if event
.type == 'UP_ARROW' and event
.value
== 'PRESS':
2464 update_grid(self
, context
)
2467 elif event
.type == 'RIGHT_ARROW' and event
.value
== 'PRESS':
2469 update_grid(self
, context
)
2471 # Grid : Delete column
2472 elif event
.type == 'DOWN_ARROW' and event
.value
== 'PRESS':
2474 update_grid(self
, context
)
2477 elif event
.type == 'LEFT_ARROW' and event
.value
== 'PRESS':
2479 update_grid(self
, context
)
2481 # Grid : Scale gap between columns
2482 if event
.type == context
.scene
.Key_Gapy
and event
.value
== 'PRESS':
2483 if self
.GridScaleX
is False:
2484 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2485 self
.GridScaleX
= True
2487 # Grid : Scale gap between rows
2488 if event
.type == context
.scene
.Key_Gapx
and event
.value
== 'PRESS':
2489 if self
.GridScaleY
is False:
2490 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2491 self
.GridScaleY
= True
2493 # Cursor depth or solidify pattern
2494 if event
.type == context
.scene
.Key_Depth
and event
.value
== 'PRESS':
2495 if (self
.ObjectMode
is False) and (self
.ProfileMode
is False):
2496 self
.snapCursor
= not self
.snapCursor
2500 if (self
.ObjectMode
or self
.ProfileMode
) and (self
.SolidifyPossible
):
2504 z
= self
.ObjectBrush
.data
.vertices
[0].co
.z
2506 for v
in self
.ObjectBrush
.data
.vertices
:
2507 if abs(v
.co
.z
- z
) > ErrorMarge
:
2509 self
.CarveDepth
= True
2510 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2515 for mb
in self
.ObjectBrush
.modifiers
:
2516 if mb
.type == 'SOLIDIFY':
2517 AlreadySoldify
= True
2519 for mb
in self
.ProfileBrush
.modifiers
:
2520 if mb
.type == 'SOLIDIFY':
2521 AlreadySoldify
= True
2523 if AlreadySoldify
is False:
2524 Selection_Save(self
)
2525 self
.BrushSolidify
= True
2527 bpy
.ops
.object.select_all(action
='TOGGLE')
2529 self
.ObjectBrush
.select
= True
2530 context
.scene
.objects
.active
= self
.ObjectBrush
2532 self
.ObjectBrush
.show_in_front
= True
2534 self
.ProfileBrush
.select
= True
2535 context
.scene
.objects
.active
= self
.ProfileBrush
2537 self
.ProfileBrush
.show_in_front
= True
2539 bpy
.ops
.object.modifier_add(type='SOLIDIFY')
2540 context
.object.modifiers
["Solidify"].name
= "CT_SOLIDIFY"
2542 context
.object.modifiers
["CT_SOLIDIFY"].thickness
= 0.1
2544 Selection_Restore(self
)
2546 self
.WidthSolidify
= not self
.WidthSolidify
2547 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2549 if event
.type == context
.scene
.Key_BrushDepth
and event
.value
== 'PRESS':
2551 self
.CarveDepth
= False
2553 self
.BrushDepth
= True
2554 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2557 if event
.type == 'R' and event
.value
== 'PRESS':
2558 self
.RandomRotation
= not self
.RandomRotation
2561 if event
.type == 'Z' and event
.value
== 'PRESS':
2563 if (self
.CutMode
== LINE
) and (self
.bDone
):
2564 if len(self
.mouse_path
) > 1:
2565 self
.mouse_path
[len(self
.mouse_path
) - 1:] = []
2570 if event
.type == 'MOUSEMOVE':
2572 if self
.ObjectMode
or self
.ProfileMode
:
2576 if self
.WidthSolidify
:
2578 bpy
.data
.objects
[self
.ObjectBrush
.name
].modifiers
[
2579 "CT_SOLIDIFY"].thickness
+= (event
.mouse_region_x
- self
.am
[0]) / fac
2580 elif self
.ProfileMode
:
2581 bpy
.data
.objects
[self
.ProfileBrush
.name
].modifiers
[
2582 "CT_SOLIDIFY"].thickness
+= (event
.mouse_region_x
- self
.am
[0]) / fac
2583 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2584 elif self
.CarveDepth
:
2585 for v
in self
.ObjectBrush
.data
.vertices
:
2586 v
.co
.z
+= (event
.mouse_region_x
- self
.am
[0]) / fac
2587 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2588 elif self
.BrushDepth
:
2589 self
.BrushDepthOffset
+= (event
.mouse_region_x
- self
.am
[0]) / fac
2590 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2592 if (self
.GridScaleX
):
2593 self
.gapx
+= (event
.mouse_region_x
- self
.am
[0]) / 50
2594 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2595 update_grid(self
, context
)
2596 return {'RUNNING_MODAL'}
2598 elif (self
.GridScaleY
):
2599 self
.gapy
+= (event
.mouse_region_x
- self
.am
[0]) / 50
2600 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2601 update_grid(self
, context
)
2602 return {'RUNNING_MODAL'}
2604 elif self
.ObjectScale
:
2605 self
.ascale
= -(event
.mouse_region_x
- self
.am
[0])
2606 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2609 self
.ObjectBrush
.scale
.x
-= float(self
.ascale
) / 150.0
2610 if self
.ObjectBrush
.scale
.x
<= 0.0:
2611 self
.ObjectBrush
.scale
.x
= 0.0
2612 self
.ObjectBrush
.scale
.y
-= float(self
.ascale
) / 150.0
2613 if self
.ObjectBrush
.scale
.y
<= 0.0:
2614 self
.ObjectBrush
.scale
.y
= 0.0
2615 self
.ObjectBrush
.scale
.z
-= float(self
.ascale
) / 150.0
2616 if self
.ObjectBrush
.scale
.z
<= 0.0:
2617 self
.ObjectBrush
.scale
.z
= 0.0
2619 elif self
.ProfileMode
:
2620 if self
.ProfileBrush
is not None:
2621 self
.ProfileBrush
.scale
.x
-= float(self
.ascale
) / 150.0
2622 self
.ProfileBrush
.scale
.y
-= float(self
.ascale
) / 150.0
2623 self
.ProfileBrush
.scale
.z
-= float(self
.ascale
) / 150.0
2628 ((int((event
.mouse_region_x
- self
.xSavMouse
) / 10.0) * PI
/ 4.0) * 25.0)
2630 self
.aRotZ
-= event
.mouse_region_x
- self
.am
[0]
2633 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2635 vBack
= Pick(context
, event
, self
)
2636 if vBack
[0] is not None:
2637 self
.ShowCursor
= True
2638 NormalObject
= Vector((0.0, 0.0, 1.0))
2639 qR
= RBenVe(NormalObject
, vBack
[1])
2640 self
.qRot
= vBack
[3] * qR
2641 MoveCursor(qR
, vBack
[0], self
)
2642 self
.SavCurLoc
= vBack
[0]
2644 if self
.SavMousePos
is not None:
2645 xEcart
= abs(self
.SavMousePos
.x
- self
.SavCurLoc
.x
)
2646 yEcart
= abs(self
.SavMousePos
.y
- self
.SavCurLoc
.y
)
2647 zEcart
= abs(self
.SavMousePos
.z
- self
.SavCurLoc
.z
)
2648 if (xEcart
> yEcart
) and (xEcart
> zEcart
):
2649 self
.CurLoc
= Vector(
2650 (vBack
[0].x
, self
.SavMousePos
.y
, self
.SavMousePos
.z
))
2651 if (yEcart
> xEcart
) and (yEcart
> zEcart
):
2652 self
.CurLoc
= Vector(
2653 (self
.SavMousePos
.x
, vBack
[0].y
, self
.SavMousePos
.z
))
2654 if (zEcart
> xEcart
) and (zEcart
> yEcart
):
2655 self
.CurLoc
= Vector(
2656 (self
.SavMousePos
.x
, self
.SavMousePos
.y
, vBack
[0].z
))
2658 self
.CurLoc
= vBack
[0]
2660 self
.CurLoc
= vBack
[0]
2663 if self
.alt
is False:
2665 if self
.ctrl
and (self
.CutMode
== LINE
):
2667 coord
= list(self
.mouse_path
[len(self
.mouse_path
) - 1])
2669 self
.mouse_path
[len(self
.mouse_path
) - 2][0] +
2670 int((event
.mouse_region_x
-
2671 self
.mouse_path
[len(self
.mouse_path
) - 2][0]
2672 ) / self
.Increment
) * self
.Increment
2675 self
.mouse_path
[len(self
.mouse_path
) - 2][1] +
2676 int((event
.mouse_region_y
-
2677 self
.mouse_path
[len(self
.mouse_path
) - 2][1]
2678 ) / self
.Increment
) * self
.Increment
2680 self
.mouse_path
[len(self
.mouse_path
) - 1] = tuple(coord
)
2682 if len(self
.mouse_path
) > 0:
2683 self
.mouse_path
[len(self
.mouse_path
) -
2684 1] = (event
.mouse_region_x
, event
.mouse_region_y
)
2686 # [ALT] press, update position
2687 self
.xpos
+= (event
.mouse_region_x
- self
.last_mouse_region_x
)
2688 self
.ypos
+= (event
.mouse_region_y
- self
.last_mouse_region_y
)
2690 self
.last_mouse_region_x
= event
.mouse_region_x
2691 self
.last_mouse_region_y
= event
.mouse_region_y
2693 elif event
.type == 'LEFTMOUSE' and event
.value
== 'PRESS':
2694 if self
.ObjectMode
or self
.ProfileMode
:
2695 if self
.LMB
is False:
2696 vBack
= Pick(context
, event
, self
)
2697 if vBack
[0] is not None:
2698 NormalObject
= Vector((0.0, 0.0, 1.0))
2699 self
.aqR
= RBenVe(NormalObject
, vBack
[1])
2700 self
.qRot
= vBack
[3] * self
.aqR
2701 self
.am
= event
.mouse_region_x
, event
.mouse_region_y
2702 self
.xSavMouse
= event
.mouse_region_x
2705 self
.nRotZ
= int((self
.aRotZ
/ 25.0) / (PI
/ 4.0))
2706 self
.aRotZ
= self
.nRotZ
* (PI
/ 4.0) * 25.0
2711 elif event
.type == 'LEFTMOUSE' and event
.value
== 'RELEASE':
2712 if self
.ObjectMode
or self
.ProfileMode
:
2713 # Rotation and scale
2715 if self
.ObjectScale
is True:
2716 self
.ObjectScale
= False
2718 if self
.GridScaleX
is True:
2719 self
.GridScaleX
= False
2721 if self
.GridScaleY
is True:
2722 self
.GridScaleY
= False
2724 if self
.WidthSolidify
:
2725 self
.WidthSolidify
= False
2727 if self
.CarveDepth
is True:
2728 self
.CarveDepth
= False
2730 if self
.BrushDepth
is True:
2731 self
.BrushDepth
= False
2734 if self
.bDone
is False:
2736 Picking(context
, event
)
2738 if self
.CutMode
== LINE
:
2739 if self
.bDone
is False:
2740 self
.mouse_path
.clear()
2741 self
.mouse_path
.append((event
.mouse_region_x
, event
.mouse_region_y
))
2742 self
.mouse_path
.append((event
.mouse_region_x
, event
.mouse_region_y
))
2744 self
.mouse_path
[0] = (event
.mouse_region_x
, event
.mouse_region_y
)
2745 self
.mouse_path
[1] = (event
.mouse_region_x
, event
.mouse_region_y
)
2748 if self
.CutMode
!= LINE
:
2750 if self
.CutMode
== RECTANGLE
:
2751 CreateCutSquare(self
, context
)
2752 if self
.CutMode
== CIRCLE
:
2753 CreateCutCircle(self
, context
)
2754 if self
.CutMode
== LINE
:
2755 CreateCutLine(self
, context
)
2759 self
.CreateGeometry()
2760 bpy
.types
.SpaceView3D
.draw_handler_remove(self
._handle
, 'WINDOW')
2762 context
.scene
.mesh_carver
.DepthCursor
= self
.snapCursor
2763 # Instantiate object
2764 context
.scene
.mesh_carver
.OInstanciate
= self
.Instantiate
2766 context
.scene
.mesh_carver
.ORandom
= self
.RandomRotation
2768 context
.scene
.mesh_carver
.DontApply
= self
.DontApply
2770 # if Object mode, set intiale state
2771 if self
.ObjectBrush
is not None:
2772 self
.ObjectBrush
.location
= self
.InitBrushPosition
2773 self
.ObjectBrush
.scale
= self
.InitBrushScale
2774 self
.ObjectBrush
.rotation_quaternion
= self
.InitBrushQRotation
2775 self
.ObjectBrush
.rotation_euler
= self
.InitBrushERotation
2776 self
.ObjectBrush
.display_type
= self
.ObjectBrush_DT
2777 self
.ObjectBrush
.show_in_front
= self
.XRay
2780 Selection_Save(self
)
2781 self
.BrushSolidify
= False
2783 bpy
.ops
.object.select_all(action
='TOGGLE')
2784 self
.ObjectBrush
.select
= True
2785 context
.scene
.objects
.active
= self
.ObjectBrush
2787 bpy
.ops
.object.modifier_remove(modifier
="CT_SOLIDIFY")
2789 Selection_Restore(self
)
2791 context
.scene
.mesh_carver
.nProfile
= self
.nProfil
2796 UndoListUpdate(self
)
2799 self
.mouse_path
.append((event
.mouse_region_x
, event
.mouse_region_y
))
2801 # Change circle subdivisions
2802 elif (event
.type == 'COMMA' and event
.value
== 'PRESS') or \
2803 (event
.type == context
.scene
.Key_Subrem
and event
.value
== 'PRESS'):
2804 if self
.ProfileMode
:
2806 if self
.nProfil
>= self
.MaxProfil
:
2808 createMeshFromData(self
)
2810 if self
.CutMode
== CIRCLE
:
2812 self
.stepRotation
+= 1
2815 if self
.step
>= len(self
.stepAngle
):
2816 self
.step
= len(self
.stepAngle
) - 1
2817 elif (event
.type == 'PERIOD' and event
.value
== 'PRESS') or \
2818 (event
.type == context
.scene
.Key_Subadd
and event
.value
== 'PRESS'):
2819 if self
.ProfileMode
:
2821 if self
.nProfil
< 0:
2822 self
.nProfil
= self
.MaxProfil
- 1
2823 createMeshFromData(self
)
2824 if self
.CutMode
== CIRCLE
:
2826 self
.stepRotation
-= 1
2831 elif event
.type in {'RIGHTMOUSE', 'ESC'}:
2833 context
.scene
.mesh_carver
.DepthCursor
= self
.snapCursor
2834 # Instantiate object
2835 context
.scene
.mesh_carver
.OInstanciate
= self
.Instantiate
2837 context
.scene
.mesh_carver
.ORandom
= self
.RandomRotation
2838 # Apply boolean operation
2839 context
.scene
.mesh_carver
.DontApply
= self
.DontApply
2842 if self
.ObjectBrush
is not None:
2843 self
.ObjectBrush
.location
= self
.InitBrushPosition
2844 self
.ObjectBrush
.scale
= self
.InitBrushScale
2845 self
.ObjectBrush
.rotation_quaternion
= self
.InitBrushQRotation
2846 self
.ObjectBrush
.rotation_euler
= self
.InitBrushERotation
2847 self
.ObjectBrush
.display_type
= self
.ObjectBrush_DT
2848 self
.ObjectBrush
.show_in_front
= self
.XRay
2850 # Remove solidify modifier
2851 Selection_Save(self
)
2852 self
.BrushSolidify
= False
2854 bpy
.ops
.object.select_all(action
='TOGGLE')
2855 self
.ObjectBrush
.select
= True
2856 context
.scene
.objects
.active
= self
.ObjectBrush
2858 bpy
.ops
.object.modifier_remove(modifier
="CT_SOLIDIFY")
2859 bpy
.ops
.object.select_all(action
='TOGGLE')
2861 Selection_Restore(self
)
2863 Selection_Save_Restore(self
)
2864 context
.scene
.objects
.active
= self
.CurrentActive
2865 context
.scene
.mesh_carver
.nProfile
= self
.nProfil
2867 bpy
.types
.SpaceView3D
.draw_handler_remove(self
._handle
, 'WINDOW')
2869 # Remove Copy Object Brush
2870 if bpy
.data
.objects
.get("CarverBrushCopy") is not None:
2871 brush
= bpy
.data
.objects
["CarverBrushCopy"]
2872 self
.ObjectBrush
.data
= bpy
.data
.meshes
[brush
.data
.name
]
2873 bpy
.ops
.object.select_all(action
='DESELECT')
2874 bpy
.data
.objects
["CarverBrushCopy"].select
= True
2875 bpy
.ops
.object.delete()
2879 return {'RUNNING_MODAL'}
2882 print("\n[Carver MT ERROR]\n")
2884 traceback
.print_exc()
2886 context
.window
.cursor_modal_set("DEFAULT")
2887 context
.area
.header_text_set(None)
2888 bpy
.types
.SpaceView3D
.draw_handler_remove(self
._handle
, 'WINDOW')
2890 self
.report({'WARNING'},
2891 "Operation finished. Failure during Carving (Check the console for more info)")
2895 def cancel(self
, context
):
2896 # Note: used to prevent memory leaks on quitting Blender while the modal operator
2897 # is still running, gets called on return {"CANCELLED"}
2898 bpy
.types
.SpaceView3D
.draw_handler_remove(self
._handle
, 'WINDOW')
2900 def invoke(self
, context
, event
):
2901 if context
.area
.type != 'VIEW_3D':
2902 self
.report({'WARNING'},
2903 "View3D not found or not currently active. Operation Cancelled")
2904 return {'CANCELLED'}
2906 if context
.mode
== 'EDIT_MESH':
2907 bpy
.ops
.object.mode_set(mode
='OBJECT')
2909 # test if some other object types are selected that are not meshes
2910 test_selection
= True
2911 for obj
in context
.selected_objects
:
2912 if obj
.type != "MESH":
2913 test_selection
= False
2915 if not test_selection
:
2916 self
.report({'WARNING'},
2917 "Some selected objects are not of the Mesh type. Operation Cancelled")
2918 return {"CANCELLED"}
2920 # Get default patterns
2923 self
.Profils
.append((p
[0], p
[1], p
[2], p
[3]))
2925 for o
in context
.scene
.objects
:
2926 if not o
.name
.startswith(context
.scene
.ProfilePrefix
):
2929 # In-scene profiles may have changed, remove them to refresh
2930 for m
in bpy
.data
.meshes
:
2931 if m
.name
.startswith(context
.scene
.ProfilePrefix
):
2932 bpy
.data
.meshes
.remove(m
)
2935 for v
in o
.data
.vertices
:
2936 vertices
.append((v
.co
.x
, v
.co
.y
, v
.co
.z
))
2939 for f
in o
.data
.polygons
:
2941 for v
in f
.vertices
:
2946 self
.Profils
.append(
2948 Vector((o
.location
.x
, o
.location
.y
, o
.location
.z
)),
2952 self
.nProfil
= context
.scene
.mesh_carver
.nProfile
2953 self
.MaxProfil
= len(self
.Profils
)
2955 # reset selected profile if last profile exceeds length of array
2956 if self
.nProfil
>= self
.MaxProfil
:
2957 self
.nProfil
= context
.scene
.mesh_carver
.nProfile
= 0
2960 self
.CurrentSelection
= context
.selected_objects
.copy()
2961 self
.CurrentActive
= context
.active_object
2962 self
.SavSel
= context
.selected_objects
.copy()
2965 args
= (self
, context
)
2967 self
._handle
= bpy
.types
.SpaceView3D
.draw_handler_add(draw_callback_px
, args
, 'WINDOW', 'POST_PIXEL')
2969 self
.mouse_path
= [(0, 0), (0, 0)]
2976 self
.DontApply
= context
.scene
.mesh_carver
.DontApply
2977 self
.Auto_BevelUpdate
= True
2979 # Cut type (Rectangle, Circle, Line)
2981 self
.BoolOps
= DIFFERENCE
2984 self
.stepAngle
= [2, 4, 5, 6, 9, 10, 15, 20, 30, 40, 45, 60, 72, 90]
2986 self
.stepRotation
= 0
2988 # Primitives Position
2991 self
.InitPosition
= False
2995 # Close polygonal shape
2999 self
.snapCursor
= context
.scene
.mesh_carver
.DepthCursor
3002 self
.AskHelp
= False
3005 self
.OpsObj
= context
.active_object
3008 self
.CreateMode
= False
3009 self
.ExclusiveCreateMode
= False
3010 if len(context
.selected_objects
) == 0:
3011 self
.ExclusiveCreateMode
= True
3012 self
.CreateMode
= True
3014 # Rebool forced (cut line)
3015 self
.ForceRebool
= False
3017 self
.ViewVector
= Vector()
3018 self
.CurrentObj
= None
3021 self
.BrushSolidify
= False
3022 self
.WidthSolidify
= False
3023 self
.CarveDepth
= False
3024 self
.BrushDepth
= False
3025 self
.BrushDepthOffset
= 0.0
3027 self
.ObjectScale
= False
3029 self
.CircleListRaw
= []
3031 self
.CurLoc
= Vector((0.0, 0.0, 0.0))
3032 self
.SavCurLoc
= Vector((0.0, 0.0, 0.0))
3034 CreatePrimitive(self
, 10.0, 1.0)
3039 self
.SavMousePos
= None
3048 self
.RandomRotation
= context
.scene
.mesh_carver
.ORandom
3050 self
.ShowCursor
= True
3051 self
.ObjectMode
= False
3052 self
.ProfileMode
= False
3053 self
.Instantiate
= context
.scene
.mesh_carver
.OInstanciate
3055 self
.ProfileBrush
= None
3056 self
.ObjectBrush
= None
3057 self
.InitBrushPosition
= None
3058 self
.InitBrushScale
= None
3059 self
.InitBrushQRotation
= None
3060 self
.InitBrushERotation
= None
3061 self
.InitBrushARotation
= None
3063 self
.ObjectBrush_DT
= "WIRE"
3074 self
.GridScaleX
= False
3075 self
.GridScaleY
= False
3077 if len(context
.selected_objects
) > 1:
3078 self
.ObjectBrush
= context
.active_object
3080 # Copy the brush object
3081 ob
= bpy
.data
.objects
.new("CarverBrushCopy", context
.object.data
.copy())
3082 ob
.location
= self
.ObjectBrush
.location
3083 scene
= context
.scene
3084 scene
.objects
.link(ob
)
3087 # Get default variables
3088 self
.InitBrushPosition
= self
.ObjectBrush
.location
.copy()
3089 self
.InitBrushScale
= self
.ObjectBrush
.scale
.copy()
3090 self
.InitBrushQRotation
= self
.ObjectBrush
.rotation_quaternion
.copy()
3091 self
.InitBrushERotation
= self
.ObjectBrush
.rotation_euler
.copy()
3092 self
.ObjectBrush_DT
= self
.ObjectBrush
.display_type
3093 self
.XRay
= self
.ObjectBrush
.show_in_front
3094 # Test if flat object
3095 z
= self
.ObjectBrush
.data
.vertices
[0].co
.z
3097 self
.Solidify_Active_Start
= True
3098 for v
in self
.ObjectBrush
.data
.vertices
:
3099 if abs(v
.co
.z
- z
) > ErrorMarge
:
3100 self
.Solidify_Active_Start
= False
3102 self
.SolidifyPossible
= False
3109 for ent
in context
.selected_objects
:
3110 if ent
!= self
.ObjectBrush
:
3111 self
.OB_List
.append(ent
)
3118 self
.undo_limit
= context
.user_preferences
.edit
.undo_steps
3121 # Boolean operations type
3122 self
.BooleanType
= 0
3125 self
.UList_Index
= -1
3128 context
.window_manager
.modal_handler_add(self
)
3129 return {'RUNNING_MODAL'}
3131 def CreateGeometry(self
):
3132 context
= bpy
.context
3135 for area
in context
.screen
.areas
:
3136 if area
.type == 'VIEW_3D':
3137 if area
.spaces
[0].local_view
is not None:
3141 bpy
.ops
.view3d
.localview()
3143 if self
.ExclusiveCreateMode
:
3147 ActiveObj
= self
.CurrentSelection
[0]
3148 if ActiveObj
is not None:
3149 objBBDiagonal
= objDiagonal(ActiveObj
) / 4
3152 if len(context
.selected_objects
) > 0:
3153 bpy
.ops
.object.select_all(action
='TOGGLE')
3155 context
.scene
.objects
.active
= self
.CurrentObj
3157 bpy
.data
.objects
[self
.CurrentObj
.name
].select
= True
3158 bpy
.ops
.object.origin_set(type='ORIGIN_GEOMETRY')
3160 bpy
.ops
.object.mode_set(mode
='EDIT')
3161 bpy
.ops
.mesh
.select_all(action
='SELECT')
3162 bpy
.ops
.mesh
.select_mode(type="EDGE")
3163 if self
.snapCursor
is False:
3164 bpy
.ops
.transform
.translate(value
=self
.ViewVector
* objBBDiagonal
* subdivisions
)
3165 bpy
.ops
.mesh
.extrude_region_move(
3166 TRANSFORM_OT_translate
={"value": -self
.ViewVector
* objBBDiagonal
* subdivisions
* 2})
3168 bpy
.ops
.mesh
.select_all(action
='SELECT')
3169 bpy
.ops
.mesh
.normals_make_consistent()
3170 bpy
.ops
.object.mode_set(mode
='OBJECT')
3172 saved_location_0
= context
.scene
.cursor_location
.copy()
3173 bpy
.ops
.view3d
.snap_cursor_to_active()
3174 saved_location
= context
.scene
.cursor_location
.copy()
3175 bpy
.ops
.object.transform_apply(location
=True, rotation
=True, scale
=True)
3176 context
.scene
.cursor_location
= saved_location
3177 bpy
.ops
.object.origin_set(type='ORIGIN_CURSOR')
3178 context
.scene
.cursor_location
= saved_location_0
3180 bpy
.data
.objects
[self
.CurrentObj
.name
].select
= True
3181 bpy
.ops
.object.origin_set(type='ORIGIN_GEOMETRY')
3183 for o
in self
.SavSel
:
3184 bpy
.data
.objects
[o
.name
].select
= True
3187 bpy
.ops
.view3d
.localview()
3190 self
.mouse_path
.clear()
3191 self
.mouse_path
= [(0, 0), (0, 0)]
3194 context
= bpy
.context
3198 for area
in context
.screen
.areas
:
3199 if area
.type == 'VIEW_3D':
3200 if area
.spaces
[0].local_view
is not None:
3204 bpy
.ops
.view3d
.localview()
3206 # Save cursor position
3207 CursorLocation
= context
.scene
.cursor_location
.copy()
3210 if (self
.ObjectMode
is False) and (self
.ProfileMode
is False):
3211 objBBDiagonal
= objDiagonal(self
.CurrentSelection
[0])
3216 # Get selected objects
3217 ActiveObjList
= context
.selected_objects
.copy()
3219 bpy
.ops
.object.select_all(action
='TOGGLE')
3221 context
.scene
.objects
.active
= self
.CurrentObj
3223 bpy
.data
.objects
[self
.CurrentObj
.name
].select
= True
3224 bpy
.ops
.object.origin_set(type='ORIGIN_GEOMETRY')
3226 bpy
.ops
.object.mode_set(mode
='EDIT')
3227 bpy
.ops
.mesh
.select_all(action
='SELECT')
3228 bpy
.ops
.mesh
.select_mode(type="EDGE")
3229 if (self
.snapCursor
is False) or (self
.ForceRebool
):
3230 bpy
.ops
.transform
.translate(value
=self
.ViewVector
* objBBDiagonal
* subdivisions
)
3231 bpy
.ops
.mesh
.extrude_region_move(
3232 TRANSFORM_OT_translate
={"value": -self
.ViewVector
* objBBDiagonal
* subdivisions
* 2})
3233 bpy
.ops
.mesh
.select_all(action
='SELECT')
3234 bpy
.ops
.mesh
.normals_make_consistent()
3235 bpy
.ops
.object.mode_set(mode
='OBJECT')
3239 for o
in self
.CurrentSelection
:
3240 if o
!= self
.ObjectBrush
:
3241 ActiveObjList
.append(o
)
3242 self
.CurrentObj
= self
.ObjectBrush
3244 ActiveObjList
= self
.CurrentSelection
3245 self
.CurrentObj
= self
.ProfileBrush
3247 for o
in self
.CurrentSelection
:
3248 UndoAdd(self
, "MESH", o
)
3250 # List objects create with rebool
3253 for ActiveObj
in ActiveObjList
:
3254 context
.scene
.cursor_location
= CursorLocation
3256 if len(context
.selected_objects
) > 0:
3257 bpy
.ops
.object.select_all(action
='TOGGLE')
3259 # Test if initial object has bevel
3261 for obj
in ActiveObjList
:
3262 for mb
in obj
.modifiers
:
3263 if mb
.type == 'BEVEL':
3267 bpy
.data
.objects
[self
.CurrentObj
.name
].select
= True
3268 context
.scene
.objects
.active
= self
.CurrentObj
3270 bpy
.ops
.object.mode_set(mode
='EDIT')
3271 bpy
.ops
.mesh
.select_all(action
='SELECT')
3272 bpy
.ops
.object.mode_set(mode
='OBJECT')
3274 # Select object to cut
3275 bpy
.data
.objects
[ActiveObj
.name
].select
= True
3276 context
.scene
.objects
.active
= ActiveObj
3278 bpy
.ops
.object.mode_set(mode
='EDIT')
3279 bpy
.ops
.mesh
.select_all(action
='DESELECT')
3280 bpy
.ops
.object.mode_set(mode
='OBJECT')
3283 if (self
.shift
is False) and (self
.ForceRebool
is False):
3284 if self
.ObjectMode
or self
.ProfileMode
:
3285 if self
.BoolOps
== UNION
:
3286 boolean_operation(bool_type
="UNION")
3288 boolean_operation(bool_type
="DIFFERENCE")
3290 boolean_operation(bool_type
="DIFFERENCE")
3293 if self
.DontApply
is False:
3294 BMname
= "CT_" + self
.CurrentObj
.name
3295 for mb
in ActiveObj
.modifiers
:
3296 if (mb
.type == 'BOOLEAN') and (mb
.name
== BMname
):
3298 bpy
.ops
.object.modifier_apply(apply_as
='DATA', modifier
=BMname
)
3300 bpy
.ops
.object.modifier_remove(modifier
=BMname
)
3301 exc_type
, exc_value
, exc_traceback
= sys
.exc_info()
3302 self
.report({'ERROR'}, str(exc_value
))
3304 bpy
.ops
.object.select_all(action
='TOGGLE')
3306 if self
.ObjectMode
or self
.ProfileMode
:
3307 for mb
in self
.CurrentObj
.modifiers
:
3308 if (mb
.type == 'SOLIDIFY') and (mb
.name
== "CT_SOLIDIFY"):
3310 bpy
.ops
.object.modifier_apply(apply_as
='DATA', modifier
="CT_SOLIDIFY")
3312 exc_type
, exc_value
, exc_traceback
= sys
.exc_info()
3313 self
.report({'ERROR'}, str(exc_value
))
3316 Rebool(context
, self
)
3317 # Test if not empty object
3318 if context
.selected_objects
[0]:
3319 rebool_RT
= context
.selected_objects
[0]
3320 if len(rebool_RT
.data
.vertices
) > 0:
3321 # Create Bevel for new objects
3323 CreateBevel(context
, context
.selected_objects
[0])
3324 UndoAdd(self
, "REBOOL", context
.selected_objects
[0])
3326 context
.scene
.cursor_location
= ActiveObj
.location
3327 bpy
.ops
.object.origin_set(type='ORIGIN_CURSOR')
3329 bpy
.ops
.object.delete(use_global
=False)
3331 context
.scene
.cursor_location
= CursorLocation
3334 context
.scene
.objects
.active
= self
.ObjectBrush
3335 if self
.ProfileMode
:
3336 context
.scene
.objects
.active
= self
.ProfileBrush
3338 if self
.DontApply
is False:
3340 BMname
= "CT_" + self
.CurrentObj
.name
3341 for mb
in ActiveObj
.modifiers
:
3342 if (mb
.type == 'BOOLEAN') and (mb
.name
== BMname
):
3344 bpy
.ops
.object.modifier_apply(apply_as
='DATA', modifier
=BMname
)
3346 bpy
.ops
.object.modifier_remove(modifier
=BMname
)
3347 exc_type
, exc_value
, exc_traceback
= sys
.exc_info()
3348 self
.report({'ERROR'}, str(exc_value
))
3349 # Get new objects created with rebool operations
3350 if len(context
.selected_objects
) > 0:
3351 if self
.shift
is True:
3352 # Get the last object selected
3353 lastSelected
.append(context
.selected_objects
[0])
3355 context
.scene
.cursor_location
= CursorLocation
3357 if self
.DontApply
is False:
3359 if (self
.ObjectMode
is False) and (self
.ProfileMode
is False):
3360 if len(context
.selected_objects
) > 0:
3361 bpy
.ops
.object.select_all(action
='TOGGLE')
3362 bpy
.data
.objects
[self
.CurrentObj
.name
].select
= True
3363 bpy
.ops
.object.delete(use_global
=False)
3366 self
.ObjectBrush
.display_type
= self
.ObjectBrush_DT
3368 if len(context
.selected_objects
) > 0:
3369 bpy
.ops
.object.select_all(action
='TOGGLE')
3371 # Select cut objects
3372 for obj
in lastSelected
:
3373 bpy
.data
.objects
[obj
.name
].select
= True
3375 for ActiveObj
in ActiveObjList
:
3376 bpy
.data
.objects
[ActiveObj
.name
].select
= True
3377 context
.scene
.objects
.active
= ActiveObj
3379 list_act_obj
= context
.selected_objects
.copy()
3380 if self
.Auto_BevelUpdate
:
3381 update_bevel(context
)
3383 # Re-select initial objects
3384 bpy
.ops
.object.select_all(action
='TOGGLE')
3387 self
.ObjectBrush
.select
= True
3388 for ActiveObj
in ActiveObjList
:
3389 bpy
.data
.objects
[ActiveObj
.name
].select
= True
3390 context
.scene
.objects
.active
= ActiveObj
3392 # If object has children, set "Wire" draw type
3393 if self
.ObjectBrush
is not None:
3394 if len(self
.ObjectBrush
.children
) > 0:
3395 self
.ObjectBrush
.display_type
= "WIRE"
3396 if self
.ProfileMode
:
3397 self
.ProfileBrush
.display_type
= "WIRE"
3400 bpy
.ops
.view3d
.localview()
3404 self
.mouse_path
.clear()
3405 self
.mouse_path
= [(0, 0), (0, 0)]
3407 self
.ForceRebool
= False
3410 class CarverProperties(bpy
.types
.PropertyGroup
):
3411 DepthCursor
= BoolProperty(
3415 OInstanciate
= BoolProperty(
3416 name
="Obj_Instantiate",
3419 ORandom
= BoolProperty(
3420 name
="Random_Rotation",
3423 DontApply
= BoolProperty(
3427 nProfile
= IntProperty(
3444 bpy
.utils
.register_class(cls
)
3446 bpy
.types
.Scene
.mesh_carver
= PointerProperty(
3447 type=CarverProperties
3450 kcfg
= bpy
.context
.window_manager
.keyconfigs
.addon
3452 km
= kcfg
.keymaps
.new(name
='3D View', space_type
='VIEW_3D')
3453 kmi
= km
.keymap_items
.new("object.carver", 'X', 'PRESS', shift
=True, ctrl
=True)
3454 addon_keymaps
.append((km
, kmi
))
3459 bpy
.utils
.unregister_class(cls
)
3461 # remove keymap entry
3462 for km
, kmi
in addon_keymaps
:
3463 km
.keymap_items
.remove(kmi
)
3464 addon_keymaps
.clear()
3466 del bpy
.types
.Scene
.mesh_carver
3469 if __name__
== "__main__":