123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446 |
- # ##### 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 #####
- # <pep8 compliant>
- from bpy.types import (
- Panel,
- )
- from bl_ui.properties_physics_common import (
- basic_force_field_settings_ui,
- basic_force_field_falloff_ui,
- )
- class PhysicButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "physics"
- @staticmethod
- def poll_force_field(context):
- ob = context.object
- return (ob and (ob.field) and (ob.field.type != 'NONE'))
- @staticmethod
- def poll_collision(context):
- ob = context.object
- return (ob and ob.type == 'MESH') and (context.collision)
- class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
- bl_label = "Force Fields"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_force_field(context):
- return False
- return (context.engine in cls.COMPAT_ENGINES)
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- ob = context.object
- field = ob.field
- layout.prop(field, "type")
- class PHYSICS_PT_field_settings(PhysicButtonsPanel, Panel):
- bl_label = "Settings"
- bl_parent_id = 'PHYSICS_PT_field'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_force_field(context):
- return False
- return (context.engine in cls.COMPAT_ENGINES)
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- ob = context.object
- field = ob.field
- if field.type not in {'NONE', 'GUIDE', 'TEXTURE'}:
- layout.prop(field, "shape", text="Shape")
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- if field.type == 'NONE':
- return # nothing to draw.
- elif field.type == 'GUIDE':
- col = flow.column()
- col.prop(field, "guide_minimum")
- col.prop(field, "guide_free")
- col.prop(field, "falloff_power")
- col.prop(field, "use_guide_path_add")
- col.prop(field, "use_guide_path_weight")
- col.separator()
- col = flow.column()
- col.prop(field, "guide_clump_amount", text="Clumping amount")
- col.prop(field, "guide_clump_shape")
- col.prop(field, "use_max_distance")
- sub = col.column()
- sub.active = field.use_max_distance
- sub.prop(field, "distance_max")
- elif field.type == 'TEXTURE':
- col = flow.column()
- col.prop(field, "texture_mode")
- col.separator()
- col.prop(field, "strength")
- col = flow.column()
- col.prop(field, "texture_nabla")
- col.prop(field, "use_object_coords")
- col.prop(field, "use_2d_force")
- elif field.type == 'SMOKE_FLOW':
- col = flow.column()
- col.prop(field, "strength")
- col.prop(field, "flow")
- col = flow.column()
- col.prop(field, "source_object")
- col.prop(field, "use_smoke_density")
- else:
- del flow
- basic_force_field_settings_ui(self, field)
- class PHYSICS_PT_field_settings_kink(PhysicButtonsPanel, Panel):
- bl_label = "Kink"
- bl_parent_id = 'PHYSICS_PT_field_settings'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_force_field(context):
- return False
- ob = context.object
- return ((ob.field.type == 'GUIDE') and (context.engine in cls.COMPAT_ENGINES))
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- ob = context.object
- field = ob.field
- layout.prop(field, "guide_kink_type", text="Type")
- if field.guide_kink_type != 'NONE':
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- col = flow.column()
- col.prop(field, "guide_kink_axis")
- col.prop(field, "guide_kink_frequency")
- col = flow.column()
- col.prop(field, "guide_kink_shape")
- col.prop(field, "guide_kink_amplitude")
- class PHYSICS_PT_field_settings_texture_select(PhysicButtonsPanel, Panel):
- bl_label = "Texture"
- bl_parent_id = 'PHYSICS_PT_field_settings'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_force_field(context):
- return False
- ob = context.object
- return ((ob.field.type == 'TEXTURE') and (context.engine in cls.COMPAT_ENGINES))
- def draw(self, context):
- layout = self.layout
- ob = context.object
- field = ob.field
- layout.row().template_ID(field, "texture", new="texture.new")
- class PHYSICS_PT_field_falloff(PhysicButtonsPanel, Panel):
- bl_label = "Falloff"
- bl_parent_id = "PHYSICS_PT_field"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_force_field(context):
- return False
- ob = context.object
- return ((ob.field.type not in {'NONE', 'GUIDE'}) and (context.engine in cls.COMPAT_ENGINES))
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- ob = context.object
- field = ob.field
- layout.prop(field, "falloff_type", text="Shape")
- basic_force_field_falloff_ui(self, field)
- class PHYSICS_PT_field_falloff_angular(PhysicButtonsPanel, Panel):
- bl_label = "Angular"
- bl_parent_id = "PHYSICS_PT_field_falloff"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_force_field(context):
- return False
- ob = context.object
- return ((ob.field.falloff_type == 'CONE') and (context.engine in cls.COMPAT_ENGINES))
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- ob = context.object
- field = ob.field
- col = flow.column()
- col.prop(field, "radial_falloff", text="Power")
- col = flow.column()
- col.prop(field, "use_radial_min", text="Use Min Angle")
- sub = col.column()
- sub.active = field.use_radial_min
- sub.prop(field, "radial_min", text="Min Angle")
- col = flow.column()
- col.prop(field, "use_radial_max", text="Use Max Angle")
- sub = col.column()
- sub.active = field.use_radial_max
- sub.prop(field, "radial_max", text="Max Angle")
- class PHYSICS_PT_field_falloff_radial(PhysicButtonsPanel, Panel):
- bl_label = "Radial"
- bl_parent_id = "PHYSICS_PT_field_falloff"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_force_field(context):
- return False
- ob = context.object
- return ((ob.field.falloff_type == 'TUBE') and (context.engine in cls.COMPAT_ENGINES))
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- ob = context.object
- field = ob.field
- col = flow.column()
- col.prop(field, "radial_falloff", text="Power")
- col = flow.column()
- col.prop(field, "use_radial_min", text="Use Minimum")
- sub = col.column()
- sub.active = field.use_radial_min
- sub.prop(field, "radial_min", text="Min Distance")
- col = flow.column()
- col.prop(field, "use_radial_max", text="Use Maximum")
- sub = col.column()
- sub.active = field.use_radial_max
- sub.prop(field, "radial_max", text="Max Distance")
- def collision_warning(layout):
- row = layout.row(align=True)
- row.alignment = 'RIGHT'
- row.label(text="No collision settings available")
- class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
- bl_label = "Collision"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_collision(context):
- return False
- return (context.engine in cls.COMPAT_ENGINES)
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- md = context.collision
- coll = md.settings
- if not coll:
- collision_warning(layout)
- return
- settings = context.object.collision
- layout.active = settings.use
- col = layout.column()
- col.prop(settings, "absorption", text="Field Absorption")
- class PHYSICS_PT_collision_particle(PhysicButtonsPanel, Panel):
- bl_label = "Particle"
- bl_parent_id = "PHYSICS_PT_collision"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_collision(context):
- return False
- return (context.engine in cls.COMPAT_ENGINES)
- def draw(self, context):
- layout = self.layout
- md = context.collision
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- coll = md.settings
- if not coll:
- collision_warning(layout)
- return
- settings = context.object.collision
- layout.active = settings.use
- col = flow.column()
- col.prop(settings, "permeability", slider=True)
- col.prop(settings, "stickiness")
- col.prop(settings, "use_particle_kill")
- col = flow.column()
- sub = col.column(align=True)
- sub.prop(settings, "damping_factor", text="Damping", slider=True)
- sub.prop(settings, "damping_random", text="Randomize", slider=True)
- col = flow.column()
- sub = col.column(align=True)
- sub.prop(settings, "friction_factor", text="Friction", slider=True)
- sub.prop(settings, "friction_random", text="Randomize", slider=True)
- class PHYSICS_PT_collision_softbody(PhysicButtonsPanel, Panel):
- bl_label = "Softbody And Cloth"
- bl_parent_id = "PHYSICS_PT_collision"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_collision(context):
- return False
- return (context.engine in cls.COMPAT_ENGINES)
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- md = context.collision
- coll = md.settings
- if not coll:
- collision_warning(layout)
- return
- settings = context.object.collision
- layout.active = settings.use
- col = flow.column()
- col.prop(settings, "damping", text="Damping", slider=True)
- col = flow.column()
- col.prop(settings, "thickness_outer", text="Thickness Outer", slider=True)
- col = flow.column()
- col.prop(settings, "thickness_inner", text="Inner", slider=True)
- col = flow.column()
- col.prop(settings, "cloth_friction")
- col = flow.column()
- col.prop(settings, "use_culling")
- col = flow.column()
- col.prop(settings, "use_normal")
- classes = (
- PHYSICS_PT_field,
- PHYSICS_PT_field_settings,
- PHYSICS_PT_field_settings_kink,
- PHYSICS_PT_field_settings_texture_select,
- PHYSICS_PT_field_falloff,
- PHYSICS_PT_field_falloff_angular,
- PHYSICS_PT_field_falloff_radial,
- PHYSICS_PT_collision,
- PHYSICS_PT_collision_particle,
- PHYSICS_PT_collision_softbody,
- )
- if __name__ == "__main__": # only for live edit.
- from bpy.utils import register_class
- for cls in classes:
- register_class(cls)
|