object_creaprim.py 13.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
# GNU General Public License for more details.
#
# If you have Internet access, you can find the license text at
# http://www.gnu.org/licenses/gpl.txt,
# if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------

22 23 24 25
"""
CreaPrim does what it says. I takes the active object and turns it into an
Add Mesh addon.	When you enable this, your custom object will be added to the
Add->Mesh menu.
26 27 28 29


Documentation

30 31 32 33 34 35 36 37 38 39 40 41
Go to User Preferences->Addons and enable the CreaPrim addon in the Object
section. The addon will show up in the 3dview properties panel.

First select your object or objects.
The name (in panel) will be set to the active object name.
Select "Apply transform" if you want transforms to be applied to the selected
objects. Modifiers will taken into account. You can always change this.
Just hit the button and the selected objects will be saved in your addons folder
as an Add Mesh addon with the name "add_mesh_XXXX.py" with XXXX being your
object name.  The addon will show up in User Preferences->Addons in the
Add Mesh section. Enable this addon et voila, your new custom primitive will
now show up in the Add Mesh menu.
42 43

REMARK - dont need to be admin anymore - saves to user scripts dir
44 45 46

ALSO - dont forget to Apply rotation and scale to have your object
show up correctly
47 48 49
"""

bl_info = {
Brendon Murphy's avatar
Brendon Murphy committed
50 51
    "name": "CreaPrim",
    "author": "Gert De Roost",
Gert De Roost's avatar
Gert De Roost committed
52
    "version": (0, 3, 10),
53
    "blender": (2, 64, 0),
Brendon Murphy's avatar
Brendon Murphy committed
54 55 56
    "location": "View3D > Object Tools",
    "description": "Create primitive addon",
    "warning": "",
57 58
    "wiki_url": "",
    "tracker_url": "https://developer.blender.org/T32801",
Brendon Murphy's avatar
Brendon Murphy committed
59
    "category": "Object"}
60

61

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
if "bpy" in locals():
	import imp


import bpy
import bmesh
import os


started = 0
oldname = ""

bpy.types.Scene.Name = bpy.props.StringProperty(
			name="Name",
			description="name for primitive",
			maxlen= 1024)

bpy.types.Scene.Apply = bpy.props.BoolProperty(
80
		name = "Apply transform",
81 82 83 84 85 86 87
		description = "apply transform to selected objects",
		default = False)


class CreaPrim(bpy.types.Operator):
	bl_idname = "object.creaprim"
	bl_label = "CreaPrim"
Gert De Roost's avatar
Gert De Roost committed
88
	bl_description = "Create primitive addon"
89
	bl_options = {"REGISTER"}
90 91


92 93 94 95 96 97
	@classmethod
	def poll(cls, context):
		obj = context.active_object
		return (obj and obj.type == 'MESH' and context.mode == 'OBJECT')

	def invoke(self, context, event):
98

99
		global oldname, groupname, message
100

101
		scn = bpy.context.scene
102

103 104 105 106
		objlist = []
		for selobj in bpy.context.scene.objects:
			if selobj.select:
				objlist.append(selobj)
107

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
		try:
			direc = bpy.utils.script_paths()[1]
			scriptdir = 1
		except:
			direc = bpy.utils.script_paths()[0]
			scriptdir = 0
		if len(objlist) > 1:
			groupname = scn.Name
			groupname = groupname.replace(".", "")
			addondir = direc + os.sep + "addons" + os.sep + "add_mesh_" + groupname + os.sep
			if not os.path.exists(addondir):
				os.makedirs(addondir)
		else:
			groupname = scn.Name
			print (bpy.utils.script_paths())
			addondir = direc + os.sep + "addons" + os.sep
			print (addondir)
			if not os.path.exists(addondir):
				os.makedirs(addondir)
127

128 129 130 131 132 133
		actobj = bpy.context.active_object
		txtlist = []
		namelist = []
		for selobj in objlist:
			if len(objlist) == 1:
				objname = scn.Name
Gert De Roost's avatar
Gert De Roost committed
134
				objname = objname.replace(" ", "_")
135 136 137
			else:
				objname = selobj.name
				objname = objname.replace(".", "")
Gert De Roost's avatar
Gert De Roost committed
138
				objname = objname.replace(" ", "_")
