Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastián Barschkis <sebbas@sebbas.org>2019-12-16 17:42:07 +0300
committerSebastián Barschkis <sebbas@sebbas.org>2019-12-16 18:30:10 +0300
commit4235fe37d6aaf9963ddda23ccaec26a483b6a580 (patch)
tree43461c553660a9ed476883d4caa0f347ca79a922 /release/scripts/startup/bl_ui
parent2aa4301c88aac15d81e08b1f5ac24da2a9279243 (diff)
Mantaflow [Part 3]: Customized UI for Manta fluids
With Mantaflow the current smoke modifier UI will accommodate both smoke and liquids. In addition, there is now an option for Mantaflow liquids in the quick effects section ("Quick Liquid"). Reviewed By: sergey Maniphest Tasks: T59995 Differential Revision: https://developer.blender.org/D3852
Diffstat (limited to 'release/scripts/startup/bl_ui')
-rw-r--r--release/scripts/startup/bl_ui/__init__.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py21
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py1196
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py692
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py1
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py2
8 files changed, 1017 insertions, 904 deletions
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 5daacbb2e44..c2bcb7d5ea5 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -54,10 +54,9 @@ _modules = [
"properties_physics_common",
"properties_physics_dynamicpaint",
"properties_physics_field",
- "properties_physics_fluid",
"properties_physics_rigidbody",
"properties_physics_rigidbody_constraint",
- "properties_physics_smoke",
+ "properties_physics_fluid",
"properties_physics_softbody",
"properties_render",
"properties_output",
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 4fe6a5ac19b..d4b2c39bd5e 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -945,7 +945,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "angle")
col.prop(md, "limits", slider=True)
- def SMOKE(self, layout, _ob, _md):
+ def FLUID(self, layout, _ob, _md):
layout.label(text="Settings are inside the Physics tab")
def SMOOTH(self, layout, ob, md):
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index fa4ec391405..21abf8bb34c 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -55,7 +55,7 @@ def particle_panel_poll(cls, context):
if not settings:
return False
- return settings.is_fluid is False and (engine in cls.COMPAT_ENGINES)
+ return (settings.is_fluid is False) and (engine in cls.COMPAT_ENGINES)
def particle_get_settings(context):
@@ -207,7 +207,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
col = layout.column()
- if part.is_fluid is False:
+ if (part.is_fluid is False):
row = col.row()
row.enabled = particle_panel_enabled(context, psys)
row.template_ID(psys, "settings", new="particle.new")
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index b69f2233035..5397020a521 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -99,8 +99,7 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
physics_add(col, context.soft_body, "Soft Body", 'SOFT_BODY', 'MOD_SOFT', True)
if obj.type == 'MESH':
- physics_add(col, context.fluid, "Fluid", 'FLUID_SIMULATION', 'MOD_FLUIDSIM', True)
- physics_add(col, context.smoke, "Smoke", 'SMOKE', 'MOD_SMOKE', True)
+ physics_add(col, context.fluid, "Fluid", 'FLUID', 'MOD_FLUIDSIM', True)
physics_add_special(
col, obj.rigid_body, "Rigid Body",
@@ -118,7 +117,7 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
)
-# cache-type can be 'PSYS' 'HAIR' 'SMOKE' etc.
+# cache-type can be 'PSYS' 'HAIR' 'FLUID' etc.
def point_cache_ui(self, cache, enabled, cachetype):
layout = self.layout
@@ -141,10 +140,10 @@ def point_cache_ui(self, cache, enabled, cachetype):
col.operator("ptcache.add", icon='ADD', text="")
col.operator("ptcache.remove", icon='REMOVE', text="")
- if cachetype in {'PSYS', 'HAIR', 'SMOKE'}:
+ if cachetype in {'PSYS', 'HAIR', 'FLUID'}:
col = layout.column()
- if cachetype == 'SMOKE':
+ if cachetype == 'FLUID':
col.prop(cache, "use_library_path", text="Use Library Path")
col.prop(cache, "use_external")
@@ -160,14 +159,14 @@ def point_cache_ui(self, cache, enabled, cachetype):
col.alignment = 'RIGHT'
col.label(text=cache_info)
else:
- if cachetype in {'SMOKE', 'DYNAMIC_PAINT'}:
+ if cachetype in {'FLUID', 'DYNAMIC_PAINT'}:
if not is_saved:
col = layout.column(align=True)
col.alignment = 'RIGHT'
col.label(text="Cache is disabled until the file is saved")
layout.enabled = False
- if not cache.use_external or cachetype == 'SMOKE':
+ if not cache.use_external or cachetype == 'FLUID':
col = layout.column(align=True)
if cachetype not in {'PSYS', 'DYNAMIC_PAINT'}:
@@ -175,18 +174,18 @@ def point_cache_ui(self, cache, enabled, cachetype):
col.prop(cache, "frame_start", text="Simulation Start")
col.prop(cache, "frame_end")
- if cachetype not in {'SMOKE', 'CLOTH', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
+ if cachetype not in {'FLUID', 'CLOTH', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
col.prop(cache, "frame_step")
cache_info = cache.info
- if cachetype != 'SMOKE' and cache_info: # avoid empty space.
+ if cachetype != 'FLUID' and cache_info: # avoid empty space.
col = layout.column(align=True)
col.alignment = 'RIGHT'
col.label(text=cache_info)
can_bake = True
- if cachetype not in {'SMOKE', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
+ if cachetype not in {'FLUID', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
if not is_saved:
col = layout.column(align=True)
col.alignment = 'RIGHT'
@@ -269,7 +268,7 @@ def effector_weights_ui(self, weights, weight_type):
col.prop(weights, "curve_guide", slider=True)
col.prop(weights, "texture", slider=True)
- if weight_type != 'SMOKE':
+ if weight_type != 'FLUID':
col.prop(weights, "smokeflow", slider=True)
col = flow.column()
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index b9e690629d1..f182a025f61 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -21,16 +21,17 @@
import bpy
from bpy.types import (
Panel,
+ Menu,
+)
+from .properties_physics_common import (
+ effector_weights_ui,
)
-from bpy.app.translations import pgettext_iface as iface_
-from bl_ui.utils import PresetPanel
-
-class FLUID_PT_presets(PresetPanel, Panel):
+class FLUID_MT_presets(Menu):
bl_label = "Fluid Presets"
preset_subdir = "fluid"
preset_operator = "script.execute_preset"
- preset_add_operator = "fluid.preset_add"
+ draw = Menu.draw_preset
class PhysicButtonsPanel:
@@ -44,23 +45,46 @@ class PhysicButtonsPanel:
if not ((ob and ob.type == 'MESH') and (context.fluid)):
return False
- return (bpy.app.build_options.mod_fluid)
+ md = context.fluid
+ return md and (context.fluid.fluid_type != 'NONE')
@staticmethod
- def poll_fluid_settings(context):
- if not (PhysicButtonsPanel.poll_fluid(context)):
+ def poll_fluid_domain(context):
+ if not PhysicButtonsPanel.poll_fluid(context):
return False
md = context.fluid
- return md and md.settings and (md.settings.type != 'NONE')
+ return md and (md.fluid_type == 'DOMAIN')
@staticmethod
- def poll_fluid_domain(context):
+ def poll_gas_domain(context):
+ if not PhysicButtonsPanel.poll_fluid(context):
+ return False
+
+ md = context.fluid
+ if md and (md.fluid_type == 'DOMAIN'):
+ domain = md.domain_settings
+ return domain.domain_type in {'GAS'}
+ return False
+
+ @staticmethod
+ def poll_liquid_domain(context):
+ if not PhysicButtonsPanel.poll_fluid(context):
+ return False
+
+ md = context.fluid
+ if md and (md.fluid_type == 'DOMAIN'):
+ domain = md.domain_settings
+ return domain.domain_type in {'LIQUID'}
+ return False
+
+ @staticmethod
+ def poll_fluid_flow(context):
if not PhysicButtonsPanel.poll_fluid(context):
return False
md = context.fluid
- return md and md.settings and (md.settings.type == 'DOMAIN')
+ return md and (md.fluid_type == 'FLOW')
class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
@@ -70,325 +94,899 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
@classmethod
def poll(cls, context):
ob = context.object
- return (ob and ob.type == 'MESH') and context.engine in cls.COMPAT_ENGINES and (context.fluid)
+ return (ob and ob.type == 'MESH') and (context.engine in cls.COMPAT_ENGINES) and (context.fluid)
def draw(self, context):
layout = self.layout
layout.use_property_split = True
- if not bpy.app.build_options.mod_fluid:
- col = layout.column()
+ if not bpy.app.build_options.fluid:
+ col = layout.column(align=True)
col.alignment = 'RIGHT'
- col.label(text="Built without fluids")
+ col.label(text="Built without Fluid modifier")
return
-
md = context.fluid
- fluid = md.settings
- col = layout.column()
- col.prop(fluid, "type")
+ layout.prop(md, "fluid_type")
-class PHYSICS_PT_fluid_flow(PhysicButtonsPanel, Panel):
- bl_label = "Flow"
- bl_parent_id = "PHYSICS_PT_fluid"
+class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
+ bl_label = "Settings"
+ bl_parent_id = 'PHYSICS_PT_fluid'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
- md = context.fluid
- fluid = md.settings
-
- if not PhysicButtonsPanel.poll_fluid_settings(context):
+ if not PhysicButtonsPanel.poll_fluid(context):
return False
- return fluid.type in {'INFLOW', 'OUTFLOW', 'CONTROL'} and (context.engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- md = context.fluid
- fluid = md.settings
- self.layout.prop(fluid, "use", text="")
+ return (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
layout.use_property_split = True
md = context.fluid
- fluid = md.settings
+ ob = context.object
+ scene = context.scene
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
+ if md.fluid_type == 'DOMAIN':
+ domain = md.domain_settings
- flow.active = fluid.use
+ # Deactivate UI if guiding is enabled but not baked yet
+ layout.active = not (domain.use_guiding and not domain.cache_baked_guiding and (domain.guiding_source == "EFFECTOR" or (domain.guiding_source == "DOMAIN" and not domain.guiding_parent)))
- if fluid.type == 'INFLOW':
- col = flow.column()
- col.prop(fluid, "volume_initialization", text="Volume Initialization")
- col.prop(fluid, "use_animated_mesh")
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+ baked_data = domain.cache_baked_data
- row = col.row()
- row.active = not fluid.use_animated_mesh
- row.prop(fluid, "use_local_coords")
+ row = layout.row()
+ row.enabled = not baking_any and not baked_data
+ row.prop(domain, "domain_type", expand=False)
- col = flow.column()
- col.prop(fluid, "inflow_velocity", text="Inflow Velocity")
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_data
- elif fluid.type == 'OUTFLOW':
col = flow.column()
- col.prop(fluid, "volume_initialization", text="Volume Initialization")
+ col.prop(domain, "resolution_max", text="Resolution Divisions")
+ col.prop(domain, "time_scale", text="Time Scale")
+ col.prop(domain, "cfl_condition", text="CFL Number")
col = flow.column()
- col.prop(fluid, "use_animated_mesh")
+ col.prop(domain, "use_adaptive_stepping", text="Use Adaptive Stepping")
+ col1 = col.column(align=True)
+ col1.enabled = domain.use_adaptive_stepping
+ col1.prop(domain, "timesteps_maximum", text="Timesteps Maximum")
+ col1.prop(domain, "timesteps_minimum", text="Minimum")
- elif fluid.type == 'CONTROL':
- col = flow.column()
- col.prop(fluid, "quality", slider=True)
- col.prop(fluid, "use_reverse_frames")
+ col.separator()
col = flow.column()
- col.prop(fluid, "start_time", text="Time Start")
- col.prop(fluid, "end_time", text="End")
+ if scene.use_gravity:
+ sub = col.column()
+ sub.enabled = False
+ sub.prop(domain, "gravity", text="Using Scene Gravity", icon='SCENE_DATA')
+ else:
+ col.prop(domain, "gravity", text="Gravity")
+ # TODO (sebbas): Clipping var useful for manta openvdb caching?
+ # col.prop(domain, "clipping", text="Empty Space")
+
+ if domain.cache_type == "MODULAR":
+ col.separator()
+ split = layout.split()
- col.separator()
+ bake_incomplete = (domain.cache_frame_pause_data < domain.cache_frame_end)
+ if domain.cache_baked_data and not domain.cache_baking_data and bake_incomplete:
+ col = split.column()
+ col.operator("fluid.bake_data", text="Resume")
+ col = split.column()
+ col.operator("fluid.free_data", text="Free")
+ elif domain.cache_baking_data and not domain.cache_baked_data:
+ split.enabled = False
+ split.operator("fluid.pause_bake", text="Baking Data - ESC to pause")
+ elif not domain.cache_baked_data and not domain.cache_baking_data:
+ split.operator("fluid.bake_data", text="Bake Data")
+ else:
+ split.operator("fluid.free_data", text="Free Data")
+
+ elif md.fluid_type == 'FLOW':
+ flow = md.flow_settings
+
+ row = layout.row()
+ row.prop(flow, "flow_type", expand=False)
+
+ grid = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ col = grid.column()
+ col.prop(flow, "flow_behavior", expand=False)
+ if flow.flow_behavior in {'INFLOW'}:
+ col.prop(flow, "use_inflow", text="Use Inflow")
+
+ col.prop(flow, "subframes", text="Sampling Substeps")
+
+ if not flow.flow_behavior == 'OUTFLOW' and flow.flow_type in {'SMOKE', 'BOTH', 'FIRE'}:
+
+ if flow.flow_type in {'SMOKE', 'BOTH'}:
+ col.prop(flow, "smoke_color", text="Smoke Color")
+
+ col = grid.column(align=True)
+ col.prop(flow, "use_absolute", text="Absolute Density")
+
+ if flow.flow_type in {'SMOKE', 'BOTH'}:
+ col.prop(flow, "temperature", text="Initial Temperature")
+ col.prop(flow, "density", text="Density")
+
+ if flow.flow_type in {'FIRE', 'BOTH'}:
+ col.prop(flow, "fuel_amount", text="Fuel")
+
+ col.separator()
+ col.prop_search(flow, "density_vertex_group", ob, "vertex_groups", text="Vertex Group")
+
+ elif md.fluid_type == 'EFFECTOR':
+ effec = md.effec_settings
+
+ row = layout.row()
+ row.prop(effec, "effec_type")
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
col = flow.column()
- col.prop(fluid, "attraction_strength", text="Attraction Strength")
- col.prop(fluid, "attraction_radius", text="Radius")
- col.separator()
+ col.prop(effec, "use_plane_init", text="Is Planar")
+ col.prop(effec, "surface_distance", text="Surface Thickness")
- col = flow.column(align=True)
- col.prop(fluid, "velocity_strength", text="Velocity Strength")
- col.prop(fluid, "velocity_radius", text="Radius")
+ if effec.effec_type == "GUIDE":
+ col.prop(effec, "velocity_factor", text="Velocity Factor")
+ col = flow.column()
+ col.prop(effec, "guiding_mode", text="Guiding Mode")
-class PHYSICS_PT_fluid_settings(PhysicButtonsPanel, Panel):
- bl_label = "Settings"
- bl_parent_id = "PHYSICS_PT_fluid"
+class PHYSICS_PT_borders(PhysicButtonsPanel, Panel):
+ bl_label = "Border Collisions"
+ bl_parent_id = 'PHYSICS_PT_settings'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
+ if not PhysicButtonsPanel.poll_fluid_domain(context):
+ return False
+
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
md = context.fluid
- fluid = md.settings
+ domain = md.domain_settings
+
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+ baked_data = domain.cache_baked_data
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_data
+
+ col = flow.column()
+ col.prop(domain, "use_collision_border_front", text="Front")
+ col = flow.column()
+ col.prop(domain, "use_collision_border_back", text="Back")
+ col = flow.column()
+ col.prop(domain, "use_collision_border_right", text="Right")
+ col = flow.column()
+ col.prop(domain, "use_collision_border_left", text="Left")
+ col = flow.column()
+ col.prop(domain, "use_collision_border_top", text="Top")
+ col = flow.column()
+ col.prop(domain, "use_collision_border_bottom", text="Bottom")
+
+
+class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
+ bl_label = "Smoke"
+ bl_parent_id = 'PHYSICS_PT_settings'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- if not PhysicButtonsPanel.poll_fluid_settings(context):
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_gas_domain(context):
return False
- return fluid.type in {'DOMAIN', 'FLUID', 'OBSTACLE', 'PARTICLE'} and (context.engine in cls.COMPAT_ENGINES)
+
+ return (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
layout.use_property_split = True
md = context.fluid
- fluid = md.settings
+ domain = md.domain_settings
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+ baked_data = domain.cache_baked_data
- if fluid.type not in {'NONE', 'DOMAIN', 'PARTICLE', 'FLUID', 'OBSTACLE'}:
- flow.active = fluid.use
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_data
- if fluid.type == 'DOMAIN':
- col = flow.column()
+ col = flow.column()
+ col.prop(domain, "alpha")
+ col.prop(domain, "beta", text="Temperature Diff.")
+ col = flow.column()
+ col.prop(domain, "vorticity")
- if bpy.app.build_options.openmp:
- col.prop(fluid, "threads", text="Simulation Threads")
- col.separator()
- col.prop(fluid, "resolution", text="Final Resolution")
- col.prop(fluid, "preview_resolution", text="Preview")
+class PHYSICS_PT_smoke_dissolve(PhysicButtonsPanel, Panel):
+ bl_label = "Dissolve"
+ bl_parent_id = 'PHYSICS_PT_smoke'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- col.separator()
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_gas_domain(context):
+ return False
- col = flow.column()
- col.prop(fluid, "render_display_mode", text="Render Display")
- col.prop(fluid, "viewport_display_mode", text="Viewport")
+ return (context.engine in cls.COMPAT_ENGINES)
- col.separator()
+ def draw_header(self, context):
+ md = context.fluid
+ domain = md.domain_settings
- col = flow.column()
- sub = col.column(align=True)
- sub.prop(fluid, "start_time", text="Time Start")
- sub.prop(fluid, "end_time", text="End")
- col.prop(fluid, "simulation_rate", text="Speed")
+ self.layout.prop(domain, "use_dissolve_smoke", text="")
- col = flow.column()
- col.prop(fluid, "use_speed_vectors")
- col.prop(fluid, "use_reverse_frames")
- col.prop(fluid, "frame_offset", text="Offset")
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
- elif fluid.type == 'FLUID':
- col = flow.column()
- col.prop(fluid, "volume_initialization", text="Volume Initialization")
- col.prop(fluid, "use_animated_mesh")
+ md = context.fluid
+ domain = md.domain_settings
- col = flow.column()
- col.prop(fluid, "initial_velocity", text="Initial Velocity")
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+ baked_data = domain.cache_baked_data
- elif fluid.type == 'OBSTACLE':
- col = flow.column()
- col.prop(fluid, "volume_initialization", text="Volume Initialization")
- col.prop(fluid, "use_animated_mesh")
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_data
- col = flow.column()
- subcol = col.column()
- subcol.enabled = not fluid.use_animated_mesh
- subcol.prop(fluid, "slip_type", text="Slip Type")
+ layout.active = domain.use_dissolve_smoke
- if fluid.slip_type == 'PARTIALSLIP':
- subcol.prop(fluid, "partial_slip_factor", text="Amount", slider=True)
+ col = flow.column()
+ col.prop(domain, "dissolve_speed", text="Time")
- col.prop(fluid, "impact_factor", text="Impact Factor")
+ col = flow.column()
+ col.prop(domain, "use_dissolve_smoke_log", text="Slow")
- elif fluid.type == 'PARTICLE':
- col = flow.column()
- col.prop(fluid, "particle_influence", text="Influence Size")
- col.prop(fluid, "alpha_influence", text="Alpha")
- col = flow.column()
- col.prop(fluid, "use_drops")
- col.prop(fluid, "use_floats")
- col.prop(fluid, "show_tracer")
+class PHYSICS_PT_fire(PhysicButtonsPanel, Panel):
+ bl_label = "Fire"
+ bl_parent_id = 'PHYSICS_PT_settings'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_gas_domain(context):
+ return False
-class PHYSICS_PT_fluid_particle_cache(PhysicButtonsPanel, Panel):
- bl_label = "Cache"
- bl_parent_id = "PHYSICS_PT_fluid"
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ md = context.fluid
+ domain = md.domain_settings
+
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+ baked_data = domain.cache_baked_data
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_data
+
+ col = flow.column()
+ col.prop(domain, "burning_rate", text="Reaction Speed")
+ col = flow.column()
+ col.prop(domain, "flame_smoke", text="Flame Smoke")
+ col = flow.column()
+ col.prop(domain, "flame_vorticity", text="Flame Vorticity")
+ col = flow.column()
+ col.prop(domain, "flame_ignition", text="Temperature Ignition")
+ col = flow.column()
+ col.prop(domain, "flame_max_temp", text="Maximum Temperature")
+ col = flow.column()
+ col.prop(domain, "flame_smoke_color", text="Flame Color")
+
+
+class PHYSICS_PT_liquid(PhysicButtonsPanel, Panel):
+ bl_label = "Liquid"
+ bl_parent_id = 'PHYSICS_PT_settings'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_liquid_domain(context):
+ return False
+
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ md = context.fluid.domain_settings
+ self.layout.prop(md, "use_flip_particles", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ md = context.fluid
+ domain = md.domain_settings
+
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+ baked_data = domain.cache_baked_data
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ col = flow.column()
+ col0 = col.column()
+ col0.enabled = not baking_any and not baked_data
+ col0.prop(domain, "simulation_method", expand=False)
+ col0.prop(domain, "flip_ratio", text="FLIP Ratio")
+ col0.prop(domain, "particle_radius", text="Particle Radius")
+
+ col1 = flow.column(align=True)
+ col1.enabled = not baking_any and not baked_data
+ col1.prop(domain, "particle_maximum", text="Particles Maximum")
+ col1.prop(domain, "particle_minimum", text="Minimum")
+
+ col1 = flow.column()
+ col1.enabled = not baking_any and not baked_data
+ col1.prop(domain, "particle_number", text="Particle Sampling")
+ col1.prop(domain, "particle_band_width", text="Narrow Band Width")
+ col1.prop(domain, "particle_randomness", text="Particle Randomness")
+
+ col2 = flow.column()
+ col2.enabled = not baking_any and not baked_data
+ col2.prop(domain, "use_fractions", text="Fractional Obstacles")
+ col3 = col2.column()
+ col3.enabled = domain.use_fractions and col2.enabled
+ col3.prop(domain, "fractions_threshold", text="Obstacle-Fluid Threshold")
+
+
+class PHYSICS_PT_flow_source(PhysicButtonsPanel, Panel):
+ bl_label = "Flow Source"
+ bl_parent_id = 'PHYSICS_PT_settings'
+ bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
- if not PhysicButtonsPanel.poll_fluid_settings(context):
+ if not PhysicButtonsPanel.poll_fluid_flow(context):
return False
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+ flow = context.fluid.flow_settings
+
+ col = layout.column()
+ col.prop(flow, "flow_source", expand=False, text="Flow Source")
+ if flow.flow_source == 'PARTICLES':
+ col.prop_search(flow, "particle_system", ob, "particle_systems", text="Particle System")
+
+ grid = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ col = grid.column()
+ if flow.flow_source == 'MESH':
+ col.prop(flow, "use_plane_init", text="Is Planar")
+ col.prop(flow, "surface_distance", text="Surface Thickness")
+ if flow.flow_type in {'SMOKE', 'BOTH', 'FIRE'}:
+ col = grid.column()
+ col.prop(flow, "volume_density", text="Volume Density")
+
+ if flow.flow_source == 'PARTICLES':
+ col.prop(flow, "use_particle_size", text="Set Size")
+ sub = col.column()
+ sub.active = flow.use_particle_size
+ sub.prop(flow, "particle_size")
+
+
+class PHYSICS_PT_flow_initial_velocity(PhysicButtonsPanel, Panel):
+ bl_label = "Initial Velocity"
+ bl_parent_id = 'PHYSICS_PT_settings'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_fluid_flow(context):
+ return False
+
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
md = context.fluid
- return md and md.settings and (md.settings.type == 'PARTICLE') and (context.engine in cls.COMPAT_ENGINES)
+ flow_smoke = md.flow_settings
+
+ self.layout.prop(flow_smoke, "use_initial_velocity", text="")
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
+
+ md = context.fluid
+ flow_smoke = md.flow_settings
+
+ flow.active = flow_smoke.use_initial_velocity
+
+ col = flow.column()
+ col.prop(flow_smoke, "velocity_factor")
+
+ if flow_smoke.flow_source == 'MESH':
+ col.prop(flow_smoke, "velocity_normal")
+ # col.prop(flow_smoke, "velocity_random")
+ col = flow.column()
+ col.prop(flow_smoke, "velocity_coord")
+
+
+class PHYSICS_PT_flow_texture(PhysicButtonsPanel, Panel):
+ bl_label = "Texture"
+ bl_parent_id = 'PHYSICS_PT_settings'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_fluid_flow(context):
+ return False
+
+ return (context.engine in cls.COMPAT_ENGINES)
+ def draw_header(self, context):
md = context.fluid
- fluid = md.settings
+ flow_smoke = md.flow_settings
+
+ self.layout.prop(flow_smoke, "use_texture", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ ob = context.object
+ flow_smoke = context.fluid.flow_settings
+
+ sub = flow.column()
+ sub.active = flow_smoke.use_texture
+ sub.prop(flow_smoke, "noise_texture")
+ sub.prop(flow_smoke, "texture_map_type", text="Mapping")
+
+ col = flow.column()
+ sub = col.column()
+ sub.active = flow_smoke.use_texture
+
+ if flow_smoke.texture_map_type == 'UV':
+ sub.prop_search(flow_smoke, "uv_layer", ob.data, "uv_layers")
- layout.prop(fluid, "filepath", text="")
+ if flow_smoke.texture_map_type == 'AUTO':
+ sub.prop(flow_smoke, "texture_size")
+ sub.prop(flow_smoke, "texture_offset")
-class PHYSICS_PT_domain_bake(PhysicButtonsPanel, Panel):
- bl_label = "Bake"
+
+class PHYSICS_PT_adaptive_domain(PhysicButtonsPanel, Panel):
+ bl_label = "Adaptive Domain"
+ bl_parent_id = 'PHYSICS_PT_fluid'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_gas_domain(context):
+ return False
+
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ md = context.fluid.domain_settings
+ domain = context.fluid.domain_settings
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+ self.layout.enabled = not baking_any and not baked_any
+ self.layout.prop(md, "use_adaptive_domain", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ domain = context.fluid.domain_settings
+ layout.active = domain.use_adaptive_domain
+
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
+ flow.enabled = not baking_any and not baked_any
+
+ col = flow.column()
+ col.prop(domain, "additional_res", text="Add Resolution")
+ col.prop(domain, "adapt_margin")
+
+ col.separator()
+
+ col = flow.column()
+ col.prop(domain, "adapt_threshold", text="Threshold")
+
+
+class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
+ bl_label = "Noise"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
- if not PhysicButtonsPanel.poll_fluid_domain(context):
+ if not PhysicButtonsPanel.poll_gas_domain(context):
return False
return (context.engine in cls.COMPAT_ENGINES)
+ def draw_header(self, context):
+ md = context.fluid.domain_settings
+ domain = context.fluid.domain_settings
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ self.layout.enabled = not baking_any
+ self.layout.prop(md, "use_noise", text="")
+
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
- md = context.fluid
- fluid = md.settings
+ domain = context.fluid.domain_settings
+
+ # Deactivate UI if guiding is enabled but not baked yet
+ layout.active = domain.use_noise and not (domain.use_guiding and not domain.cache_baked_guiding and (domain.guiding_source == "EFFECTOR" or (domain.guiding_source == "DOMAIN" and not domain.guiding_parent)))
+
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_noise = domain.cache_baked_noise
- row = layout.row(align=True)
- row.alignment = 'RIGHT'
- row.label(text="Cache Path")
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_noise
- layout.prop(fluid, "filepath", text="")
+ col = flow.column()
+ col.prop(domain, "noise_scale", text="Upres Factor")
+ # TODO (sebbas): Mantaflow only supports wavelet noise. Maybe get rid of noise type field.
+ col.prop(domain, "noise_type", text="Noise Method")
- # odd formatting here so translation script can extract string
- layout.operator(
- "fluid.bake", text=iface_("Bake (Req. Memory: %s)") % fluid.memory_estimate,
- translate=False, icon='MOD_FLUIDSIM'
- )
+ col = flow.column()
+ col.prop(domain, "noise_strength", text="Strength")
+ col.prop(domain, "noise_pos_scale", text="Scale")
+ col.prop(domain, "noise_time_anim", text="Time")
+ if domain.cache_type == "MODULAR":
+ col.separator()
-class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
- bl_label = "World"
+ split = layout.split()
+ split.enabled = domain.cache_baked_data
+
+ bake_incomplete = (domain.cache_frame_pause_noise < domain.cache_frame_end)
+ if domain.cache_baked_noise and not domain.cache_baking_noise and bake_incomplete:
+ col = split.column()
+ col.operator("fluid.bake_noise", text="Resume")
+ col = split.column()
+ col.operator("fluid.free_noise", text="Free")
+ elif not domain.cache_baked_noise and domain.cache_baking_noise:
+ split.enabled = False
+ split.operator("fluid.pause_bake", text="Baking Noise - ESC to pause")
+ elif not domain.cache_baked_noise and not domain.cache_baking_noise:
+ split.operator("fluid.bake_noise", text="Bake Noise")
+ else:
+ split.operator("fluid.free_noise", text="Free Noise")
+
+
+class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
+ bl_label = "Mesh"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
- if not PhysicButtonsPanel.poll_fluid_domain(context):
+ if not PhysicButtonsPanel.poll_liquid_domain(context):
return False
return (context.engine in cls.COMPAT_ENGINES)
+ def draw_header(self, context):
+ md = context.fluid.domain_settings
+ domain = context.fluid.domain_settings
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ self.layout.enabled = not baking_any
+ self.layout.prop(md, "use_mesh", text="")
+
def draw(self, context):
layout = self.layout
layout.use_property_split = True
- fluid = context.fluid.settings
- scene = context.scene
+ domain = context.fluid.domain_settings
- col = layout.column()
+ # Deactivate UI if guiding is enabled but not baked yet
+ layout.active = domain.use_mesh and not (domain.use_guiding and not domain.cache_baked_guiding and (domain.guiding_source == "EFFECTOR" or (domain.guiding_source == "DOMAIN" and not domain.guiding_parent)))
- use_gravity = scene.use_gravity
- use_units = scene.unit_settings.system != 'NONE'
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_mesh = domain.cache_baked_mesh
- if use_gravity or use_units:
- s_gravity = " Gravity" if use_gravity else ""
- s_units = " Units" if use_units else ""
- s_and = " and " if use_gravity and use_units else ""
- warn = f"Using {s_gravity}{s_and}{s_units} from Scene"
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_mesh
- sub = col.column()
- sub.alignment = 'RIGHT'
- sub.label(text=warn)
+ col = flow.column()
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
+ col.prop(domain, "mesh_scale", text="Upres Factor")
+ col.prop(domain, "mesh_particle_radius", text="Particle Radius")
col = flow.column()
- sub = col.column()
- sub.enabled = not use_gravity
- sub.prop(fluid, "gravity", text="Gravity")
+ col.prop(domain, "use_speed_vectors", text="Use Speed Vectors")
- sub = col.column()
- sub.enabled = not use_units
- sub.prop(fluid, "simulation_scale", text="Scene Size Meters" if use_units else "World Size Meters")
+ col.separator()
+ col.prop(domain, "mesh_generator", text="Mesh Generator")
+
+ if domain.mesh_generator in {'IMPROVED'}:
+ col = flow.column(align=True)
+ col.prop(domain, "mesh_smoothen_pos", text="Smoothing Positive")
+ col.prop(domain, "mesh_smoothen_neg", text="Negative")
+
+ col = flow.column(align=True)
+ col.prop(domain, "mesh_concave_upper", text="Concavity Upper")
+ col.prop(domain, "mesh_concave_lower", text="Lower")
+
+ # TODO (sebbas): for now just interpolate any upres grids, ie not sampling highres grids
+ #col.prop(domain, "highres_sampling", text="Flow Sampling:")
+
+ if domain.cache_type == "MODULAR":
+ col.separator()
+ split = layout.split()
+ split.enabled = domain.cache_baked_data
+
+ bake_incomplete = (domain.cache_frame_pause_mesh < domain.cache_frame_end)
+ if domain.cache_baked_mesh and not domain.cache_baking_mesh and bake_incomplete:
+ col = split.column()
+ col.operator("fluid.bake_mesh", text="Resume")
+ col = split.column()
+ col.operator("fluid.free_mesh", text="Free")
+ elif not domain.cache_baked_mesh and domain.cache_baking_mesh:
+ split.enabled = False
+ split.operator("fluid.pause_bake", text="Baking Mesh - ESC to pause")
+ elif not domain.cache_baked_mesh and not domain.cache_baking_mesh:
+ split.operator("fluid.bake_mesh", text="Bake Mesh")
+ else:
+ split.operator("fluid.free_mesh", text="Free Mesh")
+
+
+class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
+ bl_label = "Particles"
+ bl_parent_id = 'PHYSICS_PT_fluid'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_liquid_domain(context):
+ return False
+
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ domain = context.fluid.domain_settings
+
+ # Deactivate UI if guiding is enabled but not baked yet
+ layout.active = not (domain.use_guiding and not domain.cache_baked_guiding and (domain.guiding_source == "EFFECTOR" or (domain.guiding_source == "DOMAIN" and not domain.guiding_parent)))
+
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_particles = domain.cache_baked_particles
+ using_particles = domain.use_spray_particles or domain.use_foam_particles or domain.use_bubble_particles
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any
+
+ subSpray = flow.column()
+ subSpray.enabled = (domain.sndparticle_combined_export == 'OFF') or (domain.sndparticle_combined_export == 'FOAM + BUBBLES')
+ subSpray.prop(domain, "use_spray_particles", text="Spray")
+ subFoam = flow.column()
+ subFoam.enabled = (domain.sndparticle_combined_export == 'OFF') or (domain.sndparticle_combined_export == 'SPRAY + BUBBLES')
+ subFoam.prop(domain, "use_foam_particles", text="Foam")
+ subBubbles = flow.column()
+ subBubbles.enabled = (domain.sndparticle_combined_export == 'OFF') or (domain.sndparticle_combined_export == 'SPRAY + FOAM')
+ subBubbles.prop(domain, "use_bubble_particles", text="Bubbles")
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_particles and using_particles
+
+ col = flow.column()
+ col.prop(domain, "sndparticle_combined_export")
+ col.prop(domain, "particle_scale", text="Upres Factor")
+ col.separator()
+
+ col = flow.column(align=True)
+ col.prop(domain, "sndparticle_tau_max_wc", text="Wave Crest Potential Maximum")
+ col.prop(domain, "sndparticle_tau_min_wc", text="Minimum")
+ col.separator()
+
+ col = flow.column(align=True)
+ col.prop(domain, "sndparticle_tau_max_ta", text="Trapped Air Potential Maximum")
+ col.prop(domain, "sndparticle_tau_min_ta", text="Minimum")
+ col.separator()
+
+ col = flow.column(align=True)
+ col.prop(domain, "sndparticle_tau_max_k", text="Kinetic Energy Potential Maximum")
+ col.prop(domain, "sndparticle_tau_min_k", text="Minimum")
+ col.separator()
+
+ col = flow.column(align=True)
+ col.prop(domain, "sndparticle_potential_radius", text="Potential Radius")
+ col.prop(domain, "sndparticle_update_radius", text="Particle Update Radius")
+ col.separator()
+
+ col = flow.column(align=True)
+ col.prop(domain, "sndparticle_k_wc", text="Wave Crest Particle Sampling")
+ col.prop(domain, "sndparticle_k_ta", text="Trapped Air Particle Sampling")
+ col.separator()
+
+ col = flow.column(align=True)
+ col.prop(domain, "sndparticle_l_max", text="Particle Life Maximum")
+ col.prop(domain, "sndparticle_l_min", text="Minimum")
+ col.separator()
+
+ col = flow.column(align=True)
+ col.prop(domain, "sndparticle_k_b", text="Bubble Buoyancy")
+ col.prop(domain, "sndparticle_k_d", text="Bubble Drag")
col.separator()
col = flow.column()
- col.prop(fluid, "grid_levels", text="Optimization", slider=True)
- col.prop(fluid, "compressibility", slider=True)
+ col.prop(domain, "sndparticle_boundary", text="Particles in Boundary:")
+ if domain.cache_type == "MODULAR":
+ col.separator()
-class PHYSICS_PT_domain_viscosity(PhysicButtonsPanel, Panel):
- bl_label = "Viscosity"
+ split = layout.split()
+ split.enabled = domain.cache_baked_data and (domain.use_spray_particles or domain.use_bubble_particles or domain.use_foam_particles or domain.use_tracer_particles)
+
+ bake_incomplete = (domain.cache_frame_pause_particles < domain.cache_frame_end)
+ if domain.cache_baked_particles and not domain.cache_baking_particles and bake_incomplete:
+ col = split.column()
+ col.operator("fluid.bake_particles", text="Resume")
+ col = split.column()
+ col.operator("fluid.free_particles", text="Free")
+ elif not domain.cache_baked_particles and domain.cache_baking_particles:
+ split.enabled = False
+ split.operator("fluid.pause_bake", text="Baking Particles - ESC to pause")
+ elif not domain.cache_baked_particles and not domain.cache_baking_particles:
+ split.operator("fluid.bake_particles", text="Bake Particles")
+ else:
+ split.operator("fluid.free_particles", text="Free Particles")
+
+
+class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
+ bl_label = "Diffusion"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
+ # Fluid diffusion only enabled for liquids (surface tension and viscosity not relevant for smoke)
+ if not PhysicButtonsPanel.poll_liquid_domain(context):
+ return False
+
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ domain = context.fluid.domain_settings
+
+ # Deactivate UI if guiding is enabled but not baked yet
+ layout.active = not (domain.use_guiding and not domain.cache_baked_guiding and (domain.guiding_source == "EFFECTOR" or (domain.guiding_source == "DOMAIN" and not domain.guiding_parent)))
+
+ split = layout.split()
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+ baked_data = domain.cache_baked_data
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_any and not baked_data
+
+ row = flow.row()
+
+ col = row.column()
+ col.label(text="Viscosity Presets:")
+ col.menu("FLUID_MT_presets", text=bpy.types.FLUID_MT_presets.bl_label)
+
+ col = row.column(align=True)
+ col.operator("fluid.preset_add", text="", icon='ADD')
+ col.operator("fluid.preset_add", text="", icon='REMOVE').remove_active = True
+
+ col = flow.column(align=True)
+ col.prop(domain, "viscosity_base", text="Base")
+ col.prop(domain, "viscosity_exponent", text="Exponent", slider=True)
+
+ col = flow.column()
+ col.prop(domain, "domain_size", text="Real World Size")
+ col.prop(domain, "surface_tension", text="Surface Tension")
+
+
+class PHYSICS_PT_guiding(PhysicButtonsPanel, Panel):
+ bl_label = "Guiding"
+ bl_parent_id = 'PHYSICS_PT_fluid'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+
+ @classmethod
+ def poll(cls, context):
if not PhysicButtonsPanel.poll_fluid_domain(context):
return False
return (context.engine in cls.COMPAT_ENGINES)
- def draw_header_preset(self, _context):
- FLUID_PT_presets.draw_panel_header(self.layout)
+ def draw_header(self, context):
+ md = context.fluid.domain_settings
+ domain = context.fluid.domain_settings
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ self.layout.enabled = not baking_any
+ self.layout.prop(md, "use_guiding", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- fluid = context.fluid.settings
+ domain = context.fluid.domain_settings
+
+ layout.active = domain.use_guiding
+
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_data = domain.cache_baked_data
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_data
col = flow.column()
- col.prop(fluid, "viscosity_base", text="Base")
+ col.prop(domain, "guiding_alpha", text="Weight")
+ col.prop(domain, "guiding_beta", text="Size")
+ col.prop(domain, "guiding_vel_factor", text="Velocity Factor")
col = flow.column()
- col.prop(fluid, "viscosity_exponent", text="Exponent", slider=True)
+ col.prop(domain, "guiding_source", text="Velocity Source")
+ if domain.guiding_source == "DOMAIN":
+ col.prop(domain, "guiding_parent", text="Guiding Parent")
+ if domain.cache_type == "MODULAR":
+ col.separator()
-class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, Panel):
- bl_label = "Boundary"
+ if domain.guiding_source == "EFFECTOR":
+ split = layout.split()
+ bake_incomplete = (domain.cache_frame_pause_guiding < domain.cache_frame_end)
+ if domain.cache_baked_guiding and not domain.cache_baking_guiding and bake_incomplete:
+ col = split.column()
+ col.operator("fluid.bake_guiding", text="Resume")
+ col = split.column()
+ col.operator("fluid.free_guiding", text="Free")
+ elif not domain.cache_baked_guiding and domain.cache_baking_guiding:
+ split.operator("fluid.pause_bake", text="Pause Guiding")
+ elif not domain.cache_baked_guiding and not domain.cache_baking_guiding:
+ split.operator("fluid.bake_guiding", text="Bake Guiding")
+ else:
+ split.operator("fluid.free_guiding", text="Free Guiding")
+
+
+class PHYSICS_PT_collections(PhysicButtonsPanel, Panel):
+ bl_label = "Collections"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@@ -403,26 +1001,127 @@ class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- fluid = context.fluid.settings
+ domain = context.fluid.domain_settings
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+
+ col = flow.column()
+ col.prop(domain, "fluid_group", text="Flow")
+
+ # col.prop(domain, "effector_group", text="Forces")
+ col.prop(domain, "effector_group", text="Effector")
+
+
+class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
+ bl_label = "Cache"
+ bl_parent_id = 'PHYSICS_PT_fluid'
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_fluid_domain(context):
+ return False
+
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ md = context.fluid
+ domain = context.fluid.domain_settings
+
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+
+ col = layout.column()
+ col.prop(domain, "cache_directory", text="")
+ col.enabled = not baking_any
+
+ layout.use_property_split = True
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
col = flow.column()
- col.prop(fluid, "slip_type", text="Type")
+ col.prop(domain, "cache_type", expand=False)
+ col.enabled = not baking_any
+ col = flow.column(align=True)
col.separator()
- if fluid.slip_type == 'PARTIALSLIP':
- col.prop(fluid, "partial_slip_factor", slider=True, text="Amount")
+ col.prop(domain, "cache_frame_start", text="Frame Start")
+ col.prop(domain, "cache_frame_end", text="End")
+ col.enabled = not baking_any
+
+ col.separator()
col = flow.column()
- col.prop(fluid, "surface_smooth", text="Surface Smoothing")
- col.prop(fluid, "surface_subdivisions", text="Subdivisions")
- col.prop(fluid, "use_surface_noobs")
+ col.enabled = not baking_any and not baked_any
+ col.prop(domain, "cache_data_format", text="Data File Format")
+ if md.domain_settings.domain_type in {'GAS'}:
+ if domain.use_noise:
+ col.prop(domain, "cache_noise_format", text="Noise File Format")
-class PHYSICS_PT_domain_particles(PhysicButtonsPanel, Panel):
- bl_label = "Particles"
+ if md.domain_settings.domain_type in {'LIQUID'}:
+ # File format for all particle systemes (FLIP and secondary)
+ col.prop(domain, "cache_particle_format", text="Particle File Format")
+
+ if domain.use_mesh:
+ col.prop(domain, "cache_mesh_format", text="Mesh File Format")
+
+ if domain.cache_type == "FINAL":
+
+ col.separator()
+ split = layout.split()
+
+ bake_incomplete = (domain.cache_frame_pause_data < domain.cache_frame_end)
+ if domain.cache_baked_data and not domain.cache_baking_data and bake_incomplete:
+ col = split.column()
+ col.operator("fluid.bake_all", text="Resume")
+ col = split.column()
+ col.operator("fluid.free_all", text="Free")
+ elif domain.cache_baking_data and not domain.cache_baked_data:
+ split.enabled = False
+ split.operator("fluid.pause_bake", text="Baking All - ESC to pause")
+ elif not domain.cache_baked_data and not domain.cache_baking_data:
+ split.operator("fluid.bake_all", text="Bake All")
+ else:
+ split.operator("fluid.free_all", text="Free All")
+
+
+class PHYSICS_PT_export(PhysicButtonsPanel, Panel):
+ bl_label = "Advanced"
+ bl_parent_id = 'PHYSICS_PT_cache'
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+
+ @classmethod
+ def poll(cls, context):
+ if not PhysicButtonsPanel.poll_fluid_domain(context):
+ return False
+
+ return (context.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ md = context.fluid
+ domain = context.fluid.domain_settings
+
+ baking_any = domain.cache_baking_data or domain.cache_baking_mesh or domain.cache_baking_particles or domain.cache_baking_noise or domain.cache_baking_guiding
+ baked_any = domain.cache_baked_data or domain.cache_baked_mesh or domain.cache_baked_particles or domain.cache_baked_noise or domain.cache_baked_guiding
+
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ flow.enabled = not baking_any and not baked_any
+
+ col = flow.column()
+ col.prop(domain, "export_manta_script", text="Export Mantaflow Script")
+
+
+class PHYSICS_PT_field_weights(PhysicButtonsPanel, Panel):
+ bl_label = "Field Weights"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@@ -435,32 +1134,141 @@ class PHYSICS_PT_domain_particles(PhysicButtonsPanel, Panel):
return (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
+ domain = context.fluid.domain_settings
+ effector_weights_ui(self, domain.effector_weights, 'SMOKE')
+
+
+class PHYSICS_PT_viewport_display(PhysicButtonsPanel, Panel):
+ bl_label = "Viewport Display"
+ bl_parent_id = 'PHYSICS_PT_fluid'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return (PhysicButtonsPanel.poll_gas_domain(context))
+
+ def draw(self, context):
layout = self.layout
layout.use_property_split = True
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- fluid = context.fluid.settings
+ domain = context.fluid.domain_settings
col = flow.column()
- col.prop(fluid, "tracer_particles", text="Tracer")
+ col.prop(domain, "display_thickness")
+
+ col.separator()
+
+ col.prop(domain, "slice_method", text="Slicing")
+
+ slice_method = domain.slice_method
+ axis_slice_method = domain.axis_slice_method
+
+ do_axis_slicing = (slice_method == 'AXIS_ALIGNED')
+ do_full_slicing = (axis_slice_method == 'FULL')
+
+ col = col.column()
+ col.enabled = do_axis_slicing
+ col.prop(domain, "axis_slice_method")
+
+ col = flow.column()
+ sub = col.column()
+ sub.enabled = not do_full_slicing and do_axis_slicing
+ sub.prop(domain, "slice_axis")
+ sub.prop(domain, "slice_depth")
+
+ row = col.row()
+ row.enabled = do_full_slicing or not do_axis_slicing
+ row.prop(domain, "slice_per_voxel")
+
+ col.prop(domain, "display_interpolation")
+
+
+class PHYSICS_PT_viewport_display_color(PhysicButtonsPanel, Panel):
+ bl_label = "Color Mapping"
+ bl_parent_id = 'PHYSICS_PT_viewport_display'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return (PhysicButtonsPanel.poll_gas_domain(context))
+
+ def draw_header(self, context):
+ md = context.fluid.domain_settings
+
+ self.layout.prop(md, "use_color_ramp", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ domain = context.fluid.domain_settings
+ col = layout.column()
+ col.enabled = domain.use_color_ramp
+
+ col.prop(domain, "coba_field")
+
+ col.use_property_split = False
+
+ col = col.column()
+ col.template_color_ramp(domain, "color_ramp", expand=True)
+
+
+class PHYSICS_PT_viewport_display_debug(PhysicButtonsPanel, Panel):
+ bl_label = "Debug Velocity"
+ bl_parent_id = 'PHYSICS_PT_viewport_display'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return (PhysicButtonsPanel.poll_gas_domain(context))
+
+ def draw_header(self, context):
+ md = context.fluid.domain_settings
+
+ self.layout.prop(md, "show_velocity", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
+
+ domain = context.fluid.domain_settings
col = flow.column()
- col.prop(fluid, "generate_particles", text="Generate")
+ col.enabled = domain.show_velocity
+ col.prop(domain, "vector_display_type", text="Display As")
+ col.prop(domain, "vector_scale")
classes = (
- FLUID_PT_presets,
+ FLUID_MT_presets,
PHYSICS_PT_fluid,
- PHYSICS_PT_fluid_settings,
- PHYSICS_PT_fluid_flow,
- PHYSICS_PT_fluid_particle_cache,
- PHYSICS_PT_domain_bake,
- PHYSICS_PT_domain_boundary,
- PHYSICS_PT_domain_particles,
- PHYSICS_PT_domain_gravity,
- PHYSICS_PT_domain_viscosity,
+ PHYSICS_PT_settings,
+ PHYSICS_PT_borders,
+ PHYSICS_PT_smoke,
+ PHYSICS_PT_smoke_dissolve,
+ PHYSICS_PT_fire,
+ PHYSICS_PT_liquid,
+ PHYSICS_PT_flow_source,
+ PHYSICS_PT_flow_initial_velocity,
+ PHYSICS_PT_flow_texture,
+ PHYSICS_PT_adaptive_domain,
+ PHYSICS_PT_noise,
+ PHYSICS_PT_mesh,
+ PHYSICS_PT_particles,
+ PHYSICS_PT_diffusion,
+ PHYSICS_PT_guiding,
+ PHYSICS_PT_collections,
+ PHYSICS_PT_cache,
+ PHYSICS_PT_export,
+ PHYSICS_PT_field_weights,
+ PHYSICS_PT_viewport_display,
+ PHYSICS_PT_viewport_display_color,
+ PHYSICS_PT_viewport_display_debug,
)
+
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
for cls in classes:
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
deleted file mode 100644
index 057e7ddf211..00000000000
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ /dev/null
@@ -1,692 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-
-import bpy
-from bpy.types import (
- Panel,
-)
-from bl_ui.properties_physics_common import (
- point_cache_ui,
- effector_weights_ui,
-)
-
-
-class PhysicButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "physics"
-
- @staticmethod
- def poll_smoke(context):
- ob = context.object
- if not ((ob and ob.type == 'MESH') and (context.smoke)):
- return False
-
- md = context.smoke
- return md and (context.smoke.smoke_type != 'NONE') and (bpy.app.build_options.mod_smoke)
-
- @staticmethod
- def poll_smoke_domain(context):
- if not PhysicButtonsPanel.poll_smoke(context):
- return False
-
- md = context.smoke
- return md and (md.smoke_type == 'DOMAIN')
-
-
-class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
- bl_label = "Smoke"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- ob = context.object
- return (ob and ob.type == 'MESH') and (context.engine in cls.COMPAT_ENGINES) and (context.smoke)
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- if not bpy.app.build_options.mod_smoke:
- col = layout.column(align=True)
- col.alignment = 'RIGHT'
- col.label(text="Built without Smoke modifier")
- return
-
- md = context.smoke
-
- layout.prop(md, "smoke_type")
-
-
-class PHYSICS_PT_smoke_settings(PhysicButtonsPanel, Panel):
- bl_label = "Settings"
- bl_parent_id = 'PHYSICS_PT_smoke'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke(context):
- return False
-
- return (context.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- md = context.smoke
- ob = context.object
-
- if md.smoke_type == 'DOMAIN':
- domain = md.domain_settings
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
- col.enabled = (not domain.point_cache.is_baked)
- col.prop(domain, "resolution_max", text="Resolution Divisions")
- col.prop(domain, "time_scale", text="Time Scale")
-
- col.separator()
-
- col = flow.column()
- sub = col.row()
- sub.enabled = (not domain.point_cache.is_baked)
- sub.prop(domain, "collision_extents", text="Border Collisions")
-
- # This can be tweaked after baking, for render.
- col.prop(domain, "clipping", text="Empty Space")
-
- elif md.smoke_type == 'FLOW':
- flow_smoke = md.flow_settings
-
- col = layout.column()
- col.prop(flow_smoke, "smoke_flow_type", expand=False)
-
- col.separator()
-
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
- col = flow.column()
-
- if flow_smoke.smoke_flow_type != 'OUTFLOW':
- col.prop(flow_smoke, "smoke_flow_source", expand=False, text="Flow Source")
-
- if flow_smoke.smoke_flow_source == 'PARTICLES':
- col.prop_search(
- flow_smoke, "particle_system", ob, "particle_systems",
- text="Particle System"
- )
- else:
- col.prop(flow_smoke, "surface_distance")
- col.prop(flow_smoke, "volume_density")
-
- col = flow.column()
- col.prop(flow_smoke, "use_absolute")
-
- if flow_smoke.smoke_flow_type in {'SMOKE', 'BOTH'}:
- col.prop(flow_smoke, "density")
- col.prop(flow_smoke, "temperature", text="Temperature Diff.")
-
- col.separator()
-
- col = flow.column()
- col.prop(flow_smoke, "smoke_color")
-
- if flow_smoke.smoke_flow_type in {'FIRE', 'BOTH'}:
- col.prop(flow_smoke, "fuel_amount")
-
- col.prop(flow_smoke, "subframes", text="Sampling Subframes")
-
- col.separator()
-
- col.prop_search(flow_smoke, "density_vertex_group", ob, "vertex_groups", text="Vertex Group")
-
- elif md.smoke_type == 'COLLISION':
- coll = md.coll_settings
-
- col = layout.column()
- col.prop(coll, "collision_type")
-
-
-class PHYSICS_PT_smoke_settings_initial_velocity(PhysicButtonsPanel, Panel):
- bl_label = "Initial Velocity"
- bl_parent_id = 'PHYSICS_PT_smoke_settings'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke(context):
- return False
-
- md = context.smoke
- return (md and (md.smoke_type == 'FLOW')
- and md.flow_settings and md.flow_settings.smoke_flow_type != 'OUTFLOW'
- and context.engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- md = context.smoke
- flow_smoke = md.flow_settings
-
- self.layout.prop(flow_smoke, "use_initial_velocity", text="")
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
-
- md = context.smoke
- flow_smoke = md.flow_settings
-
- flow.active = flow_smoke.use_initial_velocity
-
- col = flow.column(align=True)
- col.prop(flow_smoke, "velocity_factor")
-
- if flow_smoke.smoke_flow_source == 'MESH':
- col = flow.column()
- col.prop(flow_smoke, "velocity_normal")
- # sub.prop(flow_smoke, "velocity_random")
-
-
-class PHYSICS_PT_smoke_settings_particle_size(PhysicButtonsPanel, Panel):
- bl_label = "Particle Size"
- bl_parent_id = 'PHYSICS_PT_smoke_settings'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke(context):
- return False
-
- md = context.smoke
- return (md and (md.smoke_type == 'FLOW')
- and md.flow_settings and md.flow_settings.smoke_flow_type != 'OUTFLOW'
- and md.flow_settings.smoke_flow_source == 'PARTICLES'
- and context.engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- md = context.smoke
- flow_smoke = md.flow_settings
-
- self.layout.prop(flow_smoke, "use_particle_size", text="")
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- md = context.smoke
- flow_smoke = md.flow_settings
-
- layout.active = flow_smoke.use_particle_size
-
- layout.prop(flow_smoke, "particle_size")
-
-
-class PHYSICS_PT_smoke_behavior(PhysicButtonsPanel, Panel):
- bl_label = "Behavior"
- bl_parent_id = 'PHYSICS_PT_smoke_settings'
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke_domain(context):
- return False
-
- return (context.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- md = context.smoke
- domain = md.domain_settings
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- flow.enabled = (not domain.point_cache.is_baked)
-
- col = flow.column()
- col.prop(domain, "alpha")
- col.prop(domain, "beta", text="Temperature Diff.")
- col = flow.column()
- col.prop(domain, "vorticity")
-
-
-class PHYSICS_PT_smoke_behavior_dissolve(PhysicButtonsPanel, Panel):
- bl_label = "Dissolve"
- bl_parent_id = 'PHYSICS_PT_smoke_behavior'
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke_domain(context):
- return False
-
- return (context.engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- md = context.smoke
- domain = md.domain_settings
-
- self.layout.prop(domain, "use_dissolve_smoke", text="")
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- md = context.smoke
- domain = md.domain_settings
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- flow.enabled = (not domain.point_cache.is_baked)
-
- layout.active = domain.use_dissolve_smoke
-
- col = flow.column()
- col.prop(domain, "dissolve_speed", text="Time")
-
- col = flow.column()
- col.prop(domain, "use_dissolve_smoke_log", text="Slow")
-
-
-class PHYSICS_PT_smoke_flow_texture(PhysicButtonsPanel, Panel):
- bl_label = "Texture"
- bl_parent_id = 'PHYSICS_PT_smoke'
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke(context):
- return False
-
- md = context.smoke
- return (md and (md.smoke_type == 'FLOW')
- and (md.flow_settings.smoke_flow_source == 'MESH')
- and (context.engine in cls.COMPAT_ENGINES))
-
- def draw_header(self, context):
- md = context.smoke
- flow_smoke = md.flow_settings
-
- self.layout.prop(flow_smoke, "use_texture", text="")
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- ob = context.object
- flow_smoke = context.smoke.flow_settings
-
- sub = flow.column()
- sub.active = flow_smoke.use_texture
- sub.prop(flow_smoke, "noise_texture")
- sub.prop(flow_smoke, "texture_map_type", text="Mapping")
-
- col = flow.column()
- sub = col.column()
- sub.active = flow_smoke.use_texture
-
- if flow_smoke.texture_map_type == 'UV':
- sub.prop_search(flow_smoke, "uv_layer", ob.data, "uv_layers")
-
- if flow_smoke.texture_map_type == 'AUTO':
- sub.prop(flow_smoke, "texture_size")
-
- sub.prop(flow_smoke, "texture_offset")
-
-
-class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel):
- bl_label = "Flames"
- bl_parent_id = 'PHYSICS_PT_smoke'
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke_domain(context):
- return False
-
- return (context.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- domain = context.smoke.domain_settings
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- flow.enabled = (not domain.point_cache.is_baked)
-
- col = flow.column()
- col.prop(domain, "burning_rate", text="Reaction Speed")
- col.prop(domain, "flame_smoke")
- col.prop(domain, "flame_vorticity")
-
- col.separator()
-
- col = flow.column(align=True)
- col.prop(domain, "flame_ignition", text="Temperature Ignition")
- col.prop(domain, "flame_max_temp")
-
- col.separator()
-
- sub = col.column()
- sub.prop(domain, "flame_smoke_color")
-
-
-class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel):
- bl_label = "Adaptive Domain"
- bl_parent_id = 'PHYSICS_PT_smoke'
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke_domain(context):
- return False
-
- return (context.engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- md = context.smoke.domain_settings
-
- self.layout.prop(md, "use_adaptive_domain", text="")
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- domain = context.smoke.domain_settings
- layout.active = domain.use_adaptive_domain
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
- flow.enabled = (not domain.point_cache.is_baked)
-
- col = flow.column()
- col.prop(domain, "additional_res", text="Add Resolution")
- col.prop(domain, "adapt_margin")
-
- col.separator()
-
- col = flow.column()
- col.prop(domain, "adapt_threshold", text="Threshold")
-
-
-class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
- bl_label = "High Resolution"
- bl_parent_id = 'PHYSICS_PT_smoke'
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke_domain(context):
- return False
-
- return (context.engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- md = context.smoke.domain_settings
-
- self.layout.prop(md, "use_high_resolution", text="")
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- md = context.smoke.domain_settings
- layout.active = md.use_high_resolution
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
-
- col = flow.column()
- col.enabled = not md.point_cache.is_baked
- col.prop(md, "amplify", text="Resolution Divisions")
- col.prop(md, "highres_sampling", text="Flow Sampling")
-
- col.separator()
-
- col = flow.column()
- col.enabled = not md.point_cache.is_baked
- col.prop(md, "noise_type", text="Noise Method")
- col.prop(md, "strength")
-
- layout.prop(md, "show_high_resolution")
-
-
-class PHYSICS_PT_smoke_collections(PhysicButtonsPanel, Panel):
- bl_label = "Collections"
- bl_parent_id = 'PHYSICS_PT_smoke'
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke_domain(context):
- return False
-
- return (context.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- domain = context.smoke.domain_settings
-
- col = layout.column()
- col.prop(domain, "fluid_collection", text="Flow")
-
- # col = layout.column()
- # col.prop(domain, "effector_collection", text="Effector")
- col.prop(domain, "collision_collection", text="Collision")
-
-
-class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
- bl_label = "Cache"
- bl_parent_id = 'PHYSICS_PT_smoke'
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke_domain(context):
- return False
-
- return (context.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
-
- domain = context.smoke.domain_settings
- cache_file_format = domain.cache_file_format
-
- col = flow.column()
- col.prop(domain, "cache_file_format")
-
- if cache_file_format == 'POINTCACHE':
- col = flow.column()
- col.prop(domain, "point_cache_compress_type", text="Compression")
- col.separator()
-
- elif cache_file_format == 'OPENVDB':
- if not bpy.app.build_options.openvdb:
- row = layout.row(align=True)
- row.alignment = 'RIGHT'
- row.label(text="Built without OpenVDB support")
- return
-
- col = flow.column()
- col.prop(domain, "openvdb_cache_compress_type", text="Compression")
- col.prop(domain, "data_depth", text="Data Depth")
- col.separator()
-
- cache = domain.point_cache
- point_cache_ui(self, cache, (cache.is_baked is False), 'SMOKE')
-
-
-class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel):
- bl_label = "Field Weights"
- bl_parent_id = 'PHYSICS_PT_smoke'
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- @classmethod
- def poll(cls, context):
- if not PhysicButtonsPanel.poll_smoke_domain(context):
- return False
-
- return (context.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- domain = context.smoke.domain_settings
- effector_weights_ui(self, domain.effector_weights, 'SMOKE')
-
-
-class PHYSICS_PT_smoke_viewport_display(PhysicButtonsPanel, Panel):
- bl_label = "Viewport Display"
- bl_parent_id = 'PHYSICS_PT_smoke'
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- return (PhysicButtonsPanel.poll_smoke_domain(context))
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
-
- domain = context.smoke.domain_settings
-
- col = flow.column()
- col.prop(domain, "display_thickness")
-
- col.separator()
-
- col.prop(domain, "slice_method", text="Slicing")
-
- slice_method = domain.slice_method
- axis_slice_method = domain.axis_slice_method
-
- do_axis_slicing = (slice_method == 'AXIS_ALIGNED')
- do_full_slicing = (axis_slice_method == 'FULL')
-
- col = col.column()
- col.enabled = do_axis_slicing
- col.prop(domain, "axis_slice_method")
-
- col = flow.column()
- sub = col.column()
- sub.enabled = not do_full_slicing and do_axis_slicing
- sub.prop(domain, "slice_axis")
- sub.prop(domain, "slice_depth")
-
- row = col.row()
- row.enabled = do_full_slicing or not do_axis_slicing
- row.prop(domain, "slice_per_voxel")
-
- col.prop(domain, "display_interpolation")
-
-
-class PHYSICS_PT_smoke_viewport_display_color(PhysicButtonsPanel, Panel):
- bl_label = "Color Mapping"
- bl_parent_id = 'PHYSICS_PT_smoke_viewport_display'
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- return (PhysicButtonsPanel.poll_smoke_domain(context))
-
- def draw_header(self, context):
- md = context.smoke.domain_settings
-
- self.layout.prop(md, "use_color_ramp", text="")
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
-
- domain = context.smoke.domain_settings
- col = layout.column()
- col.enabled = domain.use_color_ramp
-
- col.prop(domain, "coba_field")
-
- col.use_property_split = False
-
- col = col.column()
- col.template_color_ramp(domain, "color_ramp", expand=True)
-
-
-class PHYSICS_PT_smoke_viewport_display_debug(PhysicButtonsPanel, Panel):
- bl_label = "Debug Velocity"
- bl_parent_id = 'PHYSICS_PT_smoke_viewport_display'
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- return (PhysicButtonsPanel.poll_smoke_domain(context))
-
- def draw_header(self, context):
- md = context.smoke.domain_settings
-
- self.layout.prop(md, "show_velocity", text="")
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
-
- domain = context.smoke.domain_settings
-
- col = flow.column()
- col.enabled = domain.show_velocity
- col.prop(domain, "vector_display_type", text="Display As")
- col.prop(domain, "vector_scale")
-
-
-classes = (
- PHYSICS_PT_smoke,
- PHYSICS_PT_smoke_settings,
- PHYSICS_PT_smoke_settings_initial_velocity,
- PHYSICS_PT_smoke_settings_particle_size,
- PHYSICS_PT_smoke_behavior,
- PHYSICS_PT_smoke_behavior_dissolve,
- PHYSICS_PT_smoke_adaptive_domain,
- PHYSICS_PT_smoke_cache,
- PHYSICS_PT_smoke_field_weights,
- PHYSICS_PT_smoke_fire,
- PHYSICS_PT_smoke_flow_texture,
- PHYSICS_PT_smoke_collections,
- PHYSICS_PT_smoke_highres,
- PHYSICS_PT_smoke_viewport_display,
- PHYSICS_PT_smoke_viewport_display_color,
- PHYSICS_PT_smoke_viewport_display_debug,
-)
-
-
-if __name__ == "__main__": # only for live edit.
- from bpy.utils import register_class
- for cls in classes:
- register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 2fb8afbbd23..3aecd7b9775 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -2195,7 +2195,6 @@ class USERPREF_PT_experimental_ui(ExperimentalPanel, Panel):
col = split.column()
col.operator("wm.url_open", text=task, icon='URL').url = self.url_prefix + task
-
"""
# Example panel, leave it here so we always have a template to follow even
# after the features are gone from the experimental panel.
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 596b7b13e05..6374b3af46d 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2647,7 +2647,7 @@ class VIEW3D_MT_object_quick_effects(Menu):
layout.operator("object.quick_fur")
layout.operator("object.quick_explode")
layout.operator("object.quick_smoke")
- layout.operator("object.quick_fluid")
+ layout.operator("object.quick_liquid")
class VIEW3D_MT_object_showhide(Menu):