Merge remote-tracking branch 'origin/temp-sculpt-colors' into sculpt-dev

This was necassary because sculpt colors is currently broken in master,
and temp-sculpt-colors hasn't been approved for merging to master
yet.
This commit is contained in:
Joseph Eagar 2021-11-08 17:55:19 -08:00
commit 78d62d9be7
51 changed files with 1802 additions and 979 deletions

View File

@ -29,16 +29,12 @@ class MESH_MT_vertex_group_context_menu(Menu):
def draw(self, _context):
layout = self.layout
layout.operator(
"object.vertex_group_sort",
layout.operator("object.vertex_group_sort",
icon='SORTALPHA',
text="Sort by Name",
).sort_type = 'NAME'
layout.operator(
"object.vertex_group_sort",
text="Sort by Name",).sort_type = 'NAME'
layout.operator("object.vertex_group_sort",
icon='BONE_DATA',
text="Sort by Bone Hierarchy",
).sort_type = 'BONE_HIERARCHY'
text="Sort by Bone Hierarchy",).sort_type = 'BONE_HIERARCHY'
layout.separator()
layout.operator("object.vertex_group_copy", icon='DUPLICATE')
layout.operator("object.vertex_group_copy_to_selected")
@ -46,11 +42,9 @@ class MESH_MT_vertex_group_context_menu(Menu):
layout.operator("object.vertex_group_mirror", icon='ARROW_LEFTRIGHT').use_topology = False
layout.operator("object.vertex_group_mirror", text="Mirror Vertex Group (Topology)").use_topology = True
layout.separator()
layout.operator(
"object.vertex_group_remove_from",
layout.operator("object.vertex_group_remove_from",
icon='X',
text="Remove from All Groups",
).use_all_groups = True
text="Remove from All Groups",).use_all_groups = True
layout.operator("object.vertex_group_remove_from", text="Clear Active Group").use_all_verts = True
layout.operator("object.vertex_group_remove", text="Delete All Unlocked Groups").all_unlocked = True
layout.operator("object.vertex_group_remove", text="Delete All Groups").all = True
@ -134,7 +128,8 @@ class MESH_UL_shape_keys(UIList):
class MESH_UL_uvmaps(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
# assert(isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer)))
# assert(isinstance(item, (bpy.types.MeshTexturePolyLayer,
# bpy.types.MeshLoopColorLayer)))
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(item, "name", text="", emboss=False, icon='GROUP_UVS')
icon = 'RESTRICT_RENDER_OFF' if item.active_render else 'RESTRICT_RENDER_ON'
@ -146,7 +141,8 @@ class MESH_UL_uvmaps(UIList):
class MESH_UL_vcols(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
# assert(isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer)))
# assert(isinstance(item, (bpy.types.MeshTexturePolyLayer,
# bpy.types.MeshLoopColorLayer)))
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(item, "name", text="", emboss=False, icon='GROUP_VCOL')
icon = 'RESTRICT_RENDER_OFF' if item.active_render else 'RESTRICT_RENDER_ON'
@ -266,11 +262,7 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
col.operator("object.vertex_group_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("object.vertex_group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
if (
ob.vertex_groups and
(ob.mode == 'EDIT' or
(ob.mode == 'WEIGHT_PAINT' and ob.type == 'MESH' and ob.data.use_paint_mask_vertex))
):
if (ob.vertex_groups and (ob.mode == 'EDIT' or (ob.mode == 'WEIGHT_PAINT' and ob.type == 'MESH' and ob.data.use_paint_mask_vertex))):
row = layout.row()
sub = row.row(align=True)
@ -461,44 +453,6 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
col.operator("mesh.vertex_color_add", icon='ADD', text="")
col.operator("mesh.vertex_color_remove", icon='REMOVE', text="")
class DATA_PT_sculpt_vertex_colors(MeshButtonsPanel, Panel):
bl_label = "Sculpt Vertex Colors"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
return super().poll(context) and context.preferences.experimental.use_sculpt_vertex_colors
def draw(self, context):
layout = self.layout
me = context.mesh
row = layout.row()
col = row.column()
col.template_list(
"MESH_UL_vcols",
"svcols",
me,
"sculpt_vertex_colors",
me.sculpt_vertex_colors,
"active_index",
rows=2,
)
col = row.column(align=True)
col.operator("mesh.sculpt_vertex_color_add", icon='ADD', text="")
col.operator("mesh.sculpt_vertex_color_remove", icon='REMOVE', text="")
row = layout.row()
col = row.column()
col.operator("sculpt.vertex_to_loop_colors", text="Store Sculpt Vertex Color")
col.operator("sculpt.loop_to_vertex_colors", text="Load Sculpt Vertex Color")
class DATA_PT_remesh(MeshButtonsPanel, Panel):
bl_label = "Remesh"
bl_options = {'DEFAULT_CLOSED'}
@ -522,9 +476,9 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
col.prop(mesh, "use_remesh_preserve_materials", text="Materials")
if context.preferences.experimental.use_sculpt_vertex_colors:
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
col.operator("object.voxel_remesh", text="Voxel Remesh")
else:
@ -601,20 +555,24 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
row = layout.row()
col = row.column()
col.template_list(
"MESH_UL_attributes",
col.template_list("MESH_UL_attributes",
"attributes",
mesh,
"attributes",
mesh.attributes,
"active_index",
rows=3,
)
rows=3,)
col = row.column(align=True)
col.operator("geometry.attribute_add", icon='ADD', text="")
col.operator("geometry.attribute_remove", icon='REMOVE', text="")
active = mesh.attributes.active
if active and (active.domain == "POINT" and active.data_type == "FLOAT_COLOR"):
layout.operator("sculpt.vertex_to_loop_colors", text="Save To Corners")
layout.operator("sculpt.loop_to_vertex_colors", text="Load From Corners")
self.draw_attribute_warnings(context, layout)
def draw_attribute_warnings(self, context, layout):
@ -649,8 +607,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
layout.label(text="Name collisions: {}".format(", ".join(colliding_names)), icon='ERROR')
classes = (
MESH_MT_vertex_group_context_menu,
classes = (MESH_MT_vertex_group_context_menu,
MESH_MT_shape_key_context_menu,
MESH_UL_vgroups,
MESH_UL_fmaps,
@ -663,15 +620,13 @@ classes = (
DATA_PT_shape_keys,
DATA_PT_uv_texture,
DATA_PT_vertex_colors,
DATA_PT_sculpt_vertex_colors,
DATA_PT_face_maps,
DATA_PT_mesh_attributes,
DATA_PT_normals,
DATA_PT_texture_space,
DATA_PT_remesh,
DATA_PT_customdata,
DATA_PT_custom_props_mesh,
)
DATA_PT_custom_props_mesh,)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class

View File

@ -1163,10 +1163,6 @@ class _defs_sculpt:
exclude_filter = {}
# Use 'bpy.context' instead of 'context' since it can be None.
prefs = bpy.context.preferences
if not prefs.experimental.use_sculpt_vertex_colors:
exclude_filter = {'PAINT' : True, 'SMEAR' : True}
if not prefs.experimental.use_sculpt_uvsmooth:
exclude_filter['UV_SMOOTH'] = True
return generate_from_enum_ex(context,
idname_prefix="builtin_brush.",
@ -2592,11 +2588,11 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_sculpt.cloth_filter,
_defs_sculpt.ipmask_filter,
lambda context: ((_defs_sculpt.color_filter,)
if context is None or (context.preferences.view.show_developer_ui and context.preferences.experimental.use_sculpt_vertex_colors)
if context is None
else ()),
None,
lambda context: ((_defs_sculpt.mask_by_color,)
if context is None or (context.preferences.view.show_developer_ui and context.preferences.experimental.use_sculpt_vertex_colors)
if context is None
else ()),
None,
_defs_sculpt.face_set_edit,

View File

@ -29,7 +29,6 @@ from bpy.app.translations import contexts as i18n_contexts
# -----------------------------------------------------------------------------
# Main Header
class USERPREF_HT_header(Header):
bl_space_type = 'PREFERENCES'
@ -43,11 +42,9 @@ class USERPREF_HT_header(Header):
pass
else:
# Show '*' to let users know the preferences have been modified.
layout.operator(
"wm.save_userpref",
layout.operator("wm.save_userpref",
text=iface_("Save Preferences") + (" *" if prefs.is_dirty else ""),
translate=False,
)
translate=False,)
def draw(self, context):
layout = self.layout
@ -64,7 +61,6 @@ class USERPREF_HT_header(Header):
# -----------------------------------------------------------------------------
# Main Navigation Bar
class USERPREF_PT_navigation_bar(Panel):
bl_label = "Preferences Navigation"
bl_space_type = 'PREFERENCES'
@ -187,7 +183,6 @@ class CenterAlignMixIn:
# -----------------------------------------------------------------------------
# Interface Panels
class InterfacePanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -353,7 +348,6 @@ class USERPREF_PT_interface_menus_pie(InterfacePanel, CenterAlignMixIn, Panel):
# -----------------------------------------------------------------------------
# Editing Panels
class EditingPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -400,7 +394,8 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
col.prop(edit, "use_duplicate_armature", text="Armature")
col.prop(edit, "use_duplicate_camera", text="Camera")
col.prop(edit, "use_duplicate_curve", text="Curve")
# col.prop(edit, "use_duplicate_fcurve", text="F-Curve") # Not implemented.
# col.prop(edit, "use_duplicate_fcurve", text="F-Curve") # Not
# implemented.
col.prop(edit, "use_duplicate_grease_pencil", text="Grease Pencil")
if hasattr(edit, "use_duplicate_hair"):
col.prop(edit, "use_duplicate_hair", text="Hair")
@ -420,7 +415,8 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
col.prop(edit, "use_duplicate_speaker", text="Speaker")
col.prop(edit, "use_duplicate_surface", text="Surface")
col.prop(edit, "use_duplicate_text", text="Text")
# col.prop(edit, "use_duplicate_texture", text="Texture") # Not implemented.
# col.prop(edit, "use_duplicate_texture", text="Texture") # Not
# implemented.
col.prop(edit, "use_duplicate_volume", text="Volume")
@ -493,7 +489,6 @@ class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel):
# -----------------------------------------------------------------------------
# Animation Panels
class AnimationPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -556,7 +551,6 @@ class USERPREF_PT_animation_fcurves(AnimationPanel, CenterAlignMixIn, Panel):
# -----------------------------------------------------------------------------
# System Panels
class SystemPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -607,8 +601,6 @@ class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel):
# if hasattr(system, "opensubdiv_compute_type"):
# col.label(text="OpenSubdiv compute:")
# col.row().prop(system, "opensubdiv_compute_type", text="")
class USERPREF_PT_system_os_settings(SystemPanel, CenterAlignMixIn, Panel):
bl_label = "Operating System Settings"
@ -683,7 +675,6 @@ class USERPREF_PT_system_video_sequencer(SystemPanel, CenterAlignMixIn, Panel):
# -----------------------------------------------------------------------------
# Viewport Panels
class ViewportPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -762,7 +753,6 @@ class USERPREF_PT_viewport_selection(ViewportPanel, CenterAlignMixIn, Panel):
# -----------------------------------------------------------------------------
# Theme Panels
class ThemePanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -774,10 +764,8 @@ class USERPREF_MT_interface_theme_presets(Menu):
preset_subdir = "interface_theme"
preset_operator = "script.execute_preset"
preset_type = 'XML'
preset_xml_map = (
("preferences.themes[0]", "Theme"),
("preferences.ui_styles[0]", "ThemeStyle"),
)
preset_xml_map = (("preferences.themes[0]", "Theme"),
("preferences.ui_styles[0]", "ThemeStyle"),)
draw = Menu.draw_preset
@staticmethod
@ -937,8 +925,7 @@ class USERPREF_PT_theme_interface_transparent_checker(ThemePanel, CenterAlignMix
theme = context.preferences.themes[0]
ui = theme.user_interface
flow = layout.grid_flow(
row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow.prop(ui, "transparent_checker_primary")
flow.prop(ui, "transparent_checker_secondary")
@ -1178,8 +1165,7 @@ class ThemeGenericClassGenerator:
@staticmethod
def generate_panel_classes_for_wcols():
wcols = [
("Regular", "wcol_regular"),
wcols = [("Regular", "wcol_regular"),
("Tool", "wcol_tool"),
("Toolbar Item", "wcol_toolbar_item"),
("Radio Buttons", "wcol_radio"),
@ -1198,8 +1184,7 @@ class ThemeGenericClassGenerator:
("Scroll Bar", "wcol_scroll"),
("Progress Bar", "wcol_progress"),
("List Item", "wcol_list_item"),
("Tab", "wcol_tab"),
]
("Tab", "wcol_tab"),]
for (name, wcol) in wcols:
panel_id = "USERPREF_PT_theme_interface_" + wcol
@ -1244,12 +1229,10 @@ class ThemeGenericClassGenerator:
"datapath": new_datapath,
})
yield from generate_child_panel_classes_recurse(
panel_id,
yield from generate_child_panel_classes_recurse(panel_id,
prop.fixed_type,
theme_area,
new_datapath,
)
new_datapath,)
yield from generate_child_panel_classes_recurse(parent_id, rna_type, theme_area, datapath)
@ -1273,8 +1256,7 @@ class ThemeGenericClassGenerator:
"datapath": theme_area.identifier.lower(),
})
yield from ThemeGenericClassGenerator.generate_theme_area_child_panel_classes(
panel_id, Theme.bl_rna.properties[theme_area.identifier.lower()].fixed_type,
yield from ThemeGenericClassGenerator.generate_theme_area_child_panel_classes(panel_id, Theme.bl_rna.properties[theme_area.identifier.lower()].fixed_type,
theme_area, theme_area.identifier.lower())
@ -1427,7 +1409,6 @@ class USERPREF_PT_file_paths_asset_libraries(FilePathsPanel, Panel):
# -----------------------------------------------------------------------------
# Save/Load Panels
class SaveLoadPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -1494,7 +1475,6 @@ class USERPREF_PT_saveload_file_browser(SaveLoadPanel, CenterAlignMixIn, Panel):
# -----------------------------------------------------------------------------
# Input Panels
class InputPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -1572,7 +1552,6 @@ class USERPREF_PT_input_ndof(InputPanel, CenterAlignMixIn, Panel):
# -----------------------------------------------------------------------------
# Navigation Panels
class NavigationPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -1725,20 +1704,16 @@ class USERPREF_PT_ndof_settings(Panel):
layout.separator()
row = layout.row(heading=("Invert Axis Pan" if show_3dview_settings else "Invert Pan Axis"))
for text, attr in (
("X", "ndof_panx_invert_axis"),
for text, attr in (("X", "ndof_panx_invert_axis"),
("Y", "ndof_pany_invert_axis"),
("Z", "ndof_panz_invert_axis"),
):
("Z", "ndof_panz_invert_axis"),):
row.prop(props, attr, text=text, toggle=True)
if show_3dview_settings:
row = layout.row(heading="Orbit")
for text, attr in (
("X", "ndof_rotx_invert_axis"),
for text, attr in (("X", "ndof_rotx_invert_axis"),
("Y", "ndof_roty_invert_axis"),
("Z", "ndof_rotz_invert_axis"),
):
("Z", "ndof_rotz_invert_axis"),):
row.prop(props, attr, text=text, toggle=True)
layout.separator()
@ -1758,8 +1733,6 @@ class USERPREF_PT_ndof_settings(Panel):
# -----------------------------------------------------------------------------
# Key-Map Editor Panels
class KeymapPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -1796,7 +1769,6 @@ class USERPREF_PT_keymap(KeymapPanel, Panel):
# -----------------------------------------------------------------------------
# Add-On Panels
class AddOnPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -1818,10 +1790,8 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
import os
if not user_addon_paths:
for path in (
bpy.utils.script_path_user(),
bpy.utils.script_path_pref(),
):
for path in (bpy.utils.script_path_user(),
bpy.utils.script_path_pref(),):
if path is not None:
user_addon_paths.append(os.path.join(path, "addons"))
@ -1850,13 +1820,9 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
prefs = context.preferences
used_ext = {ext.module for ext in prefs.addons}
addon_user_dirs = tuple(
p for p in (
os.path.join(prefs.filepaths.script_directory, "addons"),
bpy.utils.user_resource('SCRIPTS', path="addons"),
)
if p
)
addon_user_dirs = tuple(p for p in (os.path.join(prefs.filepaths.script_directory, "addons"),
bpy.utils.user_resource('SCRIPTS', path="addons"),)
if p)
# Development option for 2.8x, don't show users bundled addons
# unless they have been updated for 2.8x.
@ -1900,11 +1866,9 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
sub_col.label(text=" " + addon_path)
if addon_utils.error_encoding:
self.draw_error(
col,
self.draw_error(col,
"One or more addons do not have UTF-8 encoding\n"
"(see console for details)",
)
"(see console for details)",)
show_enabled_only = prefs.view.show_addons_enabled_only
filter = wm.addon_filter
@ -1923,29 +1887,18 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
continue
# check if addon should be visible with current filters
is_visible = (
(filter == "All") or
(filter == info["category"]) or
(filter == "User" and (mod.__file__.startswith(addon_user_dirs)))
)
is_visible = ((filter == "All") or (filter == info["category"]) or (filter == "User" and (mod.__file__.startswith(addon_user_dirs))))
if show_enabled_only:
is_visible = is_visible and is_enabled
if is_visible:
if search and not (
(search in info["name"].lower()) or
(info["author"] and (search in info["author"].lower())) or
((filter == "All") and (search in info["category"].lower()))
):
if search and not ((search in info["name"].lower()) or (info["author"] and (search in info["author"].lower())) or ((filter == "All") and (search in info["category"].lower()))):
continue
# Skip 2.7x add-ons included with Blender, unless in debug mode.
# Skip 2.7x add-ons included with Blender, unless in debug
# mode.
is_addon_27x = info.get("blender", (0,)) < (2, 80)
if (
is_addon_27x and
(not show_official_27x_addons) and
(not mod.__file__.startswith(addon_user_dirs))
):
if (is_addon_27x and (not show_official_27x_addons) and (not mod.__file__.startswith(addon_user_dirs))):
continue
# Addon UI Code
@ -1954,24 +1907,21 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
colsub = box.column()
row = colsub.row(align=True)
row.operator(
"preferences.addon_expand",
row.operator("preferences.addon_expand",
icon='DISCLOSURE_TRI_DOWN' if info["show_expanded"] else 'DISCLOSURE_TRI_RIGHT',
emboss=False,
).module = module_name
emboss=False,).module = module_name
row.operator(
"preferences.addon_disable" if is_enabled else "preferences.addon_enable",
row.operator("preferences.addon_disable" if is_enabled else "preferences.addon_enable",
icon='CHECKBOX_HLT' if is_enabled else 'CHECKBOX_DEHLT', text="",
emboss=False,
).module = module_name
emboss=False,).module = module_name
sub = row.row()
sub.active = is_enabled
sub.label(text="%s: %s" % (info["category"], info["name"]))
# WARNING: 2.8x exception, may be removed
# use disabled state for old add-ons, chances are they are broken.
# use disabled state for old add-ons, chances are they are
# broken.
if is_addon_27x:
sub.label(text="Upgrade to 2.8x required")
sub.label(icon='ERROR')
@ -2017,29 +1967,19 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
split.label(text="Internet:")
sub = split.row()
if info["doc_url"]:
sub.operator(
"wm.url_open", text="Documentation", icon='HELP',
).url = info["doc_url"]
sub.operator("wm.url_open", text="Documentation", icon='HELP',).url = info["doc_url"]
# Only add "Report a Bug" button if tracker_url is set
# or the add-on is bundled (use official tracker then).
if info.get("tracker_url"):
sub.operator(
"wm.url_open", text="Report a Bug", icon='URL',
).url = info["tracker_url"]
sub.operator("wm.url_open", text="Report a Bug", icon='URL',).url = info["tracker_url"]
elif not user_addon:
addon_info = (
"Name: %s %s\n"
"Author: %s\n"
) % (info["name"], str(info["version"]), info["author"])
props = sub.operator(
"wm.url_open_preset", text="Report a Bug", icon='URL',
)
addon_info = ("Name: %s %s\n"
"Author: %s\n") % (info["name"], str(info["version"]), info["author"])
props = sub.operator("wm.url_open_preset", text="Report a Bug", icon='URL',)
props.type = 'BUG_ADDON'
props.id = addon_info
if user_addon:
sub.operator(
"preferences.addon_remove", text="Remove", icon='CANCEL',
).module = mod.__name__
sub.operator("preferences.addon_remove", text="Remove", icon='CANCEL',).module = mod.__name__
# Show addon user preferences
if is_enabled:
@ -2079,16 +2019,13 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
row.label(text="", icon='ERROR')
if is_enabled:
row.operator(
"preferences.addon_disable", icon='CHECKBOX_HLT', text="", emboss=False,
).module = module_name
row.operator("preferences.addon_disable", icon='CHECKBOX_HLT', text="", emboss=False,).module = module_name
row.label(text=module_name, translate=False)
# -----------------------------------------------------------------------------
# Studio Light Panels
class StudioLightPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -2218,7 +2155,6 @@ class USERPREF_PT_studiolight_light_editor(StudioLightPanel, Panel):
# -----------------------------------------------------------------------------
# Experimental Panels
class ExperimentalPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
@ -2276,28 +2212,19 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
bl_label = "New Features"
def draw(self, context):
self._draw_items(
context, (
({"property": "use_sculpt_vertex_colors"}, "T71947"),
({"property": "use_sculpt_uvsmooth"}, ""),
({"property": "use_sculpt_tools_tilt"}, "T82877"),
self._draw_items(context, (({"property": "use_sculpt_tools_tilt"}, "T82877"),
({"property": "use_extended_asset_browser"}, ("project/view/130/", "Project Page")),
({"property": "use_override_templates"}, ("T73318", "Milestone 4")),
),
)
({"property": "use_sculpt_uvsmooth"}, ""),),)
class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
bl_label = "Prototypes"
def draw(self, context):
self._draw_items(
context, (
({"property": "use_new_hair_type"}, "T68981"),
self._draw_items(context, (({"property": "use_new_hair_type"}, "T68981"),
({"property": "use_new_point_cloud_type"}, "T75717"),
({"property": "use_full_frame_compositor"}, "T88150"),
),
)
({"property": "use_full_frame_compositor"}, "T88150"),),)
class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
@ -2305,20 +2232,17 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
@classmethod
def poll(cls, _context):
# Unlike the other experimental panels, the debugging one is always visible
# Unlike the other experimental panels, the debugging one is always
# visible
# even in beta or release.
return True
def draw(self, context):
self._draw_items(
context, (
({"property": "use_undo_legacy"}, "T60695"),
self._draw_items(context, (({"property": "use_undo_legacy"}, "T60695"),
({"property": "override_auto_resync"}, "T83811"),
({"property": "proxy_to_override_auto_conversion"}, "T91671"),
({"property": "use_cycles_debug"}, None),
({"property": "use_geometry_nodes_legacy"}, "T91274"),
),
)
({"property": "use_geometry_nodes_legacy"}, "T91274"),),)
# -----------------------------------------------------------------------------
@ -2326,8 +2250,7 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
# Order of registration defines order in UI,
# so dynamically generated classes are 'injected' in the intended order.
classes = (
USERPREF_PT_theme_user_interface,
classes = (USERPREF_PT_theme_user_interface,
*ThemeGenericClassGenerator.generate_panel_classes_for_wcols(),
USERPREF_HT_header,
USERPREF_PT_navigation_bar,
@ -2422,8 +2345,7 @@ classes = (
# Add dynamically generated editor theme panels last,
# so they show up last in the theme section.
*ThemeGenericClassGenerator.generate_panel_classes_from_theme_areas(),
)
*ThemeGenericClassGenerator.generate_panel_classes_from_theme_areas(),)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class

View File

@ -1212,8 +1212,7 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
col.prop(mesh, "use_remesh_preserve_materials", text="Materials")
if context.preferences.experimental.use_sculpt_vertex_colors:
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
layout.operator("object.voxel_remesh", text="Remesh")

View File

@ -58,6 +58,7 @@ struct BlendExpander;
struct Brush;
struct Sculpt;
struct LibraryForeachIDData;
struct UnifiedPaintSettings;
#define MAKE_BUILTIN_CH_NAME(idname) BRUSH_BUILTIN_##idname

View File

@ -76,7 +76,12 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type);
int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type);
#define DT_DATATYPE_IS_VERT(_dt) \
ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_SKIN, DT_TYPE_BWEIGHT_VERT, DT_TYPE_PROPCOL)
ELEM(_dt, \
DT_TYPE_MDEFORMVERT, \
DT_TYPE_SHAPEKEY, \
DT_TYPE_SKIN, \
DT_TYPE_BWEIGHT_VERT, \
DT_TYPE_PROPCOL)
#define DT_DATATYPE_IS_EDGE(_dt) \
ELEM(_dt, \
DT_TYPE_CREASE, \

View File

@ -651,6 +651,11 @@ typedef struct SculptSession {
struct KeyBlock *shapekey_active;
struct MPropCol *vcol;
struct MLoopCol *mcol;
int vcol_domain;
int vcol_type;
float *vmask;
/* Mesh connectivity maps. */

View File

@ -26,6 +26,7 @@
#include "BLI_ghash.h"
/* For embedding CCGKey in iterator. */
#include "BKE_attribute.h"
#include "BKE_ccg.h"
#include <stdint.h>
@ -300,6 +301,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
unsigned int **grid_hidden,
bool fast_draw);
void BKE_pbvh_build_bmesh(PBVH *pbvh,
struct Mesh *me,
struct BMesh *bm,
bool smooth_shading,
struct BMLog *log,
@ -618,7 +620,6 @@ typedef struct PBVHVertexIter {
struct MVert *mverts;
int totvert;
const int *vert_indices;
struct MPropCol *vcol;
float *vmask;
/* bmesh */
@ -639,7 +640,6 @@ typedef struct PBVHVertexIter {
short *no;
float *fno;
float *mask;
float *col;
bool visible;
} PBVHVertexIter;
@ -699,9 +699,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
if (vi.vmask) { \
vi.mask = &vi.vmask[vi.index]; \
} \
if (vi.vcol) { \
vi.col = vi.vcol[vi.index].color; \
} \
} \
else { \
BMVert *bv = NULL; \
@ -726,10 +723,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
continue; \
} \
vi.bm_vert = bv; \
if (vi.cd_vcol_offset >= 0) { \
MPropCol *vcol = BM_ELEM_CD_GET_VOID_P(bv, vi.cd_vcol_offset); \
vi.col = vcol->color; \
} \
vi.vertex.i = (intptr_t)bv; \
vi.index = BM_elem_index_get(vi.bm_vert); \
vi.visible = !BM_elem_flag_test_bool(vi.bm_vert, BM_ELEM_HIDDEN); \
@ -785,6 +778,12 @@ struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh);
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node);
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh);
/* updates pbvh->vcol_domain, vcol_type too */
bool BKE_pbvh_get_color_layer(PBVH *pbvh,
const struct Mesh *me,
CustomDataLayer **cl_out,
AttributeDomain *attr_out);
int BKE_pbvh_get_node_index(PBVH *pbvh, PBVHNode *node);
int BKE_pbvh_get_node_id(PBVH *pbvh, PBVHNode *node);
void BKE_pbvh_set_flat_vcol_shading(PBVH *pbvh, bool value);
@ -1049,3 +1048,5 @@ void BKE_dyntopo_remesh(DynTopoState *ds,
DynRemeshParams *params,
int steps,
PBVHTopologyUpdateMode mode);
void BKE_pbvh_bmesh_get_vcol(
struct BMVert *v, float color[4], int vcol_type, int vcol_domain, int vcol_offset);

