2026-02-16

This commit is contained in:
2026-03-17 15:25:32 -06:00
parent d5dd373de0
commit 60100fbab2
560 changed files with 33397 additions and 20776 deletions
@@ -40,27 +40,16 @@ class FLIPFLUID_PT_DomainTypeAdvancedPanel(bpy.types.Panel):
aprops = obj.flip_fluid.domain.advanced
wprops = obj.flip_fluid.domain.world
#
# Frame Substeps Panel
#
box = self.layout.box()
column = box.column(align=True)
split = vcu.ui_split(column, factor=0.45)
column_left = split.column(align=True)
column_right = split.column(align=True)
header, body = box.panel("frame_substeps_settings", default_closed=False)
row = column_left.row(align=True)
row.prop(aprops, "frame_substeps_expanded",
icon="TRIA_DOWN" if aprops.frame_substeps_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row = header.row(align=True)
row.label(text="Frame Substeps:")
if not aprops.frame_substeps_expanded:
row = column_right.row(align=True)
row.prop(aprops.min_max_time_steps_per_frame, "value_min", text="Min")
row.prop(aprops.min_max_time_steps_per_frame, "value_max", text="Max")
if aprops.frame_substeps_expanded:
column = box.column(align=True)
if body:
column = body.column(align=True)
if wprops.enable_surface_tension and aprops.min_max_time_steps_per_frame.value_max < wprops.minimum_surface_tension_substeps:
row = column.row(align=True)
row.alert = True
@@ -73,77 +62,66 @@ class FLIPFLUID_PT_DomainTypeAdvancedPanel(bpy.types.Panel):
column.prop(aprops, "CFL_condition_number")
column.prop(aprops, "enable_adaptive_obstacle_time_stepping")
column.prop(aprops, "enable_adaptive_force_field_time_stepping")
else:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(aprops.min_max_time_steps_per_frame, "value_min", text="Min")
row.prop(aprops.min_max_time_steps_per_frame, "value_max", text="Max")
#
# Simulation Method Panel
#
box = self.layout.box()
column = box.column(align=True)
split = vcu.ui_split(column, factor=0.5)
column_left = split.column(align=True)
column_right = split.column(align=True)
header, body = box.panel("simulation_method_settings", default_closed=False)
row = column_left.row(align=True)
row.prop(aprops, "simulation_method_expanded",
icon="TRIA_DOWN" if aprops.simulation_method_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row = header.row(align=True)
row.label(text="Simulation Method:")
if not aprops.simulation_method_expanded:
row = column_right.row(align=True)
row.prop(aprops, "velocity_transfer_method", expand=True)
if aprops.simulation_method_expanded:
column = box.column(align=True)
if body:
column = body.column(align=True)
row = column.row(align=True)
row.prop(aprops, "velocity_transfer_method", expand=True)
if aprops.velocity_transfer_method == 'VELOCITY_TRANSFER_METHOD_FLIP':
column.prop(aprops, "PICFLIP_ratio", slider=True)
else:
column.label(text="")
else:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(aprops, "velocity_transfer_method", expand=True)
#
# Simulation and Particle Stability Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(aprops, "simulation_stability_expanded",
icon="TRIA_DOWN" if aprops.simulation_stability_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("simulation_and_particle_stability_settings", default_closed=True)
row = header.row(align=True)
row.label(text="Simulation and Particle Stability:")
if aprops.simulation_stability_expanded:
column = box.column()
if body:
column = body.column()
row = column.row(align=True)
row.prop(aprops, "particle_jitter_factor", slider=True)
row.prop(aprops, "jitter_surface_particles")
column.prop(aprops, "enable_extreme_velocity_removal")
column.separator()
column = box.column(align=True)
column = body.column(align=True)
column.prop(aprops, "pressure_solver_max_iterations")
column.prop(aprops, "viscosity_solver_max_iterations")
box = self.layout.box()
row = box.row(align=True)
row.prop(aprops, "multithreading_expanded",
icon="TRIA_DOWN" if aprops.multithreading_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Multithreading and Performance:")
if not aprops.multithreading_expanded:
info_text = ""
if aprops.threading_mode == 'THREADING_MODE_AUTO_DETECT':
info_text = "Auto-detect " + str(aprops.num_threads_auto_detect) + " threads"
elif aprops.threading_mode == 'THREADING_MODE_FIXED':
info_text = "Fixed " + str(aprops.num_threads_fixed) + " threads"
else:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text=info_text)
row.prop(aprops, "jitter_surface_particles")
if aprops.multithreading_expanded:
column = box.column()
#
# Multithreading and Performance Panel
#
box = self.layout.box()
header, body = box.panel("multithreading_and_performance_settings", default_closed=False)
row = header.row(align=True)
row.label(text="Multithreading and Performance:")
if body:
column = body.column()
split = column.split(align=True)
column_left = split.column(align=True)
@@ -156,31 +134,29 @@ class FLIPFLUID_PT_DomainTypeAdvancedPanel(bpy.types.Panel):
elif aprops.threading_mode == 'THREADING_MODE_FIXED':
row.prop(aprops, "num_threads_fixed")
column = box.column()
column = body.column()
column.prop(aprops, "enable_fracture_optimization")
# Performance and optimization settings are hidden from the UI.
# These should always be enabled for performance.
"""
column = self.layout.column(align=True)
column.separator()
column.label(text="Performance and Optimization:")
column.prop(aprops, "enable_asynchronous_meshing")
column.prop(aprops, "precompute_static_obstacles")
column.prop(aprops, "reserve_temporary_grids")
"""
else:
info_text = ""
if aprops.threading_mode == 'THREADING_MODE_AUTO_DETECT':
info_text = "Auto-detect " + str(aprops.num_threads_auto_detect) + " threads"
elif aprops.threading_mode == 'THREADING_MODE_FIXED':
info_text = "Fixed " + str(aprops.num_threads_fixed) + " threads"
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text=info_text)
#
# Warnings and Errors Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(aprops, "warnings_and_errors_expanded",
icon="TRIA_DOWN" if aprops.warnings_and_errors_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Warnings and Errors:")
header, body = box.panel("warnings_and_errors_settings", default_closed=True)
if aprops.warnings_and_errors_expanded:
column = box.column(align=True)
row = header.row(align=True)
row.label(text="Warnings and Errors:")
if body:
column = body.column(align=True)
column.prop(aprops, "disable_changing_topology_warning")
@@ -59,21 +59,16 @@ class FLIPFLUID_PT_DomainTypeCachePanel(bpy.types.Panel):
dprops = domain_object.flip_fluid.domain
cprops = dprops.cache
#
# Cache Directory Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(cprops, "cache_directory_expanded",
icon="TRIA_DOWN" if cprops.cache_directory_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("cache_directory", default_closed=False)
row = header.row(align=True)
row.label(text="Cache Directory:")
if not cprops.cache_directory_expanded:
row = row.row()
row.prop(cprops, "cache_directory")
if cprops.cache_directory_expanded:
column = box.column(align=True)
if body:
column = body.column(align=True)
subcolumn = column.column(align=True)
subcolumn.enabled = not dprops.bake.is_simulation_running
row = subcolumn.row(align=True)
@@ -85,18 +80,22 @@ class FLIPFLUID_PT_DomainTypeCachePanel(bpy.types.Panel):
row.operator("flip_fluid_operators.relative_cache_directory")
row.operator("flip_fluid_operators.absolute_cache_directory")
row.operator("flip_fluid_operators.match_filename_cache_directory")
else:
row = row.row(align=True)
row.prop(cprops, "cache_directory")
row.operator("flip_fluid_operators.increase_decrease_cache_directory", text="", icon="REMOVE").increment_mode = "DECREASE"
row.operator("flip_fluid_operators.increase_decrease_cache_directory", text="", icon="ADD").increment_mode = "INCREASE"
#
# Link Existing Exported Geometry Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(cprops, "link_exported_geometry_expanded",
icon="TRIA_DOWN" if cprops.link_exported_geometry_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Link existing exported geometry:")
header, body = box.panel("link_existing_exported_geometry", default_closed=True)
if cprops.link_exported_geometry_expanded:
column = box.column(align=True)
row = header.row(align=True)
row.label(text="Link Existing Exported Geometry:")
if body:
column = body.column(align=True)
subcolumn = column.column(align=True)
subcolumn.enabled = not dprops.bake.is_simulation_running
subcolumn.prop(cprops, "linked_geometry_directory")
@@ -106,56 +105,38 @@ class FLIPFLUID_PT_DomainTypeCachePanel(bpy.types.Panel):
column = column.column(align=True)
column.operator("flip_fluid_operators.clear_linked_geometry_directory")
column.separator()
else:
row = row.row(align=True)
row.prop(cprops, "linked_geometry_directory")
#
# Cache Operators Panel
#
if dprops.stats.is_cache_info_available:
free_text = "Free (" + format_bytes(self, dprops.stats.cache_bytes.get()) + ")"
else:
free_text = "Free"
box = self.layout.box()
row = box.row(align=True)
row.prop(cprops, "cache_operators_expanded",
icon="TRIA_DOWN" if cprops.cache_operators_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("cache_operators", default_closed=True)
row = header.row(align=True)
row.label(text="Cache Operators:")
if not cprops.cache_operators_expanded:
if dprops.stats.is_cache_info_available:
free_text = "Free (" + format_bytes(self, dprops.stats.cache_bytes.get()) + ")"
else:
free_text = "Free"
row.operator("flip_fluid_operators.free_cache", text=free_text)
if cprops.cache_operators_expanded:
column = box.column(align=True)
# The move, rename, and copy cache operations should not be performed
# in Blender and are removed from the UI. There is a potential for Blender
# to crash, which could lead to loss of data. It is best to perform these
# operations through the OS filesystem which is cabable of handling failures.
"""
row = column.row(align=True)
row.operator("flip_fluid_operators.move_cache", text="Move")
row.prop(cprops, "move_cache_directory")
row = column.row(align=True)
row.operator("flip_fluid_operators.rename_cache", text="Rename")
row.prop(cprops, "rename_cache_directory")
row = column.row(align=True)
row.operator("flip_fluid_operators.copy_cache", text="Copy")
row.prop(cprops, "copy_cache_directory")
"""
if dprops.stats.is_cache_info_available:
free_text = "Free (" + format_bytes(self, dprops.stats.cache_bytes.get()) + ")"
else:
free_text = "Free"
if body:
column = body.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
column_left.operator("flip_fluid_operators.free_cache", text=free_text)
column_right.prop(cprops, "clear_cache_directory_logs", text="Free log files")
column_right.prop(cprops, "clear_cache_directory_export", text="Free export files")
else:
if dprops.stats.is_cache_info_available:
free_text = "Free (" + format_bytes(self, dprops.stats.cache_bytes.get()) + ")"
else:
free_text = "Free"
row.operator("flip_fluid_operators.free_cache", text=free_text)
def register():
@@ -39,19 +39,18 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
obj = vcu.get_active_object(context)
gprops = obj.flip_fluid.domain.debug
#
# Grid Visualization Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(gprops, "grid_display_settings_expanded",
icon="TRIA_DOWN" if gprops.grid_display_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
if not gprops.grid_display_settings_expanded:
row.prop(gprops, "display_simulation_grid", text="")
row.label(text="Grid Visualization:")
header, body = box.panel("grid_visualization_settings", default_closed=False)
if gprops.grid_display_settings_expanded:
split = vcu.ui_split(box, align=True, factor=0.3)
row = header.row(align=True)
if not body:
row.prop(gprops, "display_simulation_grid", text="")
row.label(text="Grid Visualization:")
if body:
split = vcu.ui_split(body, align=True, factor=0.3)
column = split.column(align=True)
column.prop(gprops, "display_simulation_grid", text="Display Grid")
@@ -63,7 +62,7 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
column = split.column(align=True)
column.prop(gprops, "grid_display_scale", text="Draw Scale")
split = vcu.ui_split(box, align=True, factor=0.3)
split = vcu.ui_split(body, align=True, factor=0.3)
column = split.column(align=True)
column.enabled = gprops.display_simulation_grid
column.label(text="Enabled Grids:")
@@ -81,7 +80,7 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
row.prop(gprops, "debug_grid_offsets", text="", slider=True)
column.prop(gprops, "snap_offsets_to_grid")
column = box.column(align=True)
column = body.column(align=True)
split = vcu.ui_split(column, align=True, factor=0.3)
column = split.column(align=True)
column.prop(gprops, "display_domain_bounds")
@@ -90,14 +89,14 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
column.enabled = gprops.display_simulation_grid or gprops.display_domain_bounds
column.prop(gprops, "domain_bounds_color", text="")
#
# Fluid Particle Debugging Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(gprops, "particle_debug_settings_expanded",
icon="TRIA_DOWN" if gprops.particle_debug_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
if not gprops.particle_debug_settings_expanded:
header, body = box.panel("fluid_particle_debugging_settings", default_closed=True)
row = header.row(align=True)
if not body:
row.prop(gprops, "enable_fluid_particle_debug_output", text="")
row.label(text="Fluid Particle Debugging:")
@@ -109,10 +108,9 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
emboss=False
)
if gprops.particle_debug_settings_expanded:
box.prop(gprops, "enable_fluid_particle_debug_output")
column = box.column(align=True)
if body:
body.prop(gprops, "enable_fluid_particle_debug_output")
column = body.column(align=True)
column.enabled = gprops.enable_fluid_particle_debug_output
column.label(text="Particle Display Settings:")
row = column.row(align=True)
@@ -124,7 +122,7 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
row = column.row(align=True)
row.prop(gprops, "fluid_particle_gradient_mode", expand=True)
column = box.column()
column = body.column()
column.enabled = gprops.enable_fluid_particle_debug_output
split = vcu.ui_split(column, factor=0.33)
column = split.column()
@@ -134,14 +132,14 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
column.prop(gprops, "particle_size", text="")
column.prop_search(gprops, "particle_draw_aabb", bpy.data, "objects", text="")
#
# Force Field Debugging Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(gprops, "force_field_debug_settings_expanded",
icon="TRIA_DOWN" if gprops.force_field_debug_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
if not gprops.force_field_debug_settings_expanded:
header, body = box.panel("force_field_debugging_settings", default_closed=True)
row = header.row(align=True)
if not body:
row.prop(gprops, "export_force_field", text="")
row.label(text="Force Field Debugging:")
@@ -153,9 +151,9 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
emboss=False
)
if gprops.force_field_debug_settings_expanded:
box.prop(gprops, "export_force_field")
column = box.column(align=True)
if body:
body.prop(gprops, "export_force_field")
column = body.column(align=True)
column.enabled = gprops.export_force_field
column.label(text="Force Field Display Settings:")
@@ -168,7 +166,7 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
row = column.row(align=True)
row.prop(gprops, "force_field_gradient_mode", expand=True)
column = box.column()
column = body.column()
column.enabled = gprops.export_force_field
split = vcu.ui_split(column, factor=0.33)
column = split.column()
@@ -179,17 +177,24 @@ class FLIPFLUID_PT_DomainTypeDebugPanel(bpy.types.Panel):
column.prop(gprops, "force_field_display_amount", text="")
column.prop(gprops, "force_field_line_size", text="")
#
# Obstacle Debugging Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(gprops, "export_internal_obstacle_mesh")
next_row = row.row()
next_row.alignment = 'RIGHT'
next_row.prop(gprops, "internal_obstacle_mesh_visibility",
text="",
icon=vcu.get_hide_off_icon() if gprops.internal_obstacle_mesh_visibility else vcu.get_hide_on_icon(),
emboss=False
)
text="",
icon=vcu.get_hide_off_icon() if gprops.internal_obstacle_mesh_visibility else vcu.get_hide_on_icon(),
emboss=False
)
#
# Misc Debugging Panel
#
box = self.layout.box()
column = box.column(align=True)
column.prop(gprops, "display_render_passes_console_output")
@@ -25,16 +25,14 @@ def draw_simulation_display_settings(self, context):
rprops = domain_object.flip_fluid.domain.render
scene_props = context.scene.flip_fluid
#
# Simulation Visibility Panel
#
box = self.layout.box()
column = box.column()
row = column.row(align=True)
row.prop(rprops, "simulation_display_settings_expanded",
icon="TRIA_DOWN" if rprops.simulation_display_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("simulation_display_settings", default_closed=True)
row = header.row(align=True)
row.label(text="Simulation Visibility:")
if not scene_props.show_viewport or not scene_props.show_render:
visibility_text = ""
@@ -55,15 +53,14 @@ def draw_simulation_display_settings(self, context):
row.alignment = 'RIGHT'
row.label(text="Visibility Enabled", icon="CHECKMARK")
if not rprops.simulation_display_settings_expanded:
return
if body:
column = body.column()
split = vcu.ui_split(column)
column_left = split.column()
column_left.prop(scene_props, "show_render", text="Show In Render", icon="RESTRICT_RENDER_OFF")
split = vcu.ui_split(column)
column_left = split.column()
column_left.prop(scene_props, "show_render", text="Show In Render", icon="RESTRICT_RENDER_OFF")
column_right = split.column()
column_right.prop(scene_props, "show_viewport", text="Show In Viewport", icon="RESTRICT_VIEW_OFF")
column_right = split.column()
column_right.prop(scene_props, "show_viewport", text="Show In Viewport", icon="RESTRICT_VIEW_OFF")
def draw_surface_display_settings(self, context, menu_expand_prop_group=None):
@@ -71,18 +68,28 @@ def draw_surface_display_settings(self, context, menu_expand_prop_group=None):
rprops = domain_object.flip_fluid.domain.render
mprops = domain_object.flip_fluid.domain.materials
#
# Surface Display and Render Panel
#
box = self.layout.box()
column = box.column()
header, body = box.panel("surface_display_settings", default_closed=False)
row = column.row(align=True)
row.prop(menu_expand_prop_group, "surface_display_settings_expanded",
icon="TRIA_DOWN" if getattr(menu_expand_prop_group, "surface_display_settings_expanded") else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row = header.row(align=True)
row.label(text="Surface Display and Render:")
if body:
column = body.column()
split = vcu.ui_split(column, factor=0.5)
column_left = split.column()
column_left.label(text="Render Display Mode:")
column_left.prop(rprops, "render_display", expand=True)
if not getattr(menu_expand_prop_group, "surface_display_settings_expanded"):
column_right = split.column()
column_right.label(text="Viewport Display Mode:")
column_right.prop(rprops, "viewport_display", expand=True)
column_left.label(text="Surface Material:")
column_right.prop(mprops, "surface_material", text="")
else:
info_text = ""
if rprops.render_display == 'DISPLAY_FINAL':
info_text += "Render Final"
@@ -100,19 +107,6 @@ def draw_surface_display_settings(self, context, menu_expand_prop_group=None):
row = row.row(align=True)
row.alignment='RIGHT'
row.label(text=info_text)
return
split = vcu.ui_split(column, factor=0.5)
column_left = split.column()
column_left.label(text="Render Display Mode:")
column_left.prop(rprops, "render_display", expand=True)
column_right = split.column()
column_right.label(text="Viewport Display Mode:")
column_right.prop(rprops, "viewport_display", expand=True)
column_left.label(text="Surface Material:")
column_right.prop(mprops, "surface_material", text="")
def draw_fluid_particle_display_settings(self, context, menu_expand_prop_group=None):
@@ -122,61 +116,25 @@ def draw_fluid_particle_display_settings(self, context, menu_expand_prop_group=N
mprops = domain_object.flip_fluid.domain.materials
is_fluid_particles_enabled = domain_object.flip_fluid.domain.particles.enable_fluid_particle_output
#
# Fluid Particle Display and Render Panel
#
box = self.layout.box()
column = box.column()
header, body = box.panel("fluid_particle_display_settings", default_closed=True)
if is_fluid_particles_enabled:
row = column.row(align=True)
row.prop(menu_expand_prop_group, "fluid_particle_display_settings_expanded",
icon="TRIA_DOWN" if getattr(menu_expand_prop_group, "fluid_particle_display_settings_expanded") else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Fluid Particle Display and Render:")
else:
split = column.split()
left_column = split.column()
row = left_column.row(align=True)
row.prop(menu_expand_prop_group, "fluid_particle_display_settings_expanded",
icon="TRIA_DOWN" if getattr(menu_expand_prop_group, "fluid_particle_display_settings_expanded") else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Fluid Particle Display and Render:")
right_column = split.column()
row = right_column.row()
row = header.row(align=True)
row.label(text="Fluid Particle Display and Render:")
if not is_fluid_particles_enabled:
row = row.row()
row.alignment = 'RIGHT'
c = row.row(align=True)
c.alignment = 'RIGHT'
c.enabled = False
c.label(text="Enable in 'Particles' panel")
row.operator("flip_fluid_operators.display_enable_fluid_particles_tooltip",
text="", icon="QUESTION", emboss=False)
row.operator("flip_fluid_operators.display_enable_fluid_particles_tooltip", text="", icon="QUESTION", emboss=False)
if not getattr(menu_expand_prop_group, "fluid_particle_display_settings_expanded"):
if is_fluid_particles_enabled:
info_text = ""
if rprops.fluid_particle_render_display == 'DISPLAY_FINAL':
info_text += "Render Final"
elif rprops.fluid_particle_render_display == 'DISPLAY_PREVIEW':
info_text += "Render Preview"
elif rprops.fluid_particle_render_display == 'DISPLAY_NONE':
info_text += "Render None"
info_text += " / "
if rprops.fluid_particle_viewport_display == 'DISPLAY_FINAL':
info_text += "View Final"
elif rprops.fluid_particle_viewport_display == 'DISPLAY_PREVIEW':
info_text += "View Preview"
elif rprops.fluid_particle_viewport_display == 'DISPLAY_NONE':
info_text += "View None"
row = row.row(align=True)
row.alignment='RIGHT'
row.label(text=info_text)
return
if getattr(menu_expand_prop_group, "fluid_particle_display_settings_expanded"):
subbox = box.box()
if body:
subbox = body.box()
column = subbox.column(align=True)
column.enabled = is_fluid_particles_enabled
split = vcu.ui_split(column, factor=0.5)
@@ -229,6 +187,25 @@ def draw_fluid_particle_display_settings(self, context, menu_expand_prop_group=N
column_right = split.column()
column_left.label(text="Fluid Particle Material:")
column_right.prop(mprops, "fluid_particles_material", text="")
else:
if is_fluid_particles_enabled:
info_text = ""
if rprops.fluid_particle_render_display == 'DISPLAY_FINAL':
info_text += "Render Final"
elif rprops.fluid_particle_render_display == 'DISPLAY_PREVIEW':
info_text += "Render Preview"
elif rprops.fluid_particle_render_display == 'DISPLAY_NONE':
info_text += "Render None"
info_text += " / "
if rprops.fluid_particle_viewport_display == 'DISPLAY_FINAL':
info_text += "View Final"
elif rprops.fluid_particle_viewport_display == 'DISPLAY_PREVIEW':
info_text += "View Preview"
elif rprops.fluid_particle_viewport_display == 'DISPLAY_NONE':
info_text += "View None"
row = row.row(align=True)
row.alignment='RIGHT'
row.label(text=info_text)
def get_motion_blur_geometry_node_modifier(bl_object):
@@ -244,7 +221,7 @@ def draw_whitewater_particles_motion_blur_geometry_node_properties(ui_row, bl_mo
ui_row.alert = True
ui_row.operator(
"flip_fluid_operators.helper_initialize_cache_objects",
text="Initialize Geometry Nodes - Missing FF_GeometryNodesWhitewater modifier",
text="Click To Initialize Geometry Nodes - Missing FF_GeometryNodesWhitewater modifier",
icon="ERROR"
).cache_object_type = 'CACHE_OBJECT_TYPE_WHITEWATER_PARTICLES'
return
@@ -256,8 +233,6 @@ def draw_whitewater_particles_motion_blur_geometry_node_properties(ui_row, bl_mo
ui_row.prop(bl_mod, '["Input_4"]', text="Blur Scale")
if "Input_8" in bl_mod:
ui_row.prop(bl_mod, '["Input_8"]', text="Motion Blur")
if "Input_9" in bl_mod:
ui_row.prop(bl_mod, '["Input_9"]', text="Point Cloud")
def draw_fluid_particles_motion_blur_geometry_node_properties(ui_row, bl_mod):
@@ -265,7 +240,7 @@ def draw_fluid_particles_motion_blur_geometry_node_properties(ui_row, bl_mod):
ui_row.alert = True
ui_row.operator(
"flip_fluid_operators.helper_initialize_cache_objects",
text="Initialize Geometry Nodes - Missing FF_GeometryNodesFluidParticles modifier",
text="Click To Initialize Geometry Nodes - Missing FF_GeometryNodesFluidParticles modifier",
icon="ERROR"
).cache_object_type = 'CACHE_OBJECT_TYPE_FLUID_PARTICLES'
return
@@ -277,8 +252,6 @@ def draw_fluid_particles_motion_blur_geometry_node_properties(ui_row, bl_mod):
ui_row.prop(bl_mod, '["Input_4"]', text="Blur Scale")
if "Input_8" in bl_mod:
ui_row.prop(bl_mod, '["Input_8"]', text="Motion Blur")
if "Input_9" in bl_mod:
ui_row.prop(bl_mod, '["Input_9"]', text="Point Cloud")
def draw_whitewater_display_settings(self, context, menu_expand_prop_group=None):
@@ -287,61 +260,25 @@ def draw_whitewater_display_settings(self, context, menu_expand_prop_group=None)
rprops = dprops.render
is_whitewater_enabled = dprops.whitewater.enable_whitewater_simulation
master_box = self.layout.box()
column = master_box.column()
#
# Whitewater Display and Render Panel
#
box = self.layout.box()
header, body = box.panel("whitewater_display_settings", default_closed=True)
if is_whitewater_enabled:
row = column.row(align=True)
row.prop(menu_expand_prop_group, "whitewater_display_settings_expanded",
icon="TRIA_DOWN" if getattr(menu_expand_prop_group, "whitewater_display_settings_expanded") else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Whitewater Display and Render:")
else:
split = column.split()
left_column = split.column()
row = left_column.row(align=True)
row.prop(menu_expand_prop_group, "whitewater_display_settings_expanded",
icon="TRIA_DOWN" if getattr(menu_expand_prop_group, "whitewater_display_settings_expanded") else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Whitewater Display and Render:")
right_column = split.column()
row = right_column.row()
row = header.row(align=True)
row.label(text="Whitewater Display and Render:")
if not is_whitewater_enabled:
row = row.row()
row.alignment = 'RIGHT'
c = row.row(align=True)
c.alignment = 'RIGHT'
c.enabled = False
c.label(text="Enable in 'Whitewater' panel")
row.operator("flip_fluid_operators.display_enable_whitewater_tooltip",
text="", icon="QUESTION", emboss=False)
row.operator("flip_fluid_operators.display_enable_whitewater_tooltip", text="", icon="QUESTION", emboss=False)
if not getattr(menu_expand_prop_group, "whitewater_display_settings_expanded"):
if is_whitewater_enabled:
info_text = ""
if rprops.whitewater_render_display == 'DISPLAY_FINAL':
info_text += "Render Final"
elif rprops.whitewater_render_display == 'DISPLAY_PREVIEW':
info_text += "Render Preview"
elif rprops.whitewater_render_display == 'DISPLAY_NONE':
info_text += "Render None"
info_text += " / "
if rprops.whitewater_viewport_display == 'DISPLAY_FINAL':
info_text += "View Final"
elif rprops.whitewater_viewport_display == 'DISPLAY_PREVIEW':
info_text += "View Preview"
elif rprops.whitewater_viewport_display == 'DISPLAY_NONE':
info_text += "View None"
row = row.row(align=True)
row.alignment='RIGHT'
row.label(text=info_text)
return
if getattr(menu_expand_prop_group, "whitewater_display_settings_expanded"):
box = master_box.box()
if body:
box = body.box()
box.enabled = is_whitewater_enabled
column = box.column(align=True)
@@ -354,21 +291,7 @@ def draw_whitewater_display_settings(self, context, menu_expand_prop_group=None)
column.label(text="Viewport Display Mode:")
column.prop(rprops, "whitewater_viewport_display", expand=True)
# Whitewater motion blur rendering is currently too resource intensive
# for Blender Cycles
"""
column = box.column()
column.label(text="Motion Blur:")
split = vcu.ui_split(column, factor=0.5)
column_left = split.column()
column_left.prop(rprops, "render_whitewater_motion_blur")
column_right = split.column()
column_right.prop(rprops, "whitewater_motion_blur_scale")
"""
box = master_box.box()
box = body.box()
box.enabled = is_whitewater_enabled
column = box.column(align=True)
@@ -387,7 +310,7 @@ def draw_whitewater_display_settings(self, context, menu_expand_prop_group=None)
column.prop(rprops, "viewport_spray_pct", slider=True)
column.prop(rprops, "viewport_dust_pct", slider=True)
box = master_box.box()
box = body.box()
box.enabled = is_whitewater_enabled
column = box.column(align=True)
@@ -416,7 +339,7 @@ def draw_whitewater_display_settings(self, context, menu_expand_prop_group=None)
else:
row.label(text="Enable Whitewater feature to view full particle settings", icon='INFO')
box = master_box.box()
box = body.box()
box.enabled = is_whitewater_enabled
mprops = dprops.materials
@@ -426,6 +349,25 @@ def draw_whitewater_display_settings(self, context, menu_expand_prop_group=None)
column.prop(mprops, "whitewater_bubble_material", text="Bubble")
column.prop(mprops, "whitewater_spray_material", text="Spray")
column.prop(mprops, "whitewater_dust_material", text="Dust")
else:
if is_whitewater_enabled:
info_text = ""
if rprops.whitewater_render_display == 'DISPLAY_FINAL':
info_text += "Render Final"
elif rprops.whitewater_render_display == 'DISPLAY_PREVIEW':
info_text += "Render Preview"
elif rprops.whitewater_render_display == 'DISPLAY_NONE':
info_text += "Render None"
info_text += " / "
if rprops.whitewater_viewport_display == 'DISPLAY_FINAL':
info_text += "View Final"
elif rprops.whitewater_viewport_display == 'DISPLAY_PREVIEW':
info_text += "View Preview"
elif rprops.whitewater_viewport_display == 'DISPLAY_NONE':
info_text += "View None"
row = row.row(align=True)
row.alignment='RIGHT'
row.label(text=info_text)
class FLIPFLUID_PT_DomainTypeDisplayPanel(bpy.types.Panel):
@@ -36,43 +36,29 @@ def _draw_geometry_attributes_menu(self, context):
#
# Geometry Attributes
#
#
box = self.layout.box()
row = box.row(align=True)
row.prop(pprops, "geometry_attributes_expanded",
icon="TRIA_DOWN" if pprops.geometry_attributes_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("fluid_particle_geometry_attributes", default_closed=True)
row = header.row(align=True)
row.label(text="Fluid Particle Attributes:")
if pprops.geometry_attributes_expanded:
if not vcu.is_blender_31():
column = box.column(align=True)
column.enabled = False
column.label(text="Geometry attribute features for fluid particles are only available in", icon='ERROR')
column.label(text="Blender 3.1 or later", icon='ERROR')
return
if body:
#
# Velocity Attributes
#
subbox = box.box()
row = subbox.row(align=True)
row.prop(pprops, "velocity_attributes_expanded",
icon="TRIA_DOWN" if pprops.velocity_attributes_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Velocity Based Attributes:")
box = body.box()
header_velocity, body_velocity = box.panel("fluid_particle_velocity_attributes", default_closed=True)
if pprops.velocity_attributes_expanded:
column = subbox.column(align=True)
row_velocity = header_velocity.row(align=True)
row_velocity.label(text="Velocity Based Attributes:")
if body_velocity:
column = body_velocity.column(align=True)
column.prop(pprops, "enable_fluid_particle_velocity_vector_attribute", text="Velocity Attributes")
column.prop(pprops, "enable_fluid_particle_speed_attribute", text="Speed Attributes")
column.prop(pprops, "enable_fluid_particle_vorticity_vector_attribute", text="Vorticity Attributes")
column.operator("flip_fluid_operators.helper_initialize_motion_blur")
else:
row = row.row(align=True)
row = row_velocity.row(align=True)
row.alignment = 'RIGHT'
row.prop(pprops, "enable_fluid_particle_velocity_vector_attribute", text="Velocity")
row.prop(pprops, "enable_fluid_particle_speed_attribute", text="Speed")
@@ -81,23 +67,19 @@ def _draw_geometry_attributes_menu(self, context):
#
# Color Attributes
#
subbox = box.box()
row = subbox.row(align=True)
row.prop(pprops, "color_attributes_expanded",
icon="TRIA_DOWN" if pprops.color_attributes_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Color and Mixing Attributes:")
box = body.box()
header_color, body_color = box.panel("fluid_particle_color_attributes", default_closed=True)
if pprops.color_attributes_expanded:
column = subbox.column(align=True)
row_color = header_color.row(align=True)
row_color.label(text="Color and Mixing Attributes:")
if body_color:
column = body_color.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
column_left.prop(pprops, "enable_fluid_particle_color_attribute", text="Color Attributes")
column = subbox.column(align=True)
column = body_color.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
@@ -106,7 +88,7 @@ def _draw_geometry_attributes_menu(self, context):
column_right.enabled = pprops.enable_fluid_particle_color_attribute and sprops.enable_color_attribute_mixing
column_right.prop(sprops, "color_attribute_mixing_rate", text="Mix Rate", slider=True)
column = subbox.column(align=True)
column = body_color.column(align=True)
column.enabled = pprops.enable_fluid_particle_color_attribute and sprops.enable_color_attribute_mixing
column.label(text="Mixing Mode:")
row = column.row(align=True)
@@ -129,10 +111,10 @@ def _draw_geometry_attributes_menu(self, context):
text="Open Preferences", icon="PREFERENCES"
).view_mode = 'PREFERENCES_MENU_VIEW_MIXBOX'
else:
row = row.row(align=True)
row = row_color.row(align=True)
row.alignment = 'RIGHT'
row.prop(pprops, "enable_fluid_particle_color_attribute", text="Color")
row = row.row(align=True)
row = row_color.row(align=True)
row.alignment = 'RIGHT'
row.enabled = pprops.enable_fluid_particle_color_attribute
row.prop(sprops, "enable_color_attribute_mixing", text="Mixing")
@@ -140,17 +122,13 @@ def _draw_geometry_attributes_menu(self, context):
#
# Other Attributes
#
subbox = box.box()
row = subbox.row(align=True)
row.prop(pprops, "other_attributes_expanded",
icon="TRIA_DOWN" if pprops.other_attributes_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Other Attributes:")
box = body.box()
header_other, body_other = box.panel("fluid_particle_other_attributes", default_closed=True)
if pprops.other_attributes_expanded:
column = subbox.column(align=True)
row_other = header_other.row(align=True)
row_other.label(text="Other Attributes:")
if body_other:
column = body_other.column(align=True)
column.prop(pprops, "enable_fluid_particle_age_attribute", text="Age Attributes")
row = column.row(align=True)
row.prop(pprops, "enable_fluid_particle_lifetime_attribute", text="Lifetime Attributes")
@@ -161,7 +139,7 @@ def _draw_geometry_attributes_menu(self, context):
row.prop(pprops, "enable_fluid_particle_uid_attribute", text="UID Attributes")
row.prop(pprops, "enable_fluid_particle_uid_attribute_reuse", text="Reuse UIDs")
else:
row = row.row(align=True)
row = row_other.row(align=True)
row.alignment = 'RIGHT'
row.prop(pprops, "enable_fluid_particle_age_attribute", text="Age")
row.prop(pprops, "enable_fluid_particle_lifetime_attribute", text="Life")
@@ -192,41 +170,18 @@ class FLIPFLUID_PT_DomainTypeFluidParticlesPanel(bpy.types.Panel):
dprops = obj.flip_fluid.domain
pprops = obj.flip_fluid.domain.particles
sprops = obj.flip_fluid.domain.surface
aprops = dprops.advanced
prefs = vcu.get_addon_preferences()
if not prefs.is_extra_features_enabled():
warn_box = self.layout.box()
warn_column = warn_box.column(align=True)
warn_column.enabled = True
warn_column.label(text=" This feature is affected by a current bug in Blender.", icon='ERROR')
warn_column.label(text=" The Extra Features option must be enabled in preferences")
warn_column.label(text=" to use this feature.")
warn_column.separator()
warn_column.prop(prefs, "enable_extra_features", text="Enable Extra Features in Preferences")
warn_column.separator()
warn_column.operator(
"wm.url_open",
text="Important Info and Limitations",
icon="WORLD"
).url = "https://github.com/rlguy/Blender-FLIP-Fluids/wiki/Preferences-Menu-Settings#developer-tools"
return
#
# Fluid Particle Export Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(pprops, "fluid_particles_expanded",
icon="TRIA_DOWN" if pprops.fluid_particles_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("fluid_particles", default_closed=False)
row = header.row(align=True)
row.label(text="Fluid Particle Export:")
if not pprops.fluid_particles_expanded:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(pprops, "enable_fluid_particle_output")
if pprops.fluid_particles_expanded:
column = box.column(align=True)
if body:
column = body.column(align=True)
column.prop(pprops, "enable_fluid_particle_output")
subbox = column.box()
subbox.enabled = pprops.enable_fluid_particle_output
@@ -237,27 +192,28 @@ class FLIPFLUID_PT_DomainTypeFluidParticlesPanel(bpy.types.Panel):
subcolumn.prop(pprops, "enable_fluid_particle_interior_output")
subcolumn.separator()
subcolumn.prop(pprops, "fluid_particle_source_id_blacklist", text="Skip Particles With Source ID Value")
box = self.layout.box()
row = box.row(align=True)
row.prop(pprops, "fluid_particle_generation_expanded",
icon="TRIA_DOWN" if pprops.fluid_particle_generation_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Fluid Particle Generation:")
aprops = dprops.advanced
if not pprops.fluid_particle_generation_expanded:
else:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(aprops, "jitter_surface_particles")
row.prop(pprops, "enable_fluid_particle_output")
if pprops.fluid_particle_generation_expanded:
column = box.column()
#
# Fluid Particle Generation Panel
#
box = self.layout.box()
header, body = box.panel("fluid_particle_generation", default_closed=True)
row = header.row(align=True)
row.label(text="Fluid Particle Generation:")
if body:
column = body.column()
row = column.row(align=True)
row.prop(aprops, "particle_jitter_factor", slider=True)
row.prop(aprops, "jitter_surface_particles")
else:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(aprops, "jitter_surface_particles")
_draw_fluid_particle_display_settings(self, context)
_draw_geometry_attributes_menu(self, context)
@@ -112,211 +112,313 @@ def draw_bake_operator(self, context, box):
draw_bake_operator_UI_element(context, box)
def draw_more_bake_settings(self, context, box):
def draw_more_bake_settings(self, context, master_column):
obj = vcu.get_active_object(context)
dprops = obj.flip_fluid.domain
sprops = dprops.simulation
row = box.row(align=True)
row.prop(sprops, "more_bake_settings_expanded",
icon="TRIA_DOWN" if sprops.more_bake_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="More Bake Settings")
#
# More Bake Settings Panel
#
box = master_column.box()
header, body = box.panel("more_bake_settings", default_closed=True)
if not sprops.more_bake_settings_expanded:
return
row = header.row(align=True)
row.label(text="More Bake Settings:")
subbox = box.box()
column = subbox.column(align=True)
column.label(text="Frame Range:")
row = column.row()
row.prop(sprops, "frame_range_mode", expand=True)
row = column.row(align=True)
if sprops.frame_range_mode == 'FRAME_RANGE_TIMELINE':
row_left = row.row(align=True)
row_right = row.row(align=True)
if dprops.bake.is_autosave_available:
row_left.enabled = False
row_left.prop(dprops.bake, "original_frame_start")
else:
row_left.prop(context.scene, "frame_start")
row_right.prop(context.scene, "frame_end")
else:
row_left = row.row(align=True)
row_right = row.row(align=True)
if dprops.bake.is_autosave_available:
row_left.enabled = False
row_left.prop(dprops.bake, "original_frame_start")
else:
row_left.prop(sprops.frame_range_custom, "value_min")
row_right.prop(sprops.frame_range_custom, "value_max")
subbox = box.box()
column = subbox.column(align=True)
column.label(text="Settings and Mesh Export:")
column.prop(sprops, "update_settings_on_resume")
indent_str = 5 * " "
subbox = subbox.box()
row = subbox.row(align=True)
row.prop(sprops, "skip_mesh_reexport_expanded",
icon="TRIA_DOWN" if sprops.skip_mesh_reexport_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Skip Mesh Re-Export:")
if sprops.skip_mesh_reexport_expanded:
flip_props = context.scene.flip_fluid
flip_objects = (flip_props.get_obstacle_objects() +
flip_props.get_fluid_objects() +
flip_props.get_inflow_objects() +
flip_props.get_outflow_objects() +
flip_props.get_force_field_objects())
num_flip_objects = len(flip_objects)
flip_object_count_limit = 128
if num_flip_objects > flip_object_count_limit:
column = subbox.column()
column.alert = True
column.label(text="Menu Unavailable", icon="ERROR")
column.label(text="This menu is only available in scenes containing " + str(flip_object_count_limit) + " FLIP objects or fewer", icon="ERROR")
column.label(text="Current number of FLIP objects: " + str(num_flip_objects), icon="ERROR")
else:
column = subbox.column()
column.label(text="Object Motion Type:")
row = column.row(align=True)
row.prop(sprops, "mesh_reexport_type_filter", expand=True)
flip_objects.sort(key=lambda x: x.name)
is_all_filter_selected = sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_ALL'
if sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_ALL':
filtered_objects = flip_objects
motion_type_string = "simulation"
elif sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_STATIC':
filtered_objects = [x for x in flip_objects if _get_object_motion_type(self, x) == 'STATIC']
motion_type_string = "static"
elif sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_KEYFRAMED':
filtered_objects = [x for x in flip_objects if _get_object_motion_type(self, x) == 'KEYFRAMED']
motion_type_string = "keyframed"
elif sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_ANIMATED':
filtered_objects = [x for x in flip_objects if _get_object_motion_type(self, x) == 'ANIMATED']
motion_type_string = "animated"
if len(filtered_objects) == 0:
column.label(text=indent_str + "No " + motion_type_string + " objects found...")
if body:
subbox = body.column()
column = subbox.column(align=True)
column.label(text="Frame Range:")
row = column.row()
row.prop(sprops, "frame_range_mode", expand=True)
row = column.row(align=True)
if sprops.frame_range_mode == 'FRAME_RANGE_TIMELINE':
row_left = row.row(align=True)
row_right = row.row(align=True)
if dprops.bake.is_autosave_available:
row_left.enabled = False
row_left.prop(dprops.bake, "original_frame_start")
else:
split = column.split()
column_left = split.column(align=True)
if is_all_filter_selected:
column_animated = split.column(align=True)
row_left.prop(context.scene, "frame_start")
row_right.prop(context.scene, "frame_end")
else:
row_left = row.row(align=True)
row_right = row.row(align=True)
if dprops.bake.is_autosave_available:
row_left.enabled = False
row_left.prop(dprops.bake, "original_frame_start")
else:
row_left.prop(sprops.frame_range_custom, "value_min")
row_right.prop(sprops.frame_range_custom, "value_max")
column_middle = split.column(align=True)
column_right = split.column(align=True)
subbox = body.column()
column = subbox.column(align=True)
column.label(text="Settings and Mesh Export:")
column.prop(sprops, "update_settings_on_resume")
column_left.label(text="")
column_left.label(text="Object")
op_box = column_left.box()
op_box.label(text="")
indent_str = 5 * " "
if is_all_filter_selected:
column_animated.label(text="")
column_animated.label(text="Export Animated")
op_box = column_animated.box()
row = op_box.row(align=True)
row.alignment = 'LEFT'
row.operator("flip_fluid_operators.helper_batch_export_animated_mesh", icon='CHECKBOX_HLT', text="").enable_state = True
row.operator("flip_fluid_operators.helper_batch_export_animated_mesh", icon='CHECKBOX_DEHLT', text="").enable_state = False
row.label(text="All")
#
# Skip Re-Export Settings Panel
#
box = body.box()
header_skip_reexport, body_skip_reexport = box.panel("skip_reexport_settings", default_closed=True)
column_middle.label(text="")
column_middle.label(text="Skip Re-Export")
op_box = column_middle.box()
row = op_box.row(align=True)
row.alignment = 'LEFT'
row.operator("flip_fluid_operators.helper_batch_skip_reexport", icon='CHECKBOX_HLT', text="").enable_state = True
row.operator("flip_fluid_operators.helper_batch_skip_reexport", icon='CHECKBOX_DEHLT', text="").enable_state = False
row.label(text="All")
row_skip_reexport = header_skip_reexport.row(align=True)
row_skip_reexport.label(text="Skip Mesh Re-Export:")
column_right.label(text="Force Export")
column_right.label(text="On Next Bake")
op_box = column_right.box()
row = op_box.row(align=True)
row.alignment = 'LEFT'
row.operator("flip_fluid_operators.helper_batch_force_reexport", icon='CHECKBOX_HLT', text="").enable_state = True
row.operator("flip_fluid_operators.helper_batch_force_reexport", icon='CHECKBOX_DEHLT', text="").enable_state = False
row.label(text="All")
if body_skip_reexport:
flip_props = context.scene.flip_fluid
flip_objects = (flip_props.get_obstacle_objects() +
flip_props.get_fluid_objects() +
flip_props.get_inflow_objects() +
flip_props.get_outflow_objects() +
flip_props.get_force_field_objects())
is_export_hint_enabled = not vcu.get_addon_preferences().dismiss_export_animated_mesh_parented_relation_hint
for ob in filtered_objects:
pgroup = ob.flip_fluid.get_property_group()
column_left_row = column_left.row(align=True)
column_left_row.alignment = 'LEFT'
column_left_row.label(text=ob.name, icon="OBJECT_DATA")
num_flip_objects = len(flip_objects)
flip_object_count_limit = 128
if num_flip_objects > flip_object_count_limit:
column = body_skip_reexport.column()
column.alert = True
column.label(text="Menu Unavailable", icon="ERROR")
column.label(text="This menu is only available in scenes containing " + str(flip_object_count_limit) + " FLIP objects or fewer", icon="ERROR")
column.label(text="Current number of FLIP objects: " + str(num_flip_objects), icon="ERROR")
else:
column = body_skip_reexport.column()
column.label(text="Object Motion Type:")
row = column.row(align=True)
row.prop(sprops, "mesh_reexport_type_filter", expand=True)
is_child_object = ob.parent is not None
if is_export_hint_enabled and not pgroup.export_animated_mesh and is_child_object:
column_left_row.prop(context.scene.flip_fluid_helper, "export_animated_mesh_parent_tooltip",
icon="INFO", emboss=False, text=""
)
flip_objects.sort(key=lambda x: x.name)
is_all_filter_selected = sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_ALL'
if sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_ALL':
filtered_objects = flip_objects
motion_type_string = "simulation"
elif sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_STATIC':
filtered_objects = [x for x in flip_objects if _get_object_motion_type(self, x) == 'STATIC']
motion_type_string = "static"
elif sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_KEYFRAMED':
filtered_objects = [x for x in flip_objects if _get_object_motion_type(self, x) == 'KEYFRAMED']
motion_type_string = "keyframed"
elif sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_ANIMATED':
filtered_objects = [x for x in flip_objects if _get_object_motion_type(self, x) == 'ANIMATED']
motion_type_string = "animated"
if len(filtered_objects) == 0:
column.label(text=indent_str + "No " + motion_type_string + " objects found...")
else:
split = column.split()
column_left = split.column(align=True)
if is_all_filter_selected:
column_animated = split.column(align=True)
column_middle = split.column(align=True)
column_right = split.column(align=True)
column_left.label(text="")
column_left.label(text="Object")
op_box = column_left.box()
op_box.label(text="")
if is_all_filter_selected:
column_animated.prop(pgroup, "export_animated_mesh", text="animated", toggle=True)
column_middle.prop(pgroup, "skip_reexport", text="skip", toggle=True)
column_right.prop(pgroup, "force_reexport_on_next_bake", text="force", toggle=True)
column_animated.label(text="")
column_animated.label(text="Export Animated")
op_box = column_animated.box()
row = op_box.row(align=True)
row.alignment = 'LEFT'
row.operator("flip_fluid_operators.helper_batch_export_animated_mesh", icon='CHECKBOX_HLT', text="").enable_state = True
row.operator("flip_fluid_operators.helper_batch_export_animated_mesh", icon='CHECKBOX_DEHLT', text="").enable_state = False
row.label(text="All")
subbox = box.box()
column = subbox.column(align=True)
column.label(text="Savestates:")
column.prop(sprops, "enable_savestates")
column = subbox.column(align=True)
column.enabled = sprops.enable_savestates
split = column.split()
column = split.column()
row = column.row()
row.alignment = 'RIGHT'
row.label(text="Generate savestate every")
column = split.column()
split = column.split()
column = split.column()
row = column.row(align=True)
row.prop(sprops, "savestate_interval", text="")
row.label(text="frames")
column = subbox.column(align=True)
column.enabled = sprops.enable_savestates
column.prop(sprops, "delete_outdated_savestates")
column.prop(sprops, "delete_outdated_meshes")
column_middle.label(text="")
column_middle.label(text="Skip Re-Export")
op_box = column_middle.box()
row = op_box.row(align=True)
row.alignment = 'LEFT'
row.operator("flip_fluid_operators.helper_batch_skip_reexport", icon='CHECKBOX_HLT', text="").enable_state = True
row.operator("flip_fluid_operators.helper_batch_skip_reexport", icon='CHECKBOX_DEHLT', text="").enable_state = False
row.label(text="All")
column_right.label(text="Force Export")
column_right.label(text="On Next Bake")
op_box = column_right.box()
row = op_box.row(align=True)
row.alignment = 'LEFT'
row.operator("flip_fluid_operators.helper_batch_force_reexport", icon='CHECKBOX_HLT', text="").enable_state = True
row.operator("flip_fluid_operators.helper_batch_force_reexport", icon='CHECKBOX_DEHLT', text="").enable_state = False
row.label(text="All")
is_export_hint_enabled = not vcu.get_addon_preferences().dismiss_export_animated_mesh_parented_relation_hint
for ob in filtered_objects:
pgroup = ob.flip_fluid.get_property_group()
column_left_row = column_left.row(align=True)
column_left_row.alignment = 'LEFT'
column_left_row.label(text=ob.name, icon="OBJECT_DATA")
is_child_object = ob.parent is not None
if is_export_hint_enabled and not pgroup.export_animated_mesh and is_child_object:
column_left_row.prop(context.scene.flip_fluid_helper, "export_animated_mesh_parent_tooltip",
icon="INFO", emboss=False, text=""
)
if is_all_filter_selected:
column_animated.prop(pgroup, "export_animated_mesh", text="animated", toggle=True)
column_middle.prop(pgroup, "skip_reexport", text="skip", toggle=True)
column_right.prop(pgroup, "force_reexport_on_next_bake", text="force", toggle=True)
"""
subbox = subbox.column()
row = subbox.row(align=True)
row.prop(sprops, "skip_mesh_reexport_expanded",
icon="TRIA_DOWN" if sprops.skip_mesh_reexport_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Skip Mesh Re-Export:")
if sprops.skip_mesh_reexport_expanded:
flip_props = context.scene.flip_fluid
flip_objects = (flip_props.get_obstacle_objects() +
flip_props.get_fluid_objects() +
flip_props.get_inflow_objects() +
flip_props.get_outflow_objects() +
flip_props.get_force_field_objects())
num_flip_objects = len(flip_objects)
flip_object_count_limit = 128
if num_flip_objects > flip_object_count_limit:
column = subbox.column()
column.alert = True
column.label(text="Menu Unavailable", icon="ERROR")
column.label(text="This menu is only available in scenes containing " + str(flip_object_count_limit) + " FLIP objects or fewer", icon="ERROR")
column.label(text="Current number of FLIP objects: " + str(num_flip_objects), icon="ERROR")
else:
column = subbox.column()
column.label(text="Object Motion Type:")
row = column.row(align=True)
row.prop(sprops, "mesh_reexport_type_filter", expand=True)
flip_objects.sort(key=lambda x: x.name)
is_all_filter_selected = sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_ALL'
if sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_ALL':
filtered_objects = flip_objects
motion_type_string = "simulation"
elif sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_STATIC':
filtered_objects = [x for x in flip_objects if _get_object_motion_type(self, x) == 'STATIC']
motion_type_string = "static"
elif sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_KEYFRAMED':
filtered_objects = [x for x in flip_objects if _get_object_motion_type(self, x) == 'KEYFRAMED']
motion_type_string = "keyframed"
elif sprops.mesh_reexport_type_filter == 'MOTION_FILTER_TYPE_ANIMATED':
filtered_objects = [x for x in flip_objects if _get_object_motion_type(self, x) == 'ANIMATED']
motion_type_string = "animated"
if len(filtered_objects) == 0:
column.label(text=indent_str + "No " + motion_type_string + " objects found...")
else:
split = column.split()
column_left = split.column(align=True)
if is_all_filter_selected:
column_animated = split.column(align=True)
column_middle = split.column(align=True)
column_right = split.column(align=True)
column_left.label(text="")
column_left.label(text="Object")
op_box = column_left.box()
op_box.label(text="")
if is_all_filter_selected:
column_animated.label(text="")
column_animated.label(text="Export Animated")
op_box = column_animated.box()
row = op_box.row(align=True)
row.alignment = 'LEFT'
row.operator("flip_fluid_operators.helper_batch_export_animated_mesh", icon='CHECKBOX_HLT', text="").enable_state = True
row.operator("flip_fluid_operators.helper_batch_export_animated_mesh", icon='CHECKBOX_DEHLT', text="").enable_state = False
row.label(text="All")
column_middle.label(text="")
column_middle.label(text="Skip Re-Export")
op_box = column_middle.box()
row = op_box.row(align=True)
row.alignment = 'LEFT'
row.operator("flip_fluid_operators.helper_batch_skip_reexport", icon='CHECKBOX_HLT', text="").enable_state = True
row.operator("flip_fluid_operators.helper_batch_skip_reexport", icon='CHECKBOX_DEHLT', text="").enable_state = False
row.label(text="All")
column_right.label(text="Force Export")
column_right.label(text="On Next Bake")
op_box = column_right.box()
row = op_box.row(align=True)
row.alignment = 'LEFT'
row.operator("flip_fluid_operators.helper_batch_force_reexport", icon='CHECKBOX_HLT', text="").enable_state = True
row.operator("flip_fluid_operators.helper_batch_force_reexport", icon='CHECKBOX_DEHLT', text="").enable_state = False
row.label(text="All")
is_export_hint_enabled = not vcu.get_addon_preferences().dismiss_export_animated_mesh_parented_relation_hint
for ob in filtered_objects:
pgroup = ob.flip_fluid.get_property_group()
column_left_row = column_left.row(align=True)
column_left_row.alignment = 'LEFT'
column_left_row.label(text=ob.name, icon="OBJECT_DATA")
is_child_object = ob.parent is not None
if is_export_hint_enabled and not pgroup.export_animated_mesh and is_child_object:
column_left_row.prop(context.scene.flip_fluid_helper, "export_animated_mesh_parent_tooltip",
icon="INFO", emboss=False, text=""
)
if is_all_filter_selected:
column_animated.prop(pgroup, "export_animated_mesh", text="animated", toggle=True)
column_middle.prop(pgroup, "skip_reexport", text="skip", toggle=True)
column_right.prop(pgroup, "force_reexport_on_next_bake", text="force", toggle=True)
"""
subbox = body.column()
column = subbox.column(align=True)
column.label(text="Savestates:")
column.prop(sprops, "enable_savestates")
column = subbox.column(align=True)
column.enabled = sprops.enable_savestates
split = column.split()
column = split.column()
row = column.row()
row.alignment = 'RIGHT'
row.label(text="Generate savestate every")
column = split.column()
split = column.split()
column = split.column()
row = column.row(align=True)
row.prop(sprops, "savestate_interval", text="")
row.label(text="frames")
column = subbox.column(align=True)
column.enabled = sprops.enable_savestates
column.prop(sprops, "delete_outdated_savestates")
column.prop(sprops, "delete_outdated_meshes")
def draw_resolution_settings(self, context, master_column):
def draw_simulation_settings(self, context, master_column):
obj = vcu.get_active_object(context)
dprops = obj.flip_fluid.domain
sprops = dprops.simulation
wprops = dprops.world
aprops = dprops.advanced
#
# Grid Resolution Panel
#
box = master_column.box()
column = box.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
row = column_left.row(align=True)
row.prop(sprops, "simulation_resolution_expanded",
icon="TRIA_DOWN" if sprops.simulation_resolution_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Grid Resolution:")
header, body = box.panel("simulation_resolution", default_closed=True)
if not sprops.simulation_resolution_expanded:
row = column_right.row(align=True)
row.prop(sprops, "resolution", text="Resolution")
else:
column = box.column(align=True)
row = header.row(align=True)
row.label(text="Grid Resolution:")
if body:
column = body.column(align=True)
split = vcu.ui_split(column, factor=0.5, align=True)
column_left = split.column(align=True)
@@ -327,7 +429,7 @@ def draw_resolution_settings(self, context, master_column):
column_right.enabled = not sprops.auto_preview_resolution
column_right.prop(sprops, "preview_resolution")
column = box.column(align=True)
column = body.column(align=True)
split = vcu.ui_split(column, factor=0.5)
column_left = split.column(align=True)
column_right = split.column(align=True)
@@ -339,7 +441,7 @@ def draw_resolution_settings(self, context, master_column):
old_resolution = max(sprops.savestate_isize, sprops.savestate_jsize, sprops.savestate_ksize)
indent = 7
subbox = box.box()
subbox = body.box()
column = subbox.column(align=True)
column.label(text="Increased resolution detected")
row = column.row()
@@ -347,22 +449,24 @@ def draw_resolution_settings(self, context, master_column):
row.label(text="Simulation will be upscaled on resume.")
column.label(text=indent*" " + " Cache resolution: " + str(old_resolution))
column.label(text=indent*" " + " Current resolution: " + str(sprops.resolution))
else:
row.prop(sprops, "resolution", text="Resolution")
#
# Grid Info Panel
#
box = master_column.box()
row = box.row(align=True)
row.prop(sprops, "grid_info_expanded",
icon="TRIA_DOWN" if sprops.grid_info_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("grid_info", default_closed=True)
row = header.row(align=True)
row.label(text="Grid Info:")
row = row.row()
row.alignment = 'RIGHT'
row.prop(dprops.debug, "grid_display_mode", text="")
row.prop(dprops.debug, "display_simulation_grid", text="Visualize Grid")
if sprops.grid_info_expanded:
column = box.column(align=True)
if body:
column = body.column(align=True)
split = vcu.ui_split(column, factor=0.05, align=True)
column_left = split.column(align=True)
@@ -444,25 +548,17 @@ def draw_resolution_settings(self, context, master_column):
column_right.label(text=voxel_size_str)
column_right.label(text=voxel_count_str)
#
# Simulation Method Panel
#
box = master_column.box()
column = box.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
row = column_left.row(align=True)
row.prop(sprops, "simulation_method_expanded",
icon="TRIA_DOWN" if sprops.simulation_method_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("simulation_method", default_closed=True)
row = header.row(align=True)
row.label(text="Simulation Method:")
if not sprops.simulation_method_expanded:
row = column_right.row()
row.prop(aprops, "velocity_transfer_method", expand=True)
pass
else:
column = box.column(align=True)
if body:
column = body.column(align=True)
row = column.row(align=True)
row.prop(aprops, "velocity_transfer_method", expand=True)
row = column.row(align=True)
@@ -470,15 +566,12 @@ def draw_resolution_settings(self, context, master_column):
row.prop(aprops, "PICFLIP_ratio", slider=True)
else:
row.label(text="")
else:
row.prop(aprops, "velocity_transfer_method", expand=True)
box = master_column.box()
row = box.row(align=True)
row.prop(sprops, "world_scale_expanded",
icon="TRIA_DOWN" if sprops.world_scale_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
#
# World Scale Panel
#
xdims, ydims, zdims = wprops.get_simulation_dimensions(context)
xdims_str = '{:.2f}'.format(round(xdims, 2))
ydims_str = '{:.2f}'.format(round(ydims, 2))
@@ -487,18 +580,21 @@ def draw_resolution_settings(self, context, master_column):
ydims_str = ydims_str.rstrip("0").rstrip(".") + "m"
zdims_str = zdims_str.rstrip("0").rstrip(".") + "m"
dimensions_str = str(xdims_str) + " x " + str(ydims_str) + " x " + str(zdims_str)
box = master_column.box()
header, body = box.panel("world_scale", default_closed=True)
row = header.row(align=True)
row.label(text="World Scale:")
row = row.row(align=True)
row.alignment = 'LEFT'
row = header.row(align=True)
row.alignment = 'RIGHT'
row.label(text=dimensions_str)
if not sprops.world_scale_expanded:
pass
else:
row = box.row(align=True)
if body:
row = body.row(align=True)
row.prop(wprops, "world_scale_mode", expand=True)
column = box.column(align=True)
column = body.column(align=True)
split = column.split(align=True)
column_left = split.column()
column_right = split.column()
@@ -514,15 +610,9 @@ def draw_resolution_settings(self, context, master_column):
row.label(text="Domain Length = ")
column_right.prop(wprops, "world_scale_absolute")
box = master_column.box()
row = box.row(align=True)
row.prop(sprops, "boundary_collisions_expanded",
icon="TRIA_DOWN" if sprops.boundary_collisions_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Domain Boundary Collisions:")
#
# Boundary Collisions Panel
#
if all(sprops.fluid_boundary_collisions):
boundary_collision_status_str = "Closed"
elif not any(sprops.fluid_boundary_collisions):
@@ -530,14 +620,17 @@ def draw_resolution_settings(self, context, master_column):
else:
boundary_collision_status_str = "Mixed"
row = row.row(align=True)
box = master_column.box()
header, body = box.panel("boundary_collisions", default_closed=True)
row = header.row(align=True)
row.label(text="Domain Boundary Collisions:")
row = header.row(align=True)
row.alignment = 'RIGHT'
row.label(text=boundary_collision_status_str)
if not sprops.boundary_collisions_expanded:
pass
else:
column = box.column(align=True)
if body:
column = body.column(align=True)
row = column.row(align=True)
row.prop(sprops, "fluid_boundary_collisions", index=0, text="X ")
row.prop(sprops, "fluid_boundary_collisions", index=1, text="X+")
@@ -550,99 +643,86 @@ def draw_resolution_settings(self, context, master_column):
column.prop(sprops, "fluid_open_boundary_width", slider=True)
def _get_object_motion_type(self, obj):
props = obj.flip_fluid.get_property_group()
if hasattr(props, 'export_animated_mesh') and props.export_animated_mesh:
return 'ANIMATED'
if export_utils.is_object_keyframe_animated(obj):
return 'KEYFRAMED'
return 'STATIC'
#
# Draw Frame Rate and Time Scale Panel
#
fps_str = "{:.2f}".format(sprops.get_frame_rate()) + " FPS"
row = row.row(align =True)
box = master_column.box()
header, body = box.panel("frame_rate_and_time_scale", default_closed=True)
def draw_time_settings(self, context, box):
obj = vcu.get_active_object(context)
sprops = obj.flip_fluid.domain.simulation
row = box.row(align=True)
row.prop(sprops, "frame_rate_and_time_scale_expanded",
icon="TRIA_DOWN" if sprops.frame_rate_and_time_scale_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row = header.row(align=True)
row.label(text="Frame Rate and Time Scale:")
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text=fps_str)
if not sprops.frame_rate_and_time_scale_expanded:
fps_str = "{:.2f}".format(sprops.get_frame_rate()) + " FPS"
row = row.row(align =True)
row.alignment = 'RIGHT'
row.label(text=fps_str)
return
if body:
column = body.column(align=True)
column.label(text="Frame Rate:")
column = box.column(align=True)
column.label(text="Frame Rate:")
row = column.row(align=True)
row.prop(sprops, "frame_rate_mode", expand=True)
column = column.column(align=True)
column.enabled = sprops.frame_rate_mode == 'FRAME_RATE_MODE_CUSTOM'
if sprops.frame_rate_mode == 'FRAME_RATE_MODE_SCENE':
column.prop(context.scene.render, "fps", text="Scene Frame Rate")
else:
column.prop(sprops, "frame_rate_custom", text="Custom Frame Rate")
column = box.column(align=True)
column.label(text="Time Scale:")
row = column.row(align=True)
row.prop(sprops, "time_scale_mode", expand=True)
column = column.column(align=True)
if sprops.time_scale_mode == 'TIME_SCALE_MODE_CUSTOM':
column.prop(sprops, "time_scale", text="Custom Time Scale")
elif sprops.time_scale_mode == 'TIME_SCALE_MODE_RIGID_BODY':
if bpy.context.scene.rigidbody_world is not None:
column.prop(bpy.context.scene.rigidbody_world, "time_scale", text="Rigid Body Time Scale")
row = column.row(align=True)
row.prop(sprops, "frame_rate_mode", expand=True)
column = column.column(align=True)
column.enabled = sprops.frame_rate_mode == 'FRAME_RATE_MODE_CUSTOM'
if sprops.frame_rate_mode == 'FRAME_RATE_MODE_SCENE':
column.prop(context.scene.render, "fps", text="Scene Frame Rate")
else:
column.prop(sprops, "frame_rate_custom", text="Custom Frame Rate")
column = body.column(align=True)
column.label(text="Time Scale:")
row = column.row(align=True)
row.prop(sprops, "time_scale_mode", expand=True)
column = column.column(align=True)
if sprops.time_scale_mode == 'TIME_SCALE_MODE_CUSTOM':
column.prop(sprops, "time_scale", text="Custom Time Scale")
elif sprops.time_scale_mode == 'TIME_SCALE_MODE_RIGID_BODY':
if bpy.context.scene.rigidbody_world is not None:
column.prop(bpy.context.scene.rigidbody_world, "time_scale", text="Rigid Body Time Scale")
else:
row = column.row(align=True)
row.label(text="No Rigid Body World: ")
row.operator("rigidbody.world_add")
elif sprops.time_scale_mode == 'TIME_SCALE_MODE_SOFT_BODY':
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
column_left.label(text="Soft Body Object:")
column_right.prop(sprops, "time_scale_object_soft_body", text="")
row = column.row(align=True)
row.label(text="No Rigid Body World: ")
row.operator("rigidbody.world_add")
elif sprops.time_scale_mode == 'TIME_SCALE_MODE_SOFT_BODY':
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
column_left.label(text="Soft Body Object:")
column_right.prop(sprops, "time_scale_object_soft_body", text="")
row = column.row(align=True)
soft_body_modifier = sprops.get_selected_time_scale_object_soft_body_modifier()
if soft_body_modifier is not None:
row.prop(soft_body_modifier.settings, "speed", text="Soft Body Time Scale")
else:
if sprops.time_scale_object_soft_body is not None:
row.label(text="No soft body simulation found on object")
soft_body_modifier = sprops.get_selected_time_scale_object_soft_body_modifier()
if soft_body_modifier is not None:
row.prop(soft_body_modifier.settings, "speed", text="Soft Body Time Scale")
else:
row.label(text="No soft body object selected")
if sprops.time_scale_object_soft_body is not None:
row.label(text="No soft body simulation found on object")
else:
row.label(text="No soft body object selected")
elif sprops.time_scale_mode == 'TIME_SCALE_MODE_CLOTH':
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
column_left.label(text="Cloth Object:")
column_right.prop(sprops, "time_scale_object_cloth", text="")
row = column.row(align=True)
cloth_modifier = sprops.get_selected_time_scale_object_cloth_modifier()
if cloth_modifier is not None:
row.prop(cloth_modifier.settings, "time_scale", text="Cloth Time Scale")
else:
if sprops.time_scale_object_cloth is not None:
row.label(text="No cloth simulation found on object")
elif sprops.time_scale_mode == 'TIME_SCALE_MODE_CLOTH':
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
column_left.label(text="Cloth Object:")
column_right.prop(sprops, "time_scale_object_cloth", text="")
row = column.row(align=True)
cloth_modifier = sprops.get_selected_time_scale_object_cloth_modifier()
if cloth_modifier is not None:
row.prop(cloth_modifier.settings, "time_scale", text="Cloth Time Scale")
else:
row.label(text="No cloth object selected")
if sprops.time_scale_object_cloth is not None:
row.label(text="No cloth simulation found on object")
else:
row.label(text="No cloth object selected")
elif sprops.time_scale_mode == 'TIME_SCALE_MODE_FLUID':
if vcu.is_blender_282():
elif sprops.time_scale_mode == 'TIME_SCALE_MODE_FLUID':
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
@@ -658,9 +738,15 @@ def draw_time_settings(self, context, box):
row.label(text="No Mantaflow domain found on object")
else:
row.label(text="No Mantaflow domain object selected")
else:
column.label(text="Mantaflow fluid simulation time scale mode")
column.label(text="only supported in Blender 2.82 or later")
def _get_object_motion_type(self, obj):
props = obj.flip_fluid.get_property_group()
if hasattr(props, 'export_animated_mesh') and props.export_animated_mesh:
return 'ANIMATED'
if export_utils.is_object_keyframe_animated(obj):
return 'KEYFRAMED'
return 'STATIC'
class FLIPFLUID_PT_DomainTypePanel(bpy.types.Panel):
@@ -700,10 +786,7 @@ class FLIPFLUID_PT_DomainTypePanel(bpy.types.Panel):
draw_more_bake_settings(self, context, box)
column = self.layout.column()
draw_resolution_settings(self, context, column)
box = self.layout.box()
draw_time_settings(self, context, box)
draw_simulation_settings(self, context, column)
def register():
@@ -54,17 +54,16 @@ def draw_frame_info_simulation_stats(self, context, box):
sprops = vcu.get_active_object(context).flip_fluid.domain.stats
simprops = vcu.get_active_object(context).flip_fluid.domain.simulation
subbox = box.box()
row = subbox.row()
row.prop(sprops, "frame_info_simulation_stats_expanded",
icon="TRIA_DOWN" if sprops.frame_info_simulation_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Simulation Stats")
#
# Simulation Frame Stats Panel
#
box = box.box()
header, body = box.panel("simulation_frame_stats_settings", default_closed=False)
if sprops.frame_info_simulation_stats_expanded:
column = subbox.column()
row = header.row(align=True)
row.label(text="Simulation Stats:")
if body:
column = body.column()
split = column.split()
column = split.column()
column.label(text="Frame ID:")
@@ -102,30 +101,27 @@ def draw_frame_info_simulation_stats(self, context, box):
def draw_frame_info_solver_stats(self, context, box):
sprops = vcu.get_active_object(context).flip_fluid.domain.stats
subbox = box.box()
row = subbox.row()
row.prop(sprops, "frame_info_solver_stats_expanded",
icon="TRIA_DOWN" if sprops.frame_info_solver_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Solver Stats")
#
# Solver Frame Stats Panel
#
stress_threshold = 80.0
if sprops.frame_info_solver_stats_expanded:
box = box.box()
header, body = box.panel("solver_frame_stats_settings", default_closed=False)
row = header.row(align=True)
row.label(text="Solver Stats:")
if body:
if sprops.frame_pressure_solver_enabled:
stress_threshold = 80.0
#
# Pressure Solver Frame Stats Panel
#
header_pressure, body_pressure = body.panel("pressure_solver_frame_stats_settings", default_closed=False)
stat_box = subbox.box()
row = stat_box.row()
row.prop(sprops, "frame_info_pressure_solver_stats_expanded",
icon="TRIA_DOWN" if sprops.frame_info_pressure_solver_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Pressure Solver")
if sprops.frame_info_pressure_solver_stats_expanded:
column = stat_box.column(align=True)
row_pressure = header_pressure.row(align=True)
row_pressure.label(text="Pressure Solver:")
if body_pressure:
column = body_pressure.column(align=True)
split = column.split()
column1 = split.column(align=True)
column2 = split.column(align=True)
@@ -157,17 +153,15 @@ def draw_frame_info_solver_stats(self, context, box):
row.prop(sprops.frame_pressure_solver_stress, "stress_level", slider=True, text=stress_status)
if sprops.frame_viscosity_solver_enabled:
stat_box = subbox.box()
row = stat_box.row()
row.prop(sprops, "frame_info_viscosity_solver_stats_expanded",
icon="TRIA_DOWN" if sprops.frame_info_viscosity_solver_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Viscosity Solver")
#
# Viscosity Solver Frame Stats Panel
#
header_viscosity, body_viscosity = body.panel("viscosity_solver_frame_stats_settings", default_closed=False)
if sprops.frame_info_viscosity_solver_stats_expanded:
column = stat_box.column(align=True)
row_viscosity = header_viscosity.row(align=True)
row_viscosity.label(text="Viscosity Solver:")
if body_viscosity:
column = body_viscosity.column(align=True)
column.alert = not sprops.frame_viscosity_solver_success
split = column.split()
@@ -204,17 +198,16 @@ def draw_frame_info_solver_stats(self, context, box):
def draw_frame_info_timing_stats(self, context, box):
sprops = vcu.get_active_object(context).flip_fluid.domain.stats
subbox = box.box()
row = subbox.row()
row.prop(sprops, "frame_info_timing_stats_expanded",
icon="TRIA_DOWN" if sprops.frame_info_timing_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Timing Stats")
#
# Timing Frame Stats Panel
#
box = box.box()
header, body = box.panel("timing_frame_stats_settings", default_closed=False)
if sprops.frame_info_timing_stats_expanded:
column = subbox.column()
row = header.row(align=True)
row.label(text="Timing Stats:")
if body:
column = body.column()
split = vcu.ui_split(column, factor=0.75)
column = split.column(align = True)
column.prop(sprops.time_mesh, "pct", slider = True, text = "Mesh Generation")
@@ -246,7 +239,7 @@ def draw_frame_info_timing_stats(self, context, box):
sprops.time_diffuse.time + sprops.time_viscosity.time +
sprops.time_objects.time + sprops.time_other.time)
column = subbox.column()
column = body.column()
split = column.split()
column = split.column()
column = split.column()
@@ -261,17 +254,16 @@ def draw_frame_info_mesh_stats(self, context, box):
sprops = vcu.get_active_object(context).flip_fluid.domain.stats
simprops = vcu.get_active_object(context).flip_fluid.domain.simulation
subbox = box.box()
row = subbox.row()
row.prop(sprops, "frame_info_mesh_stats_expanded",
icon="TRIA_DOWN" if sprops.frame_info_mesh_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Mesh Stats")
#
# Mesh Frame Stats Panel
#
box = box.box()
header, body = box.panel("mesh_frame_stats_settings", default_closed=False)
if sprops.frame_info_mesh_stats_expanded:
column = subbox.column()
row = header.row(align=True)
row.label(text="Mesh Stats:")
if body:
column = body.column()
split = column.split()
column1 = split.column()
column2 = split.column()
@@ -368,6 +360,13 @@ def draw_frame_info_mesh_stats(self, context, box):
column4.label(text=format_bytes(sprops.surfaceviscosity_mesh.bytes.get()))
total_bytes += sprops.surfaceviscosity_mesh.bytes.get()
if sprops.surfacedensity_mesh.enabled:
column1.label(text="Density")
column2.label(text=format_number(sprops.surfacedensity_mesh.verts))
column3.label(text="")
column4.label(text=format_bytes(sprops.surfacedensity_mesh.bytes.get()))
total_bytes += sprops.surfacedensity_mesh.bytes.get()
if sprops.foam_mesh.enabled:
column1.label(text="Foam")
column2.label(text=format_number(sprops.foam_mesh.verts))
@@ -578,6 +577,20 @@ def draw_frame_info_mesh_stats(self, context, box):
column4.label(text=format_bytes(sprops.fluid_particle_viscosity_mesh.bytes.get()))
total_bytes += sprops.fluid_particle_viscosity_mesh.bytes.get()
if sprops.fluid_particle_density_mesh.enabled:
column1.label(text="Fluid Particles Density")
column2.label(text=format_number(sprops.fluid_particle_density_mesh.verts))
column3.label(text="")
column4.label(text=format_bytes(sprops.fluid_particle_density_mesh.bytes.get()))
total_bytes += sprops.fluid_particle_density_mesh.bytes.get()
if sprops.fluid_particle_density_average_mesh.enabled:
column1.label(text="Fluid Particles Density Average")
column2.label(text=format_number(sprops.fluid_particle_density_average_mesh.verts))
column3.label(text="")
column4.label(text=format_bytes(sprops.fluid_particle_density_average_mesh.bytes.get()))
total_bytes += sprops.fluid_particle_density_average_mesh.bytes.get()
if sprops.fluid_particle_whitewater_proximity_mesh.enabled:
column1.label(text="Fluid Particles Whitewater Proximity")
column2.label(text=format_number(sprops.fluid_particle_whitewater_proximity_mesh.verts))
@@ -627,7 +640,6 @@ def draw_frame_info(self, context, box):
else:
box.label(text="Data Not Available (frame " + str(sprops.current_info_frame) + ")", icon='ERROR')
box.separator()
draw_frame_info_simulation_stats(self, context, box)
draw_frame_info_solver_stats(self, context, box)
draw_frame_info_timing_stats(self, context, box)
@@ -639,20 +651,19 @@ def draw_cache_info_simulation_stats(self, context, box):
sprops = dprops.stats
simprops = dprops.simulation
subbox = box.box()
row = subbox.row()
row.prop(sprops, "cache_info_simulation_stats_expanded",
icon="TRIA_DOWN" if sprops.cache_info_simulation_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Simulation Stats")
#
# Simulation Cache Stats Panel
#
box = box.box()
header, body = box.panel("simulation_cache_stats_settings", default_closed=False)
if sprops.cache_info_simulation_stats_expanded:
row = header.row(align=True)
row.label(text="Simulation Stats:")
if body:
num_frames = dprops.simulation.frame_end - sprops.frame_start + 1
num_baked_frames = sprops.num_cache_frames
column = subbox.column()
column = body.column()
split = column.split()
column = split.column()
column.label(text="Completed Frames:")
@@ -672,7 +683,7 @@ def draw_cache_info_simulation_stats(self, context, box):
column.label(text=str(sprops.average_performance_score))
if dprops.bake.is_simulation_running:
column = subbox.column()
column = body.column()
split = column.split()
column = split.column()
@@ -690,119 +701,111 @@ def draw_cache_info_solver_stats(self, context, box):
sprops = dprops.stats
simprops = dprops.simulation
subbox = box.box()
row = subbox.row()
row.prop(sprops, "cache_info_solver_stats_expanded",
icon="TRIA_DOWN" if sprops.cache_info_solver_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Solver Stats")
#
# Solver Cache Stats Panel
#
box = box.box()
header, body = box.panel("solver_cache_stats_settings", default_closed=False)
if not sprops.cache_info_solver_stats_expanded:
return
row = header.row(align=True)
row.label(text="Solver Stats:")
if body:
if sprops.pressure_solver_enabled:
#
# Pressure Solver Cache Stats Panel
#
header_pressure, body_pressure = body.panel("pressure_solver_cache_stats_settings", default_closed=False)
if sprops.pressure_solver_enabled:
pressure_box = subbox.box()
row = pressure_box.row()
row.prop(sprops, "cache_info_pressure_solver_stats_expanded",
icon="TRIA_DOWN" if sprops.cache_info_pressure_solver_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Pressure Solver")
row_pressure = header_pressure.row(align=True)
row_pressure.label(text="Pressure Solver:")
if body_pressure:
column = body_pressure.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_middle = split.column(align=True)
column_right = split.column(align=True)
if sprops.cache_info_pressure_solver_stats_expanded:
column = pressure_box.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_middle = split.column(align=True)
column_right = split.column(align=True)
column_left.label(text="Solver Failures:")
column_left.label(text="Max Iterations:")
column_left.label(text="Max Error:")
column_left.label(text="Max Stress:")
column_left.label(text="Solver Failures:")
column_left.label(text="Max Iterations:")
column_left.label(text="Max Error:")
column_left.label(text="Max Stress:")
failure_str = str(sprops.pressure_solver_failures) + " failures / " + str(sprops.pressure_solver_steps) + " steps"
iterations_str = str(sprops.pressure_solver_max_iterations)
error_str = '{0:.12f}'.format(sprops.pressure_solver_max_error)
stress_threshold = 80.0
stress_state = "OK"
if sprops.pressure_solver_max_stress > stress_threshold:
stress_state = "HIGH"
if sprops.pressure_solver_max_stress >= 99.999:
stress_state = "MAX"
stress_str = '{0:.1f}'.format(sprops.pressure_solver_max_stress) + "% " + stress_state
failure_str = str(sprops.pressure_solver_failures) + " failures / " + str(sprops.pressure_solver_steps) + " steps"
iterations_str = str(sprops.pressure_solver_max_iterations)
error_str = '{0:.12f}'.format(sprops.pressure_solver_max_error)
stress_threshold = 80.0
stress_state = "OK"
if sprops.pressure_solver_max_stress > stress_threshold:
stress_state = "HIGH"
if sprops.pressure_solver_max_stress >= 99.999:
stress_state = "MAX"
stress_str = '{0:.1f}'.format(sprops.pressure_solver_max_stress) + "% " + stress_state
column_middle.label(text=failure_str)
column_middle.label(text=iterations_str)
column_middle.label(text=error_str)
column_middle.label(text=stress_str)
column_middle.label(text=failure_str)
column_middle.label(text=iterations_str)
column_middle.label(text=error_str)
column_middle.label(text=stress_str)
column_right.label(text="")
column_right.label(text="(frame " + str(sprops.pressure_solver_max_iterations_frame) + ")")
column_right.label(text="(frame " + str(sprops.pressure_solver_max_error_frame) + ")")
column_right.label(text="(frame " + str(sprops.pressure_solver_max_stress_frame) + ")")
column_right.label(text="")
column_right.label(text="(frame " + str(sprops.pressure_solver_max_iterations_frame) + ")")
column_right.label(text="(frame " + str(sprops.pressure_solver_max_error_frame) + ")")
column_right.label(text="(frame " + str(sprops.pressure_solver_max_stress_frame) + ")")
if sprops.viscosity_solver_enabled:
#
# Viscosity Solver Cache Stats Panel
#
header_viscosity, body_viscosity = body.panel("viscosity_solver_cache_stats_settings", default_closed=False)
if sprops.viscosity_solver_enabled:
viscosity_box = subbox.box()
row = viscosity_box.row()
row.prop(sprops, "cache_info_viscosity_solver_stats_expanded",
icon="TRIA_DOWN" if sprops.cache_info_viscosity_solver_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Viscosity Solver")
row_viscosity = header_viscosity.row(align=True)
row_viscosity.label(text="Viscosity Solver:")
if body_viscosity:
column = body_viscosity.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_middle = split.column(align=True)
column_right = split.column(align=True)
if sprops.cache_info_viscosity_solver_stats_expanded:
column = viscosity_box.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_middle = split.column(align=True)
column_right = split.column(align=True)
column_left.label(text="Solver Failures:")
column_left.label(text="Max Iterations:")
column_left.label(text="Max Error:")
column_left.label(text="Max Stress:")
column_left.label(text="Solver Failures:")
column_left.label(text="Max Iterations:")
column_left.label(text="Max Error:")
column_left.label(text="Max Stress:")
failure_str = str(sprops.viscosity_solver_failures) + " failures / " + str(sprops.viscosity_solver_steps) + " steps"
iterations_str = str(sprops.viscosity_solver_max_iterations)
error_str = '{0:.12f}'.format(sprops.viscosity_solver_max_error)
stress_threshold = 80.0
stress_state = "OK"
if sprops.viscosity_solver_max_stress > stress_threshold:
stress_state = "HIGH"
if sprops.viscosity_solver_max_stress >= 99.999:
stress_state = "MAX"
stress_str = '{0:.1f}'.format(sprops.viscosity_solver_max_stress) + "% " + stress_state
failure_str = str(sprops.viscosity_solver_failures) + " failures / " + str(sprops.viscosity_solver_steps) + " steps"
iterations_str = str(sprops.viscosity_solver_max_iterations)
error_str = '{0:.12f}'.format(sprops.viscosity_solver_max_error)
stress_threshold = 80.0
stress_state = "OK"
if sprops.viscosity_solver_max_stress > stress_threshold:
stress_state = "HIGH"
if sprops.viscosity_solver_max_stress >= 99.999:
stress_state = "MAX"
stress_str = '{0:.1f}'.format(sprops.viscosity_solver_max_stress) + "% " + stress_state
column_middle.label(text=failure_str)
column_middle.label(text=iterations_str)
column_middle.label(text=error_str)
column_middle.label(text=stress_str)
column_middle.label(text=failure_str)
column_middle.label(text=iterations_str)
column_middle.label(text=error_str)
column_middle.label(text=stress_str)
column_right.label(text="")
column_right.label(text="(frame " + str(sprops.viscosity_solver_max_iterations_frame) + ")")
column_right.label(text="(frame " + str(sprops.viscosity_solver_max_error_frame) + ")")
column_right.label(text="(frame " + str(sprops.viscosity_solver_max_stress_frame) + ")")
column_right.label(text="")
column_right.label(text="(frame " + str(sprops.viscosity_solver_max_iterations_frame) + ")")
column_right.label(text="(frame " + str(sprops.viscosity_solver_max_error_frame) + ")")
column_right.label(text="(frame " + str(sprops.viscosity_solver_max_stress_frame) + ")")
def draw_cache_info_timing_stats(self, context, box):
sprops = vcu.get_active_object(context).flip_fluid.domain.stats
subbox = box.box()
row = subbox.row()
row.prop(sprops, "cache_info_timing_stats_expanded",
icon="TRIA_DOWN" if sprops.cache_info_timing_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Timing Stats")
#
# Timing Cache Stats Panel
#
box = box.box()
header, body = box.panel("timing_cache_stats_settings", default_closed=False)
if sprops.cache_info_timing_stats_expanded:
column = subbox.column()
row = header.row(align=True)
row.label(text="Timing Stats:")
if body:
column = body.column()
split = vcu.ui_split(column, factor=0.75)
column = split.column(align=True)
column.prop(sprops.time_mesh, "pct", slider=True, text="Mesh Generation")
@@ -834,7 +837,7 @@ def draw_cache_info_timing_stats(self, context, box):
sprops.time_diffuse.time + sprops.time_viscosity.time +
sprops.time_objects.time + sprops.time_other.time)
column = subbox.column()
column = body.column()
split = column.split()
column = split.column()
column = split.column()
@@ -848,17 +851,16 @@ def draw_cache_info_timing_stats(self, context, box):
def draw_cache_info_mesh_stats(self, context, box):
sprops = vcu.get_active_object(context).flip_fluid.domain.stats
subbox = box.box()
row = subbox.row()
row.prop(sprops, "cache_info_mesh_stats_expanded",
icon="TRIA_DOWN" if sprops.cache_info_mesh_stats_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Mesh Stats")
#
# Mesh Cache Stats Panel
#
box = box.box()
header, body = box.panel("mesh_cache_stats_settings", default_closed=False)
if sprops.cache_info_mesh_stats_expanded:
column = subbox.column()
row = header.row(align=True)
row.label(text="Mesh Stats:")
if body:
column = body.column()
split = vcu.ui_split(column, factor=0.5)
column1 = split.column()
column2 = split.column()
@@ -875,6 +877,7 @@ def draw_cache_info_mesh_stats(self, context, box):
sprops.surfacecolor_mesh.enabled or
sprops.surfacesourceid_mesh.enabled or
sprops.surfaceviscosity_mesh.enabled or
sprops.surfacedensity_mesh.enabled or
sprops.foam_mesh.enabled or
sprops.bubble_mesh.enabled or
sprops.spray_mesh.enabled or
@@ -904,6 +907,8 @@ def draw_cache_info_mesh_stats(self, context, box):
sprops.fluid_particle_age_mesh.enabled or
sprops.fluid_particle_lifetime_mesh.enabled or
sprops.fluid_particle_viscosity_mesh.enabled or
sprops.fluid_particle_density_mesh.enabled or
sprops.fluid_particle_density_average_mesh.enabled or
sprops.fluid_particle_whitewater_proximity_mesh.enabled or
sprops.fluid_particle_source_id_mesh.enabled or
sprops.fluid_particle_uid_mesh.enabled or
@@ -988,6 +993,12 @@ def draw_cache_info_mesh_stats(self, context, box):
row_count += 1
total_size += sprops.surfaceviscosity_mesh.bytes.get()
if sprops.surfacedensity_mesh.enabled:
column1.label(text="Density")
column2.label(text=format_bytes(sprops.surfacedensity_mesh.bytes.get()))
row_count += 1
total_size += sprops.surfacedensity_mesh.bytes.get()
if sprops.foam_mesh.enabled:
column1.label(text="Foam")
column2.label(text=format_bytes(sprops.foam_mesh.bytes.get()))
@@ -1168,6 +1179,18 @@ def draw_cache_info_mesh_stats(self, context, box):
row_count += 1
total_size += sprops.fluid_particle_viscosity_mesh.bytes.get()
if sprops.fluid_particle_density_mesh.enabled:
column1.label(text="Fluid Particles Density")
column2.label(text=format_bytes(sprops.fluid_particle_density_mesh.bytes.get()))
row_count += 1
total_size += sprops.fluid_particle_density_mesh.bytes.get()
if sprops.fluid_particle_density_average_mesh.enabled:
column1.label(text="Fluid Particles Density Average")
column2.label(text=format_bytes(sprops.fluid_particle_density_average_mesh.bytes.get()))
row_count += 1
total_size += sprops.fluid_particle_density_average_mesh.bytes.get()
if sprops.fluid_particle_whitewater_proximity_mesh.enabled:
column1.label(text="Fluid Particles Whitewater Proximity")
column2.label(text=format_bytes(sprops.fluid_particle_whitewater_proximity_mesh.bytes.get()))
@@ -1193,7 +1216,7 @@ def draw_cache_info_mesh_stats(self, context, box):
total_size += sprops.obstacle_mesh.bytes.get()
if stats_exist:
column = subbox.column()
column = body.column()
split = column.split()
column1 = split.column()
column2 = split.column()
@@ -31,61 +31,33 @@ def _draw_geometry_attributes_menu(self, context):
obj = vcu.get_active_object(context)
sprops = obj.flip_fluid.domain.surface
rprops = obj.flip_fluid.domain.render
is_surface_mesh_generation_enabled = sprops.enable_surface_mesh_generation
#
# Geometry Attributes
#
is_preview_mode_enabled = rprops.viewport_display == 'DISPLAY_PREVIEW'
is_attributes_enabled = (
sprops.enable_velocity_vector_attribute or
sprops.enable_speed_attribute or
sprops.enable_vorticity_vector_attribute or
sprops.enable_color_attribute or
sprops.enable_age_attribute or
sprops.enable_lifetime_attribute or
sprops.enable_whitewater_proximity_attribute or
sprops.enable_source_id_attribute or
sprops.enable_viscosity_attribute
)
box = self.layout.box()
row = box.row(align=True)
row.alert = not sprops.enable_surface_mesh_generation
row.prop(sprops, "geometry_attributes_expanded",
icon="TRIA_DOWN" if sprops.geometry_attributes_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("geometry_attributes", default_closed=True)
row = header.row(align=True)
row.alert = not is_surface_mesh_generation_enabled
row.label(text="Surface Attributes:")
if sprops.geometry_attributes_expanded:
prefs = vcu.get_addon_preferences()
if not prefs.is_extra_features_enabled():
warn_box = box.box()
warn_column = warn_box.column(align=True)
warn_column.enabled = True
warn_column.label(text=" This feature is affected by a current bug in Blender.", icon='ERROR')
warn_column.label(text=" The Extra Features option must be enabled in preferences")
warn_column.label(text=" to use this feature.")
warn_column.separator()
warn_column.prop(prefs, "enable_extra_features", text="Enable Extra Features in Preferences")
warn_column.separator()
warn_column.operator(
"wm.url_open",
text="Important Info and Limitations",
icon="WORLD"
).url = "https://github.com/rlguy/Blender-FLIP-Fluids/wiki/Preferences-Menu-Settings#developer-tools"
return
if not vcu.is_blender_293():
column = box.column(align=True)
column.enabled = False
column.label(text="Geometry attribute features for the fluid surface are only available in", icon='ERROR')
column.label(text="Blender 2.93 or later. Blender 3.1 or later recommended.", icon='ERROR')
return
is_preview_mode_enabled = rprops.viewport_display == 'DISPLAY_PREVIEW'
is_attributes_enabled = (
sprops.enable_velocity_vector_attribute or
sprops.enable_speed_attribute or
sprops.enable_vorticity_vector_attribute or
sprops.enable_color_attribute or
sprops.enable_age_attribute or
sprops.enable_lifetime_attribute or
sprops.enable_whitewater_proximity_attribute or
sprops.enable_source_id_attribute or
sprops.enable_viscosity_attribute
)
if body:
if is_preview_mode_enabled and is_attributes_enabled:
row = box.row(align=True)
row = body.row(align=True)
row.alert = True
row.alignment = 'LEFT'
row.prop(sprops, "preview_mode_attributes_tooltip", icon="QUESTION", emboss=False, text="")
@@ -94,17 +66,14 @@ def _draw_geometry_attributes_menu(self, context):
#
# Velocity Attributes
#
subbox = box.box()
row = subbox.row(align=True)
row.prop(sprops, "velocity_attributes_expanded",
icon="TRIA_DOWN" if sprops.velocity_attributes_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Velocity Based Attributes:")
box = body.box()
header_velocity, body_velocity = box.panel("velocity_attributes", default_closed=True)
if sprops.velocity_attributes_expanded:
column = subbox.column(align=True)
row_velocity = header_velocity.row(align=True)
row_velocity.alert = not is_surface_mesh_generation_enabled
row_velocity.label(text="Velocity Based Attributes:")
if body_velocity:
column = body_velocity.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
@@ -119,7 +88,7 @@ def _draw_geometry_attributes_menu(self, context):
column.separator()
column.operator("flip_fluid_operators.helper_initialize_motion_blur")
else:
row = row.row(align=True)
row = row_velocity.row(align=True)
row.alignment = 'RIGHT'
row.prop(sprops, "enable_velocity_vector_attribute", text="Velocity")
row.prop(sprops, "enable_speed_attribute", text="Speed")
@@ -128,17 +97,14 @@ def _draw_geometry_attributes_menu(self, context):
#
# Color Attributes
#
subbox = box.box()
row = subbox.row(align=True)
row.prop(sprops, "color_attributes_expanded",
icon="TRIA_DOWN" if sprops.color_attributes_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Color and Mixing Attributes:")
box = body.box()
header_color, body_color = box.panel("color_attributes", default_closed=True)
if sprops.color_attributes_expanded:
column = subbox.column(align=True)
row_color = header_color.row(align=True)
row_color.alert = not is_surface_mesh_generation_enabled
row_color.label(text="Color and Mixing Attributes:")
if body_color:
column = body_color.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
@@ -146,7 +112,7 @@ def _draw_geometry_attributes_menu(self, context):
if sprops.show_smoothing_radius_in_ui:
column_right.prop(sprops, "color_attribute_radius", text="Smoothing", slider=True)
column = subbox.column(align=True)
column = body_color.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
@@ -155,7 +121,7 @@ def _draw_geometry_attributes_menu(self, context):
column_right.enabled = sprops.enable_color_attribute and sprops.enable_color_attribute_mixing
column_right.prop(sprops, "color_attribute_mixing_rate", text="Mix Rate", slider=True)
column = subbox.column(align=True)
column = body_color.column(align=True)
column.enabled = sprops.enable_color_attribute and sprops.enable_color_attribute_mixing
column.label(text="Mixing Mode:")
row = column.row(align=True)
@@ -178,10 +144,10 @@ def _draw_geometry_attributes_menu(self, context):
text="Open Preferences", icon="PREFERENCES"
).view_mode = 'PREFERENCES_MENU_VIEW_MIXBOX'
else:
row = row.row(align=True)
row = row_color.row(align=True)
row.alignment = 'RIGHT'
row.prop(sprops, "enable_color_attribute", text="Color")
row = row.row(align=True)
row = row_color.row(align=True)
row.alignment = 'RIGHT'
row.enabled = sprops.enable_color_attribute
row.prop(sprops, "enable_color_attribute_mixing", text="Mixing")
@@ -189,17 +155,14 @@ def _draw_geometry_attributes_menu(self, context):
#
# Other Attributes
#
subbox = box.box()
row = subbox.row(align=True)
row.prop(sprops, "other_attributes_expanded",
icon="TRIA_DOWN" if sprops.other_attributes_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Other Attributes:")
box = body.box()
header_other, body_other = box.panel("other_attributes", default_closed=True)
if sprops.other_attributes_expanded:
column = subbox.column(align=True)
row_other = header_other.row(align=True)
row_other.alert = not is_surface_mesh_generation_enabled
row_other.label(text="Other Attributes:")
if body_other:
column = body_other.column(align=True)
row = column.row(align=True)
row.prop(sprops, "enable_age_attribute", text="Age Attributes")
if sprops.show_smoothing_radius_in_ui:
@@ -217,7 +180,7 @@ def _draw_geometry_attributes_menu(self, context):
row.prop(sprops, "whitewater_proximity_attribute_radius", text="Smoothing", slider=True)
column.prop(sprops, "enable_source_id_attribute", text="Source ID Attributes")
else:
row = row.row(align=True)
row = row_other.row(align=True)
row.alignment = 'RIGHT'
row.prop(sprops, "enable_age_attribute", text="Age")
row.prop(sprops, "enable_lifetime_attribute", text="Life")
@@ -245,21 +208,28 @@ class FLIPFLUID_PT_DomainTypeFluidSurfacePanel(bpy.types.Panel):
def draw(self, context):
obj = vcu.get_active_object(context)
sprops = obj.flip_fluid.domain.surface
is_surface_mesh_generation_enabled = sprops.enable_surface_mesh_generation
column = self.layout.column(align=True)
column.prop(sprops, "enable_surface_mesh_generation")
#
# Surface Mesh Panel
#
box = self.layout.box()
row = box.row(align=True)
row.alert = not sprops.enable_surface_mesh_generation
row.prop(sprops, "surface_mesh_expanded",
icon="TRIA_DOWN" if sprops.surface_mesh_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Surface Mesh:")
header, body = box.panel("surface_mesh", default_closed=False)
if not sprops.surface_mesh_expanded:
row = header.row(align=True)
row.alert = not is_surface_mesh_generation_enabled
row.label(text="Surface Mesh:")
if body:
column = body.column(align=True)
column.prop(sprops, "subdivisions")
row = column.row(align=True)
if sprops.particle_scale < 0.999:
row.alert = True
row.prop(sprops, "particle_scale")
else:
info_text = "Subdivisions " + str(sprops.subdivisions) + " / "
info_text += "Scale " + "{:.2f}".format(sprops.particle_scale)
row = row.row(align=True)
@@ -268,71 +238,53 @@ class FLIPFLUID_PT_DomainTypeFluidSurfacePanel(bpy.types.Panel):
row.alert = True
row.label(text=info_text)
if sprops.surface_mesh_expanded:
column = box.column(align=True)
column.prop(sprops, "subdivisions")
row = column.row(align=True)
if sprops.particle_scale < 0.999:
row.alert = True
row.prop(sprops, "particle_scale")
object_collection = vcu.get_scene_collection()
if vcu.is_blender_28():
search_group = "all_objects"
else:
search_group = "objects"
#
# Meshing Volume Panel
#
box = self.layout.box()
row = box.row(align=True)
row.alert = not sprops.enable_surface_mesh_generation
row.prop(sprops, "meshing_volume_expanded",
icon="TRIA_DOWN" if sprops.meshing_volume_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("meshing_volume", default_closed=True)
row = header.row(align=True)
row.alert = not is_surface_mesh_generation_enabled
row.label(text="Meshing Volume:")
if not sprops.meshing_volume_expanded:
info_text = ""
if sprops.meshing_volume_mode == "MESHING_VOLUME_MODE_DOMAIN":
info_text = "Domain Volume"
elif sprops.meshing_volume_mode == "MESHING_VOLUME_MODE_OBJECT":
info_text = "Object Volume"
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text=info_text)
if sprops.meshing_volume_expanded:
row = box.row(align=True)
if body:
row = body.row(align=True)
row.prop(sprops, "meshing_volume_mode", expand=True)
column = box.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
column_right.enabled = sprops.meshing_volume_mode == "MESHING_VOLUME_MODE_OBJECT"
column_right.prop_search(sprops, "meshing_volume_object", object_collection, search_group, text="Object")
column_right.prop_search(sprops, "meshing_volume_object", vcu.get_scene_collection(), "all_objects", text="Object")
column_right.prop(sprops, "export_animated_meshing_volume_object")
box = self.layout.box()
row = box.row(align=True)
row.alert = not sprops.enable_surface_mesh_generation
row.prop(sprops, "meshing_against_boundary_expanded",
icon="TRIA_DOWN" if sprops.meshing_against_boundary_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Meshing Against Boundary:")
if not sprops.meshing_against_boundary_expanded:
else:
info_text = ""
if sprops.meshing_volume_mode == "MESHING_VOLUME_MODE_DOMAIN":
info_text = "Domain Volume"
elif sprops.meshing_volume_mode == "MESHING_VOLUME_MODE_OBJECT":
info_text = "Object Volume"
if sprops.meshing_volume_object is not None:
info_text += ": <" + sprops.meshing_volume_object.name + ">"
else:
info_text += ": None"
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(sprops, "remove_mesh_near_domain", text="Remove")
row.label(text=info_text)
if sprops.meshing_against_boundary_expanded:
column = box.column(align=True)
#
# Meshing Volume Panel
#
box = self.layout.box()
header, body = box.panel("meshing_against_boundary", default_closed=True)
row = header.row(align=True)
row.alert = not is_surface_mesh_generation_enabled
row.label(text="Meshing Against Boundary:")
if body:
column = body.column(align=True)
column.prop(sprops, "remove_mesh_near_domain")
column = box.column(align=True)
column = body.column(align=True)
column.enabled = sprops.remove_mesh_near_domain
row = column.row(align=True)
row.prop(sprops, "remove_mesh_near_domain_sides", index=0, text="X ")
@@ -344,44 +296,31 @@ class FLIPFLUID_PT_DomainTypeFluidSurfacePanel(bpy.types.Panel):
row.prop(sprops, "remove_mesh_near_domain_sides", index=4, text="Z ")
row.prop(sprops, "remove_mesh_near_domain_sides", index=5, text="Z+")
column.prop(sprops, "remove_mesh_near_domain_distance")
else:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(sprops, "remove_mesh_near_domain", text="Remove")
#
# Meshing Against Obstacle Panel
#
box = self.layout.box()
row = box.row(align=True)
row.alert = not sprops.enable_surface_mesh_generation
row.prop(sprops, "meshing_against_obstacles_expanded",
icon="TRIA_DOWN" if sprops.meshing_against_obstacles_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Meshing Against Obstacles:")
header, body = box.panel("meshing_against_obstacles", default_closed=True)
if not sprops.meshing_against_obstacles_expanded:
row = header.row(align=True)
row.alert = not is_surface_mesh_generation_enabled
row.label(text="Meshing Against Obstacles:")
if body:
column = body.column(align=True)
column.prop(sprops, "enable_meshing_offset")
row = body.row(align=True)
row.enabled = sprops.enable_meshing_offset
row.prop(sprops, "obstacle_meshing_mode", expand=True)
else:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(sprops, "enable_meshing_offset", text="Enable ")
if sprops.meshing_against_obstacles_expanded:
column = box.column(align=True)
column.prop(sprops, "enable_meshing_offset")
row = box.row(align=True)
row.enabled = sprops.enable_meshing_offset
row.prop(sprops, "obstacle_meshing_mode", expand=True)
# Removed surface smoothing options. These are better set
# using a Blender smooth modifier.
"""
box = self.layout.box()
box.label(text="Smoothing:")
row = box.row(align=True)
row.prop(sprops, "smoothing_value")
row.prop(sprops, "smoothing_iterations")
"""
# Motion Blur is no longer supported
#column = self.layout.column(align=True)
#column.separator()
#column.prop(sprops, "generate_motion_blur_data")
_draw_fluid_surface_display_settings(self, context)
_draw_geometry_attributes_menu(self, context)
@@ -33,55 +33,22 @@ def _draw_geometry_attributes_menu(self, context):
wprops = dprops.whitewater
prefs = vcu.get_addon_preferences()
#
# Whitewater Attributes Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(wprops, "geometry_attributes_expanded",
icon="TRIA_DOWN" if wprops.geometry_attributes_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Whitewater Attributes:")
header, body = box.panel("whitewater_geometry_attributes", default_closed=True)
if wprops.geometry_attributes_expanded:
if not prefs.is_extra_features_enabled():
warn_box = box.box()
warn_column = warn_box.column(align=True)
warn_column.enabled = True
warn_column.label(text=" This feature is affected by a current bug in Blender.", icon='ERROR')
warn_column.label(text=" The Extra Features option must be enabled in preferences")
warn_column.label(text=" to use this feature.")
warn_column.separator()
warn_column.prop(prefs, "enable_extra_features", text="Enable Extra Features in Preferences")
warn_column.separator()
warn_column.operator(
"wm.url_open",
text="Important Info and Limitations",
icon="WORLD"
).url = "https://github.com/rlguy/Blender-FLIP-Fluids/wiki/Preferences-Menu-Settings#developer-tools"
return
column = box.column(align=True)
if not vcu.is_blender_31():
column.enabled = False
column.label(text="Geometry attribute features for whitewater are only available in", icon='ERROR')
column.label(text="Blender 3.1 or later", icon='ERROR')
return
column = box.column(align=True)
row = header.row(align=True)
row.label(text="Whitewater Attribute:")
if body:
column = body.column(align=True)
column.prop(wprops, "enable_velocity_vector_attribute")
column.prop(wprops, "enable_id_attribute")
column.prop(wprops, "enable_lifetime_attribute")
column.separator()
column.operator("flip_fluid_operators.helper_initialize_motion_blur")
else:
if not vcu.is_blender_31():
row = row.row(align=True)
row.enabled = False
row.alignment = 'RIGHT'
row.label(text="(Blender 3.1 or later required)")
return
if not prefs.is_extra_features_enabled():
return
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(wprops, "enable_velocity_vector_attribute", text="Velocity")
@@ -118,29 +85,17 @@ class FLIPFLUID_PT_DomainTypeWhitewaterPanel(bpy.types.Panel):
column.prop(wprops, "enable_whitewater_simulation")
column.separator()
#
# Settings View Mode Panel
#
box = self.layout.box()
box.enabled = is_whitewater_enabled
header, body = box.panel("whitewater_settings_view_mode", default_closed=True)
column = box.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_right = split.column(align=True)
row = column_left.row(align=True)
row.prop(wprops, "settings_view_mode_expanded",
icon="TRIA_DOWN" if wprops.settings_view_mode_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row = header.row(align=True)
row.label(text="Settings View Mode:")
if not wprops.settings_view_mode_expanded:
row = column_right.row(align=True)
row.alignment = 'RIGHT'
row.prop(wprops, "whitewater_ui_mode", expand=True)
if wprops.settings_view_mode_expanded:
column = box.column(align=True)
if body:
column = body.column(align=True)
row = column.row()
row.prop(wprops, "whitewater_ui_mode", expand=True)
@@ -149,18 +104,30 @@ class FLIPFLUID_PT_DomainTypeWhitewaterPanel(bpy.types.Panel):
column_right = split.column()
column_right.enabled = show_advanced_whitewater
column_right.prop(wprops, "highlight_advanced_settings")
else:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.prop(wprops, "whitewater_ui_mode", expand=True)
#
# Whitewater Particle Types Panel
#
box = self.layout.box()
box.enabled = is_whitewater_enabled
row = box.row(align=True)
row.prop(wprops, "whitewater_simulation_particles_expanded",
icon="TRIA_DOWN" if wprops.whitewater_simulation_particles_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Whitewater Particles:")
header, body = box.panel("whitewater_simulation_particles", default_closed=True)
if not wprops.whitewater_simulation_particles_expanded:
row = header.row(align=True)
row.label(text="Whitewater Particle Types:")
if body:
column = body.column(align=True)
column.enabled = is_whitewater_enabled
row = column.row()
row.prop(wprops, "enable_foam")
row.prop(wprops, "enable_bubbles")
row.prop(wprops, "enable_spray")
row.prop(wprops, "enable_dust")
else:
info_text = ""
enabled_particles = []
if wprops.enable_foam:
@@ -183,48 +150,36 @@ class FLIPFLUID_PT_DomainTypeWhitewaterPanel(bpy.types.Panel):
row.alignment = 'RIGHT'
row.label(text=info_text)
if wprops.whitewater_simulation_particles_expanded:
column = box.column(align=True)
column.enabled = is_whitewater_enabled
row = column.row()
row.prop(wprops, "enable_foam")
row.prop(wprops, "enable_bubbles")
row.prop(wprops, "enable_spray")
row.prop(wprops, "enable_dust")
#
# Emitter Settings Panel
#
box = self.layout.box()
box.enabled = is_whitewater_enabled
row = box.row(align=True)
row.prop(wprops, "emitter_settings_expanded",
icon="TRIA_DOWN" if wprops.emitter_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("whitewater_emitter_settings", default_closed=False)
row = header.row(align=True)
row.label(text="Emitter Settings:")
if wprops.emitter_settings_expanded:
column = box.column(align=True)
if body:
column = body.column(align=True)
column.prop(wprops, "enable_whitewater_emission")
if show_advanced_whitewater:
column = box.column(align=True)
column = body.column(align=True)
column.alert = highlight_advanced
column.prop(wprops, "whitewater_emitter_generation_rate")
column = box.column(align=True)
column = body.column(align=True)
column.prop(wprops, "wavecrest_emission_rate")
column.prop(wprops, "turbulence_emission_rate")
column = column.column(align=True)
column.enabled = wprops.enable_dust
column.prop(wprops, "dust_emission_rate")
column = box.column(align=True)
column = body.column(align=True)
column.prop(wprops, "spray_emission_speed", slider=True)
if show_advanced_whitewater:
column = box.column(align=True)
column = body.column(align=True)
row = column.row(align=True)
row.prop(wprops.min_max_whitewater_energy_speed, "value_min")
row.prop(wprops.min_max_whitewater_energy_speed, "value_max")
@@ -239,35 +194,34 @@ class FLIPFLUID_PT_DomainTypeWhitewaterPanel(bpy.types.Panel):
row.prop(wprops.min_max_whitewater_turbulence, "value_min")
row.prop(wprops.min_max_whitewater_turbulence, "value_max")
else:
column = box.column()
column = body.column()
row = column.row(align=True)
row.prop(wprops.min_max_whitewater_energy_speed, "value_min")
row.prop(wprops.min_max_whitewater_energy_speed, "value_max")
column = box.column(align=True)
column = body.column(align=True)
column.prop(wprops, "max_whitewater_particles")
if show_advanced_whitewater:
column = box.column(align=True)
column = body.column(align=True)
column.alert = highlight_advanced
column.prop(wprops, "enable_whitewater_emission_near_boundary")
column = box.column(align=True)
column = body.column(align=True)
column.enabled = wprops.enable_dust
column.prop(wprops, "enable_dust_emission_near_boundary", text="Enable dust emission near domain floor")
column.prop(wprops, "enable_dust_emission_near_boundary", text="Enable Dust Emission Near Domain Floor")
#
# Particle Behavior Settings Panel
#
box = self.layout.box()
box.enabled = is_whitewater_enabled
row = box.row(align=True)
row.prop(wprops, "particle_settings_expanded",
icon="TRIA_DOWN" if wprops.particle_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Particle Behavior Settings:")
header, body = box.panel("whitewater_particle_behavior_settings", default_closed=True)
if wprops.particle_settings_expanded:
column = box.column()
row = header.row(align=True)
row.label(text="Particle Behavior Settings:")
if body:
column = body.column()
column.label(text="Foam:")
row = column.row()
@@ -282,22 +236,22 @@ class FLIPFLUID_PT_DomainTypeWhitewaterPanel(bpy.types.Panel):
row.alert = highlight_advanced
row.prop(wprops, "foam_layer_offset", text="Offset", slider=True)
column = box.column(align=True)
column = body.column(align=True)
column.label(text="Bubble:")
column.prop(wprops, "bubble_drag_coefficient", text="Drag Coefficient", slider=True)
column.prop(wprops, "bubble_bouyancy_coefficient", text="Buoyancy Coefficient")
column = box.column(align=True)
column = body.column(align=True)
column.label(text="Spray:")
column.prop(wprops, "spray_drag_coefficient", text="Drag Coefficient", slider=True)
column = box.column(align=True)
column = body.column(align=True)
column.enabled = wprops.enable_dust
column.label(text="Dust:")
column.prop(wprops, "dust_drag_coefficient", text="Drag Coefficient", slider=True)
column.prop(wprops, "dust_bouyancy_coefficient", text="Buoyancy Coefficient")
column = box.column(align=True)
column = body.column(align=True)
split = column.split()
column = split.column(align=True)
column.label(text="Lifespan:")
@@ -314,28 +268,17 @@ class FLIPFLUID_PT_DomainTypeWhitewaterPanel(bpy.types.Panel):
column.enabled = wprops.enable_dust
column.prop(wprops, "dust_lifespan_modifier", text="Dust")
#
# Domain Boundary Collisions Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(wprops, "boundary_behaviour_settings_expanded",
icon="TRIA_DOWN" if wprops.boundary_behaviour_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
box.enabled = is_whitewater_enabled
header, body = box.panel("whitewater_boundary_behaviour_settings", default_closed=True)
row = header.row(align=True)
row.label(text="Domain Boundary Collisions:")
if not wprops.boundary_behaviour_settings_expanded:
info_text = ""
if wprops.whitewater_boundary_collisions_mode == 'BOUNDARY_COLLISIONS_MODE_INHERIT':
info_text = "Inherit"
elif wprops.whitewater_boundary_collisions_mode == 'BOUNDARY_COLLISIONS_MODE_CUSTOM':
info_text = "Custom"
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text=info_text)
if wprops.boundary_behaviour_settings_expanded:
column = box.column()
if body:
column = body.column()
row = column.row(align=True)
row.prop(wprops, "whitewater_boundary_collisions_mode", expand=True)
@@ -417,26 +360,28 @@ class FLIPFLUID_PT_DomainTypeWhitewaterPanel(bpy.types.Panel):
row.alignment = 'LEFT'
row.prop(wprops, "dust_boundary_collisions", index=4, text="Z ")
row.prop(wprops, "dust_boundary_collisions", index=5, text="Z+")
else:
info_text = ""
if wprops.whitewater_boundary_collisions_mode == 'BOUNDARY_COLLISIONS_MODE_INHERIT':
info_text = "Inherit"
elif wprops.whitewater_boundary_collisions_mode == 'BOUNDARY_COLLISIONS_MODE_CUSTOM':
info_text = "Custom"
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text=info_text)
#
# Obstacle Influence Settings Panel
#
box = self.layout.box()
box.enabled = is_whitewater_enabled
row = box.row(align=True)
row.prop(wprops, "obstacle_settings_expanded",
icon="TRIA_DOWN" if wprops.obstacle_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("whitewater_obstacle_influence_settings", default_closed=True)
row = header.row(align=True)
row.label(text="Obstacle Influence Settings:")
if wprops.obstacle_settings_expanded:
column = box.column(align=True)
# The following properties are probably set at reasonable values and
# are not needed by the user
"""
column.prop(wprops, "obstacle_influence_base_level", text="Base Level")
column.prop(wprops, "obstacle_influence_decay_rate", text="Decay Rate")
"""
if body:
column = body.column(align=True)
obstacle_objects = context.scene.flip_fluid.get_obstacle_objects()
indent_str = 5 * " "
@@ -48,31 +48,19 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
wprops = obj.flip_fluid.domain.world
aprops = obj.flip_fluid.domain.advanced
#
# World Scale Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(wprops, "world_scale_settings_expanded",
icon="TRIA_DOWN" if wprops.world_scale_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("world_scale_settings", default_closed=False)
row = header.row(align=True)
row.label(text="World Scale:")
if not wprops.world_scale_settings_expanded:
xdims, ydims, zdims = wprops.get_simulation_dimensions(context)
xdims_str = '{:.2f}'.format(round(xdims, 2)) + " m"
ydims_str = '{:.2f}'.format(round(ydims, 2)) + " m"
zdims_str = '{:.2f}'.format(round(zdims, 2)) + " m"
info_text = xdims_str + " x " + ydims_str + " x " + zdims_str
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text=info_text)
if wprops.world_scale_settings_expanded:
row = box.row(align=True)
if body:
row = body.row(align=True)
row.prop(wprops, "world_scale_mode", expand=True)
column = box.column(align=True)
column = body.column(align=True)
split = column.split(align=True)
column_left = split.column()
column_right = split.column()
@@ -106,19 +94,27 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
column_right.label(text=xdims_str)
column_right.label(text=ydims_str)
column_right.label(text=zdims_str)
else:
xdims, ydims, zdims = wprops.get_simulation_dimensions(context)
xdims_str = '{:.2f}'.format(round(xdims, 2)) + " m"
ydims_str = '{:.2f}'.format(round(ydims, 2)) + " m"
zdims_str = '{:.2f}'.format(round(zdims, 2)) + " m"
info_text = xdims_str + " x " + ydims_str + " x " + zdims_str
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text=info_text)
#
# Gravity and Force Fields Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(wprops, "force_field_settings_expanded",
icon="TRIA_DOWN" if wprops.force_field_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("gravity_and_force_field_settings", default_closed=True)
row = header.row(align=True)
row.label(text="Gravity and Force Fields:")
if wprops.force_field_settings_expanded:
subbox = box.box()
if body:
subbox = body.box()
subbox.label(text="Gravity:")
row = subbox.row(align=True)
row.prop(wprops, "gravity_type", expand=True)
@@ -154,7 +150,7 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
column = subbox.column(align=True)
column.operator("flip_fluid_operators.make_zero_gravity")
subbox = box.box()
subbox = body.box()
subbox.label(text="Force Field Resolution:")
column = subbox.column(align=True)
row = column.row(align=True)
@@ -178,7 +174,7 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
row.label(text="Grid resolution: ")
column_right.label(text=str(field_resolution))
subbox = box.box()
subbox = body.box()
subbox.label(text="Force Field Weights:")
column = subbox.column(align=True)
column.prop(wprops, "force_field_weight_fluid_particles", slider=True)
@@ -187,29 +183,21 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
column.prop(wprops, "force_field_weight_whitewater_spray", slider=True)
column.prop(wprops, "force_field_weight_whitewater_dust", slider=True)
box = self.layout.box()
row = box.row(align=True)
row.prop(wprops, "viscosity_settings_expanded",
icon="TRIA_DOWN" if wprops.viscosity_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
if not wprops.viscosity_settings_expanded:
row.prop(wprops, "enable_viscosity", text="")
row.label(text="Viscosity:")
#
# Viscosity Panel
#
is_variable_viscosity_enabled = attrprops.enable_viscosity_attribute
if not wprops.viscosity_settings_expanded:
if not is_variable_viscosity_enabled:
total_viscosity = wprops.viscosity * (10**(-wprops.viscosity_exponent))
total_viscosity_str = format_number_precision(self, total_viscosity)
row = row.row(align=True)
row.alignment = 'RIGHT'
row.enabled = wprops.enable_viscosity
row.label(text=total_viscosity_str)
if wprops.viscosity_settings_expanded:
column = box.column(align=True)
box = self.layout.box()
header, body = box.panel("viscosity_settings", default_closed=True)
row = header.row(align=True)
if not body:
row.prop(wprops, "enable_viscosity", text="")
row.label(text="Viscosity:")
if body:
column = body.column(align=True)
row = column.row(align=True)
row.prop(wprops, "enable_viscosity")
@@ -218,7 +206,7 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
row.enabled = wprops.enable_viscosity
row.prop(attrprops, "enable_viscosity_attribute", text="Variable Viscosity")
column = box.column(align=True)
column = body.column(align=True)
column.enabled = wprops.enable_viscosity
if is_variable_viscosity_enabled:
@@ -236,29 +224,27 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
total_viscosity = wprops.viscosity * (10**(-wprops.viscosity_exponent))
total_viscosity_str = "Total viscosity = " + format_number_precision(self, total_viscosity)
column.label(text=total_viscosity_str)
else:
if not is_variable_viscosity_enabled:
total_viscosity = wprops.viscosity * (10**(-wprops.viscosity_exponent))
total_viscosity_str = format_number_precision(self, total_viscosity)
row = row.row(align=True)
row.alignment = 'RIGHT'
row.enabled = wprops.enable_viscosity
row.label(text=total_viscosity_str)
#
# Surface Tension Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(wprops, "surface_tension_settings_expanded",
icon="TRIA_DOWN" if wprops.surface_tension_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
if not wprops.surface_tension_settings_expanded:
row.prop(wprops, "enable_surface_tension", text="")
header, body = box.panel("surface_tension_settings", default_closed=True)
row = header.row(align=True)
if not body:
row.prop(wprops, "enable_surface_tension", text="")
row.label(text="Surface Tension:")
if not wprops.surface_tension_settings_expanded:
total_surface_tension = wprops.get_surface_tension_value()
surface_tension_str = format_number_precision(self, total_surface_tension)
row = row.row(align=True)
row.alignment = 'RIGHT'
row.enabled = wprops.enable_surface_tension
row.alert = wprops.enable_surface_tension and wprops.minimum_surface_tension_substeps > aprops.min_max_time_steps_per_frame.value_max
row.label(text=surface_tension_str)
if wprops.surface_tension_settings_expanded:
column = box.column(align=True)
if body:
column = body.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_left.prop(wprops, "enable_surface_tension")
@@ -292,21 +278,27 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
row.alert = True
row.prop(wprops, "surface_tension_substeps_exceeded_tooltip", icon="QUESTION", emboss=False, text="")
row.label(text=" Warning: Too Many Substeps")
else:
total_surface_tension = wprops.get_surface_tension_value()
surface_tension_str = format_number_precision(self, total_surface_tension)
row = row.row(align=True)
row.alignment = 'RIGHT'
row.enabled = wprops.enable_surface_tension
row.alert = wprops.enable_surface_tension and wprops.minimum_surface_tension_substeps > aprops.min_max_time_steps_per_frame.value_max
row.label(text=surface_tension_str)
#
# Sheeting Effects Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(wprops, "sheeting_settings_expanded",
icon="TRIA_DOWN" if wprops.sheeting_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
if not wprops.sheeting_settings_expanded:
row.prop(wprops, "enable_sheet_seeding", text="")
row.label(text="Sheeting Effects:")
header, body = box.panel("sheeting_effects_settings", default_closed=True)
if wprops.sheeting_settings_expanded:
box.label(text="Sheeting Effects:")
column = box.column(align=True)
row = header.row(align=True)
if not body:
row.prop(wprops, "enable_sheet_seeding", text="")
row.label(text="Sheeting Effects:")
if body:
column = body.column(align=True)
split = column.split(align=True)
column_left = split.column(align=True)
column_left.prop(wprops, "enable_sheet_seeding")
@@ -328,42 +320,54 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
pgroup = ob.flip_fluid.get_property_group()
column_left.label(text=ob.name, icon="OBJECT_DATA")
column_right.prop(pgroup, "sheeting_strength", text="Strength Scale")
#
# Variable Density Panel
#
box = self.layout.box()
row = box.row(align=True)
row.prop(wprops, "friction_settings_expanded",
icon="TRIA_DOWN" if wprops.friction_settings_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
header, body = box.panel("variable_density_settings", default_closed=True)
row = header.row(align=True)
if not body:
row.prop(wprops, "enable_density_attribute", text="")
row.label(text="Variable Density:")
if body:
column = body.column(align=True)
column.prop(wprops, "enable_density_attribute")
column = body.column(align=True)
column.enabled = wprops.enable_density_attribute
column.label(text="Variable density values can be set in the", icon='INFO')
column.label(text="Fluid or Inflow physics properties menu", icon='INFO')
#
# Friction Panel
#
box = self.layout.box()
header, body = box.panel("friction_settings", default_closed=True)
row = header.row(align=True)
row.label(text="Friction:")
if not wprops.friction_settings_expanded:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text="Boundary Friction ")
row.prop(wprops, "boundary_friction", text="")
if wprops.friction_settings_expanded:
column = box.column()
if body:
column = body.column()
split = column.split(align=True)
column_left = split.column()
column_left.label(text="Boundary Friction:")
column_right = split.column()
column_right.prop(wprops, "boundary_friction", text="")
row = box.row(align=True)
row.prop(wprops, "obstacle_friction_expanded",
icon="TRIA_DOWN" if wprops.obstacle_friction_expanded else "TRIA_RIGHT",
icon_only=True,
emboss=False
)
row.label(text="Obstacle Friction:")
#
# Obstacle Friction Panel
#
box = body.box()
header_obstacle_friction, body_obstacle_friction = box.panel("obstacle_friction_settings", default_closed=True)
if wprops.obstacle_friction_expanded:
row_obstacle_friction = header_obstacle_friction.row(align=True)
row_obstacle_friction.label(text="Obstacle Friction:")
if body_obstacle_friction:
obstacle_objects = context.scene.flip_fluid.get_obstacle_objects()
column = box.column(align=True)
column = body_obstacle_friction.column(align=True)
indent_str = 5 * " "
if len(obstacle_objects) == 0:
column.label(text=indent_str + "No obstacle objects found...")
@@ -375,6 +379,11 @@ class FLIPFLUID_PT_DomainTypeFluidWorldPanel(bpy.types.Panel):
pgroup = ob.flip_fluid.get_property_group()
column_left.label(text=ob.name, icon="OBJECT_DATA")
column_right.prop(pgroup, "friction")
else:
row = row.row(align=True)
row.alignment = 'RIGHT'
row.label(text="Boundary Friction ")
row.prop(wprops, "boundary_friction", text="")
def register():
@@ -104,10 +104,7 @@ class FLIPFLUID_PT_FluidTypePanel(bpy.types.Panel):
column_left.prop(fluid_props, "initial_speed")
target_collection = vcu.get_scene_collection()
if vcu.is_blender_28():
search_group = "all_objects"
else:
search_group = "objects"
search_group = "all_objects"
column_right = split.column(align=True)
column_right.label(text="Target Object:")
@@ -137,80 +134,91 @@ class FLIPFLUID_PT_FluidTypePanel(bpy.types.Panel):
box = self.layout.box()
box.label(text="Geometry Attributes:")
column = box.column(align=True)
if vcu.is_blender_293():
is_color_attribute_enabled = dprops is not None and (dprops.surface.enable_color_attribute or
dprops.particles.enable_fluid_particle_color_attribute)
show_color = dprops is not None and is_color_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_color
column_left.prop(fluid_props, "color")
column_right = split.column(align=True)
column_right.label(text="")
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_color:
row.operator("flip_fluid_operators.enable_color_attribute_tooltip",
text="Enable Color Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
is_color_attribute_enabled = dprops is not None and (dprops.surface.enable_color_attribute or
dprops.particles.enable_fluid_particle_color_attribute)
show_color = dprops is not None and is_color_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_color
column_left.prop(fluid_props, "color")
column_right = split.column(align=True)
column_right.label(text="")
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_color:
row.operator("flip_fluid_operators.enable_color_attribute_tooltip",
text="Enable Color Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
show_viscosity = dprops is not None and dprops.surface.enable_viscosity_attribute
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_viscosity
column_left.prop(fluid_props, "viscosity")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_viscosity:
row.operator("flip_fluid_operators.enable_viscosity_attribute_tooltip",
text="Enable Viscosity Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
show_viscosity = dprops is not None and dprops.world.enable_viscosity and dprops.surface.enable_viscosity_attribute
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_viscosity
column_left.prop(fluid_props, "viscosity")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_viscosity:
row.operator("flip_fluid_operators.enable_viscosity_attribute_tooltip",
text="Enable Viscosity Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
is_lifetime_attribute_enabled = dprops is not None and (dprops.surface.enable_lifetime_attribute or
dprops.particles.enable_fluid_particle_lifetime_attribute)
show_lifetime = dprops is not None and is_lifetime_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_lifetime
column_left.prop(fluid_props, "lifetime")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_lifetime:
row.operator("flip_fluid_operators.enable_lifetime_attribute_tooltip",
text="Enable Lifetime Attribute", icon="PLUS", emboss=False)
elif dprops is not None:
row.alignment = 'EXPAND'
row.prop(fluid_props, "lifetime_variance", text="Variance")
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
show_density = dprops is not None and dprops.world.enable_density_attribute
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_density
column_left.prop(fluid_props, "density")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_density:
row.operator("flip_fluid_operators.enable_density_attribute_tooltip",
text="Enable Density Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
is_source_id_attribute_enabled = dprops is not None and (dprops.surface.enable_source_id_attribute or
dprops.particles.enable_fluid_particle_source_id_attribute)
show_source_id = dprops is not None and is_source_id_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_source_id
column_left.prop(fluid_props, "source_id")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_source_id:
row.operator("flip_fluid_operators.enable_source_id_attribute_tooltip",
text="Enable Source ID Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
else:
column.enabled = False
column.label(text="Geometry attribute features are only available in", icon='ERROR')
column.label(text="Blender 2.93 or later", icon='ERROR')
is_lifetime_attribute_enabled = dprops is not None and (dprops.surface.enable_lifetime_attribute or
dprops.particles.enable_fluid_particle_lifetime_attribute)
show_lifetime = dprops is not None and is_lifetime_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_lifetime
column_left.prop(fluid_props, "lifetime")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_lifetime:
row.operator("flip_fluid_operators.enable_lifetime_attribute_tooltip",
text="Enable Lifetime Attribute", icon="PLUS", emboss=False)
elif dprops is not None:
row.alignment = 'EXPAND'
row.prop(fluid_props, "lifetime_variance", text="Variance")
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
is_source_id_attribute_enabled = dprops is not None and (dprops.surface.enable_source_id_attribute or
dprops.particles.enable_fluid_particle_source_id_attribute)
show_source_id = dprops is not None and is_source_id_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_source_id
column_left.prop(fluid_props, "source_id")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_source_id:
row.operator("flip_fluid_operators.enable_source_id_attribute_tooltip",
text="Enable Source ID Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
box = self.layout.box()
box.label(text="Mesh Data Export:")
@@ -184,7 +184,7 @@ class FLIPFLUID_PT_ForceFieldTypePanel(bpy.types.Panel):
self.layout.separator()
box = self.layout.box()
box.label(text="Antigravity")
box.label(text="Antigravity:")
column = box.column(align=True)
if force_field_props.force_field_type == 'FORCE_FIELD_TYPE_POINT':
@@ -199,6 +199,18 @@ class FLIPFLUID_PT_ForceFieldTypePanel(bpy.types.Panel):
elif force_field_props.force_field_type == 'FORCE_FIELD_TYPE_CURVE':
column.prop(force_field_props, "gravity_scale_curve", slider=True)
column.prop(force_field_props, "gravity_scale_width_curve", text="Width", slider=True)
dprops = context.scene.flip_fluid.get_domain_properties()
if dprops is not None:
box = self.layout.box()
box.label(text="Global Force Field Weights:")
column = box.column(align=True)
column.prop(dprops.world, "force_field_weight_fluid_particles", slider=True)
column.prop(dprops.world, "force_field_weight_whitewater_foam", slider=True)
column.prop(dprops.world, "force_field_weight_whitewater_bubble", slider=True)
column.prop(dprops.world, "force_field_weight_whitewater_spray", slider=True)
column.prop(dprops.world, "force_field_weight_whitewater_dust", slider=True)
box = self.layout.box()
box.label(text="Mesh Data Export:")
File diff suppressed because it is too large Load Diff
@@ -97,10 +97,7 @@ class FLIPFLUID_PT_InflowTypePanel(bpy.types.Panel):
column_left.prop(inflow_props, "inflow_speed")
target_collection = vcu.get_scene_collection()
if vcu.is_blender_28():
search_group = "all_objects"
else:
search_group = "objects"
search_group = "all_objects"
column_right = split.column(align=True)
column_right.label(text="Target Object:")
@@ -132,80 +129,91 @@ class FLIPFLUID_PT_InflowTypePanel(bpy.types.Panel):
box = self.layout.box()
box.label(text="Geometry Attributes:")
column = box.column(align=True)
if vcu.is_blender_293():
is_color_attribute_enabled = dprops is not None and (dprops.surface.enable_color_attribute or
dprops.particles.enable_fluid_particle_color_attribute)
show_color = dprops is not None and is_color_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_color
column_left.prop(inflow_props, "color")
column_right = split.column(align=True)
column_right.label(text="")
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_color:
row.operator("flip_fluid_operators.enable_color_attribute_tooltip",
text="Enable Color Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
is_color_attribute_enabled = dprops is not None and (dprops.surface.enable_color_attribute or
dprops.particles.enable_fluid_particle_color_attribute)
show_color = dprops is not None and is_color_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_color
column_left.prop(inflow_props, "color")
column_right = split.column(align=True)
column_right.label(text="")
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_color:
row.operator("flip_fluid_operators.enable_color_attribute_tooltip",
text="Enable Color Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
show_viscosity = dprops is not None and dprops.surface.enable_viscosity_attribute
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_viscosity
column_left.prop(inflow_props, "viscosity")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_viscosity:
row.operator("flip_fluid_operators.enable_viscosity_attribute_tooltip",
text="Enable Viscosity Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
show_viscosity = dprops is not None and dprops.world.enable_viscosity and dprops.surface.enable_viscosity_attribute
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_viscosity
column_left.prop(inflow_props, "viscosity")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_viscosity:
row.operator("flip_fluid_operators.enable_viscosity_attribute_tooltip",
text="Enable Viscosity Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
is_lifetime_attribute_enabled = dprops is not None and (dprops.surface.enable_lifetime_attribute or
dprops.particles.enable_fluid_particle_lifetime_attribute)
show_lifetime = dprops is not None and is_lifetime_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_lifetime
column_left.prop(inflow_props, "lifetime")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_lifetime:
row.operator("flip_fluid_operators.enable_lifetime_attribute_tooltip",
text="Enable Lifetime Attribute", icon="PLUS", emboss=False)
elif dprops is not None:
row.alignment = 'EXPAND'
row.prop(inflow_props, "lifetime_variance", text="Variance")
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
show_density = dprops is not None and dprops.world.enable_density_attribute
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_density
column_left.prop(inflow_props, "density")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_density:
row.operator("flip_fluid_operators.enable_density_attribute_tooltip",
text="Enable Density Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
is_source_id_attribute_enabled = dprops is not None and (dprops.surface.enable_source_id_attribute or
dprops.particles.enable_fluid_particle_source_id_attribute)
show_source_id = dprops is not None and is_source_id_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_source_id
column_left.prop(inflow_props, "source_id")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_source_id:
row.operator("flip_fluid_operators.enable_source_id_attribute_tooltip",
text="Enable Source ID Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
else:
column.enabled = False
column.label(text="Geometry attribute features are only available in", icon='ERROR')
column.label(text="Blender 2.93 or later", icon='ERROR')
is_lifetime_attribute_enabled = dprops is not None and (dprops.surface.enable_lifetime_attribute or
dprops.particles.enable_fluid_particle_lifetime_attribute)
show_lifetime = dprops is not None and is_lifetime_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_lifetime
column_left.prop(inflow_props, "lifetime")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_lifetime:
row.operator("flip_fluid_operators.enable_lifetime_attribute_tooltip",
text="Enable Lifetime Attribute", icon="PLUS", emboss=False)
elif dprops is not None:
row.alignment = 'EXPAND'
row.prop(inflow_props, "lifetime_variance", text="Variance")
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
is_source_id_attribute_enabled = dprops is not None and (dprops.surface.enable_source_id_attribute or
dprops.particles.enable_fluid_particle_source_id_attribute)
show_source_id = dprops is not None and is_source_id_attribute_enabled
split = column.split(align=True)
column_left = split.column(align=True)
column_left.enabled = show_source_id
column_left.prop(inflow_props, "source_id")
column_right = split.column(align=True)
row = column_right.row(align=True)
row.alignment = 'LEFT'
if dprops is not None and not show_source_id:
row.operator("flip_fluid_operators.enable_source_id_attribute_tooltip",
text="Enable Source ID Attribute", icon="PLUS", emboss=False)
if dprops is None:
row.label(text="Domain required for this option")
column.separator()
box = self.layout.box()
box.label(text="Mesh Data Export:")