Don't use context.active_object
[blender-addons.git] / object_cloud_gen.py
blob7d56f9859b17064c567cbfdf4b28e0f15afb91ce
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 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # <pep8 compliant>
21 bl_info = {
22 "name": "Cloud Generator",
23 "author": "Nick Keeline(nrk)",
24 "version": (1, 0),
25 "blender": (2, 75, 0),
26 "location": "Blender Render: Tool Shelf > Create Tab",
27 "description": "Creates Volumetric Clouds",
28 "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
29 "Scripts/Object/Cloud_Gen",
30 "category": "Object",
33 import bpy
34 from bpy.props import BoolProperty, EnumProperty
35 from bpy.types import Operator, Panel
38 # This routine takes an object and deletes all of the geometry in it
39 # and adds a bounding box to it.
40 # It will add or subtract the bound box size by the variable sizeDifference.
42 def getMeshandPutinEditMode(scene, object):
44 # Go into Object Mode
45 bpy.ops.object.mode_set(mode='OBJECT')
47 # Deselect All
48 bpy.ops.object.select_all(action='DESELECT')
50 # Select the object
51 object.select = True
52 scene.objects.active = object
54 # Go into Edit Mode
55 bpy.ops.object.mode_set(mode='EDIT')
57 return object.data
60 def maxAndMinVerts(scene, object):
62 mesh = getMeshandPutinEditMode(scene, object)
63 verts = mesh.vertices
65 #Set the max and min verts to the first vertex on the list
66 maxVert = [verts[0].co[0], verts[0].co[1], verts[0].co[2]]
67 minVert = [verts[0].co[0], verts[0].co[1], verts[0].co[2]]
69 #Create Max and Min Vertex array for the outer corners of the box
70 for vert in verts:
71 #Max vertex
72 if vert.co[0] > maxVert[0]:
73 maxVert[0] = vert.co[0]
74 if vert.co[1] > maxVert[1]:
75 maxVert[1] = vert.co[1]
76 if vert.co[2] > maxVert[2]:
77 maxVert[2] = vert.co[2]
79 #Min Vertex
80 if vert.co[0] < minVert[0]:
81 minVert[0] = vert.co[0]
82 if vert.co[1] < minVert[1]:
83 minVert[1] = vert.co[1]
84 if vert.co[2] < minVert[2]:
85 minVert[2] = vert.co[2]
87 return [maxVert, minVert]
90 def makeObjectIntoBoundBox(scene, object, sizeDifference, takeFromObject):
92 # Let's find the max and min of the reference object,
93 # it can be the same as the destination object
94 [maxVert, minVert] = maxAndMinVerts(scene, takeFromObject)
96 #get objects mesh
97 mesh = getMeshandPutinEditMode(scene, object)
99 #Add the size difference to the max size of the box
100 maxVert[0] = maxVert[0] + sizeDifference
101 maxVert[1] = maxVert[1] + sizeDifference
102 maxVert[2] = maxVert[2] + sizeDifference
104 #subtract the size difference to the min size of the box
105 minVert[0] = minVert[0] - sizeDifference
106 minVert[1] = minVert[1] - sizeDifference
107 minVert[2] = minVert[2] - sizeDifference
109 #Create arrays of verts and faces to be added to the mesh
110 addVerts = []
112 #X high loop
113 addVerts.append([maxVert[0], maxVert[1], maxVert[2]])
114 addVerts.append([maxVert[0], maxVert[1], minVert[2]])
115 addVerts.append([maxVert[0], minVert[1], minVert[2]])
116 addVerts.append([maxVert[0], minVert[1], maxVert[2]])
118 #x low loop
119 addVerts.append([minVert[0], maxVert[1], maxVert[2]])
120 addVerts.append([minVert[0], maxVert[1], minVert[2]])
121 addVerts.append([minVert[0], minVert[1], minVert[2]])
122 addVerts.append([minVert[0], minVert[1], maxVert[2]])
124 # Make the faces of the bounding box.
125 addFaces = []
127 # Draw a box on paper and number the vertices.
128 # Use right hand rule to come up with number orders for faces on
129 # the box (with normals pointing out).
130 addFaces.append([0, 3, 2, 1])
131 addFaces.append([4, 5, 6, 7])
132 addFaces.append([0, 1, 5, 4])
133 addFaces.append([1, 2, 6, 5])
134 addFaces.append([2, 3, 7, 6])
135 addFaces.append([0, 4, 7, 3])
137 # Delete all geometry from the object.
138 bpy.ops.mesh.select_all(action='SELECT')
139 bpy.ops.mesh.delete(type='VERT')
141 # Must be in object mode for from_pydata to work
142 bpy.ops.object.mode_set(mode='OBJECT')
144 # Add the mesh data.
145 mesh.from_pydata(addVerts, [], addFaces)
147 # Update the mesh
148 mesh.update()
151 def applyScaleRotLoc(scene, obj):
152 # Deselect All
153 bpy.ops.object.select_all(action='DESELECT')
155 # Select the object
156 obj.select = True
157 scene.objects.active = obj
159 bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
162 def totallyDeleteObject(scene, obj):
163 scene.objects.unlink(obj)
164 bpy.data.objects.remove(obj)
167 def makeParent(parentobj, childobj, scene):
169 applyScaleRotLoc(scene, parentobj)
170 applyScaleRotLoc(scene, childobj)
171 childobj.parent = parentobj
174 def addNewObject(scene, name, copyobj):
176 # Create new mesh
177 mesh = bpy.data.meshes.new(name)
179 # Create a new object.
180 ob_new = bpy.data.objects.new(name, mesh)
181 tempme = copyobj.data
182 ob_new.data = tempme.copy()
183 ob_new.scale = copyobj.scale
184 ob_new.location = copyobj.location
186 # Link new object to the given scene and select it.
187 scene.objects.link(ob_new)
188 ob_new.select = True
190 return ob_new
193 def getpdensitytexture(object):
195 for mslot in object.material_slots:
196 mat = mslot.material
197 for tslot in mat.texture_slots:
198 if tslot != 'NoneType':
199 tex = tslot.texture
200 if tex.type == 'POINT_DENSITY':
201 if tex.point_density.point_source == 'PARTICLE_SYSTEM':
202 return tex
205 def removeParticleSystemFromObj(scene, object):
207 # Deselect All
208 bpy.ops.object.select_all(action='DESELECT')
210 # Select the object.
211 object.select = True
212 scene.objects.active = object
214 bpy.ops.object.particle_system_remove()
216 # Deselect All
217 bpy.ops.object.select_all(action='DESELECT')
220 def convertParticlesToMesh(scene, particlesobj, destobj, replacemesh):
222 # Select the Destination object.
223 destobj.select = True
224 scene.objects.active = destobj
226 #Go to Edit Mode
227 bpy.ops.object.mode_set(mode='EDIT', toggle=False)
229 #Delete everything in mesh if replace true
230 if replacemesh:
231 bpy.ops.mesh.select_all(action='SELECT')
232 bpy.ops.mesh.delete(type='VERT')
234 meshPnts = destobj.data
236 listCloudParticles = particlesobj.particles
238 listMeshPnts = []
239 for pTicle in listCloudParticles:
240 listMeshPnts.append(pTicle.location)
242 # Must be in object mode for from_pydata to work.
243 bpy.ops.object.mode_set(mode='OBJECT')
245 # Add in the mesh data.
246 meshPnts.from_pydata(listMeshPnts, [], [])
248 # Update the mesh.
249 meshPnts.update()
252 def combineObjects(scene, combined, listobjs):
253 # scene is the current scene
254 # combined is the object we want to combine everything into
255 # listobjs is the list of objects to stick into combined
257 # Deselect All
258 bpy.ops.object.select_all(action='DESELECT')
260 # Select the new object.
261 combined.select = True
262 scene.objects.active = combined
264 # Add data
265 if len(listobjs) > 0:
266 for i in listobjs:
267 # Add a modifier
268 bpy.ops.object.modifier_add(type='BOOLEAN')
270 union = combined.modifiers
271 union[0].name = "AddEmUp"
272 union[0].object = i
273 union[0].operation = 'UNION'
275 # Apply modifier
276 bpy.ops.object.modifier_apply(apply_as='DATA', modifier=union[0].name)
279 # Returns the action we want to take
280 def getActionToDo(obj):
282 if not obj or obj.type != 'MESH':
283 return 'NOT_OBJ_DO_NOTHING'
284 elif obj is None:
285 return 'NO_SELECTION_DO_NOTHING'
286 elif "CloudMember" in obj:
287 if obj["CloudMember"] != None:
288 if obj["CloudMember"] == "MainObj":
289 return 'DEGENERATE'
290 elif obj["CloudMember"] == "CreatedObj" and len(obj.particle_systems) > 0:
291 return 'CLOUD_CONVERT_TO_MESH'
292 else:
293 return 'CLOUD_DO_NOTHING'
294 elif obj.type == 'MESH':
295 return 'GENERATE'
296 else:
297 return 'DO_NOTHING'
300 class VIEW3D_PT_tools_cloud(Panel):
301 bl_space_type = 'VIEW_3D'
302 bl_region_type = 'TOOLS'
303 bl_category = 'Create'
304 bl_label = "Cloud Generator"
305 bl_context = "objectmode"
306 bl_options = {'DEFAULT_CLOSED'}
308 def draw(self, context):
309 if context.scene.render.engine == "BLENDER_RENDER":
310 active_obj = context.active_object
311 layout = self.layout
312 col = layout.column(align=True)
314 WhatToDo = getActionToDo(active_obj)
316 if WhatToDo == 'DEGENERATE':
317 col.operator("cloud.generate_cloud", text="DeGenerate")
319 elif WhatToDo == 'CLOUD_CONVERT_TO_MESH':
320 col.operator("cloud.generate_cloud", text="Convert to Mesh")
322 elif WhatToDo == 'NO_SELECTION_DO_NOTHING':
323 col.label(text="Select one or more")
324 col.label(text="objects to generate")
325 col.label(text="a cloud")
327 elif WhatToDo == 'CLOUD_DO_NOTHING':
328 col.label(text="Must select")
329 col.label(text="bound box")
331 elif WhatToDo == 'GENERATE':
332 col.operator("cloud.generate_cloud", text="Generate Cloud")
334 col.prop(context.scene, "cloud_type")
335 col.prop(context.scene, "cloudparticles")
336 col.prop(context.scene, "cloudsmoothing")
337 else:
338 col.label(text="Select one or more")
339 col.label(text="objects to generate")
340 col.label(text="a cloud")
342 if context.scene.render.engine == "CYCLES":
343 layout = self.layout
344 layout.label(text="Blender Render Only")
346 class GenerateCloud(Operator):
347 """Create a Cloud,Undo Cloud, or convert to Mesh Cloud depending on selection"""
348 bl_idname = "cloud.generate_cloud"
349 bl_label = "Generate Cloud"
350 bl_register = True
351 bl_undo = True
353 @classmethod
354 def poll(cls, context):
355 if not context.active_object:
356 return False
357 else:
358 return (context.active_object.type == 'MESH')
361 def execute(self, context):
362 # Make variable that is the current .blend file main data blocks
363 space_data = bpy.context.space_data
365 if True in space_data.layers_local_view:
366 self.report({'INFO'}, 'Global Perspective mode only unable to continue.')
367 return {'FINISHED'}
368 blend_data = context.blend_data
370 # Make variable that is the active object selected by user
371 active_object = context.active_object
373 # Make variable scene that is current scene
374 scene = context.scene
376 # Parameters the user may want to change:
377 # Number of points this number is multiplied by the volume to get
378 # the number of points the scripts will put in the volume.
379 numOfPoints = 1.0
380 maxNumOfPoints = 100000
381 maxPointDensityRadius = 1.5
382 scattering = 2.5
383 pointDensityRadiusFactor = 1.0
384 densityScale = 1.5
386 # What should we do?
387 WhatToDo = getActionToDo(active_object)
389 if WhatToDo == 'DEGENERATE':
390 # Degenerate Cloud
391 mainObj = active_object
393 cloudMembers = active_object.children
395 createdObjects = []
396 definitionObjects = []
397 for member in cloudMembers:
398 applyScaleRotLoc(scene, member)
399 if member["CloudMember"] == "CreatedObj":
400 createdObjects.append(member)
401 else:
402 definitionObjects.append(member)
404 for defObj in definitionObjects:
405 # Delete cloudmember data from objects
406 if "CloudMember" in defObj:
407 del(defObj["CloudMember"])
409 for createdObj in createdObjects:
410 totallyDeleteObject(scene, createdObj)
412 # Delete the blend_data object
413 totallyDeleteObject(scene, mainObj)
415 # Select all of the left over boxes so people can immediately
416 # press generate again if they want.
417 for eachMember in definitionObjects:
418 eachMember.draw_type = 'SOLID'
419 eachMember.select = True
420 eachMember.hide_render = False
422 elif WhatToDo == 'CLOUD_CONVERT_TO_MESH':
424 cloudParticles = active_object.particle_systems.active
426 bounds = active_object.parent
428 ###############Create CloudPnts for putting points in#########
429 # Create a new object cloudPnts
430 cloudPnts = addNewObject(scene, "CloudPoints", bounds)
431 cloudPnts["CloudMember"] = "CreatedObj"
432 cloudPnts.draw_type = 'WIRE'
433 cloudPnts.hide_render = True
435 makeParent(bounds, cloudPnts, scene)
437 convertParticlesToMesh(scene, cloudParticles, cloudPnts, True)
439 removeParticleSystemFromObj(scene, active_object)
441 pDensity = getpdensitytexture(bounds)
442 pDensity.point_density.point_source = 'OBJECT'
443 pDensity.point_density.object = cloudPnts
445 #Let's resize the bound box to be more accurate.
446 how_much_bigger = pDensity.point_density.radius
447 makeObjectIntoBoundBox(scene, bounds, how_much_bigger, cloudPnts)
449 else:
450 # Generate Cloud
452 ###############Create Combined Object bounds##################
453 # Make a list of all Selected objects.
454 selectedObjects = bpy.context.selected_objects
455 if not selectedObjects:
456 selectedObjects = [bpy.context.active_object]
458 # Create a new object bounds
459 bounds = addNewObject(scene,
460 "CloudBounds",
461 selectedObjects[0])
463 bounds.draw_type = 'BOUNDS'
464 bounds.hide_render = False
466 # Just add a Definition Property designating this
467 # as the blend_data object.
468 bounds["CloudMember"] = "MainObj"
470 # Since we used iteration 0 to copy with object we
471 # delete it off the list.
472 firstObject = selectedObjects[0]
473 del selectedObjects[0]
475 # Apply location Rotation and Scale to all objects involved.
476 applyScaleRotLoc(scene, bounds)
477 for each in selectedObjects:
478 applyScaleRotLoc(scene, each)
480 # Let's combine all of them together.
481 combineObjects(scene, bounds, selectedObjects)
483 # Let's add some property info to the objects.
484 for selObj in selectedObjects:
485 selObj["CloudMember"] = "DefinitioinObj"
486 selObj.name = "DefinitioinObj"
487 selObj.draw_type = 'WIRE'
488 selObj.hide_render = True
489 makeParent(bounds, selObj, scene)
491 # Do the same to the 1. object since it is no longer in list.
492 firstObject["CloudMember"] = "DefinitioinObj"
493 firstObject.name = "DefinitioinObj"
494 firstObject.draw_type = 'WIRE'
495 firstObject.hide_render = True
496 makeParent(bounds, firstObject, scene)
498 ###############Create Cloud for putting Cloud Mesh############
499 # Create a new object cloud.
500 cloud = addNewObject(scene, "CloudMesh", bounds)
501 cloud["CloudMember"] = "CreatedObj"
502 cloud.draw_type = 'WIRE'
503 cloud.hide_render = True
505 makeParent(bounds, cloud, scene)
507 bpy.ops.object.editmode_toggle()
508 bpy.ops.mesh.select_all(action='SELECT')
510 #Don't subdivide object or smooth if smoothing box not checked.
511 if scene.cloudsmoothing:
512 bpy.ops.mesh.subdivide(number_cuts=2, fractal=0, smoothness=1)
513 # bpy.ops.object.transform_apply(location=True)
514 bpy.ops.mesh.vertices_smooth(repeat=20)
515 bpy.ops.mesh.tris_convert_to_quads()
516 bpy.ops.mesh.faces_shade_smooth()
517 bpy.ops.object.editmode_toggle()
519 ###############Create Particles in cloud obj##################
521 # Set time to 0.
522 scene.frame_current = 0
524 # Add a new particle system.
525 bpy.ops.object.particle_system_add()
527 #Particle settings setting it up!
528 cloudParticles = cloud.particle_systems.active
529 cloudParticles.name = "CloudParticles"
530 cloudParticles.settings.frame_start = 0
531 cloudParticles.settings.frame_end = 0
532 cloudParticles.settings.emit_from = 'VOLUME'
533 cloudParticles.settings.lifetime = scene.frame_end
534 cloudParticles.settings.draw_method = 'DOT'
535 cloudParticles.settings.render_type = 'NONE'
536 cloudParticles.settings.distribution = 'RAND'
537 cloudParticles.settings.physics_type = 'NEWTON'
538 cloudParticles.settings.normal_factor = 0
540 #Gravity does not effect the particle system
541 eWeights = cloudParticles.settings.effector_weights
542 eWeights.gravity = 0
544 ####################Create Volume Material####################
545 # Deselect All
546 bpy.ops.object.select_all(action='DESELECT')
548 # Select the object.
549 bounds.select = True
550 scene.objects.active = bounds
552 # Turn bounds object into a box. Use itself as a reference.
553 makeObjectIntoBoundBox(scene, bounds, 1.0, bounds)
555 # Delete all material slots in bounds object.
556 for i in range(len(bounds.material_slots)):
557 bounds.active_material_index = i - 1
558 bpy.ops.object.material_slot_remove()
560 # Add a new material.
561 cloudMaterial = blend_data.materials.new("CloudMaterial")
562 bpy.ops.object.material_slot_add()
563 bounds.material_slots[0].material = cloudMaterial
565 # Set Up the Cloud Material
566 cloudMaterial.name = "CloudMaterial"
567 cloudMaterial.type = 'VOLUME'
568 mVolume = cloudMaterial.volume
569 mVolume.scattering = scattering
570 mVolume.density = 0
571 mVolume.density_scale = densityScale
572 mVolume.transmission_color = 3.0, 3.0, 3.0
573 mVolume.step_size = 0.1
574 mVolume.use_light_cache = True
575 mVolume.cache_resolution = 45
577 # Add a texture
578 # vMaterialTextureSlots = cloudMaterial.texture_slots # UNUSED
579 cloudtex = blend_data.textures.new("CloudTex", type='CLOUDS')
580 cloudtex.noise_type = 'HARD_NOISE'
581 cloudtex.noise_scale = 2
582 mtex = cloudMaterial.texture_slots.add()
583 mtex.texture = cloudtex
584 mtex.texture_coords = 'ORCO'
585 mtex.use_map_color_diffuse = True
587 # Set time
588 scene.frame_current = 1
590 # Add a Point Density texture
591 pDensity = blend_data.textures.new("CloudPointDensity", 'POINT_DENSITY')
593 mtex = cloudMaterial.texture_slots.add()
594 mtex.texture = pDensity
595 mtex.texture_coords = 'GLOBAL'
596 mtex.use_map_density = True
597 mtex.use_rgb_to_intensity = True
598 mtex.texture_coords = 'GLOBAL'
600 pDensity.point_density.vertex_cache_space = 'WORLD_SPACE'
601 pDensity.point_density.use_turbulence = True
602 pDensity.point_density.noise_basis = 'VORONOI_F2'
603 pDensity.point_density.turbulence_depth = 3
605 pDensity.use_color_ramp = True
606 pRamp = pDensity.color_ramp
607 #pRamp.use_interpolation = 'LINEAR'
608 pRampElements = pRamp.elements
609 #pRampElements[1].position = .9
610 #pRampElements[1].color = 0.18, 0.18, 0.18, 0.8
611 bpy.ops.texture.slot_move(type='UP')
613 # Estimate the number of particles for the size of bounds.
614 volumeBoundBox = (bounds.dimensions[0] * bounds.dimensions[1] * bounds.dimensions[2])
615 numParticles = int((2.4462 * volumeBoundBox + 430.4) * numOfPoints)
616 if numParticles > maxNumOfPoints:
617 numParticles = maxNumOfPoints
618 if numParticles < 10000:
619 numParticles = int(numParticles + 15 * volumeBoundBox)
620 print(numParticles)
622 # Set the number of particles according to the volume
623 # of bounds.
624 cloudParticles.settings.count = numParticles
626 pDensity.point_density.radius = (.00013764 * volumeBoundBox + .3989) * pointDensityRadiusFactor
628 if pDensity.point_density.radius > maxPointDensityRadius:
629 pDensity.point_density.radius = maxPointDensityRadius
631 # Set time to 1.
632 scene.frame_current = 1
634 if not scene.cloudparticles:
635 ###############Create CloudPnts for putting points in#########
636 # Create a new object cloudPnts
637 cloudPnts = addNewObject(scene, "CloudPoints", bounds)
638 cloudPnts["CloudMember"] = "CreatedObj"
639 cloudPnts.draw_type = 'WIRE'
640 cloudPnts.hide_render = True
642 makeParent(bounds, cloudPnts, scene)
644 convertParticlesToMesh(scene, cloudParticles, cloudPnts, True)
646 # Add a modifier.
647 bpy.ops.object.modifier_add(type='DISPLACE')
649 cldPntsModifiers = cloudPnts.modifiers
650 cldPntsModifiers[0].name = "CloudPnts"
651 cldPntsModifiers[0].texture = cloudtex
652 cldPntsModifiers[0].texture_coords = 'OBJECT'
653 cldPntsModifiers[0].texture_coords_object = cloud
654 cldPntsModifiers[0].strength = -1.4
656 # Apply modifier
657 bpy.ops.object.modifier_apply(apply_as='DATA', modifier=cldPntsModifiers[0].name)
659 pDensity.point_density.point_source = 'OBJECT'
660 pDensity.point_density.object = cloudPnts
662 removeParticleSystemFromObj(scene, cloud)
664 else:
666 pDensity.point_density.point_source = 'PARTICLE_SYSTEM'
667 pDensity.point_density.object = cloud
668 pDensity.point_density.particle_system = cloudParticles
670 if scene.cloud_type == '1': # Cumulous
671 print("Cumulous")
672 mVolume.density_scale = 2.22
673 pDensity.point_density.turbulence_depth = 10
674 pDensity.point_density.turbulence_strength = 6.3
675 pDensity.point_density.turbulence_scale = 2.9
676 pRampElements[1].position = .606
677 pDensity.point_density.radius = pDensity.point_density.radius + 0.1
679 elif scene.cloud_type == '2': # Cirrus
680 print("Cirrus")
681 pDensity.point_density.turbulence_strength = 22
682 mVolume.transmission_color = 3.5, 3.5, 3.5
683 mVolume.scattering = 0.13
685 elif scene.cloud_type == '3': # Explosion
686 mVolume.emission = 1.42
687 mtex.use_rgb_to_intensity = False
688 pRampElements[0].position = 0.825
689 pRampElements[0].color = 0.119, 0.119, 0.119, 1
690 pRampElements[1].position = .049
691 pRampElements[1].color = 1.0, 1.0, 1.0, 0
692 pDensity.point_density.turbulence_strength = 1.5
693 pRampElement1 = pRampElements.new(.452)
694 pRampElement1.color = 0.814, 0.112, 0, 1
695 pRampElement2 = pRampElements.new(.234)
696 pRampElement2.color = 0.814, 0.310, 0.002, 1
697 pRampElement3 = pRampElements.new(0.669)
698 pRampElement3.color = 0.0, 0.0, 0.040, 1
700 # Select the object.
701 bounds.select = True
702 scene.objects.active = bounds
704 #Let's resize the bound box to be more accurate.
705 how_much_bigger = pDensity.point_density.radius + 0.1
707 #If it's a particle cloud use cloud mesh if otherwise use point mesh
708 if not scene.cloudparticles:
709 makeObjectIntoBoundBox(scene, bounds, how_much_bigger, cloudPnts)
710 else:
711 makeObjectIntoBoundBox(scene, bounds, how_much_bigger, cloud)
713 return {'FINISHED'}
716 def register():
717 bpy.utils.register_module(__name__)
719 bpy.types.Scene.cloudparticles = BoolProperty(
720 name="Particles",
721 description="Generate Cloud as Particle System",
722 default=False)
724 bpy.types.Scene.cloudsmoothing = BoolProperty(
725 name="Smoothing",
726 description="Smooth Resultant Geometry From Gen Cloud Operation",
727 default=True)
729 bpy.types.Scene.cloud_type = EnumProperty(
730 name="Type",
731 description="Select the type of cloud to create with material settings",
732 items=[("0", "Stratus", "Generate Stratus_foggy Cloud"),
733 ("1", "Cumulous", "Generate Cumulous_puffy Cloud"),
734 ("2", "Cirrus", "Generate Cirrus_wispy Cloud"),
735 ("3", "Explosion", "Generate Explosion"),
737 default='0')
740 def unregister():
741 bpy.utils.unregister_module(__name__)
743 del bpy.types.Scene.cloudparticles
744 del bpy.types.Scene.cloud_type
747 if __name__ == "__main__":
748 register()