Fix T52833: OBJ triangulate doesn't match viewport
[blender-addons.git] / add_advanced_objects_menu / oscurart_chain_maker.py
blob6dcd6f808e8f2d9f8a2807c3566e1e66f559ac4c
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # TODO: find English versions of created object names
21 bl_info = {
22 "name": "Oscurart Chain Maker",
23 "author": "Oscurart",
24 "version": (1, 1),
25 "blender": (2, 56, 0),
26 "location": "Add > Mesh > Oscurart Chain",
27 "description": "Create chain links from armatures",
28 "warning": "",
29 "wiki_url": "oscurart.blogspot.com",
30 "category": "Object"}
33 import bpy
34 from bpy.props import (
35 BoolProperty,
36 FloatProperty,
38 from bpy.types import Operator
41 def makeChain(self, context, mult, curverig):
43 if not context.active_object.type == 'ARMATURE':
44 self.report({'WARNING'}, "Active Object must be an Armature")
45 return False
47 bpy.ops.object.mode_set(mode='OBJECT')
48 VAR_SWITCH = abs(1)
49 ARMATURE = bpy.context.active_object
51 def creahuesocero(hueso):
52 # create data to link
53 mesh = bpy.data.meshes.new("objectData" + str(hueso.name))
54 object = bpy.data.objects.new("HardLink" + str(hueso.name), mesh)
55 mesh.from_pydata(
56 [(-0.04986128956079483, -0.6918092370033264, -0.17846597731113434),
57 (-0.04986128956079483, -0.6918091773986816, 0.17846640944480896),
58 (-0.049861326813697815, -0.154555082321167, 0.17846627533435822),
59 (-0.049861326813697815, -0.15455523133277893, -0.17846614122390747),
60 (-0.04986133798956871, -0.03475356101989746, 0.25805795192718506),
61 (-0.04986133798956871, -0.03475397825241089, -0.25805795192718506),
62 (-0.049861278384923935, -0.8116106986999512, -0.2580576539039612),
63 (-0.049861278384923935, -0.8116104602813721, 0.25805822014808655),
64 (-0.04986128211021423, -0.7692053318023682, 2.6668965347198537e-07),
65 (-0.04986127093434334, -0.923523485660553, 2.7834033744511544e-07),
66 (-0.04986133426427841, -0.0771591067314148, 3.5627678585115063e-08),
67 (-0.04986134544014931, 0.0771591067314148, -3.5627678585115063e-08),
68 (0.04986133798956871, -0.03475397825241089, -0.25805795192718506),
69 (0.04986133053898811, 0.0771591067314148, -3.5627678585115063e-08),
70 (0.04986133798956871, -0.03475356101989746, 0.25805795192718506),
71 (0.04986134544014931, -0.15455523133277893, -0.17846614122390747),
72 (0.04986134544014931, -0.0771591067314148, 3.5627678585115063e-08),
73 (0.04986134544014931, -0.154555082321167, 0.17846627533435822),
74 (0.049861397594213486, -0.8116106986999512, -0.2580576539039612),
75 (0.04986140504479408, -0.923523485660553, 2.7834033744511544e-07),
76 (0.049861397594213486, -0.8116104602813721, 0.25805822014808655),
77 (0.04986139014363289, -0.6918091773986816, 0.17846640944480896),
78 (0.04986139014363289, -0.7692053318023682, 2.6668965347198537e-07),
79 (0.04986139014363289, -0.6918092370033264, -0.17846597731113434)],
80 [(1, 2), (0, 3), (3, 5), (2, 4), (0, 6), (5, 6), (1, 7), (4, 7), (0, 8), (1, 8),
81 (7, 9), (6, 9), (8, 9), (2, 10), (3, 10), (4, 11), (5, 11), (10, 11), (5, 12),
82 (12, 13), (11, 13), (13, 14), (4, 14), (10, 16), (15, 16), (3, 15), (2, 17),
83 (16, 17), (9, 19), (18, 19), (6, 18), (7, 20), (19, 20), (8, 22), (21, 22),
84 (1, 21), (0, 23), (22, 23), (14, 20), (12, 18), (15, 23), (17, 21), (12, 15),
85 (13, 16), (14, 17), (20, 21), (19, 22), (18, 23)],
86 [(6, 0, 3, 5), (1, 7, 4, 2), (0, 6, 9, 8), (8, 9, 7, 1), (2, 4, 11, 10), (10, 11, 5, 3),
87 (11, 13, 12, 5), (4, 14, 13, 11), (3, 15, 16, 10), (10, 16, 17, 2), (6, 18, 19, 9),
88 (9, 19, 20, 7), (1, 21, 22, 8), (23, 0, 8, 22), (7, 20, 14, 4), (5, 12, 18, 6),
89 (0, 23, 15, 3), (2, 17, 21, 1), (16, 15, 12, 13), (17, 16, 13, 14), (22, 21, 20, 19),
90 (23, 22, 19, 18), (21, 17, 14, 20), (15, 23, 18, 12)]
92 mesh.validate()
93 bpy.context.scene.objects.link(object)
94 # scale to the bone
95 bpy.data.objects["HardLink" + str(hueso.name)].scale = (hueso.length * mult,
96 hueso.length * mult,
97 hueso.length * mult)
98 # Parent Objects
99 bpy.data.objects["HardLink" + str(hueso.name)].parent = ARMATURE
100 bpy.data.objects["HardLink" + str(hueso.name)].parent_type = 'BONE'
101 bpy.data.objects["HardLink" + str(hueso.name)].parent_bone = hueso.name
103 def creahuesonoventa(hueso):
104 # create data to link
105 mesh = bpy.data.meshes.new("objectData" + str(hueso.name))
106 object = bpy.data.objects.new("NewLink" + str(hueso.name), mesh)
107 mesh.from_pydata(
108 [(0.1784660965204239, -0.6918091773986816, -0.049861203879117966),
109 (-0.1784662902355194, -0.6918091773986816, -0.04986126348376274),
110 (-0.17846627533435822, -0.1545550525188446, -0.04986134544014931),
111 (0.17846617102622986, -0.15455520153045654, -0.04986128583550453),
112 (-0.25805795192718506, -0.03475359082221985, -0.049861375242471695),
113 (0.25805795192718506, -0.034753888845443726, -0.04986129328608513),
114 (0.2580578327178955, -0.8116105794906616, -0.04986117407679558),
115 (-0.2580580413341522, -0.8116105198860168, -0.049861256033182144),
116 (-9.672299938756623e-08, -0.7692052721977234, -0.04986122250556946),
117 (-8.99775329799013e-08, -0.923523485660553, -0.04986120015382767),
118 (-7.764004550381287e-09, -0.07715904712677002, -0.049861326813697815),
119 (4.509517737005808e-08, 0.0771591067314148, -0.049861349165439606),
120 (0.25805795192718506, -0.034753888845443726, 0.049861375242471695),
121 (-2.2038317837314025e-08, 0.0771591067314148, 0.049861326813697815),
122 (-0.25805795192718506, -0.03475359082221985, 0.04986129328608513),
123 (0.17846617102622986, -0.15455520153045654, 0.04986138269305229),
124 (-1.529285498236277e-08, -0.07715907692909241, 0.049861352890729904),
125 (-0.17846627533435822, -0.1545550525188446, 0.049861323088407516),
126 (0.2580578029155731, -0.8116105794906616, 0.049861494451761246),
127 (-1.5711103173998708e-07, -0.923523485660553, 0.04986147582530975),
128 (-0.2580580711364746, -0.8116105198860168, 0.04986141249537468),
129 (-0.1784663051366806, -0.6918091773986816, 0.049861419945955276),
130 (-1.340541757599567e-07, -0.7692052721977234, 0.049861449748277664),
131 (0.1784660816192627, -0.6918091773986816, 0.04986146464943886)],
132 [(1, 2), (0, 3), (3, 5), (2, 4), (0, 6), (5, 6), (1, 7), (4, 7), (0, 8),
133 (1, 8), (7, 9), (6, 9), (8, 9), (2, 10), (3, 10), (4, 11), (5, 11), (10, 11),
134 (5, 12), (12, 13), (11, 13), (13, 14), (4, 14), (10, 16), (15, 16), (3, 15),
135 (2, 17), (16, 17), (9, 19), (18, 19), (6, 18), (7, 20), (19, 20), (8, 22),
136 (21, 22), (1, 21), (0, 23), (22, 23), (14, 20), (12, 18), (15, 23), (17, 21),
137 (12, 15), (13, 16), (14, 17), (20, 21), (19, 22), (18, 23)],
138 [(6, 0, 3, 5), (1, 7, 4, 2), (0, 6, 9, 8), (8, 9, 7, 1), (2, 4, 11, 10),
139 (10, 11, 5, 3), (11, 13, 12, 5), (4, 14, 13, 11), (3, 15, 16, 10), (10, 16, 17, 2),
140 (6, 18, 19, 9), (9, 19, 20, 7), (1, 21, 22, 8), (23, 0, 8, 22), (7, 20, 14, 4),
141 (5, 12, 18, 6), (0, 23, 15, 3), (2, 17, 21, 1), (16, 15, 12, 13), (17, 16, 13, 14),
142 (22, 21, 20, 19), (23, 22, 19, 18), (21, 17, 14, 20), (15, 23, 18, 12)]
144 mesh.validate()
145 bpy.context.scene.objects.link(object)
146 # scale to the bone
147 bpy.data.objects["NewLink" + str(hueso.name)].scale = (hueso.length * mult,
148 hueso.length * mult,
149 hueso.length * mult)
150 # Parent objects
151 bpy.data.objects["NewLink" + str(hueso.name)].parent = ARMATURE
152 bpy.data.objects["NewLink" + str(hueso.name)].parent_type = 'BONE'
153 bpy.data.objects["NewLink" + str(hueso.name)].parent_bone = hueso.name
155 for hueso in bpy.context.active_object.pose.bones:
156 if VAR_SWITCH == 1:
157 creahuesocero(hueso)
158 else:
159 creahuesonoventa(hueso)
160 if VAR_SWITCH == 1:
161 VAR_SWITCH = 0
162 else:
163 VAR_SWITCH = 1
165 # if curve rig is activated
166 if curverig is True:
167 # variables
168 LISTA_POINTC = []
169 ACTARM = bpy.context.active_object
171 # create data and link the object to the scene
172 crv = bpy.data.curves.new("CurvaCable", "CURVE")
173 obCable = bpy.data.objects.new("Cable", crv)
174 bpy.context.scene.objects.link(obCable)
176 # set the attributes
177 crv.dimensions = "3D"
178 crv.resolution_u = 10
179 crv.resolution_v = 10
180 crv.twist_mode = "MINIMUM"
182 # create the list of tail and head coordinates
183 LISTA_POINTC.append((
184 ACTARM.data.bones[0].head_local[0],
185 ACTARM.data.bones[0].head_local[1],
186 ACTARM.data.bones[0].head_local[2], 1
189 for hueso in ACTARM.data.bones:
190 LISTA_POINTC.append((
191 hueso.tail_local[0],
192 hueso.tail_local[1],
193 hueso.tail_local[2], 1
196 # create the Spline
197 spline = crv.splines.new("NURBS")
198 lencoord = len(LISTA_POINTC)
199 rango = range(lencoord)
200 spline.points.add(lencoord - 1)
202 for punto in rango:
203 spline.points[punto].co = LISTA_POINTC[punto]
205 # set the endpoint
206 bpy.data.objects['Cable'].data.splines[0].use_endpoint_u = True
207 # select the curve
208 bpy.ops.object.select_all(action='DESELECT')
209 bpy.data.objects['Cable'].select = 1
210 bpy.context.scene.objects.active = bpy.data.objects['Cable']
211 # switch to Edit mode
212 bpy.ops.object.mode_set(mode='EDIT')
214 # create hooks
215 POINTSTEP = 0
216 for POINT in bpy.data.objects['Cable'].data.splines[0].points:
217 bpy.ops.curve.select_all(action="DESELECT")
218 bpy.data.objects['Cable'].data.splines[0].points[POINTSTEP].select = 1
219 bpy.ops.object.hook_add_newob()
220 POINTSTEP += 1
222 # Objects selection step
223 bpy.ops.object.mode_set(mode='OBJECT')
224 bpy.ops.object.select_all(action='DESELECT')
225 ACTARM.select = 1
226 bpy.context.scene.objects.active = bpy.data.objects['Armature']
227 bpy.ops.object.mode_set(mode='POSE')
228 bpy.ops.pose.select_all(action='DESELECT')
229 ACTARM.data.bones[-1].select = 1
230 ACTARM.data.bones.active = ACTARM.data.bones[-1]
232 # set IK Spline
233 bpy.ops.pose.constraint_add_with_targets(type='SPLINE_IK')
234 ACTARM.pose.bones[-1].constraints['Spline IK'].target = bpy.data.objects['Cable']
235 ACTARM.pose.bones[-1].constraints['Spline IK'].chain_count = 100
236 bpy.context.active_object.pose.bones[-1].constraints['Spline IK'].use_y_stretch = False
237 # return to Object mode
238 bpy.ops.object.mode_set(mode='OBJECT')
241 class MESH_OT_primitive_oscurart_chain_add(Operator):
242 bl_idname = "mesh.primitive_oscurart_chain_add"
243 bl_label = "Chain to Bones"
244 bl_description = ("Add Chain Parented to an Existing Armature\n"
245 "The Active/Last Selected Object must be an Armature")
246 bl_options = {'REGISTER', 'UNDO'}
248 curverig = BoolProperty(
249 name="Curve Rig",
250 default=False
252 multiplier = FloatProperty(
253 name="Scale",
254 default=1,
255 min=0.01, max=100.0
258 @classmethod
259 def poll(cls, context):
260 obj = context.active_object
261 return (obj is not None and obj.type == "ARMATURE")
263 def execute(self, context):
264 try:
265 makeChain(self, context, self.multiplier, self.curverig)
267 except Exception as e:
268 self.report({'WARNING'},
269 "Some operations could not be performed (See Console for more info)")
271 print("\n[Add Advanced Objects]\nOperator: "
272 "mesh.primitive_oscurart_chain_add\nError: {}".format(e))
274 return {'CANCELLED'}
276 return {'FINISHED'}
279 def register():
280 bpy.utils.register_class(MESH_OT_primitive_oscurart_chain_add)
283 def unregister():
284 bpy.utils.unregister_class(MESH_OT_primitive_oscurart_chain_add)
287 if __name__ == "__main__":
288 register()