Skip to content
Snippets Groups Projects
Commit 82484e86 authored by Campbell Barton's avatar Campbell Barton
Browse files

removed warning (works in trunk now), also made pep8 edits

parent c6d684b3
No related branches found
No related tags found
No related merge requests found
...@@ -16,23 +16,24 @@ ...@@ -16,23 +16,24 @@
# #
# ##### END GPL LICENSE BLOCK ##### # ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
bl_info = { bl_info = {
"name": "Cloud Generator", "name": "Cloud Generator",
"author": "Nick Keeline(nrk)", "author": "Nick Keeline(nrk)",
"version": (1,0), "version": (1, 0),
"blender": (2, 5, 9), "blender": (2, 5, 9),
"location": "View3D > Tool Shelf > Cloud Generator Panel", "location": "View3D > Tool Shelf > Cloud Generator Panel",
"description": "Creates Volumetric Clouds", "description": "Creates Volumetric Clouds",
"warning": "broken with bmesh", "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\ "Scripts/Object/Cloud_Gen",
"Scripts/Object/Cloud_Gen", "tracker_url": "https://projects.blender.org/tracker/index.php?"
"tracker_url": "https://projects.blender.org/tracker/index.php?"\ "func=detail&aid=22015",
"func=detail&aid=22015",
"category": "Object"} "category": "Object"}
import bpy import bpy
from math import * from bpy.props import BoolProperty, EnumProperty
from bpy.props import * from bpy.types import Operator, Panel
# This routine takes an object and deletes all of the geometry in it # This routine takes an object and deletes all of the geometry in it
...@@ -40,24 +41,25 @@ from bpy.props import * ...@@ -40,24 +41,25 @@ from bpy.props import *
# It will add or subtract the bound box size by the variable sizeDifference. # It will add or subtract the bound box size by the variable sizeDifference.
def getMeshandPutinEditMode(scene, object): def getMeshandPutinEditMode(scene, object):
# Go into Object Mode # Go into Object Mode
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')
# Deselect All # Deselect All
bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_all(action='DESELECT')
# Select the object # Select the object
object.select = True object.select = True
scene.objects.active = object scene.objects.active = object
# Go into Edit Mode # Go into Edit Mode
bpy.ops.object.mode_set(mode='EDIT') bpy.ops.object.mode_set(mode='EDIT')
return object.data return object.data
def maxAndMinVerts(scene, object): def maxAndMinVerts(scene, object):
mesh = getMeshandPutinEditMode(scene, object) mesh = getMeshandPutinEditMode(scene, object)
verts = mesh.vertices verts = mesh.vertices
...@@ -82,12 +84,14 @@ def maxAndMinVerts(scene, object): ...@@ -82,12 +84,14 @@ def maxAndMinVerts(scene, object):
minVert[1] = vert.co[1] minVert[1] = vert.co[1]
if vert.co[2] < minVert[2]: if vert.co[2] < minVert[2]:
minVert[2] = vert.co[2] minVert[2] = vert.co[2]
return [maxVert, minVert] return [maxVert, minVert]
def makeObjectIntoBoundBox(scene, object, sizeDifference, takeFromObject): def makeObjectIntoBoundBox(scene, object, sizeDifference, takeFromObject):
#Let's find the max and min of the reference object, it can be the same as the destination object # Let's find the max and min of the reference object,
# it can be the same as the destination object
[maxVert, minVert] = maxAndMinVerts(scene, takeFromObject) [maxVert, minVert] = maxAndMinVerts(scene, takeFromObject)
#get objects mesh #get objects mesh
...@@ -144,6 +148,7 @@ def makeObjectIntoBoundBox(scene, object, sizeDifference, takeFromObject): ...@@ -144,6 +148,7 @@ def makeObjectIntoBoundBox(scene, object, sizeDifference, takeFromObject):
# Update the mesh # Update the mesh
mesh.update() mesh.update()
def applyScaleRotLoc(scene, obj): def applyScaleRotLoc(scene, obj):
# Deselect All # Deselect All
bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_all(action='DESELECT')
...@@ -153,7 +158,8 @@ def applyScaleRotLoc(scene, obj): ...@@ -153,7 +158,8 @@ def applyScaleRotLoc(scene, obj):
scene.objects.active = obj scene.objects.active = obj
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
def totallyDeleteObject(scene, obj): def totallyDeleteObject(scene, obj):
scene.objects.unlink(obj) scene.objects.unlink(obj)
bpy.data.objects.remove(obj) bpy.data.objects.remove(obj)
...@@ -184,17 +190,19 @@ def addNewObject(scene, name, copyobj): ...@@ -184,17 +190,19 @@ def addNewObject(scene, name, copyobj):
return ob_new return ob_new
def getpdensitytexture(object): def getpdensitytexture(object):
for mslot in object.material_slots: for mslot in object.material_slots:
mat = mslot.material mat = mslot.material
for tslot in mat.texture_slots: for tslot in mat.texture_slots:
if tslot!= 'NoneType': if tslot != 'NoneType':
tex = tslot.texture tex = tslot.texture
if tex.type == 'POINT_DENSITY': if tex.type == 'POINT_DENSITY':
if tex.point_density.point_source == 'PARTICLE_SYSTEM': if tex.point_density.point_source == 'PARTICLE_SYSTEM':
return tex return tex
def removeParticleSystemFromObj(scene, object): def removeParticleSystemFromObj(scene, object):
# Deselect All # Deselect All
...@@ -208,16 +216,17 @@ def removeParticleSystemFromObj(scene, object): ...@@ -208,16 +216,17 @@ def removeParticleSystemFromObj(scene, object):
# Deselect All # Deselect All
bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_all(action='DESELECT')
def convertParticlesToMesh(scene, particlesobj, destobj, replacemesh): def convertParticlesToMesh(scene, particlesobj, destobj, replacemesh):
# Select the Destination object. # Select the Destination object.
destobj.select = True destobj.select = True
scene.objects.active = destobj scene.objects.active = destobj
#Go to Edit Mode #Go to Edit Mode
bpy.ops.object.mode_set(mode='EDIT',toggle=False) bpy.ops.object.mode_set(mode='EDIT', toggle=False)
#Delete everything in mesh if replace true #Delete everything in mesh if replace true
if replacemesh: if replacemesh:
bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.select_all(action='SELECT')
...@@ -240,6 +249,7 @@ def convertParticlesToMesh(scene, particlesobj, destobj, replacemesh): ...@@ -240,6 +249,7 @@ def convertParticlesToMesh(scene, particlesobj, destobj, replacemesh):
# Update the mesh. # Update the mesh.
meshPnts.update() meshPnts.update()
def combineObjects(scene, combined, listobjs): def combineObjects(scene, combined, listobjs):
# scene is the current scene # scene is the current scene
# combined is the object we want to combine everything into # combined is the object we want to combine everything into
...@@ -266,9 +276,10 @@ def combineObjects(scene, combined, listobjs): ...@@ -266,9 +276,10 @@ def combineObjects(scene, combined, listobjs):
# Apply modifier # Apply modifier
bpy.ops.object.modifier_apply(apply_as='DATA', modifier=union[0].name) bpy.ops.object.modifier_apply(apply_as='DATA', modifier=union[0].name)
# Returns the action we want to take # Returns the action we want to take
def getActionToDo(obj): def getActionToDo(obj):
if not obj or obj.type != 'MESH': if not obj or obj.type != 'MESH':
return 'NOT_OBJ_DO_NOTHING' return 'NOT_OBJ_DO_NOTHING'
elif obj is None: elif obj is None:
...@@ -276,7 +287,7 @@ def getActionToDo(obj): ...@@ -276,7 +287,7 @@ def getActionToDo(obj):
elif "CloudMember" in obj: elif "CloudMember" in obj:
if obj["CloudMember"] != None: if obj["CloudMember"] != None:
if obj["CloudMember"] == "MainObj": if obj["CloudMember"] == "MainObj":
return 'DEGENERATE' return 'DEGENERATE'
elif obj["CloudMember"] == "CreatedObj" and len(obj.particle_systems) > 0: elif obj["CloudMember"] == "CreatedObj" and len(obj.particle_systems) > 0:
return 'CLOUD_CONVERT_TO_MESH' return 'CLOUD_CONVERT_TO_MESH'
else: else:
...@@ -286,7 +297,8 @@ def getActionToDo(obj): ...@@ -286,7 +297,8 @@ def getActionToDo(obj):
else: else:
return 'DO_NOTHING' return 'DO_NOTHING'
class VIEW3D_PT_tools_cloud(bpy.types.Panel):
class VIEW3D_PT_tools_cloud(Panel):
bl_space_type = 'VIEW_3D' bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS' bl_region_type = 'TOOLS'
...@@ -314,7 +326,7 @@ class VIEW3D_PT_tools_cloud(bpy.types.Panel): ...@@ -314,7 +326,7 @@ class VIEW3D_PT_tools_cloud(bpy.types.Panel):
elif WhatToDo == 'CLOUD_DO_NOTHING': elif WhatToDo == 'CLOUD_DO_NOTHING':
col.label(text="Must select") col.label(text="Must select")
col.label(text="bound box") col.label(text="bound box")
elif WhatToDo == 'GENERATE': elif WhatToDo == 'GENERATE':
col.operator("cloud.generate_cloud", text="Generate Cloud") col.operator("cloud.generate_cloud", text="Generate Cloud")
...@@ -327,10 +339,10 @@ class VIEW3D_PT_tools_cloud(bpy.types.Panel): ...@@ -327,10 +339,10 @@ class VIEW3D_PT_tools_cloud(bpy.types.Panel):
col.label(text="a cloud") col.label(text="a cloud")
class GenerateCloud(bpy.types.Operator): class GenerateCloud(Operator):
"""Create a Cloud,Undo Cloud, or convert to Mesh Cloud depending on selection"""
bl_idname = "cloud.generate_cloud" bl_idname = "cloud.generate_cloud"
bl_label = "Generate Cloud" bl_label = "Generate Cloud"
bl_description = "Create a Cloud,Undo Cloud, or convert to Mesh Cloud depending on selection"
bl_register = True bl_register = True
bl_undo = True bl_undo = True
...@@ -339,7 +351,7 @@ class GenerateCloud(bpy.types.Operator): ...@@ -339,7 +351,7 @@ class GenerateCloud(bpy.types.Operator):
if not context.active_object: if not context.active_object:
return False return False
else: else:
return (context.active_object.type=='MESH') return (context.active_object.type == 'MESH')
def execute(self, context): def execute(self, context):
# Make variable that is the current .blend file main data blocks # Make variable that is the current .blend file main data blocks
...@@ -367,29 +379,29 @@ class GenerateCloud(bpy.types.Operator): ...@@ -367,29 +379,29 @@ class GenerateCloud(bpy.types.Operator):
if WhatToDo == 'DEGENERATE': if WhatToDo == 'DEGENERATE':
# Degenerate Cloud # Degenerate Cloud
mainObj = active_object mainObj = active_object
cloudMembers = active_object.children cloudMembers = active_object.children
createdObjects = [] createdObjects = []
definitionObjects = [] definitionObjects = []
for member in cloudMembers: for member in cloudMembers:
applyScaleRotLoc(scene, member) applyScaleRotLoc(scene, member)
if member["CloudMember"] == "CreatedObj": if member["CloudMember"] == "CreatedObj":
createdObjects.append(member) createdObjects.append(member)
else: else:
definitionObjects.append(member) definitionObjects.append(member)
for defObj in definitionObjects: for defObj in definitionObjects:
# Delete cloudmember data from objects # Delete cloudmember data from objects
if "CloudMember" in defObj: if "CloudMember" in defObj:
del(defObj["CloudMember"]) del(defObj["CloudMember"])
for createdObj in createdObjects: for createdObj in createdObjects:
totallyDeleteObject(scene, createdObj) totallyDeleteObject(scene, createdObj)
# Delete the blend_data object # Delete the blend_data object
totallyDeleteObject(scene, mainObj) totallyDeleteObject(scene, mainObj)
# Select all of the left over boxes so people can immediately # Select all of the left over boxes so people can immediately
# press generate again if they want. # press generate again if they want.
for eachMember in definitionObjects: for eachMember in definitionObjects:
...@@ -400,17 +412,17 @@ class GenerateCloud(bpy.types.Operator): ...@@ -400,17 +412,17 @@ class GenerateCloud(bpy.types.Operator):
elif WhatToDo == 'CLOUD_CONVERT_TO_MESH': elif WhatToDo == 'CLOUD_CONVERT_TO_MESH':
cloudParticles = active_object.particle_systems.active cloudParticles = active_object.particle_systems.active
bounds = active_object.parent bounds = active_object.parent
###############Create CloudPnts for putting points in######### ###############Create CloudPnts for putting points in#########
# Create a new object cloudPnts # Create a new object cloudPnts
cloudPnts = addNewObject(scene, "CloudPoints", bounds) cloudPnts = addNewObject(scene, "CloudPoints", bounds)
cloudPnts["CloudMember"] = "CreatedObj" cloudPnts["CloudMember"] = "CreatedObj"
cloudPnts.draw_type = 'WIRE' cloudPnts.draw_type = 'WIRE'
cloudPnts.hide_render = True cloudPnts.hide_render = True
makeParent(bounds, cloudPnts, scene) makeParent(bounds, cloudPnts, scene)
convertParticlesToMesh(scene, cloudParticles, cloudPnts, True) convertParticlesToMesh(scene, cloudParticles, cloudPnts, True)
...@@ -421,7 +433,7 @@ class GenerateCloud(bpy.types.Operator): ...@@ -421,7 +433,7 @@ class GenerateCloud(bpy.types.Operator):
pDensity.point_density.object = cloudPnts pDensity.point_density.object = cloudPnts
#Let's resize the bound box to be more accurate. #Let's resize the bound box to be more accurate.
how_much_bigger = pDensity.point_density.radius how_much_bigger = pDensity.point_density.radius
makeObjectIntoBoundBox(scene, bounds, how_much_bigger, cloudPnts) makeObjectIntoBoundBox(scene, bounds, how_much_bigger, cloudPnts)
else: else:
...@@ -484,9 +496,9 @@ class GenerateCloud(bpy.types.Operator): ...@@ -484,9 +496,9 @@ class GenerateCloud(bpy.types.Operator):
bpy.ops.object.editmode_toggle() bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.select_all(action='SELECT')
#Don't subdivide object or smooth if smoothing box not checked. #Don't subdivide object or smooth if smoothing box not checked.
if scene.cloudsmoothing: if scene.cloudsmoothing:
bpy.ops.mesh.subdivide(number_cuts=2, fractal=0, smoothness=1) bpy.ops.mesh.subdivide(number_cuts=2, fractal=0, smoothness=1)
# bpy.ops.object.transform_apply(location=True) # bpy.ops.object.transform_apply(location=True)
bpy.ops.mesh.vertices_smooth(repeat=20) bpy.ops.mesh.vertices_smooth(repeat=20)
...@@ -518,7 +530,7 @@ class GenerateCloud(bpy.types.Operator): ...@@ -518,7 +530,7 @@ class GenerateCloud(bpy.types.Operator):
#Gravity does not effect the particle system #Gravity does not effect the particle system
eWeights = cloudParticles.settings.effector_weights eWeights = cloudParticles.settings.effector_weights
eWeights.gravity = 0 eWeights.gravity = 0
####################Create Volume Material#################### ####################Create Volume Material####################
# Deselect All # Deselect All
bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_all(action='DESELECT')
...@@ -528,7 +540,7 @@ class GenerateCloud(bpy.types.Operator): ...@@ -528,7 +540,7 @@ class GenerateCloud(bpy.types.Operator):
scene.objects.active = bounds scene.objects.active = bounds
# Turn bounds object into a box. Use itself as a reference. # Turn bounds object into a box. Use itself as a reference.
makeObjectIntoBoundBox(scene, bounds, 1.0, bounds) makeObjectIntoBoundBox(scene, bounds, 1.0, bounds)
# Delete all material slots in bounds object. # Delete all material slots in bounds object.
for i in range(len(bounds.material_slots)): for i in range(len(bounds.material_slots)):
...@@ -547,7 +559,7 @@ class GenerateCloud(bpy.types.Operator): ...@@ -547,7 +559,7 @@ class GenerateCloud(bpy.types.Operator):
mVolume.scattering = scattering mVolume.scattering = scattering
mVolume.density = 0 mVolume.density = 0
mVolume.density_scale = densityScale mVolume.density_scale = densityScale
mVolume.transmission_color = [3, 3, 3] mVolume.transmission_color = 3.0, 3.0, 3.0
mVolume.step_size = 0.1 mVolume.step_size = 0.1
mVolume.use_light_cache = True mVolume.use_light_cache = True
mVolume.cache_resolution = 45 mVolume.cache_resolution = 45
...@@ -567,7 +579,7 @@ class GenerateCloud(bpy.types.Operator): ...@@ -567,7 +579,7 @@ class GenerateCloud(bpy.types.Operator):
# Add a Point Density texture # Add a Point Density texture
pDensity = blend_data.textures.new("CloudPointDensity", 'POINT_DENSITY') pDensity = blend_data.textures.new("CloudPointDensity", 'POINT_DENSITY')
mtex = cloudMaterial.texture_slots.add() mtex = cloudMaterial.texture_slots.add()
mtex.texture = pDensity mtex.texture = pDensity
mtex.texture_coords = 'GLOBAL' mtex.texture_coords = 'GLOBAL'
...@@ -585,19 +597,18 @@ class GenerateCloud(bpy.types.Operator): ...@@ -585,19 +597,18 @@ class GenerateCloud(bpy.types.Operator):
#pRamp.use_interpolation = 'LINEAR' #pRamp.use_interpolation = 'LINEAR'
pRampElements = pRamp.elements pRampElements = pRamp.elements
#pRampElements[1].position = .9 #pRampElements[1].position = .9
#pRampElements[1].color = [.18,.18,.18,.8] #pRampElements[1].color = 0.18, 0.18, 0.18, 0.8
bpy.ops.texture.slot_move(type='UP') bpy.ops.texture.slot_move(type='UP')
# Estimate the number of particles for the size of bounds. # Estimate the number of particles for the size of bounds.
volumeBoundBox = (bounds.dimensions[0] * bounds.dimensions[1]* bounds.dimensions[2]) volumeBoundBox = (bounds.dimensions[0] * bounds.dimensions[1] * bounds.dimensions[2])
numParticles = int((2.4462 * volumeBoundBox + 430.4) * numOfPoints) numParticles = int((2.4462 * volumeBoundBox + 430.4) * numOfPoints)
if numParticles > maxNumOfPoints: if numParticles > maxNumOfPoints:
numParticles = maxNumOfPoints numParticles = maxNumOfPoints
if numParticles < 10000: if numParticles < 10000:
numParticles = int(numParticles + 15 * volumeBoundBox) numParticles = int(numParticles + 15 * volumeBoundBox)
print(numParticles) print(numParticles)
# Set the number of particles according to the volume # Set the number of particles according to the volume
# of bounds. # of bounds.
cloudParticles.settings.count = numParticles cloudParticles.settings.count = numParticles
...@@ -606,7 +617,7 @@ class GenerateCloud(bpy.types.Operator): ...@@ -606,7 +617,7 @@ class GenerateCloud(bpy.types.Operator):
if pDensity.point_density.radius > maxPointDensityRadius: if pDensity.point_density.radius > maxPointDensityRadius:
pDensity.point_density.radius = maxPointDensityRadius pDensity.point_density.radius = maxPointDensityRadius
# Set time to 1. # Set time to 1.
scene.frame_current = 1 scene.frame_current = 1
...@@ -641,49 +652,49 @@ class GenerateCloud(bpy.types.Operator): ...@@ -641,49 +652,49 @@ class GenerateCloud(bpy.types.Operator):
removeParticleSystemFromObj(scene, cloud) removeParticleSystemFromObj(scene, cloud)
else: else:
pDensity.point_density.point_source = 'PARTICLE_SYSTEM' pDensity.point_density.point_source = 'PARTICLE_SYSTEM'
pDensity.point_density.object = cloud pDensity.point_density.object = cloud
pDensity.point_density.particle_system = cloudParticles pDensity.point_density.particle_system = cloudParticles
if scene.cloud_type == '1': # Cumulous if scene.cloud_type == '1': # Cumulous
print("Cumulous") print("Cumulous")
mVolume.density_scale = 2.22 mVolume.density_scale = 2.22
pDensity.point_density.turbulence_depth = 10 pDensity.point_density.turbulence_depth = 10
pDensity.point_density.turbulence_strength = 6.3 pDensity.point_density.turbulence_strength = 6.3
pDensity.point_density.turbulence_scale = 2.9 pDensity.point_density.turbulence_scale = 2.9
pRampElements[1].position = .606 pRampElements[1].position = .606
pDensity.point_density.radius = pDensity.point_density.radius + .1 pDensity.point_density.radius = pDensity.point_density.radius + 0.1
elif scene.cloud_type == '2': # Cirrus elif scene.cloud_type == '2': # Cirrus
print("Cirrus") print("Cirrus")
pDensity.point_density.turbulence_strength = 22 pDensity.point_density.turbulence_strength = 22
mVolume.transmission_color = [3.5, 3.5, 3.5] mVolume.transmission_color = 3.5, 3.5, 3.5
mVolume.scattering = .13 mVolume.scattering = 0.13
elif scene.cloud_type == '3': # Explosion elif scene.cloud_type == '3': # Explosion
mVolume.emission = 1.42 mVolume.emission = 1.42
mtex.use_rgb_to_intensity = False mtex.use_rgb_to_intensity = False
pRampElements[0].position = .825 pRampElements[0].position = 0.825
pRampElements[0].color = [.119,.119,.119,1] pRampElements[0].color = 0.119, 0.119, 0.119, 1
pRampElements[1].position = .049 pRampElements[1].position = .049
pRampElements[1].color = [1.0,1.0,1.0,0] pRampElements[1].color = 1.0, 1.0, 1.0, 0
pDensity.point_density.turbulence_strength = 1.5 pDensity.point_density.turbulence_strength = 1.5
pRampElement1 = pRampElements.new(.452) pRampElement1 = pRampElements.new(.452)
pRampElement1.color = [.814,.112,0,1] pRampElement1.color = 0.814, 0.112, 0, 1
pRampElement2 = pRampElements.new(.234) pRampElement2 = pRampElements.new(.234)
pRampElement2.color = [.814,.310,.002,1] pRampElement2.color = 0.814, 0.310, 0.002, 1
pRampElement3 = pRampElements.new(.669) pRampElement3 = pRampElements.new(0.669)
pRampElement3.color = [0,.0,.040,1] pRampElement3.color = 0.0, 0.0, 0.040, 1
# Select the object. # Select the object.
bounds.select = True bounds.select = True
scene.objects.active = bounds scene.objects.active = bounds
#Let's resize the bound box to be more accurate. #Let's resize the bound box to be more accurate.
how_much_bigger = pDensity.point_density.radius + .1 how_much_bigger = pDensity.point_density.radius + 0.1
#If it's a particle cloud use cloud mesh if otherwise use point mesh #If it's a particle cloud use cloud mesh if otherwise use point mesh
if not scene.cloudparticles: if not scene.cloudparticles:
makeObjectIntoBoundBox(scene, bounds, how_much_bigger, cloudPnts) makeObjectIntoBoundBox(scene, bounds, how_much_bigger, cloudPnts)
else: else:
...@@ -708,10 +719,10 @@ def register(): ...@@ -708,10 +719,10 @@ def register():
bpy.types.Scene.cloud_type = EnumProperty( bpy.types.Scene.cloud_type = EnumProperty(
name="Type", name="Type",
description="Select the type of cloud to create with material settings", description="Select the type of cloud to create with material settings",
items=[("0","Stratus","Generate Stratus_foggy Cloud"), items=[("0", "Stratus", "Generate Stratus_foggy Cloud"),
("1","Cumulous","Generate Cumulous_puffy Cloud"), ("1", "Cumulous", "Generate Cumulous_puffy Cloud"),
("2","Cirrus","Generate Cirrus_wispy Cloud"), ("2", "Cirrus", "Generate Cirrus_wispy Cloud"),
("3","Explosion","Generate Explosion"), ("3", "Explosion", "Generate Explosion"),
], ],
default='0') default='0')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment