UI: Move Extensions repositories popover to header
[blender-addons-contrib.git] / object_creaprim.py
blobf4d46dee76d712dd289fc23ca3402019946d4ffd
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 # 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.
18 # ###### END GPL LICENCE BLOCK ######
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.
27 Documentation
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.
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.
42 REMARK - dont need to be admin anymore - saves to user scripts dir
44 ALSO - dont forget to Apply rotation and scale to have your object
45 show up correctly
46 """
48 bl_info = {
49 "name": "CreaPrim",
50 "author": "Gert De Roost",
51 "version": (0, 3, 11),
52 "blender": (2, 80, 0),
53 "location": "View3D > Object Tools",
54 "description": "Create primitive addon",
55 "warning": "under construction",
56 "doc_url": "",
57 "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
58 "category": "Object"}
61 import bpy
62 import bmesh
63 import os
66 started = 0
67 oldname = ""
70 def test_data(obj):
71 me = obj.data
72 is_faces = bool(len(me.polygons) > 0)
73 return is_faces
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"}
82 @classmethod
83 def poll(cls, context):
84 obj = context.active_object
85 return (obj and obj.type == 'MESH' and context.mode == 'OBJECT')
87 def invoke(self, context, event):
89 global oldname, groupname, message
91 scn = bpy.context.scene
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)
98 if len(objlist) == 0:
99 self.report({'WARNING'},
100 "Please select Mesh objects containing Polygons. Operation Cancelled")
101 return {"CANCELLED"}
103 try:
104 direc = bpy.utils.script_paths()[1]
105 scriptdir = 1
106 except:
107 direc = bpy.utils.script_paths()[0]
108 scriptdir = 0
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)
124 actobj = context.view_layer.objects.active
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(preserve_all_data_layers=False, depsgraph=None)
137 oldname = selobj.name
138 context.view_layer.objects.active = selobj
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)
144 if txt == 0:
145 return {'CANCELLED'}
147 txtlist.append(txt)
149 oldname = actobj.name
150 context.view_layer.objects.active = actobj
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))
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')
164 return {'FINISHED'}
167 class MessageOperator(bpy.types.Operator):
168 bl_idname = "creaprim.message"
169 bl_label = "Saved"
171 def invoke(self, context, event):
172 wm = context.window_manager
173 return wm.invoke_popup(self, width=500)
175 def draw(self, context):
177 global groupname
179 layout = self.layout
180 row = layout.row()
181 row.label(text='', icon="PLUGIN")
182 row.label(message)
185 def panel_func(self, context):
187 global started
189 scn = bpy.context.scene
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")
197 classes = (
198 CreaPrim,
199 MessageOperator)
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
211 bpy.types.Scene.Creaprim_Apply = bpy.props.BoolProperty(
212 name="Apply transform",
213 description="Apply transform to selected objects",
214 default=False
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)
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
234 if __name__ == "__main__":
235 register()
238 def do_creaprim(self, mesh, objname, addondir):
240 global message
242 objname = objname.replace(".", "")
243 objname = objname.replace(" ", "_")
244 bm = bmesh.new()
245 bm.from_mesh(mesh)
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")
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, 80, 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(" \"doc_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")
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_class(__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_class(__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)
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
377 fileobj.write(endstring)
378 fileobj.close()
380 bm.free()
382 return txt
385 def makeinit(txtlist, namelist, groupname, addondir):
387 global message
389 try:
390 txt = bpy.data.texts["__init__.py"]
391 txt.clear()
392 except:
393 txt = bpy.data.texts.new("__init__.py")
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(" \"doc_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")
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)
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
464 fileobj.write(endstring)
465 fileobj.close()
468 @bpy.app.handlers.persistent
469 def setname(dummy):
471 scn = bpy.context.scene
472 oldname = scn.Creaprim_Name
474 if bpy.context.active_object and bpy.context.active_object.name != oldname:
476 scn.Creaprim_Name = bpy.context.active_object.name