139 140 141 142 143 144 145 146 147 148 149 150
				namelist.append(objname)
			mesh = selobj.to_mesh(scn, True, "PREVIEW")
			oldname = selobj.name
			scn.objects.active = selobj
			if scn.Apply:
				bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
			txt = do_creaprim(self, mesh, objname, addondir)
			if txt == 0:
				return {'CANCELLED'}
			txtlist.append(txt)
		oldname = actobj.name
		scn.objects.active = actobj
151

152 153 154 155 156
		if len(txtlist) > 1:
			makeinit(txtlist, namelist, groupname, addondir)
			bpy.ops.wm.addon_enable(module="add_mesh_" + groupname)
		else:
			bpy.ops.wm.addon_enable(module="add_mesh_" + str.lower(objname))
157

158 159 160 161 162
		if scriptdir == 1:
			message = "Add Mesh addon " + groupname + " saved to user scripts directory."
		else:
			message = "Add Mesh addon " + groupname + " saved to main scripts directory."
		bpy.ops.creaprim.message('INVOKE_DEFAULT')
163

164 165 166 167 168 169
		return {'FINISHED'}


class MessageOperator(bpy.types.Operator):
	bl_idname = "creaprim.message"
	bl_label = "Saved"
170

171 172 173 174
	def invoke(self, context, event):
		wm = context.window_manager
		return wm.invoke_popup(self, width=500, height=20)
		return {'FINISHED'}
175

176
	def draw(self, context):
177

178
		global groupname
179

180 181 182 183
		layout = self.layout
		row = layout.row()
		row.label(text = '', icon = "PLUGIN")
		row.label(message)
184

185
def panel_func(self, context):
186

187
	global started
188

189
	scn = bpy.context.scene
190

191
	self.layout.label(text="CreaPrim:")
Brendon Murphy's avatar
Brendon Murphy committed
192
	self.layout.operator("object.creaprim", text="Create primitive", icon = 'PLUGIN')
193 194 195 196 197 198 199
	self.layout.prop(scn, "Name")
	self.layout.prop(scn, "Apply")

def register():
	bpy.utils.register_module(__name__)
	bpy.types.VIEW3D_PT_tools_objectmode.append(panel_func)
	bpy.app.handlers.scene_update_post.append(setname)
200

201 202 203 204 205 206 207 208 209 210 211 212
def unregister():
	bpy.utils.unregister_module(__name__)
	bpy.types.VIEW3D_PT_tools_objectmode.remove(panel_func)
	bpy.app.handlers.scene_update_post.remove(setname)

if __name__ == "__main__":
	register()




def do_creaprim(self, mesh, objname, addondir):
213

214
	global message
215

216
	objname = objname.replace(".", "")
Gert De Roost's avatar
Gert De Roost committed
217
	objname = objname.replace(" ", "_")
218
	bm = bmesh.new()
219 220 221
	bm.from_mesh(mesh)


222 223 224 225 226
	try:
		txt = bpy.data.texts[str.lower("add_mesh_" + objname) + ".py"]
		txt.clear()
	except:
		txt = bpy.data.texts.new("add_mesh_" + str.lower(objname) + ".py")
227

228 229 230 231 232
	strlist = []
	strlist.append("bl_info = {\n")
	strlist.append("\"name\": \"" + objname + "\", \n")
	strlist.append("\"author\": \"Gert De Roost\",\n")
	strlist.append("\"version\": (1, 0, 0),\n")
Campbell Barton's avatar
Campbell Barton committed
233
	strlist.append("\"blender\": (2, 65, 0),\n")
234 235 236 237 238 239 240
	strlist.append("\"location\": \"Add > Mesh\",\n")
	strlist.append("\"description\": \"Create " + objname + " primitive.\",\n")
	strlist.append("\"warning\": \"\",\n")
	strlist.append("\"wiki_url\": \"\",\n")
	strlist.append("\"tracker_url\": \"\",\n")
	strlist.append("\"category\": \"Add Mesh\"}\n")
	strlist.append("\n")