View File

@ -2063,6 +2063,8 @@ void BKE_brush_sculpt_reset(Brush *br)
zero_v3(br->rgb);
disable_dyntopo = true;
add_v3_fl(br->rgb, 1.0f);
zero_v3(br->secondary_rgb);
break;
case SCULPT_TOOL_SMEAR:
br->alpha = 1.0f;

View File

@ -46,6 +46,7 @@
#include "BLT_translation.h"
#include "BKE_attribute.h"
#include "BKE_brush.h"
#include "BKE_ccg.h"
#include "BKE_colortools.h"
@ -80,13 +81,13 @@
#include "bmesh.h"
// XXX todo: figure out bad cross module refs
// TODO: figure out bad cross module refs
void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me);
void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
void SCULPT_dyntopo_node_layers_add(SculptSession *ss);
void SCULPT_dyntopo_node_layers_add(SculptSession *ss, Object *ob);
BMesh *SCULPT_dyntopo_empty_bmesh();
void SCULPT_undo_ensure_bmlog(Object *ob);
void SCULPT_update_customdata_refs(SculptSession *ss);
void SCULPT_update_customdata_refs(SculptSession *ss, Object *ob);
static void init_mdyntopo_layer(SculptSession *ss, PBVH *pbvh, int totvert);
@ -1533,12 +1534,13 @@ void BKE_sculptsession_free(Object *ob)
MEM_SAFE_FREE(ss->texcache);
bool SCULPT_temp_customlayer_release(SculptSession * ss, struct SculptCustomLayer * scl);
bool SCULPT_temp_customlayer_release(
SculptSession * ss, Object * ob, struct SculptCustomLayer * scl);
if (ss->layers_to_free) {
for (int i = 0; i < ss->tot_layers_to_free; i++) {
if (ss->layers_to_free[i]) {
SCULPT_temp_customlayer_release(ss, ss->layers_to_free[i]);
SCULPT_temp_customlayer_release(ss, ob, ss->layers_to_free[i]);
// SCULPT_temp_customlayer_release frees layers_to_free[i] itself
}
}
@ -1747,7 +1749,6 @@ static void sculpt_update_object(Depsgraph *depsgraph,
ss->multires.modifier = NULL;
ss->multires.level = 0;
ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
ss->vcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
ss->totloops = me->totloop;
ss->totedges = me->totedge;
@ -1756,6 +1757,27 @@ static void sculpt_update_object(Depsgraph *depsgraph,
ss->edata = &me->edata;
ss->ldata = &me->ldata;
ss->pdata = &me->pdata;
CustomDataLayer *cl;
AttributeDomain domain;
ss->vcol = NULL;
ss->mcol = NULL;
if (BKE_pbvh_get_color_layer(ss->pbvh, me, &cl, &domain)) {
if (cl->type == CD_PROP_COLOR) {
ss->vcol = cl->data;
}
else {
ss->mcol = cl->data;
}
ss->vcol_domain = domain;
ss->vcol_type = cl->type;
}
else {
ss->vcol_type = -1;
}
}
/* Sculpt Face Sets. */
@ -1877,7 +1899,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
if (idx == -1) {
BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_SHAPEKEY, key->name);
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
idx = CustomData_get_named_layer_index(&ss->bm->vdata, CD_SHAPEKEY, key->name);
ss->bm->vdata.layers[idx].uid = key->uid;
@ -1923,7 +1945,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
int cd_co = ss->bm->vdata.layers[idx].offset;
ss->bm->vdata.layers[idx].uid = newkey->uid;
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
float *keyco = BM_ELEM_CD_GET_VOID_P(v, cd_co);
@ -2010,18 +2032,54 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval)
void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
{
Mesh *orig_me = BKE_object_get_original_mesh(object);
if (!U.experimental.use_sculpt_vertex_colors) {
return;
int types[] = {CD_PROP_COLOR, CD_MLOOPCOL};
bool has_color = false;
for (int i = 0; i < 3; i++) {
bool ok = CustomData_has_layer(&orig_me->vdata, types[i]);
ok = ok || CustomData_has_layer(&orig_me->ldata, types[i]);
if (ok) {
has_color = true;
break;
}
}
if (CustomData_has_layer(&orig_me->vdata, CD_PROP_COLOR)) {
return;
CustomDataLayer *cl;
if (has_color) {
cl = BKE_id_attributes_active_get(&orig_me->id);
if (!cl || !ELEM(cl->type, CD_PROP_COLOR, CD_MLOOPCOL)) {
cl = NULL;
/* find a color layer */
for (int step = 0; !cl && step < 2; step++) {
CustomData *cdata = step ? &orig_me->ldata : &orig_me->vdata;
for (int i = 0; i < cdata->totlayer; i++) {
if (ELEM(cdata->layers[i].type, CD_PROP_COLOR, CD_MLOOPCOL)) {
cl = cdata->layers + i;
break;
}
}
}
}
else {
cl = NULL; /* no need to update active layer */
}
}
else {
CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert);
cl = orig_me->vdata.layers + CustomData_get_layer_index(&orig_me->vdata, CD_PROP_COLOR);
BKE_mesh_update_customdata_pointers(orig_me, true);
}
CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert);
BKE_mesh_update_customdata_pointers(orig_me, true);
DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES);
SCULPT_dynamic_topology_sync_layers(object, orig_me);
if (cl) {
BKE_id_attributes_active_set(&orig_me->id, cl);
DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES);
}
}
void BKE_sculpt_update_object_for_edit(
@ -2259,8 +2317,8 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv
const bool is_hidden = (face_sets[face_index] < 0);
/* Avoid creating and modifying the grid_hidden bitmap if the base mesh face is visible and
* there is not bitmap for the grid. This is because missing grid_hidden implies grid is fully
* visible. */
* there is not bitmap for the grid. This is because missing grid_hidden implies grid is
* fully visible. */
if (is_hidden) {
BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg, i);
}
@ -2299,8 +2357,8 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
object->sculpt->face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
/* NOTE: In theory we could add that on the fly when required by sculpt code.
* But this then requires proper update of depsgraph etc. For now we play safe, optimization is
* always possible later if it's worth it. */
* But this then requires proper update of depsgraph etc. For now we play safe, optimization
* is always possible later if it's worth it. */
BKE_sculpt_mask_layers_ensure(object, mmd);
}
@ -2308,8 +2366,8 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
BKE_mesh_tessface_clear(mesh);
/* We always need to flush updates from depsgraph here, since at the very least
* `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer of
* the mesh.
* `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer
* of the mesh.
*
* All known potential sources of updates:
* - Addition of, or changes to, the `CD_SCULPT_FACE_SETS` data layer
@ -2331,6 +2389,7 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
BKE_pbvh_set_symmetry(pbvh, 0, (int)BKE_get_fset_boundary_symflag(ob));
BKE_pbvh_build_bmesh(pbvh,
BKE_object_get_original_mesh(ob),
ob->sculpt->bm,
ob->sculpt->bm_smooth_shading,
ob->sculpt->bm_log,
@ -2576,12 +2635,12 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
.copy_temp_cdlayers = true,
.cd_mask_extra = CD_MASK_DYNTOPO_VERT}));
SCULPT_dyntopo_node_layers_add(ob->sculpt);
SCULPT_dyntopo_node_layers_add(ob->sculpt, ob);
SCULPT_undo_ensure_bmlog(ob);
pbvh = build_pbvh_for_dynamic_topology(ob);
SCULPT_update_customdata_refs(ob->sculpt);
SCULPT_update_customdata_refs(ob->sculpt, ob);
}
else {
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);

View File

@ -33,6 +33,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_attribute.h"
#include "BKE_ccg.h"
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
#include "BKE_mesh_mapping.h"
@ -780,6 +781,10 @@ PBVH *BKE_pbvh_new(void)
{
PBVH *pbvh = MEM_callocN(sizeof(PBVH), "pbvh");
pbvh->respect_hide = true;
pbvh->vcol_type = -1;
pbvh->vcol_domain = ATTR_DOMAIN_NUM;
return pbvh;
}
@ -1365,6 +1370,80 @@ static int pbvh_get_buffers_update_flags(PBVH *UNUSED(pbvh))
return update_flags;
}
/* updates pbvh->vcol_domain, vcol_type too */
ATTR_NO_OPT bool BKE_pbvh_get_color_layer(PBVH *pbvh,
const Mesh *me,
CustomDataLayer **r_cl,
AttributeDomain *r_attr)
{
CustomDataLayer *cl = BKE_id_attributes_active_get((ID *)me);
AttributeDomain domain;
if (!cl || !ELEM(cl->type, CD_PROP_COLOR, CD_MLOOPCOL)) {
if (pbvh) {
pbvh->cd_vcol_offset = pbvh->vcol_type = -1;
pbvh->vcol_domain = (int)ATTR_DOMAIN_NUM;
}
return false;
}
domain = BKE_id_attribute_domain((ID *)me, cl);
if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) {
if (pbvh) {
pbvh->cd_vcol_offset = pbvh->vcol_type = -1;
pbvh->vcol_domain = (int)ATTR_DOMAIN_NUM;
}
return false;
}
if (cl) {
*r_cl = cl;
*r_attr = domain;
if (pbvh && pbvh->bm) {
CustomData *cdata_bm = domain == ATTR_DOMAIN_POINT ? &pbvh->bm->vdata : &pbvh->bm->ldata;
int idx = CustomData_get_named_layer_index(cdata_bm, cl->type, cl->name);
if (!idx) {
/* should never happen, but the edge cases can get pretty crazy in
sculpt code. Delay till the layer exists, typically it's added
by SCULPT_dynamic_topology_sync_layers.*/
pbvh->cd_vcol_offset = pbvh->vcol_type = -1;
pbvh->vcol_domain = (int)ATTR_DOMAIN_NUM;
*r_cl = NULL;
*r_attr = ATTR_DOMAIN_NUM;
return false;
}
pbvh->cd_vcol_offset = cdata_bm->layers[idx].offset;
cl = *r_cl = cdata_bm->layers + idx;
}
if (pbvh) {
pbvh->vcol_domain = domain;
pbvh->vcol_type = cl->type;
}
return true;
}
else {
if (pbvh) {
pbvh->cd_vcol_offset = pbvh->vcol_type = -1;
pbvh->vcol_domain = (int)ATTR_DOMAIN_NUM;
}
*r_cl = NULL;
return false;
}
}
static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
@ -1432,17 +1511,23 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
&pbvh->gridkey,
update_flags);
break;
case PBVH_FACES:
case PBVH_FACES: {
CustomDataLayer *cl = NULL;
AttributeDomain domain;
BKE_pbvh_get_color_layer(pbvh, pbvh->mesh, &cl, &domain);
GPU_pbvh_mesh_buffers_update(node->draw_buffers,
pbvh->verts,
CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK),
CustomData_get_layer(pbvh->ldata, CD_MLOOPCOL),
cl ? cl->data : NULL,
cl ? cl->type : -1,
cl ? domain : ATTR_DOMAIN_AUTO,
CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
pbvh->face_sets_color_seed,
pbvh->face_sets_color_default,
CustomData_get_layer(pbvh->vdata, CD_PROP_COLOR),
update_flags);
break;
} break;
case PBVH_BMESH:
if (BKE_pbvh_bmesh_check_tris(pbvh, node)) {
pbvh_free_all_draw_buffers(node);
@ -1469,18 +1554,22 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
continue;
}
GPU_pbvh_bmesh_buffers_update(node->mat_draw_buffers[i],
pbvh->bm,
node->bm_faces,
node->bm_unique_verts,
node->bm_other_verts,
node->tri_buffers + i,
update_flags,
pbvh->cd_vert_node_offset,
pbvh->face_sets_color_seed,
pbvh->face_sets_color_default,
data->flat_vcol_shading,
node->tri_buffers[i].mat_nr);
PBVHGPUBuildArgs args = {.buffers = node->mat_draw_buffers[i],
.bm = pbvh->bm,
.bm_faces = node->bm_faces,
.bm_unique_verts = node->bm_unique_verts,
.bm_other_verts = node->bm_other_verts,
.tribuf = node->tri_buffers + i,
.update_flags = update_flags,
.cd_vert_node_offset = pbvh->cd_vert_node_offset,
.face_sets_color_seed = pbvh->face_sets_color_seed,
.face_sets_color_default = pbvh->face_sets_color_default,
.flat_vcol = data->flat_vcol_shading,
.mat_nr = node->tri_buffers[i].mat_nr,
.active_vcol_domain = pbvh->vcol_domain,
.active_vcol_type = pbvh->vcol_type};
GPU_pbvh_bmesh_buffers_update(&args);
}
break;
}
@ -1542,8 +1631,6 @@ static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode,
if (pbvh->type == PBVH_BMESH) {
if (pbvh->bm) {
pbvh->cd_vcol_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PROP_COLOR);
vdata = &pbvh->bm->vdata;
ldata = &pbvh->bm->ldata;
}
@ -1556,8 +1643,12 @@ static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode,
ldata = pbvh->ldata;
}
GPU_pbvh_update_attribute_names(
vdata, ldata, GPU_pbvh_need_full_render_get(), pbvh->flags & PBVH_FAST_DRAW);
GPU_pbvh_update_attribute_names(vdata,
ldata,
GPU_pbvh_need_full_render_get(),
pbvh->flags & PBVH_FAST_DRAW,
pbvh->vcol_type,
pbvh->vcol_domain);
if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) {
/* Free buffers uses OpenGL, so not in parallel. */
@ -1629,21 +1720,19 @@ void BKE_pbvh_update_origcolor_bmesh(PBVH *pbvh, PBVHNode *node)
{
PBVHVertexIter vd;
if (!pbvh->bm || pbvh->cd_vcol_offset < 0) {
if (!pbvh->bm || pbvh->vcol_type == -1) {
return;
}
int cd_vcol_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PROP_COLOR);
if (cd_vcol_offset == -1) {
if (pbvh->vcol_type == -1) {
return;
}
BKE_pbvh_vertex_iter_begin (pbvh, node, vd, PBVH_ITER_UNIQUE) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, vd.bm_vert);
float *c2 = BM_ELEM_CD_GET_VOID_P(vd.bm_vert, pbvh->cd_vcol_offset);
copy_v4_v4(mv->origcolor, c2);
BKE_pbvh_bmesh_get_vcol(
vd.bm_vert, mv->origcolor, pbvh->vcol_type, pbvh->vcol_domain, pbvh->cd_vcol_offset);
}
BKE_pbvh_vertex_iter_end;
}
@ -1703,7 +1792,9 @@ void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag)
}
if (flag & (PBVH_UpdateColor)) {
/* Do nothing */
for (int i = 0; i < totnode; i++) {
nodes[i]->flag |= PBVH_UpdateRedraw | PBVH_UpdateDrawBuffers | PBVH_UpdateColor;
}
}
if (flag & (PBVH_UpdateVisibility)) {
@ -3371,7 +3462,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi->grid = NULL;
vi->no = NULL;
vi->col = NULL;
vi->fno = NULL;
vi->mvert = NULL;
vi->vertex.i = 0;
@ -3415,9 +3505,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi->bm_vert = NULL;
vi->cd_sculpt_vert = CustomData_get_offset(vi->bm_vdata, CD_DYNTOPO_VERT);
// we ensure pbvh->cd_vcol_offset is up to date here too
vi->cd_vcol_offset = CustomData_get_offset(vi->bm_vdata, CD_PROP_COLOR);
vi->cd_vert_mask_offset = CustomData_get_offset(vi->bm_vdata, CD_PAINT_MASK);
}
@ -3429,7 +3516,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi->mask = NULL;
if (pbvh->type == PBVH_FACES) {
vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK);
vi->vcol = CustomData_get_layer(pbvh->vdata, CD_PROP_COLOR);
}
}
@ -4197,16 +4283,10 @@ void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
{
MSculptVert *mv = pbvh->mdyntopo_verts + vertex.i;
int last_fset = 0;
int last_fset2 = 0;
mv->flag &= ~(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_NEED_BOUNDARY |
SCULPTVERT_FSET_CORNER | SCULPTVERT_CORNER | SCULPTVERT_SEAM_BOUNDARY |
SCULPTVERT_SHARP_BOUNDARY | SCULPTVERT_SEAM_CORNER | SCULPTVERT_SHARP_CORNER);
int totsharp = 0, totseam = 0;
int visible = false;
int index = (int)vertex.i;
/* TODO: optimize this. We could fill #SculptVertexNeighborIter directly,

View File

@ -809,6 +809,71 @@ void BKE_pbvh_bmesh_regen_node_verts(PBVH *pbvh)
}
}
void BKE_pbvh_bmesh_get_vcol(
BMVert *v, float color[4], int vcol_type, int vcol_domain, int vcol_offset)
{
if (vcol_domain == ATTR_DOMAIN_POINT) {
switch (vcol_offset) {
case CD_PROP_COLOR:
copy_v4_v4(color, (float *)BM_ELEM_CD_GET_VOID_P(v, vcol_offset));
break;
case CD_MLOOPCOL: {
MLoopCol *mp = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(v, vcol_offset);
rgba_uchar_to_float(color, (const char *)mp);
srgb_to_linearrgb_v3_v3(color, color);
break;
}
}
}
else { /*average all loop colors*/
BMEdge *e = v->e;
zero_v4(color);
if (!e) {
return;
}
int tot = 0;
do {
BMLoop *l = e->l;
if (!l) {
continue;
}
do {
switch (vcol_type) {
case CD_PROP_COLOR:
add_v4_v4(color, (float *)BM_ELEM_CD_GET_VOID_P(l, vcol_offset));
tot++;
break;
case CD_MLOOPCOL: {
MLoopCol *mp = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(l, vcol_offset);
float temp[4];
rgba_uchar_to_float(temp, (const char *)mp);
srgb_to_linearrgb_v3_v3(temp, temp);
add_v4_v4(color, temp);
tot++;
break;
}
}
} while ((l = l->radial_next) != e->l);
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
if (tot > 0) {
mul_v4_fl(color, 1.0f / (float)tot);
}
}
}
void BKE_pbvh_bmesh_update_origvert(
PBVH *pbvh, BMVert *v, float **r_co, float **r_no, float **r_color, bool log_undo)
{
@ -838,10 +903,9 @@ void BKE_pbvh_bmesh_update_origvert(
}
}
if (r_color && pbvh->cd_vcol_offset >= 0) {
MPropCol *ml1 = BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_vcol_offset);
copy_v4_v4(mv->origcolor, ml1->color);
if (r_color && pbvh->vcol_type != -1) {
BKE_pbvh_bmesh_get_vcol(
v, mv->origcolor, pbvh->vcol_type, pbvh->vcol_domain, pbvh->cd_vcol_offset);
if (r_color) {
*r_color = mv->origcolor;
@ -1515,8 +1579,6 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
{
MSculptVert *mv = BKE_PBVH_SCULPTVERT(cd_sculpt_vert, v);
float avg[3] = {0.0f, 0.0f, 0.0f};
float avg_len = 0.0f;
float curv = 0.0f, totcurv = 0.0f;
BMEdge *e = v->e;
@ -1581,6 +1643,10 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
}
#ifdef MV_COLOR_BOUNDARY
# error "fix me! need to handle loops too"
#endif
#ifdef MV_COLOR_BOUNDARY // CURRENTLY BROKEN
if (cd_vcol >= 0) {
float *color1 = BM_ELEM_CD_GET_VOID_P(v, cd_vcol);
float *color2 = BM_ELEM_CD_GET_VOID_P(v2, cd_vcol);
@ -1845,6 +1911,7 @@ void BKE_pbvh_update_all_boundary_bmesh(PBVH *pbvh)
}
/* Build a PBVH from a BMesh */
void BKE_pbvh_build_bmesh(PBVH *pbvh,
struct Mesh *me,
BMesh *bm,
bool smooth_shading,
BMLog *log,
@ -1868,7 +1935,6 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
pbvh->type = PBVH_BMESH;
pbvh->bm_log = log;
pbvh->cd_vcol_offset = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
pbvh->cd_faceset_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
pbvh->depth_limit = 18;
@ -1881,8 +1947,6 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
// BKE_pbvh_update_all_boundary_bmesh(pbvh);
int cd_vcol_offset = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
if (smooth_shading) {
pbvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
}
@ -1956,7 +2020,7 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
pbvh->cd_faceset_offset,
pbvh->cd_vert_node_offset,
pbvh->cd_face_node_offset,
pbvh->cd_vcol_offset,
-1,
v,
pbvh->boundary_symmetry);
BKE_pbvh_bmesh_update_valence(pbvh->cd_sculpt_vert, (SculptVertRef){(intptr_t)v});
@ -1964,14 +2028,21 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
copy_v3_v3(mv->origco, v->co);
copy_v3_v3(mv->origno, v->no);
if (cd_vcol_offset >= 0) {
MPropCol *c1 = BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offset);
copy_v4_v4(mv->origcolor, c1->color);
if (pbvh->vcol_type != -1) {
BKE_pbvh_bmesh_get_vcol(
v, mv->origcolor, pbvh->vcol_type, pbvh->vcol_domain, pbvh->cd_vcol_offset);
}
else {
zero_v4(mv->origcolor);
}
}
if (me) { // ensure pbvh->vcol_type, vcol_domain and cd_vcol_offset are up to date
CustomDataLayer *cl;
AttributeDomain domain;
BKE_pbvh_get_color_layer(pbvh, me, &cl, &domain);
}
}
void BKE_pbvh_set_bm_log(PBVH *pbvh, struct BMLog *log)
@ -3510,15 +3581,10 @@ void BKE_pbvh_update_offsets(PBVH *pbvh,
const int cd_sculpt_vert,
const int cd_face_areas)
{
if (pbvh->bm) {
pbvh->cd_vcol_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PROP_COLOR);
}
pbvh->cd_face_node_offset = cd_face_node_offset;
pbvh->cd_vert_node_offset = cd_vert_node_offset;
pbvh->cd_face_area = cd_face_areas;
pbvh->cd_vert_mask_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK);
pbvh->cd_vcol_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PROP_COLOR);
pbvh->cd_sculpt_vert = cd_sculpt_vert;
pbvh->cd_faceset_offset = CustomData_get_offset(&pbvh->bm->pdata, CD_SCULPT_FACE_SETS);
}
@ -5143,8 +5209,16 @@ void pbvh_bmesh_cache_test(CacheParams *params, BMesh **r_bm, PBVH **r_pbvh_out)
BM_mesh_elem_table_ensure(bm, BM_VERT | BM_FACE);
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE | BM_FACE);
BKE_pbvh_build_bmesh(
pbvh, bm, false, bmlog, cd_vert_node, cd_face_node, cd_sculpt_vert, cd_face_area, false);
BKE_pbvh_build_bmesh(pbvh,
NULL,
bm,
false,
bmlog,
cd_vert_node,
cd_face_node,
cd_sculpt_vert,
cd_face_area,
false);
int loop_size = sizeof(BMLoop) - sizeof(void *) * 4;
@ -5543,7 +5617,6 @@ static void pbvh_bmesh_fetch_cdrefs(PBVH *pbvh)
pbvh->cd_face_area = bm->pdata.layers[idx].offset;
pbvh->cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
pbvh->cd_vcol_offset = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
pbvh->cd_faceset_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
pbvh->cd_sculpt_vert = CustomData_get_offset(&bm->vdata, CD_DYNTOPO_VERT);
}

