io_export_after_effects: update to 2.8 T63856
[blender-addons-contrib.git] / object_creaprim.py
1 # ###### BEGIN GPL LICENSE BLOCK ######
2 #
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.
7 #
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.
12 #
13 # If you have Internet access, you can find the license text at
14 # http://www.gnu.org/licenses/gpl.txt,
15 # if not, write to the Free Software Foundation,
16 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #
18 # ###### END GPL LICENCE BLOCK ######
19
20
21 """
22 CreaPrim does what it says. I takes the active object and turns it into an
23 Add Mesh addon. When you enable this, your custom object will be added to the
24 Add->Mesh menu.
25
26
27 Documentation
28
29 Go to User Preferences->Addons and enable the CreaPrim addon in the Object
30 section. The addon will show up in the 3dview properties panel.
31
32 First select your object or objects.
33 The name (in panel) will be set to the active object name.
34 Select "Apply transform" if you want transforms to be applied to the selected
35 objects. Modifiers will taken into account. You can always change this.
36 Just hit the button and the selected objects will be saved in your addons folder
37 as an Add Mesh addon with the name "add_mesh_XXXX.py" with XXXX being your
38 object name.  The addon will show up in User Preferences->Addons in the
39 Add Mesh section. Enable this addon et voila, your new custom primitive will
40 now show up in the Add Mesh menu.
41
42 REMARK - dont need to be admin anymore - saves to user scripts dir
43
44 ALSO - dont forget to Apply rotation and scale to have your object
45 show up correctly
46 """
47
48 bl_info = {
49     "name": "CreaPrim",
50     "author": "Gert De Roost",
51     "version": (0, 3, 11),
52     "blender": (2, 64, 0),
53     "location": "View3D > Object Tools",
54     "description": "Create primitive addon",
55     "warning": "",
56     "wiki_url": "",
57     "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
58     "category": "Object"}
59
60
61 import bpy
62 import bmesh
63 import os
64
65
66 started = 0
67 oldname = ""
68
69
70 def test_data(obj):
71     me = obj.data
72     is_faces = bool(len(me.polygons) > 0)
73     return is_faces
74
75
76 class CreaPrim(bpy.types.Operator):
77     bl_idname = "object.creaprim"
78     bl_label = "CreaPrim"
79     bl_description = "Create a primitive add-on"
80     bl_options = {"REGISTER"}
81
82     @classmethod
83     def poll(cls, context):
84         obj = context.active_object
85         return (obj and obj.type == 'MESH' and context.mode == 'OBJECT')
86
87     def invoke(self, context, event):
88
89         global oldname, groupname, message
90
91         scn = bpy.context.scene
92
93         objlist = []
94         for selobj in bpy.context.scene.objects:
95             if selobj.select_get() and test_data(selobj) is True:
96                 objlist.append(selobj)
97
98         if len(objlist) == 0:
99             self.report({'WARNING'},
100                         "Please select Mesh objects containing Polygons. Operation Cancelled")
101             return {"CANCELLED"}
102
103         try:
104             direc = bpy.utils.script_paths()[1]
105             scriptdir = 1
106         except:
107             direc = bpy.utils.script_paths()[0]
108             scriptdir = 0
109
110         if len(objlist) > 1:
111             groupname = scn.Creaprim_Name
112             groupname = groupname.replace(".", "")
113             addondir = direc + os.sep + "addons" + os.sep + "add_mesh_" + groupname + os.sep
114             if not os.path.exists(addondir):
115                 os.makedirs(addondir)
116         else:
117             groupname = scn.Creaprim_Name
118             print(bpy.utils.script_paths())
119             addondir = direc + os.sep + "addons" + os.sep
120             print(addondir)
121             if not os.path.exists(addondir):
122                 os.makedirs(addondir)
123
124         actobj = bpy.context.active_object
125         txtlist = []
126         namelist = []
127         for selobj in objlist:
128             if len(objlist) == 1:
129                 objname = scn.Creaprim_Name
130                 objname = objname.replace(" ", "_")
131             else:
132                 objname = selobj.name
133                 objname = objname.replace(".", "")
134                 objname = objname.replace(" ", "_")
135                 namelist.append(objname)
136             mesh = selobj.to_mesh(scn, True, "PREVIEW")
137             oldname = selobj.name
138             scn.objects.active = selobj
139
140             if scn.Creaprim_Apply:
141                 bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
142             txt = do_creaprim(self, mesh, objname, addondir)
143
144             if txt == 0:
145                 return {'CANCELLED'}
146
147             txtlist.append(txt)
148
149         oldname = actobj.name
150         scn.objects.active = actobj
151
152         if len(txtlist) > 1:
153             makeinit(txtlist, namelist, groupname, addondir)
154             bpy.ops.preferences.addon_enable(module="add_mesh_" + groupname)
155         else:
156             bpy.ops.preferences.addon_enable(module="add_mesh_" + str.lower(objname))
157
158         if scriptdir == 1:
159             message = "Add Mesh addon " + groupname + " saved to user scripts directory."
160         else:
161             message = "Add Mesh addon " + groupname + " saved to main scripts directory."
162         bpy.ops.creaprim.message('INVOKE_DEFAULT')
163
164         return {'FINISHED'}
165
166
167 class MessageOperator(bpy.types.Operator):
168     bl_idname = "creaprim.message"
169     bl_label = "Saved"
170
171     def invoke(self, context, event):
172         wm = context.window_manager
173         return wm.invoke_popup(self, width=500, height=20)
174
175     def draw(self, context):
176
177         global groupname
178
179         layout = self.layout
180         row = layout.row()
181         row.label(text='', icon="PLUGIN")
182         row.label(message)
183
184
185 def panel_func(self, context):
186
187     global started
188
189     scn = bpy.context.scene
190
191     self.layout.label(text="CreaPrim:")
192     self.layout.operator("object.creaprim", text="Create primitive", icon='PLUGIN')
193     self.layout.prop(scn, "Creaprim_Name")
194     self.layout.prop(scn, "Creaprim_Apply")
195
196
197 classes = (
198     CreaPrim,
199     MessageOperator)
200
201
202 def register():
203     for cls in classes:
204         bpy.utils.register_class(cls)
205     #bpy.utils.register_module(__name__)
206     bpy.types.Scene.Creaprim_Name = bpy.props.StringProperty(
207             name="Name",
208             description="Name for the primitive",
209             maxlen=1024
210             )
211     bpy.types.Scene.Creaprim_Apply = bpy.props.BoolProperty(
212             name="Apply transform",
213             description="Apply transform to selected objects",
214             default=False
215             )
216     #bpy.types.VIEW3D_PT_tools_object.append(panel_func)
217     bpy.types.OBJECT_PT_context_object.append(panel_func)
218     #bpy.app.handlers.scene_update_post.append(setname)
219     bpy.app.handlers.depsgraph_update_post.append(setname)
220
221
222 def unregister():
223     #bpy.utils.unregister_module(__name__)
224     for cls in reversed(classes):
225         bpy.utils.unregister_class(cls)
226     #bpy.types.VIEW3D_PT_tools_object.remove(panel_func)
227     bpy.types.OBJECT_PT_context_object.remove(panel_func)
228     #bpy.app.handlers.scene_update_post.remove(setname)
229     bpy.app.handlers.depsgraph_update_post.remove(setname)
230     del bpy.types.Scene.Creaprim_Name
231     del bpy.types.Scene.Creaprim_Apply
232
233
234 if __name__ == "__main__":
235     register()
236
237
238 def do_creaprim(self, mesh, objname, addondir):
239
240     global message
241
242     objname = objname.replace(".", "")
243     objname = objname.replace(" ", "_")
244     bm = bmesh.new()
245     bm.from_mesh(mesh)
246
247     try:
248         txt = bpy.data.texts[str.lower("add_mesh_" + objname) + ".py"]
249         txt.clear()
250     except:
251         txt = bpy.data.texts.new("add_mesh_" + str.lower(objname) + ".py")
252
253     strlist = []
254     strlist.append("# Script autogenerated by object_creaprim.py")
255     strlist.append("\n")
256     strlist.append("bl_info = {\n")
257     strlist.append("    \"name\": \"" + objname + "\",\n")
258     strlist.append("    \"author\": \"Gert De Roost\",\n")
259     strlist.append("    \"version\": (1, 0, 0),\n")
260     strlist.append("    \"blender\": (2, 65, 0),\n")
261     strlist.append("    \"location\": \"Add > Mesh\",\n")
262     strlist.append("    \"description\": \"Create " + objname + " primitive\",\n")
263     strlist.append("    \"warning\": \"\",\n")
264     strlist.append("    \"wiki_url\": \"\",\n")
265     strlist.append("    \"tracker_url\": \"\",\n")
266     strlist.append("    \"category\": \"Add Mesh\"}\n")
267     strlist.append("\n")
268     strlist.append("\n")
269     strlist.append("import bpy\n")
270     strlist.append("import bmesh\n")
271     strlist.append("import math\n")
272     strlist.append("from mathutils import *\n")
273     strlist.append("\n")
274     strlist.append("\n")
275     strlist.append("class " + objname + "(bpy.types.Operator):\n")
276     strlist.append("    bl_idname = \"mesh." + str.lower(objname) + "\"\n")
277     strlist.append("    bl_label = \"" + objname + "\"\n")
278     strlist.append("    bl_options = {\'REGISTER\', \'UNDO\'}\n")
279     strlist.append("    bl_description = \"add " + objname + " primitive\"\n")
280     strlist.append("\n")
281     strlist.append("    def invoke(self, context, event):\n")
282     strlist.append("\n")
283     strlist.append("        mesh = bpy.data.meshes.new(name=\"" + objname + "\")\n")
284     strlist.append("        obj = bpy.data.objects.new(name=\"" + objname + "\", object_data=mesh)\n")
285     strlist.append("        collection = bpy.context.collection\n")
286     strlist.append("        scene = bpy.context.scene\n")
287     strlist.append("        collection.objects.link(obj)\n")
288     strlist.append("        obj.location = scene.cursor.location\n")
289     strlist.append("        bm = bmesh.new()\n")
290     strlist.append("        bm.from_mesh(mesh)\n")
291     strlist.append("\n")
292     strlist.append("        idxlist = []\n")
293     posn = 0
294     strlist.append("        vertlist = [")
295     for v in bm.verts:
296         if posn > 0:
297             strlist.append(", ")
298         posn += 1
299         strlist.append(str(v.co[:]))
300     strlist.append("]\n")
301     strlist.append("        for co in vertlist:\n")
302     strlist.append("            v = bm.verts.new(co)\n")
303     strlist.append("            bm.verts.index_update()\n")
304     strlist.append("            idxlist.append(v.index)\n")
305     posn = 0
306     strlist.append("        edgelist = [")
307     for e in bm.edges:
308         if posn > 0:
309             strlist.append(", ")
310         posn += 1
311         strlist.append("[" + str(e.verts[0].index) + ", " + str(e.verts[1].index) + "]")
312     strlist.append("]\n")
313     strlist.append("        for verts in edgelist:\n")
314     strlist.append("            try:\n")
315     strlist.append("                bm.edges.new((bm.verts[verts[0]], bm.verts[verts[1]]))\n")
316     strlist.append("            except:\n")
317     strlist.append("                pass\n")
318     posn1 = 0
319     strlist.append("        facelist = [(")
320     for f in bm.faces:
321         if posn1 > 0:
322             strlist.append(", (")
323         posn1 += 1
324         posn2 = 0
325         for v in f.verts:
326             if posn2 > 0:
327                 strlist.append(", ")
328             strlist.append(str(v.index))
329             posn2 += 1
330         strlist.append(")")
331     strlist.append("]\n")
332     strlist.append("        bm.verts.ensure_lookup_table()\n")
333     strlist.append("        for verts in facelist:\n")
334     strlist.append("            vlist = []\n")
335     strlist.append("            for idx in verts:\n")
336     strlist.append("                vlist.append(bm.verts[idxlist[idx]])\n")
337     strlist.append("            try:\n")
338     strlist.append("                bm.faces.new(vlist)\n")
339     strlist.append("            except:\n")
340     strlist.append("                pass\n")
341     strlist.append("\n")
342     strlist.append("        bm.to_mesh(mesh)\n")
343     strlist.append("        mesh.update()\n")
344     strlist.append("        bm.free()\n")
345     strlist.append("        obj.rotation_quaternion = (Matrix.Rotation(math.radians(90), 3, \'X\').to_quaternion())\n")
346     strlist.append("\n")
347     strlist.append("        return {\'FINISHED\'}\n")
348
349     strlist.append("\n")
350     strlist.append("\n")
351     strlist.append("def menu_item(self, context):\n")
352     strlist.append("    self.layout.operator(" + objname + ".bl_idname, text=\"" + objname + "\", icon=\"PLUGIN\")\n")
353     strlist.append("\n")
354     strlist.append("\n")
355     strlist.append("def register():\n")
356     strlist.append("    bpy.utils.register_module(__name__)\n")
357     strlist.append("    bpy.types.VIEW3D_MT_mesh_add.append(menu_item)\n")
358     strlist.append("\n")
359     strlist.append("\n")
360     strlist.append("def unregister():\n")
361     strlist.append("    bpy.utils.unregister_module(__name__)\n")
362     strlist.append("    bpy.types.VIEW3D_MT_mesh_add.remove(menu_item)\n")
363     strlist.append("\n")
364     strlist.append("\n")
365     strlist.append("if __name__ == \"__main__\":\n")
366     strlist.append("    register()\n")
367     endstring = ''.join(strlist)
368     txt.write(endstring)
369
370     try:
371         fileobj = open(addondir + "add_mesh_" + str.lower(objname) + ".py", "w")
372     except:
373         message = "Permission problem - cant write file - run Blender as Administrator!"
374         bpy.ops.creaprim.message('INVOKE_DEFAULT')
375         return 0
376
377     fileobj.write(endstring)
378     fileobj.close()
379
380     bm.free()
381
382     return txt
383
384
385 def makeinit(txtlist, namelist, groupname, addondir):
386
387     global message
388
389     try:
390         txt = bpy.data.texts["__init__.py"]
391         txt.clear()
392     except:
393         txt = bpy.data.texts.new("__init__.py")
394
395     strlist = []
396     strlist.append("# Script autogenerated by object_creaprim.py")
397     strlist.append("\n")
398     strlist.append("bl_info = {\n")
399     strlist.append("    \"name\": \"" + groupname + "\",\n")
400     strlist.append("    \"author\": \"Gert De Roost\",\n")
401     strlist.append("    \"version\": (1, 0, 0),\n")
402     strlist.append("    \"blender\": (2, 65, 0),\n")
403     strlist.append("    \"location\": \"Add > Mesh\",\n")
404     strlist.append("    \"description\": \"Create " + groupname + " primitive group\",\n")
405     strlist.append("    \"warning\": \"\",\n")
406     strlist.append("    \"wiki_url\": \"\",\n")
407     strlist.append("    \"tracker_url\": \"\",\n")
408     strlist.append("    \"category\": \"Add Mesh\"}\n")
409     strlist.append("\n")
410     strlist.append("\n")
411     strlist.append("if \"bpy\" in locals():\n")
412     strlist.append("    import importlib\n")
413     addonlist = []
414     for txt in txtlist:
415         name = txt.name.replace(".py", "")
416         addonlist.append(name)
417     for name in addonlist:
418         strlist.append("    importlib.reload(" + name + ")\n")
419     strlist.append("else:\n")
420     for name in addonlist:
421         strlist.append("    from . import " + name + "\n")
422     strlist.append("\n")
423     strlist.append("\n")
424     strlist.append("import bpy\n")
425     strlist.append("\n")
426     strlist.append("\n")
427     strlist.append("class VIEW3D_MT_mesh_" + str.lower(groupname) + "_add(bpy.types.Menu):\n")
428     strlist.append("    bl_idname = \"VIEW3D_MT_mesh_" + str.lower(groupname) + "_add\"\n")
429     strlist.append("    bl_label = \"" + groupname + "\"\n")
430     strlist.append("\n")
431     strlist.append("    def draw(self, context):\n")
432     strlist.append("        layout = self.layout\n")
433
434     for name in namelist:
435         strlist.append("        layout.operator(\"mesh." + str.lower(name) + "\", text=\"" + name + "\")\n")
436     strlist.append("\n")
437     strlist.append("\n")
438     strlist.append("def menu_item(self, context):\n")
439     strlist.append("    self.layout.menu(\"VIEW3D_MT_mesh_" + str.lower(groupname) + "_add\", icon=\"PLUGIN\")\n")
440     strlist.append("\n")
441     strlist.append("\n")
442     strlist.append("def register():\n")
443     strlist.append("    bpy.utils.register_module(__name__)\n")
444     strlist.append("    bpy.types.VIEW3D_MT_mesh_add.append(menu_item)\n")
445     strlist.append("\n")
446     strlist.append("\n")
447     strlist.append("def unregister():\n")
448     strlist.append("    bpy.utils.unregister_module(__name__)\n")
449     strlist.append("    bpy.types.VIEW3D_MT_mesh_add.remove(menu_item)\n")
450     strlist.append("\n")
451     strlist.append("\n")
452     strlist.append("if __name__ == \"__main__\":\n")
453     strlist.append("    register()\n")
454     endstring = ''.join(strlist)
455     txt.write(endstring)
456
457     try:
458         fileobj = open(addondir + "__init__.py", "w")
459     except:
460         message = "Permission problem - cant write file - run Blender as Administrator!"
461         bpy.ops.creaprim.message('INVOKE_DEFAULT')
462         return 0
463
464     fileobj.write(endstring)
465     fileobj.close()
466
467
468 def setname(dummy):
469
470     scn = bpy.context.scene
471     oldname = scn.Creaprim_Name
472
473     if bpy.context.active_object and bpy.context.active_object.name != oldname:
474
475         scn.Creaprim_Name = bpy.context.active_object.name