Fix T52833: OBJ triangulate doesn't match viewport
[blender-addons.git] / add_advanced_objects_menu / circle_array.py
blobaf5a6a0aefa3a39fc6e14939b4d391597743ee8c
1 # gpl author: Antonis Karvelas
3 # -*- coding: utf-8 -*-
5 bl_info = {
6 "name": "Circle Array",
7 "author": "Antonis Karvelas",
8 "version": (1, 0, 1),
9 "blender": (2, 6, 7),
10 "location": "View3D > Object > Circle_Array",
11 "description": "Uses an existing array and creates an empty, "
12 "rotates it properly and makes a Circle Array",
13 "warning": "",
14 "wiki_url": "",
15 "category": "Mesh"
19 import bpy
20 from bpy.types import Operator
21 from math import radians
24 class Circle_Array(Operator):
25 bl_label = "Circle Array"
26 bl_idname = "objects.circle_array_operator"
27 bl_description = ("Creates an Array Modifier with offset empty object\n"
28 "Works with Mesh, Curve, Text and Surface\n"
29 "Use an object with an existing Array modifier\n"
30 "or rotate the newly created Empty with the name pattern\n"
31 "EMPTY_C_Array_ if the Array doesn't exist (angle: 360/Count)")
33 @classmethod
34 def poll(cls, context):
35 return context.active_object is not None
37 def check_empty_name(self, context):
38 new_name, def_name = "", "EMPTY_C_Array"
39 suffix = 1
40 try:
41 # first slap a simple linear count + 1 for numeric suffix, if it fails
42 # harvest for the rightmost numbers and append the max value
43 list_obj = []
44 obj_all = context.scene.objects
45 list_obj = [obj.name for obj in obj_all if obj.name.startswith(def_name)]
46 new_name = "{}_{}".format(def_name, len(list_obj) + 1)
48 if new_name in list_obj:
49 from re import findall
50 test_num = [findall("\d+", words) for words in list_obj]
51 suffix += max([int(l[-1]) for l in test_num])
52 new_name = "{}_{}".format(def_name, suffix)
53 return new_name
54 except:
55 return None
57 def execute(self, context):
58 is_allowed = True
59 try:
60 allowed_obj = ['MESH', 'CURVE', 'SURFACE', 'FONT']
61 for obj in context.selected_objects:
62 if obj.type not in allowed_obj:
63 is_allowed = False
64 break
66 if not is_allowed:
67 self.report(
68 {"WARNING"},
69 "The Active/Selected objects are not of "
70 "Mesh, Curve, Surface or Font type. Operation Cancelled"
72 return {'CANCELLED'}
74 default_name = self.check_empty_name(context) or "EMPTY_C_Array"
75 bpy.ops.object.modifier_add(type='ARRAY')
77 if len(context.selected_objects) == 2:
78 selected = context.selected_objects
79 lists = [obj for obj in selected if obj != context.active_object]
80 active = lists[0]
81 # check if the list object has a modifier
82 check_mod = None
83 for mod in active.modifiers[:]:
84 if mod.type == "ARRAY":
85 check_mod = mod
86 break
88 if check_mod:
89 check_mod.use_object_offset = True
90 check_mod.use_relative_offset = False
91 else:
92 # fallback
93 bpy.context.scene.objects.active = active
94 bpy.ops.object.modifier_add(type='ARRAY')
95 active.modifiers[0].use_object_offset = True
96 active.modifiers[0].use_relative_offset = False
98 active.modifiers[0].use_object_offset = True
99 active.modifiers[0].use_relative_offset = False
100 active.select = False
101 bpy.context.scene.objects.active = context.active_object
102 bpy.ops.view3d.snap_cursor_to_selected()
104 if active.modifiers[0].offset_object is None:
105 bpy.ops.object.add(type='EMPTY')
106 empty_name = bpy.context.active_object
107 empty_name.name = default_name
108 active.modifiers[0].offset_object = empty_name
109 else:
110 empty_name = active.modifiers[0].offset_object
112 bpy.context.scene.objects.active = active
113 num = active.modifiers["Array"].count
114 rotate_num = 360 / num
115 active.select = True
116 bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
117 empty_name.rotation_euler = (0, 0, radians(rotate_num))
118 empty_name.select = False
119 active.select = True
120 bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
122 return {'FINISHED'}
123 else:
124 active = context.active_object
125 active.modifiers[0].use_object_offset = True
126 active.modifiers[0].use_relative_offset = False
127 bpy.ops.view3d.snap_cursor_to_selected()
129 if active.modifiers[0].offset_object is None:
130 bpy.ops.object.add(type='EMPTY')
131 empty_name = bpy.context.active_object
132 empty_name.name = default_name
133 active.modifiers[0].offset_object = empty_name
134 else:
135 empty_name = active.modifiers[0].offset_object
137 bpy.context.scene.objects.active = active
138 num = active.modifiers["Array"].count
139 rotate_num = 360 / num
140 active.select = True
141 bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
142 empty_name.rotation_euler = (0, 0, radians(rotate_num))
143 empty_name.select = False
144 active.select = True
146 return {'FINISHED'}
148 except Exception as e:
149 self.report({'WARNING'},
150 "Circle Array operator could not be executed (See the console for more info)")
151 print("\n[objects.circle_array_operator]\nError: {}\n".format(e))
153 return {'CANCELLED'}
156 # Register
157 def register():
158 bpy.utils.register_class(Circle_Array)
161 def unregister():
162 bpy.utils.unregister_class(Circle_Array)
165 if __name__ == "__main__":
166 register()