Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormeta-androcto <meta.androcto1@gmail.com>2016-07-31 11:59:58 +0300
committermeta-androcto <meta.androcto1@gmail.com>2016-07-31 11:59:58 +0300
commit2b7e36093b3ede3b3ecec2d0f6a77996b372788f (patch)
treea218aa501c2aeae6dca9859d6e2c8b8200df0f4c /mesh_carver.py
parent84b69e64ea67ae01b31a6831d11c339496a525bc (diff)
Add mesh_carver.py to release. re: T48561
Diffstat (limited to 'mesh_carver.py')
-rw-r--r--mesh_carver.py3405
1 files changed, 3405 insertions, 0 deletions
diff --git a/mesh_carver.py b/mesh_carver.py
new file mode 100644
index 00000000..ae6f3ecf
--- /dev/null
+++ b/mesh_carver.py
@@ -0,0 +1,3405 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+
+bl_info = {
+ "name": "Carver MT",
+ "category": "Object",
+ "author": "Pixivore, Cédric LEPILLER",
+ "version": (1, 1, 5),
+ "blender": (2, 77, 0),
+ "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
+ "Scripts/Modeling/Carver",
+ "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
+ "description": "Multiple tools to carve or to create objects.",
+}
+
+import bpy
+import bgl
+import blf
+import math
+import mathutils
+import sys
+import random
+import bmesh
+import bpy_extras
+from bpy_extras import view3d_utils
+from bpy_extras.view3d_utils import region_2d_to_vector_3d, region_2d_to_location_3d
+import numpy as np
+
+Profils = [
+ ("CTP_4882",
+ mathutils.Vector((2.61824, -5.56469, 0)),
+ [(-1.156501, 0.799282, 0.032334),
+ (-0.967583, 0.838861, 0.032334),
+ (-1.10386, 0.846403, 0.032334),
+ (-1.034712, 0.86089, 0.032334),
+ (-1.88472, -0.564419, 0.032334),
+ (-1.924299, -0.375502, 0.032334),
+ (-1.93184, -0.511778, 0.032334),
+ (-1.946327, -0.44263, 0.032334),
+ (-0.219065, -0.869195, 0.032334),
+ (-0.149916, -0.854708, 0.032334),
+ (-0.286193, -0.847167, 0.032334),
+ (-0.097275, -0.807588, 0.032334),
+ (0.692551, 0.434324, 0.032334),
+ (0.678064, 0.503472, 0.032334),
+ (0.670523, 0.367196, 0.032334),
+ (0.630943, 0.556113, 0.032334),
+ (-0.780424, -0.44263, 0.032334),
+ (-0.765937, -0.511778, 0.032334),
+ (-0.758396, -0.375502, 0.032334),
+ (-0.718817, -0.564419, 0.032334),
+ (-0.53496, 0.556113, 0.032334),
+ (-0.49538, 0.367196, 0.032334),
+ (-0.487839, 0.503472, 0.032334),
+ (-0.473352, 0.434324, 0.032334),
+ (-1.263178, -0.807588, 0.032334),
+ (-1.452096, -0.847167, 0.032334),
+ (-1.315819, -0.854708, 0.032334),
+ (-1.384968, -0.869195, 0.032334),
+ (0.131191, 0.86089, 0.032334),
+ (0.062043, 0.846403, 0.032334),
+ (0.19832, 0.838861, 0.032334),
+ (0.009402, 0.799282, 0.032334),
+ (0.946838, -0.869195, 0.032334),
+ (1.015987, -0.854708, 0.032334),
+ (0.87971, -0.847167, 0.032334),
+ (1.068628, -0.807588, 0.032334),
+ (1.858454, 0.434324, 0.032334),
+ (1.843967, 0.503472, 0.032334),
+ (1.836426, 0.367196, 0.032334),
+ (1.796846, 0.556113, 0.032334),
+ (0.385479, -0.44263, 0.032334),
+ (0.399966, -0.511778, 0.032334),
+ (0.407507, -0.375502, 0.032334),
+ (0.447086, -0.564419, 0.032334),
+ (1.297095, 0.86089, 0.032334),
+ (1.227946, 0.846403, 0.032334),
+ (1.364223, 0.838861, 0.032334),
+ (1.175305, 0.799282, 0.032334),
+ ],
+ [[16, 17, 19], [5, 4, 24], [14, 12, 15], [14, 15, 31], [10, 8, 11], [15, 30, 31], [19, 10, 11],
+ [11, 14, 31], [31, 18, 11], [8, 9, 11], [18, 16, 19], [12, 13, 15], [18, 19, 11], [28, 29, 31],
+ [30, 28, 31], [24, 21, 0], [23, 22, 20], [20, 1, 0], [3, 2, 0], [0, 5, 24], [7, 6, 4], [4, 25, 24],
+ [27, 26, 24], [21, 23, 20], [1, 3, 0], [5, 7, 4], [25, 27, 24], [21, 20, 0], [40, 41, 43], [38, 36, 39],
+ [38, 39, 47], [34, 32, 35], [39, 46, 47], [43, 34, 35], [35, 38, 47], [47, 42, 35], [32, 33, 35],
+ [42, 40, 43], [36, 37, 39], [42, 43, 35], [44, 45, 47], [46, 44, 47]]),
+ ("CTP_8354",
+ mathutils.Vector((-0.06267, -2.43829, -0.0)),
+ [(-0.534254, -1.0, 0.032334),
+ (-1.0, -0.534254, 0.032334),
+ (-0.654798, -0.98413, 0.032334),
+ (-0.767127, -0.937602, 0.032334),
+ (-0.863586, -0.863586, 0.032334),
+ (-0.937602, -0.767127, 0.032334),
+ (-0.98413, -0.654798, 0.032334),
+ (1.0, -0.534254, 0.032334),
+ (0.534254, -1.0, 0.032334),
+ (0.98413, -0.654798, 0.032334),
+ (0.937602, -0.767127, 0.032334),
+ (0.863586, -0.863586, 0.032334),
+ (0.767127, -0.937602, 0.032334),
+ (0.654798, -0.98413, 0.032334),
+ (-1.0, 0.534254, 0.032334),
+ (-0.534254, 1.0, 0.032334),
+ (-0.98413, 0.654798, 0.032334),
+ (-0.937602, 0.767127, 0.032334),
+ (-0.863586, 0.863586, 0.032334),
+ (-0.767127, 0.937602, 0.032334),
+ (-0.654798, 0.98413, 0.032334),
+ (0.534254, 1.0, 0.032334),
+ (1.0, 0.534254, 0.032334),
+ (0.654798, 0.98413, 0.032334),
+ (0.767127, 0.937602, 0.032334),
+ (0.863586, 0.863586, 0.032334),
+ (0.937602, 0.767127, 0.032334),
+ (0.98413, 0.654798, 0.032334),
+ (-0.763998, 0.518786, 0.032334),
+ (-0.763998, -0.518786, 0.032334),
+ (-0.754202, -0.593189, 0.032334),
+ (-0.731454, -0.648108, 0.032334),
+ (-0.695267, -0.695267, 0.032334),
+ (-0.648108, -0.731454, 0.032334),
+ (-0.593189, -0.754202, 0.032334),
+ (-0.518786, -0.763998, 0.032334),
+ (0.518786, -0.763998, 0.032334),
+ (0.593189, -0.754202, 0.032334),
+ (0.648108, -0.731454, 0.032334),
+ (0.695267, -0.695267, 0.032334),
+ (0.731454, -0.648108, 0.032334),
+ (0.754202, -0.593189, 0.032334),
+ (0.763998, -0.518786, 0.032334),
+ (0.763998, 0.518786, 0.032334),
+ (0.754202, 0.593189, 0.032334),
+ (0.731454, 0.648108, 0.032334),
+ (0.695267, 0.695267, 0.032334),
+ (0.648108, 0.731454, 0.032334),
+ (0.593189, 0.754202, 0.032334),
+ (0.518786, 0.763998, 0.032334),
+ (-0.518786, 0.763998, 0.032334),
+ (-0.593189, 0.754202, 0.032334),
+ (-0.648108, 0.731454, 0.032334),
+ (-0.695267, 0.695267, 0.032334),
+ (-0.731454, 0.648108, 0.032334),
+ (-0.754202, 0.593189, 0.032334),
+ (0.518786, 0.518786, 0.032334),
+ (-0.518786, 0.518786, 0.032334),
+ (0.518786, -0.518786, 0.032334),
+ (-0.518786, -0.518786, 0.032334),
+ (-0.593189, 0.518786, 0.032334),
+ (-0.593189, -0.518786, 0.032334),
+ (0.518786, -0.593189, 0.032334),
+ (-0.518786, -0.593189, 0.032334),
+ (-0.593189, -0.593189, 0.032334),
+ (0.593189, 0.518786, 0.032334),
+ (0.593189, -0.518786, 0.032334),
+ (0.593189, -0.593189, 0.032334),
+ (-0.593189, 0.593189, 0.032334),
+ (-0.518786, 0.593189, 0.032334),
+ (0.518786, 0.593189, 0.032334),
+ (0.593189, 0.593189, 0.032334),
+ (-0.648108, 0.593189, 0.032334),
+ (-0.648108, 0.518786, 0.032334),
+ (-0.648108, -0.518786, 0.032334),
+ (-0.648108, -0.593189, 0.032334),
+ (-0.695267, 0.593189, 0.032334),
+ (-0.695267, 0.518786, 0.032334),
+ (-0.695267, -0.518786, 0.032334),
+ (-0.695267, -0.593189, 0.032334),
+ (0.648108, 0.593189, 0.032334),
+ (0.648108, 0.518786, 0.032334),
+ (0.648108, -0.518786, 0.032334),
+ (0.648108, -0.593189, 0.032334),
+ (0.695267, 0.593189, 0.032334),
+ (0.695267, 0.518786, 0.032334),
+ (0.695267, -0.518786, 0.032334),
+ (0.695267, -0.593189, 0.032334),
+ ],
+ [[87, 39, 40, 41], [29, 28, 14, 1], [30, 29, 1, 6], [31, 30, 6, 5], [32, 31, 5, 4], [33, 32, 4, 3],
+ [34, 33, 3, 2], [35, 34, 2, 0], [36, 35, 0, 8], [37, 36, 8, 13], [38, 37, 13, 12], [39, 38, 12, 11],
+ [40, 39, 11, 10], [41, 40, 10, 9], [42, 41, 9, 7], [43, 42, 7, 22], [44, 43, 22, 27], [45, 44, 27, 26],
+ [46, 45, 26, 25], [47, 46, 25, 24], [48, 47, 24, 23], [49, 48, 23, 21], [50, 49, 21, 15], [51, 50, 15, 20],
+ [52, 51, 20, 19], [53, 52, 19, 18], [54, 53, 18, 17], [55, 54, 17, 16], [28, 55, 16, 14], [68, 69, 50, 51],
+ [63, 35, 36, 62], [69, 57, 56, 70], [84, 85, 43, 44], [64, 34, 35, 63], [57, 59, 58, 56], [85, 86, 42, 43],
+ [60, 61, 59, 57], [73, 74, 61, 60], [72, 68, 51, 52], [75, 33, 34, 64], [61, 64, 63, 59], [59, 63, 62, 58],
+ [86, 87, 41, 42], [74, 75, 64, 61], [58, 62, 67, 66], [56, 58, 66, 65], [70, 56, 65, 71], [62, 36, 37, 67],
+ [49, 70, 71, 48], [50, 69, 70, 49], [60, 57, 69, 68], [73, 60, 68, 72], [46, 84, 44, 45], [78, 79, 75, 74],
+ [77, 78, 74, 73], [77, 73, 72, 76], [76, 72, 52, 53], [79, 32, 33, 75], [29, 30, 79, 78], [28, 29, 78, 77],
+ [28, 77, 76, 55], [55, 76, 53, 54], [30, 31, 32, 79], [66, 67, 83, 82], [65, 66, 82, 81], [71, 65, 81, 80],
+ [48, 71, 80, 47], [67, 37, 38, 83], [82, 83, 87, 86], [81, 82, 86, 85], [80, 81, 85, 84], [47, 80, 84, 46],
+ [83, 38, 39, 87]]),
+ ("CTP_5585",
+ mathutils.Vector((5.0114, -2.4281, 0.0)),
+ [(-0.490711, -1.0, 0.032334),
+ (-1.0, -0.490711, 0.032334),
+ (1.0, -0.490711, 0.032334),
+ (0.490711, -1.0, 0.032334),
+ (-1.0, 0.490711, 0.032334),
+ (-0.490711, 1.0, 0.032334),
+ (0.490711, 1.0, 0.032334),
+ (1.0, 0.490711, 0.032334),
+ (-0.51852, 0.291276, 0.032334),
+ (-0.51852, -0.291276, 0.032334),
+ (-0.291276, -0.51852, 0.032334),
+ (0.291276, -0.51852, 0.032334),
+ (0.51852, -0.291276, 0.032334),
+ (0.51852, 0.291276, 0.032334),
+ (0.291276, 0.51852, 0.032334),
+ (-0.291276, 0.51852, 0.032334),
+ ],
+ [[11, 12, 13, 14], [9, 8, 4, 1], [10, 9, 1, 0], [11, 10, 0, 3], [12, 11, 3, 2], [13, 12, 2, 7],
+ [14, 13, 7, 6], [15, 14, 6, 5], [8, 15, 5, 4], [9, 10, 15, 8], [10, 11, 14, 15]]),
+ ("CTP_6960",
+ mathutils.Vector((-0.11417, 2.48371, -0.0)),
+ [(0.0, 1.0, 0.016827),
+ (-0.382683, 0.92388, 0.016827),
+ (-0.707107, 0.707107, 0.016827),
+ (-0.92388, 0.382683, 0.016827),
+ (-1.0, -0.0, 0.016827),
+ (-0.92388, -0.382684, 0.016827),
+ (-0.707107, -0.707107, 0.016827),
+ (-0.382683, -0.92388, 0.016827),
+ (-0.0, -1.0, 0.016827),
+ (0.382683, -0.92388, 0.016827),
+ (0.707107, -0.707107, 0.016827),
+ (0.92388, -0.382684, 0.016827),
+ (1.0, 0.0, 0.016827),
+ (0.923879, 0.382684, 0.016827),
+ (0.707107, 0.707107, 0.016827),
+ (0.382683, 0.92388, 0.016827),
+ (-0.0, 0.546859, 0.016827),
+ (-0.209274, 0.505231, 0.016827),
+ (-0.386687, 0.386687, 0.016827),
+ (-0.505231, 0.209274, 0.016827),
+ (-0.546859, -0.0, 0.016827),
+ (-0.505231, -0.209274, 0.016827),
+ (-0.386687, -0.386687, 0.016827),
+ (-0.209274, -0.505231, 0.016827),
+ (-0.0, -0.546859, 0.016827),
+ (0.209274, -0.505231, 0.016827),
+ (0.386687, -0.386688, 0.016827),
+ (0.505231, -0.209274, 0.016827),
+ (0.546858, 0.0, 0.016827),
+ (0.505231, 0.209274, 0.016827),
+ (0.386687, 0.386688, 0.016827),
+ (0.209273, 0.505232, 0.016827),
+ ],
+ [[3, 19, 18, 2], [11, 27, 26, 10], [4, 20, 19, 3], [12, 28, 27, 11], [5, 21, 20, 4], [13, 29, 28, 12],
+ [6, 22, 21, 5], [14, 30, 29, 13], [7, 23, 22, 6], [15, 31, 30, 14], [8, 24, 23, 7], [1, 17, 16, 0],
+ [0, 16, 31, 15], [9, 25, 24, 8], [2, 18, 17, 1], [10, 26, 25, 9]]),
+ ("CTP_5359",
+ mathutils.Vector((5.50446, 2.41669, -0.0)),
+ [(0.0, 0.714247, 0.023261),
+ (-0.382683, 0.659879, 0.023261),
+ (-0.707107, 0.505049, 0.023261),
+ (-0.92388, 0.273331, 0.023261),
+ (-1.0, -0.0, 0.023261),
+ (-0.92388, -0.273331, 0.023261),
+ (-0.707107, -0.505049, 0.023261),
+ (-0.382683, -0.659879, 0.023261),
+ (-0.0, -0.714247, 0.023261),
+ (0.382683, -0.659879, 0.023261),
+ (0.707107, -0.505049, 0.023261),
+ (0.92388, -0.273331, 0.023261),
+ (1.0, 0.0, 0.023261),
+ (0.923879, 0.273331, 0.023261),
+ (0.707107, 0.505049, 0.023261),
+ (0.382683, 0.659879, 0.023261),
+ (-0.0, 0.303676, 0.023261),
+ (-0.162705, 0.28056, 0.023261),
+ (-0.30064, 0.214731, 0.023261),
+ (-0.392805, 0.116212, 0.023261),
+ (-0.425169, -0.0, 0.023261),
+ (-0.392805, -0.116212, 0.023261),
+ (-0.30064, -0.214731, 0.023261),
+ (-0.162705, -0.28056, 0.023261),
+ (-0.0, -0.303676, 0.023261),
+ (0.162705, -0.28056, 0.023261),
+ (0.30064, -0.214731, 0.023261),
+ (0.392805, -0.116212, 0.023261),
+ (0.425169, 0.0, 0.023261),
+ (0.392805, 0.116212, 0.023261),
+ (0.30064, 0.214731, 0.023261),
+ (0.162705, 0.28056, 0.023261),
+ ],
+ [[3, 19, 18, 2], [11, 27, 26, 10], [4, 20, 19, 3], [12, 28, 27, 11], [5, 21, 20, 4], [13, 29, 28, 12],
+ [6, 22, 21, 5], [14, 30, 29, 13], [7, 23, 22, 6], [15, 31, 30, 14], [8, 24, 23, 7], [1, 17, 16, 0],
+ [0, 16, 31, 15], [9, 25, 24, 8], [2, 18, 17, 1], [10, 26, 25, 9]]),
+ ("CTP_5424",
+ mathutils.Vector((2.61824, 2.34147, 0.0)),
+ [(1.0, -1.0, 0.032334),
+ (-1.0, 1.0, 0.032334),
+ (1.0, 1.0, 0.032334),
+ (0.783867, -0.259989, 0.032334),
+ (-0.393641, 0.857073, 0.032334),
+ (0.73142, -0.116299, 0.032334),
+ (0.657754, 0.02916, 0.032334),
+ (0.564682, 0.172804, 0.032334),
+ (0.454497, 0.311098, 0.032334),
+ (0.329912, 0.440635, 0.032334),
+ (0.193995, 0.558227, 0.032334),
+ (0.050092, 0.660978, 0.032334),
+ (-0.098254, 0.746358, 0.032334),
+ (-0.247389, 0.812263, 0.032334),
+ ],
+ [[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],
+ [8, 7, 2], [2, 11, 10], [9, 8, 2]]),
+ ("CTP_3774",
+ mathutils.Vector((2.61824, -2.52425, 0.0)),
+ [(1.0, 0.0, 0.020045),
+ (-1.0, 0.0, 0.020045),
+ (0.31903, -0.664947, 0.020045),
+ (-0.31903, -0.664947, 0.020045),
+ (-0.31903, 1.0, 0.020045),
+ (0.31903, 1.0, 0.020045),
+ (0.31903, 0.0, 0.020045),
+ (-0.31903, 0.0, 0.020045),
+ (-1.0, 0.614333, 0.020045),
+ (-0.614333, 1.0, 0.020045),
+ (-0.970643, 0.761921, 0.020045),
+ (-0.887041, 0.887041, 0.020045),
+ (-0.761921, 0.970643, 0.020045),
+ (0.614333, 1.0, 0.020045),
+ (1.0, 0.614333, 0.020045),
+ (0.761921, 0.970643, 0.020045),
+ (0.887041, 0.887041, 0.020045),
+ (0.970643, 0.761921, 0.020045),
+ (-0.31903, 0.614333, 0.020045),
+ (0.31903, 0.614333, 0.020045),
+ (0.31903, 0.761921, 0.020045),
+ (-0.31903, 0.761921, 0.020045),
+ (0.31903, 0.887041, 0.020045),
+ (-0.31903, 0.887041, 0.020045),
+ (0.614333, 0.614333, 0.020045),
+ (0.614333, 0.0, 0.020045),
+ (0.614333, 0.761921, 0.020045),
+ (0.614333, 0.887041, 0.020045),
+ (-0.614333, 0.761921, 0.020045),
+ (-0.614333, 0.0, 0.020045),
+ (-0.614333, 0.887041, 0.020045),
+ (-0.614333, 0.614333, 0.020045),
+ ],
+ [[6, 25, 24, 19], [6, 19, 18, 7], [2, 6, 7, 3], [1, 29, 31, 8], [8, 31, 28, 10], [19, 24, 26, 20],
+ [18, 19, 20, 21], [21, 20, 22, 23], [10, 28, 30, 11], [20, 26, 27, 22], [22, 27, 13, 5], [23, 22, 5, 4],
+ [11, 30, 9, 12], [17, 16, 27, 26], [14, 17, 26, 24], [24, 25, 0, 14], [15, 13, 27, 16], [9, 30, 23, 4],
+ [31, 29, 7, 18], [28, 31, 18, 21], [30, 28, 21, 23]]),
+ ("CTP_4473",
+ mathutils.Vector((7.31539, 0.0, 0.0)),
+ [(0.24549, -1.0, 0.022454),
+ (-0.24549, -1.0, 0.022454),
+ (-0.24549, 1.0, 0.022454),
+ (0.24549, 1.0, 0.022454),
+ (1.0, 0.267452, 0.022454),
+ (1.0, -0.267452, 0.022454),
+ (-1.0, -0.267452, 0.022454),
+ (-1.0, 0.267452, 0.022454),
+ (0.24549, 0.267452, 0.022454),
+ (0.24549, -0.267452, 0.022454),
+ (-0.24549, 0.267452, 0.022454),
+ (-0.24549, -0.267452, 0.022454),
+ ],
+ [[8, 3, 2, 10], [0, 9, 11, 1], [4, 8, 9, 5], [8, 10, 11, 9], [10, 7, 6, 11]]),
+ ("CTP_4003",
+ mathutils.Vector((4.91276, 0.0, 0.0)),
+ [(-1.0, -1.0, 0.026945),
+ (1.0, -1.0, 0.026945),
+ (-1.0, 1.0, 0.026945),
+ (-0.026763, -1.0, 0.026945),
+ (-0.026763, 1.0, 0.026945),
+ (1.0, -0.026763, 0.026945),
+ (0.238983, 0.965014, 0.026945),
+ (0.486619, 0.86244, 0.026945),
+ (0.699268, 0.699268, 0.026945),
+ (0.86244, 0.486619, 0.026945),
+ (0.965014, 0.238983, 0.026945),
+ (0.238983, -1.0, 0.026945),
+ (0.486619, -1.0, 0.026945),
+ (0.699268, -1.0, 0.026945),
+ (0.86244, -1.0, 0.026945),
+ (-0.026763, 0.479676, 0.026945),
+ (0.486619, 0.479676, 0.026945),
+ (0.699268, 0.479676, 0.026945),
+ (0.238983, 0.479676, 0.026945),
+ (0.865316, 0.479676, 0.026945),
+ (-1.0, 0.479676, 0.026945),
+ (0.86244, 0.479676, 0.026945),
+ (-0.026763, 0.238983, 0.026945),
+ (0.486619, 0.238983, 0.026945),
+ (0.699268, 0.238983, 0.026945),
+ (0.238983, 0.238983, 0.026945),
+ (-1.0, 0.238983, 0.026945),
+ (0.86244, 0.238983, 0.026945),
+ (-0.026763, -0.026763, 0.026945),
+ (0.486619, -0.026763, 0.026945),
+ (0.699268, -0.026763, 0.026945),
+ (0.238983, -0.026763, 0.026945),
+ (-1.0, -0.026763, 0.026945),
+ (0.86244, -0.026763, 0.026945),
+ ],
+ [[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],
+ [19, 21, 27, 10], [16, 18, 25, 23], [17, 16, 23, 24], [20, 15, 4, 2], [21, 17, 24, 27], [27, 24, 30, 33],
+ [23, 25, 31, 29], [24, 23, 29, 30], [25, 22, 28, 31], [26, 22, 15, 20], [10, 27, 33, 5], [31, 28, 3, 11],
+ [33, 30, 13, 14], [29, 31, 11, 12], [5, 33, 14, 1], [30, 29, 12, 13], [32, 28, 22, 26]]),
+ ("CTP_3430",
+ mathutils.Vector((2.61824, 0.0, 0.0)),
+ [(-1.0, -1.0, 0.032334),
+ (1.0, -1.0, 0.032334),
+ (-1.0, 1.0, 0.032334),
+ (1.0, 1.0, 0.032334),
+ ],
+ [[0, 1, 3, 2]]),
+ ("CTP_7175",
+ mathutils.Vector((0.0, 0.0, 0.0)),
+ [(-1.0, -1.0, 0.032334),
+ (1.0, -1.0, 0.032334),
+ (-1.0, 1.0, 0.032334),
+ (1.0, 1.0, 0.032334),
+ (0.0, 0.0, 0.032334),
+ (0.0, 0.0, 0.032334),
+ (0.0, 0.0, 0.032334),
+ (0.0, 0.0, 0.032334),
+ (0.0, 0.0, 0.032334),
+ (-0.636126, 0.636126, 0.032334),
+ (-0.636126, -0.636126, 0.032334),
+ (0.636126, -0.636126, 0.032334),
+ (0.636126, 0.636126, 0.032334),
+ ],
+ [[10, 9, 2, 0], [11, 10, 0, 1], [12, 11, 1, 3], [9, 12, 3, 2]]),
+]
+
+# Cut Type
+RECTANGLE = 0
+LINE = 1
+CIRCLE = 2
+
+# Boolean operation
+DIFFERENCE = 0
+UNION = 1
+
+
+class CarverPrefs(bpy.types.AddonPreferences):
+ bl_idname = __name__
+
+ bpy.types.Scene.Enable_Tab_01 = bpy.props.BoolProperty(default=False)
+ bpy.types.Scene.Enable_Tab_02 = bpy.props.BoolProperty(default=False)
+
+ bpy.types.Scene.Key_Create = bpy.props.StringProperty(
+ name="Object creation",
+ description="Object creation",
+ maxlen=1,
+ default="C")
+ bpy.types.Scene.Key_Update = bpy.props.StringProperty(
+ name="Auto Bevel Update",
+ description="Auto Bevel Update",
+ maxlen=1,
+ default="A",
+ )
+ bpy.types.Scene.Key_Bool = bpy.props.StringProperty(
+ name="Boolean type",
+ description="Boolean operation type",
+ maxlen=1,
+ default="T",
+ )
+ bpy.types.Scene.Key_Brush = bpy.props.StringProperty(
+ name="Brush Mode",
+ description="Brush Mode",
+ maxlen=1,
+ default="B",
+ )
+ bpy.types.Scene.Key_Help = bpy.props.StringProperty(
+ name="Help display",
+ description="Help display",
+ maxlen=1,
+ default="H",
+ )
+ bpy.types.Scene.Key_Instant = bpy.props.StringProperty(
+ name="Instantiate",
+ description="Instantiate object",
+ maxlen=1,
+ default="I",
+ )
+ bpy.types.Scene.Key_Close = bpy.props.StringProperty(
+ name="Close polygonal shape",
+ description="Close polygonal shape",
+ maxlen=1,
+ default="X",
+ )
+ bpy.types.Scene.Key_Apply = bpy.props.StringProperty(
+ name="Apply operation",
+ description="Apply operation",
+ maxlen=1,
+ default="Q",
+ )
+ bpy.types.Scene.Key_Scale = bpy.props.StringProperty(
+ name="Scale object",
+ description="Scale object",
+ maxlen=1,
+ default="S",
+ )
+ bpy.types.Scene.Key_Gapy = bpy.props.StringProperty(
+ name="Gap rows",
+ description="Scale gap between columns",
+ maxlen=1,
+ default="J",
+ )
+ bpy.types.Scene.Key_Gapx = bpy.props.StringProperty(
+ name="Gap columns",
+ description="Scale gap between columns",
+ maxlen=1,
+ default="U",
+ )
+ bpy.types.Scene.Key_Depth = bpy.props.StringProperty(
+ name="Depth",
+ description="Cursor depth or solidify pattern",
+ maxlen=1,
+ default="D",
+ )
+ bpy.types.Scene.Key_Subadd = bpy.props.StringProperty(
+ name="Add subdivision",
+ description="Add subdivision",
+ maxlen=1,
+ default="X",
+ )
+ bpy.types.Scene.Key_Subrem = bpy.props.StringProperty(
+ name="Remove subdivision",
+ description="Remove subdivision",
+ maxlen=1,
+ default="W",
+ )
+ bpy.types.Scene.Key_Randrot = bpy.props.StringProperty(
+ name="Random rotation",
+ description="Random rotation",
+ maxlen=1,
+ default="R",
+ )
+
+ def draw(self, context):
+ scene = context.scene
+ layout = self.layout
+
+ layout.prop(context.scene, "Enable_Tab_01", text="Info", icon="QUESTION")
+ if scene.Enable_Tab_01:
+ row = layout.row()
+ layout.label(text="Carver Operator")
+ layout.label(text="Select object and [CTRL]+[SHIFT]+[X] to carve")
+
+ layout.prop(scene, "Enable_Tab_02", text="Keys", icon="KEYINGSET")
+ if scene.Enable_Tab_02:
+ split = layout.split()
+ col = split.column()
+ col.label("Object Creation:")
+ col.prop(scene, "Key_Create", text="")
+ col.label("Auto bevel update:")
+ col.prop(scene, "Key_Update", text="")
+ col.label("Boolean operation type:")
+ col.prop(scene, "Key_Bool", text="")
+
+ col = split.column()
+ col.label("Brush Mode:")
+ col.prop(scene, "Key_Brush", text="")
+ col.label("Help display:")
+ col.prop(scene, "Key_Help", text="")
+ col.label("Instantiate object:")
+ col.prop(scene, "Key_Instant", text="")
+
+ col = split.column()
+ col.label("Close polygonal shape:")
+ col.prop(scene, "Key_Close", text="")
+ col.label("Apply operation:")
+ col.prop(scene, "Key_Apply", text="")
+ col.label("Scale object:")
+ col.prop(scene, "Key_Scale", text="")
+
+ col = split.column()
+ col.label("Gap rows:")
+ col.prop(scene, "Key_Gapy", text="")
+ col.label("Gap columns:")
+ col.prop(scene, "Key_Gapx", text="")
+ col.label("Depth / Solidify:")
+ col.prop(scene, "Key_Depth", text="")
+
+ col = split.column()
+ col.label("Subdiv add:")
+ col.prop(scene, "Key_Subadd", text="")
+ col.label("Subdiv Remove:")
+ col.prop(scene, "Key_Subrem", text="")
+ col.label("Random rotation:")
+ col.prop(scene, "Key_Randrot", text="")
+
+
+# Draw Text (Center position)
+def DrawCenterText(text, xt, yt, Size, Color, self):
+ font_id = 0
+ # Decalage Ombre
+ Sshadow_x = 2
+ Sshadow_y = -2
+
+ blf.size(font_id, Size, 72)
+ blf.position(font_id, xt + Sshadow_x - blf.dimensions(font_id, text)[0] / 2, yt + Sshadow_y, 0)
+ bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
+
+ blf.draw(font_id, text)
+ blf.position(font_id, xt - blf.dimensions(font_id, text)[0] / 2, yt, 0)
+ if Color is not None:
+ mColor = mathutils.Color((Color[0], Color[1], Color[2]))
+ bgl.glColor4f(mColor.r, mColor.g, mColor.b, 1.0)
+ else:
+ bgl.glColor4f(1.0, 1.0, 1.0, 1.0)
+ blf.draw(font_id, text)
+
+
+# Draw text (Left position)
+def DrawLeftText(text, xt, yt, Size, Color, self):
+ font_id = 0
+ # Decalage Ombre
+ Sshadow_x = 2
+ Sshadow_y = -2
+
+ blf.size(font_id, Size, 72)
+ blf.position(font_id, xt + Sshadow_x, yt + Sshadow_y, 0)
+ bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
+ blf.draw(font_id, text)
+ blf.position(font_id, xt, yt, 0)
+ if Color is not None:
+ mColor = mathutils.Color((Color[0], Color[1], Color[2]))
+ bgl.glColor4f(mColor.r, mColor.g, mColor.b, 1.0)
+ else:
+ bgl.glColor4f(1.0, 1.0, 1.0, 1.0)
+ blf.draw(font_id, text)
+
+
+# Draw text (Right position)
+def DrawRightText(text, xt, yt, Size, Color, self):
+ font_id = 0
+ # Decalage Ombre
+ Sshadow_x = 2
+ Sshadow_y = -2
+
+ blf.size(font_id, Size, 72)
+ blf.position(font_id, xt + Sshadow_x - blf.dimensions(font_id, text)[0], yt + Sshadow_y, 0)
+ bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
+ blf.draw(font_id, text)
+ blf.position(font_id, xt - blf.dimensions(font_id, text)[0], yt, 0)
+ if Color is not None:
+ mColor = mathutils.Color((Color[0], Color[1], Color[2]))
+ bgl.glColor4f(mColor.r, mColor.g, mColor.b, 1.0)
+ else:
+ bgl.glColor4f(1.0, 1.0, 1.0, 1.0)
+ blf.draw(font_id, text)
+
+
+# Opengl draws
+def draw_callback_px(self, context):
+ font_id = 0
+ region = context.region
+
+ # Width screen
+ overlap = context.user_preferences.system.use_region_overlap
+ t_panel_width = 0
+ if overlap:
+ for region in context.area.regions:
+ if region.type == 'TOOLS':
+ t_panel_width = region.width
+
+ # Initial position
+ xt = int(region.width / 2.0)
+ yt = 130
+ if region.width >= 850:
+ xt = int(region.width / 2.0)
+ yt = 150
+
+ # Command Display
+ if self.CreateMode and ((self.ObjectMode == False) and (self.ProfileMode == False)):
+ BooleanMode = "Create"
+ else:
+ if self.ObjectMode or self.ProfileMode:
+ if self.BoolOps == DIFFERENCE:
+ BooleanType = "Difference) [T]"
+ else:
+ BooleanType = "Union) [T]"
+
+ if self.ObjectMode:
+ BooleanMode = "Object Brush (" + BooleanType
+ else:
+ BooleanMode = "Profil Brush (" + BooleanType
+ else:
+ if (self.shift == False) and (self.ForceRebool == False):
+ BooleanMode = "Difference"
+ else:
+ BooleanMode = "Rebool"
+
+ UIColor = (0.992, 0.5518, 0.0, 1.0)
+
+ # Display boolean mode
+ if region.width >= 850:
+ DrawCenterText(BooleanMode, xt, yt, 40, UIColor, self)
+ else:
+ DrawCenterText(BooleanMode, xt, yt, 20, UIColor, self)
+
+ # Separator (Line)
+ LineWidth = 75
+ if region.width >= 850:
+ LineWidth = 140
+ bgl.glLineWidth(1)
+ bgl.glColor4f(1.0, 1.0, 1.0, 1.0)
+ bgl.glBegin(bgl.GL_LINE_STRIP)
+ bgl.glVertex2i(int(xt - LineWidth), yt - 8)
+ bgl.glVertex2i(int(xt + LineWidth), yt - 8)
+ bgl.glEnd()
+
+ # Text position
+ xt = xt - blf.dimensions(font_id, "Difference")[0] / 2 + 80
+
+ # Primitives type
+ PrimitiveType = "Rectangle "
+ if self.CutMode == CIRCLE:
+ PrimitiveType = "Circle "
+ if self.CutMode == LINE:
+ PrimitiveType = "Line "
+
+ # Variables according to screen size
+ IFontSize = 12
+ yInterval = 20
+ xCmd = 0
+ yCmd = yt - 30
+ if region.width >= 850:
+ IFontSize = 18
+ yInterval = 25
+ xCmd = 100
+
+ # Color
+ Color0 = None
+ Color1 = UIColor
+
+ # Help Display
+ if (self.ObjectMode == False) and (self.ProfileMode == False):
+ TypeStr = "Cut Type [Space] : "
+ if self.CreateMode:
+ TypeStr = "Type [Space] : "
+ blf.size(font_id, IFontSize, 72)
+ OpsStr = TypeStr + PrimitiveType
+ TotalWidth = blf.dimensions(font_id, OpsStr)[0]
+ xLeft = region.width / 2 - TotalWidth / 2
+ xLeftP = xLeft + blf.dimensions(font_id, TypeStr)[0]
+ DrawLeftText(TypeStr, xLeft, yCmd, IFontSize, Color0, self)
+ DrawLeftText(PrimitiveType, xLeftP, yCmd, IFontSize, Color1, self)
+
+ # Depth Cursor
+ TypeStr = "Cursor Depth [" + context.scene.Key_Depth + "] : "
+ if self.snapCursor:
+ BoolStr = "(ON)"
+ else:
+ BoolStr = "(OFF)"
+ OpsStr = TypeStr + BoolStr
+ TotalWidth = blf.dimensions(font_id, OpsStr)[0]
+ xLeft = region.width / 2 - TotalWidth / 2
+ xLeftP = xLeft + blf.dimensions(font_id, TypeStr)[0]
+ DrawLeftText(TypeStr, xLeft, yCmd - yInterval, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, yCmd - yInterval, IFontSize, Color1, self)
+
+ if self.CreateMode == False:
+ # Apply Booleans
+ TypeStr = "Apply Operations [" + context.scene.Key_Apply + "] : "
+ if self.DontApply:
+ BoolStr = "(OFF)"
+ else:
+ BoolStr = "(ON)"
+ OpsStr = TypeStr + BoolStr
+ TotalWidth = blf.dimensions(font_id, OpsStr)[0]
+ xLeft = region.width / 2 - TotalWidth / 2
+ xLeftP = xLeft + blf.dimensions(font_id, TypeStr)[0]
+ DrawLeftText(TypeStr, xLeft, yCmd - yInterval * 2, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, yCmd - yInterval * 2, IFontSize, Color1, self)
+
+ # Auto update for bevel
+ TypeStr = "Bevel Update [" + context.scene.Key_Update + "] : "
+ if self.Auto_BevelUpdate:
+ BoolStr = "(ON)"
+ else:
+ BoolStr = "(OFF)"
+ OpsStr = TypeStr + BoolStr
+ TotalWidth = blf.dimensions(font_id, OpsStr)[0]
+ xLeft = region.width / 2 - TotalWidth / 2
+ xLeftP = xLeft + blf.dimensions(font_id, TypeStr)[0]
+ DrawLeftText(TypeStr, xLeft, yCmd - yInterval * 3, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, yCmd - yInterval * 3, IFontSize, Color1, self)
+
+ # Subdivisions
+ if self.CutMode == CIRCLE:
+ if self.CreateMode == False:
+ y = yCmd - yInterval * 4
+ else:
+ y = yCmd - yInterval * 2
+ TypeStr = "Subdivisions [" + context.scene.Key_Subrem + "][" + context.scene.Key_Subadd + "] : "
+ BoolStr = str((int(360 / self.stepAngle[self.step])))
+ OpsStr = TypeStr + BoolStr
+ TotalWidth = blf.dimensions(font_id, OpsStr)[0]
+ xLeft = region.width / 2 - TotalWidth / 2
+ xLeftP = xLeft + blf.dimensions(font_id, TypeStr)[0]
+ DrawLeftText(TypeStr, xLeft, y, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, y, IFontSize, Color1, self)
+
+ else:
+ #---INSTANTIATE:
+ TypeStr = "Instantiate [" + context.scene.Key_Instant + "] : "
+ if self.Instantiate:
+ BoolStr = "(ON)"
+ else:
+ BoolStr = "(OFF)"
+ OpsStr = TypeStr + BoolStr
+ blf.size(font_id, IFontSize, 72)
+ TotalWidth = blf.dimensions(font_id, OpsStr)[0]
+ xLeft = region.width / 2 - TotalWidth / 2
+ xLeftP = xLeft + blf.dimensions(font_id, TypeStr)[0]
+ DrawLeftText(TypeStr, xLeft, yCmd, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, yCmd, IFontSize, Color1, self)
+
+ #---RANDOM ROTATION:
+ if self.alt:
+ TypeStr = "Random Rotation [" + context.scene.Key_Randrot + "] : "
+ if self.RandomRotation:
+ BoolStr = "(ON)"
+ else:
+ BoolStr = "(OFF)"
+ OpsStr = TypeStr + BoolStr
+ blf.size(font_id, IFontSize, 72)
+ TotalWidth = blf.dimensions(font_id, OpsStr)[0]
+ xLeft = region.width / 2 - TotalWidth / 2
+ xLeftP = xLeft + blf.dimensions(font_id, TypeStr)[0]
+ DrawLeftText(TypeStr, xLeft, yCmd - yInterval, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, yCmd - yInterval, IFontSize, Color1, self)
+
+ #---THICKNESS:
+ if self.BrushSolidify:
+ TypeStr = "Thickness [" + context.scene.Key_Depth + "] : "
+ if self.ProfileMode:
+ BoolStr = str(round(self.ProfileBrush.modifiers["CT_SOLIDIFY"].thickness, 2))
+ if self.ObjectMode:
+ BoolStr = str(round(self.ObjectBrush.modifiers["CT_SOLIDIFY"].thickness, 2))
+ OpsStr = TypeStr + BoolStr
+ blf.size(font_id, IFontSize, 72)
+ TotalWidth = blf.dimensions(font_id, OpsStr)[0]
+ xLeft = region.width / 2 - TotalWidth / 2
+ xLeftP = xLeft + blf.dimensions(font_id, TypeStr)[0]
+ if self.alt:
+ DrawLeftText(TypeStr, xLeft, yCmd - yInterval * 2, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, yCmd - yInterval * 2, IFontSize, Color1, self)
+ else:
+ DrawLeftText(TypeStr, xLeft, yCmd - yInterval, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, yCmd - yInterval, IFontSize, Color1, self)
+
+ #---BRUSH DEPTH:
+ if (self.ObjectMode):
+ TypeStr = "Brush Depth [" + context.scene.Key_Depth + "] : "
+ BoolStr = str(round(self.ObjectBrush.data.vertices[0].co.z, 2))
+ OpsStr = TypeStr + BoolStr
+ blf.size(font_id, IFontSize, 72)
+ TotalWidth = blf.dimensions(font_id, OpsStr)[0]
+ xLeft = region.width / 2 - TotalWidth / 2
+ xLeftP = xLeft + blf.dimensions(font_id, TypeStr)[0]
+ if self.alt:
+ DrawLeftText(TypeStr, xLeft, yCmd - yInterval * 2, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, yCmd - yInterval * 2, IFontSize, Color1, self)
+ else:
+ DrawLeftText(TypeStr, xLeft, yCmd - yInterval, IFontSize, Color0, self)
+ DrawLeftText(BoolStr, xLeftP, yCmd - yInterval, IFontSize, Color1, self)
+
+ bgl.glEnable(bgl.GL_BLEND)
+ if region.width >= 850:
+ if self.AskHelp == False:
+ xrect = 40
+ yrect = 40
+ bgl.glColor4f(0.0, 0.0, 0.0, 0.3)
+ bgl.glRecti(xrect, yrect, xrect + 90, yrect + 25)
+ DrawLeftText("[" + context.scene.Key_Help + "] for help", xrect + 10, yrect + 8, 13, None, self)
+ else:
+ xHelp = 30 + t_panel_width
+ yHelp = 80
+ Help_FontSize = 12
+ Help_Interval = 14
+ if region.width >= 850:
+ Help_FontSize = 15
+ Help_Interval = 20
+ yHelp = 200
+
+ if self.ObjectMode or self.ProfileMode:
+ if self.ProfileMode:
+ DrawLeftText("[" + context.scene.Key_Brush + "]", xHelp, yHelp +
+ Help_Interval * 2, Help_FontSize, UIColor, self)
+ DrawLeftText(": Object Mode", 150 + t_panel_width, yHelp +
+ Help_Interval * 2, Help_FontSize, None, self)
+ else:
+ DrawLeftText("[" + context.scene.Key_Brush + "]", xHelp, yHelp +
+ Help_Interval * 2, Help_FontSize, UIColor, self)
+ DrawLeftText(": Return", 150 + t_panel_width, yHelp + Help_Interval * 2, Help_FontSize, None, self)
+ else:
+ DrawLeftText("[" + context.scene.Key_Brush + "]", xHelp, yHelp +
+ Help_Interval * 2, Help_FontSize, UIColor, self)
+ DrawLeftText(": Profil Brush", 150 + t_panel_width, yHelp +
+ Help_Interval * 2, Help_FontSize, None, self)
+ DrawLeftText("[Ctrl + LMB]", xHelp, yHelp - Help_Interval * 5, Help_FontSize, UIColor, self)
+ DrawLeftText(": Move Cursor", 150 + t_panel_width, yHelp -
+ Help_Interval * 5, Help_FontSize, None, self)
+
+ if (self.ObjectMode == False) and (self.ProfileMode == False):
+ if self.CreateMode == False:
+ DrawLeftText("[" + context.scene.Key_Create + "]", xHelp,
+ yHelp + Help_Interval, Help_FontSize, UIColor, self)
+ DrawLeftText(": Create geometry", 150 + t_panel_width,
+ yHelp + Help_Interval, Help_FontSize, None, self)
+ else:
+ DrawLeftText("[" + context.scene.Key_Create + "]", xHelp,
+ yHelp + Help_Interval, Help_FontSize, UIColor, self)
+ DrawLeftText(": Cut", 150 + t_panel_width, yHelp + Help_Interval, Help_FontSize, None, self)
+
+ if self.CutMode == RECTANGLE:
+ DrawLeftText("MouseMove", xHelp, yHelp, Help_FontSize, UIColor, self)
+ DrawLeftText("[Alt]", xHelp, yHelp - Help_Interval, Help_FontSize, UIColor, self)
+ DrawLeftText(": Dimension", 150 + t_panel_width, yHelp, Help_FontSize, None, self)
+ DrawLeftText(": Move all", 150 + t_panel_width, yHelp - Help_Interval, Help_FontSize, None, self)
+
+ if self.CutMode == CIRCLE:
+ DrawLeftText("MouseMove", xHelp, yHelp, Help_FontSize, UIColor, self)
+ DrawLeftText("[Alt]", xHelp, yHelp - Help_Interval, Help_FontSize, UIColor, self)
+ DrawLeftText("[" + context.scene.Key_Subrem + "] [" + context.scene.Key_Subadd + "]",
+ xHelp, yHelp - Help_Interval * 2, Help_FontSize, UIColor, self)
+ DrawLeftText("[Ctrl]", xHelp, yHelp - Help_Interval * 3, Help_FontSize, UIColor, self)
+ DrawLeftText(": Rotation and Radius", 150 + t_panel_width, yHelp, Help_FontSize, None, self)
+ DrawLeftText(": Move all", 150 + t_panel_width, yHelp - Help_Interval, Help_FontSize, None, self)
+ DrawLeftText(": Subdivision", 150 + t_panel_width, yHelp -
+ Help_Interval * 2, Help_FontSize, None, self)
+ DrawLeftText(": Incremental rotation", 150 + t_panel_width,
+ yHelp - Help_Interval * 3, Help_FontSize, None, self)
+
+ if self.CutMode == LINE:
+ DrawLeftText("MouseMove", xHelp, yHelp, Help_FontSize, UIColor, self)
+ DrawLeftText("[Alt]", xHelp, yHelp - Help_Interval, Help_FontSize, UIColor, self)
+ DrawLeftText("[Space]", xHelp, yHelp - Help_Interval * 2, Help_FontSize, UIColor, self)
+ DrawLeftText("[Ctrl]", xHelp, yHelp - Help_Interval * 3, Help_FontSize, UIColor, self)
+ DrawLeftText(": Dimension", 150 + t_panel_width, yHelp, Help_FontSize, None, self)
+ DrawLeftText(": Move all", 150 + t_panel_width, yHelp - Help_Interval, Help_FontSize, None, self)
+ DrawLeftText(": Validate", 150 + t_panel_width, yHelp -
+ Help_Interval * 2, Help_FontSize, None, self)
+ DrawLeftText(": Incremental", 150 + t_panel_width, yHelp -
+ Help_Interval * 3, Help_FontSize, None, self)
+ if self.CreateMode:
+ DrawLeftText("[" + context.scene.Key_Subadd + "]", xHelp, yHelp -
+ Help_Interval * 4, Help_FontSize, UIColor, self)
+ DrawLeftText(": Close geometry", 150 + t_panel_width, yHelp -
+ Help_Interval * 4, Help_FontSize, None, self)
+ else:
+ DrawLeftText("[Space]", xHelp, yHelp + Help_Interval, Help_FontSize, UIColor, self)
+ DrawLeftText(": Difference", 150 + t_panel_width, yHelp + Help_Interval, Help_FontSize, None, self)
+ DrawLeftText("[Shift][Space]", xHelp, yHelp, Help_FontSize, UIColor, self)
+ DrawLeftText(": Rebool", 150 + t_panel_width, yHelp, Help_FontSize, None, self)
+ DrawLeftText("[Alt][Space]", xHelp, yHelp - Help_Interval, Help_FontSize, UIColor, self)
+ DrawLeftText(": Duplicate", 150 + t_panel_width, yHelp - Help_Interval, Help_FontSize, None, self)
+ DrawLeftText("[" + context.scene.Key_Scale + "]", xHelp, yHelp -
+ Help_Interval * 2, Help_FontSize, UIColor, self)
+ DrawLeftText(": Scale", 150 + t_panel_width, yHelp - Help_Interval * 2, Help_FontSize, None, self)
+ DrawLeftText("[LMB][Move]", xHelp, yHelp - Help_Interval * 3, Help_FontSize, UIColor, self)
+ DrawLeftText(": Rotation", 150 + t_panel_width, yHelp - Help_Interval * 3, Help_FontSize, None, self)
+ DrawLeftText("[Ctrl][LMB][Move]", xHelp, yHelp - Help_Interval * 4, Help_FontSize, UIColor, self)
+ DrawLeftText(": Step Angle", 150 + t_panel_width, yHelp - Help_Interval * 4, Help_FontSize, None, self)
+ if self.ProfileMode:
+ DrawLeftText("[" + context.scene.Key_Subadd + "][" + context.scene.Key_Subrem + "]",
+ xHelp, yHelp - Help_Interval * 5, Help_FontSize, UIColor, self)
+ DrawLeftText(": Previous or Next Profile", 150 + t_panel_width,
+ yHelp - Help_Interval * 5, Help_FontSize, None, self)
+ DrawLeftText("[ARROWS]", xHelp, yHelp - Help_Interval * 6, Help_FontSize, UIColor, self)
+ DrawLeftText(": Create / Delete rows or columns", 150 + t_panel_width,
+ yHelp - Help_Interval * 6, Help_FontSize, None, self)
+ DrawLeftText("[" + context.scene.Key_Gapy + "][" + context.scene.Key_Gapx + "]",
+ xHelp, yHelp - Help_Interval * 7, Help_FontSize, UIColor, self)
+ DrawLeftText(": Gap between rows or columns", 150 + t_panel_width,
+ yHelp - Help_Interval * 7, Help_FontSize, None, self)
+
+ # Opengl Initialise
+ bgl.glEnable(bgl.GL_BLEND)
+ bgl.glColor4f(0.512, 0.919, 0.04, 1.0)
+ bgl.glLineWidth(2)
+
+# if context.space_data.region_3d.is_perspective == False:
+ if 1:
+ bgl.glEnable(bgl.GL_POINT_SMOOTH)
+
+ bgl.glPointSize(6)
+
+ if self.ProfileMode:
+ xrect = region.width - t_panel_width - 80
+ yrect = 80
+ bgl.glColor4f(0.0, 0.0, 0.0, 0.3)
+ bgl.glRecti(xrect, yrect, xrect + 60, yrect - 60)
+
+ faces = self.Profils[self.nProfil][3]
+ vertices = self.Profils[self.nProfil][2]
+ WidthProfil = 50
+ location = mathutils.Vector((region.width - t_panel_width - WidthProfil, 50, 0))
+ ProfilScale = 20.0
+ bgl.glColor4f(UIColor[0], UIColor[1], UIColor[2], 0.7)
+ for f in faces:
+ if len(f) == 4:
+ bgl.glBegin(bgl.GL_QUADS)
+ bgl.glVertex3f(vertices[f[0]][0] * ProfilScale + location.x, vertices[f[0]][1]
+ * ProfilScale + location.y, vertices[f[0]][2] * ProfilScale + location.z)
+ bgl.glVertex3f(vertices[f[1]][0] * ProfilScale + location.x, vertices[f[1]][1]
+ * ProfilScale + location.y, vertices[f[1]][2] * ProfilScale + location.z)
+ bgl.glVertex3f(vertices[f[2]][0] * ProfilScale + location.x, vertices[f[2]][1]
+ * ProfilScale + location.y, vertices[f[2]][2] * ProfilScale + location.z)
+ bgl.glVertex3f(vertices[f[3]][0] * ProfilScale + location.x, vertices[f[3]][1]
+ * ProfilScale + location.y, vertices[f[3]][2] * ProfilScale + location.z)
+ bgl.glEnd()
+ if len(f) == 3:
+ bgl.glBegin(bgl.GL_TRIANGLES)
+ bgl.glVertex3f(vertices[f[0]][0] * ProfilScale + location.x, vertices[f[0]][1]
+ * ProfilScale + location.y, vertices[f[0]][2] * ProfilScale + location.z)
+ bgl.glVertex3f(vertices[f[1]][0] * ProfilScale + location.x, vertices[f[1]][1]
+ * ProfilScale + location.y, vertices[f[1]][2] * ProfilScale + location.z)
+ bgl.glVertex3f(vertices[f[2]][0] * ProfilScale + location.x, vertices[f[2]][1]
+ * ProfilScale + location.y, vertices[f[2]][2] * ProfilScale + location.z)
+ bgl.glEnd()
+
+ if self.bDone:
+ if len(self.mouse_path) > 1:
+ x0 = self.mouse_path[0][0]
+ y0 = self.mouse_path[0][1]
+ x1 = self.mouse_path[1][0]
+ y1 = self.mouse_path[1][1]
+
+ # Cut Line
+ if self.CutMode == LINE:
+ if (self.shift) or (self.CreateMode and self.Closed):
+ bgl.glColor4f(UIColor[0], UIColor[1], UIColor[2], 0.5)
+
+ bgl.glBegin(bgl.GL_POLYGON)
+ for x, y in self.mouse_path:
+ bgl.glVertex2i(x + self.xpos, y + self.ypos)
+ bgl.glEnd()
+
+ bgl.glColor4f(UIColor[0], UIColor[1], UIColor[2], 1.0)
+ bgl.glBegin(bgl.GL_LINE_STRIP)
+ for x, y in self.mouse_path:
+ bgl.glVertex2i(x + self.xpos, y + self.ypos)
+ bgl.glEnd()
+ if (self.CreateMode == False) or (self.CreateMode and self.Closed):
+ bgl.glBegin(bgl.GL_LINE_STRIP)
+ bgl.glVertex2i(self.mouse_path[len(self.mouse_path) - 1][0] + self.xpos,
+ self.mouse_path[len(self.mouse_path) - 1][1] + self.ypos)
+ bgl.glVertex2i(self.mouse_path[0][0] + self.xpos, self.mouse_path[0][1] + self.ypos)
+ bgl.glEnd()
+
+ bgl.glPointSize(6)
+ bgl.glBegin(bgl.GL_POINTS)
+ for x, y in self.mouse_path:
+ bgl.glVertex2i(x + self.xpos, y + self.ypos)
+ bgl.glEnd()
+
+ # Cut rectangle
+ if self.CutMode == RECTANGLE:
+ bgl.glColor4f(UIColor[0], UIColor[1], UIColor[2], 0.5)
+
+ # if SHIFT, fill primitive
+ if self.shift or self.CreateMode:
+ bgl.glBegin(bgl.GL_QUADS)
+ bgl.glVertex2i(x0 + self.xpos, y0 + self.ypos)
+ bgl.glVertex2i(x1 + self.xpos, y0 + self.ypos)
+ bgl.glVertex2i(x1 + self.xpos, y1 + self.ypos)
+ bgl.glVertex2i(x0 + self.xpos, y1 + self.ypos)
+ bgl.glEnd()
+
+ bgl.glBegin(bgl.GL_LINE_STRIP)
+ bgl.glVertex2i(x0 + self.xpos, y0 + self.ypos)
+ bgl.glVertex2i(x1 + self.xpos, y0 + self.ypos)
+ bgl.glVertex2i(x1 + self.xpos, y1 + self.ypos)
+ bgl.glVertex2i(x0 + self.xpos, y1 + self.ypos)
+ bgl.glVertex2i(x0 + self.xpos, y0 + self.ypos)
+ bgl.glEnd()
+ bgl.glPointSize(6)
+
+ bgl.glColor4f(UIColor[0], UIColor[1], UIColor[2], 1.0)
+ bgl.glBegin(bgl.GL_POINTS)
+ bgl.glVertex2i(x0 + self.xpos, y0 + self.ypos)
+ bgl.glVertex2i(x1 + self.xpos, y0 + self.ypos)
+ bgl.glVertex2i(x1 + self.xpos, y1 + self.ypos)
+ bgl.glVertex2i(x0 + self.xpos, y1 + self.ypos)
+ bgl.glEnd()
+
+ # Circle Cut
+ if self.CutMode == CIRCLE:
+ DEG2RAD = 3.14159 / 180
+ v0 = mathutils.Vector((self.mouse_path[0][0], self.mouse_path[0][1], 0))
+ v1 = mathutils.Vector((self.mouse_path[1][0], self.mouse_path[1][1], 0))
+ v0 -= v1
+ radius = self.mouse_path[1][0] - self.mouse_path[0][0]
+ DEG2RAD = 3.14159 / (180.0 / self.stepAngle[self.step])
+ if self.ctrl:
+ self.stepR = (self.mouse_path[1][1] - self.mouse_path[0][1]) / 25
+ shift = (3.14159 / (360.0 / 60.0)) * int(self.stepR)
+ else:
+ shift = (self.mouse_path[1][1] - self.mouse_path[0][1]) / 50
+
+ if self.shift or self.CreateMode:
+ bgl.glColor4f(UIColor[0], UIColor[1], UIColor[2], 0.5)
+ bgl.glBegin(bgl.GL_TRIANGLE_FAN)
+ bgl.glVertex2f(x0 + self.xpos, y0 + self.ypos)
+ for i in range(0, int(360 / self.stepAngle[self.step])):
+ degInRad = i * DEG2RAD
+ bgl.glVertex2f(x0 + self.xpos + math.cos(degInRad + shift) * radius,
+ y0 + self.ypos + math.sin(degInRad + shift) * radius)
+ bgl.glVertex2f(x0 + self.xpos + math.cos(0 + shift) * radius,
+ y0 + self.ypos + math.sin(0 + shift) * radius)
+ bgl.glEnd()
+
+ bgl.glColor4f(UIColor[0], UIColor[1], UIColor[2], 1.0)
+ bgl.glBegin(bgl.GL_LINE_LOOP)
+ for i in range(0, int(360 / self.stepAngle[self.step])):
+ degInRad = i * DEG2RAD
+ bgl.glVertex2f(x0 + self.xpos + math.cos(degInRad + shift) * radius,
+ y0 + self.ypos + math.sin(degInRad + shift) * radius)
+ bgl.glEnd()
+
+ if self.ObjectMode or self.ProfileMode:
+ if self.ShowCursor:
+ region = context.region
+ rv3d = context.space_data.region_3d
+ view_width = context.region.width
+
+ if self.ObjectMode:
+ ob = self.ObjectBrush
+ if self.ProfileMode:
+ ob = self.ProfileBrush
+ mat = ob.matrix_world
+
+ # 50% alpha, 2 pixel width line
+ bgl.glEnable(bgl.GL_BLEND)
+
+ bbox = [mat * mathutils.Vector(b) for b in ob.bound_box]
+
+ if self.shift:
+ bgl.glLineWidth(4)
+ bgl.glColor4f(0.5, 1.0, 0.0, 1.0)
+ else:
+ bgl.glLineWidth(2)
+ bgl.glColor4f(1.0, 0.8, 0.0, 1.0)
+ bgl.glBegin(bgl.GL_LINE_STRIP)
+ idx = 0
+ CRadius = ((bbox[7] - bbox[0]).length) / 2
+ for i in range(int(len(self.CLR_C) / 3)):
+ vector3d = (self.CLR_C[idx * 3] * CRadius + self.CurLoc.x, self.CLR_C[idx * 3 + 1]
+ * CRadius + self.CurLoc.y, self.CLR_C[idx * 3 + 2] * CRadius + self.CurLoc.z)
+ vector2d = bpy_extras.view3d_utils.location_3d_to_region_2d(region, rv3d, vector3d)
+ if vector2d is not None:
+ bgl.glVertex2f(*vector2d)
+ idx += 1
+ bgl.glEnd()
+
+ bgl.glLineWidth(1)
+ bgl.glDisable(bgl.GL_BLEND)
+ bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
+
+ # Object display
+ if self.qRot is not None:
+ ob.location = self.CurLoc
+
+ e = mathutils.Euler()
+ e.x = 0.0
+ e.y = 0.0
+ e.z = self.aRotZ / 25.0
+
+ qe = e.to_quaternion()
+ qRot = self.qRot * qe
+ ob.rotation_mode = 'QUATERNION'
+ ob.rotation_quaternion = qRot
+ ob.rotation_mode = 'XYZ'
+
+ if self.ProfileMode:
+ if self.ProfileBrush is not None:
+ self.ProfileBrush.location = self.CurLoc
+ self.ProfileBrush.rotation_mode = 'QUATERNION'
+ self.ProfileBrush.rotation_quaternion = qRot
+ self.ProfileBrush.rotation_mode = 'XYZ'
+
+ # Opengl defaults
+ bgl.glLineWidth(1)
+ bgl.glDisable(bgl.GL_BLEND)
+ bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
+ bgl.glDisable(bgl.GL_POINT_SMOOTH)
+
+
+# Intersection
+# intersection function (ideasman42)
+def isect_line_plane_v3(p0, p1, p_co, p_no, epsilon=1e-6):
+ """
+ p0, p1: define the line
+ p_co, p_no: define the plane:
+ p_co is a point on the plane (plane coordinate).
+ p_no is a normal vector defining the plane direction; does not need to be normalized.
+
+ return a Vector or None (when the intersection can't be found).
+ """
+
+ u = sub_v3v3(p1, p0)
+ dot = dot_v3v3(p_no, u)
+
+ if abs(dot) > epsilon:
+ # the factor of the point between p0 -> p1 (0 - 1)
+ # if 'fac' is between (0 - 1) the point intersects with the segment.
+ # otherwise:
+ # < 0.0: behind p0.
+ # > 1.0: infront of p1.
+ w = sub_v3v3(p0, p_co)
+ fac = -dot_v3v3(p_no, w) / dot
+ u = mul_v3_fl(u, fac)
+ return add_v3v3(p0, u)
+ else:
+ # The segment is parallel to plane
+ return None
+
+# ----------------------
+# generic math functions
+
+
+def add_v3v3(v0, v1):
+ return (
+ v0[0] + v1[0],
+ v0[1] + v1[1],
+ v0[2] + v1[2],
+ )
+
+
+def sub_v3v3(v0, v1):
+ return (
+ v0[0] - v1[0],
+ v0[1] - v1[1],
+ v0[2] - v1[2],
+ )
+
+
+def dot_v3v3(v0, v1):
+ return (
+ (v0[0] * v1[0]) +
+ (v0[1] * v1[1]) +
+ (v0[2] * v1[2])
+ )
+
+
+def len_squared_v3(v0):
+ return dot_v3v3(v0, v0)
+
+
+def mul_v3_fl(v0, f):
+ return (
+ v0[0] * f,
+ v0[1] * f,
+ v0[2] * f,
+ )
+
+# Cut Square
+
+
+def CreateCutSquare(self, context):
+ FAR_LIMIT = 10000.0
+
+ # New mesh
+ me = bpy.data.meshes.new('CMT_Square')
+
+ # New object
+ ob = bpy.data.objects.new('CMT_Square', me)
+ # Save new object
+ self.CurrentObj = ob
+ # Scene informations
+ scene = context.scene
+ region = context.region
+ rv3d = context.region_data
+ coord = self.mouse_path[0][0], self.mouse_path[0][1]
+
+ depthLocation = region_2d_to_vector_3d(region, rv3d, coord)
+ self.ViewVector = depthLocation
+ if self.snapCursor:
+ PlanePoint = context.scene.cursor_location
+ else:
+ if self.OpsObj is not None:
+ PlanePoint = self.OpsObj.location
+ else:
+ PlanePoint = mathutils.Vector((0.0, 0.0, 0.0))
+
+ PlaneNormal = depthLocation
+ PlaneNormalised = PlaneNormal.normalized()
+ d = -PlanePoint.x * PlaneNormalised.x - PlanePoint.y * PlaneNormalised.y - PlanePoint.z * PlaneNormalised.z
+
+ # Link object to scene
+ context.scene.objects.link(ob)
+
+ # New bmesh
+ t_bm = bmesh.new()
+ t_bm.from_mesh(me)
+ # Convert in 3d space
+ v0 = self.mouse_path[0][0] + self.xpos, self.mouse_path[0][1] + self.ypos
+ v1 = self.mouse_path[1][0] + self.xpos, self.mouse_path[1][1] + self.ypos
+ v2 = self.mouse_path[1][0] + self.xpos, self.mouse_path[0][1] + self.ypos
+ v3 = self.mouse_path[0][0] + self.xpos, self.mouse_path[1][1] + self.ypos
+ vec = region_2d_to_vector_3d(region, rv3d, v0)
+ loc0 = region_2d_to_location_3d(region, rv3d, v0, vec)
+
+ vec = region_2d_to_vector_3d(region, rv3d, v1)
+ loc1 = region_2d_to_location_3d(region, rv3d, v1, vec)
+
+ vec = region_2d_to_vector_3d(region, rv3d, v2)
+ loc2 = region_2d_to_location_3d(region, rv3d, v2, vec)
+
+ vec = region_2d_to_vector_3d(region, rv3d, v3)
+ loc3 = region_2d_to_location_3d(region, rv3d, v3, vec)
+ p0 = loc0
+ p1 = loc0 + PlaneNormalised * FAR_LIMIT
+ loc0 = isect_line_plane_v3(p0, p1, PlanePoint, PlaneNormalised)
+ p0 = loc1
+ p1 = loc1 + PlaneNormalised * FAR_LIMIT
+ loc1 = isect_line_plane_v3(p0, p1, PlanePoint, PlaneNormalised)
+ p0 = loc2
+ p1 = loc2 + PlaneNormalised * FAR_LIMIT
+ loc2 = isect_line_plane_v3(p0, p1, PlanePoint, PlaneNormalised)
+ p0 = loc3
+ p1 = loc3 + PlaneNormalised * FAR_LIMIT
+ loc3 = isect_line_plane_v3(p0, p1, PlanePoint, PlaneNormalised)
+
+ t_v0 = t_bm.verts.new(loc0)
+ t_v1 = t_bm.verts.new(loc2)
+ t_v2 = t_bm.verts.new(loc1)
+ t_v3 = t_bm.verts.new(loc3)
+
+ # Update vertices index
+ t_bm.verts.index_update()
+ # New faces
+ t_face = t_bm.faces.new([t_v0, t_v1, t_v2, t_v3])
+ # Set mesh
+ t_bm.to_mesh(me)
+
+
+# Cut Line
+def CreateCutLine(self, context):
+ FAR_LIMIT = 10000.0
+
+ me = bpy.data.meshes.new('CMT_Line')
+
+ ob = bpy.data.objects.new('CMT_Line', me)
+ self.CurrentObj = ob
+
+ scene = context.scene
+ region = context.region
+ rv3d = context.region_data
+ coord = self.mouse_path[0][0], self.mouse_path[0][1]
+ depthLocation = region_2d_to_vector_3d(region, rv3d, coord)
+ self.ViewVector = depthLocation
+ if self.snapCursor:
+ PlanePoint = context.scene.cursor_location
+ else:
+ PlanePoint = mathutils.Vector((0.0, 0.0, 0.0))
+
+ PlaneNormal = depthLocation
+ PlaneNormalised = PlaneNormal.normalized()
+ d = -PlanePoint.x * PlaneNormalised.x - PlanePoint.y * PlaneNormalised.y - PlanePoint.z * PlaneNormalised.z
+
+ context.scene.objects.link(ob)
+
+ t_bm = bmesh.new()
+ t_bm.from_mesh(me)
+
+ FacesList = []
+ NbVertices = 0
+
+ bLine = False
+
+ if (len(self.mouse_path) == 2) or ((len(self.mouse_path) <= 3) and (self.mouse_path[1] == self.mouse_path[2])):
+ PlanePoint = mathutils.Vector((0.0, 0.0, 0.0))
+ PlaneNormal = depthLocation
+ PlaneNormalised = PlaneNormal.normalized()
+ # Force rebool
+ self.ForceRebool = True
+ # It's a line
+ bLine = True
+ Index = 0
+ for x, y in self.mouse_path:
+ if Index < 2:
+ v0 = x + self.xpos, y + self.ypos
+ vec = region_2d_to_vector_3d(region, rv3d, v0)
+ loc0 = region_2d_to_location_3d(region, rv3d, v0, vec)
+
+ p0 = loc0
+ p1 = loc0 + PlaneNormalised * FAR_LIMIT
+ loc0 = isect_line_plane_v3(p0, p1, PlanePoint, PlaneNormalised)
+
+ NbVertices += 1
+ Index += 1
+ if NbVertices == 1:
+ t_v0 = t_bm.verts.new(loc0)
+ t_init = t_v0
+ LocInit = loc0
+ t_bm.verts.index_update()
+ else:
+ t_v1 = t_bm.verts.new(loc0)
+ t_edges = t_bm.edges.new([t_v0, t_v1])
+ NbVertices = 1
+ t_v0 = t_v1
+
+ else:
+ for x, y in self.mouse_path:
+ v0 = x + self.xpos, y + self.ypos
+ vec = region_2d_to_vector_3d(region, rv3d, v0)
+ loc0 = region_2d_to_location_3d(region, rv3d, v0, vec)
+
+ p0 = loc0
+ p1 = loc0 + PlaneNormalised * FAR_LIMIT
+ loc0 = isect_line_plane_v3(p0, p1, PlanePoint, PlaneNormalised)
+
+ NbVertices += 1
+ if NbVertices == 1:
+ t_v0 = t_bm.verts.new(loc0)
+ t_init = t_v0
+ LocInit = loc0
+ t_bm.verts.index_update()
+ FacesList.append(t_v0)
+ else:
+ t_v1 = t_bm.verts.new(loc0)
+ t_edges = t_bm.edges.new([t_v0, t_v1])
+ FacesList.append(t_v1)
+ NbVertices = 1
+ t_v0 = t_v1
+
+ if self.CreateMode:
+ if self.Closed and (bLine == False):
+ t_v1 = t_bm.verts.new(LocInit)
+ t_edges = t_bm.edges.new([t_v0, t_v1])
+ FacesList.append(t_v1)
+ t_face = t_bm.faces.new(FacesList)
+ else:
+ if bLine == False:
+ t_v1 = t_bm.verts.new(LocInit)
+ t_edges = t_bm.edges.new([t_v0, t_v1])
+ FacesList.append(t_v1)
+ t_face = t_bm.faces.new(FacesList)
+
+ t_bm.to_mesh(me)
+
+
+# Cut Circle
+def CreateCutCircle(self, context):
+ FAR_LIMIT = 10000.0
+
+ me = bpy.data.meshes.new('CMT_Circle')
+
+ ob = bpy.data.objects.new('CMT_Circle', me)
+ self.CurrentObj = ob
+
+ scene = context.scene
+ region = context.region
+ rv3d = context.region_data
+ coord = self.mouse_path[0][0], self.mouse_path[0][1]
+ depthLocation = region_2d_to_vector_3d(region, rv3d, coord)
+ self.ViewVector = depthLocation
+ if self.snapCursor:
+ PlanePoint = context.scene.cursor_location
+ else:
+ PlanePoint = mathutils.Vector((0.0, 0.0, 0.0))
+
+ PlaneNormal = depthLocation
+ PlaneNormalised = PlaneNormal.normalized()
+ d = -PlanePoint.x * PlaneNormalised.x - PlanePoint.y * PlaneNormalised.y - PlanePoint.z * PlaneNormalised.z
+
+ context.scene.objects.link(ob)
+
+ t_bm = bmesh.new()
+ t_bm.from_mesh(me)
+
+ x0 = self.mouse_path[0][0]
+ y0 = self.mouse_path[0][1]
+ x1 = self.mouse_path[1][0]
+ y1 = self.mouse_path[1][1]
+
+ v0 = mathutils.Vector((self.mouse_path[0][0], self.mouse_path[0][1], 0))
+ v1 = mathutils.Vector((self.mouse_path[1][0], self.mouse_path[1][1], 0))
+ v0 -= v1
+ radius = self.mouse_path[1][0] - self.mouse_path[0][0]
+ DEG2RAD = math.pi / (180.0 / self.stepAngle[self.step])
+ if self.ctrl:
+ self.stepR = (self.mouse_path[1][1] - self.mouse_path[0][1]) / 25
+ shift = (math.pi / (360.0 / self.stepAngle[self.step])) * (self.stepR)
+ else:
+ shift = (self.mouse_path[1][1] - self.mouse_path[0][1]) / 50
+
+ # Convert point in 3D Space
+ FacesList = []
+ for i in range(0, int(360.0 / self.stepAngle[self.step])):
+ degInRad = i * DEG2RAD
+ v0 = x0 + self.xpos + math.cos(degInRad + shift) * radius, y0 + self.ypos + math.sin(degInRad + shift) * radius
+ vec = region_2d_to_vector_3d(region, rv3d, v0)
+ loc0 = region_2d_to_location_3d(region, rv3d, v0, vec)
+
+ p0 = loc0
+ p1 = loc0 + PlaneNormalised * FAR_LIMIT
+ loc0 = isect_line_plane_v3(p0, p1, PlanePoint, PlaneNormalised)
+
+ t_v0 = t_bm.verts.new(loc0)
+
+ FacesList.append(t_v0)
+
+ t_bm.verts.index_update()
+
+ t_face = t_bm.faces.new(FacesList)
+
+ t_bm.to_mesh(me)
+
+
+# Object dimensions (SCULPT Tools tips)
+def objDiagonal(obj):
+ return ((obj.dimensions[0]**2) + (obj.dimensions[1]**2) + (obj.dimensions[2]**2))**0.5
+
+
+# Bevel Update
+def update_bevel(context):
+ selection = context.selected_objects.copy()
+ active = context.active_object
+
+ if len(selection) > 0:
+ for obj in selection:
+ bpy.ops.object.select_all(action='DESELECT')
+ obj.select = True
+ context.scene.objects.active = obj
+
+ # Test object name
+ if obj.data.name.startswith("S_") or obj.data.name.startswith("S "):
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.region_to_loop()
+ bpy.ops.transform.edge_bevelweight(value=1)
+ bpy.ops.object.mode_set(mode='OBJECT')
+ else:
+ act_bevel = False
+ for mod in obj.modifiers:
+ if mod.type == 'BEVEL':
+ act_bevel = True
+ if act_bevel:
+ context.scene.objects.active = bpy.data.objects[obj.name]
+ active = obj
+
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Edge mode
+ bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
+
+ # Clear all
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.mark_sharp(clear=True)
+ bpy.ops.transform.edge_crease(value=-1)
+
+ bpy.ops.transform.edge_bevelweight(value=-1)
+ bpy.ops.mesh.select_all(action='DESELECT')
+ bpy.ops.mesh.edges_select_sharp(sharpness=0.523599)
+ bpy.ops.mesh.mark_sharp()
+ bpy.ops.transform.edge_crease(value=1)
+ bpy.ops.mesh.select_all(action='DESELECT')
+ bpy.ops.mesh.edges_select_sharp(sharpness=0.523599)
+ bpy.ops.transform.edge_bevelweight(value=1)
+ bpy.ops.mesh.select_all(action='DESELECT')
+
+ bpy.ops.object.mode_set(mode="OBJECT")
+
+ active.data.use_customdata_edge_bevel = True
+
+ for i in range(len(active.data.edges)):
+ if active.data.edges[i].select == True:
+ active.data.edges[i].bevel_weight = 1.0
+ active.data.edges[i].use_edge_sharp = True
+
+ Already = False
+ for m in active.modifiers:
+ if m.name == 'Bevel':
+ Already = True
+
+ if Already == False:
+ bpy.ops.object.modifier_add(type='BEVEL')
+ mod = context.object.modifiers[-1]
+ mod.limit_method = 'WEIGHT'
+ mod.width = 0.01
+ mod.profile = 0.699099
+ mod.use_clamp_overlap = False
+ mod.segments = 3
+ mod.loop_slide = False
+
+ bpy.ops.object.shade_smooth()
+
+ context.object.data.use_auto_smooth = True
+ context.object.data.auto_smooth_angle = 1.0472
+
+ bpy.ops.object.select_all(action='DESELECT')
+
+ for obj in selection:
+ obj.select = True
+ context.scene.objects.active = active
+
+# Create bevel
+
+
+def CreateBevel(context, CurrentObject):
+ # Save active object
+ SavActive = context.active_object
+ # Active "CurrentObject"
+ context.scene.objects.active = CurrentObject
+
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Edge mode
+ bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
+
+ # Clear all
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.mark_sharp(clear=True)
+ bpy.ops.transform.edge_crease(value=-1)
+
+ bpy.ops.transform.edge_bevelweight(value=-1)
+ bpy.ops.mesh.select_all(action='DESELECT')
+ bpy.ops.mesh.edges_select_sharp(sharpness=0.523599)
+ bpy.ops.mesh.mark_sharp()
+ bpy.ops.transform.edge_crease(value=1)
+ bpy.ops.mesh.select_all(action='DESELECT')
+ bpy.ops.mesh.edges_select_sharp(sharpness=0.523599)
+ bpy.ops.transform.edge_bevelweight(value=1)
+ bpy.ops.mesh.select_all(action='DESELECT')
+
+ bpy.ops.object.mode_set(mode="OBJECT")
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ Already = False
+ for m in CurrentObject.modifiers:
+ if m.name == 'Bevel':
+ Already = True
+
+ if Already == False:
+ bpy.ops.object.modifier_add(type='BEVEL')
+ mod = context.object.modifiers[-1]
+ mod.limit_method = 'WEIGHT'
+ mod.width = 0.01
+ mod.profile = 0.699099
+ mod.use_clamp_overlap = False
+ mod.segments = 3
+ mod.loop_slide = False
+
+ bpy.ops.object.shade_smooth()
+
+ context.object.data.use_auto_smooth = True
+ context.object.data.auto_smooth_angle = 1.0471975
+
+ # Remet l'objet actif par défaut
+ context.scene.objects.active = SavActive
+
+
+# Picking (template)
+def Picking(context, event):
+ # get the context arguments
+ scene = context.scene
+ region = context.region
+ rv3d = context.region_data
+ coord = event.mouse_region_x, event.mouse_region_y
+
+ # get the ray from the viewport and mouse
+ view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
+ ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
+
+ ray_target = ray_origin + view_vector
+
+ def visible_objects_and_duplis():
+ for obj in context.visible_objects:
+ if obj.type == 'MESH':
+ yield (obj, obj.matrix_world.copy())
+
+ if obj.dupli_type != 'NONE':
+ obj.dupli_list_create(scene)
+ for dob in obj.dupli_list:
+ obj_dupli = dob.object
+ if obj_dupli.type == 'MESH':
+ yield (obj_dupli, dob.matrix.copy())
+
+ obj.dupli_list_clear()
+
+ def obj_ray_cast(obj, matrix):
+ # get the ray relative to the object
+ matrix_inv = matrix.inverted()
+ ray_origin_obj = matrix_inv * ray_origin
+ ray_target_obj = matrix_inv * ray_target
+ ray_direction_obj = ray_target_obj - ray_origin_obj
+ # cast the ray
+ success, location, normal, face_index = obj.ray_cast(ray_origin_obj, ray_direction_obj)
+ if success:
+ return location, normal, face_index
+ else:
+ return None, None, None
+
+ # cast rays and find the closest object
+ best_length_squared = -1.0
+ best_obj = None
+
+ # cast rays and find the closest object
+ for obj, matrix in visible_objects_and_duplis():
+ if obj.type == 'MESH':
+ hit, normal, face_index = obj_ray_cast(obj, matrix)
+ if hit is not None:
+ hit_world = matrix * hit
+ length_squared = (hit_world - ray_origin).length_squared
+ if best_obj is None or length_squared < best_length_squared:
+ scene.cursor_location = hit_world
+ best_length_squared = length_squared
+ best_obj = obj
+ else:
+ if best_obj is None:
+ depthLocation = region_2d_to_vector_3d(region, rv3d, coord)
+ loc = region_2d_to_location_3d(region, rv3d, coord, depthLocation)
+ scene.cursor_location = loc
+
+
+def CreatePrimitive(self, _AngleStep, _radius):
+ CLRaw = []
+ Angle = 0.0
+ self.NbPointsInPrimitive = 0
+ while(Angle < 360.0):
+ self.CircleListRaw.append(math.cos(math.radians(Angle)) * _radius)
+ self.CircleListRaw.append(math.sin(math.radians(Angle)) * _radius)
+ self.CircleListRaw.append(0.0)
+ Angle += _AngleStep
+ self.NbPointsInPrimitive += 1
+ self.CircleListRaw.append(math.cos(math.radians(0.0)) * _radius)
+ self.CircleListRaw.append(math.sin(math.radians(0.0)) * _radius)
+ self.CircleListRaw.append(0.0)
+ self.NbPointsInPrimitive += 1
+
+
+def MoveCursor(qRot, location, self):
+ if qRot is not None:
+ self.CLR_C.clear()
+ vc = mathutils.Vector()
+ idx = 0
+ for i in range(int(len(self.CircleListRaw) / 3)):
+ vc.x = self.CircleListRaw[idx * 3] * self.CRadius
+ vc.y = self.CircleListRaw[idx * 3 + 1] * self.CRadius
+ vc.z = self.CircleListRaw[idx * 3 + 2] * self.CRadius
+ vc = qRot * vc
+ self.CLR_C.append(vc.x)
+ self.CLR_C.append(vc.y)
+ self.CLR_C.append(vc.z)
+ idx += 1
+
+
+def RBenVe(Object, Dir):
+ ObjectV = Object.normalized()
+ DirV = Dir.normalized()
+ cosTheta = ObjectV.dot(DirV)
+ rotationAxis = mathutils.Vector((0.0, 0.0, 0.0))
+ if (cosTheta < -1 + 0.001):
+ v = mathutils.Vector((0.0, 1.0, 0.0))
+ rotationAxis = ObjectV.cross(v)
+ rotationAxis = rotationAxis.normalized()
+ q = mathutils.Quaternion()
+ q.w = 0.0
+ q.x = rotationAxis.x
+ q.y = rotationAxis.y
+ q.z = rotationAxis.z
+ return q
+ rotationAxis = ObjectV.cross(DirV)
+ s = math.sqrt((1.0 + cosTheta) * 2.0)
+ invs = 1 / s
+ q = mathutils.Quaternion()
+ q.w = s * 0.5
+ q.x = rotationAxis.x * invs
+ q.y = rotationAxis.y * invs
+ q.z = rotationAxis.z * invs
+ return q
+
+
+def Pick(context, event, self, ray_max=10000.0):
+ scene = context.scene
+ region = context.region
+ rv3d = context.region_data
+ coord = event.mouse_region_x, event.mouse_region_y
+ view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
+ ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
+ ray_target = ray_origin + (view_vector * ray_max)
+
+ def obj_ray_cast(obj, matrix):
+ matrix_inv = matrix.inverted()
+ ray_origin_obj = matrix_inv * ray_origin
+ ray_target_obj = matrix_inv * ray_target
+ success, hit, normal, face_index = obj.ray_cast(ray_origin_obj, ray_target_obj)
+ if success:
+ return hit, normal, face_index
+ else:
+ return None, None, None
+
+ best_length_squared = ray_max * ray_max
+ best_obj = None
+ for obj in self.CList:
+ matrix = obj.matrix_world
+ hit, normal, face_index = obj_ray_cast(obj, matrix)
+ if hit is not None:
+ hit_world = matrix * hit
+ length_squared = (hit_world - ray_origin).length_squared
+ if length_squared < best_length_squared:
+ best_length_squared = length_squared
+ best_obj = obj
+ hits = hit_world
+ ns = normal
+ fs = face_index
+
+ if best_obj is not None:
+ return hits, ns, fs
+ else:
+ return None, None, None
+
+
+def SelectObject(self, copyobj):
+ copyobj.select = True
+
+ for child in copyobj.children:
+ SelectObject(self, child)
+
+ if copyobj.parent is None:
+ bpy.context.scene.objects.active = copyobj
+
+
+# Undo
+def printUndo(self):
+ for l in self.UList:
+ print(l)
+
+
+def UndoAdd(self, type, OpsObj):
+ if OpsObj is None:
+ return
+ if type != "DUPLICATE":
+ ob = OpsObj
+ # Creation du mesh de 'sauvegarde'
+ bm = bmesh.new()
+ bm.from_mesh(ob.data)
+
+ self.UndoOps.append((OpsObj, type, bm))
+ else:
+ self.UndoOps.append((OpsObj, type, None))
+
+
+def UndoListUpdate(self):
+ self.UList.append((self.UndoOps.copy()))
+ self.UList_Index += 1
+ self.UndoOps.clear()
+
+
+def Undo(self):
+ if self.UList_Index < 0:
+ return
+ # get previous mesh
+ for o in self.UList[self.UList_Index]:
+ if o[1] == "MESH":
+ bm = o[2]
+ bm.to_mesh(o[0].data)
+
+ SelectObjList = bpy.context.selected_objects.copy()
+ Active_Obj = bpy.context.active_object
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ for o in self.UList[self.UList_Index]:
+ if o[1] == "REBOOL":
+ o[0].select = True
+ o[0].hide = False
+
+ if o[1] == "DUPLICATE":
+ o[0].select = True
+ o[0].hide = False
+
+ bpy.ops.object.delete(use_global=False)
+
+ for so in SelectObjList:
+ bpy.data.objects[so.name].select = True
+ bpy.context.scene.objects.active = Active_Obj
+
+ self.UList_Index -= 1
+ self.UList[self.UList_Index + 1:] = []
+
+
+def duplicateObject(self):
+ if self.Instantiate:
+ bpy.ops.object.duplicate_move_linked(
+ OBJECT_OT_duplicate={
+ "linked": True,
+ "mode": 'TRANSLATION',
+ },
+ TRANSFORM_OT_translate={
+ "value": (0, 0, 0),
+ },
+ )
+ else:
+ bpy.ops.object.duplicate_move(
+ OBJECT_OT_duplicate={
+ "linked": False,
+ "mode": 'TRANSLATION',
+ },
+ TRANSFORM_OT_translate={
+ "value": (0, 0, 0),
+ },
+ )
+
+ ob_new = bpy.context.active_object
+
+ ob_new.location = self.CurLoc
+ if self.ObjectMode:
+ ob_new.scale = self.ObjectBrush.scale
+ if self.ProfileMode:
+ ob_new.scale = self.ProfileBrush.scale
+
+ e = mathutils.Euler()
+ e.x = e.y = 0.0
+ e.z = self.aRotZ / 25.0
+
+#---If duplicate with a grid, no random rotation (each mesh in the grid is already rotated randomly)
+ if (self.alt == True) and ((self.nbcol + self.nbrow) < 3):
+ if self.RandomRotation:
+ e.z += random.random()
+
+ qe = e.to_quaternion()
+ qRot = self.qRot * qe
+ ob_new.rotation_mode = 'QUATERNION'
+ ob_new.rotation_quaternion = qRot
+ ob_new.rotation_mode = 'XYZ'
+
+ if (ob_new.draw_type == "WIRE") and (self.BrushSolidify == False):
+ ob_new.hide = True
+
+ if self.BrushSolidify:
+ ob_new.draw_type = "SOLID"
+ ob_new.show_x_ray = False
+
+ for o in bpy.context.selected_objects:
+ UndoAdd(self, "DUPLICATE", o)
+
+ if len(bpy.context.selected_objects) > 0:
+ bpy.ops.object.select_all(action='TOGGLE')
+ for o in self.SavSel:
+ o.select = True
+
+ bpy.context.scene.objects.active = self.OpsObj
+
+
+def update_grid(self, context):
+ """
+ Thanks to batFINGER for his help :
+ source : http://blender.stackexchange.com/questions/55864/multiple-meshes-not-welded-with-pydata
+ """
+ verts = []
+ edges = []
+ faces = []
+ numface = 0
+
+ if self.nbcol < 1:
+ self.nbcol = 1
+ if self.nbrow < 1:
+ self.nbrow = 1
+ if self.gapx < 0:
+ self.gapx = 0
+ if self.gapy < 0:
+ self.gapy = 0
+
+#---Get the data from the profils or the object
+ if self.ProfileMode:
+ brush = bpy.data.objects.new(self.Profils[self.nProfil][0], bpy.data.meshes[self.Profils[self.nProfil][0]])
+ obj = bpy.data.objects["CT_Profil"]
+ obfaces = brush.data.polygons
+ obverts = brush.data.vertices
+ lenverts = len(obverts)
+ else:
+ brush = bpy.data.objects["CarverBrushCopy"]
+ obj = context.selected_objects[0]
+ obverts = brush.data.vertices
+ obfaces = brush.data.polygons
+ lenverts = len(brush.data.vertices)
+
+#--Gap between each row / column
+ gapx = self.gapx
+ gapy = self.gapy
+
+#--Width of each row / column
+ widthx = brush.dimensions.x * self.scale_x
+ widthy = brush.dimensions.y * self.scale_y
+
+#--Compute the corners so the new object will be always at the center
+ left = -((self.nbcol - 1) * (widthx + gapx)) / 2
+ start = -((self.nbrow - 1) * (widthy + gapy)) / 2
+
+ for i in range(self.nbrow * self.nbcol):
+ row = i % self.nbrow
+ col = i // self.nbrow
+ startx = left + ((widthx + gapx) * col)
+ starty = start + ((widthy + gapy) * row)
+
+ #---Add random rotation
+ if (self.RandomRotation) and not (self.GridScaleX or self.GridScaleY):
+ rotmat = mathutils.Matrix.Rotation(math.radians(360 * random.random()), 4, 'Z')
+ for v in obverts:
+ v.co = v.co * rotmat
+
+ verts.extend([((v.co.x - startx, v.co.y - starty, v.co.z)) for v in obverts])
+ faces.extend([[v + numface * lenverts for v in p.vertices] for p in obfaces])
+ numface += 1
+
+#---Update the mesh
+ # Create mesh data
+ mymesh = bpy.data.meshes.new("CT_Profil")
+ # Generate mesh data
+ mymesh.from_pydata(verts, edges, faces)
+ # Calculate the edges
+ mymesh.update(calc_edges=True)
+ # Update data
+ obj.data = mymesh
+ # Make the the object the active one to remove double
+ context.scene.objects.active = obj
+
+
+def boolean_difference():
+ ActiveObj = bpy.context.active_object
+
+ if bpy.context.selected_objects[0] != bpy.context.active_object:
+ bpy.ops.object.modifier_apply(apply_as='DATA', modifier="CT_SOLIDIFY")
+ BoolMod = ActiveObj.modifiers.new("CT_" + bpy.context.selected_objects[0].name, "BOOLEAN")
+ BoolMod.object = bpy.context.selected_objects[0]
+ BoolMod.operation = "DIFFERENCE"
+ bpy.context.selected_objects[0].draw_type = 'WIRE'
+ else:
+ BoolMod = ActiveObj.modifiers.new("CT_" + bpy.context.selected_objects[1].name, "BOOLEAN")
+ BoolMod.object = bpy.context.selected_objects[1]
+ BoolMod.operation = "DIFFERENCE"
+ bpy.context.selected_objects[1].draw_type = 'WIRE'
+
+
+def boolean_union():
+ ActiveObj = bpy.context.active_object
+
+ if bpy.context.selected_objects[0] != bpy.context.active_object:
+ BoolMod = ActiveObj.modifiers.new("CT_" + bpy.context.selected_objects[0].name, "BOOLEAN")
+ BoolMod.object = bpy.context.selected_objects[0]
+ BoolMod.operation = "UNION"
+ bpy.context.selected_objects[0].draw_type = 'WIRE'
+ else:
+ BoolMod = ActiveObj.modifiers.new("CT_" + bpy.context.selected_objects[1].name, "BOOLEAN")
+ BoolMod.object = bpy.context.selected_objects[1]
+ BoolMod.operation = "UNION"
+ bpy.context.selected_objects[1].draw_type = 'WIRE'
+
+
+def Rebool(context, self):
+ SelObj_Name = []
+ BoolObj = []
+
+ LastObj = context.active_object
+
+ Brush = context.selected_objects[0]
+ Brush.draw_type = "WIRE"
+ obj = context.selected_objects[1]
+
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ context.scene.objects.active = obj
+ obj.draw_type = "SOLID"
+ obj.select = True
+ bpy.ops.object.duplicate_move(
+ OBJECT_OT_duplicate={
+ "linked": False,
+ "mode": 'TRANSLATION',
+ },
+ TRANSFORM_OT_translate={
+ "value": (0, 0, 0),
+ "constraint_axis": (False, False, False),
+ "constraint_orientation": 'GLOBAL',
+ "mirror": False,
+ "proportional": 'DISABLED',
+ "proportional_edit_falloff": 'SMOOTH',
+ "proportional_size": 1,
+ "snap": False,
+ "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0),
+ "snap_align": False,
+ "snap_normal": (0, 0, 0),
+ "gpencil_strokes": False,
+ "texture_space": False,
+ "remove_on_cancel": False,
+ "release_confirm": False,
+ },
+ )
+ LastObjectCreated = context.active_object
+
+ m = LastObjectCreated.modifiers.new("CT_INTERSECT", "BOOLEAN")
+ m.operation = "INTERSECT"
+ m.object = Brush
+
+ m = obj.modifiers.new("CT_DIFFERENCE", "BOOLEAN")
+ m.operation = "DIFFERENCE"
+ m.object = Brush
+
+ for mb in LastObj.modifiers:
+ if mb.type == 'BEVEL':
+ mb.show_viewport = False
+
+ if self.ObjectBrush or self.ProfileBrush:
+ LastObjectCreated.show_x_ray = False
+ try:
+ bpy.ops.object.modifier_apply(apply_as='DATA', modifier="CT_SOLIDIFY")
+ except:
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ self.report({'ERROR'}, str(exc_value))
+
+ if self.DontApply == False:
+ try:
+ bpy.ops.object.modifier_apply(apply_as='DATA', modifier="CT_INTERSECT")
+ except:
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ self.report({'ERROR'}, str(exc_value))
+
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ for mb in LastObj.modifiers:
+ if mb.type == 'BEVEL':
+ mb.show_viewport = True
+
+ context.scene.objects.active = obj
+ obj.select = True
+ if self.DontApply == False:
+ try:
+ bpy.ops.object.modifier_apply(apply_as='DATA', modifier="CT_DIFFERENCE")
+ except:
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ self.report({'ERROR'}, str(exc_value))
+
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ LastObjectCreated.select = True
+
+
+def createMeshFromData(self):
+ if self.Profils[self.nProfil][0] not in bpy.data.meshes:
+ # Create mesh and object
+ me = bpy.data.meshes.new(self.Profils[self.nProfil][0])
+ # Create mesh from given verts, faces.
+ me.from_pydata(self.Profils[self.nProfil][2], [], self.Profils[self.nProfil][3])
+ # Update mesh with new data
+ me.update()
+
+ if "CT_Profil" not in bpy.data.objects:
+ ob = bpy.data.objects.new("CT_Profil", bpy.data.meshes[self.Profils[self.nProfil][0]])
+ ob.location = mathutils.Vector((0.0, 0.0, 0.0))
+
+ # Link object to scene and make active
+ scn = bpy.context.scene
+ scn.objects.link(ob)
+ scn.objects.active = ob
+ ob.select = True
+ ob.location = mathutils.Vector((10000.0, 0.0, 0.0))
+ ob.draw_type = "WIRE"
+
+ self.SolidifyPossible = True
+ else:
+ bpy.data.objects["CT_Profil"].data = bpy.data.meshes[self.Profils[self.nProfil][0]]
+
+
+def Selection_Save(self):
+ self.SavSel = bpy.context.selected_objects.copy()
+ self.Sav_ac = bpy.context.active_object
+
+
+def Selection_Restore(self):
+ for o in self.SavSel:
+ o.select = True
+ bpy.context.scene.objects.active = self.Sav_ac
+
+
+# Modal Operator
+class Carver(bpy.types.Operator):
+ bl_idname = "object.carver"
+ bl_label = "Carver"
+ bl_description = "Cut or create in object mode"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ #---------------------------------------------------------------------------------------------------
+ @classmethod
+ def poll(cls, context):
+ ob = None
+ if len(context.selected_objects) > 0:
+ ob = context.selected_objects[0]
+ # Test if selected object or none (for create mode)
+ return (
+ (ob and ob.type == 'MESH' and context.mode == 'OBJECT') or
+ (context.mode == 'OBJECT' and ob is None) or
+ (context.mode == 'EDIT_MESH'))
+ #---------------------------------------------------------------------------------------------------
+
+ #---------------------------------------------------------------------------------------------------
+ def modal(self, context, event):
+ PI = 3.14156
+
+ region_types = {'WINDOW', 'UI'}
+ win = context.window
+ for area in win.screen.areas:
+ if area.type in ('VIEW_3D'):
+ for region in area.regions:
+ if not region_types or region.type in region_types:
+ region.tag_redraw()
+
+ if event.type in {
+ 'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE',
+ 'NUMPAD_1', 'NUMPAD_2', 'NUMPAD_3', 'NUMPAD_4', 'NUMPAD_6',
+ 'NUMPAD_7', 'NUMPAD_8', 'NUMPAD_9', 'NUMPAD_5'}:
+ return {'PASS_THROUGH'}
+ try:
+ # [Shift]
+ self.shift = False
+ if event.shift:
+ self.shift = True
+
+ # [Ctrl]
+ self.ctrl = False
+ if event.ctrl:
+ self.ctrl = True
+
+ # [Alt]
+ self.alt = False
+ if event.alt:
+ if self.InitPosition == False:
+ # Initialise position variable for start position
+ self.xpos = 0
+ self.ypos = 0
+ self.last_mouse_region_x = event.mouse_region_x
+ self.last_mouse_region_y = event.mouse_region_y
+ self.InitPosition = True
+ self.alt = True
+ # [Alt] release
+ if self.InitPosition and self.alt == False:
+ # Update coordonnee
+ for i in range(0, len(self.mouse_path)):
+ l = list(self.mouse_path[i])
+ l[0] += self.xpos
+ l[1] += self.ypos
+ self.mouse_path[i] = tuple(l)
+
+ self.xpos = self.ypos = 0
+ self.InitPosition = False
+
+ # Mode change (cut type)
+ if event.type == 'SPACE' and event.value == 'PRESS':
+ if self.ObjectMode or self.ProfileMode:
+ # If grid, remove double with intersect meshes
+ if ((self.nbcol + self.nbrow) > 3):
+ # Go in edit mode mode
+ bpy.ops.object.mode_set(mode='EDIT')
+ # Remove duplicate vertices
+ bpy.ops.mesh.remove_doubles()
+ # Return in object mode
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ if self.alt:
+ # Save selected objects
+ self.SavSel = context.selected_objects.copy()
+ if len(context.selected_objects) > 0:
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ if self.ObjectMode:
+ SelectObject(self, self.ObjectBrush)
+ else:
+ SelectObject(self, self.ProfileBrush)
+ duplicateObject(self)
+ else:
+ # Brush Cut
+ self.Cut()
+ # Save selected objects
+ if self.ObjectMode:
+ if len(self.ObjectBrush.children) > 0:
+ self.SavSel = context.selected_objects.copy()
+ if len(context.selected_objects) > 0:
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ if self.ObjectMode:
+ SelectObject(self, self.ObjectBrush)
+ else:
+ SelectObject(self, self.ProfileBrush)
+ duplicateObject(self)
+
+ UndoListUpdate(self)
+
+ # Save cursor position
+ self.SavMousePos = self.CurLoc
+ else:
+ if self.bDone == False:
+ # Cut Mode
+ self.CutMode += 1
+ if self.CutMode > 2:
+ self.CutMode = 0
+ else:
+ if self.CutMode == LINE:
+ # Cuts creation
+ CreateCutLine(self, context)
+ if self.CreateMode:
+ # Object creation
+ self.CreateGeometry()
+ bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+ # Cursor Snap
+ context.scene.DepthCursor = self.snapCursor
+ # Object Instantiate
+ context.scene.OInstanciate = self.Instantiate
+ # Random rotation
+ context.scene.ORandom = self.RandomRotation
+
+ return {'FINISHED'}
+ else:
+ # Cut
+ self.Cut()
+ UndoListUpdate(self)
+
+ # Object creation
+ if event.type == context.scene.Key_Create and event.value == 'PRESS':
+ if self.ExclusiveCreateMode == False:
+ self.CreateMode = not self.CreateMode
+
+ # Auto Bevel Update
+ if event.type == context.scene.Key_Update and event.value == 'PRESS':
+ self.Auto_BevelUpdate = not self.Auto_BevelUpdate
+
+ # Boolean operation type
+ if event.type == context.scene.Key_Bool and event.value == 'PRESS':
+ if (self.ProfileMode == True) or (self.ObjectMode == True):
+ if self.BoolOps == DIFFERENCE:
+ self.BoolOps = UNION
+ else:
+ self.BoolOps = DIFFERENCE
+
+ # Brush Mode
+ if event.type == context.scene.Key_Brush and event.value == 'PRESS':
+ self.DontApply = False
+ if (self.ProfileMode == False) and (self.ObjectMode == False):
+ self.ProfileMode = True
+ else:
+ self.ProfileMode = False
+ if self.ObjectBrush is not None:
+ if self.ObjectMode == False:
+ self.ObjectMode = True
+ self.BrushSolidify = False
+ self.CList = self.OB_List
+
+ if "CT_Profil" in bpy.data.objects:
+ Selection_Save(self)
+ bpy.ops.object.select_all(action='DESELECT')
+ bpy.data.objects["CT_Profil"].select = True
+ context.scene.objects.active = bpy.data.objects["CT_Profil"]
+ bpy.ops.object.delete(use_global=False)
+ Selection_Restore(self)
+
+ context.scene.nProfile = self.nProfil
+
+ else:
+ self.ObjectMode = False
+ else:
+ self.BrushSolidify = False
+
+ if "CT_Profil" in bpy.data.objects:
+ Selection_Save(self)
+ bpy.ops.object.select_all(action='DESELECT')
+ bpy.data.objects["CT_Profil"].select = True
+ context.scene.objects.active = bpy.data.objects["CT_Profil"]
+ bpy.ops.object.delete(use_global=False)
+ Selection_Restore(self)
+
+ if self.ProfileMode:
+ createMeshFromData(self)
+ self.ProfileBrush = bpy.data.objects["CT_Profil"]
+ Selection_Save(self)
+ self.BrushSolidify = True
+
+ bpy.ops.object.select_all(action='TOGGLE')
+ self.ProfileBrush.select = True
+ context.scene.objects.active = self.ProfileBrush
+ # Set xRay
+ self.ProfileBrush.show_x_ray = True
+
+ bpy.ops.object.modifier_add(type='SOLIDIFY')
+ context.object.modifiers["Solidify"].name = "CT_SOLIDIFY"
+
+ context.object.modifiers["CT_SOLIDIFY"].thickness = 0.1
+
+ Selection_Restore(self)
+
+ self.CList = self.CurrentSelection
+ else:
+ if self.ObjectBrush is not None:
+ if self.ObjectMode == False:
+ if self.ObjectBrush is not None:
+ self.ObjectBrush.location = self.InitBrushPosition
+ self.ObjectBrush.scale = self.InitBrushScale
+ self.ObjectBrush.rotation_quaternion = self.InitBrushQRotation
+ self.ObjectBrush.rotation_euler = self.InitBrushERotation
+ self.ObjectBrush.draw_type = self.ObjectBrush_DT
+ self.ObjectBrush.show_x_ray = self.XRay
+
+ # Remove solidify modifier
+ Selection_Save(self)
+ self.BrushSolidify = False
+
+ bpy.ops.object.select_all(action='TOGGLE')
+ self.ObjectBrush.select = True
+ context.scene.objects.active = self.ObjectBrush
+
+ bpy.ops.object.modifier_remove(modifier="CT_SOLIDIFY")
+
+ Selection_Restore(self)
+ else:
+
+ if self.Solidify_Active_Start:
+ Selection_Save(self)
+ self.BrushSolidify = True
+ self.SolidifyPossible = True
+ bpy.ops.object.select_all(action='TOGGLE')
+ self.ObjectBrush.select = True
+ context.scene.objects.active = self.ObjectBrush
+ # Set xRay
+ self.ObjectBrush.show_x_ray = True
+ bpy.ops.object.modifier_add(type='SOLIDIFY')
+ context.object.modifiers["Solidify"].name = "CT_SOLIDIFY"
+ context.object.modifiers["CT_SOLIDIFY"].thickness = 0.1
+ Selection_Restore(self)
+
+ # Help display
+ if event.type == context.scene.Key_Help and event.value == 'PRESS':
+ self.AskHelp = not self.AskHelp
+
+ # Instantiate object
+ if event.type == context.scene.Key_Instant and event.value == 'PRESS':
+ self.Instantiate = not self.Instantiate
+
+ # Close polygonal shape
+ if event.type == context.scene.Key_Close and event.value == 'PRESS':
+ if self.CreateMode:
+ self.Closed = not self.Closed
+
+ if event.type == context.scene.Key_Apply and event.value == 'PRESS':
+ self.DontApply = not self.DontApply
+
+ # Scale object
+ if event.type == context.scene.Key_Scale and event.value == 'PRESS':
+ if self.ObjectScale == False:
+ elf.am = event.mouse_region_x, event.mouse_regiony
+ self.ObjectScale = True
+
+ # Grid : Add column
+ if event.type == 'UP_ARROW' and event.value == 'PRESS':
+ self.nbcol += 1
+ update_grid(self, context)
+
+ # Grid : Add row
+ elif event.type == 'RIGHT_ARROW' and event.value == 'PRESS':
+ self.nbrow += 1
+ update_grid(self, context)
+
+ # Grid : Delete column
+ elif event.type == 'DOWN_ARROW' and event.value == 'PRESS':
+ self.nbcol -= 1
+ update_grid(self, context)
+
+ # Grid : Delete row
+ elif event.type == 'LEFT_ARROW' and event.value == 'PRESS':
+ self.nbrow -= 1
+ update_grid(self, context)
+
+ # Grid : Scale gap between columns
+ if event.type == context.scene.Key_Gapy and event.value == 'PRESS':
+ if self.GridScaleX == False:
+ self.am = event.mouse_region_x, event.mouse_region_y
+ self.GridScaleX = True
+
+ # Grid : Scale gap between rows
+ if event.type == context.scene.Key_Gapx and event.value == 'PRESS':
+ if self.GridScaleY == False:
+ self.am = event.mouse_region_x, event.mouse_region_y
+ self.GridScaleY = True
+
+ # Cursor depth or solidify pattern
+ if event.type == context.scene.Key_Depth and event.value == 'PRESS':
+ if (self.ObjectMode == False) and (self.ProfileMode == False):
+ self.snapCursor = not self.snapCursor
+ else:
+ # Solidify
+
+ if (self.ObjectMode or self.ProfileMode) and (self.SolidifyPossible):
+ solidify = True
+
+ if self.ObjectMode:
+ z = self.ObjectBrush.data.vertices[0].co.z
+ ErrorMarge = 0.01
+ for v in self.ObjectBrush.data.vertices:
+ if abs(v.co.z - z) > ErrorMarge:
+ solidify = False
+ self.BrushDepth = True
+ self.am = event.mouse_region_x, event.mouse_region_y
+ break
+
+ if solidify:
+ if self.ObjectMode:
+ for mb in self.ObjectBrush.modifiers:
+ if mb.type == 'SOLIDIFY':
+ AlreadySoldify = True
+ else:
+ for mb in self.ProfileBrush.modifiers:
+ if mb.type == 'SOLIDIFY':
+ AlreadySoldify = True
+
+ if AlreadySoldify == False:
+ Selection_Save(self)
+ self.BrushSolidify = True
+
+ bpy.ops.object.select_all(action='TOGGLE')
+ if self.ObjectMode:
+ self.ObjectBrush.select = True
+ context.scene.objects.active = self.ObjectBrush
+ # Active le xray
+ self.ObjectBrush.show_x_ray = True
+ else:
+ self.ProfileBrush.select = True
+ context.scene.objects.active = self.ProfileBrush
+ # Active le xray
+ self.ProfileBrush.show_x_ray = True
+
+ bpy.ops.object.modifier_add(type='SOLIDIFY')
+ context.object.modifiers["Solidify"].name = "CT_SOLIDIFY"
+
+ context.object.modifiers["CT_SOLIDIFY"].thickness = 0.1
+
+ Selection_Restore(self)
+
+ self.WidthSolidify = not self.WidthSolidify
+ self.am = event.mouse_region_x, event.mouse_region_y
+
+ # Random rotation
+ if event.type == 'R' and event.value == 'PRESS':
+ self.RandomRotation = not self.RandomRotation
+
+ # Undo
+ if event.type == 'Z' and event.value == 'PRESS':
+ if self.ctrl:
+ if (self.CutMode == LINE) and (self.bDone):
+ if len(self.mouse_path) > 1:
+ self.mouse_path[len(self.mouse_path) - 1:] = []
+ else:
+ Undo(self)
+
+ # Mouse move
+ if event.type == 'MOUSEMOVE':
+
+ if self.ObjectMode or self.ProfileMode:
+ fac = 50.0
+ if self.shift:
+ fac = 500.0
+ if self.WidthSolidify:
+ if self.ObjectMode:
+ bpy.data.objects[self.ObjectBrush.name].modifiers[
+ "CT_SOLIDIFY"].thickness += (event.mouse_region_x - self.am[0]) / fac
+ elif self.ProfileMode:
+ bpy.data.objects[self.ProfileBrush.name].modifiers[
+ "CT_SOLIDIFY"].thickness += (event.mouse_region_x - self.am[0]) / fac
+ self.am = event.mouse_region_x, event.mouse_region_y
+ elif self.BrushDepth:
+ for v in self.ObjectBrush.data.vertices:
+ v.co.z += (event.mouse_region_x - self.am[0]) / fac
+ self.am = event.mouse_region_x, event.mouse_region_y
+ else:
+ if (self.GridScaleX):
+ self.gapx += (event.mouse_region_x - self.am[0]) / 50
+ self.am = event.mouse_region_x, event.mouse_region_y
+ update_grid(self, context)
+ return {'RUNNING_MODAL'}
+
+ elif (self.GridScaleY):
+ self.gapy += (event.mouse_region_x - self.am[0]) / 50
+ self.am = event.mouse_region_x, event.mouse_region_y
+ update_grid(self, context)
+ return {'RUNNING_MODAL'}
+
+ elif self.ObjectScale:
+ self.ascale = -(event.mouse_region_x - self.am[0])
+ self.am = event.mouse_region_x, event.mouse_region_y
+
+ if self.ObjectMode:
+ self.ObjectBrush.scale.x -= float(self.ascale) / 150.0
+ if self.ObjectBrush.scale.x <= 0.0:
+ self.ObjectBrush.scale.x = 0.0
+ self.ObjectBrush.scale.y -= float(self.ascale) / 150.0
+ if self.ObjectBrush.scale.y <= 0.0:
+ self.ObjectBrush.scale.y = 0.0
+ self.ObjectBrush.scale.z -= float(self.ascale) / 150.0
+ if self.ObjectBrush.scale.z <= 0.0:
+ self.ObjectBrush.scale.z = 0.0
+
+ elif self.ProfileMode:
+ if self.ProfileBrush is not None:
+ self.ProfileBrush.scale.x -= float(self.ascale) / 150.0
+ self.ProfileBrush.scale.y -= float(self.ascale) / 150.0
+ self.ProfileBrush.scale.z -= float(self.ascale) / 150.0
+
+ else:
+ if self.LMB:
+ if self.ctrl:
+ self.aRotZ = - \
+ ((int((event.mouse_region_x - self.xSavMouse) / 10.0) * PI / 4.0) * 25.0)
+ else:
+ self.aRotZ -= event.mouse_region_x - self.am[0]
+ self.ascale = 0.0
+
+ self.am = event.mouse_region_x, event.mouse_region_y
+ else:
+ vBack = Pick(context, event, self)
+ if vBack[0] is not None:
+ self.ShowCursor = True
+ NormalObject = mathutils.Vector((0.0, 0.0, 1.0))
+ qR = RBenVe(NormalObject, vBack[1])
+ self.qRot = qR
+ Pos = vBack[0]
+ MoveCursor(qR, vBack[0], self)
+ self.SavCurLoc = vBack[0]
+ if self.ctrl:
+ if self.SavMousePos is not None:
+ xEcart = abs(self.SavMousePos.x - self.SavCurLoc.x)
+ yEcart = abs(self.SavMousePos.y - self.SavCurLoc.y)
+ zEcart = abs(self.SavMousePos.z - self.SavCurLoc.z)
+ if (xEcart > yEcart) and (xEcart > zEcart):
+ self.CurLoc = mathutils.Vector(
+ (vBack[0].x, self.SavMousePos.y, self.SavMousePos.z))
+ if (yEcart > xEcart) and (yEcart > zEcart):
+ self.CurLoc = mathutils.Vector(
+ (self.SavMousePos.x, vBack[0].y, self.SavMousePos.z))
+ if (zEcart > xEcart) and (zEcart > yEcart):
+ self.CurLoc = mathutils.Vector(
+ (self.SavMousePos.x, self.SavMousePos.y, vBack[0].z))
+ else:
+ self.CurLoc = vBack[0]
+ else:
+ self.CurLoc = vBack[0]
+ else:
+ if self.bDone:
+ if self.alt == False:
+ if self.bDone:
+ if self.ctrl and (self.CutMode == LINE):
+ # Incremental mode
+ coord = list(self.mouse_path[len(self.mouse_path) - 1])
+ coord[0] = int(self.mouse_path[len(self.mouse_path) - 2][0] + int((event.mouse_region_x -
+ self.mouse_path[len(self.mouse_path) - 2][0]) / self.Increment) * self.Increment)
+ coord[1] = int(self.mouse_path[len(self.mouse_path) - 2][1] + int((event.mouse_region_y -
+ self.mouse_path[len(self.mouse_path) - 2][1]) / self.Increment) * self.Increment)
+ self.mouse_path[len(self.mouse_path) - 1] = tuple(coord)
+ else:
+ if len(self.mouse_path) > 0:
+ self.mouse_path[len(self.mouse_path) -
+ 1] = (event.mouse_region_x, event.mouse_region_y)
+ else:
+ # [ALT] press, update position
+ self.xpos += (event.mouse_region_x - self.last_mouse_region_x)
+ self.ypos += (event.mouse_region_y - self.last_mouse_region_y)
+
+ self.last_mouse_region_x = event.mouse_region_x
+ self.last_mouse_region_y = event.mouse_region_y
+
+ elif event.type == 'LEFTMOUSE' and event.value == 'PRESS':
+ if self.ObjectMode or self.ProfileMode:
+ if self.LMB == False:
+ vBack = Pick(context, event, self)
+ if vBack[0] is not None:
+ NormalObject = mathutils.Vector((0.0, 0.0, 1.0))
+ self.aqR = RBenVe(NormalObject, vBack[1])
+ self.qRot = self.aqR
+ self.am = event.mouse_region_x, event.mouse_region_y
+ self.xSavMouse = event.mouse_region_x
+
+ if self.ctrl:
+ self.nRotZ = int((self.aRotZ / 25.0) / (PI / 4.0))
+ self.aRotZ = self.nRotZ * (PI / 4.0) * 25.0
+
+ self.LMB = True
+
+ # LEFTMOUSE
+ elif event.type == 'LEFTMOUSE' and event.value == 'RELEASE':
+ if self.ObjectMode or self.ProfileMode:
+ # Rotation and scale
+ self.LMB = False
+ if self.ObjectScale == True:
+ self.ObjectScale = False
+
+ if self.GridScaleX == True:
+ self.GridScaleX = False
+
+ if self.GridScaleY == True:
+ self.GridScaleY = False
+
+ if self.WidthSolidify:
+ self.WidthSolidify = False
+
+ if self.BrushDepth == True:
+ self.BrushDepth = False
+
+ else:
+ if self.bDone == False:
+ if self.ctrl:
+ Picking(context, event)
+ else:
+ if self.CutMode == LINE:
+ if self.bDone == False:
+ self.mouse_path.clear()
+ self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
+ self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
+ else:
+ self.mouse_path[0] = (event.mouse_region_x, event.mouse_region_y)
+ self.mouse_path[1] = (event.mouse_region_x, event.mouse_region_y)
+ self.bDone = True
+ else:
+ if self.CutMode != LINE:
+ # Cut creation
+ if self.CutMode == RECTANGLE:
+ CreateCutSquare(self, context)
+ if self.CutMode == CIRCLE:
+ CreateCutCircle(self, context)
+ if self.CutMode == LINE:
+ CreateCutLine(self, context)
+
+ if self.CreateMode:
+ # Object creation
+ self.CreateGeometry()
+ bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+ # Depth Cursor
+ context.scene.DepthCursor = self.snapCursor
+ # Instantiate object
+ context.scene.OInstanciate = self.Instantiate
+ # Random rotation
+ context.scene.ORandom = self.RandomRotation
+ # Apply operation
+ context.scene.DontApply = self.DontApply
+
+ # if Object mode, set intiale state
+ if self.ObjectBrush is not None:
+ self.ObjectBrush.location = self.InitBrushPosition
+ self.ObjectBrush.scale = self.InitBrushScale
+ self.ObjectBrush.rotation_quaternion = self.InitBrushQRotation
+ self.ObjectBrush.rotation_euler = self.InitBrushERotation
+ self.ObjectBrush.draw_type = self.ObjectBrush_DT
+ self.ObjectBrush.show_x_ray = self.XRay
+
+ # remove solidify
+ Selection_Save(self)
+ self.BrushSolidify = False
+
+ bpy.ops.object.select_all(action='TOGGLE')
+ self.ObjectBrush.select = True
+ context.scene.objects.active = self.ObjectBrush
+
+ bpy.ops.object.modifier_remove(modifier="CT_SOLIDIFY")
+
+ Selection_Restore(self)
+
+ context.scene.nProfile = self.nProfil
+
+ return {'FINISHED'}
+ else:
+ # Cut
+ self.Cut()
+ UndoListUpdate(self)
+
+ else:
+ # Line
+ self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
+
+ # Change circle subdivisions
+ elif (event.type == 'COMMA' and event.value == 'PRESS') or (event.type == context.scene.Key_Subrem and event.value == 'PRESS'):
+ if self.ProfileMode:
+ self.nProfil += 1
+ if self.nProfil >= self.MaxProfil:
+ self.nProfil = 0
+ createMeshFromData(self)
+ # Circle rotation
+ if self.CutMode == CIRCLE:
+ if self.ctrl:
+ self.stepRotation += 1
+ else:
+ self.step += 1
+ if self.step >= len(self.stepAngle):
+ self.step = len(self.stepAngle) - 1
+ elif (event.type == 'PERIOD' and event.value == 'PRESS') or (event.type == context.scene.Key_Subadd and event.value == 'PRESS'):
+ if self.ProfileMode:
+ self.nProfil -= 1
+ if self.nProfil < 0:
+ self.nProfil = self.MaxProfil - 1
+ createMeshFromData(self)
+ if self.CutMode == CIRCLE:
+ if self.ctrl:
+ self.stepRotation -= 1
+ else:
+ if self.step > 0:
+ self.step -= 1
+
+ # Quit
+ elif event.type in {'RIGHTMOUSE', 'ESC'}:
+ # Depth Cursor
+ context.scene.DepthCursor = self.snapCursor
+ # Instantiate object
+ context.scene.OInstanciate = self.Instantiate
+ # Random Rotation
+ context.scene.ORandom = self.RandomRotation
+ # Apply boolean operation
+ context.scene.DontApply = self.DontApply
+
+ # Reset Object
+ if self.ObjectBrush is not None:
+ self.ObjectBrush.location = self.InitBrushPosition
+ self.ObjectBrush.scale = self.InitBrushScale
+ self.ObjectBrush.rotation_quaternion = self.InitBrushQRotation
+ self.ObjectBrush.rotation_euler = self.InitBrushERotation
+ self.ObjectBrush.draw_type = self.ObjectBrush_DT
+ self.ObjectBrush.show_x_ray = self.XRay
+
+ # Remove solidify modifier
+ Selection_Save(self)
+ self.BrushSolidify = False
+
+ bpy.ops.object.select_all(action='TOGGLE')
+ self.ObjectBrush.select = True
+ context.scene.objects.active = self.ObjectBrush
+
+ bpy.ops.object.modifier_remove(modifier="CT_SOLIDIFY")
+
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ Selection_Restore(self)
+
+ if "CT_Profil" in bpy.data.objects:
+ Selection_Save(self)
+ bpy.ops.object.select_all(action='DESELECT')
+ bpy.data.objects["CT_Profil"].select = True
+ context.scene.objects.active = bpy.data.objects["CT_Profil"]
+ bpy.ops.object.delete(use_global=False)
+ Selection_Restore(self)
+
+ context.scene.objects.active = self.CurrentActive
+
+ context.scene.nProfile = self.nProfil
+
+ bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+ # Remove Copy Object Brush
+ if bpy.data.objects.get("CarverBrushCopy") is not None:
+ brush = bpy.data.objects["CarverBrushCopy"]
+ self.ObjectBrush.data = bpy.data.meshes[brush.data.name]
+ bpy.ops.object.select_all(action='DESELECT')
+ bpy.data.objects["CarverBrushCopy"].select = True
+ bpy.ops.object.delete()
+
+ return {'FINISHED'}
+
+ return {'RUNNING_MODAL'}
+
+ except:
+ print("Sometimes, something goes wrong...")
+ context.window.cursor_modal_set("DEFAULT")
+ context.area.header_text_set()
+ bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+ return {'FINISHED'}
+
+ #---------------------------------------------------------------------------------------------------
+
+ #---------------------------------------------------------------------------------------------------
+ def invoke(self, context, event):
+ if context.area.type == 'VIEW_3D':
+ if context.mode == 'EDIT_MESH':
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ win = context.window
+
+ # Get default patterns
+ self.Profils = []
+ for p in Profils:
+ self.Profils.append((p[0], p[1], p[2], p[3]))
+ self.nProfil = context.scene.nProfile
+ self.MaxProfil = len(self.Profils)
+
+ # Save selection
+ self.CurrentSelection = context.selected_objects.copy()
+ self.CurrentActive = context.active_object
+ self.SavSel = context.selected_objects.copy()
+ self.Sav_ac = None
+
+ args = (self, context)
+
+ self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
+
+ self.mouse_path = [(0, 0), (0, 0)]
+
+ self.shift = False
+ self.ctrl = False
+ self.alt = False
+
+ self.bDone = False
+
+ self.DontApply = context.scene.DontApply
+ self.Auto_BevelUpdate = True
+
+ # Cut type (Rectangle, Circle, Line)
+ self.CutMode = 0
+ self.BoolOps = DIFFERENCE
+
+ # Circle variables
+ self.stepAngle = [2, 4, 5, 6, 9, 10, 15, 20, 30, 40, 45, 60, 72, 90]
+ self.step = 4
+ self.stepRotation = 0
+
+ # Primitives Position
+ self.xpos = 0
+ self.ypos = 0
+ self.InitPosition = False
+
+ # Line Increment
+ self.Increment = 15
+ # Close polygonal shape
+ self.Closed = False
+
+ # Depth Cursor
+ self.snapCursor = context.scene.DepthCursor
+
+ # Help
+ self.AskHelp = False
+
+ # Working object
+ self.OpsObj = context.active_object
+
+ # Create mode
+ self.CreateMode = False
+ self.ExclusiveCreateMode = False
+ if len(context.selected_objects) == 0:
+ self.ExclusiveCreateMode = True
+ self.CreateMode = True
+
+ # Rebool forced (cut line)
+ self.ForceRebool = False
+
+ self.ViewVector = mathutils.Vector()
+
+ self.CurrentObj = None
+
+ # Brush
+ self.BrushSolidify = False
+ self.WidthSolidify = False
+ self.BrushDepth = False
+
+ self.ObjectScale = False
+
+ self.CircleListRaw = []
+ self.CLR_C = []
+ self.CurLoc = mathutils.Vector((0.0, 0.0, 0.0))
+ self.SavCurLoc = mathutils.Vector((0.0, 0.0, 0.0))
+ self.CRadius = 1.0
+ CreatePrimitive(self, 10.0, 1.0)
+ self.VertsList = []
+ self.FacesList = []
+
+ self.am = -1, -1
+ self.SavMousePos = None
+ self.xSavMouse = 0
+
+ self.ascale = 0
+ self.aRotZ = 0
+ self.nRotZ = 0
+ self.aqR = None
+ self.qRot = None
+
+ self.RandomRotation = context.scene.ORandom
+
+ self.ShowCursor = True
+
+ self.ObjectMode = False
+ self.ProfileMode = False
+ self.Instantiate = context.scene.OInstanciate
+
+ self.ProfileBrush = None
+ self.ObjectBrush = None
+ self.InitBrushPosition = None
+ self.InitBrushScale = None
+ self.InitBrushQRotation = None
+ self.InitBrushERotation = None
+ self.InitBrushARotation = None
+
+ self.ObjectBrush_DT = "WIRE"
+ self.XRay = False
+
+ # Grid mesh
+ self.nbcol = 1
+ self.nbrow = 1
+ self.gapx = 0
+ self.gapy = 0
+ self.scale_x = 1
+ self.scale_y = 1
+
+ self.GridScaleX = False
+ self.GridScaleY = False
+
+ if len(context.selected_objects) > 1:
+ self.ObjectBrush = context.active_object
+
+ #---Copy the brush object
+ ob = bpy.data.objects.new("CarverBrushCopy", context.object.data.copy())
+ ob.location = self.ObjectBrush.location
+ scene = context.scene
+ scene.objects.link(ob)
+ scene.update()
+
+ # Get default variables
+ self.InitBrushPosition = self.ObjectBrush.location.copy()
+ self.InitBrushScale = self.ObjectBrush.scale.copy()
+ self.InitBrushQRotation = self.ObjectBrush.rotation_quaternion.copy()
+ self.InitBrushERotation = self.ObjectBrush.rotation_euler.copy()
+ self.ObjectBrush_DT = self.ObjectBrush.draw_type
+ self.XRay = self.ObjectBrush.show_x_ray
+ # Test if flat object
+ z = self.ObjectBrush.data.vertices[0].co.z
+ ErrorMarge = 0.01
+ self.Solidify_Active_Start = True
+ for v in self.ObjectBrush.data.vertices:
+ if abs(v.co.z - z) > ErrorMarge:
+ self.Solidify_Active_Start = False
+ break
+ self.SolidifyPossible = False
+
+ self.CList = []
+ self.OPList = []
+ self.RList = []
+ self.OB_List = []
+
+ for ent in context.selected_objects:
+ if ent != self.ObjectBrush:
+ self.OB_List.append(ent)
+
+ # Left button
+ self.LMB = False
+
+ # Undo Variables
+ self.undo_index = 0
+ self.undo_limit = context.user_preferences.edit.undo_steps
+ self.undo_list = []
+
+ # Boolean operations type
+ self.BooleanType = 0
+
+ self.UList = []
+ self.UList_Index = -1
+ self.UndoOps = []
+
+ context.window_manager.modal_handler_add(self)
+ return {'RUNNING_MODAL'}
+ else:
+ self.report({'WARNING'}, "View3D not found, cannot run operator")
+ return {'CANCELLED'}
+ #---------------------------------------------------------------------------------------------------
+
+ #---------------------------------------------------------------------------------------------------
+ def CreateGeometry(self):
+ context = bpy.context
+
+ region_id = context.region.id
+
+ bLocalView = False
+ for area in context.screen.areas:
+ if area.type == 'VIEW_3D':
+ if area.spaces[0].local_view is not None:
+ bLocalView = True
+
+ if bLocalView:
+ bpy.ops.view3d.localview()
+
+ if self.ExclusiveCreateMode:
+ # Default width
+ objBBDiagonal = 0.5
+ else:
+ ActiveObj = self.CurrentSelection[0]
+ if ActiveObj is not None:
+ objBBDiagonal = objDiagonal(ActiveObj) / 4
+ subdivisions = 2
+
+ if len(context.selected_objects) > 0:
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ context.scene.objects.active = self.CurrentObj
+
+ bpy.data.objects[self.CurrentObj.name].select = True
+ bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.select_mode(type="EDGE")
+ if self.snapCursor == False:
+ bpy.ops.transform.translate(value=self.ViewVector * objBBDiagonal * subdivisions)
+ bpy.ops.mesh.extrude_region_move(
+ TRANSFORM_OT_translate={"value": -self.ViewVector * objBBDiagonal * subdivisions * 2})
+
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.normals_make_consistent()
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ saved_location_0 = context.scene.cursor_location.copy()
+ bpy.ops.view3d.snap_cursor_to_active()
+ saved_location = context.scene.cursor_location.copy()
+ bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
+ context.scene.cursor_location = saved_location
+ bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
+ context.scene.cursor_location = saved_location_0
+
+ bpy.data.objects[self.CurrentObj.name].select = True
+ bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
+
+ for o in self.SavSel:
+ bpy.data.objects[o.name].select = True
+
+ if bLocalView:
+ bpy.ops.view3d.localview()
+
+ self.bDone = False
+ self.mouse_path.clear()
+ self.mouse_path = [(0, 0), (0, 0)]
+ #---------------------------------------------------------------------------------------------------
+
+ #---------------------------------------------------------------------------------------------------
+ def Cut(self):
+ context = bpy.context
+
+ UNDO = []
+
+ # Local view ?
+ bLocalView = False
+ for area in context.screen.areas:
+ if area.type == 'VIEW_3D':
+ if area.spaces[0].local_view is not None:
+ bLocalView = True
+
+ if bLocalView:
+ bpy.ops.view3d.localview()
+
+ # Save cursor position
+ CursorLocation = context.scene.cursor_location.copy()
+
+ ActiveObjList = []
+ if (self.ObjectMode == False) and (self.ProfileMode == False):
+ objBBDiagonal = objDiagonal(self.CurrentSelection[0])
+ subdivisions = 32
+ if self.DontApply:
+ subdivisions = 1
+
+ # Get selected objects
+ ActiveObjList = context.selected_objects.copy()
+
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ context.scene.objects.active = self.CurrentObj
+
+ bpy.data.objects[self.CurrentObj.name].select = True
+ bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.select_mode(type="EDGE")
+ if (self.snapCursor == False) or (self.ForceRebool):
+ bpy.ops.transform.translate(value=self.ViewVector * objBBDiagonal * subdivisions)
+ bpy.ops.mesh.extrude_region_move(
+ TRANSFORM_OT_translate={"value": -self.ViewVector * objBBDiagonal * subdivisions * 2})
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.normals_make_consistent()
+ bpy.ops.object.mode_set(mode='OBJECT')
+ else:
+ # Create liste
+ if self.ObjectMode:
+ for o in self.CurrentSelection:
+ if o != self.ObjectBrush:
+ ActiveObjList.append(o)
+ self.CurrentObj = self.ObjectBrush
+ else:
+ ActiveObjList = self.CurrentSelection
+ self.CurrentObj = self.ProfileBrush
+
+ for o in self.CurrentSelection:
+ UndoAdd(self, "MESH", o)
+
+ # List objects create with rebool
+ lastSelected = []
+
+ for ActiveObj in ActiveObjList:
+ context.scene.cursor_location = CursorLocation
+
+ if len(context.selected_objects) > 0:
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ # Testif intitiale object has bevel
+ BevelAO = False
+ for obj in ActiveObjList:
+ for mb in obj.modifiers:
+ if mb.type == 'BEVEL':
+ BevelAO = True
+
+ # Select cut object
+ bpy.data.objects[self.CurrentObj.name].select = True
+ context.scene.objects.active = self.CurrentObj
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Select object to cut
+ bpy.data.objects[ActiveObj.name].select = True
+ context.scene.objects.active = ActiveObj
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.select_all(action='DESELECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Boolean operation
+ if (self.shift == False) and (self.ForceRebool == False):
+ if self.ObjectMode or self.ProfileMode:
+ if self.BoolOps == UNION:
+ # Union
+ boolean_union()
+ else:
+ # Cut object
+ boolean_difference()
+ else:
+ # Cut
+ boolean_difference()
+
+ # Apply booleans
+ if self.DontApply == False:
+ BMname = "CT_" + self.CurrentObj.name
+ for mb in ActiveObj.modifiers:
+ if (mb.type == 'BOOLEAN') and (mb.name == BMname):
+ try:
+ bpy.ops.object.modifier_apply(apply_as='DATA', modifier=BMname)
+ except:
+ bpy.ops.object.modifier_remove(modifier=BMname)
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ self.report({'ERROR'}, str(exc_value))
+
+ bpy.ops.object.select_all(action='TOGGLE')
+ else:
+ if self.ObjectMode or self.ProfileMode:
+ for mb in self.CurrentObj.modifiers:
+ if (mb.type == 'SOLIDIFY') and (mb.name == "CT_SOLIDIFY"):
+ try:
+ bpy.ops.object.modifier_apply(apply_as='DATA', modifier="CT_SOLIDIFY")
+ except:
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ self.report({'ERROR'}, str(exc_value))
+
+ # Rebool
+ Rebool(context, self)
+ # Test if not empty object
+ if context.selected_objects[0]:
+ rebool_RT = context.selected_objects[0]
+ if len(rebool_RT.data.vertices) > 0:
+ # Create Bevel for new objects
+ if BevelAO:
+ CreateBevel(context, context.selected_objects[0])
+ UndoAdd(self, "REBOOL", context.selected_objects[0])
+
+ context.scene.cursor_location = ActiveObj.location
+ bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
+ else:
+ bpy.ops.object.delete(use_global=False)
+
+ context.scene.cursor_location = CursorLocation
+
+ if self.ObjectMode:
+ context.scene.objects.active = self.ObjectBrush
+ if self.ProfileMode:
+ context.scene.objects.active = self.ProfileBrush
+
+ if self.DontApply == False:
+ # Apply booleans
+ BMname = "CT_" + self.CurrentObj.name
+ for mb in ActiveObj.modifiers:
+ if (mb.type == 'BOOLEAN') and (mb.name == BMname):
+ try:
+ bpy.ops.object.modifier_apply(apply_as='DATA', modifier=BMname)
+ except:
+ bpy.ops.object.modifier_remove(modifier=BMname)
+ exc_type, exc_value, exc_traceback = sys.exc_info()
+ self.report({'ERROR'}, str(exc_value))
+ # Get new objects created with rebool operations
+ if len(context.selected_objects) > 0:
+ if self.shift == True:
+ # Get the last object selected
+ lastSelected.append(context.selected_objects[0])
+
+ context.scene.cursor_location = CursorLocation
+
+ if self.DontApply == False:
+ # Remove cut object
+ if (self.ObjectMode == False) and (self.ProfileMode == False):
+ if len(context.selected_objects) > 0:
+ bpy.ops.object.select_all(action='TOGGLE')
+ bpy.data.objects[self.CurrentObj.name].select = True
+ cname = self.CurrentObj.name
+ bpy.ops.object.delete(use_global=False)
+ else:
+ if self.ObjectMode:
+ self.ObjectBrush.draw_type = self.ObjectBrush_DT
+
+ if len(context.selected_objects) > 0:
+ bpy.ops.object.select_all(action='TOGGLE')
+
+ # Select cutted objects
+ for obj in lastSelected:
+ bpy.data.objects[obj.name].select = True
+
+ for ActiveObj in ActiveObjList:
+ bpy.data.objects[ActiveObj.name].select = True
+ context.scene.objects.active = ActiveObj
+ # Update bevel
+ list_act_obj = context.selected_objects.copy()
+ if self.Auto_BevelUpdate:
+ update_bevel(context)
+
+ # Reselect intiale objects
+ bpy.ops.object.select_all(action='TOGGLE')
+ if self.ObjectMode:
+ # Reselect brush
+ self.ObjectBrush.select = True
+ for ActiveObj in ActiveObjList:
+ bpy.data.objects[ActiveObj.name].select = True
+ context.scene.objects.active = ActiveObj
+
+ # If object has children, set "Wire" draw type
+ if self.ObjectBrush is not None:
+ if len(self.ObjectBrush.children) > 0:
+ self.ObjectBrush.draw_type = "WIRE"
+ if self.ProfileMode:
+ self.ProfileBrush.draw_type = "WIRE"
+
+ if bLocalView:
+ bpy.ops.view3d.localview()
+
+ # Reset variables
+ self.bDone = False
+ self.mouse_path.clear()
+ self.mouse_path = [(0, 0), (0, 0)]
+
+ self.ForceRebool = False
+
+
+classes = (
+ Carver,
+ )
+
+addon_keymaps = []
+
+
+def register():
+ bpy.types.Scene.DepthCursor = bpy.props.BoolProperty(name="DepthCursor", default=False)
+ bpy.types.Scene.OInstanciate = bpy.props.BoolProperty(name="Obj_Instantiate", default=False)
+ bpy.types.Scene.ORandom = bpy.props.BoolProperty(name="Random_Rotation", default=False)
+ bpy.types.Scene.DontApply = bpy.props.BoolProperty(name="Dont_Apply", default=False)
+ bpy.types.Scene.nProfile = bpy.props.IntProperty(name="Num_Profile", default=0)
+
+ bpy.utils.register_class(CarverPrefs)
+
+ bpy.utils.register_class(Carver)
+ # add keymap entry
+ kcfg = bpy.context.window_manager.keyconfigs.addon
+ if kcfg:
+ km = kcfg.keymaps.new(name='3D View', space_type='VIEW_3D')
+ kmi = km.keymap_items.new("object.carver", 'X', 'PRESS', shift=True, ctrl=True)
+ addon_keymaps.append((km, kmi))
+
+
+def unregister():
+ bpy.utils.unregister_class(CarverPrefs)
+
+ # remove keymap entry
+ for km, kmi in addon_keymaps:
+ km.keymap_items.remove(kmi)
+ addon_keymaps.clear()
+
+ bpy.utils.unregister_class(Carver)
+
+
+if __name__ == "__main__":
+ register()