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 #####
22 "name": "Cloud Generator",
23 "author": "Nick Keeline(nrk)",
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",
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):
45 bpy
.ops
.object.mode_set(mode
='OBJECT')
48 bpy
.ops
.object.select_all(action
='DESELECT')
52 scene
.objects
.active
= object
55 bpy
.ops
.object.mode_set(mode
='EDIT')
60 def maxAndMinVerts(scene
, object):
62 mesh
= getMeshandPutinEditMode(scene
, object)
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
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]
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
)
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
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]])
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.
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')
145 mesh
.from_pydata(addVerts
, [], addFaces
)
151 def applyScaleRotLoc(scene
, obj
):
153 bpy
.ops
.object.select_all(action
='DESELECT')
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
):
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
)
193 def getpdensitytexture(object):
195 for mslot
in object.material_slots
:
197 for tslot
in mat
.texture_slots
:
198 if tslot
!= 'NoneType':
200 if tex
.type == 'POINT_DENSITY':
201 if tex
.point_density
.point_source
== 'PARTICLE_SYSTEM':
205 def removeParticleSystemFromObj(scene
, object):
208 bpy
.ops
.object.select_all(action
='DESELECT')
212 scene
.objects
.active
= object
214 bpy
.ops
.object.particle_system_remove()
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
227 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
229 #Delete everything in mesh if replace true
231 bpy
.ops
.mesh
.select_all(action
='SELECT')
232 bpy
.ops
.mesh
.delete(type='VERT')
234 meshPnts
= destobj
.data
236 listCloudParticles
= particlesobj
.particles
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
, [], [])
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
258 bpy
.ops
.object.select_all(action
='DESELECT')
260 # Select the new object.
261 combined
.select
= True
262 scene
.objects
.active
= combined
265 if len(listobjs
) > 0:
268 bpy
.ops
.object.modifier_add(type='BOOLEAN')
270 union
= combined
.modifiers
271 union
[0].name
= "AddEmUp"
273 union
[0].operation
= 'UNION'
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'
285 return 'NO_SELECTION_DO_NOTHING'
286 elif "CloudMember" in obj
:
287 if obj
["CloudMember"] != None:
288 if obj
["CloudMember"] == "MainObj":
290 elif obj
["CloudMember"] == "CreatedObj" and len(obj
.particle_systems
) > 0:
291 return 'CLOUD_CONVERT_TO_MESH'
293 return 'CLOUD_DO_NOTHING'
294 elif obj
.type == 'MESH':
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
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")
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":
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"
354 def poll(cls
, context
):
355 if not context
.active_object
:
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.')
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.
380 maxNumOfPoints
= 100000
381 maxPointDensityRadius
= 1.5
383 pointDensityRadiusFactor
= 1.0
387 WhatToDo
= getActionToDo(active_object
)
389 if WhatToDo
== 'DEGENERATE':
391 mainObj
= active_object
393 cloudMembers
= active_object
.children
396 definitionObjects
= []
397 for member
in cloudMembers
:
398 applyScaleRotLoc(scene
, member
)
399 if member
["CloudMember"] == "CreatedObj":
400 createdObjects
.append(member
)
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
)
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
,
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##################
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
544 ####################Create Volume Material####################
546 bpy
.ops
.object.select_all(action
='DESELECT')
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
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
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
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
)
622 # Set the number of particles according to the volume
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
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)
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
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
)
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
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
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
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
)
711 makeObjectIntoBoundBox(scene
, bounds
, how_much_bigger
, cloud
)
717 bpy
.utils
.register_module(__name__
)
719 bpy
.types
.Scene
.cloudparticles
= BoolProperty(
721 description
="Generate Cloud as Particle System",
724 bpy
.types
.Scene
.cloudsmoothing
= BoolProperty(
726 description
="Smooth Resultant Geometry From Gen Cloud Operation",
729 bpy
.types
.Scene
.cloud_type
= EnumProperty(
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"),
741 bpy
.utils
.unregister_module(__name__
)
743 del bpy
.types
.Scene
.cloudparticles
744 del bpy
.types
.Scene
.cloud_type
747 if __name__
== "__main__":