Hi everyone, I’m fairly new to Python Scripting and this forum. I wrote a short script which creates a simulation of a cellular automaton system (like the Game Of Life). It isn’t really useful for anything, but it’s kind of funny to play with.
I’m posting it here because I would like to have more experienced coders’ feedback on the script, whether it’s easy to use, if there are bugs, etc. It is not exactly light, because the simulation grid extends to infinity, and the simulation quickly freezes depending on the settings…
I couldn’t find any such script in for blender, but if there are, sorry for the redundancy…
Have fun!
PS. I’m not really sure how to share the script, but since it’s not that heavy and there is no .blend, I guess I’ll just put it here. Please tell me if it’s not the proper way
###########################################################################################################################
#
#
# Use : Make sure you delete every object before using the script, except cubes with a "*_*_*" name format
# To add or remove cells prior to simulation, choose the coordinates for the cell and click add/remove
#
# Use the left and right arrow to navigate the simulation time (one frame = one iteration).
#
# Have fun !
#
###########################################################################################################################
bl_info = {
"name": "Cellular Automaton",
"author": "M.Zob",
"version": (0, 0),
"blender": (2, 6, 5),
"api": 35853,
"location": "View3D > Tool Shelf > Cellular Automaton",
"description": "Creates a cellular automaton system",
"warning": "",
"wiki_url": "",
"tracker_url": "",
"category": "3D View"}
import bpy
###Programme definition
listeCellulesInit = [[0,1,0],[0,0,1],[1,0,0]]
def creerCubes(listeCoordonnees):
for a in range(len(listeCoordonnees)):
bpy.ops.mesh.primitive_cube_add(location = (listeCoordonnees[a][0],listeCoordonnees[a][1],listeCoordonnees[a][2]))
bpy.ops.transform.resize(value=(0.5,0.5,0.5))
nom = str(listeCoordonnees[a][0]) + '_' + str(listeCoordonnees[a][1]) + '_' + str(listeCoordonnees[a][2])
bpy.context.object.name = nom
bpy.data.objects[nom].hide = True
bpy.context.object.keyframe_insert('hide', frame = bpy.context.scene.frame_current - 1, group = "groupAutomate")
bpy.data.objects[nom].hide = False
bpy.context.object.keyframe_insert('hide', frame = bpy.context.scene.frame_current, group = "groupAutomate")
#def init():
# """Initialization"""
# for object in bpy.data.objects:
# object.hide = False
# bpy.ops.object.select_all(action='SELECT')
# bpy.ops.object.delete()
# creerCubes(listeCellulesInit)
def iteration():
nbrIterations = bpy.context.scene.cell_aut_iter
min = bpy.context.scene.cell_aut_min
max = bpy.context.scene.cell_aut_max
for iter in range(0,nbrIterations):
listeCellules = []
coeffCellules = []
bpy.context.scene.frame_set(bpy.context.scene.frame_current + 1)
for object in bpy.data.objects:
if object.hide == False:
nom = object.name
coordonnees = nom.split('_')
###Listing adjacent cells
for x in range(-1,2):
for y in range(-1,2):
for z in range(-1,2):
### Counting nimber of adjacent old cells for each new cell.
if not [int(coordonnees[0])+x, int(coordonnees[1])+y, int(coordonnees[2])+z] in listeCellules:
listeCellules.append([int(coordonnees[0])+x, int(coordonnees[1])+y, int(coordonnees[2])+z])
coeffCellules.append(1)
else:
indexCell = listeCellules.index([int(coordonnees[0])+x, int(coordonnees[1])+y, int(coordonnees[2])+z])
coeffCellules[indexCell] = coeffCellules[indexCell] + 1
object.hide = True
###Creating / showing new cells
for newCell in range(len(listeCellules)):
if coeffCellules[newCell] <= max and coeffCellules[newCell] >= min:
nomNewCell = str(listeCellules[newCell][0]) + "_" + str(listeCellules[newCell][1]) + "_" + str(listeCellules[newCell][2])
if nomNewCell in bpy.data.objects:
bpy.data.objects[nomNewCell].hide = False
if not nomNewCell in bpy.data.objects:
creerCubes([[listeCellules[newCell][0], listeCellules[newCell][1], listeCellules[newCell][2]]])
for object in bpy.data.objects:
object.keyframe_insert('hide', frame = bpy.context.scene.frame_current, group = "groupAutomate")
def main(context):
# init()
iteration()
def ajout(context):
xAjout = bpy.context.scene.cell_aut_x_add
yAjout = bpy.context.scene.cell_aut_y_add
zAjout = bpy.context.scene.cell_aut_z_add
nom = str(xAjout) + "_" + str(yAjout) + "_" + str(zAjout)
if not nom in bpy.data.objects:
creerCubes([[xAjout,yAjout,zAjout]])
elif bpy.data.objects[nom].hide == False:
bpy.data.objects[nom].hide = True
else:
bpy.data.objects[nom].hide = False
###Definition des proprietes de l'operateur
def init_properties():
sc = bpy.types.Scene
sc.cell_aut_min = bpy.props.IntProperty(
name="Min neighbours",
description="Minimum neighbour number for a cell to live on.",
default=3,
min=1,
max=27)
sc.cell_aut_max = bpy.props.IntProperty(
name="Max neighbours",
description="Minimum neighbour number for a cell to live on.",
default=5,
min=1,
max=27)
sc.cell_aut_iter = bpy.props.IntProperty(
name="Iterations",
description="Number of iterations (frames).",
default=3,
min=0,
max=100)
sc.cell_aut_x_add = bpy.props.IntProperty(
name="x",
description="X coordinate for the cell to add / remove.",
default=0)
sc.cell_aut_y_add = bpy.props.IntProperty(
name="y",
description="Y coordinate for the cell to add / remove.",
default=0)
sc.cell_aut_z_add = bpy.props.IntProperty(
name="z",
description="Z coordinate for the cell to add / remove.",
default=0)
def clear_properties():
props = ["cell_aut_min", "cell_aut_max", "cell_aut_iter", "cell_aut_x_add", "cell_aut_y_add", "cell_aut_z_add"]
for p in props:
if bpy.context.window_manager.get(p) != None:
del bpy.context.window_manager[p]
try:
x = getattr(bpy.types.WindowManager, p)
del x
except:
pass
class OperateurAutomateCellulaire(bpy.types.Operator):
bl_label = "Operateur automate cellulaire"
bl_idname = "view3d.automate_cellulaire"
@classmethod
def poll(cls, context):
return (1 is not None)
def execute(self, context):
main(context)
return {'FINISHED'}
class OperateurAutomateCellulaireAjout(bpy.types.Operator):
bl_label = "Operateur automate cellulaire : ajout / retrait"
bl_idname = "view3d.automate_cellulaire_ajout"
@classmethod
def poll(cls, context):
return (1 is not None)
def execute(self, context):
ajout(context)
return {'FINISHED'}
###Definition de l'UI
class PanneauAutomateCellulaire(bpy.types.Panel):
bl_label = "Cellular automaton"
bl_idname = "3D_VIEW_PT_automate_cellulaire"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
def draw(self,context):
sc = context.scene
layout = self.layout
col = layout.column(align = True)
row = col.row(align = True)
row.label("Add / remove cell")
row = col.row(align = True)
row.prop(sc,"cell_aut_x_add")
row.prop(sc,"cell_aut_y_add")
row.prop(sc,"cell_aut_z_add")
row = col.row(align = True)
row.operator("view3d.automate_cellulaire_ajout", text = "Add / remove")
col = layout.column(align = True)
row = col.row(align = True)
row.label("Automaton settings")
row = col.row(align = True)
row.prop(sc, "cell_aut_min")
row.prop(sc, "cell_aut_max")
row = col.row(align = True)
row.prop(sc, "cell_aut_iter")
row = col.row(align = True)
row.operator("view3d.automate_cellulaire", text = "Automaton !")
def register():
init_properties()
bpy.utils.register_class(OperateurAutomateCellulaire)
bpy.utils.register_class(OperateurAutomateCellulaireAjout)
bpy.utils.register_class(PanneauAutomateCellulaire)
def unregister():
clear_properties()
bpy.utils.unregister_class(OperateurAutomateCellulaire)
bpy.utils.unregister_class(OperateurAutomateCellulaireAjout)
bpy.utils.unregister_class(PanneauAutomateCellulaire)
if __name__ == "__main__":
register()