Refactor: Node Wrangler: PreviewNode operator
[blender-addons.git] / io_mesh_atomic / utility_gui.py
blob678e1045925151821e07b3c9b4b28f0cf18788fb
1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 import bpy
6 from bpy.types import Operator, Panel
7 from bpy.props import (StringProperty,
8 EnumProperty,
9 FloatProperty,
10 BoolProperty)
12 from io_mesh_atomic.utility_panel import choose_objects
13 from io_mesh_atomic.utility_panel import custom_datafile
14 from io_mesh_atomic.utility_panel import custom_datafile_change_atom_props
15 from io_mesh_atomic.utility_panel import separate_atoms
16 from io_mesh_atomic.utility_panel import distance
19 # -----------------------------------------------------------------------------
20 # GUI
22 # The panel.
23 class PANEL_PT_prepare(Panel):
24 bl_label = "Atomic Blender Utilities"
25 bl_space_type = "VIEW_3D"
26 bl_region_type = "UI"
27 bl_options = {'DEFAULT_CLOSED'}
28 bl_category = "Create"
29 bl_idname = "ATOMIC_PT_utilities"
32 # This thing here just guarantees that the panel is NOT opened when the
33 # check box in the addon preferences is not activated! See __init__.py
34 @classmethod
35 def poll(cls, context):
36 pref = context.preferences
37 return pref.addons[__package__].preferences.bool_utility
39 def draw(self, context):
40 layout = self.layout
41 scn = context.scene.atom_blend
43 box = layout.box()
44 col = box.column(align=True)
45 col.label(text="Custom data file")
46 col.prop(scn, "datafile")
47 col.operator("atom_blend.datafile_apply")
49 box = layout.box()
50 col = box.column(align=True)
51 col.label(text="Measure distances")
52 col.operator("atom_blend.button_distance")
53 col.prop(scn, "distance")
55 box = layout.box()
56 col = box.column(align=True)
57 col.label(text="Change atom size")
58 col.label(text="1. Type of radii")
59 col.prop(scn, "radius_type")
60 col2 = col.column()
61 col2.active = (scn.radius_type == '3')
62 col2.prop(scn, "radius_type_ionic")
63 col = box.column(align=True)
64 col.label(text="2. Radii in pm")
65 col.prop(scn, "radius_pm_name")
66 col.prop(scn, "radius_pm")
67 col = box.column(align=True)
68 col.label(text="3. Radii by scale")
69 col.prop(scn, "radius_all")
70 row = col.row()
71 row.operator("atom_blend.radius_all_smaller")
72 row.operator("atom_blend.radius_all_bigger")
74 box = layout.box()
75 col = box.column(align=True)
76 col.label(text="Change stick size")
77 col.prop(scn, "sticks_all")
78 row = col.row()
79 row.operator("atom_blend.sticks_all_smaller")
80 row.operator("atom_blend.sticks_all_bigger")
82 box = layout.box()
83 col = box.column(align=True)
84 col.label(text="Change atom shape")
85 col2 = col.column()
86 col2.active = (scn.replace_objs_special == '0')
87 col2.prop(scn, "replace_objs")
88 col2.prop(scn, "replace_objs_material")
89 col.prop(scn, "replace_objs_special")
90 col.operator("atom_blend.replace_atom")
91 col.label(text="Default values")
92 col.operator("atom_blend.default_atoms")
94 box = layout.box()
95 col = box.column(align=True)
96 col.label(text="Separate atoms")
97 col3 = col.column()
98 col3.active = (bpy.context.mode == 'EDIT_MESH')
99 col3.operator("atom_blend.separate_atom")
102 # The properties of buttons etc. in the panel.
103 class PanelProperties(bpy.types.PropertyGroup):
105 def Callback_radius_type(self, context):
106 scn = bpy.context.scene.atom_blend
107 choose_objects("ATOM_RADIUS_TYPE",
108 None,
109 None,
110 scn.radius_type,
111 scn.radius_type_ionic,
112 None)
113 def Callback_radius_pm(self, context):
114 scn = bpy.context.scene.atom_blend
115 choose_objects("ATOM_RADIUS_PM",
116 None,
117 [scn.radius_pm_name,
118 scn.radius_pm],
119 None,
120 None,
121 None)
123 datafile: StringProperty(
124 name = "", description="Path to your custom data file",
125 maxlen = 256, default = "", subtype='FILE_PATH')
126 XYZ_file: StringProperty(
127 name = "Path to file", default="",
128 description = "Path of the XYZ file")
129 number_atoms: StringProperty(name="",
130 default="Number", description = "This output shows "
131 "the number of atoms which have been loaded")
132 distance: StringProperty(
133 name="", default="Distance (A)",
134 description="Distance of 2 objects in Angstrom")
135 replace_objs: EnumProperty(
136 name="Shape",
137 description="Choose a different atom shape",
138 items=(('0',"Unchanged", "Do not change the shape"),
139 ('1a',"Sphere (Mesh)", "Replace with a sphere (Mesh)"),
140 ('1b',"Sphere (NURBS)", "Replace with a sphere (NURBS)"),
141 ('2',"Cube", "Replace with a cube"),
142 ('3',"Plane", "Replace with a plane"),
143 ('4a',"Circle (Mesh)", "Replace with a circle (Mesh)"),
144 ('4b',"Circle (NURBS)", "Replace with a circle (NURBS)"),
145 ('5a',"Icosphere 1", "Replace with a icosphere, subd=1"),
146 ('5b',"Icosphere 2", "Replace with a icosphere, subd=2"),
147 ('5c',"Icosphere 3", "Replace with a icosphere, subd=3"),
148 ('5d',"Icosphere 4", "Replace with a icosphere, subd=4"),
149 ('5e',"Icosphere 5", "Replace with a icosphere, subd=5"),
150 ('6a',"Cylinder (Mesh)", "Replace with a cylinder (Mesh)"),
151 ('6b',"Cylinder (NURBS)", "Replace with a cylinder (NURBS)"),
152 ('7',"Cone", "Replace with a cone"),
153 ('8a',"Torus (Mesh)", "Replace with a torus (Mesh)"),
154 ('8b',"Torus (NURBS)", "Replace with a torus (NURBS)")),
155 default='0',)
156 replace_objs_material: EnumProperty(
157 name="Material",
158 description="Choose a different material",
159 items=(('0',"Unchanged", "Leave the material unchanged"),
160 ('1',"Normal", "Use normal material (no transparency and reflection)"),
161 ('2',"Transparent", "Use transparent material"),
162 ('3',"Reflecting", "Use reflecting material"),
163 ('4',"Transparent + reflecting", "Use transparent and reflecting material")),
164 default='0',)
165 replace_objs_special: EnumProperty(
166 name="Special",
167 description="Choose a special atom shape",
168 items=(('0',"None", "Use no special shape."),
169 ('1',"F2+ center", "Replace with a F2+ center"),
170 ('2',"F+ center", "Replace with a F+ center"),
171 ('3',"F0 center", "Replace with a F0 center")),
172 default='0',)
173 radius_type: EnumProperty(
174 name="Type",
175 description="Which type of atom radii?",
176 items=(('0',"predefined", "Use pre-defined radii"),
177 ('1',"atomic", "Use atomic radii"),
178 ('2',"van der Waals","Use van der Waals radii"),
179 ('3',"ionic radii", "Use ionic radii")),
180 default='0',update=Callback_radius_type)
181 radius_type_ionic: EnumProperty(
182 name="Charge",
183 description="Charge state of the ions if existing",
184 items=(('0',"-4", "Charge state -4"),
185 ('1',"-3", "Charge state -3"),
186 ('2',"-2", "Charge state -2"),
187 ('3',"-1", "Charge state -1"),
188 ('4'," 0", "Charge state 0: nothing is done"),
189 ('5',"+1", "Charge state +1"),
190 ('6',"+2", "Charge state +2"),
191 ('7',"+3", "Charge state +3"),
192 ('8',"+4", "Charge state +4"),
193 ('9',"+5", "Charge state +5"),
194 ('10',"+6", "Charge state +6"),
195 ('11',"+7", "Charge state +7")),
196 default='4',update=Callback_radius_type)
197 radius_pm_name: StringProperty(
198 name="", default="Atom name",
199 description="Put in the name of the atom (e.g. Hydrogen)")
200 radius_pm: FloatProperty(
201 name="", default=100.0, min=0.0,
202 description="Put in the radius of the atom (in pm)",
203 update=Callback_radius_pm)
204 radius_all: FloatProperty(
205 name="Scale", default = 1.05, min=1.0, max=5.0,
206 description="Put in the scale factor")
207 sticks_all: FloatProperty(
208 name="Scale", default = 1.05, min=1.0, max=5.0,
209 description="Put in the scale factor")
212 # Button loading a custom data file
213 class DatafileApply(Operator):
214 bl_idname = "atom_blend.datafile_apply"
215 bl_label = "Apply"
216 bl_description = "Use color and radii values stored in the custom file"
218 def execute(self, context):
219 scn = bpy.context.scene.atom_blend
221 if scn.datafile == "":
222 return {'FINISHED'}
224 custom_datafile(scn.datafile)
225 custom_datafile_change_atom_props()
227 return {'FINISHED'}
230 # Button for separating single atoms from a dupliverts structure
231 class DefaultAtom(Operator):
232 bl_idname = "atom_blend.default_atoms"
233 bl_label = "Default"
234 bl_description = ("Use default shapes and colors for atoms")
236 # Are we in the OBJECT mode?
237 @classmethod
238 def poll(self, context):
239 if bpy.context.mode == 'OBJECT':
240 return True
241 else:
242 return False
244 def execute(self, context):
245 scn = bpy.context.scene.atom_blend
246 choose_objects("ATOM_DEFAULT_OBJ",
247 None,
248 None,
249 None,
250 None,
251 None)
252 return {'FINISHED'}
255 # Button for separating single atoms from a dupliverts structure
256 class ReplaceAtom(Operator):
257 bl_idname = "atom_blend.replace_atom"
258 bl_label = "Replace"
259 bl_description = ("Replace selected atoms with atoms of different shape")
261 # Are we in the OBJECT mode?
262 @classmethod
263 def poll(self, context):
264 if bpy.context.mode == 'OBJECT':
265 return True
266 else:
267 return False
269 def execute(self, context):
270 scn = bpy.context.scene.atom_blend
271 choose_objects("ATOM_REPLACE_OBJ",
272 None,
273 None,
274 None,
275 None,
276 None)
277 return {'FINISHED'}
280 # Button for separating single atoms from a dupliverts structure
281 class SeparateAtom(Operator):
282 bl_idname = "atom_blend.separate_atom"
283 bl_label = "Separate"
284 bl_description = ("Separate selected atoms in a dupliverts structure. "
285 "You have to be in the 'Edit Mode'")
287 # Are we in the EDIT mode?
288 @classmethod
289 def poll(self, context):
290 if bpy.context.mode == 'EDIT_MESH':
291 return True
292 else:
293 return False
295 def execute(self, context):
296 scn = bpy.context.scene.atom_blend
298 separate_atoms(scn)
300 return {'FINISHED'}
303 # Button for measuring the distance of active objects
304 class DistanceButton(Operator):
305 bl_idname = "atom_blend.button_distance"
306 bl_label = "Measure ..."
307 bl_description = "Measure the distance between two atoms (objects)"
309 def execute(self, context):
310 scn = bpy.context.scene.atom_blend
311 dist = distance()
313 # Put the distance into the string of the output field.
314 scn.distance = dist
315 return {'FINISHED'}
318 # Button for increasing the radii of all selected atoms
319 class RadiusAllBiggerButton(Operator):
320 bl_idname = "atom_blend.radius_all_bigger"
321 bl_label = "Bigger ..."
322 bl_description = "Increase the radii of selected atoms"
324 def execute(self, context):
325 scn = bpy.context.scene.atom_blend
326 choose_objects("ATOM_RADIUS_ALL",
327 scn.radius_all,
328 None,
329 None,
330 None,
331 None)
332 return {'FINISHED'}
335 # Button for decreasing the radii of all selected atoms
336 class RadiusAllSmallerButton(Operator):
337 bl_idname = "atom_blend.radius_all_smaller"
338 bl_label = "Smaller ..."
339 bl_description = "Decrease the radii of selected atoms"
341 def execute(self, context):
342 scn = bpy.context.scene.atom_blend
343 choose_objects("ATOM_RADIUS_ALL",
344 1.0/scn.radius_all,
345 None,
346 None,
347 None,
348 None)
349 return {'FINISHED'}
352 # Button for increasing the radii of all selected sticks
353 class SticksAllBiggerButton(Operator):
354 bl_idname = "atom_blend.sticks_all_bigger"
355 bl_label = "Bigger ..."
356 bl_description = "Increase the radii of selected sticks"
358 def execute(self, context):
359 scn = bpy.context.scene.atom_blend
360 choose_objects("STICKS_RADIUS_ALL",
361 None,
362 None,
363 None,
364 None,
365 scn.sticks_all)
366 return {'FINISHED'}
369 # Button for decreasing the radii of all selected sticks
370 class SticksAllSmallerButton(Operator):
371 bl_idname = "atom_blend.sticks_all_smaller"
372 bl_label = "Smaller ..."
373 bl_description = "Decrease the radii of selected sticks"
375 def execute(self, context):
376 scn = bpy.context.scene.atom_blend
377 choose_objects("STICKS_RADIUS_ALL",
378 None,
379 None,
380 None,
381 None,
382 1.0/scn.sticks_all)
383 return {'FINISHED'}