241
	strlist.append("\n")
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
	strlist.append("if \"bpy\" in locals():\n")
	strlist.append("	   import imp\n")
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("import bpy\n")
	strlist.append("import bmesh\n")
	strlist.append("import math\n")
	strlist.append("from mathutils import *\n")
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("class " + objname + "(bpy.types.Operator):\n")
	strlist.append("	bl_idname = \"mesh." + str.lower(objname) + "\"\n")
	strlist.append("	bl_label = \"" + objname + "\"\n")
	strlist.append("	bl_options = {\'REGISTER\', \'UNDO\'}\n")
	strlist.append("	bl_description = \"add " + objname + " primitive\"\n")
	strlist.append("\n")
	strlist.append("	def invoke(self, context, event):\n")
	strlist.append("\n")
	strlist.append("		mesh = bpy.data.meshes.new(name=\"" + objname + "\")\n")
	strlist.append("		obj = bpy.data.objects.new(name=\"" + objname + "\", object_data=mesh)\n")
	strlist.append("		scene = bpy.context.scene\n")
	strlist.append("		scene.objects.link(obj)\n")
	strlist.append("		obj.location = scene.cursor_location\n")
	strlist.append("		bm = bmesh.new()\n")
	strlist.append("		bm.from_mesh(mesh)\n")
	strlist.append("\n")
	strlist.append("		idxlist = []\n")
	posn = 0
	strlist.append("		vertlist = [")
	for v in bm.verts:
		if posn > 0:
			strlist.append(", ")
		posn += 1
		strlist.append(str(v.co[:]))
278
	strlist.append("]\n")
279 280 281 282 283 284 285 286 287 288 289
	strlist.append("		for co in vertlist:\n")
	strlist.append("			v = bm.verts.new(co)\n")
	strlist.append("			bm.verts.index_update()\n")
	strlist.append("			idxlist.append(v.index)\n")
	posn = 0
	strlist.append("		edgelist = [")
	for e in bm.edges:
		if posn > 0:
			strlist.append(", ")
		posn += 1
		strlist.append("[" + str(e.verts[0].index) + ", " + str(e.verts[1].index) + "]")
290
	strlist.append("]\n")
291
	strlist.append("		for verts in edgelist:\n")
Gert De Roost's avatar
Gert De Roost committed
292 293 294 295
	strlist.append("			try:\n")
	strlist.append("				bm.edges.new((bm.verts[verts[0]], bm.verts[verts[1]]))\n")
	strlist.append("			except:\n")
	strlist.append("				pass\n")
296 297 298 299 300 301 302 303 304 305 306 307 308
	posn1 = 0
	strlist.append("		facelist = [(")
	for f in bm.faces:
		if posn1 > 0:
			strlist.append(", (")
		posn1 += 1
		posn2 = 0
		for v in f.verts:
			if posn2 > 0:
				strlist.append(", ")
			strlist.append(str(v.index))
			posn2 += 1
		strlist.append(")")
309
	strlist.append("]\n")
310
	strlist.append("		for verts in facelist:\n")
311 312 313
	strlist.append("			vlist = []\n")
	strlist.append("			for idx in verts:\n")
	strlist.append("				vlist.append(bm.verts[idxlist[idx]])\n")
Gert De Roost's avatar
Gert De Roost committed
314 315 316 317
	strlist.append("			try:\n")
	strlist.append("				bm.faces.new(vlist)\n")
	strlist.append("			except:\n")
	strlist.append("				pass\n")
318 319 320
	strlist.append("\n")
	strlist.append("		bm.to_mesh(mesh)\n")
	strlist.append("		mesh.update()\n")
321
	strlist.append("		bm.free()\n")
322 323 324
	strlist.append("		obj.rotation_quaternion = (Matrix.Rotation(math.radians(90), 3, \'X\').to_quaternion())\n")
	strlist.append("\n")
	strlist.append("		return {\'FINISHED\'}\n")
325 326

	strlist.append("\n")
327 328 329
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("\n")
330
	strlist.append("def menu_item(self, context):\n")
331
	strlist.append("	   self.layout.operator(" + objname + ".bl_idname, text=\"" + objname + "\", icon=\"PLUGIN\")\n")
332
	strlist.append("\n")
333 334 335
	strlist.append("def register():\n")
	strlist.append("	   bpy.utils.register_module(__name__)\n")
	strlist.append("	   bpy.types.INFO_MT_mesh_add.append(menu_item)\n")
336
	strlist.append("\n")
337 338 339
	strlist.append("def unregister():\n")
	strlist.append("	   bpy.utils.unregister_module(__name__)\n")
	strlist.append("	   bpy.types.INFO_MT_mesh_add.remove(menu_item)\n")
340 341 342
	strlist.append("\n")
	strlist.append("if __name__ == \"__main__\":\n")
	strlist.append("	   register()\n")
343 344
	endstring = ''.join(strlist)
	txt.write(endstring)
345

