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