View File

@ -201,9 +201,12 @@ struct PBVH {
int cd_vert_node_offset;
int cd_face_node_offset;
int cd_vert_mask_offset;
int cd_vcol_offset;
int cd_faceset_offset;
int cd_face_area;
int cd_vcol_offset;
int vcol_type;
int vcol_domain;
float planes[6][4];
int num_planes;
@ -372,5 +375,4 @@ BLI_INLINE bool pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v)
}
void pbvh_bmesh_check_other_verts(PBVHNode *node);
//#define DEFRAGMENT_MEMORY

View File

@ -1790,6 +1790,20 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 300, 26)) {
LISTBASE_FOREACH (Brush *, br, &bmain->brushes) {
/* buggy code in wm_toolsystem broke smear in old files,
reset to defaults*/
if (br->sculpt_tool == SCULPT_TOOL_SMEAR) {
br->alpha = 1.0f;
br->spacing = 5;
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE_ATTEN;
br->curve_preset = BRUSH_CURVE_SPHERE;
}
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 300, 23)) {
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {

View File

@ -186,12 +186,7 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd,
geom = DRW_cache_mesh_surface_vertpaint_get(ob);
}
else {
if (U.experimental.use_sculpt_vertex_colors) {
geom = DRW_cache_mesh_surface_sculptcolors_get(ob);
}
else {
geom = DRW_cache_mesh_surface_vertpaint_get(ob);
}
geom = DRW_cache_mesh_surface_sculptcolors_get(ob);
}
}
else {
@ -272,15 +267,13 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
}
}
else if (color_type == V3D_SHADING_VERTEX_COLOR) {
if (U.experimental.use_sculpt_vertex_colors) {
if ((me == NULL) || !CustomData_has_layer(&me->vdata, CD_PROP_COLOR)) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
}
else {
if ((me == NULL) || !CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
bool has_color = me && (CustomData_has_layer(&me->vdata, CD_PROP_COLOR) ||
CustomData_has_layer(&me->vdata, CD_MLOOPCOL) ||
CustomData_has_layer(&me->ldata, CD_PROP_COLOR) ||
CustomData_has_layer(&me->ldata, CD_MLOOPCOL));
if (!has_color) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
}

View File

@ -464,6 +464,10 @@ MeshRenderData *mesh_render_data_create(Mesh *me,
mr->bm = me->edit_mesh->bm;
mr->edit_bmesh = me->edit_mesh;
mr->me = (do_final) ? me->edit_mesh->mesh_eval_final : me->edit_mesh->mesh_eval_cage;
/* needed so correct vcol layer is shown in edit mode */
mr->me->attributes_active_index = me->attributes_active_index;
mr->edit_data = is_mode_active ? mr->me->runtime.edit_data : NULL;
if (mr->edit_data) {

View File

@ -457,15 +457,37 @@ static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd
}
}
static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshAttributes *attrs_used)
static bool mesh_cd_calc_active_vcol_layer(Mesh *me, DRW_MeshAttributes *attrs_used)
{
CustomDataLayer *layer = BKE_id_attributes_active_get((ID *)me);
const Mesh *me_final = editmesh_final_or_this(me);
const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final);
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR);
if (layer != -1) {
drw_mesh_attributes_add_request(attrs_used, CD_PROP_COLOR, layer, ATTR_DOMAIN_POINT);
int type, idx = -1;
AttributeDomain domain;
if (layer && ELEM(layer->type, CD_PROP_COLOR, CD_MLOOPCOL)) {
domain = BKE_id_attribute_domain((ID *)me, layer);
type = layer->type;
idx = CustomData_get_named_layer(
domain == ATTR_DOMAIN_POINT ? cd_vdata : cd_ldata, type, layer->name);
}
else {
idx = CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR);
type = CD_PROP_COLOR;
domain = ATTR_DOMAIN_POINT;
}
if (idx != -1) {
if (type != CD_MLOOPCOL) {
drw_mesh_attributes_add_request(attrs_used, type, idx, domain);
}
}
return idx != -1;
}
static void mesh_cd_calc_active_mloopcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
@ -543,6 +565,11 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name);
type = CD_MTFACE;
if (layer == -1) {
layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name);
type = CD_PROP_COLOR;
}
if (layer == -1) {
layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name);
type = CD_MCOL;
@ -617,13 +644,15 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
break;
}
case CD_MCOL: {
const CustomData *cdata = domain == ATTR_DOMAIN_POINT ? cd_vdata : cd_ldata;
/* Vertex Color Data */
if (layer == -1) {
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) :
CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL);
layer = (name[0] != '\0') ? CustomData_get_named_layer(cdata, CD_MLOOPCOL, name) :
CustomData_get_render_layer(cdata, CD_MLOOPCOL);
}
if (layer != -1) {
cd_used.vcol |= (1 << layer);
cd_used.vcol = 1;
}
break;
@ -632,12 +661,15 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
cd_used.orco = 1;
break;
}
case CD_PROP_COLOR:
cd_used.vcol = 1;
/* fallthrough */
case CD_PROP_FLOAT3:
case CD_PROP_BOOL:
case CD_PROP_INT32:
case CD_PROP_FLOAT:
case CD_PROP_FLOAT2:
case CD_PROP_FLOAT3:
case CD_PROP_COLOR: {
case CD_PROP_FLOAT2: {
if (layer != -1 && domain != ATTR_DOMAIN_NUM) {
drw_mesh_attributes_add_request(attributes, type, layer, domain);
}
@ -1107,7 +1139,10 @@ static void sculpt_request_active_vcol(MeshBatchCache *cache, Mesh *me)
{
DRW_MeshAttributes attrs_needed;
drw_mesh_attributes_clear(&attrs_needed);
mesh_cd_calc_active_vcol_layer(me, &attrs_needed);
if (mesh_cd_calc_active_vcol_layer(me, &attrs_needed)) {
cache->cd_used.vcol = 1;
}
BLI_assert(attrs_needed.num_requests != 0 &&
"No MPropCol layer available in Sculpt, but batches requested anyway!");
@ -1133,6 +1168,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
mesh_batch_cache_request_surface_batches(cache);
return cache->batch.surface;
}

View File

@ -42,30 +42,61 @@ static void extract_vcol_init(const MeshRenderData *mr,
GPUVertFormat format = {0};
GPU_vertformat_deinterleave(&format);
CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
uint32_t vcol_layers = cache->cd_used.vcol;
for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i);
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
/*
Note there are two color attribute types that operate over two domains
(verts and face corners).
*/
int vcol_types[2] = {CD_MLOOPCOL, CD_PROP_COLOR};
BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
CustomDataLayer *actlayer = BKE_id_attributes_active_get((ID *)mr->me);
AttributeDomain actdomain = actlayer ? BKE_id_attribute_domain((ID *)mr->me, actlayer) :
ATTR_DOMAIN_AUTO;
int actn = -1;
if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL)) {
GPU_vertformat_alias_add(&format, "c");
}
if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL)) {
GPU_vertformat_alias_add(&format, "ac");
}
/* prefer the active attribute to set active color if it's a color layer */
if (actlayer && ELEM(actlayer->type, CD_PROP_COLOR, CD_MLOOPCOL) &&
ELEM(actdomain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) {
CustomData *cdata = actdomain == ATTR_DOMAIN_POINT ? cd_vdata : cd_ldata;
actn = actlayer - (cdata->layers + cdata->typemap[actlayer->type]);
}
/* Gather number of auto layers. */
/* We only do `vcols` that are not overridden by `uvs`. */
if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) {
BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
GPU_vertformat_alias_add(&format, attr_name);
/* set up vbo format */
for (int i = 0; i < ARRAY_SIZE(vcol_types); i++) {
int type = vcol_types[i];
for (int step = 0; step < 2; step++) {
CustomData *cdata = step ? cd_ldata : cd_vdata;
int count = CustomData_number_of_layers(cdata, type);
AttributeDomain domain = step ? ATTR_DOMAIN_CORNER : ATTR_DOMAIN_POINT;
for (int j = 0; j < count; j++) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *layer_name = CustomData_get_layer_name(cdata, type, j);
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
if (j == CustomData_get_render_layer(cdata, type)) {
GPU_vertformat_alias_add(&format, "c");
}
bool is_active = actn == -1 && j == CustomData_get_active_layer(cdata, type);
is_active |= actn != -1 && domain == actdomain && j == actn && type == actlayer->type;
if (is_active) {
GPU_vertformat_alias_add(&format, "ac");
}
/* Gather number of auto layers. */
/* We only do `vcols` that are not overridden by `uvs`. */
if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) {
BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
GPU_vertformat_alias_add(&format, attr_name);
}
}
}
}
@ -79,32 +110,122 @@ static void extract_vcol_init(const MeshRenderData *mr,
gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo);
for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
if (mr->extract_type == MR_EXTRACT_BMESH) {
int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i);
BMIter f_iter;
BMFace *efa;
BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
do {
const MLoopCol *mloopcol = (const MLoopCol *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
vcol_data++;
} while ((l_iter = l_iter->next) != l_first);
/* build data */
for (int i = 0; i < ARRAY_SIZE(vcol_types); i++) {
int type = vcol_types[i];
for (int step = 0; step < 2; step++) {
CustomData *cdata = step ? cd_ldata : cd_vdata;
int count = CustomData_number_of_layers(cdata, type);
for (int j = 0; j < count; j++) {
int idx = CustomData_get_layer_index_n(cdata, type, j);
if (mr->extract_type == MR_EXTRACT_BMESH) {
BMFace *f;
BMIter iter;
CustomData *cdata_orig = step ? &mr->bm->ldata : &mr->bm->vdata;
int idx_orig = CustomData_get_layer_index_n(cdata_orig, type, j);
int cd_vcol = cdata_orig->layers[idx_orig].offset;
BM_ITER_MESH (f, &iter, mr->bm, BM_FACES_OF_MESH) {
BMLoop *l_iter = BM_FACE_FIRST_LOOP(f);
do {
BMElem *elem = step ? (BMElem *)l_iter : (BMElem *)l_iter->v;
switch (type) {
case CD_PROP_COLOR: {
float *color = (float *)BM_ELEM_CD_GET_VOID_P(elem, cd_vcol);
vcol_data->r = unit_float_to_ushort_clamp(color[0]);
vcol_data->g = unit_float_to_ushort_clamp(color[1]);
vcol_data->b = unit_float_to_ushort_clamp(color[2]);
vcol_data->a = unit_float_to_ushort_clamp(color[3]);
break;
}
case CD_MLOOPCOL: {
float temp[4];
MLoopCol *mloopcol = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(elem, cd_vcol);
rgba_uchar_to_float(temp, (unsigned char *)mloopcol);
srgb_to_linearrgb_v3_v3(temp, temp);
vcol_data->r = unit_float_to_ushort_clamp(temp[0]);
vcol_data->g = unit_float_to_ushort_clamp(temp[1]);
vcol_data->b = unit_float_to_ushort_clamp(temp[2]);
vcol_data->a = unit_float_to_ushort_clamp(temp[3]);
break;
}
}
vcol_data++;
} while ((l_iter = l_iter->next) != BM_FACE_FIRST_LOOP(f));
}
}
}
else {
const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, mloopcol++, vcol_data++) {
vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
else {
switch (type) {
case CD_PROP_COLOR: {
MPropCol *colors = (MPropCol *)cdata->layers[idx].data;
if (step) {
for (int k = 0; k < mr->loop_len; k++, vcol_data++, colors++) {
vcol_data->r = unit_float_to_ushort_clamp(colors->color[0]);
vcol_data->g = unit_float_to_ushort_clamp(colors->color[1]);
vcol_data->b = unit_float_to_ushort_clamp(colors->color[2]);
vcol_data->a = unit_float_to_ushort_clamp(colors->color[3]);
}
}
else {
const MLoop *ml = mr->mloop;
for (int k = 0; k < mr->loop_len; k++, vcol_data++, ml++) {
MPropCol *color = colors + ml->v;
vcol_data->r = unit_float_to_ushort_clamp(color->color[0]);
vcol_data->g = unit_float_to_ushort_clamp(color->color[1]);
vcol_data->b = unit_float_to_ushort_clamp(color->color[2]);
vcol_data->a = unit_float_to_ushort_clamp(color->color[3]);
}
}
break;
}
case CD_MLOOPCOL: {
MLoopCol *colors = (MLoopCol *)cdata->layers[idx].data;
if (step) {
for (int k = 0; k < mr->loop_len; k++, vcol_data++, colors++) {
float temp[4];
rgba_uchar_to_float(temp, (unsigned char *)colors);
srgb_to_linearrgb_v3_v3(temp, temp);
vcol_data->r = unit_float_to_ushort_clamp(temp[0]);
vcol_data->g = unit_float_to_ushort_clamp(temp[1]);
vcol_data->b = unit_float_to_ushort_clamp(temp[2]);
vcol_data->a = unit_float_to_ushort_clamp(temp[3]);
}
}
else {
const MLoop *ml = mr->mloop;
for (int k = 0; k < mr->loop_len; k++, vcol_data++, ml++) {
MLoopCol *color = colors + ml->v;
float temp[4];
rgba_uchar_to_float(temp, (unsigned char *)color);
srgb_to_linearrgb_v3_v3(temp, temp);
vcol_data->r = unit_float_to_ushort_clamp(temp[0]);
vcol_data->g = unit_float_to_ushort_clamp(temp[1]);
vcol_data->b = unit_float_to_ushort_clamp(temp[2]);
vcol_data->a = unit_float_to_ushort_clamp(temp[3]);
}
}
break;
}
}
}
}
}

View File

@ -449,7 +449,7 @@ static bool bake_object_check(ViewLayer *view_layer,
if (target == R_BAKE_TARGET_VERTEX_COLORS) {
MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
const bool mcol_valid = (mcol != NULL && U.experimental.use_sculpt_vertex_colors);
const bool mcol_valid = (mcol != NULL);
MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
if (mloopcol == NULL && !mcol_valid) {
BKE_reportf(reports,
@ -926,7 +926,7 @@ static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, Re
Mesh *me = ob->data;
MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
const bool mcol_valid = (mcol != NULL && U.experimental.use_sculpt_vertex_colors);
const bool mcol_valid = (mcol != NULL);
MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
if (mloopcol == NULL && !mcol_valid) {
BKE_report(reports, RPT_ERROR, "No vertex colors layer found to bake to");
@ -1081,7 +1081,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob)
{
Mesh *me = ob->data;
MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
const bool mcol_valid = (mcol != NULL && U.experimental.use_sculpt_vertex_colors);
const bool mcol_valid = (mcol != NULL);
MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
const int num_channels = targets->num_channels;
const float *result = targets->result;

View File

@ -391,7 +391,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
}
/* End undo. */
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
/* Ensure that edges and faces get hidden as well (not used by
* sculpt but it looks wrong when entering editmode otherwise). */

View File

@ -190,7 +190,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
if (nodes) {
MEM_freeN(nodes);
@ -724,7 +724,7 @@ static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext)
operation->sculpt_gesture_end(C, sgcontext);
SCULPT_undo_push_end();
SCULPT_undo_push_end(CTX_data_active_object(C));
SCULPT_tag_update_overlays(C);
}
@ -1340,7 +1340,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
BMO_op_callf(trimbm, BMO_FLAG_DEFAULTS, "duplicate geom=%avef dest=%p", bm, 3);
SCULPT_update_customdata_refs(sgcontext->ss);
SCULPT_update_customdata_refs(sgcontext->ss, sgcontext->vc.obact);
BM_mesh_free(trimbm);
const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
@ -1404,6 +1404,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
sgcontext->ss->pbvh = BKE_pbvh_new();
BKE_pbvh_build_bmesh(sgcontext->ss->pbvh,
sculpt_mesh,
sgcontext->ss->bm,
sgcontext->ss->bm_smooth_shading,
sgcontext->ss->bm_log,

View File

@ -1253,7 +1253,7 @@ static void ed_vwpaintmode_enter_generic(
/* Create vertex/weight paint mode session data */
if (ob->sculpt) {
if (ob->sculpt->cache) {
SCULPT_cache_free(ob->sculpt, ob->sculpt->cache);
SCULPT_cache_free(ob->sculpt, ob, ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
BKE_sculptsession_free(ob);
@ -1322,7 +1322,7 @@ static void ed_vwpaintmode_exit_generic(Object *ob, const eObjectMode mode_flag)
/* If the cache is not released by a cancel or a done, free it now. */
if (ob->sculpt && ob->sculpt->cache) {
SCULPT_cache_free(ob->sculpt, ob->sculpt->cache);
SCULPT_cache_free(ob->sculpt, ob, ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
@ -2516,7 +2516,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
SCULPT_cache_free(ob->sculpt, ob->sculpt->cache);
SCULPT_cache_free(ob->sculpt, ob, ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
@ -2567,7 +2567,7 @@ static void wpaint_cancel(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
if (ob->sculpt->cache) {
SCULPT_cache_free(ob->sculpt, ob->sculpt->cache);
SCULPT_cache_free(ob->sculpt, ob, ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
@ -3456,7 +3456,7 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
MEM_freeN(vpd);
SCULPT_cache_free(ob->sculpt, ob->sculpt->cache);
SCULPT_cache_free(ob->sculpt, ob, ob->sculpt->cache);
ob->sculpt->cache = NULL;
}
@ -3508,7 +3508,7 @@ static void vpaint_cancel(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
if (ob->sculpt->cache) {
SCULPT_cache_free(ob->sculpt, ob->sculpt->cache);
SCULPT_cache_free(ob->sculpt, ob, ob->sculpt->cache);
ob->sculpt->cache = NULL;
}

View File

@ -411,24 +411,274 @@ const float *SCULPT_vertex_co_get(SculptSession *ss, SculptVertRef index)
return NULL;
}
const float *SCULPT_vertex_color_get(SculptSession *ss, SculptVertRef vertex)
bool SCULPT_has_colors(const SculptSession *ss)
{
return ss->vcol_type != -1;
}
ATTR_NO_OPT bool SCULPT_vertex_color_get(const SculptSession *ss,
SculptVertRef vertex,
float out[4])
{
if (vertex.i == SCULPT_REF_NONE) {
return NULL;
return false;
}
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
if (ss->vcol) {
return ss->vcol[vertex.i].color;
if (!(ss->vcol || ss->mcol)) {
zero_v4(out);
return false;
}
if (ss->vcol_domain == ATTR_DOMAIN_CORNER) {
zero_v4(out);
int count = ss->pmap[vertex.i].count;
for (int i = 0; i < count; i++) {
MPoly *mp = ss->mpoly + ss->pmap[vertex.i].indices[i];
MLoop *ml = ss->mloop + mp->loopstart;
int li = mp->loopstart;
for (int j = 0; j < mp->totloop; j++, li++, ml++) {
if (ml->v != vertex.i) {
continue;
}
if (ss->vcol_type == CD_MLOOPCOL) {
MLoopCol *col = ss->mcol + li;
float temp[4];
rgba_uchar_to_float(temp, (const char *)col);
srgb_to_linearrgb_v3_v3(temp, temp);
add_v4_v4(out, temp);
}
else if (ss->vcol_type == CD_PROP_COLOR) {
add_v4_v4(out, ss->vcol[li].color);
}
}
}
if (count) {
mul_v4_fl(out, 1.0f / (float)count);
}
}
else {
if (ss->vcol_type == CD_MLOOPCOL) {
MLoopCol *col = ss->mcol + vertex.i;
float temp[4];
rgba_uchar_to_float(temp, (const char *)col);
srgb_to_linearrgb_v3_v3(temp, temp);
copy_v4_v4(out, temp);
}
if (ss->vcol_type == CD_PROP_COLOR) {
copy_v4_v4(out, ss->vcol[vertex.i].color);
}
}
return ss->vcol || ss->mcol;
case PBVH_BMESH: {
BMVert *v = (BMVert *)vertex.i;
if (ss->vcol_type == -1) {
return false;
}
if (ss->vcol_domain == ATTR_DOMAIN_POINT) {
switch (ss->vcol_type) {
case CD_PROP_COLOR:
copy_v4_v4(out, (float *)BM_ELEM_CD_GET_VOID_P(v, ss->cd_vcol_offset));
break;
case CD_MLOOPCOL: {
MLoopCol *mp = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(v, ss->cd_vcol_offset);
float temp[4];
rgba_uchar_to_float(temp, (const char *)mp);
srgb_to_linearrgb_v3_v3(temp, temp);
copy_v4_v4(out, temp);
break;
}
}
}
else {
int tot = 0;
BMEdge *e = v->e;
if (!e) {
return false;
}
zero_v4(out);
do {
if (!e->l) {
continue;
}
BMLoop *l = e->l;
do {
BMLoop *l2 = l->v != v ? l->next : l;
switch (ss->vcol_type) {
case CD_PROP_COLOR:
add_v4_v4(out, (float *)BM_ELEM_CD_GET_VOID_P(l2, ss->cd_vcol_offset));
tot++;
break;
case CD_MLOOPCOL: {
MLoopCol *mp = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(l2, ss->cd_vcol_offset);
float temp[4];
rgba_uchar_to_float(temp, (const char *)mp);
srgb_to_linearrgb_v3_v3(temp, temp);
add_v4_v4(out, temp);
tot++;
break;
}
}
} while ((l = l->radial_next) != e->l);
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
if (tot > 0) {
mul_v4_fl(out, 1.0f / (float)tot);
}
}
return true;
}
case PBVH_GRIDS:
break;
}
return false;
}
ATTR_NO_OPT void SCULPT_vertex_color_set(const SculptSession *ss,
SculptVertRef vertex,
float color[4])
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
if (!(ss->vcol || ss->mcol)) {
return;
}
if (ss->vcol_domain == ATTR_DOMAIN_CORNER) {
int count = ss->pmap[vertex.i].count;
for (int i = 0; i < count; i++) {
MPoly *mp = ss->mpoly + ss->pmap[vertex.i].indices[i];
MLoop *ml = ss->mloop + mp->loopstart;
int li = mp->loopstart;
for (int j = 0; j < mp->totloop; j++, li++, ml++) {
if (ml->v != vertex.i) {
continue;
}
if (ss->vcol_type == CD_MLOOPCOL) {
float temp[4];
MLoopCol *col = ss->mcol + li;
linearrgb_to_srgb_v3_v3(temp, color);
temp[3] = color[3];
rgba_float_to_uchar((char *)col, temp);
}
else if (ss->vcol_type == CD_PROP_COLOR) {
copy_v4_v4(ss->vcol[li].color, color);
}
}
}
}
else {
if (ss->vcol_type == CD_MLOOPCOL) {
MLoopCol *col = ss->mcol + vertex.i;
float temp[4];
linearrgb_to_srgb_v3_v3(temp, color);
temp[3] = color[3];
rgba_float_to_uchar((char *)col, temp);
}
else if (ss->vcol_type == CD_PROP_COLOR) {
copy_v4_v4(ss->vcol[vertex.i].color, color);
}
}
break;
case PBVH_BMESH: {
BMVert *v = (BMVert *)vertex.i;
if (ss->cd_vcol_offset >= 0) {
MPropCol *col = BM_ELEM_CD_GET_VOID_P(v, ss->cd_vcol_offset);
return col->color;
if (ss->vcol_type == -1) {
return;
}
if (ss->vcol_domain == ATTR_DOMAIN_POINT) {
switch (ss->vcol_type) {
case CD_PROP_COLOR:
copy_v4_v4((float *)BM_ELEM_CD_GET_VOID_P(v, ss->cd_vcol_offset), color);
break;
case CD_MLOOPCOL: {
MLoopCol *mp = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(v, ss->cd_vcol_offset);
float temp[4];
linearrgb_to_srgb_v3_v3(temp, color);
temp[3] = color[3];
rgba_float_to_uchar((char *)mp, temp);
break;
}
}
}
else {
BMEdge *e = v->e;
if (!e) {
return;
}
do {
if (!e->l) {
continue;
}
BMLoop *l = e->l;
do {
BMLoop *l2 = l->v != v ? l->next : l;
switch (ss->vcol_type) {
case CD_PROP_COLOR:
copy_v4_v4((float *)BM_ELEM_CD_GET_VOID_P(l2, ss->cd_vcol_offset), color);
break;
case CD_MLOOPCOL: {
MLoopCol *mp = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(l2, ss->cd_vcol_offset);
float temp[4];
linearrgb_to_srgb_v3_v3(temp, color);
temp[3] = color[3];
rgba_float_to_uchar((char *)mp, temp);
break;
}
}
} while ((l = l->radial_next) != e->l);
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
}
break;
@ -436,7 +686,6 @@ const float *SCULPT_vertex_color_get(SculptSession *ss, SculptVertRef vertex)
case PBVH_GRIDS:
break;
}
return NULL;
}
void SCULPT_vertex_normal_get(SculptSession *ss, SculptVertRef index, float no[3])
@ -554,6 +803,7 @@ void SCULPT_vertex_persistent_normal_get(SculptSession *ss, SculptVertRef vertex
}
static bool sculpt_temp_customlayer_get(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
@ -578,7 +828,8 @@ static bool sculpt_temp_customlayer_get(SculptSession *ss,
if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
if (permanent) {
printf(
"%s: error: tried to make permanent customdata in multires mode; will make local array "
"%s: error: tried to make permanent customdata in multires mode; will make local "
"array "
"instead.\n",
__func__);
permanent = false;
@ -720,7 +971,7 @@ static bool sculpt_temp_customlayer_get(SculptSession *ss,
BM_data_layer_add_named(ss->bm, cdata, proptype, name);
idx = CustomData_get_named_layer_index(cdata, proptype, name);
SCULPT_dyntopo_node_layers_update_offsets(ss);
SCULPT_dyntopo_node_layers_update_offsets(ss, ob);
if (!permanent) {
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
@ -838,7 +1089,7 @@ static bool sculpt_temp_customlayer_get(SculptSession *ss,
return true;
}
void SCULPT_update_customdata_refs(SculptSession *ss)
void SCULPT_update_customdata_refs(SculptSession *ss, Object *ob)
{
/* run twice, in case sculpt_temp_customlayer_get had to recreate a layer and
messed up the ordering. */
@ -848,13 +1099,13 @@ void SCULPT_update_customdata_refs(SculptSession *ss)
if (scl && !scl->released && !scl->params.simple_array) {
sculpt_temp_customlayer_get(
ss, scl->domain, scl->proptype, scl->name, scl, true, &scl->params);
ss, ob, scl->domain, scl->proptype, scl->name, scl, true, &scl->params);
}
}
}
if (ss->bm) {
SCULPT_dyntopo_node_layers_update_offsets(ss);
SCULPT_dyntopo_node_layers_update_offsets(ss, ob);
}
}
@ -882,6 +1133,7 @@ float SCULPT_vertex_mask_get(SculptSession *ss, SculptVertRef index)
}
bool SCULPT_temp_customlayer_ensure(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
@ -891,11 +1143,11 @@ bool SCULPT_temp_customlayer_ensure(SculptSession *ss,
// call SCULPT_update_customdata_refs before and after,
// thoeretically it can allocate new layers
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
bool ret = sculpt_temp_customlayer_get(ss, domain, proptype, name, &scl, true, params);
bool ret = sculpt_temp_customlayer_get(ss, ob, domain, proptype, name, &scl, true, params);
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
return ret;
}
@ -940,7 +1192,7 @@ bool SCULPT_temp_customlayer_has(SculptSession *ss,
return false;
}
bool SCULPT_temp_customlayer_release(SculptSession *ss, SculptCustomLayer *scl)
bool SCULPT_temp_customlayer_release(SculptSession *ss, Object *ob, SculptCustomLayer *scl)
{
AttributeDomain domain = scl->domain;
@ -979,7 +1231,7 @@ bool SCULPT_temp_customlayer_release(SculptSession *ss, SculptCustomLayer *scl)
}
CustomData_free_layer(cdata, scl->layer->type, totelem, scl->layer - cdata->layers);
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
}
else {
MEM_SAFE_FREE(scl->data);
@ -991,14 +1243,15 @@ bool SCULPT_temp_customlayer_release(SculptSession *ss, SculptCustomLayer *scl)
}
bool SCULPT_temp_customlayer_get(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptCustomLayer *scl,
SculptLayerParams *params)
{
bool ret = sculpt_temp_customlayer_get(ss, domain, proptype, name, scl, true, params);
SCULPT_update_customdata_refs(ss);
bool ret = sculpt_temp_customlayer_get(ss, ob, domain, proptype, name, scl, true, params);
SCULPT_update_customdata_refs(ss, ob);
return ret;
}
@ -1196,9 +1449,9 @@ void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible)
case PBVH_GRIDS:
for (int i = 0; i < ss->totfaces; i++) {
/* This can run on geometry without a face set assigned, so its ID sign can't be changed to
* modify the visibility. Force that geometry to the ID 1 to enable changing the visibility
* here. */
/* This can run on geometry without a face set assigned, so its ID sign can't be changed
* to modify the visibility. Force that geometry to the ID 1 to enable changing the
* visibility here. */
if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) {
ss->face_sets[i] = 1;
}
@ -1235,9 +1488,9 @@ void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible)
BKE_pbvh_node_mark_update_triangulation(BKE_pbvh_node_from_index(ss->pbvh, node));
}
/* This can run on geometry without a face set assigned, so its ID sign can't be changed to
* modify the visibility. Force that geometry to the ID 1 to enable changing the visibility
* here. */
/* This can run on geometry without a face set assigned, so its ID sign can't be changed
* to modify the visibility. Force that geometry to the ID 1 to enable changing the
* visibility here. */
if (fset == SCULPT_FACE_SET_NONE) {
fset = 1;
@ -1252,7 +1505,6 @@ void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible)
BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, fset);
}
break;
}
}
}
@ -2526,7 +2778,7 @@ SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
ss->cd_faceset_offset,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
ss->cd_vcol_offset,
-1,
(BMVert *)vertex.i,
ss->boundary_symmetry);
}
@ -2583,7 +2835,7 @@ SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
ss->cd_faceset_offset,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
ss->cd_vcol_offset,
-1,
(BMVert *)vertex.i,
ss->boundary_symmetry);
}
@ -3096,12 +3348,9 @@ bool SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex)
copy_v3_v3(mv->origco, SCULPT_vertex_co_get(ss, vertex));
SCULPT_vertex_normal_get(ss, vertex, mv->origno);
const float *color = SCULPT_vertex_color_get(ss, vertex);
if (color) {
copy_v4_v4(mv->origcolor, color);
}
SCULPT_vertex_color_get(ss, vertex, mv->origcolor);
mv->origmask = (short)(SCULPT_vertex_mask_get(ss, vertex) * 65535.0f);
mv->origmask = unit_float_to_ushort_clamp(SCULPT_vertex_mask_get(ss, vertex));
return false;
}
@ -3215,12 +3464,16 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
*vd.mask = mv->origmask;
}
if (type & SCULPT_UNDO_COLOR && vd.col) {
if (len_squared_v4v4(vd.col, mv->origcolor) > FLT_EPSILON) {
modified = true;
}
if (type & SCULPT_UNDO_COLOR) {
float color[4];
copy_v4_v4(vd.col, mv->origcolor);
if (SCULPT_vertex_color_get(ss, vd.vertex, color)) {
if (len_squared_v4v4(color, mv->origcolor) > FLT_EPSILON) {
modified = true;
}
SCULPT_vertex_color_set(ss, vd.vertex, mv->origcolor);
}
}
if (vd.mvert) {
@ -5306,7 +5559,7 @@ void do_brush_action(
if (SCULPT_stroke_is_first_brush_step(ss->cache) &&
SCULPT_get_tool(ss, brush) == SCULPT_TOOL_DRAW_FACE_SETS) {
SCULPT_face_ensure_original(ss);
SCULPT_face_ensure_original(ss, ob);
for (int i = 0; i < ss->totfaces; i++) {
SculptFaceRef face = BKE_pbvh_table_index_to_face(ss->pbvh, i);
@ -5400,7 +5653,7 @@ void do_brush_action(
if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) {
if (!ss->cache->cloth_sim) {
ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
ss, 1.0f, 1.0f, 0.0f, false, true);
ss, ob, 1.0f, 1.0f, 0.0f, false, true);
SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim);
}
SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim);
@ -5911,7 +6164,7 @@ static void SCULPT_run_command(
if (brush2->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) {
if (!ss->cache->cloth_sim) {
ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
ss, 1.0f, 1.0f, 0.0f, false, true);
ss, ob, 1.0f, 1.0f, 0.0f, false, true);
SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim);
}
SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim);
@ -6344,8 +6597,8 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
PBVH_CHECK_NAN(val);
if (ss->filter_cache && ss->filter_cache->cloth_sim) {
/* When there is a simulation running in the filter cache that was created by a tool, combine
* the proxies into the simulation instead of directly into the mesh. */
/* When there is a simulation running in the filter cache that was created by a tool,
* combine the proxies into the simulation instead of directly into the mesh. */
SCULPT_clip(sd, ss, ss->filter_cache->cloth_sim->pos[vd.index], val);
}
else {
@ -6747,10 +7000,6 @@ bool SCULPT_mode_poll(bContext *C)
bool SCULPT_vertex_colors_poll(bContext *C)
{
if (!U.experimental.use_sculpt_vertex_colors) {
return false;
}
return SCULPT_mode_poll(C);
}
@ -6884,7 +7133,7 @@ static const char *sculpt_tool_name(Sculpt *sd)
* Operator for applying a stroke (various attributes including mouse path)
* using the current brush. */
void SCULPT_cache_free(SculptSession *ss, StrokeCache *cache)
void SCULPT_cache_free(SculptSession *ss, Object *ob, StrokeCache *cache)
{
MEM_SAFE_FREE(cache->dial);
MEM_SAFE_FREE(cache->surface_smooth_laplacian_disp);
@ -6897,13 +7146,13 @@ void SCULPT_cache_free(SculptSession *ss, StrokeCache *cache)
#endif
if (ss->custom_layers[SCULPT_SCL_LAYER_DISP]) {
SCULPT_temp_customlayer_release(ss, ss->custom_layers[SCULPT_SCL_LAYER_DISP]);
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_LAYER_DISP]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_LAYER_DISP]);
ss->custom_layers[SCULPT_SCL_LAYER_DISP] = NULL;
}
if (ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]) {
SCULPT_temp_customlayer_release(ss, ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]);
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID]);
ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID] = NULL;
}
@ -6916,20 +7165,20 @@ void SCULPT_cache_free(SculptSession *ss, StrokeCache *cache)
}
if (ss->custom_layers[SCULPT_SCL_FAIRING_MASK]) {
SCULPT_temp_customlayer_release(ss, ss->custom_layers[SCULPT_SCL_FAIRING_MASK]);
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_FAIRING_MASK]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_FAIRING_MASK]);
ss->custom_layers[SCULPT_SCL_FAIRING_MASK] = NULL;
}
if (ss->custom_layers[SCULPT_SCL_FAIRING_FADE]) {
SCULPT_temp_customlayer_release(ss, ss->custom_layers[SCULPT_SCL_FAIRING_FADE]);
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_FAIRING_FADE]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_FAIRING_FADE]);
ss->custom_layers[SCULPT_SCL_FAIRING_FADE] = NULL;
}
if (ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]) {
SCULPT_temp_customlayer_release(ss, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]);
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]);
MEM_freeN(ss->custom_layers[SCULPT_SCL_PREFAIRING_CO]);
ss->custom_layers[SCULPT_SCL_PREFAIRING_CO] = NULL;
@ -6975,7 +7224,7 @@ void SCULPT_cache_free(SculptSession *ss, StrokeCache *cache)
MEM_freeN(cache);
}
void SCULPT_release_customlayers(SculptSession *ss, bool non_customdata_only)
void SCULPT_release_customlayers(SculptSession *ss, Object *ob, bool non_customdata_only)
{
for (int i = 0; i < SCULPT_SCL_LAYER_MAX; i++) {
if (ss->custom_layers[i]) {
@ -6983,7 +7232,7 @@ void SCULPT_release_customlayers(SculptSession *ss, bool non_customdata_only)
continue;
}
SCULPT_temp_customlayer_release(ss, ss->custom_layers[i]);
SCULPT_temp_customlayer_release(ss, ob, ss->custom_layers[i]);
MEM_freeN(ss->custom_layers[i]);
ss->custom_layers[i] = NULL;
@ -7789,7 +8038,19 @@ static bool sculpt_needs_connectivity_info(Sculpt *sd,
SculptSession *ss,
int stroke_mode)
{
// if (ss && ss->pbvh && SCULPT_is_automasking_enabled(sd, ss, brush)) {
return true;
// }
return ((stroke_mode == BRUSH_STROKE_SMOOTH) || (ss && ss->cache && ss->cache->alt_smooth) ||
(brush->sculpt_tool == SCULPT_TOOL_SMOOTH) || (brush->autosmooth_factor > 0) ||
((brush->sculpt_tool == SCULPT_TOOL_MASK) && (brush->mask_tool == BRUSH_MASK_SMOOTH)) ||
(brush->sculpt_tool == SCULPT_TOOL_POSE) || (brush->sculpt_tool == SCULPT_TOOL_PAINT) ||
(brush->sculpt_tool == SCULPT_TOOL_SMEAR) ||
(brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) ||
(brush->sculpt_tool == SCULPT_TOOL_SLIDE_RELAX) ||
(brush->sculpt_tool == SCULPT_TOOL_CLOTH) || (brush->sculpt_tool == SCULPT_TOOL_SMEAR) ||
(brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) ||
(brush->sculpt_tool == SCULPT_TOOL_DISPLACEMENT_SMEAR));
}
void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush)
@ -8558,7 +8819,8 @@ void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerR
brush->alpha = fabs(brush->alpha);
ss->cache->bstrength = -fabs(ss->cache->bstrength);
// BKE_brush_channelset_set_float(ss->cache->channels_final, "strength", ss->cache->bstrength);
// BKE_brush_channelset_set_float(ss->cache->channels_final, "strength",
// ss->cache->bstrength);
}
ss->cache->stroke_distance = stroke->stroke_distance;
@ -8785,13 +9047,13 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
}
if (SCULPT_is_automasking_enabled(sd, ss, brush)) {
SCULPT_automasking_cache_free(ss, ss->cache->automasking);
SCULPT_automasking_cache_free(ss, ob, ss->cache->automasking);
}
int tool = SCULPT_get_tool(ss, brush); // save tool for after we've freed ss->cache
BKE_pbvh_node_color_buffer_free(ss->pbvh);
SCULPT_cache_free(ss, ss->cache);
SCULPT_cache_free(ss, ob, ss->cache);
ss->cache = NULL;
if (tool == SCULPT_TOOL_ARRAY) {
@ -8799,7 +9061,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
SCULPT_array_datalayers_free(ss->array, ob);
}
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
if (tool == SCULPT_TOOL_MASK) {
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
@ -8887,7 +9149,7 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
paint_stroke_cancel(C, op);
if (ss->cache) {
SCULPT_cache_free(ss, ss->cache);
SCULPT_cache_free(ss, ob, ss->cache);
ss->cache = NULL;
}
@ -9063,7 +9325,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
if (has_undo) {
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
}
else if (need_bmlog) {
if (ob->sculpt->bm_log) {

View File

@ -82,7 +82,7 @@ static void sculpt_vertex_array_data_get(SculptArray *array,
*r_symmetry_pass = array->symmetry_pass[vertex];
}
static void sculpt_array_datalayers_init(SculptArray *array, SculptSession *ss)
static void sculpt_array_datalayers_init(Object *ob, SculptArray *array, SculptSession *ss)
{
SculptLayerParams params = {.permanent = true, .simple_array = false};
@ -95,14 +95,19 @@ static void sculpt_array_datalayers_init(SculptArray *array, SculptSession *ss)
}
SCULPT_temp_customlayer_ensure(
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, &params);
SCULPT_temp_customlayer_ensure(
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, &params);
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, &params);
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, array->scl_sym, &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, &params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_symmetry_pass_cd_name,
array->scl_sym,
&params);
}
static void sculpt_array_datalayers_add(SculptArray *array, SculptSession *ss, Mesh *mesh)
@ -156,22 +161,28 @@ void SCULPT_array_datalayers_free(SculptArray *array, Object *ob)
SculptLayerParams params = {.permanent = true, .simple_array = false};
if (array->scl_inst) {
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, &params);
SCULPT_temp_customlayer_release(ss, array->scl_inst);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_instance_cd_name,
array->scl_inst,
&params);
SCULPT_temp_customlayer_release(ss, ob, array->scl_inst);
}
if (array->scl_sym) {
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_symmetry_pass_cd_name,
array->scl_sym,
&params);
SCULPT_temp_customlayer_release(ss, array->scl_sym);
SCULPT_temp_customlayer_release(ss, ob, array->scl_sym);
}
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
array->scl_inst = NULL;
array->scl_sym = NULL;
@ -338,14 +349,19 @@ static void sculpt_array_ensure_geometry_indices(Object *ob, SculptArray *array)
SculptSession *ss = ob->sculpt;
int totvert = SCULPT_vertex_count_get(ss);
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
SculptLayerParams params = {.permanent = true, .simple_array = false};
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, &params);
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, array->scl_sym, &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, &params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
array_symmetry_pass_cd_name,
array->scl_sym,
&params);
array->copy_index = MEM_malloc_arrayN(totvert, sizeof(int), "array copy index");
array->symmetry_pass = MEM_malloc_arrayN(totvert, sizeof(int), "array symmetry pass index");
@ -368,7 +384,7 @@ static void sculpt_array_mesh_build(Sculpt *sd, Object *ob, SculptArray *array)
Mesh *sculpt_mesh = BKE_object_get_original_mesh(ob);
Brush *brush = BKE_paint_brush(&sd->paint);
sculpt_array_datalayers_init(array, ob->sculpt);
sculpt_array_datalayers_init(ob, array, ob->sculpt);
sculpt_array_datalayers_add(array, ob->sculpt, sculpt_mesh);
BMesh *srcbm = sculpt_array_source_build(ob, brush, array);
@ -424,7 +440,7 @@ static void sculpt_array_mesh_build(Sculpt *sd, Object *ob, SculptArray *array)
BM_mesh_free(destbm);
}
else {
SCULPT_update_customdata_refs(ob->sculpt);
SCULPT_update_customdata_refs(ob->sculpt, ob);
ob->sculpt->needs_pbvh_rebuild = true;
}

