Cleanup: tabs -> spaces
[blender-addons.git] / io_mesh_atomic / utility_gui.py
blob295d1490fde3661f059e9106991894dd9bb64a5a
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 import bpy
20 from bpy.types import Operator, Panel
21 from bpy.props import (StringProperty,
22 EnumProperty,
23 FloatProperty,
24 BoolProperty)
26 from io_mesh_atomic.utility_panel import choose_objects
27 from io_mesh_atomic.utility_panel import custom_datafile
28 from io_mesh_atomic.utility_panel import custom_datafile_change_atom_props
29 from io_mesh_atomic.utility_panel import separate_atoms
30 from io_mesh_atomic.utility_panel import distance
33 # -----------------------------------------------------------------------------
34 # GUI
36 # The panel.
37 class PANEL_PT_prepare(Panel):
38 bl_label = "Atomic Blender Utilities"
39 bl_space_type = "VIEW_3D"
40 bl_region_type = "UI"
41 bl_options = {'DEFAULT_CLOSED'}
42 bl_category = "Create"
43 bl_idname = "ATOMIC_PT_utilities"
46 # This thing here just guarantees that the panel is NOT opened when the
47 # check box in the addon preferences is not activated! See __init__.py
48 @classmethod
49 def poll(cls, context):
50 pref = context.preferences
51 return pref.addons[__package__].preferences.bool_utility
53 def draw(self, context):
54 layout = self.layout
55 scn = context.scene.atom_blend
57 box = layout.box()
58 col = box.column(align=True)
59 col.label(text="Custom data file")
60 col.prop(scn, "datafile")
61 col.operator("atom_blend.datafile_apply")
63 box = layout.box()
64 col = box.column(align=True)
65 col.label(text="Measure distances")
66 col.operator("atom_blend.button_distance")
67 col.prop(scn, "distance")
69 # This is from Blender 2.79 and does not work in 2.80. However, it
70 # might be useful later on if changed.
72 #box = layout.box()
73 #col = box.column(align=True)
74 #col.label(text="All changes concern:")
75 #col.prop(scn, "action_type")
77 box = layout.box()
78 col = box.column(align=True)
79 col.label(text="Change atom size")
80 col.label(text="1. Type of radii")
81 col.prop(scn, "radius_type")
82 col2 = col.column()
83 col2.active = (scn.radius_type == '3')
84 col2.prop(scn, "radius_type_ionic")
85 col = box.column(align=True)
86 col.label(text="2. Radii in pm")
87 col.prop(scn, "radius_pm_name")
88 col.prop(scn, "radius_pm")
89 col = box.column(align=True)
90 col.label(text="3. Radii by scale")
91 col.prop(scn, "radius_all")
92 row = col.row()
93 row.operator("atom_blend.radius_all_smaller")
94 row.operator("atom_blend.radius_all_bigger")
96 box = layout.box()
97 col = box.column(align=True)
98 col.label(text="Change stick size")
99 col.prop(scn, "sticks_all")
100 row = col.row()
101 row.operator("atom_blend.sticks_all_smaller")
102 row.operator("atom_blend.sticks_all_bigger")
104 box = layout.box()
105 col = box.column(align=True)
106 col.label(text="Change atom shape")
107 col2 = col.column()
108 col2.active = (scn.replace_objs_special == '0')
109 col2.prop(scn, "replace_objs")
110 col2.prop(scn, "replace_objs_material")
111 col.prop(scn, "replace_objs_special")
112 col.operator("atom_blend.replace_atom")
113 col.label(text="Default values")
114 col.operator("atom_blend.default_atoms")
116 box = layout.box()
117 col = box.column(align=True)
118 col.label(text="Separate atoms")
119 col3 = col.column()
120 col3.active = (bpy.context.mode == 'EDIT_MESH')
121 col3.operator("atom_blend.separate_atom")
124 # The properties of buttons etc. in the panel.
125 class PanelProperties(bpy.types.PropertyGroup):
127 def Callback_radius_type(self, context):
128 scn = bpy.context.scene.atom_blend
129 choose_objects("ATOM_RADIUS_TYPE",
130 scn.action_type,
131 None,
132 None,
133 scn.radius_type,
134 scn.radius_type_ionic,
135 None)
136 def Callback_radius_pm(self, context):
137 scn = bpy.context.scene.atom_blend
138 choose_objects("ATOM_RADIUS_PM",
139 scn.action_type,
140 None,
141 [scn.radius_pm_name,
142 scn.radius_pm],
143 None,
144 None,
145 None)
147 datafile: StringProperty(
148 name = "", description="Path to your custom data file",
149 maxlen = 256, default = "", subtype='FILE_PATH')
150 XYZ_file: StringProperty(
151 name = "Path to file", default="",
152 description = "Path of the XYZ file")
153 number_atoms: StringProperty(name="",
154 default="Number", description = "This output shows "
155 "the number of atoms which have been loaded")
156 distance: StringProperty(
157 name="", default="Distance (A)",
158 description="Distance of 2 objects in Angstrom")
159 replace_objs: EnumProperty(
160 name="Shape",
161 description="Choose a different atom shape.",
162 items=(('0',"Unchanged", "Do not change the shape"),
163 ('1a',"Sphere (Mesh)", "Replace with a sphere (Mesh)"),
164 ('1b',"Sphere (NURBS)", "Replace with a sphere (NURBS)"),
165 ('2',"Cube", "Replace with a cube"),
166 ('3',"Plane", "Replace with a plane"),
167 ('4a',"Circle (Mesh)", "Replace with a circle (Mesh)"),
168 ('4b',"Circle (NURBS)", "Replace with a circle (NURBS)"),
169 ('5a',"Icosphere 1", "Replace with a icosphere, subd=1"),
170 ('5b',"Icosphere 2", "Replace with a icosphere, subd=2"),
171 ('5c',"Icosphere 3", "Replace with a icosphere, subd=3"),
172 ('5d',"Icosphere 4", "Replace with a icosphere, subd=4"),
173 ('5e',"Icosphere 5", "Replace with a icosphere, subd=5"),
174 ('6a',"Cylinder (Mesh)", "Replace with a cylinder (Mesh)"),
175 ('6b',"Cylinder (NURBS)", "Replace with a cylinder (NURBS)"),
176 ('7',"Cone", "Replace with a cone"),
177 ('8a',"Torus (Mesh)", "Replace with a torus (Mesh)"),
178 ('8b',"Torus (NURBS)", "Replace with a torus (NURBS)")),
179 default='0',)
180 replace_objs_material: EnumProperty(
181 name="Material",
182 description="Choose a different material.",
183 items=(('0',"Unchanged", "Leave the material unchanged"),
184 ('1',"Normal", "Use normal material (no transparency and reflection)"),
185 ('2',"Transparent", "Use transparent material"),
186 ('3',"Reflecting", "Use reflecting material"),
187 ('4',"Transparent + reflecting", "Use transparent and reflecting material")),
188 default='0',)
189 replace_objs_special: EnumProperty(
190 name="Special",
191 description="Choose a special atom shape.",
192 items=(('0',"None", "Use no special shape."),
193 ('1',"F2+ center", "Replace with a F2+ center"),
194 ('2',"F+ center", "Replace with a F+ center"),
195 ('3',"F0 center", "Replace with a F0 center")),
196 default='0',)
197 action_type: EnumProperty(
198 name="",
199 description="Which objects shall be modified?",
200 items=(('ALL_ACTIVE',"all active objects", "in the current layer"),
201 ('ALL_IN_LAYER',"all in all selected layers",
202 "in selected layer(s)")),
203 default='ALL_ACTIVE',)
204 radius_type: EnumProperty(
205 name="Type",
206 description="Which type of atom radii?",
207 items=(('0',"predefined", "Use pre-defined radii"),
208 ('1',"atomic", "Use atomic radii"),
209 ('2',"van der Waals","Use van der Waals radii"),
210 ('3',"ionic radii", "Use ionic radii")),
211 default='0',update=Callback_radius_type)
212 radius_type_ionic: EnumProperty(
213 name="Charge",
214 description="Charge state of the ions if existing.",
215 items=(('0',"-4", "Charge state -4"),
216 ('1',"-3", "Charge state -3"),
217 ('2',"-2", "Charge state -2"),
218 ('3',"-1", "Charge state -1"),
219 ('4'," 0", "Charge state 0: nothing is done"),
220 ('5',"+1", "Charge state +1"),
221 ('6',"+2", "Charge state +2"),
222 ('7',"+3", "Charge state +3"),
223 ('8',"+4", "Charge state +4"),
224 ('9',"+5", "Charge state +5"),
225 ('10',"+6", "Charge state +6"),
226 ('11',"+7", "Charge state +7")),
227 default='4',update=Callback_radius_type)
228 radius_pm_name: StringProperty(
229 name="", default="Atom name",
230 description="Put in the name of the atom (e.g. Hydrogen)")
231 radius_pm: FloatProperty(
232 name="", default=100.0, min=0.0,
233 description="Put in the radius of the atom (in pm)",
234 update=Callback_radius_pm)
235 radius_all: FloatProperty(
236 name="Scale", default = 1.05, min=1.0, max=5.0,
237 description="Put in the scale factor")
238 sticks_all: FloatProperty(
239 name="Scale", default = 1.05, min=1.0, max=5.0,
240 description="Put in the scale factor")
243 # Button loading a custom data file
244 class DatafileApply(Operator):
245 bl_idname = "atom_blend.datafile_apply"
246 bl_label = "Apply"
247 bl_description = "Use color and radii values stored in the custom file"
249 def execute(self, context):
250 scn = bpy.context.scene.atom_blend
252 if scn.datafile == "":
253 return {'FINISHED'}
255 custom_datafile(scn.datafile)
256 custom_datafile_change_atom_props()
258 return {'FINISHED'}
261 # Button for separating single atoms from a dupliverts structure
262 class DefaultAtom(Operator):
263 bl_idname = "atom_blend.default_atoms"
264 bl_label = "Default"
265 bl_description = ("Use default shapes and colors for atoms.")
267 # Are we in the OBJECT mode?
268 @classmethod
269 def poll(self, context):
270 if bpy.context.mode == 'OBJECT':
271 return True
272 else:
273 return False
275 def execute(self, context):
276 scn = bpy.context.scene.atom_blend
277 choose_objects("ATOM_DEFAULT_OBJ",
278 scn.action_type,
279 None,
280 None,
281 None,
282 None,
283 None)
284 return {'FINISHED'}
287 # Button for separating single atoms from a dupliverts structure
288 class ReplaceAtom(Operator):
289 bl_idname = "atom_blend.replace_atom"
290 bl_label = "Replace"
291 bl_description = ("Replace selected atoms with atoms of different shape.")
293 # Are we in the OBJECT mode?
294 @classmethod
295 def poll(self, context):
296 if bpy.context.mode == 'OBJECT':
297 return True
298 else:
299 return False
301 def execute(self, context):
302 scn = bpy.context.scene.atom_blend
303 choose_objects("ATOM_REPLACE_OBJ",
304 scn.action_type,
305 None,
306 None,
307 None,
308 None,
309 None)
310 return {'FINISHED'}
313 # Button for separating single atoms from a dupliverts structure
314 class SeparateAtom(Operator):
315 bl_idname = "atom_blend.separate_atom"
316 bl_label = "Separate"
317 bl_description = ("Separate selected atoms in a dupliverts structure. "
318 "You have to be in the 'Edit Mode'")
320 # Are we in the EDIT mode?
321 @classmethod
322 def poll(self, context):
323 if bpy.context.mode == 'EDIT_MESH':
324 return True
325 else:
326 return False
328 def execute(self, context):
329 scn = bpy.context.scene.atom_blend
331 separate_atoms(scn)
333 return {'FINISHED'}
336 # Button for measuring the distance of active objects
337 class DistanceButton(Operator):
338 bl_idname = "atom_blend.button_distance"
339 bl_label = "Measure ..."
340 bl_description = "Measure the distance between two atoms (objects)."
342 def execute(self, context):
343 scn = bpy.context.scene.atom_blend
344 dist = distance()
346 # Put the distance into the string of the output field.
347 scn.distance = dist
348 return {'FINISHED'}
351 # Button for increasing the radii of all selected atoms
352 class RadiusAllBiggerButton(Operator):
353 bl_idname = "atom_blend.radius_all_bigger"
354 bl_label = "Bigger ..."
355 bl_description = "Increase the radii of selected atoms"
357 def execute(self, context):
358 scn = bpy.context.scene.atom_blend
359 choose_objects("ATOM_RADIUS_ALL",
360 scn.action_type,
361 scn.radius_all,
362 None,
363 None,
364 None,
365 None)
366 return {'FINISHED'}
369 # Button for decreasing the radii of all selected atoms
370 class RadiusAllSmallerButton(Operator):
371 bl_idname = "atom_blend.radius_all_smaller"
372 bl_label = "Smaller ..."
373 bl_description = "Decrease the radii of selected atoms"
375 def execute(self, context):
376 scn = bpy.context.scene.atom_blend
377 choose_objects("ATOM_RADIUS_ALL",
378 scn.action_type,
379 1.0/scn.radius_all,
380 None,
381 None,
382 None,
383 None)
384 return {'FINISHED'}
387 # Button for increasing the radii of all selected sticks
388 class SticksAllBiggerButton(Operator):
389 bl_idname = "atom_blend.sticks_all_bigger"
390 bl_label = "Bigger ..."
391 bl_description = "Increase the radii of selected sticks"
393 def execute(self, context):
394 scn = bpy.context.scene.atom_blend
395 choose_objects("STICKS_RADIUS_ALL",
396 scn.action_type,
397 None,
398 None,
399 None,
400 None,
401 scn.sticks_all)
402 return {'FINISHED'}
405 # Button for decreasing the radii of all selected sticks
406 class SticksAllSmallerButton(Operator):
407 bl_idname = "atom_blend.sticks_all_smaller"
408 bl_label = "Smaller ..."
409 bl_description = "Decrease the radii of selected sticks"
411 def execute(self, context):
412 scn = bpy.context.scene.atom_blend
413 choose_objects("STICKS_RADIUS_ALL",
414 scn.action_type,
415 None,
416 None,
417 None,
418 None,
419 1.0/scn.sticks_all)
420 return {'FINISHED'}