b37d121e0a
Extract - Add to Quick Favorites tooltip. - "Mask", the name of a newly created mask (DATA_). - "New" in the context of the new mask ID button. - A few strings using BLI_STR_UTF8_ defines were not extracted. Take the special characters out of the translation macros. - "External" menu items from the filebrowser's Files context menu (right-click on a file). These items were already extracted, but not translated. Improve - Separate formatted error message "%s is not compatible with ["the specified", "any"] 'refresh' options" into two messages. Disambiguate - Use Action context for new F-modifiers' names. This is already used for the "type" operator prop. - Translate ImportHelper's default confirmation text using the Operator context, as it uses the operator name which is extracted with this context. - "Scale" can be a noun, the scale of something, or a verb, to scale something. The latter mostly uses the Operator context, so apply this context to verbs, and the default contexts to nouns. - "Scale Influence" can mean "Influence on Scale" (tracking stabilization) and "to Scale the Influence" (dynamic paint canvas). - "Object Line Art" as type of Line Art to add, as opposed to the active object's Line Art settings. - Float to Integer node: use NodeTree context for the node label, as this is already extracted and used for the enum. Do not translate - Sequencer labels containing only a string formatting field. Some issues reported by Gabriel Gazzán and Ye Gui. Pull Request: https://projects.blender.org/blender/blender/pulls/122283
1001 lines
30 KiB
Python
1001 lines
30 KiB
Python
# SPDX-FileCopyrightText: 2011-2023 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
from bpy.types import (
|
|
Panel,
|
|
UIList,
|
|
)
|
|
from bpy.app.translations import contexts as i18n_contexts
|
|
from bl_ui.properties_physics_common import (
|
|
point_cache_ui,
|
|
effector_weights_ui,
|
|
)
|
|
|
|
|
|
class PHYSICS_UL_dynapaint_surfaces(UIList):
|
|
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
|
# assert(isinstance(item, bpy.types.DynamicPaintSurface)
|
|
surf = item
|
|
sticon = layout.enum_item_icon(surf, "surface_type", surf.surface_type)
|
|
|
|
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
|
row = layout.row(align=True)
|
|
row.label(text="", icon_value=icon)
|
|
row.prop(surf, "name", text="", emboss=False, icon_value=sticon)
|
|
row = layout.row(align=True)
|
|
row.prop(surf, "is_active", text="")
|
|
|
|
elif self.layout_type == 'GRID':
|
|
layout.alignment = 'CENTER'
|
|
row = layout.row(align=True)
|
|
row.label(text="", icon_value=icon)
|
|
row.label(text="", icon_value=sticon)
|
|
|
|
|
|
class PhysicButtonsPanel:
|
|
bl_space_type = 'PROPERTIES'
|
|
bl_region_type = 'WINDOW'
|
|
bl_context = "physics"
|
|
|
|
@staticmethod
|
|
def poll_dyn_paint(context):
|
|
ob = context.object
|
|
return (ob and ob.type == 'MESH') and context.dynamic_paint
|
|
|
|
@staticmethod
|
|
def poll_dyn_canvas(context):
|
|
if not PhysicButtonsPanel.poll_dyn_paint(context):
|
|
return False
|
|
|
|
md = context.dynamic_paint
|
|
return (md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active)
|
|
|
|
@staticmethod
|
|
def poll_dyn_canvas_paint(context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas(context):
|
|
return False
|
|
|
|
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
|
|
return (surface.surface_type == 'PAINT')
|
|
|
|
@staticmethod
|
|
def poll_dyn_canvas_brush(context):
|
|
if not PhysicButtonsPanel.poll_dyn_paint(context):
|
|
return False
|
|
|
|
md = context.dynamic_paint
|
|
return (md and md.ui_type == 'BRUSH' and md.brush_settings)
|
|
|
|
@staticmethod
|
|
def poll_dyn_output(context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas(context):
|
|
return False
|
|
|
|
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
|
|
return (not (surface.surface_format == 'VERTEX' and (surface.surface_type in {'DISPLACE', 'WAVE'})))
|
|
|
|
@staticmethod
|
|
def poll_dyn_output_maps(context):
|
|
if not PhysicButtonsPanel.poll_dyn_output(context):
|
|
return False
|
|
|
|
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
|
|
return (surface.surface_format == 'IMAGE' and surface.surface_type == 'PAINT')
|
|
|
|
|
|
class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
|
|
bl_label = "Dynamic Paint"
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_paint(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
md = context.dynamic_paint
|
|
|
|
layout.prop(md, "ui_type")
|
|
|
|
|
|
class PHYSICS_PT_dynamic_paint_settings(PhysicButtonsPanel, Panel):
|
|
bl_label = "Settings"
|
|
bl_parent_id = "PHYSICS_PT_dynamic_paint"
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_paint(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
md = context.dynamic_paint
|
|
|
|
if md.ui_type == 'CANVAS':
|
|
canvas = md.canvas_settings
|
|
|
|
if canvas is None:
|
|
layout.operator("dpaint.type_toggle", text="Add Canvas").type = 'CANVAS'
|
|
return # do nothing.
|
|
|
|
layout.operator("dpaint.type_toggle", text="Remove Canvas", icon='X').type = 'CANVAS'
|
|
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
row = layout.row()
|
|
row.template_list(
|
|
"PHYSICS_UL_dynapaint_surfaces", "", canvas, "canvas_surfaces",
|
|
canvas.canvas_surfaces, "active_index", rows=1,
|
|
)
|
|
|
|
col = row.column(align=True)
|
|
col.operator("dpaint.surface_slot_add", icon='ADD', text="")
|
|
col.operator("dpaint.surface_slot_remove", icon='REMOVE', text="")
|
|
|
|
layout.separator()
|
|
|
|
layout.use_property_split = True
|
|
|
|
if surface:
|
|
flow = layout.grid_flow(
|
|
row_major=True, columns=0, even_columns=True, even_rows=False, align=False,
|
|
)
|
|
col = flow.column()
|
|
|
|
col.prop(surface, "surface_format")
|
|
|
|
if surface.surface_format != 'VERTEX':
|
|
col.prop(surface, "image_resolution")
|
|
col.prop(surface, "use_antialiasing")
|
|
|
|
col = flow.column(align=True)
|
|
col.prop(surface, "frame_start", text="Frame Start")
|
|
col.prop(surface, "frame_end", text="End")
|
|
|
|
col.prop(surface, "frame_substeps")
|
|
|
|
elif md.ui_type == 'BRUSH':
|
|
brush = md.brush_settings
|
|
|
|
if brush is None:
|
|
layout.operator("dpaint.type_toggle", text="Add Brush").type = 'BRUSH'
|
|
return # do nothing.
|
|
|
|
layout.operator("dpaint.type_toggle", text="Remove Brush", icon='X').type = 'BRUSH'
|
|
|
|
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(brush, "paint_color")
|
|
col.prop(brush, "paint_alpha", text="Alpha", slider=True)
|
|
|
|
col = flow.column()
|
|
col.prop(brush, "paint_wetness", text="Wetness", slider=True)
|
|
col.prop(brush, "use_absolute_alpha")
|
|
col.prop(brush, "use_paint_erase")
|
|
|
|
|
|
class PHYSICS_PT_dp_surface_canvas(PhysicButtonsPanel, Panel):
|
|
bl_label = "Surface"
|
|
bl_parent_id = "PHYSICS_PT_dynamic_paint"
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
surface_type = surface.surface_type
|
|
|
|
layout.prop(surface, "surface_type")
|
|
|
|
layout.separator()
|
|
|
|
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
|
|
|
|
# per type settings
|
|
if surface_type == 'DISPLACE':
|
|
col = flow.column()
|
|
|
|
if surface.surface_format == 'VERTEX':
|
|
col.prop(surface, "depth_clamp")
|
|
col.prop(surface, "displace_factor")
|
|
|
|
col.prop(surface, "use_incremental_displace")
|
|
col.separator()
|
|
|
|
elif surface_type == 'WAVE':
|
|
col = flow.column()
|
|
col.prop(surface, "use_wave_open_border")
|
|
col.prop(surface, "wave_timescale")
|
|
col.prop(surface, "wave_speed")
|
|
|
|
col.separator()
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "wave_damping")
|
|
col.prop(surface, "wave_spring")
|
|
col.prop(surface, "wave_smoothness")
|
|
|
|
col.separator()
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "brush_collection")
|
|
|
|
if surface_type not in {'DISPLACE', 'WAVE'}:
|
|
col = flow.column() # flow the layout otherwise.
|
|
|
|
col.prop(surface, "brush_influence_scale", text="Scale Influence", text_ctxt=i18n_contexts.id_simulation)
|
|
col.prop(surface, "brush_radius_scale", text="Radius")
|
|
|
|
|
|
class PHYSICS_PT_dp_surface_canvas_paint_dry(PhysicButtonsPanel, Panel):
|
|
bl_label = "Dry"
|
|
bl_parent_id = "PHYSICS_PT_dp_surface_canvas"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas_paint(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw_header(self, context):
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
self.layout.prop(surface, "use_drying", 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)
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
flow.active = surface.use_drying
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "dry_speed", text="Time")
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "color_dry_threshold", text="Color")
|
|
col.prop(surface, "use_dry_log", text="Slow")
|
|
|
|
|
|
class PHYSICS_PT_dp_surface_canvas_paint_dissolve(PhysicButtonsPanel, Panel):
|
|
bl_label = "Dissolve"
|
|
bl_translation_context = i18n_contexts.id_simulation
|
|
bl_parent_id = "PHYSICS_PT_dp_surface_canvas"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas(context):
|
|
return False
|
|
|
|
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
|
|
|
|
return (surface.surface_type != 'WAVE' and context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw_header(self, context):
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
self.layout.prop(surface, "use_dissolve", 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)
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
flow.active = surface.use_dissolve
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "dissolve_speed", text="Time")
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "use_dissolve_log", text="Slow")
|
|
|
|
|
|
class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
|
|
bl_label = "Output"
|
|
bl_parent_id = "PHYSICS_PT_dynamic_paint"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_output(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
ob = context.object
|
|
|
|
surface_type = surface.surface_type
|
|
|
|
# vertex format outputs.
|
|
if surface.surface_format == 'VERTEX':
|
|
if surface_type == 'PAINT':
|
|
# paint-map output.
|
|
row = layout.row()
|
|
row.prop_search(surface, "output_name_a", ob.data, "vertex_colors", text="Paintmap Layer")
|
|
|
|
icons = 'REMOVE' if surface.output_exists(object=ob, index=0) else 'ADD'
|
|
row.operator("dpaint.output_toggle", icon=icons, text="").output = 'A'
|
|
|
|
# wet-map output.
|
|
row = layout.row()
|
|
row.prop_search(surface, "output_name_b", ob.data, "vertex_colors", text="Wetmap Layer")
|
|
|
|
icons = 'REMOVE' if surface.output_exists(object=ob, index=1) else 'ADD'
|
|
row.operator("dpaint.output_toggle", icon=icons, text="").output = 'B'
|
|
|
|
elif surface_type == 'WEIGHT':
|
|
row = layout.row()
|
|
row.prop_search(surface, "output_name_a", ob, "vertex_groups", text="Vertex Group")
|
|
|
|
icons = 'REMOVE' if surface.output_exists(object=ob, index=0) else 'ADD'
|
|
row.operator("dpaint.output_toggle", icon=icons, text="").output = 'A'
|
|
|
|
# image format outputs.
|
|
if surface.surface_format == 'IMAGE':
|
|
|
|
layout.operator("dpaint.bake", text="Bake Image Sequence", icon='MOD_DYNAMICPAINT')
|
|
|
|
layout.prop(surface, "image_output_path", text="Cache Path")
|
|
|
|
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
|
|
|
col = flow.column()
|
|
|
|
col.prop_search(surface, "uv_layer", ob.data, "uv_layers", text="UV Map")
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "image_fileformat")
|
|
col.prop(surface, "use_premultiply", text="Premultiply Alpha")
|
|
|
|
if surface_type != 'PAINT':
|
|
col = col.column()
|
|
col.prop(surface, "output_name_a", text="Filename")
|
|
|
|
if surface_type == 'DISPLACE':
|
|
col.prop(surface, "displace_type", text="Displace Type")
|
|
col.prop(surface, "depth_clamp")
|
|
|
|
elif surface_type == 'WAVE':
|
|
col.prop(surface, "depth_clamp", text="Wave Clamp")
|
|
|
|
|
|
class PHYSICS_PT_dp_canvas_output_paintmaps(PhysicButtonsPanel, Panel):
|
|
bl_label = "Paintmaps"
|
|
bl_parent_id = "PHYSICS_PT_dp_canvas_output"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_output_maps(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw_header(self, context):
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
self.layout.prop(surface, "use_output_a", text="")
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
sub = layout.column()
|
|
sub.active = surface.use_output_a
|
|
sub.prop(surface, "output_name_a", text="Name")
|
|
|
|
|
|
class PHYSICS_PT_dp_canvas_output_wetmaps(PhysicButtonsPanel, Panel):
|
|
bl_label = "Wetmaps"
|
|
bl_parent_id = "PHYSICS_PT_dp_canvas_output"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_output_maps(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw_header(self, context):
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
self.layout.prop(surface, "use_output_b", text="")
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
sub = layout.column()
|
|
sub.active = surface.use_output_b
|
|
sub.prop(surface, "output_name_b", text="Name")
|
|
|
|
|
|
class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel):
|
|
bl_label = "Initial Color"
|
|
bl_parent_id = "PHYSICS_PT_dynamic_paint"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas_paint(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
ob = context.object
|
|
|
|
layout.use_property_split = True
|
|
|
|
col = layout.column()
|
|
col.prop(surface, "init_color_type", text="Type", expand=False)
|
|
|
|
if surface.init_color_type != 'NONE':
|
|
col.separator()
|
|
|
|
# dissolve
|
|
if surface.init_color_type == 'COLOR':
|
|
layout.prop(surface, "init_color")
|
|
|
|
elif surface.init_color_type == 'TEXTURE':
|
|
col.prop(surface, "init_texture")
|
|
col.prop_search(surface, "init_layername", ob.data, "uv_layers", text="UV Map")
|
|
|
|
elif surface.init_color_type == 'VERTEX_COLOR':
|
|
col.prop_search(surface, "init_layername", ob.data, "vertex_colors", text="Color Layer")
|
|
|
|
|
|
class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
|
|
bl_label = "Effects"
|
|
bl_parent_id = "PHYSICS_PT_dynamic_paint"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas_paint(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, _context):
|
|
return # do nothing.
|
|
|
|
|
|
class PHYSICS_PT_dp_effects_spread(PhysicButtonsPanel, Panel):
|
|
bl_label = "Spread"
|
|
bl_parent_id = "PHYSICS_PT_dp_effects"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_paint(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw_header(self, context):
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
self.layout.prop(surface, "use_spread", 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)
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
layout.active = surface.use_spread
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "spread_speed", text="Speed")
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "color_spread_speed", text="Color")
|
|
|
|
|
|
class PHYSICS_PT_dp_effects_drip(PhysicButtonsPanel, Panel):
|
|
bl_label = "Drip"
|
|
bl_parent_id = "PHYSICS_PT_dp_effects"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_paint(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw_header(self, context):
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
self.layout.prop(surface, "use_drip", 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)
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
flow.active = surface.use_drip
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "drip_velocity", slider=True)
|
|
|
|
col = flow.column()
|
|
col.prop(surface, "drip_acceleration", slider=True)
|
|
|
|
|
|
class PHYSICS_PT_dp_effects_drip_weights(PhysicButtonsPanel, Panel):
|
|
bl_label = "Weights"
|
|
bl_parent_id = "PHYSICS_PT_dp_effects_drip"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_paint(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
layout.active = surface.use_drip
|
|
|
|
effector_weights_ui(self, surface.effector_weights, 'DYNAMIC_PAINT')
|
|
|
|
|
|
class PHYSICS_PT_dp_effects_shrink(PhysicButtonsPanel, Panel):
|
|
bl_label = "Shrink"
|
|
bl_parent_id = "PHYSICS_PT_dp_effects"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_paint(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw_header(self, context):
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
|
|
self.layout.prop(surface, "use_shrink", text="")
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
canvas = context.dynamic_paint.canvas_settings
|
|
surface = canvas.canvas_surfaces.active
|
|
layout.active = surface.use_shrink
|
|
|
|
layout.prop(surface, "shrink_speed", text="Speed")
|
|
|
|
|
|
class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
|
|
bl_label = "Cache"
|
|
bl_parent_id = "PHYSICS_PT_dynamic_paint"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas(context):
|
|
return False
|
|
|
|
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
|
|
return (surface.is_cache_user and (context.engine in cls.COMPAT_ENGINES))
|
|
|
|
def draw(self, context):
|
|
surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
|
|
cache = surface.point_cache
|
|
|
|
point_cache_ui(self, cache, (cache.is_baked is False), 'DYNAMIC_PAINT')
|
|
|
|
|
|
class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
|
|
bl_label = "Source"
|
|
bl_parent_id = "PHYSICS_PT_dynamic_paint"
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
brush = context.dynamic_paint.brush_settings
|
|
ob = context.object
|
|
|
|
layout.prop(brush, "paint_source", text="Paint")
|
|
|
|
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
|
|
|
if brush.paint_source == 'PARTICLE_SYSTEM':
|
|
col = flow.column()
|
|
|
|
col.separator()
|
|
|
|
col.prop_search(brush, "particle_system", ob, "particle_systems")
|
|
|
|
if brush.particle_system:
|
|
col = flow.column()
|
|
|
|
sub = col.column()
|
|
sub.active = not brush.use_particle_radius
|
|
sub.prop(brush, "solid_radius", text="Effect Solid Radius")
|
|
|
|
col.prop(brush, "use_particle_radius", text="Use Particle's Radius")
|
|
col.prop(brush, "smooth_radius", text="Smooth Radius")
|
|
|
|
if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'}:
|
|
col = flow.column()
|
|
|
|
col.separator()
|
|
|
|
col.prop(brush, "paint_distance", text="Distance")
|
|
col.prop(brush, "proximity_falloff")
|
|
|
|
if brush.paint_source == 'VOLUME_DISTANCE':
|
|
col.prop(brush, "invert_proximity")
|
|
|
|
col = flow.column()
|
|
col.prop(brush, "use_negative_volume")
|
|
|
|
if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE'}:
|
|
col = flow.column() if brush.paint_source != 'VOLUME_DISTANCE' else col.column()
|
|
col.prop(brush, "use_proximity_project")
|
|
|
|
sub = col.column()
|
|
sub.active = brush.use_proximity_project
|
|
sub.prop(brush, "ray_direction")
|
|
|
|
|
|
class PHYSICS_PT_dp_brush_source_color_ramp(PhysicButtonsPanel, Panel):
|
|
bl_label = "Falloff Ramp"
|
|
bl_parent_id = "PHYSICS_PT_dp_brush_source"
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
|
|
return False
|
|
|
|
brush = context.dynamic_paint.brush_settings
|
|
return ((brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'})
|
|
and (brush.proximity_falloff == 'RAMP')
|
|
and (context.engine in cls.COMPAT_ENGINES))
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
brush = context.dynamic_paint.brush_settings
|
|
layout.prop(brush, "use_proximity_ramp_alpha", text="Only Use Alpha")
|
|
|
|
layout.use_property_split = False
|
|
layout.template_color_ramp(brush, "paint_ramp", expand=True)
|
|
|
|
|
|
class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel):
|
|
bl_label = "Velocity"
|
|
bl_parent_id = "PHYSICS_PT_dynamic_paint"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
|
|
|
brush = context.dynamic_paint.brush_settings
|
|
|
|
col = flow.column()
|
|
col.prop(brush, "use_velocity_alpha")
|
|
col.prop(brush, "use_velocity_color")
|
|
|
|
col = flow.column()
|
|
col.prop(brush, "use_velocity_depth")
|
|
sub = col.column()
|
|
sub.active = (brush.use_velocity_alpha or brush.use_velocity_color or brush.use_velocity_depth)
|
|
sub.prop(brush, "velocity_max")
|
|
|
|
|
|
class PHYSICS_PT_dp_brush_velocity_color_ramp(PhysicButtonsPanel, Panel):
|
|
bl_label = "Ramp"
|
|
bl_parent_id = "PHYSICS_PT_dp_brush_velocity"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
brush = context.dynamic_paint.brush_settings
|
|
|
|
layout.template_color_ramp(brush, "velocity_ramp", expand=True)
|
|
|
|
|
|
class PHYSICS_PT_dp_brush_velocity_smudge(PhysicButtonsPanel, Panel):
|
|
bl_label = "Smudge"
|
|
bl_parent_id = "PHYSICS_PT_dp_brush_velocity"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw_header(self, context):
|
|
brush = context.dynamic_paint.brush_settings
|
|
|
|
self.layout.prop(brush, "use_smudge", text="")
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
brush = context.dynamic_paint.brush_settings
|
|
|
|
layout.active = brush.use_smudge
|
|
layout.prop(brush, "smudge_strength", text="Strength", slider=True)
|
|
|
|
|
|
class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel):
|
|
bl_label = "Waves"
|
|
bl_parent_id = "PHYSICS_PT_dynamic_paint"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
|
|
return False
|
|
|
|
return (context.engine in cls.COMPAT_ENGINES)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
brush = context.dynamic_paint.brush_settings
|
|
|
|
layout.prop(brush, "wave_type", text="Type")
|
|
|
|
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
|
|
|
|
if brush.wave_type != 'REFLECT':
|
|
col = flow.column()
|
|
col.prop(brush, "wave_factor")
|
|
|
|
col = flow.column()
|
|
col.prop(brush, "wave_clamp")
|
|
|
|
|
|
classes = (
|
|
PHYSICS_UL_dynapaint_surfaces,
|
|
PHYSICS_PT_dynamic_paint,
|
|
PHYSICS_PT_dynamic_paint_settings,
|
|
PHYSICS_PT_dp_surface_canvas,
|
|
PHYSICS_PT_dp_surface_canvas_paint_dissolve,
|
|
PHYSICS_PT_dp_surface_canvas_paint_dry,
|
|
PHYSICS_PT_dp_cache,
|
|
PHYSICS_PT_dp_effects,
|
|
PHYSICS_PT_dp_effects_spread,
|
|
PHYSICS_PT_dp_effects_drip,
|
|
PHYSICS_PT_dp_effects_drip_weights,
|
|
PHYSICS_PT_dp_effects_shrink,
|
|
PHYSICS_PT_dp_canvas_initial_color,
|
|
PHYSICS_PT_dp_brush_source,
|
|
PHYSICS_PT_dp_brush_source_color_ramp,
|
|
PHYSICS_PT_dp_brush_velocity,
|
|
PHYSICS_PT_dp_brush_velocity_color_ramp,
|
|
PHYSICS_PT_dp_brush_velocity_smudge,
|
|
PHYSICS_PT_dp_brush_wave,
|
|
PHYSICS_PT_dp_canvas_output,
|
|
PHYSICS_PT_dp_canvas_output_paintmaps,
|
|
PHYSICS_PT_dp_canvas_output_wetmaps,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__": # only for live edit.
|
|
from bpy.utils import register_class
|
|
for cls in classes:
|
|
register_class(cls)
|