addons-contrib: more view_layer syntax updates
[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 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.wm.addon_enable(module="add_mesh_" + groupname)
155         else:
156             bpy.ops.wm.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 def register():
198     bpy.utils.register_module(__name__)
199     bpy.types.Scene.Creaprim_Name = bpy.props.StringProperty(
200             name="Name",
201             description="Name for the primitive",
202             maxlen=1024
203             )
204     bpy.types.Scene.Creaprim_Apply = bpy.props.BoolProperty(
205             name="Apply transform",
206             description="Apply transform to selected objects",
207             default=False
208             )
209     bpy.types.VIEW3D_PT_tools_object.append(panel_func)
210     bpy.app.handlers.scene_update_post.append(setname)
211
212
213 def unregister():
214     bpy.utils.unregister_module(__name__)
215     bpy.types.VIEW3D_PT_tools_object.remove(panel_func)
216     bpy.app.handlers.scene_update_post.remove(setname)
217     del bpy.types.Scene.Creaprim_Name
218     del bpy.types.Scene.Creaprim_Apply
219
220
221 if __name__ == "__main__":
222     register()
223
224
225 def do_creaprim(self, mesh, objname, addondir):
226
227     global message
228
229     objname = objname.replace(".", "")
230     objname = objname.replace(" ", "_")
231     bm = bmesh.new()
232     bm.from_mesh(mesh)
233
234     try:
235         txt = bpy.data.texts[str.lower("add_mesh_" + objname) + ".py"]
236         txt.clear()
237     except:
238         txt = bpy.data.texts.new("add_mesh_" + str.lower(objname) + ".py")
239
240     strlist = []
241     strlist.append("# Script autogenerated by object_creaprim.py")
242     strlist.append("\n")
243     strlist.append("bl_info = {\n")
244     strlist.append("    \"name\": \"" + objname + "\",\n")
245     strlist.append("    \"author\": \"Gert De Roost\",\n")
246     strlist.append("    \"version\": (1, 0, 0),\n")
247     strlist.append("    \"blender\": (2, 65, 0),\n")
248     strlist.append("    \"location\": \"Add > Mesh\",\n")
249     strlist.append("    \"description\": \"Create " + objname + " primitive\",\n")
250     strlist.append("    \"warning\": \"\",\n")
251     strlist.append("    \"wiki_url\": \"\",\n")
252     strlist.append("    \"tracker_url\": \"\",\n")
253     strlist.append("    \"category\": \"Add Mesh\"}\n")
254     strlist.append("\n")
255     strlist.append("\n")
256     strlist.append("import bpy\n")
257     strlist.append("import bmesh\n")
258     strlist.append("import math\n")
259     strlist.append("from mathutils import *\n")
260     strlist.append("\n")
261     strlist.append("\n")
262     strlist.append("class " + objname + "(bpy.types.Operator):\n")
263     strlist.append("    bl_idname = \"mesh." + str.lower(objname) + "\"\n")
264     strlist.append("    bl_label = \"" + objname + "\"\n")
265     strlist.append("    bl_options = {\'REGISTER\', \'UNDO\'}\n")
266     strlist.append("    bl_description = \"add " + objname + " primitive\"\n")
267     strlist.append("\n")
268     strlist.append("    def invoke(self, context, event):\n")
269     strlist.append("\n")
270     strlist.append("        mesh = bpy.data.meshes.new(name=\"" + objname + "\")\n")
271     strlist.append("        obj = bpy.data.objects.new(name=\"" + objname + "\", object_data=mesh)\n")
272     strlist.append("        scene = bpy.context.scene\n")
273     strlist.append("        scene.objects.link(obj)\n")
274     strlist.append("        obj.location = scene.cursor_location\n")
275     strlist.append("        bm = bmesh.new()\n")
276     strlist.append("        bm.from_mesh(mesh)\n")
277     strlist.append("\n")
278     strlist.append("        idxlist = []\n")
279     posn = 0
280     strlist.append("        vertlist = [")
281     for v in bm.verts:
282         if posn > 0:
283             strlist.append(", ")
284         posn += 1
285         strlist.append(str(v.co[:]))
286     strlist.append("]\n")
287     strlist.append("        for co in vertlist:\n")
288     strlist.append("            v = bm.verts.new(co)\n")
289     strlist.append("            bm.verts.index_update()\n")
290     strlist.append("            idxlist.append(v.index)\n")
291     posn = 0
292     strlist.append("        edgelist = [")
293     for e in bm.edges:
294         if posn > 0:
295             strlist.append(", ")
296         posn += 1
297         strlist.append("[" + str(e.verts[0].index) + ", " + str(e.verts[1].index) + "]")
298     strlist.append("]\n")
299     strlist.append("        for verts in edgelist:\n")
300     strlist.append("            try:\n")
301     strlist.append("                bm.edges.new((bm.verts[verts[0]], bm.verts[verts[1]]))\n")
302     strlist.append("            except:\n")
303     strlist.append("                pass\n")
304     posn1 = 0
305     strlist.append("        facelist = [(")
306     for f in bm.faces:
307         if posn1 > 0:
308             strlist.append(", (")
309         posn1 += 1
310         posn2 = 0
311         for v in f.verts:
312             if posn2 > 0:
313                 strlist.append(", ")
314             strlist.append(str(v.index))
315             posn2 += 1
316         strlist.append(")")
317     strlist.append("]\n")
318     strlist.append("        bm.verts.ensure_lookup_table()\n")
319     strlist.append("        for verts in facelist:\n")
320     strlist.append("            vlist = []\n")
321     strlist.append("            for idx in verts:\n")
322     strlist.append("                vlist.append(bm.verts[idxlist[idx]])\n")
323     strlist.append("            try:\n")
324     strlist.append("                bm.faces.new(vlist)\n")
325     strlist.append("            except:\n")
326     strlist.append("                pass\n")
327     strlist.append("\n")
328     strlist.append("        bm.to_mesh(mesh)\n")
329     strlist.append("        mesh.update()\n")
330     strlist.append("        bm.free()\n")
331     strlist.append("        obj.rotation_quaternion = (Matrix.Rotation(math.radians(90), 3, \'X\').to_quaternion())\n")
332     strlist.append("\n")
333     strlist.append("        return {\'FINISHED\'}\n")
334
335     strlist.append("\n")
336     strlist.append("\n")
337     strlist.append("def menu_item(self, context):\n")
338     strlist.append("    self.layout.operator(" + objname + ".bl_idname, text=\"" + objname + "\", icon=\"PLUGIN\")\n")
339     strlist.append("\n")
340     strlist.append("\n")
341     strlist.append("def register():\n")
342     strlist.append("    bpy.utils.register_module(__name__)\n")
343     strlist.append("    bpy.types.VIEW3D_MT_mesh_add.append(menu_item)\n")
344     strlist.append("\n")
345     strlist.append("\n")
346     strlist.append("def unregister():\n")
347     strlist.append("    bpy.utils.unregister_module(__name__)\n")
348     strlist.append("    bpy.types.VIEW3D_MT_mesh_add.remove(menu_item)\n")
349     strlist.append("\n")
350     strlist.append("\n")
351     strlist.append("if __name__ == \"__main__\":\n")
352     strlist.append("    register()\n")
353     endstring = ''.join(strlist)
354     txt.write(endstring)
355
356     try:
357         fileobj = open(addondir + "add_mesh_" + str.lower(objname) + ".py", "w")
358     except:
359         message = "Permission problem - cant write file - run Blender as Administrator!"
360         bpy.ops.creaprim.message('INVOKE_DEFAULT')
361         return 0
362
363     fileobj.write(endstring)
364     fileobj.close()
365
366     bm.free()
367
368     return txt
369
370
371 def makeinit(txtlist, namelist, groupname, addondir):
372
373     global message
374
375     try:
376         txt = bpy.data.texts["__init__.py"]
377         txt.clear()
378     except:
379         txt = bpy.data.texts.new("__init__.py")
380
381     strlist = []
382     strlist.append("# Script autogenerated by object_creaprim.py")
383     strlist.append("\n")
384     strlist.append("bl_info = {\n")
385     strlist.append("    \"name\": \"" + groupname + "\",\n")
386     strlist.append("    \"author\": \"Gert De Roost\",\n")
387     strlist.append("    \"version\": (1, 0, 0),\n")
388     strlist.append("    \"blender\": (2, 65, 0),\n")
389     strlist.append("    \"location\": \"Add > Mesh\",\n")
390     strlist.append("    \"description\": \"Create " + groupname + " primitive group\",\n")
391     strlist.append("    \"warning\": \"\",\n")
392     strlist.append("    \"wiki_url\": \"\",\n")
393     strlist.append("    \"tracker_url\": \"\",\n")
394     strlist.append("    \"category\": \"Add Mesh\"}\n")
395     strlist.append("\n")
396     strlist.append("\n")
397     strlist.append("if \"bpy\" in locals():\n")
398     strlist.append("    import importlib\n")
399     addonlist = []
400     for txt in txtlist:
401         name = txt.name.replace(".py", "")
402         addonlist.append(name)
403     for name in addonlist:
404         strlist.append("    importlib.reload(" + name + ")\n")
405     strlist.append("else:\n")
406     for name in addonlist:
407         strlist.append("    from . import " + name + "\n")
408     strlist.append("\n")
409     strlist.append("\n")
410     strlist.append("import bpy\n")
411     strlist.append("\n")
412     strlist.append("\n")
413     strlist.append("class VIEW3D_MT_mesh_" + str.lower(groupname) + "_add(bpy.types.Menu):\n")
414     strlist.append("    bl_idname = \"VIEW3D_MT_mesh_" + str.lower(groupname) + "_add\"\n")
415     strlist.append("    bl_label = \"" + groupname + "\"\n")
416     strlist.append("\n")
417     strlist.append("    def draw(self, context):\n")
418     strlist.append("        layout = self.layout\n")
419
420     for name in namelist:
421         strlist.append("        layout.operator(\"mesh." + str.lower(name) + "\", text=\"" + name + "\")\n")
422     strlist.append("\n")
423     strlist.append("\n")
424     strlist.append("def menu_item(self, context):\n")
425     strlist.append("    self.layout.menu(\"VIEW3D_MT_mesh_" + str.lower(groupname) + "_add\", icon=\"PLUGIN\")\n")
426     strlist.append("\n")
427     strlist.append("\n")
428     strlist.append("def register():\n")
429     strlist.append("    bpy.utils.register_module(__name__)\n")
430     strlist.append("    bpy.types.VIEW3D_MT_mesh_add.append(menu_item)\n")
431     strlist.append("\n")
432     strlist.append("\n")
433     strlist.append("def unregister():\n")
434     strlist.append("    bpy.utils.unregister_module(__name__)\n")
435     strlist.append("    bpy.types.VIEW3D_MT_mesh_add.remove(menu_item)\n")
436     strlist.append("\n")
437     strlist.append("\n")
438     strlist.append("if __name__ == \"__main__\":\n")
439     strlist.append("    register()\n")
440     endstring = ''.join(strlist)
441     txt.write(endstring)
442
443     try:
444         fileobj = open(addondir + "__init__.py", "w")
445     except:
446         message = "Permission problem - cant write file - run Blender as Administrator!"
447         bpy.ops.creaprim.message('INVOKE_DEFAULT')
448         return 0
449
450     fileobj.write(endstring)
451     fileobj.close()
452
453
454 def setname(dummy):
455
456     scn = bpy.context.scene
457     oldname = scn.Creaprim_Name
458
459     if bpy.context.active_object and bpy.context.active_object.name != oldname:
460
461         scn.Creaprim_Name = bpy.context.active_object.name