View File

@ -198,14 +198,14 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
return mask;
}
void SCULPT_automasking_cache_free(SculptSession *ss, AutomaskingCache *automasking)
void SCULPT_automasking_cache_free(SculptSession *ss, Object *ob, AutomaskingCache *automasking)
{
if (!automasking) {
return;
}
if (automasking->factorlayer) {
SCULPT_temp_customlayer_release(ss, automasking->factorlayer);
SCULPT_temp_customlayer_release(ss, ob, automasking->factorlayer);
MEM_SAFE_FREE(automasking->factorlayer);
}
@ -485,6 +485,7 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush,
SculptLayerParams params = {.permanent = false, .simple_array = false};
if (!SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
"__sculpt_mask_factor",

View File

@ -1895,13 +1895,14 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
#endif
}
void SCULPT_ensure_persistent_layers(SculptSession *ss)
void SCULPT_ensure_persistent_layers(SculptSession *ss, Object *ob)
{
if (!ss->custom_layers[SCULPT_SCL_PERS_CO]) {
SculptLayerParams params = {.permanent = true, .simple_array = false};
ss->custom_layers[SCULPT_SCL_PERS_CO] = MEM_callocN(sizeof(SculptCustomLayer), "scl_pers_co");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_LAYER_PERS_CO,
@ -1910,6 +1911,7 @@ void SCULPT_ensure_persistent_layers(SculptSession *ss)
ss->custom_layers[SCULPT_SCL_PERS_NO] = MEM_callocN(sizeof(SculptCustomLayer), "scl_pers_no");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
SCULPT_LAYER_PERS_NO,
@ -1919,6 +1921,7 @@ void SCULPT_ensure_persistent_layers(SculptSession *ss)
ss->custom_layers[SCULPT_SCL_PERS_DISP] = MEM_callocN(sizeof(SculptCustomLayer),
"scl_pers_disp");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_LAYER_PERS_DISP,
@ -1941,13 +1944,14 @@ void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
#endif
if ((brush->flag & BRUSH_PERSISTENT) && SCULPT_has_persistent_base(ss)) {
SCULPT_ensure_persistent_layers(ss);
SCULPT_ensure_persistent_layers(ss, ob);
}
if (!ss->custom_layers[SCULPT_SCL_LAYER_DISP]) {
ss->custom_layers[SCULPT_SCL_LAYER_DISP] = MEM_callocN(sizeof(SculptCustomLayer),
"layer disp scl");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
SCULPT_LAYER_DISP,
@ -1959,6 +1963,7 @@ void SCULPT_do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
ss->custom_layers[SCULPT_SCL_LAYER_STROKE_ID] = MEM_callocN(sizeof(SculptCustomLayer),
"layer disp scl");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
SCULPT_LAYER_STROKE_ID,
@ -3380,6 +3385,7 @@ void SCULPT_do_fairing_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
SculptLayerParams params = {.permanent = false, .simple_array = true};
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_BOOL,
"fairing_mask",
@ -3387,6 +3393,7 @@ void SCULPT_do_fairing_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
&params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT,
"fairing_fade",
@ -3394,13 +3401,14 @@ void SCULPT_do_fairing_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
&params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
"prefairing_co",
ss->custom_layers[SCULPT_SCL_PREFAIRING_CO],
&params);
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
}
if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) {
@ -3902,8 +3910,10 @@ void SCULPT_bmesh_topology_rake(Sculpt *sd,
Brush local_brush;
// vector4, nto color
SCULPT_dyntopo_ensure_templayer(ss, CD_PROP_COLOR, "_rake_temp", false);
/* TODO: use SCULPT_temp_customlayer api */
/* vector4, but not a color */
SCULPT_dyntopo_ensure_templayer(ss, ob, CD_PROP_COLOR, "_rake_temp", false);
int cd_temp = SCULPT_dyntopo_get_templayer(ss, CD_PROP_COLOR, "_rake_temp");

View File

@ -313,7 +313,7 @@ static bool calc_bending_gradients(const SculptClothSimulation *cloth_sim,
float invElen = 1.0f / elen;
float tmp1[3], tmp2[3], tmp3[3], tmp4[3], n1[3], n2[3];
float tmp1[3], tmp2[3], n1[3], n2[3];
sub_v3_v3v3(tmp1, p2, p0);
sub_v3_v3v3(tmp2, p3, p0);
@ -2183,6 +2183,7 @@ static void cloth_sim_initialize_default_node_state(SculptSession *ss,
/* Public functions. */
SculptClothSimulation *SCULPT_cloth_brush_simulation_create(SculptSession *ss,
Object *ob,
const float cloth_mass,
const float cloth_damping,
const float cloth_softbody_strength,
@ -2200,7 +2201,7 @@ SculptClothSimulation *SCULPT_cloth_brush_simulation_create(SculptSession *ss,
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
if (SCULPT_has_persistent_base(ss)) {
SCULPT_ensure_persistent_layers(ss);
SCULPT_ensure_persistent_layers(ss, ob);
cloth_sim->cd_pers_co = ss->custom_layers[SCULPT_SCL_PERS_CO]->cd_offset;
cloth_sim->cd_pers_no = ss->custom_layers[SCULPT_SCL_PERS_NO]->cd_offset;
@ -2376,6 +2377,7 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
if (SCULPT_stroke_is_first_brush_step(ss->cache) || !ss->cache->cloth_sim) {
ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
ss,
ob,
SCULPT_get_float(ss, cloth_mass, sd, brush),
SCULPT_get_float(ss, cloth_damping, sd, brush),
SCULPT_get_float(ss, cloth_constraint_softbody_strength, sd, brush),
@ -2740,8 +2742,8 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
float filter_strength = RNA_float_get(op->ptr, "strength");
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
SCULPT_filter_cache_free(ss);
SCULPT_undo_push_end();
SCULPT_filter_cache_free(ss, ob);
SCULPT_undo_push_end(ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
return OPERATOR_FINISHED;
}
@ -2850,6 +2852,7 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
ss->filter_cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
ss,
ob,
cloth_mass,
cloth_damping,
0.0f,

View File

@ -206,7 +206,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
SCULPT_dyntopo_automasking_end(mask_cb_data);
MEM_SAFE_FREE(nodes);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
/* Force rebuild of PBVH for better BB placement. */
SCULPT_pbvh_clear(ob);

View File

@ -405,7 +405,7 @@ void SCULPT_reorder_bmesh(SculptSession *ss)
ss->active_face_index = BKE_pbvh_table_index_to_face(ss->pbvh, actf);
}
SCULPT_dyntopo_node_layers_update_offsets(ss);
SCULPT_dyntopo_node_layers_update_offsets(ss, ob);
if (ss->bm_log) {
BM_log_set_bm(ss->bm, ss->bm_log);
@ -519,24 +519,33 @@ void SCULPT_dyntopo_save_origverts(SculptSession *ss)
BMIter iter;
BMVert *v;
if (ss->vcol_type == -1) {
return;
}
BM_ITER_MESH (v, &iter, ss->bm, BM_VERTS_OF_MESH) {
MSculptVert *mv = BKE_PBVH_SCULPTVERT(ss->cd_sculpt_vert, v);
copy_v3_v3(mv->origco, v->co);
copy_v3_v3(mv->origno, v->no);
if (ss->cd_vcol_offset >= 0) {
MPropCol *mp = (MPropCol *)BM_ELEM_CD_GET_VOID_P(v, ss->cd_vcol_offset);
copy_v4_v4(mv->origcolor, mp->color);
if (ss->cd_vert_mask_offset >= 0) {
mv->origmask = BM_ELEM_CD_GET_FLOAT(v, ss->cd_vert_mask_offset);
}
if (ss->vcol_type != -1) {
BKE_pbvh_bmesh_get_vcol(
v, mv->origcolor, ss->vcol_type, ss->vcol_domain, ss->cd_vcol_offset);
}
}
}
char dyntopop_node_idx_layer_id[] = "_dyntopo_node_id";
void SCULPT_dyntopo_node_layers_update_offsets(SculptSession *ss)
void SCULPT_dyntopo_node_layers_update_offsets(SculptSession *ss, Object *ob)
{
SCULPT_dyntopo_node_layers_add(ss);
SCULPT_dyntopo_node_layers_add(ss, ob);
if (ss->pbvh) {
BKE_pbvh_update_offsets(ss->pbvh,
ss->cd_vert_node_offset,
@ -554,10 +563,8 @@ bool SCULPT_dyntopo_has_templayer(SculptSession *ss, int type, const char *name)
return CustomData_get_named_layer_index(&ss->bm->vdata, type, name) >= 0;
}
void SCULPT_dyntopo_ensure_templayer(SculptSession *ss,
int type,
const char *name,
bool not_temporary)
void SCULPT_dyntopo_ensure_templayer(
SculptSession *ss, Object *ob, int type, const char *name, bool not_temporary)
{
if (ss->save_temp_layers) {
not_temporary = true;
@ -567,7 +574,7 @@ void SCULPT_dyntopo_ensure_templayer(SculptSession *ss,
if (li < 0) {
BM_data_layer_add_named(ss->bm, &ss->bm->vdata, type, name);
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
li = CustomData_get_named_layer_index(&ss->bm->vdata, type, name);
ss->bm->vdata.layers[li].flag |= not_temporary ? 0 : CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
@ -588,7 +595,7 @@ int SCULPT_dyntopo_get_templayer(SculptSession *ss, int type, const char *name)
char dyntopop_faces_areas_layer_id[] = "__dyntopo_face_areas";
void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
void SCULPT_dyntopo_node_layers_add(SculptSession *ss, Object *ob)
{
int cd_node_layer_index, cd_face_node_layer_index;
@ -613,12 +620,8 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
cd_face_node_layer_index = CustomData_get_named_layer_index(
&ss->bm->pdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
ss->cd_origvcol_offset = -1;
ss->cd_sculpt_vert = CustomData_get_offset(&ss->bm->vdata, CD_DYNTOPO_VERT);
ss->cd_vcol_offset = CustomData_get_offset(&ss->bm->vdata, CD_PROP_COLOR);
ss->cd_vert_node_offset = CustomData_get_n_offset(
&ss->bm->vdata,
CD_PROP_INT32,
@ -637,6 +640,21 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
ss->cd_face_areas = CustomData_get_named_layer(
&ss->bm->pdata, CD_PROP_FLOAT, dyntopop_faces_areas_layer_id);
ss->cd_face_areas = ss->bm->pdata.layers[ss->cd_face_areas].offset;
AttributeDomain domain;
CustomDataLayer *cl;
Mesh *me = BKE_object_get_original_mesh(ob);
if (BKE_pbvh_get_color_layer(ss->pbvh, me, &cl, &domain)) {
ss->vcol_domain = (int)domain;
ss->vcol_type = cl->type;
ss->cd_vcol_offset = cl->offset;
}
else {
ss->cd_vcol_offset = -1;
ss->vcol_type = -1;
ss->vcol_domain = (int)ATTR_DOMAIN_NUM;
}
}
/**
@ -688,6 +706,26 @@ void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me)
modified = true;
}
/* sync various ids */
for (int j = 0; j < data1->totlayer; j++) {
CustomDataLayer *cl1 = data1->layers + j;
if ((1 << cl1->type) & badmask) {
continue;
}
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
if (idx == -1) {
continue;
}
CustomDataLayer *cl2 = data2->layers + idx;
cl2->anonymous_id = cl1->anonymous_id;
cl2->uid = cl1->uid;
}
bool typemap[CD_NUMTYPES] = {0};
for (int j = 0; j < data1->totlayer; j++) {
@ -749,7 +787,7 @@ void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me)
}
if (modified) {
SCULPT_dyntopo_node_layers_update_offsets(ss);
SCULPT_dyntopo_node_layers_update_offsets(ss, ob);
}
}
@ -774,7 +812,7 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
}
/* destroy non-customdata temporary layers (which are rarely used) */
SCULPT_release_customlayers(ss, true);
SCULPT_release_customlayers(ss, ob, true);
/* clear all the other temporary layer references, that point to customdata layers*/
SCULPT_clear_scl_pointers(ss);
@ -784,7 +822,7 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
}
else {
/*sculpt session was set up by paint.c. just call SCULPT_update_customdata_refs to be safe*/
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
/* also check bm_log */
if (!ss->bm_log) {
@ -847,20 +885,18 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
SCULPT_dynamic_topology_triangulate(ss, ss->bm);
#endif
SCULPT_dyntopo_node_layers_add(ss);
SCULPT_dyntopo_node_layers_add(ss, ob);
SCULPT_dyntopo_save_origverts(ss);
if (SCULPT_has_persistent_base(ss)) {
SCULPT_ensure_persistent_layers(ss);
SCULPT_ensure_persistent_layers(ss, ob);
}
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
BMIter iter;
BMVert *v;
int cd_vcol_offset = CustomData_get_offset(&ss->bm->vdata, CD_PROP_COLOR);
int i = 0;
BMEdge *e;
@ -877,19 +913,11 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
ss->cd_faceset_offset,
ss->cd_vert_node_offset,
ss->cd_face_node_offset,
ss->cd_vcol_offset,
-1,
v,
ss->boundary_symmetry);
BKE_pbvh_bmesh_update_valence(ss->cd_sculpt_vert, (SculptVertRef){.i = (intptr_t)v});
copy_v3_v3(mv->origco, v->co);
copy_v3_v3(mv->origno, v->no);
if (ss->cd_vcol_offset >= 0) {
MPropCol *color = (MPropCol *)BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offset);
copy_v4_v4(mv->origcolor, color->color);
}
i++;
}
@ -926,8 +954,8 @@ static void SCULPT_dynamic_topology_disable_ex(
SCULPT_pbvh_clear(ob);
/* destroy non-customdata temporary layers (which are rarely used) */
SCULPT_release_customlayers(ss, true);
/* destroy non-customdata temporary layers (which are rarely (never?) used for PBVH_BMESH) */
SCULPT_release_customlayers(ss, ob, true);
/* free all the other pointers in ss->custom_layers*/
SCULPT_clear_scl_pointers(ss);
@ -987,7 +1015,7 @@ void sculpt_dynamic_topology_disable_with_undo(Main *bmain,
}
SCULPT_dynamic_topology_disable_ex(bmain, depsgraph, scene, ob, NULL);
if (use_undo) {
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
}
ss->active_vertex_index.i = ss->active_face_index.i = 0;
@ -1010,7 +1038,7 @@ static void sculpt_dynamic_topology_enable_with_undo(Main *bmain,
SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob);
if (use_undo) {
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
}
ss->active_vertex_index.i = ss->active_face_index.i = 0;

View File

@ -1336,7 +1336,7 @@ static void sculpt_expand_restore_color_data(SculptSession *ss, ExpandCache *exp
PBVHNode *node = nodes[n];
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
copy_v4_v4(vd.col, expand_cache->original_colors[vd.index]);
SCULPT_vertex_color_set(ss, vd.vertex, expand_cache->original_colors[vd.index]);
}
BKE_pbvh_vertex_iter_end;
BKE_pbvh_node_mark_redraw(node);
@ -1400,7 +1400,7 @@ static void sculpt_expand_cancel(bContext *C, wmOperator *UNUSED(op))
sculpt_expand_restore_original_state(C, ob, ss->expand_cache);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
sculpt_expand_cache_free(ss);
}
@ -1504,7 +1504,7 @@ static void sculpt_expand_colors_update_task_cb(void *__restrict userdata,
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_ALL) {
float initial_color[4];
copy_v4_v4(initial_color, vd.col);
SCULPT_vertex_color_get(ss, vd.vertex, initial_color);
const bool enabled = sculpt_expand_state_get(ss, expand_cache, vd.vertex);
float fade;
@ -1531,7 +1531,8 @@ static void sculpt_expand_colors_update_task_cb(void *__restrict userdata,
continue;
}
copy_v4_v4(vd.col, final_color);
SCULPT_vertex_color_set(ss, vd.vertex, final_color);
any_changed = true;
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@ -1569,6 +1570,8 @@ static void sculpt_expand_original_state_store(Object *ob, ExpandCache *expand_c
const int totvert = SCULPT_vertex_count_get(ss);
const int totface = ss->totfaces;
SCULPT_vertex_random_access_ensure(ss);
/* Face Sets are always stored as they are needed for snapping. */
expand_cache->initial_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "initial face set");
expand_cache->original_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "original face set");
@ -1592,8 +1595,9 @@ static void sculpt_expand_original_state_store(Object *ob, ExpandCache *expand_c
if (expand_cache->target == SCULPT_EXPAND_TARGET_COLORS) {
expand_cache->original_colors = MEM_malloc_arrayN(totvert, sizeof(float[4]), "initial colors");
for (int i = 0; i < totvert; i++) {
copy_v4_v4(expand_cache->original_colors[i],
SCULPT_vertex_color_get(ss, BKE_pbvh_table_index_to_vertex(ss->pbvh, i)));
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
SCULPT_vertex_color_get(ss, vertex, expand_cache->original_colors[i]);
}
}
}
@ -1759,7 +1763,7 @@ static void sculpt_expand_finish(bContext *C)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
/* Tag all nodes to redraw to avoid artifacts after the fast partial updates. */
PBVHNode **nodes;

View File

@ -161,7 +161,7 @@ int SCULPT_face_set_original_get(SculptSession *ss, SculptFaceRef face)
return s[0];
}
void SCULPT_face_ensure_original(SculptSession *ss)
void SCULPT_face_ensure_original(SculptSession *ss, Object *ob)
{
if (ss->custom_layers[SCULPT_SCL_ORIG_FSETS]) {
return;
@ -170,6 +170,7 @@ void SCULPT_face_ensure_original(SculptSession *ss)
SculptCustomLayer *scl = MEM_callocN(sizeof(*scl), "orig fset scl");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_FACE,
CD_PROP_INT32,
"orig_faceset_attr_name",
@ -889,7 +890,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
MEM_SAFE_FREE(nodes);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
SCULPT_tag_update_overlays(C);
@ -1236,7 +1237,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
break;
}
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
/* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
SCULPT_visibility_sync_all_face_sets_to_vertices(ob);
@ -1435,7 +1436,7 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
/* Sync face sets visibility and vertex visibility. */
SCULPT_visibility_sync_all_face_sets_to_vertices(ob);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
@ -2107,7 +2108,7 @@ static void sculpt_face_set_edit_modify_face_sets(Object *ob,
SCULPT_undo_push_begin(ob, "face set edit");
SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
face_set_edit_do_post_visibility_updates(ob, nodes, totnode);
MEM_freeN(nodes);
}
@ -2135,7 +2136,7 @@ static void sculpt_face_set_edit_modify_coordinates(bContext *C,
}
SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
MEM_freeN(nodes);
}
@ -2205,7 +2206,7 @@ static void sculpt_face_set_extrude_id(Object *ob,
BMesh *bm = sculpt_faceset_bm_begin(ob, ss, mesh);
if (ss->bm) {
BKE_pbvh_bmesh_set_toolflags(ss->pbvh, true);
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
}
BM_mesh_elem_table_init(bm, BM_FACE);
@ -2623,7 +2624,7 @@ static void sculpt_face_set_extrude_id(Object *ob,
if (ss->bm) {
// slow! BKE_pbvh_bmesh_set_toolflags(ss->pbvh, false);
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
}
}
@ -2833,7 +2834,7 @@ static int sculpt_face_set_edit_modal(bContext *C, wmOperator *op, const wmEvent
MEM_SAFE_FREE(op->customdata);
if (ss->bm) {
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
}
else {
ED_sculpt_undo_geometry_end(ob);

View File

@ -175,7 +175,7 @@ static int sculpt_face_set_by_topology_invoke(bContext *C, wmOperator *op, const
MEM_freeN(nodes);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
SCULPT_tag_update_overlays(C);
return OPERATOR_FINISHED;

View File

@ -196,13 +196,21 @@ static void color_filter_task_cb(void *__restrict userdata,
case COLOR_FILTER_SMOOTH: {
fade = clamp_f(fade, -1.0f, 1.0f);
float smooth_color[4];
SCULPT_neighbor_color_average(ss, smooth_color, vd.vertex);
blend_color_interpolate_float(final_color, vd.col, smooth_color, fade);
float col[4];
SCULPT_vertex_color_get(ss, vd.vertex, col);
blend_color_interpolate_float(final_color, col, smooth_color, fade);
break;
}
}
copy_v3_v3(vd.col, final_color);
float col[4];
SCULPT_vertex_color_get(ss, vd.vertex, col);
copy_v3_v3(col, final_color);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@ -221,8 +229,8 @@ static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent
float filter_strength = RNA_float_get(op->ptr, "strength");
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
SCULPT_undo_push_end();
SCULPT_filter_cache_free(ss);
SCULPT_undo_push_end(ob);
SCULPT_filter_cache_free(ss, ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR);
return OPERATOR_FINISHED;
}
@ -285,7 +293,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_CANCELLED;
}
if (!ss->vcol) {
if (!SCULPT_has_colors(ss)) {
return OPERATOR_CANCELLED;
}

View File

@ -257,7 +257,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
MEM_SAFE_FREE(nodes);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
SCULPT_tag_update_overlays(C);
@ -945,8 +945,8 @@ static void sculpt_ipmask_filter_cancel(bContext *C, wmOperator *UNUSED(op))
SculptSession *ss = ob->sculpt;
sculpt_ipmask_restore_original_mask(ob);
SCULPT_undo_push_end();
SCULPT_filter_cache_free(ss);
SCULPT_undo_push_end(ob);
SCULPT_filter_cache_free(ss, ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
}
@ -972,8 +972,8 @@ static int sculpt_ipmask_filter_modal(bContext *C, wmOperator *op, const wmEvent
for (int i = 0; i < filter_cache->totnode; i++) {
BKE_pbvh_node_mark_update_mask(filter_cache->nodes[i]);
}
SCULPT_filter_cache_free(ss);
SCULPT_undo_push_end();
SCULPT_filter_cache_free(ss, ob);
SCULPT_undo_push_end(ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
return OPERATOR_FINISHED;
}
@ -1096,8 +1096,8 @@ static int sculpt_ipmask_filter_exec(bContext *C, wmOperator *op)
}
SCULPT_tag_update_overlays(C);
SCULPT_filter_cache_free(ss);
SCULPT_undo_push_end();
SCULPT_filter_cache_free(ss, ob);
SCULPT_undo_push_end(ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
return OPERATOR_FINISHED;
}
@ -1347,7 +1347,7 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
ED_region_tag_redraw(region);

View File

@ -181,13 +181,14 @@ static void mask_filter_delta_step_free(void *delta_step_free)
MEM_SAFE_FREE(delta_step->index);
MEM_SAFE_FREE(delta_step);
}
void SCULPT_filter_cache_free(SculptSession *ss)
void SCULPT_filter_cache_free(SculptSession *ss, Object *ob)
{
if (ss->filter_cache->cloth_sim) {
SCULPT_cloth_simulation_free(ss->filter_cache->cloth_sim);
}
if (ss->filter_cache->automasking) {
SCULPT_automasking_cache_free(ss, ss->filter_cache->automasking);
SCULPT_automasking_cache_free(ss, ob, ss->filter_cache->automasking);
}
if (ss->filter_cache->mask_delta_step) {
BLI_ghash_free(ss->filter_cache->mask_delta_step, NULL, mask_filter_delta_step_free);
@ -760,8 +761,8 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
float filter_strength = RNA_float_get(op->ptr, "strength");
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
SCULPT_filter_cache_free(ss);
SCULPT_undo_push_end();
SCULPT_filter_cache_free(ss, ob);
SCULPT_undo_push_end(ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
return OPERATOR_FINISHED;
}
@ -911,7 +912,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
if (filter_type == MESH_FILTER_SMOOTH && ss->filter_cache->bound_smooth_radius != 0.0f) {
/*ensure ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] exists*/
SCULPT_bound_smooth_ensure(ss);
SCULPT_bound_smooth_ensure(ss, ob);
}
WM_event_add_modal_handler(C, op);

View File

@ -144,12 +144,15 @@ void SCULPT_vertex_random_access_ensure(struct SculptSession *ss);
void SCULPT_face_random_access_ensure(struct SculptSession *ss);
int SCULPT_vertex_valence_get(const struct SculptSession *ss, SculptVertRef vertex);
int SCULPT_vertex_count_get(const struct SculptSession *ss);
bool SCULPT_vertex_color_get(const SculptSession *ss, SculptVertRef vertex, float out[4]);
void SCULPT_vertex_color_set(const SculptSession *ss, SculptVertRef vertex, float color[4]);
bool SCULPT_has_colors(const SculptSession *ss);
const float *SCULPT_vertex_co_get(struct SculptSession *ss, SculptVertRef index);
void SCULPT_vertex_normal_get(SculptSession *ss, SculptVertRef index, float no[3]);
float SCULPT_vertex_mask_get(struct SculptSession *ss, SculptVertRef index);
const float *SCULPT_vertex_color_get(SculptSession *ss, SculptVertRef index);
const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, SculptVertRef index);
void SCULPT_vertex_persistent_normal_get(SculptSession *ss, SculptVertRef index, float no[3]);
@ -379,7 +382,7 @@ bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, SculptVertRef ind
void SCULPT_face_sets_visibility_invert(SculptSession *ss);
void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible);
void SCULPT_face_ensure_original(SculptSession *ss);
void SCULPT_face_ensure_original(SculptSession *ss, struct Object *ob);
int SCULPT_face_set_original_get(SculptSession *ss, SculptFaceRef face);
void SCULPT_face_check_origdata(SculptSession *ss, SculptFaceRef face);
@ -512,9 +515,9 @@ enum eDynTopoWarnFlag {
struct Mesh;
void SCULPT_update_customdata_refs(SculptSession *ss);
void SCULPT_update_customdata_refs(SculptSession *ss, Object *ob);
void SCULPT_dyntopo_node_layers_update_offsets(SculptSession *ss);
void SCULPT_dyntopo_node_layers_update_offsets(SculptSession *ss, Object *ob);
void SCULPT_dynamic_topology_sync_layers(Object *ob, struct Mesh *me);
void SCULPT_dynamic_topology_enable_ex(struct Main *bmain,
@ -530,7 +533,7 @@ void sculpt_dynamic_topology_disable_with_undo(struct Main *bmain,
bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush);
void SCULPT_dynamic_topology_triangulate(struct SculptSession *ss, struct BMesh *bm);
void SCULPT_dyntopo_node_layers_add(struct SculptSession *ss);
void SCULPT_dyntopo_node_layers_add(struct SculptSession *ss, Object *ob);
void SCULPT_dyntopo_save_origverts(struct SculptSession *ss);
enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob);
@ -547,7 +550,9 @@ float SCULPT_automasking_factor_get(struct AutomaskingCache *automasking,
struct AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss);
struct AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush, Object *ob);
void SCULPT_automasking_cache_free(SculptSession *ss, struct AutomaskingCache *automasking);
void SCULPT_automasking_cache_free(SculptSession *ss,
Object *ob,
struct AutomaskingCache *automasking);
bool SCULPT_is_automasking_mode_enabled(const SculptSession *ss,
const Sculpt *sd,
@ -589,8 +594,11 @@ float *SCULPT_geodesic_from_vertex(Object *ob,
const float limit_radius);
/* Filters. */
void SCULPT_filter_cache_init(struct bContext *C, Object *ob, Sculpt *sd, const int undo_type);
void SCULPT_filter_cache_free(SculptSession *ss);
void SCULPT_filter_cache_init(struct bContext *C,
struct Object *ob,
Sculpt *sd,
const int undo_type);
void SCULPT_filter_cache_free(SculptSession *ss, struct Object *ob);
void SCULPT_mask_filter_smooth_apply(
Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, const int smooth_iterations);
@ -607,6 +615,7 @@ void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim);
struct SculptClothSimulation *SCULPT_cloth_brush_simulation_create(
struct SculptSession *ss,
struct Object *ob,
const float cloth_mass,
const float cloth_damping,
const float cloth_softbody_strength,
@ -1734,7 +1743,7 @@ void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
const char symm,
const char axis,
const float angle);
void SCULPT_cache_free(SculptSession *ss, StrokeCache *cache);
void SCULPT_cache_free(SculptSession *ss, struct Object *ob, StrokeCache *cache);
bool SCULPT_vertex_check_origdata(SculptSession *ss, SculptVertRef vertex);
@ -1751,8 +1760,8 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node, SculptUndoType type);
SculptUndoNode *SCULPT_undo_get_first_node(void);
void SCULPT_undo_push_begin(struct Object *ob, const char *name);
void SCULPT_undo_push_end(void);
void SCULPT_undo_push_end_ex(const bool use_nested_undo);
void SCULPT_undo_push_end(struct Object *ob);
void SCULPT_undo_push_end_ex(struct Object *ob, const bool use_nested_undo);
void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]);
@ -1862,10 +1871,8 @@ which works with all three PBVH types
Ensure a named temporary layer exists, creating it if necassary.
The layer will be marked with CD_FLAG_TEMPORARY.
*/
void SCULPT_dyntopo_ensure_templayer(SculptSession *ss,
int type,
const char *name,
bool not_temporary);
void SCULPT_dyntopo_ensure_templayer(
SculptSession *ss, struct Object *ob, int type, const char *name, bool not_temporary);
bool SCULPT_dyntopo_has_templayer(SculptSession *ss, int type, const char *name);
@ -1873,7 +1880,7 @@ bool SCULPT_dyntopo_has_templayer(SculptSession *ss, int type, const char *name)
-1 is returned.*/
int SCULPT_dyntopo_get_templayer(SculptSession *ss, int type, const char *name);
void SCULPT_ensure_persistent_layers(SculptSession *ss);
void SCULPT_ensure_persistent_layers(SculptSession *ss, struct Object *ob);
#define SCULPT_LAYER_PERS_CO "Persistent Base Co"
#define SCULPT_LAYER_PERS_NO "Persistent Base No"
@ -1948,22 +1955,24 @@ Access per element data with SCULPT_temp_cdata_get.
*/
bool SCULPT_temp_customlayer_ensure(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptLayerParams *params);
bool SCULPT_temp_customlayer_get(SculptSession *ss,
Object *ob,
AttributeDomain domain,
int proptype,
const char *name,
SculptCustomLayer *scl,
SculptLayerParams *params);
bool SCULPT_temp_customlayer_release(SculptSession *ss, SculptCustomLayer *scl);
bool SCULPT_temp_customlayer_release(SculptSession *ss, struct Object *ob, SculptCustomLayer *scl);
bool SCULPT_temp_customlayer_has(SculptSession *ss,
AttributeDomain domain,
int proptype,
const char *name);
void SCULPT_release_customlayers(SculptSession *ss, bool non_customdata_only);
void SCULPT_release_customlayers(SculptSession *ss, struct Object *ob, bool non_customdata_only);
bool SCULPT_dyntopo_automasking_init(const SculptSession *ss,
Sculpt *sd,
@ -2042,7 +2051,7 @@ struct BMesh *SCULPT_dyntopo_empty_bmesh();
/* initializes customdata layer used by SCULPT_neighbor_coords_average_interior when bound_smooth >
* 0.0f*/
void SCULPT_bound_smooth_ensure(SculptSession *ss);
void SCULPT_bound_smooth_ensure(SculptSession *ss, struct Object *ob);
#define SCULPT_stroke_needs_original(brush) \
ELEM(brush->sculpt_tool, \

View File

@ -97,8 +97,8 @@ static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op)
if (!create_face_set) {
SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
}
SCULPT_filter_cache_free(ss);
SCULPT_undo_push_end();
SCULPT_filter_cache_free(ss, ob);
SCULPT_undo_push_end(ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
ED_workspace_status_text(C, NULL);
}
@ -253,9 +253,9 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]);
}
SCULPT_filter_cache_free(ss);
SCULPT_filter_cache_free(ss, ob);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
ED_workspace_status_text(C, NULL);
return OPERATOR_FINISHED;

View File

@ -166,7 +166,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
multires_stitch_grids(ob);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask);
MEM_SAFE_FREE(nodes);

View File

@ -139,7 +139,7 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
SculptCustomLayer *scl_co, *scl_no, *scl_disp;
SCULPT_ensure_persistent_layers(ss);
SCULPT_ensure_persistent_layers(ss, ob);
scl_co = ss->custom_layers[SCULPT_SCL_PERS_CO];
scl_no = ss->custom_layers[SCULPT_SCL_PERS_NO];
@ -253,7 +253,7 @@ static int sculpt_spatial_sort_exec(bContext *C, wmOperator *op)
ss->pbvh = NULL;
/* Finish undo. */
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
break;
case PBVH_FACES:
@ -326,10 +326,11 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *op)
// symmetrize is messing up ids, regenerate them from scratch
BM_reassign_ids(ss->bm);
BM_mesh_toolflags_set(ss->bm, false);
BM_log_full_mesh(ss->bm, ss->bm_log);
/* Finish undo. */
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
break;
case PBVH_FACES:
@ -491,15 +492,25 @@ static int vertex_to_loop_colors_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
bool SCULPT_convert_colors_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
bool ok = ob && ob->data && ob->type == OB_MESH;
ok = ok && ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_OBJECT);
return ok;
}
static void SCULPT_OT_vertex_to_loop_colors(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Sculpt Vertex Color to Vertex Color";
ot->description = "Copy the Sculpt Vertex Color to a regular color layer";
ot->description = "Copy to active face corner color attribute";
ot->idname = "SCULPT_OT_vertex_to_loop_colors";
/* api callbacks */
ot->poll = SCULPT_vertex_colors_poll_no_bmesh;
ot->poll = SCULPT_convert_colors_poll;
ot->exec = vertex_to_loop_colors_exec;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -558,11 +569,11 @@ static void SCULPT_OT_loop_to_vertex_colors(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Vertex Color to Sculpt Vertex Color";
ot->description = "Copy the active loop color layer to the vertex color";
ot->description = "Load from active face corner color attribute";
ot->idname = "SCULPT_OT_loop_to_vertex_colors";
/* api callbacks */
ot->poll = SCULPT_vertex_colors_poll_no_bmesh;
ot->poll = SCULPT_convert_colors_poll;
ot->exec = loop_to_vertex_colors_exec;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -692,7 +703,7 @@ static int sculpt_sample_color_modal(bContext *C, wmOperator *op, const wmEvent
const bool over_mesh = SCULPT_cursor_geometry_info_update(C, &sgi, sccd->mval, false, false);
if (over_mesh) {
SculptVertRef active_vertex = SCULPT_active_vertex_get(ss);
copy_v4_v4(sccd->sampled_color, SCULPT_vertex_color_get(ss, active_vertex));
SCULPT_vertex_color_get(ss, active_vertex, sccd->sampled_color);
IMB_colormanagement_scene_linear_to_srgb_v3(sccd->sampled_color);
}
else {
@ -707,19 +718,23 @@ static int sculpt_sample_color_modal(bContext *C, wmOperator *op, const wmEvent
static int sculpt_sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e))
{
ARegion *region = CTX_wm_region(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
Brush *brush = BKE_paint_brush(&sd->paint);
ARegion *region = CTX_wm_region(C);
SculptSession *ss = ob->sculpt;
SculptVertRef active_vertex = SCULPT_active_vertex_get(ss);
float active_vertex_color[4];
if (!ss->bm && !ss->vcol) {
if (!SCULPT_vertex_color_get(ss, active_vertex, active_vertex_color)) {
return OPERATOR_CANCELLED;
}
else {
const SculptVertRef active_vertex = SCULPT_active_vertex_get(ss);
const float *active_vertex_color = SCULPT_vertex_color_get(ss, active_vertex);
float active_vertex_color[4];
SCULPT_vertex_color_get(ss, active_vertex, active_vertex_color);
if (!active_vertex_color) {
return OPERATOR_CANCELLED;
@ -727,7 +742,7 @@ static int sculpt_sample_color_invoke(bContext *C, wmOperator *op, const wmEvent
SampleColorCustomData *sccd = MEM_callocN(sizeof(SampleColorCustomData),
"Sample Color Custom Data");
copy_v4_v4(sccd->sampled_color, SCULPT_vertex_color_get(ss, active_vertex));
copy_v4_v4(sccd->sampled_color, active_vertex_color);
copy_v4_v4(sccd->initial_color, BKE_brush_color_get(scene, brush));
sccd->draw_handle = ED_region_draw_cb_activate(
@ -811,7 +826,7 @@ typedef struct MaskByColorContiguousFloodFillData {
float threshold;
bool invert;
float *new_mask;
float initial_color[3];
float initial_color[4];
} MaskByColorContiguousFloodFillData;
static void do_mask_by_color_contiguous_update_nodes_cb(
@ -852,7 +867,10 @@ static bool sculpt_mask_by_color_contiguous_floodfill_cb(
int to_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_v);
int from_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_v);
const float *current_color = SCULPT_vertex_color_get(ss, to_v);
const float current_color[4];
SCULPT_vertex_color_get(ss, to_v, current_color);
float new_vertex_mask = sculpt_mask_by_color_delta_get(
current_color, data->initial_color, data->threshold, data->invert);
data->new_mask[to_v_i] = new_vertex_mask;
@ -891,7 +909,7 @@ static void sculpt_mask_by_color_contiguous(Object *object,
ffd.threshold = threshold;
ffd.invert = invert;
ffd.new_mask = new_mask;
copy_v3_v3(ffd.initial_color, SCULPT_vertex_color_get(ss, vertex));
SCULPT_vertex_color_get(ss, vertex, ffd.initial_color);
SCULPT_floodfill_execute(ss, &flood, sculpt_mask_by_color_contiguous_floodfill_cb, &ffd);
SCULPT_floodfill_free(&flood);
@ -933,12 +951,18 @@ static void do_mask_by_color_task_cb(void *__restrict userdata,
const float threshold = data->mask_by_color_threshold;
const bool invert = data->mask_by_color_invert;
const bool preserve_mask = data->mask_by_color_preserve_mask;
const float *active_color = SCULPT_vertex_color_get(ss, data->mask_by_color_vertex);
float active_color[4];
SCULPT_vertex_color_get(ss, data->mask_by_color_vertex, active_color);
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
const float current_mask = *vd.mask;
const float new_mask = sculpt_mask_by_color_delta_get(active_color, vd.col, threshold, invert);
float vcolor[4];
SCULPT_vertex_color_get(ss, vd.vertex, vcolor);
const float new_mask = sculpt_mask_by_color_delta_get(active_color, vcolor, threshold, invert);
*vd.mask = sculpt_mask_by_color_final_mask_get(current_mask, new_mask, invert, preserve_mask);
if (current_mask == *vd.mask) {
@ -991,6 +1015,10 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
if (!SCULPT_has_colors(ss)) {
return OPERATOR_CANCELLED;
}
/* Color data is not available in Multires. */
if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
return OPERATOR_CANCELLED;
@ -1025,7 +1053,7 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
}
BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
@ -1110,7 +1138,7 @@ static int sculpt_set_limit_surface_exec(bContext *C, wmOperator *UNUSED(op))
SCULPT_vertex_random_access_ensure(ss);
if (ss->limit_surface) {
SCULPT_temp_customlayer_release(ss, ss->limit_surface);
SCULPT_temp_customlayer_release(ss, ob, ss->limit_surface);
}
MEM_SAFE_FREE(ss->limit_surface);
@ -1119,9 +1147,14 @@ static int sculpt_set_limit_surface_exec(bContext *C, wmOperator *UNUSED(op))
SculptLayerParams params = {.permanent = false, .simple_array = false};
SCULPT_temp_customlayer_ensure(
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "_sculpt_limit_surface", &params);
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "_sculpt_limit_surface", ss->limit_surface, &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "_sculpt_limit_surface", &params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
"_sculpt_limit_surface",
ss->limit_surface,
&params);
const int totvert = SCULPT_vertex_count_get(ss);
const bool weighted = false;
@ -1208,7 +1241,7 @@ static int sculpt_regularize_rake_exec(bContext *C, wmOperator *op)
SCULPT_ensure_dyntopo_node_undo(ob, nodes[i], SCULPT_UNDO_COLOR, -1);
BKE_pbvh_node_mark_update_color(nodes[i]);
}
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
MEM_SAFE_FREE(nodes);

View File

@ -101,8 +101,13 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata,
thread_id);
float smooth_color[4];
float color[4];
SCULPT_neighbor_color_average(ss, smooth_color, vd.vertex);
blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade);
SCULPT_vertex_color_get(ss, vd.vertex, color);
blend_color_interpolate_float(color, color, smooth_color, fade);
SCULPT_vertex_color_set(ss, vd.vertex, color);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@ -128,10 +133,6 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
PBVHVertexIter vd;
// SculptOrigVertData orig_data;
// SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COLOR);
// orig_data.datatype = SCULPT_UNDO_COLOR;
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
@ -227,18 +228,22 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
/* Final mix over the color/original-color using brush alpha. */
mul_v4_v4fl(buffer_color, color_buffer, alpha);
float vcolor[4];
SCULPT_vertex_color_get(ss, vd.vertex, vcolor);
if (do_accum) {
mul_v4_fl(buffer_color, fade);
IMB_blend_color_float(vd.col, vd.col, buffer_color, brush->blend);
vd.col[3] = 1.0f;
IMB_blend_color_float(vcolor, vcolor, buffer_color, brush->blend);
vcolor[3] = 1.0f;
}
else {
MSculptVert *mv = SCULPT_vertex_get_mdyntopo(ss, vd.vertex);
IMB_blend_color_float(vd.col, mv->origcolor, buffer_color, brush->blend);
IMB_blend_color_float(vcolor, mv->origcolor, buffer_color, brush->blend);
}
CLAMP4(vd.col, 0.0f, 1.0f);
CLAMP4(vcolor, 0.0f, 1.0f);
SCULPT_vertex_color_set(ss, vd.vertex, vcolor);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@ -273,7 +278,10 @@ static void do_sample_wet_paint_task_cb(void *__restrict userdata,
continue;
}
add_v4_v4(swptd->color, vd.col);
float col[4];
SCULPT_vertex_color_get(ss, vd.vertex, col);
add_v4_v4(swptd->color, col);
swptd->tot_samples++;
}
BKE_pbvh_vertex_iter_end;
@ -295,7 +303,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
SculptSession *ss = ob->sculpt;
Brush *brush = ss->cache ? ss->cache->brush : BKE_paint_brush(&sd->paint);
if (!ss->vcol) {
if (!SCULPT_has_colors(ss)) {
return;
}
@ -358,7 +366,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
};
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, false, totnode);
BLI_task_parallel_range(0, totnode, &data, do_color_smooth_task_cb_exec, &settings);
return;
}
@ -414,14 +422,19 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
// reuse smear's buffer name
SCULPT_temp_customlayer_ensure(
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &params);
SCULPT_temp_customlayer_ensure(
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, "_paint_buffer_stroke_id", &params_id);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, "_paint_buffer_stroke_id", &params_id);
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &buffer_scl, &params);
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, "_paint_buffer_stroke_id", &stroke_id_scl, &params_id);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &buffer_scl, &params);
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_INT32,
"_paint_buffer_stroke_id",
&stroke_id_scl,
&params_id);
/* Threaded loop over nodes. */
SculptThreadedTaskData data = {
@ -438,7 +451,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
};
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
BKE_pbvh_parallel_range_settings(&settings, false, totnode);
BLI_task_parallel_range(0, totnode, &data, do_paint_brush_task_cb_ex, &settings);
if (brush->vcol_boundary_factor > 0.0f) {
@ -446,9 +459,9 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
}
}
static void do_smear_brush_task_cb_exec(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
ATTR_NO_OPT static void do_smear_brush_task_cb_exec(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
@ -505,6 +518,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
float vertex_disp_norm[3];
sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.vertex), vd.co);
const float *neighbor_color = SCULPT_temp_cdata_get(ni.vertex, data->scl);
normalize_v3_v3(vertex_disp_norm, vertex_disp);
if (dot_v3v3(current_disp_norm, vertex_disp_norm) >= 0.0f) {
continue;
@ -518,7 +532,12 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
blend_color_interpolate_float(vd.col, prev_color, interp_color, fade * blend);
float vcolor[4];
SCULPT_vertex_color_get(ss, vd.vertex, vcolor);
blend_color_interpolate_float(vcolor, prev_color, interp_color, fade * blend);
clamp_v4(vcolor, 0.0f, 1.0f);
SCULPT_vertex_color_set(ss, vd.vertex, vcolor);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@ -527,19 +546,15 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls))
ATTR_NO_OPT static void do_smear_store_prev_colors_task_cb_exec(
void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
copy_v4_v4((float *)SCULPT_temp_cdata_get(vd.vertex, data->scl),
SCULPT_vertex_color_get(ss, vd.vertex));
// copy_v4_v4(ss->cache->prev_colors[vd.index], SCULPT_vertex_color_get(ss, vd.vertex));
SCULPT_vertex_color_get(ss, vd.vertex, (float *)SCULPT_temp_cdata_get(vd.vertex, data->scl));
}
BKE_pbvh_vertex_iter_end;
}
@ -549,19 +564,19 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
SculptSession *ss = ob->sculpt;
Brush *brush = ss->cache ? ss->cache->brush : BKE_paint_brush(&sd->paint);
if (!ss->vcol) {
if (!SCULPT_has_colors(ss)) {
return;
}
SCULPT_vertex_random_access_ensure(ss);
SculptCustomLayer prev_scl;
SculptLayerParams params = {.permanent = false, .simple_array = false};
SCULPT_temp_customlayer_ensure(
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &params);
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &prev_scl, &params);
SCULPT_vertex_random_access_ensure(ss);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &prev_scl, &params);
BKE_curvemapping_init(brush->curve);

View File

@ -797,7 +797,7 @@ void SCULPT_replay_make_cube(struct bContext *C, int steps)
BKE_pbvh_free(ss->pbvh);
ss->pbvh = NULL;
SCULPT_dyntopo_node_layers_update_offsets(ss);
SCULPT_dyntopo_node_layers_update_offsets(ss, ob);
/* Redraw. */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@ -931,7 +931,7 @@ void SCULPT_replay(struct bContext *C)
ss->cache = NULL;
}
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
log->is_playing = false;
}

View File

@ -589,9 +589,13 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
// th = 1.0 - th;
#if 0
float *color = (float *)SCULPT_vertex_color_get(ss,ni.vertex);
float color[4];
SCULPT_vertex_color_get(ss,ni.vertex, color);
color[0] = color[1] = color[2] = th;
color[3] = 1.0f;
SCULPT_vertex_color_set(ss, ni.vertex, color);
#endif
float fac = bound_smooth;
@ -1168,14 +1172,18 @@ float SCULPT_neighbor_mask_average(SculptSession *ss, SculptVertRef index)
return SCULPT_vertex_mask_get(ss, index);
}
void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], SculptVertRef index)
void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], SculptVertRef vertex)
{
float avg[4] = {0.0f, 0.0f, 0.0f, 0.0f};
int total = 0;
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
add_v4_v4(avg, SCULPT_vertex_color_get(ss, ni.vertex));
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
float tmp[4] = {0};
SCULPT_vertex_color_get(ss, ni.vertex, tmp);
add_v4_v4(avg, tmp);
total++;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
@ -1184,7 +1192,7 @@ void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], SculptVer
mul_v4_v4fl(result, avg, 1.0f / total);
}
else {
copy_v4_v4(result, SCULPT_vertex_color_get(ss, index));
SCULPT_vertex_color_get(ss, vertex, result);
}
}
@ -1248,9 +1256,9 @@ static void SCULPT_enhance_details_brush(Sculpt *sd,
bool weighted = SCULPT_get_int(ss, use_weighted_smooth, sd, brush);
SCULPT_temp_customlayer_ensure(
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &params);
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &scl, &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &scl, &params);
if (SCULPT_stroke_is_first_brush_step(ss->cache) &&
(ss->cache->brush->flag2 & BRUSH_SMOOTH_USE_AREA_WEIGHT)) {
@ -1540,7 +1548,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
}
#endif
void SCULPT_bound_smooth_ensure(SculptSession *ss)
void SCULPT_bound_smooth_ensure(SculptSession *ss, Object *ob)
{
SculptLayerParams params = {.permanent = true, .simple_array = false};
@ -1549,6 +1557,7 @@ void SCULPT_bound_smooth_ensure(SculptSession *ss)
"bound_scl");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_COLOR,
"t__smooth_bdist",
@ -1592,6 +1601,7 @@ void SCULPT_smooth(Sculpt *sd,
"vel_smooth_scl");
SCULPT_temp_customlayer_get(ss,
ob,
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
"__scl_smooth_vel",
@ -1642,7 +1652,7 @@ void SCULPT_smooth(Sculpt *sd,
bound_smooth = powf(ss->cache->brush->boundary_smooth_factor, BOUNDARY_SMOOTH_EXP);
/* ensure ss->custom_layers[SCULPT_SCL_SMOOTH_BDIS] exists */
SCULPT_bound_smooth_ensure(ss);
SCULPT_bound_smooth_ensure(ss, ob);
}
#ifdef PROXY_ADVANCED
@ -1905,9 +1915,9 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
SculptLayerParams params = {.permanent = false, .simple_array = false};
SCULPT_temp_customlayer_ensure(
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", &params);
SCULPT_temp_customlayer_get(
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", &scl, &params);
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", &scl, &params);
if (SCULPT_stroke_is_first_brush_step(ss->cache) &&
(ss->cache->brush->flag2 & BRUSH_SMOOTH_USE_AREA_WEIGHT)) {
@ -2172,9 +2182,9 @@ static void do_smooth_vcol_boundary_brush_task_cb_ex(void *__restrict userdata,
float avg[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float tot = 0.0f;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (!vd.col) {
continue;
}
float vcolor[4];
SCULPT_vertex_color_get(ss, vd.vertex, vcolor);
if (sculpt_brush_test_sq_fn(&test, vd.co)) {
const float fade = bstrength * SCULPT_brush_strength_factor(
@ -2188,7 +2198,7 @@ static void do_smooth_vcol_boundary_brush_task_cb_ex(void *__restrict userdata,
vd.vertex,
thread_id);
madd_v3_v3fl(avg, vd.col, fade);
madd_v3_v3fl(avg, vcolor, fade);
tot += fade;
}
}
@ -2220,14 +2230,15 @@ static void do_smooth_vcol_boundary_brush_task_cb_ex(void *__restrict userdata,
smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
vd.vertex,
thread_id);
if (!vd.col) {
continue;
}
float vcolor[4];
SCULPT_vertex_color_get(ss, vd.vertex, vcolor);
float avg2[3], avg3[3], val[3];
float tot2 = 0.0f, tot4 = 0.0f;
copy_v4_v4(avg, vd.col);
copy_v4_v4(avg, vcolor);
zero_v3(avg2);
zero_v3(avg3);
@ -2237,7 +2248,9 @@ static void do_smooth_vcol_boundary_brush_task_cb_ex(void *__restrict userdata,
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) {
const float *col = SCULPT_vertex_color_get(ss, ni.vertex);
float col[4];
SCULPT_vertex_color_get(ss, ni.vertex, col);
const float *co = SCULPT_vertex_co_get(ss, ni.vertex);
// simple color metric. TODO: plug in appropriate color space code?

View File

@ -90,7 +90,7 @@ void ED_sculpt_init_transform(struct bContext *C, Object *ob)
case SCULPT_TRANSFORM_DEFORM_TARGET_CLOTH_SIM:
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
ss->filter_cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
ss, 1.0f, 1.0f, 0.0f, true, false);
ss, ob, 1.0f, 1.0f, 0.0f, true, false);
SCULPT_cloth_brush_simulation_init(ss, ss->filter_cache->cloth_sim);
SCULPT_cloth_brush_store_simulation_state(ss, ss->filter_cache->cloth_sim);
SCULPT_cloth_brush_ensure_nodes_constraints(sd,
@ -385,13 +385,13 @@ void ED_sculpt_end_transform(struct bContext *C, Object *ob)
{
SculptSession *ss = ob->sculpt;
if (ss->filter_cache) {
SCULPT_filter_cache_free(ss);
SCULPT_filter_cache_free(ss, ob);
}
/* Force undo push to happen even inside transform operator, since the sculpt
* undo system works separate from regular undo and this is require to properly
* finish an undo step also when canceling. */
const bool use_nested_undo = true;
SCULPT_undo_push_end_ex(use_nested_undo);
SCULPT_undo_push_end_ex(ob, use_nested_undo);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
}

View File

@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "BKE_attribute.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
@ -48,6 +49,7 @@
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_multires.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@ -112,6 +114,8 @@
* End of dynamic topology and symmetrize in this mode are handled in a special
* manner as well. */
#define NO_ACTIVE_LAYER ATTR_DOMAIN_AUTO
typedef struct UndoSculpt {
ListBase nodes;
@ -119,13 +123,30 @@ typedef struct UndoSculpt {
BMLog *bm_restore;
} UndoSculpt;
typedef struct SculptAttrRef {
AttributeDomain domain;
int type;
char name[MAX_CUSTOMDATA_LAYER_NAME];
bool was_set;
} SculptAttrRef;
typedef struct SculptUndoStep {
UndoStep step;
/* NOTE: will split out into list for multi-object-sculpt-mode. */
UndoSculpt data;
int id;
// active vcol layer
SculptAttrRef active_attr_start;
SculptAttrRef active_attr_end;
bContext *C;
} SculptUndoStep;
static UndoSculpt *sculpt_undo_get_nodes(void);
static bool sculpt_attr_ref_equals(SculptAttrRef *a, SculptAttrRef *b);
static void sculpt_save_active_attr(Object *ob, SculptAttrRef *attr);
static void update_unode_bmesh_memsize(SculptUndoNode *unode);
static UndoSculpt *sculpt_undo_get_nodes(void);
void sculpt_undo_print_nodes(void *active);
@ -346,14 +367,33 @@ static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode)
Object *ob = OBACT(view_layer);
SculptSession *ss = ob->sculpt;
if (!ss->pmap) {
Mesh *me = BKE_object_get_original_mesh(ob);
BKE_mesh_vert_poly_map_create(&ss->pmap,
&ss->pmap_mem,
me->mvert,
me->medge,
me->mpoly,
me->mloop,
me->totvert,
me->totpoly,
me->totloop,
false);
}
if (unode->maxvert) {
/* regular mesh restore */
SculptVertRef *index = unode->index;
MVert *mvert = ss->mvert;
MPropCol *vcol = ss->vcol;
for (int i = 0; i < unode->totvert; i++) {
swap_v4_v4(vcol[index[i].i].color, unode->col[i]);
float tmp[4];
SCULPT_vertex_color_get(ss, index[i], tmp);
SCULPT_vertex_color_set(ss, index[i], unode->col[i]);
copy_v4_v4(unode->col[i], tmp);
mvert[index[i].i].flag |= ME_VERT_PBVH_UPDATE;
}
}
@ -671,7 +711,7 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
NULL,
(void *)&data};
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
// pbvh_bmesh_check_nodes(ss->pbvh);
@ -753,8 +793,8 @@ static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode, bool is_
.active_shapekey = ob->shapenr,
}));
SCULPT_dyntopo_node_layers_add(ss);
SCULPT_update_customdata_refs(ss);
SCULPT_dyntopo_node_layers_add(ss, ob);
SCULPT_update_customdata_refs(ss, ob);
if (ss->pbvh && ss->bm) {
SCULT_dyntopo_flag_all_disk_sort(ss);
@ -971,7 +1011,7 @@ static int sculpt_undo_bmesh_restore(
if (ss->bm_log && ss->bm &&
!ELEM(unode->type, SCULPT_UNDO_DYNTOPO_BEGIN, SCULPT_UNDO_DYNTOPO_END)) {
SCULPT_update_customdata_refs(ss);
SCULPT_update_customdata_refs(ss, ob);
BM_log_set_cd_offsets(ss->bm_log, ss->cd_sculpt_vert);
#if 0
@ -1101,7 +1141,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
bool update = false, rebuild = false, update_mask = false, update_visibility = false;
bool need_mask = false;
bool need_refine_subdiv = false;
bool did_first_hack = false;
// bool did_first_hack = false;
for (unode = lb->first; unode; unode = unode->next) {
#if 0
@ -1124,7 +1164,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
ss->bm_log = log;
SCULPT_dyntopo_node_layers_update_offsets(ss);
SCULPT_dyntopo_node_layers_update_offsets(ss, ob);
BM_log_set_cd_offsets(ss->bm_log, ss->cd_sculpt_vert);
}
@ -1350,6 +1390,9 @@ static void sculpt_undo_free_list(ListBase *lb)
if (unode->nodemap) {
MEM_freeN(unode->nodemap);
}
if (unode->col) {
MEM_freeN(unode->col);
}
if (unode->no) {
MEM_freeN(unode->no);
}
@ -1558,7 +1601,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
usculpt->undo_size += alloc_size;
/* FIXME: Should explain why this is allocated here, to be freed in
* `SCULPT_undo_push_end_ex()`? */
* `SCULPT_undo_push_end_ex(ob)`? */
alloc_size = sizeof(*unode->no) * (size_t)allvert;
unode->no = MEM_callocN(alloc_size, "SculptUndoNode.no");
usculpt->undo_size += alloc_size;
@ -1651,8 +1694,6 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
if (ss->deform_modifiers_active) {
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, unode->index[vd.i]);
copy_v3_v3(unode->orig_co[vd.i], orig_data.co);
}
}
@ -1699,7 +1740,10 @@ static void sculpt_undo_store_color(Object *ob, SculptUndoNode *unode)
// unode->gen++;
BKE_pbvh_vertex_iter_begin (ss->pbvh, unode->node, vd, PBVH_ITER_ALL) {
copy_v4_v4(unode->col[vd.i], vd.col);
float col[4];
SCULPT_vertex_color_get(ss, vd.vertex, col);
copy_v4_v4(unode->col[vd.i], col);
}
BKE_pbvh_vertex_iter_end;
}
@ -1896,7 +1940,6 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
case SCULPT_UNDO_COLOR: {
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
float *dummy;
bm_logstack_push();
BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset, true);
bm_logstack_pop();
@ -1928,6 +1971,8 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
case SCULPT_UNDO_GEOMETRY:
BM_log_full_mesh(ss->bm, ss->bm_log);
break;
default: // to avoid warnings
break;
}
}
@ -2041,7 +2086,7 @@ static bool check_first_undo_entry_dyntopo(Object *ob)
if (bad) {
sculpt_undo_push_begin_ex(ob, "Dyntopo Begin", true);
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
}
return bad;
@ -2148,9 +2193,33 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
return unode;
}
static bool sculpt_attr_ref_equals(SculptAttrRef *a, SculptAttrRef *b)
{
return a->domain == b->domain && a->type == b->type && STREQ(a->name, b->name);
}
static void sculpt_save_active_attr(Object *ob, SculptAttrRef *attr)
{
Mesh *me = BKE_object_get_original_mesh(ob);
CustomDataLayer *cl;
if (ob && me && (cl = BKE_id_attributes_active_get((ID *)me))) {
attr->domain = BKE_id_attribute_domain((ID *)me, cl);
BLI_strncpy(attr->name, cl->name, sizeof(attr->name));
attr->type = cl->type;
}
else {
attr->domain = NO_ACTIVE_LAYER;
attr->name[0] = 0;
}
attr->was_set = true;
}
void sculpt_undo_push_begin_ex(Object *ob, const char *name, bool no_first_entry_check)
{
UndoStack *ustack = ED_undo_stack_get();
SculptUndoStep *us;
SCULPT_undo_ensure_bmlog(ob);
@ -2168,7 +2237,12 @@ void sculpt_undo_push_begin_ex(Object *ob, const char *name, bool no_first_entry
/* Special case, we never read from this. */
bContext *C = NULL;
BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_SCULPT);
us = (SculptUndoStep *)BKE_undosys_step_push_init_with_type(
ustack, C, name, BKE_UNDOSYS_TYPE_SCULPT);
if (!us->active_attr_start.was_set) {
sculpt_save_active_attr(ob, &us->active_attr_start);
}
SculptSession *ss = ob->sculpt;
@ -2193,12 +2267,12 @@ void SCULPT_undo_push_begin(Object *ob, const char *name)
sculpt_undo_push_begin_ex(ob, name, false);
}
void SCULPT_undo_push_end(void)
void SCULPT_undo_push_end(Object *ob)
{
SCULPT_undo_push_end_ex(false);
SCULPT_undo_push_end_ex(ob, false);
}
void SCULPT_undo_push_end_ex(const bool use_nested_undo)
void SCULPT_undo_push_end_ex(struct Object *ob, const bool use_nested_undo)
{
UndoSculpt *usculpt = sculpt_undo_get_nodes();
SculptUndoNode *unode;
@ -2226,22 +2300,53 @@ void SCULPT_undo_push_end_ex(const bool use_nested_undo)
}
WM_file_tag_modified();
}
UndoStack *ustack = ED_undo_stack_get();
SculptUndoStep *us = (SculptUndoStep *)BKE_undosys_stack_init_or_active_with_type(
ustack, BKE_UNDOSYS_TYPE_SCULPT);
sculpt_save_active_attr(ob, &us->active_attr_end);
}
/* -------------------------------------------------------------------- */
/** \name Implements ED Undo System
* \{ */
static void sculpt_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p)
static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr)
{
Object *ob = CTX_data_active_object(C);
Mesh *me = BKE_object_get_original_mesh(ob);
if (attr->domain == NO_ACTIVE_LAYER) {
// from reading the code, it appears you cannot set
// the active layer to NULL, so don't worry about it.
// BKE_id_attributes_active_set(&me->id, NULL);
return;
}
SculptAttrRef existing;
sculpt_save_active_attr(ob, &existing);
if (!sculpt_attr_ref_equals(&existing, attr) && ob->sculpt && ob->sculpt->pbvh) {
BKE_pbvh_update_vertex_data(ob->sculpt->pbvh, PBVH_UpdateColor);
}
CustomDataLayer *cl;
cl = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain);
if (cl) {
BKE_id_attributes_active_set(&me->id, cl);
}
}
static void sculpt_undosys_step_encode_init(struct bContext *C, UndoStep *us_p)
{
SculptUndoStep *us = (SculptUndoStep *)us_p;
/* Dummy, memory is cleared anyway. */
BLI_listbase_clear(&us->data.nodes);
}
static bool sculpt_undosys_step_encode(struct bContext *UNUSED(C),
struct Main *bmain,
UndoStep *us_p)
static bool sculpt_undosys_step_encode(struct bContext *C, struct Main *bmain, UndoStep *us_p)
{
/* Dummy, encoding is done along the way by adding tiles
* to the current 'SculptUndoStep' added by encode_init. */
@ -2300,10 +2405,18 @@ static void sculpt_undosys_step_decode_undo(struct bContext *C,
while ((us_iter != us) || (!is_final && us_iter == us)) {
BLI_assert(us_iter->step.type == us->step.type); /* Previous loop ensures this. */
sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_start);
sculpt_undosys_step_decode_undo_impl(C, depsgraph, us_iter);
// sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_start);
if (us_iter == us) {
if (us_iter->step.prev && us_iter->step.prev->type == BKE_UNDOSYS_TYPE_SCULPT) {
sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter->step.prev)->active_attr_end);
}
break;
}
us_iter = (SculptUndoStep *)us_iter->step.prev;
}
}
@ -2320,8 +2433,11 @@ static void sculpt_undosys_step_decode_redo(struct bContext *C,
us_iter = (SculptUndoStep *)us_iter->step.prev;
}
while (us_iter && (us_iter->step.is_applied == false)) {
sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_start);
sculpt_undosys_step_decode_redo_impl(C, depsgraph, us_iter);
if (us_iter == us) {
sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_end);
break;
}
us_iter = (SculptUndoStep *)us_iter->step.next;
@ -2353,8 +2469,6 @@ static void sculpt_undosys_step_decode(
* (some) evaluated data. */
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
Mesh *me = ob->data;
#ifndef WHEN_GLOBAL_UNDO_WORKS
/* Don't add sculpt topology undo steps when reading back undo state.
* The undo steps must enter/exit for us. */
@ -2398,7 +2512,7 @@ void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name)
void ED_sculpt_undo_geometry_end(struct Object *ob)
{
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY);
SCULPT_undo_push_end();
SCULPT_undo_push_end(ob);
}
/* Export for ED_undo_sys. */
@ -2535,7 +2649,7 @@ void ED_sculpt_undo_push_multires_mesh_end(bContext *C, const char *str)
SculptUndoNode *geometry_unode = SCULPT_undo_push_node(object, NULL, SCULPT_UNDO_GEOMETRY);
geometry_unode->geometry_clear_pbvh = false;
SCULPT_undo_push_end();
SCULPT_undo_push_end(object);
}
/** \} */

