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:
commit
78d62d9be7
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ struct BlendExpander;
|
|||
struct Brush;
|
||||
struct Sculpt;
|
||||
struct LibraryForeachIDData;
|
||||
struct UnifiedPaintSettings;
|
||||
|
||||
#define MAKE_BUILTIN_CH_NAME(idname) BRUSH_BUILTIN_##idname
|
||||
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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). */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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, ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, ¶ms);
|
||||
SCULPT_temp_customlayer_ensure(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, ¶ms);
|
||||
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, array->scl_sym, ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, ¶ms);
|
||||
SCULPT_temp_customlayer_get(ss,
|
||||
ob,
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_INT32,
|
||||
array_symmetry_pass_cd_name,
|
||||
array->scl_sym,
|
||||
¶ms);
|
||||
}
|
||||
|
||||
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, ¶ms);
|
||||
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,
|
||||
¶ms);
|
||||
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,
|
||||
¶ms);
|
||||
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, ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_symmetry_pass_cd_name, array->scl_sym, ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, array_instance_cd_name, array->scl_inst, ¶ms);
|
||||
SCULPT_temp_customlayer_get(ss,
|
||||
ob,
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_INT32,
|
||||
array_symmetry_pass_cd_name,
|
||||
array->scl_sym,
|
||||
¶ms);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
|||
¶ms);
|
||||
|
||||
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
|
|||
¶ms);
|
||||
|
||||
SCULPT_temp_customlayer_get(ss,
|
||||
ob,
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_FLOAT3,
|
||||
"prefairing_co",
|
||||
ss->custom_layers[SCULPT_SCL_PREFAIRING_CO],
|
||||
¶ms);
|
||||
|
||||
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");
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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", ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "_sculpt_limit_surface", ss->limit_surface, ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "_sculpt_limit_surface", ¶ms);
|
||||
SCULPT_temp_customlayer_get(ss,
|
||||
ob,
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_FLOAT3,
|
||||
"_sculpt_limit_surface",
|
||||
ss->limit_surface,
|
||||
¶ms);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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", ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", ¶ms);
|
||||
SCULPT_temp_customlayer_ensure(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, "_paint_buffer_stroke_id", ¶ms_id);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_INT32, "_paint_buffer_stroke_id", ¶ms_id);
|
||||
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &buffer_scl, ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_INT32, "_paint_buffer_stroke_id", &stroke_id_scl, ¶ms_id);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &buffer_scl, ¶ms);
|
||||
SCULPT_temp_customlayer_get(ss,
|
||||
ob,
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_INT32,
|
||||
"_paint_buffer_stroke_id",
|
||||
&stroke_id_scl,
|
||||
¶ms_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", ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &prev_scl, ¶ms);
|
||||
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", &prev_scl, ¶ms);
|
||||
|
||||
BKE_curvemapping_init(brush->curve);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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", ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &scl, ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_detail_dir", &scl, ¶ms);
|
||||
|
||||
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", ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", &scl, ¶ms);
|
||||
ss, ob, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, "__dyntopo_lapsmooth", &scl, ¶ms);
|
||||
|
||||
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?
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue