-
Clemens Barth authored
The new addon with a tracker now ... Blendphys.
Clemens Barth authoredThe new addon with a tracker now ... Blendphys.
__init__.py 17.76 KiB
# ##### 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
#
# Main author : Clemens Barth (Blendphys@root-1.de)
# Authors : Clemens Barth, ...
#
# Homepage(Wiki) : http://development.root-1.de/Atomic_Blender.php
# Tracker : ...
#
# Start of project : 2012-03-25 by Clemens Barth
# First publication in Blender : 2012-05-27
# Last modified : 2012-05-27
#
#
#
# To do:
# ======
#
# 1. Include other shapes: icosahedron, dodecahedron
# 2. ...
#
#
bl_info = {
"name": "Atomic Blender - Cluster",
"description": "Creating cluster formed by atoms",
"author": "Clemens Barth",
"version": (0,5),
"blender": (2,6),
"location": "Panel: View 3D - Tools (left side)",
"warning": "",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Add_Mesh/Cluster",
"tracker_url": "http://projects.blender.org/tracker/"
"index.php?func=detail&aid=31618&group_id=153&atid=468",
"category": "Add mesh"
}
import os
import io
import bpy
from bpy.types import Operator, Panel
from bpy_extras.io_utils import ImportHelper, ExportHelper
from bpy.props import (StringProperty,
BoolProperty,
EnumProperty,
IntProperty,
FloatProperty)
from . import add_mesh_cluster
# -----------------------------------------------------------------------------
# GUI
# The panel, which is loaded after the file has been
# chosen via the menu 'File -> Import'
class CLASS_atom_cluster_panel(Panel):
bl_label = "Atomic Blender - Cluster"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOL_PROPS"
def draw(self, context):
layout = self.layout
if len(context.scene.atom_cluster) == 0:
bpy.context.scene.atom_cluster.add()
scn = context.scene.atom_cluster[0]
row = layout.row()
row.label(text="Cluster properties")
box = layout.box()
row = box.row()
row.prop(scn, "shape")
if scn.shape in ["parabolid_square","parabolid_ab","parabolid_abc"]:
row = box.row()
row.prop(scn, "parabol_diameter")
row = box.row()
row.prop(scn, "parabol_height")
else:
row = box.row()
row.prop(scn, "size")
row = box.row()
row.prop(scn, "skin")
row = box.row()
row.prop(scn, "lattice_parameter")
row = box.row()
row.prop(scn, "element")
row = box.row()
row.prop(scn, "radius_type")
row = box.row()
row.prop(scn, "scale_radius")
row = box.row()
row.prop(scn, "scale_distances")
row = layout.row()
row.label(text="Load cluster")
box = layout.box()
row = box.row()
row.operator("atom_cluster.load")
row = box.row()
row.label(text="Number of atoms")
row = box.row()
row.prop(scn, "atom_number_total")
row = box.row()
row.prop(scn, "atom_number_drawn")
row = layout.row()
row.label(text="Modify cluster")
box = layout.box()
row = box.row()
row.label(text="All changes concern:")
row = box.row()
row.prop(scn, "radius_how")
row = box.row()
row.label(text="1. Change type of radii")
row = box.row()
row.prop(scn, "radius_type")
row = box.row()
row.label(text="2. Change atom radii by scale")
row = box.row()
col = row.column()
col.prop(scn, "radius_all")
col = row.column(align=True)
col.operator( "atom_cluster.radius_all_bigger" )
col.operator( "atom_cluster.radius_all_smaller" )
# The properties (gadgets) in the panel. They all go to scene
# during initialization (see end)
class CLASS_atom_cluster_Properties(bpy.types.PropertyGroup):
def Callback_radius_type(self, context):
scn = bpy.context.scene.atom_cluster[0]
DEF_atom_cluster_radius_type(scn.radius_type,
scn.radius_how,)
size = FloatProperty(
name = "Size", default=30.0, min=0.1,
description = "Size of cluster in Angstroem")
skin = FloatProperty(
name = "Skin", default=1.0, min=0.0, max = 1.0,
description = "Skin of cluster in % of size (skin=1.0: show all atoms, skin=0.1: show only the outer atoms)")
parabol_diameter = FloatProperty(
name = "Diameter", default=30.0, min=0.1,
description = "Top diameter in Angstroem")
parabol_height = FloatProperty(
name = "Height", default=30.0, min=0.1,
description = "Height in Angstroem")
shape = EnumProperty(
name="",
description="Choose the shape of the cluster",
items=(('sphere_square', "Sphere - square", "Sphere with square lattice"),
('sphere_hex_ab', "Sphere - hex ab", "Sphere with hexagonal ab-lattice"),
('sphere_hex_abc', "Sphere - hex abc", "Sphere with hexagonal abc-lattice"),
('pyramide_square', "Pyramide - Square", "Pyramide: square (abc-lattice)"),
('pyramide_hex_abc', "Pyramide - Tetraeder", "Pyramide: tetraeder (abcabc-lattice)"),
('octahedron', "Octahedron", "Octahedron"),
('truncated_octahedron', "Truncated octahedron", "Truncated octahedron"),
('parabolid_square', "Paraboloid: square", "Paraboloid with square lattice"),
('parabolid_ab', "Paraboloid: hex ab", "Paraboloid with ab-lattice"),
('parabolid_abc', "Paraboloid: hex abc", "Paraboloid with abc-lattice")),
default='sphere_square',)
lattice_parameter = FloatProperty(
name = "Lattice", default=4.0, min=0.1,
description = "Lattice parameter in Angstroem")
element = StringProperty(name="Element",
default="Gold", description = "Enter the name of the element")
radius_type = EnumProperty(
name="Radius",
description="Which type of atom radii?",
items=(('0',"predefined", "Use pre-defined radii"),
('1',"atomic", "Use atomic radii"),
('2',"van der Waals","Use van der Waals radii")),
default='0',)
scale_radius = FloatProperty(
name = "Scale R", default=1.0, min=0.0,
description = "Scale radius of atoms")
scale_distances = FloatProperty(
name = "Scale d", default=1.0, min=0.0,
description = "Scale distances")
atom_number_total = StringProperty(name="Total",
default="---", description = "Number of all atoms in the cluster")
atom_number_drawn = StringProperty(name="Drawn",
default="---", description = "Number of drawn atoms in the cluster")
radius_how = EnumProperty(
name="",
description="Which objects shall be modified?",
items=(('ALL_ACTIVE',"all active objects", "in the current layer"),
('ALL_IN_LAYER',"all"," in active layer(s)")),
default='ALL_ACTIVE',)
radius_type = EnumProperty(
name="Type",
description="Which type of atom radii?",
items=(('0',"predefined", "Use pre-defined radii"),
('1',"atomic", "Use atomic radii"),
('2',"van der Waals","Use van der Waals radii")),
default='0',update=Callback_radius_type)
radius_all = FloatProperty(
name="Scale", default = 1.05, min=0.0,
description="Put in the scale factor")
# The button for reloading the atoms and creating the scene
class CLASS_atom_cluster_load_button(Operator):
bl_idname = "atom_cluster.load"
bl_label = "Load"
bl_description = "Load the cluster"
def execute(self, context):
scn = context.scene.atom_cluster[0]
add_mesh_cluster.DEF_atom_read_atom_data()
add_mesh_cluster.ATOM_CLUSTER_ALL_ATOMS[:] = []
print(scn.shape)
if scn.shape in ["parabolid_ab", "parabolid_abc", "parabolid_square"]:
parameter1 = scn.parabol_height
parameter2 = scn.parabol_diameter
elif scn.shape == "pyramide_hex_abc":
parameter1 = scn.size * 1.6
parameter2 = scn.skin
elif scn.shape == "pyramide_square":
parameter1 = scn.size * 1.4
parameter2 = scn.skin
elif scn.shape in ["octahedron", "truncated_octahedron"]:
parameter1 = scn.size * 1.4
parameter2 = scn.skin
else:
parameter1 = scn.size
parameter2 = scn.skin
if scn.shape in ["octahedron", "truncated_octahedron", "sphere_square", "pyramide_square", "parabolid_square"]:
numbers = add_mesh_cluster.create_square_lattice(
scn.shape,
parameter1,
parameter2,
(scn.lattice_parameter/2.0))
if scn.shape in ["sphere_hex_ab", "parabolid_ab"]:
numbers = add_mesh_cluster.create_hexagonal_abab_lattice(
scn.shape,
parameter1,
parameter2,
scn.lattice_parameter)
if scn.shape in ["sphere_hex_abc", "pyramide_hex_abc", "parabolid_abc"]:
numbers = add_mesh_cluster.create_hexagonal_abcabc_lattice(
scn.shape,
parameter1,
parameter2,
scn.lattice_parameter)
DEF_atom_draw_atoms(scn.element,
scn.radius_type,
scn.scale_radius,
scn.scale_distances)
scn.atom_number_total = str(numbers[0])
scn.atom_number_drawn = str(numbers[1])
return {'FINISHED'}
def DEF_atom_draw_atoms(prop_element,
prop_radius_type,
prop_scale_radius,
prop_scale_distances):
current_layers=bpy.context.scene.layers
for element in add_mesh_cluster.ATOM_CLUSTER_ELEMENTS:
if prop_element in element.name:
number = element.number
name = element.name
color = element.color
radii = element.radii
break
material = bpy.data.materials.new(name)
material.name = name
material.diffuse_color = color
atom_vertices = []
for atom in add_mesh_cluster.ATOM_CLUSTER_ALL_ATOMS:
atom_vertices.append( atom.location * prop_scale_distances )
# Build the mesh
atom_mesh = bpy.data.meshes.new("Mesh_"+name)
atom_mesh.from_pydata(atom_vertices, [], [])
atom_mesh.update()
new_atom_mesh = bpy.data.objects.new(name, atom_mesh)
bpy.context.scene.objects.link(new_atom_mesh)
bpy.ops.surface.primitive_nurbs_surface_sphere_add(
view_align=False, enter_editmode=False,
location=(0,0,0), rotation=(0.0, 0.0, 0.0),
layers=current_layers)
ball = bpy.context.scene.objects.active
ball.scale = (radii[int(prop_radius_type)]*prop_scale_radius,) * 3
ball.active_material = material
ball.parent = new_atom_mesh
new_atom_mesh.dupli_type = 'VERTS'
# ------------------------------------------------------------------------
# SELECT ALL LOADED OBJECTS
bpy.ops.object.select_all(action='DESELECT')
new_atom_mesh.select = True
bpy.context.scene.objects.active = new_atom_mesh
return True
# Routine to modify the radii via the type: predefined, atomic or van der Waals
# Explanations here are also valid for the next 3 DEFs.
def DEF_atom_cluster_radius_type(rtype,how):
if how == "ALL_IN_LAYER":
# Note all layers that are active.
layers = []
for i in range(20):
if bpy.context.scene.layers[i] == True:
layers.append(i)
# Put all objects, which are in the layers, into a list.
change_objects = []
for obj in bpy.context.scene.objects:
for layer in layers:
if obj.layers[layer] == True:
change_objects.append(obj)
# Consider all objects, which are in the list 'change_objects'.
for obj in change_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
for element in add_mesh_cluster.ATOM_CLUSTER_ELEMENTS:
if element.name in obj.name:
obj.children[0].scale = (element.radii[int(rtype)],) * 3
else:
if obj.type == "SURFACE" or obj.type == "MESH":
for element in add_mesh_cluster.ATOM_CLUSTER_ELEMENTS:
if element.name in obj.name:
obj.scale = (element.radii[int(rtype)],) * 3
# Routine to scale the radii of all atoms
def DEF_atom_cluster_radius_all(scale, how):
if how == "ALL_IN_LAYER":
layers = []
for i in range(20):
if bpy.context.scene.layers[i] == True:
layers.append(i)
change_objects = []
for obj in bpy.context.scene.objects:
for layer in layers:
if obj.layers[layer] == True:
change_objects.append(obj)
for obj in change_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
if "Stick" not in obj.name:
obj.children[0].scale *= scale
else:
if obj.type == "SURFACE" or obj.type == "MESH":
if "Stick" not in obj.name:
obj.scale *= scale
if how == "ALL_ACTIVE":
for obj in bpy.context.selected_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
if "Stick" not in obj.name:
obj.children[0].scale *= scale
else:
if obj.type == "SURFACE" or obj.type == "MESH":
if "Stick" not in obj.name:
obj.scale *= scale
# Button for increasing the radii of all atoms
class CLASS_atom_cluster_radius_all_bigger_button(Operator):
bl_idname = "atom_cluster.radius_all_bigger"
bl_label = "Bigger ..."
bl_description = "Increase the radii of the atoms"
def execute(self, context):
scn = bpy.context.scene.atom_cluster[0]
DEF_atom_cluster_radius_all(
scn.radius_all,
scn.radius_how,)
return {'FINISHED'}
# Button for decreasing the radii of all atoms
class CLASS_atom_cluster_radius_all_smaller_button(Operator):
bl_idname = "atom_cluster.radius_all_smaller"
bl_label = "Smaller ..."
bl_description = "Decrease the radii of the atoms"
def execute(self, context):
scn = bpy.context.scene.atom_cluster[0]
DEF_atom_cluster_radius_all(
1.0/scn.radius_all,
scn.radius_how,)
return {'FINISHED'}
# Routine to scale the radii of all atoms
def DEF_atom_cluster_radius_all(scale, how):
if how == "ALL_IN_LAYER":
layers = []
for i in range(20):
if bpy.context.scene.layers[i] == True:
layers.append(i)
change_objects = []
for obj in bpy.context.scene.objects:
for layer in layers:
if obj.layers[layer] == True:
change_objects.append(obj)
for obj in change_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
if "Stick" not in obj.name:
obj.children[0].scale *= scale
else:
if obj.type == "SURFACE" or obj.type == "MESH":
if "Stick" not in obj.name:
obj.scale *= scale
if how == "ALL_ACTIVE":
for obj in bpy.context.selected_objects:
if len(obj.children) != 0:
if obj.children[0].type == "SURFACE" or obj.children[0].type == "MESH":
if "Stick" not in obj.name:
obj.children[0].scale *= scale
else:
if obj.type == "SURFACE" or obj.type == "MESH":
if "Stick" not in obj.name:
obj.scale *= scale
def register_atom_class():
bpy.types.Scene.atom_cluster = bpy.props.CollectionProperty(type=CLASS_atom_cluster_Properties)
bpy.context.scene.atom_cluster.add()
def register():
bpy.utils.register_module(__name__)
register_atom_class()
def unregister():
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()