View File

@ -983,8 +983,7 @@ static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, Pointer
if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
if (U.experimental.use_sculpt_vertex_colors &&
RNA_collection_length(&dataptr, "sculpt_vertex_colors")) {
if (RNA_collection_length(&dataptr, "sculpt_vertex_colors")) {
uiItemPointerR(
layout, ptr, "layer_name", &dataptr, "sculpt_vertex_colors", "", ICON_GROUP_VCOL);
}

View File

@ -25,6 +25,8 @@
#include <stddef.h>
#include "BKE_attribute.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -49,6 +51,24 @@ struct CustomData;
/* Buffers for drawing from PBVH grids. */
typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
typedef struct PBVHGPUBuildArgs {
GPU_PBVH_Buffers *buffers;
struct BMesh *bm;
struct TableGSet *bm_faces;
struct TableGSet *bm_unique_verts;
struct TableGSet *bm_other_verts;
struct PBVHTriBuf *tribuf;
const int update_flags;
const int cd_vert_node_offset;
int face_sets_color_seed;
int face_sets_color_default;
bool flat_vcol;
short mat_nr, active_vcol_type, active_vcol_domain;
} PBVHGPUBuildArgs;
/* Build must be called once before using the other functions, used every time
* mesh topology changes. Threaded. */
GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const struct MPoly *mpoly,
@ -80,31 +100,23 @@ enum {
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const struct MVert *mvert,
const float *vmask,
const struct MLoopCol *vcol,
const void *vcol_data,
const int vcol_type,
const AttributeDomain vcol_domain,
const int *sculpt_face_sets,
const int face_sets_color_seed,
const int face_sets_color_default,
const struct MPropCol *vtcol,
const int update_flags);
void GPU_pbvh_update_attribute_names(
struct CustomData *vdata,
struct CustomData *ldata,
CustomData *vdata,
CustomData *ldata,
bool need_full_render,
bool fast_mode); // fast mode renders without vcol, uv, facesets, even mask, etc
bool fast_mode,
int active_vcol_type,
int active_vcol_domain); // fast mode renders without vcol, uv, facesets, even mask, etc
void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
struct BMesh *bm,
struct TableGSet *bm_faces,
struct TableGSet *bm_unique_verts,
struct TableGSet *bm_other_verts,
struct PBVHTriBuf *tribuf,
const int update_flags,
const int cd_vert_node_offset,
int face_sets_color_seed,
int face_sets_color_default,
bool flat_vcol,
short mat_nr);
void GPU_pbvh_bmesh_buffers_update(PBVHGPUBuildArgs *args);
void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
struct SubdivCCG *subdiv_ccg,