346 347 348 349 350 351 352 353 354
	try:
		fileobj = open(addondir + "add_mesh_" + str.lower(objname) + ".py", "w")
	except:
		message = "Permission problem - cant write file - run Blender as Administrator!"
		bpy.ops.creaprim.message('INVOKE_DEFAULT')
		return 0

	fileobj.write(endstring)
	fileobj.close()
355

356
	bm.free()
357

358
	return txt
359 360


361
def makeinit(txtlist, namelist, groupname, addondir):
362

363
	global message
364

365 366 367 368 369
	try:
		txt = bpy.data.texts["__init__.py"]
		txt.clear()
	except:
		txt = bpy.data.texts.new("__init__.py")
370

371 372 373 374 375
	strlist = []
	strlist.append("bl_info = {\n")
	strlist.append("\"name\": \"" + groupname + "\", \n")
	strlist.append("\"author\": \"Gert De Roost\",\n")
	strlist.append("\"version\": (1, 0, 0),\n")
Campbell Barton's avatar
Campbell Barton committed
376
	strlist.append("\"blender\": (2, 65, 0),\n")
377 378 379 380 381 382 383
	strlist.append("\"location\": \"Add > Mesh\",\n")
	strlist.append("\"description\": \"Create " + groupname + " primitive group.\",\n")
	strlist.append("\"warning\": \"\",\n")
	strlist.append("\"wiki_url\": \"\",\n")
	strlist.append("\"tracker_url\": \"\",\n")
	strlist.append("\"category\": \"Add Mesh\"}\n")
	strlist.append("\n")
384
	strlist.append("\n")
385 386 387 388 389 390 391
	strlist.append("if \"bpy\" in locals():\n")
	strlist.append("	import imp\n")
	addonlist = []
	for txt in txtlist:
		name = txt.name.replace(".py", "")
		addonlist.append(name)
	for name in addonlist:
392
		strlist.append("	imp.reload(" + name + ")\n")
393 394
	strlist.append("else:\n")
	for name in addonlist:
395
		strlist.append("	from . import " + name + "\n")
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("import bpy\n")
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("class INFO_MT_mesh_" + str.lower(groupname) + "_add(bpy.types.Menu):\n")
	strlist.append("	bl_idname = \"INFO_MT_mesh_" + str.lower(groupname) + "_add\"\n")
	strlist.append("	bl_label = \"" + groupname + "\"\n")
	strlist.append("\n")
	strlist.append("	def draw(self, context):\n")
	strlist.append("		layout = self.layout\n")
#		 layout.operator_context = 'INVOKE_REGION_WIN'
	for name in namelist:
		strlist.append("		layout.operator(\"mesh." + str.lower(name) + "\", text=\"" + name + "\")\n")
	strlist.append("\n")
	strlist.append("\n")
	strlist.append("\n")
415 416
	strlist.append("\n")
	strlist.append("def menu_item(self, context):\n")
417
	strlist.append("	   self.layout.menu(\"INFO_MT_mesh_" + str.lower(groupname) + "_add\", icon=\"PLUGIN\")\n")
418
	strlist.append("\n")
419 420 421
	strlist.append("def register():\n")
	strlist.append("	   bpy.utils.register_module(__name__)\n")
	strlist.append("	   bpy.types.INFO_MT_mesh_add.append(menu_item)\n")
422
	strlist.append("\n")
423 424 425
	strlist.append("def unregister():\n")
	strlist.append("	   bpy.utils.unregister_module(__name__)\n")
	strlist.append("	   bpy.types.INFO_MT_mesh_add.remove(menu_item)\n")
426 427 428
	strlist.append("\n")
	strlist.append("if __name__ == \"__main__\":\n")
	strlist.append("	   register()\n")
429 430
	endstring = ''.join(strlist)
	txt.write(endstring)
431

432 433 434 435 436 437 438 439 440 441 442 443
	try:
		fileobj = open(addondir + "__init__.py", "w")
	except:
		message = "Permission problem - cant write file - run Blender as Administrator!"
		bpy.ops.creaprim.message('INVOKE_DEFAULT')
		return 0
	fileobj.write(endstring)
	fileobj.close()



def setname(dummy):
444

445
	global oldname
446

447
	scn = bpy.context.scene
448

449 450 451
	if bpy.context.active_object.name != oldname:
		scn.Name = bpy.context.active_object.name
		oldname = scn.Name
452 453 454



455