View File

@ -45,7 +45,9 @@
#include "DNA_userdef_types.h"
#include "BKE_DerivedMesh.h"
#include "BKE_attribute.h"
#include "BKE_ccg.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_paint.h"
@ -76,8 +78,6 @@ all other attributes.
To test, enable #if 0 branch in sculpt_draw_cb in draw_manager_data.c
*/
//#define QUANTIZED_PERF_TEST
//#define NEW_ATTR_SYSTEM
struct GPU_PBVH_Buffers {
@ -121,9 +121,6 @@ struct GPU_PBVH_Buffers {
void *last_tribuf_tris; // used to detect if we can reuse index buffers
bool show_overlay;
#ifdef QUANTIZED_PERF_TEST
float matrix[4][4];
#endif
};
#ifdef NEW_ATTR_SYSTEM
@ -146,10 +143,18 @@ typedef struct CDAttrLayers {
} CDAttrLayers;
#endif
typedef struct ColorRef {
uchar domain, type;
ushort cd_offset;
int layer_idx;
} ColorRef;
#define MAX_GPU_MCOL 256
static struct {
GPUVertFormat format;
uint pos, nor, msk, fset, uv;
uint col[MAX_MCOL];
uint col[MAX_GPU_MCOL];
int totcol;
#ifdef NEW_ATTR_SYSTEM
@ -360,7 +365,7 @@ static void free_cd_layers(CDAttrLayers *cdattr)
void gpu_pbvh_init()
{
GPU_pbvh_update_attribute_names(NULL, NULL, false, false);
GPU_pbvh_update_attribute_names(NULL, NULL, false, false, -1, -1);
}
void gpu_pbvh_exit()
@ -400,23 +405,14 @@ static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, uint vert_len)
return GPU_vertbuf_get_data(buffers->vert_buf) != NULL;
}
/* was used by QUANTIZED_PERF_TEST, now unused */
float *GPU_pbvh_get_extra_matrix(GPU_PBVH_Buffers *buffers)
{
#ifdef QUANTIZED_PERF_TEST
return (float *)buffers->matrix;
#else
return NULL;
#endif
}
static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim)
{
#ifdef QUANTIZED_PERF_TEST
memset(buffers->matrix, 0, sizeof(buffers->matrix));
buffers->matrix[0][0] = buffers->matrix[1][1] = buffers->matrix[2][2] = buffers->matrix[3][3] =
1.0f;
#endif
if (buffers->triangles == NULL) {
buffers->triangles = GPU_batch_create(prim,
buffers->vert_buf,
@ -460,20 +456,25 @@ static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt,
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const MVert *mvert,
const float *vmask,
const MLoopCol *vcol,
const void *vcol_data,
const int vcol_type,
const AttributeDomain vcol_domain,
const int *sculpt_face_sets,
const int face_sets_color_seed,
const int face_sets_color_default,
const MPropCol *vtcol,
const int update_flags)
{
const bool show_mask = vmask && (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0 &&
!g_vbo_id.fast_mode;
const bool show_face_sets = sculpt_face_sets &&
(update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0 &&
!g_vbo_id.fast_mode;
const bool show_vcol = (vcol || (vtcol && U.experimental.use_sculpt_vertex_colors)) &&
const MPropCol *vtcol = vcol_type == CD_PROP_COLOR ? vcol_data : NULL;
const MLoopCol *vcol = vcol_type == CD_MLOOPCOL ? vcol_data : NULL;
const float(*f3col)[3] = vcol_type == CD_PROP_FLOAT3 ? vcol_data : NULL;
const bool color_loops = vcol_domain == ATTR_DOMAIN_CORNER;
const bool show_vcol = (vtcol || vcol || f3col) &&
(update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
const bool show_mask = vmask && (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
const bool show_face_sets = sculpt_face_sets &&
(update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0;
bool empty_mask = true;
bool default_face_set = true;
@ -556,16 +557,40 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
/* Vertex Colors. */
if (show_vcol) {
ushort scol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
if (vtcol && U.experimental.use_sculpt_vertex_colors) {
scol[0] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[0]);
scol[1] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[1]);
scol[2] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[2]);
scol[3] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[3]);
if (vtcol) {
if (color_loops) {
scol[0] = unit_float_to_ushort_clamp(vtcol[lt->tri[j]].color[0]);
scol[1] = unit_float_to_ushort_clamp(vtcol[lt->tri[j]].color[1]);
scol[2] = unit_float_to_ushort_clamp(vtcol[lt->tri[j]].color[2]);
scol[3] = unit_float_to_ushort_clamp(vtcol[lt->tri[j]].color[3]);
}
else {
scol[0] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[0]);
scol[1] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[1]);
scol[2] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[2]);
scol[3] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[3]);
}
memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol));
}
else {
else if (f3col) {
if (color_loops) {
scol[0] = unit_float_to_ushort_clamp(f3col[lt->tri[j]][0]);
scol[1] = unit_float_to_ushort_clamp(f3col[lt->tri[j]][1]);
scol[2] = unit_float_to_ushort_clamp(f3col[lt->tri[j]][2]);
scol[3] = USHRT_MAX;
}
else {
scol[0] = unit_float_to_ushort_clamp(f3col[vtri[j]][0]);
scol[1] = unit_float_to_ushort_clamp(f3col[vtri[j]][1]);
scol[2] = unit_float_to_ushort_clamp(f3col[vtri[j]][2]);
scol[3] = USHRT_MAX;
}
memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol));
}
else if (vcol) {
const uint loop_index = lt->tri[j];
const MLoopCol *mcol = &vcol[loop_index];
const MLoopCol *mcol = vcol + (color_loops ? loop_index : vtri[j]);
scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]);
scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]);
scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]);
@ -1063,20 +1088,103 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hid
static int debug_pass = 0;
bool pbvh_show_orig_co = false;
ATTR_NO_OPT static void gpu_bmesh_get_vcol(BMVert *v,
BMLoop *l,
const ColorRef *ref,
float color[4])
{
if (ref->domain == ATTR_DOMAIN_POINT) {
switch (ref->type) {
case CD_PROP_COLOR:
copy_v4_v4(color, (float *)BM_ELEM_CD_GET_VOID_P(v, ref->cd_offset));
break;
case CD_MLOOPCOL: {
MLoopCol *mp = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(v, ref->cd_offset);
rgba_uchar_to_float(color, (const char *)mp);
srgb_to_linearrgb_v3_v3(color, color);
break;
}
}
}
else if (l) {
switch (ref->type) {
case CD_PROP_COLOR:
copy_v4_v4(color, (float *)BM_ELEM_CD_GET_VOID_P(l, ref->cd_offset));
break;
case CD_MLOOPCOL: {
MLoopCol *mp = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(l, ref->cd_offset);
rgba_uchar_to_float(color, (const char *)mp);
srgb_to_linearrgb_v3_v3(color, color);
break;
}
}
}
else { /*average all loop colors*/
BMEdge *e = v->e;
zero_v4(color);
if (!e) {
return;
}
int tot = 0;
do {
BMLoop *l = e->l;
if (!l) {
continue;
}
do {
switch (ref->type) {
case CD_PROP_COLOR:
add_v4_v4(color, (float *)BM_ELEM_CD_GET_VOID_P(l, ref->cd_offset));
tot++;
break;
case CD_MLOOPCOL: {
MLoopCol *mp = (MLoopCol *)BM_ELEM_CD_GET_VOID_P(l, ref->cd_offset);
float temp[4];
rgba_uchar_to_float(temp, (const char *)mp);
srgb_to_linearrgb_v3_v3(temp, temp);
add_v4_v4(color, temp);
tot++;
break;
}
}
} while ((l = l->radial_next) != e->l);
} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
if (tot > 0) {
mul_v4_fl(color, 1.0f / (float)tot);
}
}
}
/* Output a BMVert into a VertexBufferFormat array at v_index. */
static void gpu_bmesh_vert_to_buffer_copy(BMesh *bm,
BMVert *v,
GPUVertBuf *vert_buf,
int v_index,
const float fno[3],
const float *fmask,
const int cd_vert_mask_offset,
const int cd_vert_node_offset,
const bool show_mask,
const bool show_vcol,
bool *empty_mask,
const int cd_vcol_offsets[MAX_MCOL],
int totvcol)
ATTR_NO_OPT static void gpu_bmesh_vert_to_buffer_copy(BMesh *bm,
BMVert *v,
BMLoop *l,
GPUVertBuf *vert_buf,
int v_index,
const float fno[3],
const float *fmask,
const int cd_vert_mask_offset,
const int cd_vert_node_offset,
const bool show_mask,
const bool show_vcol,
bool *empty_mask,
const ColorRef *vcol_layers,
const int totvcol)
{
/* Vertex should always be visible if it's used by a visible face. */
BLI_assert(!BM_elem_flag_test(v, BM_ELEM_HIDDEN));
@ -1123,14 +1231,15 @@ static void gpu_bmesh_vert_to_buffer_copy(BMesh *bm,
# ifndef NEW_ATTR_SYSTEM
if (show_vcol && totvcol > 0) {
for (int i = 0; i < totvcol; i++) {
ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
float color[4];
gpu_bmesh_get_vcol(v, l, vcol_layers + i, color);
MPropCol *col = BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offsets[i]);
ushort vcol[4];
vcol[0] = unit_float_to_ushort_clamp(col->color[0]);
vcol[1] = unit_float_to_ushort_clamp(col->color[1]);
vcol[2] = unit_float_to_ushort_clamp(col->color[2]);
vcol[3] = unit_float_to_ushort_clamp(col->color[3]);
vcol[0] = unit_float_to_ushort_clamp(color[0]);
vcol[1] = unit_float_to_ushort_clamp(color[1]);
vcol[2] = unit_float_to_ushort_clamp(color[2]);
vcol[3] = unit_float_to_ushort_clamp(color[3]);
// const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col[i], v_index, vcol);
@ -1182,7 +1291,6 @@ static int gpu_bmesh_vert_visible_count(TableGSet *bm_unique_verts, TableGSet *b
static int gpu_bmesh_face_visible_count(PBVHTriBuf *tribuf, int mat_nr)
{
int totface = 0;
BMFace *f;
for (int i = 0; i < tribuf->tottri; i++) {
PBVHTri *tri = tribuf->tris + i;
@ -1210,16 +1318,22 @@ void GPU_pbvh_bmesh_buffers_update_free(GPU_PBVH_Buffers *buffers)
}
static int gpu_pbvh_bmesh_make_vcol_offs(CustomData *vdata,
int r_cd_vcols[MAX_MCOL],
int r_cd_layers[MAX_MCOL],
bool active_only)
CustomData *ldata,
ColorRef r_cd_vcols[MAX_GPU_MCOL],
bool active_only,
int active_type,
int active_domain)
{
if (active_only) {
int idx = CustomData_get_offset(vdata, CD_PROP_COLOR);
CustomData *cdata = active_domain == ATTR_DOMAIN_POINT ? vdata : ldata;
int idx = active_type != -1 ? CustomData_get_active_layer_index(cdata, active_type) : -1;
if (idx >= 0) {
r_cd_vcols[0] = idx;
r_cd_layers[0] = CustomData_get_active_layer_index(vdata, CD_PROP_COLOR);
r_cd_vcols[0].cd_offset = cdata->layers[idx].offset;
r_cd_vcols[0].domain = active_domain;
r_cd_vcols[0].type = active_type;
r_cd_vcols[0].layer_idx = idx;
return 1;
}
@ -1228,37 +1342,36 @@ static int gpu_pbvh_bmesh_make_vcol_offs(CustomData *vdata,
}
int count = 0;
int tot = CustomData_number_of_layers(vdata, CD_PROP_COLOR);
for (int step = 0; step < 2; step++) {
CustomData *cdata = step ? ldata : vdata;
CustomDataLayer *cl = cdata->layers;
AttributeDomain domain = step ? ATTR_DOMAIN_CORNER : ATTR_DOMAIN_POINT;
for (int i = 0; i < tot; i++) {
int idx = CustomData_get_layer_index_n(vdata, CD_PROP_COLOR, i);
// idx = CustomData_get_active_layer_index(vdata, CD_PROP_COLOR);
for (int i = 0; count < MAX_GPU_MCOL && i < cdata->totlayer; i++, cl++) {
if (ELEM(cl->type, CD_PROP_COLOR, CD_MLOOPCOL)) {
ColorRef *ref = r_cd_vcols + count;
if (idx < 0) {
printf("eek, corruption in customdata!\n");
break;
ref->cd_offset = cl->offset;
ref->type = cl->type;
ref->layer_idx = i;
ref->domain = domain;
count++;
}
}
CustomDataLayer *cl = vdata->layers + idx;
if (cl->flag & CD_FLAG_TEMPORARY) {
continue; // ignore original color layer
}
r_cd_layers[count] = idx;
r_cd_vcols[count] = CustomData_get_n_offset(vdata, CD_PROP_COLOR, i);
count++;
}
// ensure render layer is last
// draw cache code seems to need this
int render = CustomData_get_render_layer_index(vdata, CD_PROP_COLOR);
/* ensure render layer is last
draw cache code seems to need this
*/
int render = CustomData_get_render_layer_index(
active_domain == ATTR_DOMAIN_POINT ? vdata : ldata, active_type);
// int active = CustomData_get_active_layer_index(
// active_domain == ATTR_DOMAIN_POINT ? vdata : ldata, active_type);
for (int i = 0; i < count; i++) {
if (r_cd_layers[i] == render) {
SWAP(int, r_cd_layers[i], r_cd_layers[count - 1]);
SWAP(int, r_cd_vcols[i], r_cd_vcols[count - 1]);
if (r_cd_vcols[i].layer_idx == render) {
SWAP(ColorRef, r_cd_vcols[i], r_cd_vcols[count - 1]);
break;
}
}
@ -1277,10 +1390,12 @@ bool GPU_pbvh_need_full_render_get()
return g_vbo_id.need_full_render;
}
void GPU_pbvh_update_attribute_names(CustomData *vdata,
CustomData *ldata,
bool need_full_render,
bool fast_mode)
ATTR_NO_OPT void GPU_pbvh_update_attribute_names(CustomData *vdata,
CustomData *ldata,
bool need_full_render,
bool fast_mode,
int active_vcol_type,
int active_vcol_domain)
{
const bool active_only = !need_full_render;
@ -1293,30 +1408,17 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata,
// g_vbo_id.loop_attrs = build_cd_layers(vdata, )
/* Initialize vertex buffer (match 'VertexBufferFormat'). */
if (g_vbo_id.format.attr_len == 0) {
#ifdef QUANTIZED_PERF_TEST
g_vbo_id.pos = GPU_vertformat_attr_add(
&g_vbo_id.format, "pos", GPU_COMP_U16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
g_vbo_id.nor = GPU_vertformat_attr_add(
&g_vbo_id.format, "nor", GPU_COMP_I8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
#else
g_vbo_id.pos = GPU_vertformat_attr_add(
&g_vbo_id.format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
g_vbo_id.nor = GPU_vertformat_attr_add(
&g_vbo_id.format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
#endif
/* TODO: Do not allocate these `.msk` and `.col` when they are not used. */
#ifdef QUANTIZED_PERF_TEST
return;
#endif
#ifndef GPU_PERF_TEST
if (!fast_mode) {
g_vbo_id.msk = GPU_vertformat_attr_add(
&g_vbo_id.format, "msk", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
#endif
g_vbo_id.totcol = 0;
@ -1359,27 +1461,27 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata,
#endif
#if !defined(NEW_ATTR_SYSTEM) && !defined(GPU_PERF_TEST)
if (vdata && CustomData_has_layer(vdata, CD_PROP_COLOR)) {
const int act = CustomData_get_active_layer_index(vdata, CD_PROP_COLOR);
if (active_vcol_type != -1) {
const int act = CustomData_get_active_layer_index(
active_vcol_domain == ATTR_DOMAIN_POINT ? vdata : ldata, active_vcol_type);
int ci = 0;
int cd_vcol_offs[MAX_MCOL];
int cd_vcol_layers[MAX_MCOL];
ColorRef vcol_layers[MAX_GPU_MCOL];
int totlayer = gpu_pbvh_bmesh_make_vcol_offs(
vdata, cd_vcol_offs, cd_vcol_layers, active_only);
vdata, ldata, vcol_layers, active_only, active_vcol_type, active_vcol_domain);
for (int i = 0; i < totlayer; i++) {
int idx = cd_vcol_layers[i];
CustomDataLayer *cl = vdata->layers + idx;
ColorRef *ref = vcol_layers + i;
CustomDataLayer *cl = vdata->layers + ref->layer_idx;
if (g_vbo_id.totcol < MAX_MCOL) {
if (g_vbo_id.totcol < MAX_GPU_MCOL) {
g_vbo_id.col[ci++] = GPU_vertformat_attr_add(
&g_vbo_id.format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
g_vbo_id.totcol++;
DRW_make_cdlayer_attr_aliases(&g_vbo_id.format, "c", vdata, cl);
if (idx == act) {
if ((int)ref->layer_idx == act && (int)ref->domain == active_vcol_domain) {
GPU_vertformat_alias_add(&g_vbo_id.format, "ac");
}
}
@ -1427,24 +1529,28 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata,
}
}
static void gpu_flat_vcol_make_vert(float co[3],
BMVert *v,
GPUVertBuf *vert_buf,
int v_index,
const int cd_vcol_offsets[MAX_MCOL],
int totoffsets,
const float fno[3])
ATTR_NO_OPT static void gpu_flat_vcol_make_vert(float co[3],
BMVert *v,
BMLoop *l,
GPUVertBuf *vert_buf,
int v_index,
ColorRef vcol_refs[MAX_GPU_MCOL],
int totoffsets,
const float fno[3])
{
for (int i = 0; i < totoffsets; i++) {
MPropCol *mp = BM_ELEM_CD_GET_VOID_P(v, cd_vcol_offsets[i]);
float color[4];
gpu_bmesh_get_vcol(v, l, vcol_refs + i, color);
ushort vcol[4];
// printf(
// "%.2f %.2f %.2f %.2f\n", mp->color[0], mp->color[1], mp->color[2], mp->color[3]);
vcol[0] = unit_float_to_ushort_clamp(mp->color[0]);
vcol[1] = unit_float_to_ushort_clamp(mp->color[1]);
vcol[2] = unit_float_to_ushort_clamp(mp->color[2]);
vcol[3] = unit_float_to_ushort_clamp(mp->color[3]);
vcol[0] = unit_float_to_ushort_clamp(color[0]);
vcol[1] = unit_float_to_ushort_clamp(color[1]);
vcol[2] = unit_float_to_ushort_clamp(color[2]);
vcol[3] = unit_float_to_ushort_clamp(color[3]);
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col[i], v_index, vcol);
}
@ -1471,7 +1577,9 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
const int cd_vert_node_offset,
int face_sets_color_seed,
int face_sets_color_default,
short mat_nr)
short mat_nr,
int active_vcol_type,
int active_vcol_domain)
{
bool active_vcol_only = g_vbo_id.active_vcol_only;
@ -1482,11 +1590,10 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
bool empty_mask = true;
int cd_fset_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
int cd_vcols[MAX_MCOL];
int cd_vcol_layers[MAX_MCOL];
ColorRef cd_vcols[MAX_GPU_MCOL];
const int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
&bm->vdata, &bm->ldata, cd_vcols, active_vcol_only, active_vcol_type, active_vcol_domain);
/* Count visible triangles */
tottri = gpu_bmesh_face_visible_count(tribuf, mat_nr) * 6;
@ -1529,6 +1636,7 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
BMVert *v[3];
BMLoop *l[3];
float fmask = 0.0f;
@ -1536,6 +1644,15 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
v[1] = (BMVert *)tribuf->verts[tri->v[1]].i;
v[2] = (BMVert *)tribuf->verts[tri->v[2]].i;
if (tribuf->loops) {
l[0] = (BMLoop *)tribuf->loops[tri->v[0]];
l[1] = (BMLoop *)tribuf->loops[tri->v[1]];
l[2] = (BMLoop *)tribuf->loops[tri->v[2]];
}
else {
l[0] = l[1] = l[2] = NULL;
}
/* Average mask value */
for (int j = 0; j < 3; j++) {
fmask += BM_ELEM_CD_GET_FLOAT(v[j], cd_vert_mask_offset);
@ -1579,18 +1696,18 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
int prev = 3 + ((j + 3 - 1) % 3);
gpu_flat_vcol_make_vert(
v[j]->co, v[j], buffers->vert_buf, v_index, cd_vcols, cd_vcol_count, f->no);
v[j]->co, v[j], l[j], buffers->vert_buf, v_index, cd_vcols, cd_vcol_count, f->no);
gpu_flat_vcol_make_vert(
cos[next], v[j], buffers->vert_buf, v_index + 1, cd_vcols, cd_vcol_count, f->no);
cos[next], v[j], l[j], buffers->vert_buf, v_index + 1, cd_vcols, cd_vcol_count, f->no);
gpu_flat_vcol_make_vert(
cos[6], v[j], buffers->vert_buf, v_index + 2, cd_vcols, cd_vcol_count, f->no);
cos[6], v[j], l[j], buffers->vert_buf, v_index + 2, cd_vcols, cd_vcol_count, f->no);
gpu_flat_vcol_make_vert(
v[j]->co, v[j], buffers->vert_buf, v_index + 3, cd_vcols, cd_vcol_count, f->no);
v[j]->co, v[j], l[j], buffers->vert_buf, v_index + 3, cd_vcols, cd_vcol_count, f->no);
gpu_flat_vcol_make_vert(
cos[6], v[j], buffers->vert_buf, v_index + 4, cd_vcols, cd_vcol_count, f->no);
cos[6], v[j], l[j], buffers->vert_buf, v_index + 4, cd_vcols, cd_vcol_count, f->no);
gpu_flat_vcol_make_vert(
cos[prev], v[j], buffers->vert_buf, v_index + 5, cd_vcols, cd_vcol_count, f->no);
cos[prev], v[j], l[j], buffers->vert_buf, v_index + 5, cd_vcols, cd_vcol_count, f->no);
/*
v1
@ -1645,13 +1762,15 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
int face_sets_color_seed,
int face_sets_color_default,
bool flat_vcol,
short mat_nr)
short mat_nr,
int active_vcol_type,
int active_vcol_domain)
{
bool active_vcol_only = g_vbo_id.active_vcol_only;
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0 && !g_vbo_id.fast_mode;
bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0 && active_vcol_type != -1;
if (g_vbo_id.totcol == 0 && g_vbo_id.fast_mode) {
show_vcol = false;
@ -1664,11 +1783,10 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
int tottri, totvert;
bool empty_mask = true;
int cd_vcols[MAX_MCOL];
int cd_vcol_layers[MAX_MCOL];
ColorRef cd_vcols[MAX_GPU_MCOL];
int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
&bm->vdata, &bm->ldata, cd_vcols, active_vcol_only, active_vcol_type, active_vcol_domain);
/* Count visible triangles */
tottri = gpu_bmesh_face_visible_count(tribuf, mat_nr);
@ -1704,72 +1822,13 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
return;
}
#ifdef QUANTIZED_PERF_TEST
GPUVertBuf *vert_buf = buffers->vert_buf;
float min[3];
float max[3];
float mat[4][4];
float imat[4][4];
float scale[3];
INIT_MINMAX(min, max);
for (int i = 0; i < tribuf->totvert; i++) {
BMVert *v = (BMVert *)tribuf->verts[i].i;
minmax_v3v3_v3(min, max, v->co);
}
sub_v3_v3v3(scale, max, min);
scale[0] = scale[0] != 0.0f ? 1.0f / scale[0] : 0.0f;
scale[1] = scale[1] != 0.0f ? 1.0f / scale[1] : 0.0f;
scale[2] = scale[2] != 0.0f ? 1.0f / scale[2] : 0.0f;
memset((float *)mat, 0, sizeof(float) * 16);
mat[0][0] = scale[0];
mat[1][1] = scale[1];
mat[2][2] = scale[2];
mat[3][0] = -min[0] * scale[0];
mat[3][1] = -min[1] * scale[1];
mat[3][2] = -min[2] * scale[2];
mat[3][3] = 1.0f;
invert_m4_m4(imat, mat);
#endif
for (int i = 0; i < tribuf->totvert; i++) {
BMVert *v = (BMVert *)tribuf->verts[i].i;
BMLoop *l = (BMLoop *)tribuf->loops[i];
#ifdef QUANTIZED_PERF_TEST
float co[3];
copy_v3_v3(co, v->co);
mul_v3_m4v3(co, mat, co);
// sub_v3_v3(co, tribuf->min);
// mul_v3_v3(co, scale);
// normal_float_to_short_
unsigned short co_short[3];
co_short[0] = (unsigned short)(co[0] * 65535.0f);
co_short[1] = (unsigned short)(co[1] * 65535.0f);
co_short[2] = (unsigned short)(co[2] * 65535.0f);
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, i, co_short);
signed char no_short[3];
// normal_float_to_short_v3(no_short, v->no);
no_short[0] = (signed char)(v->no[0] * 127.0f);
no_short[1] = (signed char)(v->no[1] * 127.0f);
no_short[2] = (signed char)(v->no[2] * 127.0f);
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, i, no_short);
#else
gpu_bmesh_vert_to_buffer_copy(bm,
v,
l,
buffers->vert_buf,
i,
NULL,
@ -1781,10 +1840,9 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
&empty_mask,
cd_vcols,
cd_vcol_count);
#endif
if (!g_vbo_id.fast_mode) {
const uchar face_set_color[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
uchar face_set_color[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
/* Add default face sets color to avoid artifacts. */
int fset = BM_ELEM_CD_GET_INT(l->f, cd_fset_offset);
@ -1831,11 +1889,9 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
GPU_indexbuf_add_tri_verts(&elb, tri->v[0], tri->v[1], tri->v[2]);
#ifndef QUANTIZED_PERF_TEST
GPU_indexbuf_add_line_verts(&elb_lines, tri->v[0], tri->v[1]);
GPU_indexbuf_add_line_verts(&elb_lines, tri->v[1], tri->v[2]);
GPU_indexbuf_add_line_verts(&elb_lines, tri->v[2], tri->v[0]);
#endif
}
buffers->tot_tri = tottri;
@ -1852,47 +1908,41 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
buffers->show_overlay = (!empty_mask || !default_face_set) && !g_vbo_id.fast_mode;
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
#ifdef QUANTIZED_PERF_TEST
copy_m4_m4(buffers->matrix, imat);
#endif
}
/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
* shading, an element index buffer.
* Threaded - do not call any functions that use OpenGL calls! */
void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
BMesh *bm,
TableGSet *bm_faces,
TableGSet *bm_unique_verts,
TableGSet *bm_other_verts,
PBVHTriBuf *tribuf,
const int update_flags,
const int cd_vert_node_offset,
int face_sets_color_seed,
int face_sets_color_default,
bool flat_vcol,
short mat_nr)
ATTR_NO_OPT void GPU_pbvh_bmesh_buffers_update(PBVHGPUBuildArgs *args)
{
BMesh *bm = args->bm;
GPU_PBVH_Buffers *buffers = args->buffers;
PBVHTriBuf *tribuf = args->tribuf;
const int update_flags = args->update_flags;
const int mat_nr = args->mat_nr;
bool active_vcol_only = g_vbo_id.active_vcol_only;
if (flat_vcol && CustomData_has_layer(&bm->vdata, CD_PROP_COLOR)) {
if (args->flat_vcol && args->active_vcol_type != -1) {
GPU_pbvh_bmesh_buffers_update_flat_vcol(buffers,
bm,
bm_faces,
bm_unique_verts,
bm_other_verts,
args->bm_faces,
args->bm_unique_verts,
args->bm_other_verts,
tribuf,
update_flags,
cd_vert_node_offset,
face_sets_color_seed,
face_sets_color_default,
mat_nr);
args->cd_vert_node_offset,
args->face_sets_color_seed,
args->face_sets_color_default,
mat_nr,
args->active_vcol_type,
args->active_vcol_domain);
return;
}
const bool have_uv = CustomData_has_layer(&bm->ldata, CD_MLOOPUV);
const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0 &&
args->active_vcol_type != -1;
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0 && !g_vbo_id.fast_mode;
const bool show_face_sets = CustomData_has_layer(&bm->pdata, CD_SCULPT_FACE_SETS) &&
(update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0 &&
@ -1902,26 +1952,31 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
bool empty_mask = true;
int cd_fset_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
int cd_vcols[MAX_MCOL];
int cd_vcol_layers[MAX_MCOL];
ColorRef cd_vcols[MAX_GPU_MCOL];
int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(&bm->vdata,
&bm->ldata,
cd_vcols,
active_vcol_only,
args->active_vcol_type,
args->active_vcol_domain);
/* Count visible triangles */
if (buffers->smooth) {
GPU_pbvh_bmesh_buffers_update_indexed(buffers,
bm,
bm_faces,
bm_unique_verts,
bm_other_verts,
args->bm_faces,
args->bm_unique_verts,
args->bm_other_verts,
tribuf,
update_flags,
cd_vert_node_offset,
face_sets_color_seed,
face_sets_color_default,
flat_vcol,
mat_nr);
args->cd_vert_node_offset,
args->face_sets_color_seed,
args->face_sets_color_default,
args->flat_vcol,
mat_nr,
args->active_vcol_type,
args->active_vcol_domain);
return;
}
@ -1929,8 +1984,10 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
/* TODO, make mask layer optional for bmesh buffer */
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
const int cd_mcol_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
const int cd_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
int face_sets_color_default = args->face_sets_color_default;
int face_sets_color_seed = args->face_sets_color_seed;
int cd_vert_node_offset = args->cd_vert_node_offset;
bool default_face_set = true;
@ -1940,7 +1997,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
if (!tottri) {
/* empty node (i.e. not just hidden)? */
if (BLI_table_gset_len(bm_faces) == 0) {
if (BLI_table_gset_len(args->bm_faces) == 0) {
buffers->clear_bmesh_on_flush = true;
}
@ -2010,6 +2067,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
gpu_bmesh_vert_to_buffer_copy(bm,
v[j],
l[j],
buffers->vert_buf,
v_index,
no,
@ -2017,39 +2075,11 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
cd_vert_mask_offset,
cd_vert_node_offset,
show_mask,
false,
show_vcol,
&empty_mask,
NULL,
0);
cd_vcols,
cd_vcol_count);
# ifndef GPU_PERF_TEST
if (cd_vcol_count >= 0) {
for (int k = 0; k < cd_vcol_count; k++) {
MPropCol *mp = BM_ELEM_CD_GET_VOID_P(l[j]->v, cd_vcols[k]);
ushort vcol[4];
// printf(
// "%.2f %.2f %.2f %.2f\n", mp->color[0], mp->color[1], mp->color[2],
// mp->color[3]);
vcol[0] = unit_float_to_ushort_clamp(mp->color[0]);
vcol[1] = unit_float_to_ushort_clamp(mp->color[1]);
vcol[2] = unit_float_to_ushort_clamp(mp->color[2]);
vcol[3] = unit_float_to_ushort_clamp(mp->color[3]);
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[k], v_index, vcol);
}
}
else if (cd_mcol_offset >= 0) {
ushort vcol[4];
MLoopCol *ml = BM_ELEM_CD_GET_VOID_P(l[j], cd_mcol_offset);
vcol[0] = ml->r * 257;
vcol[1] = ml->g * 257;
vcol[2] = ml->b * 257;
vcol[3] = ml->a * 257;
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], v_index, vcol);
}
if (have_uv) {
MLoopUV *mu = BM_ELEM_CD_GET_VOID_P(l[j], cd_uv_offset);
@ -2129,6 +2159,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
gpu_bmesh_vert_to_buffer_copy(bm,
v[i],
l[j],
buffers->vert_buf,
v_index,
no,

View File

@ -6374,10 +6374,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cycles Debug", "Enable Cycles debugging options for developers");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "use_sculpt_vertex_colors", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_sculpt_vertex_colors", 1);
RNA_def_property_ui_text(prop, "Sculpt Vertex Colors", "Use the new Vertex Painting system");
prop = RNA_def_property(srna, "use_sculpt_tools_tilt", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_sculpt_tools_tilt", 1);
RNA_def_property_ui_text(

View File

@ -456,7 +456,7 @@ static void panelRegister(ARegionType *region_type)
region_type, "vertex_vgroup", "Vertex Groups", NULL, vertex_vgroup_panel_draw, vertex_panel);
modifier_subpanel_register(
region_type, "vert_propcol", "Sculpt Colors", NULL, vert_propcol_panel_draw, vertex_panel);
region_type, "vert_propcol", "Colors", NULL, vert_propcol_panel_draw, vertex_panel);
modifier_subpanel_register(
region_type, "edge", "", edge_panel_draw_header, edge_panel_draw, panel_type);
@ -469,7 +469,7 @@ static void panelRegister(ARegionType *region_type)
panel_type);
modifier_subpanel_register(region_type,
"face_corner_vcol",
"Vertex Colors",
"Colors",
NULL,
face_corner_vcol_panel_draw,
face_corner_panel);

View File

@ -39,11 +39,7 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat,
GPUNodeStack *out)
{
NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage;
if (U.experimental.use_sculpt_vertex_colors) {
GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_PROP_COLOR, vertexColor->layer_name);
return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink);
}
GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_MCOL, vertexColor->layer_name);
GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_PROP_COLOR, vertexColor->layer_name);
return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink);
}

View File

@ -31,6 +31,7 @@
#include "BLI_utildefines.h"
#include "DNA_ID.h"
#include "DNA_brush_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
@ -211,6 +212,7 @@ static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tre
}
else {
brush = BKE_brush_add(bmain, items[i].name, paint->runtime.ob_mode);
BKE_brush_tool_set(brush, paint, slot_index);
}
BKE_paint_brush_set(paint, brush);